Subversion Repositories Kolibri OS

Rev

Rev 6115 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <drm/i915_drm.h>
  5. #include <kos32sys.h>
  6. #include "pixlib3.h"
  7. #include "pixdriver.h"
  8. #include "pxgl.h"
  9.  
  10. #define WIN_STATE_MINIMIZED  0x02
  11. #define WIN_STATE_ROLLED     0x04
  12.  
  13. static int drm_ioctl(int fd, unsigned long request, void *arg)
  14. {
  15.     ioctl_t  io;
  16.  
  17.     io.handle   = fd;
  18.     io.io_code  = request;
  19.     io.input    = arg;
  20.     io.inp_size = 64;
  21.     io.output   = NULL;
  22.     io.out_size = 0;
  23.  
  24.     return call_service(&io);
  25. }
  26.  
  27. static EGLImageKHR px_create_image(struct render *px,void *name,GLuint tex, EGLint *attribs)
  28. {
  29.     EGLImageKHR image;
  30.  
  31.     image = eglCreateImageKHR(px->dpy, px->context,
  32.                               EGL_DRM_BUFFER_MESA, name, attribs);
  33.     if(image == NULL)
  34.         goto err_0;
  35.  
  36.     glBindTexture(GL_TEXTURE_2D, tex);
  37.     if(glGetError() != GL_NO_ERROR)
  38.        goto err_1;
  39.  
  40.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
  41.     if(glGetError() != GL_NO_ERROR)
  42.        goto err_1;
  43.  
  44.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  45.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  46.  
  47.     return image;
  48.  
  49. err_1:
  50.     eglDestroyImageKHR(px->dpy, image);
  51. err_0:
  52.     return NULL;
  53. };
  54.  
  55. static int update_fb(struct render *px, int name, int pitch)
  56. {
  57.     GLenum      status;
  58.     EGLImageKHR screen;
  59.  
  60.     EGLint attribs[] = {
  61.         EGL_WIDTH, px->scr_width,
  62.         EGL_HEIGHT, px->scr_height,
  63.         EGL_DRM_BUFFER_STRIDE_MESA, pitch/4,
  64.         EGL_DRM_BUFFER_FORMAT_MESA,
  65.         EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
  66.         EGL_DRM_BUFFER_USE_MESA,
  67.         EGL_DRM_BUFFER_USE_SHARE_MESA |
  68.         EGL_DRM_BUFFER_USE_SCANOUT_MESA,
  69.         EGL_NONE
  70.     };
  71.     char *errmsg;
  72.  
  73.     px->screen = px_create_image(px,(void*)name, px->texture[TEX_SCREEN], attribs);
  74.     errmsg = "failed to create new screen image\n";
  75.     if(px->screen == EGL_NO_IMAGE_KHR)
  76.         goto err_0;
  77.  
  78.     px->screen = screen;
  79.  
  80.     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
  81.                        GL_TEXTURE_2D, px->texture[TEX_SCREEN],0);
  82.  
  83.     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  84.     if (status != GL_FRAMEBUFFER_COMPLETE)
  85.     {
  86.         const char *str;
  87.         switch (status)
  88.         {
  89.             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  90.                 str = "incomplete attachment";
  91.                 break;
  92.             case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  93.                 str = "incomplete/missing attachment";
  94.                 break;
  95.             case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
  96.                 str = "incomplete draw buffer";
  97.                 break;
  98.             case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
  99.                 str = "incomplete read buffer";
  100.                 break;
  101.             case GL_FRAMEBUFFER_UNSUPPORTED:
  102.                 str = "unsupported";
  103.                 break;
  104.             case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
  105.                 str = "incomplete multiple";
  106.                 break;
  107.             default:
  108.                 str = "unknown error";
  109.                 break;
  110.         }
  111.         DBG("destination framebuffer incomplete: %s [%#x]\n", str, status);
  112.  
  113.         return -1;
  114.     };
  115.  
  116.     DBG("framebuffer changed successfull\n");
  117.  
  118.     glViewport(0, 0, px->scr_width, px->scr_height);
  119.  
  120.     return 0;
  121.  
  122. err_0:
  123.     DBG("%s %s\n", __FUNCTION__, errmsg);
  124.  
  125.     return -1;
  126. };
  127.  
  128. static GLint create_shader(GLenum type, const char *source)
  129. {
  130.     GLint ok;
  131.     GLint shader;
  132.  
  133.     shader = glCreateShader(type);
  134.     if(shader == 0)
  135.         goto err;
  136.  
  137.     glShaderSource(shader, 1, (const GLchar **) &source, NULL);
  138.     glCompileShader(shader);
  139.     glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
  140.     if (!ok) {
  141.         GLchar *info;
  142.         GLint size;
  143.  
  144.         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
  145.         info = malloc(size);
  146.  
  147.         glGetShaderInfoLog(shader, size, NULL, info);
  148.         DBG("Failed to compile %s: %s\n",
  149.                 type == GL_FRAGMENT_SHADER ? "FS" : "VS",info);
  150.         DBG("Program source:\n%s", source);
  151.         DBG("GLSL compile failure\n");
  152.         free(info);
  153.         glDeleteShader(shader);
  154.         shader = 0;
  155.     };
  156.  
  157.     DBG("create shader %d\n", shader);
  158. err:
  159.     return shader;
  160. }
  161.  
  162.  
  163. static void *px_create_obj(struct render *px, size_t size,
  164.                            GLuint *handle, GLuint *name)
  165. {
  166.     struct drm_i915_gem_create create;
  167.     struct drm_i915_gem_mmap mmap_arg;
  168.     struct drm_gem_close close;
  169.     struct drm_gem_flink flink;
  170.  
  171.     create.size   = size;
  172.     create.handle = 0;
  173.  
  174.     if(drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_CREATE, &create))
  175.         goto err_0;
  176.  
  177.     *handle      = create.handle;
  178.     flink.handle = create.handle;
  179.     if (drm_ioctl(px->fd, DRM_IOCTL_GEM_FLINK, &flink))
  180.         goto err_1;
  181.  
  182.     *name = flink.name;
  183.  
  184.     mmap_arg.handle = *handle;
  185.     mmap_arg.offset = 0;
  186.     mmap_arg.size   = size;
  187.     if (drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))
  188.     {
  189.         DBG("%s: failed to mmap bitmap handle=%d, %d bytes, into CPU domain\n",
  190.                __FUNCTION__, *handle, size);
  191.         goto err_1;
  192.     };
  193.  
  194.     return (void*)(uintptr_t)mmap_arg.addr_ptr;
  195.  
  196. err_1:
  197.     close.handle = *handle;
  198.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  199. err_0:
  200.     return NULL;
  201. };
  202.  
  203.  
  204. static int px_create_bitmap(struct render *px, struct bitmap *bitmap,
  205.                             size_t size, EGLint format)
  206. {
  207.     struct drm_gem_close close;
  208.     EGLint attribs[] = {
  209.         EGL_WIDTH, bitmap->width,
  210.         EGL_HEIGHT, bitmap->height,
  211.         EGL_DRM_BUFFER_STRIDE_MESA, 0,
  212.         EGL_DRM_BUFFER_FORMAT_MESA,
  213.         format,
  214.         EGL_DRM_BUFFER_USE_MESA,
  215.         EGL_DRM_BUFFER_USE_SHARE_MESA,
  216.         EGL_NONE
  217.     };
  218.  
  219.     bitmap->buffer = px_create_obj(px, size, &bitmap->handle, &bitmap->name);
  220.     if(bitmap->buffer == NULL)
  221.         goto err_0;
  222.  
  223.     switch(format)
  224.     {
  225.         case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  226.             attribs[5] = bitmap->pitch/4;
  227.             break;
  228.         case EGL_DRM_BUFFER_FORMAT_R8_MESA:
  229.             attribs[5] = bitmap->pitch;
  230.             break;
  231.         default:
  232.             DBG("%s invalid format %x\n",
  233.                     __FUNCTION__, format);
  234.             goto err_1;
  235.     }
  236.  
  237.     bitmap->image = px_create_image(px,(void*)bitmap->name,
  238.                                     bitmap->tex, attribs);
  239.     if(bitmap->image == NULL)
  240.         goto err_1;
  241.  
  242.     DBG("create bitmap:%p %dx%d pitch:%d\n"
  243.            "KHRimage:%p gl_tex:%d handle:%d name:%d\n"
  244.            "mapped at %x\n",
  245.             bitmap, bitmap->width, bitmap->height, bitmap->pitch,
  246.             bitmap->image, bitmap->tex, bitmap->handle, bitmap->name,
  247.             bitmap->buffer);
  248.  
  249.     return 0;
  250.  
  251. err_1:
  252.     user_free(bitmap->buffer);
  253.     close.handle = bitmap->handle;
  254.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  255. err_0:
  256.     return -1;
  257. }
  258.  
  259.  
  260. static int create_mask(struct render *px)
  261. {
  262.     struct drm_i915_mask_update update;
  263.     int    pitch;
  264.  
  265.     pitch = (px->width+15) & ~15;
  266.  
  267.     px->mask.width  = px->width;
  268.     px->mask.height = px->height;
  269.     px->mask.pitch  = pitch;
  270.     px->mask.tex    = px->texture[TEX_MASK];
  271.     px->mask_size   = pitch * px->height;
  272.  
  273.     if(px_create_bitmap(px, &px->mask, px->mask_size,
  274.                          EGL_DRM_BUFFER_FORMAT_R8_MESA) == 0)
  275.     {
  276.         update.handle = px->mask.handle;
  277.         update.dx     = px->dx;
  278.         update.dy     = px->dy;
  279.         update.width  = px->width;
  280.         update.height = px->height;
  281.         update.bo_pitch = (px->width+15) & ~15;
  282.         update.bo_map = (int)px->mask.buffer;
  283.         update.forced = 1;
  284.         drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update);
  285.         return 0;
  286.     };
  287.     return -1;
  288. };
  289.  
  290.  
  291. static int update_mask(struct render *px)
  292. {
  293.     struct drm_gem_close close;
  294.     EGLint attribs[] = {
  295.         EGL_WIDTH, 0,
  296.         EGL_HEIGHT, 0,
  297.         EGL_DRM_BUFFER_STRIDE_MESA, 0,
  298.         EGL_DRM_BUFFER_FORMAT_MESA,
  299.         EGL_DRM_BUFFER_FORMAT_R8_MESA,
  300.         EGL_DRM_BUFFER_USE_MESA,
  301.         EGL_DRM_BUFFER_USE_SHARE_MESA,
  302.         EGL_NONE
  303.     };
  304.     unsigned int size, pitch;
  305.  
  306.     eglDestroyImageKHR(px->dpy, px->mask.image);
  307.  
  308.     pitch = (px->width+15) & ~15;
  309.     size = pitch*px->height;
  310.  
  311.     if(size > px->mask_size)
  312.     {
  313.         user_free(px->mask.buffer);
  314.         close.handle = px->mask.handle;
  315.         drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  316.  
  317.         px->mask_size = size;
  318.  
  319.         px->mask.buffer = px_create_obj(px, px->mask_size,
  320.                                       &px->mask.handle, &px->mask.name);
  321.         if(px->mask.buffer == 0)
  322.             goto err_0;
  323.     };
  324.  
  325.     attribs[1] = px->width;
  326.     attribs[3] = px->height;
  327.     attribs[5] = pitch;
  328.  
  329.     px->mask.image = px_create_image(px,(void*)px->mask.name,
  330.                                      px->mask.tex, attribs);
  331.     if(px->mask.image == NULL)
  332.         goto err_1;
  333.  
  334.     DBG("create mask w:%d h:%d pitch:%d\n"
  335.         "KHRimage:%p gl_tex:%d handle:%d name:%d\n"
  336.         "mapped at %x\n",
  337.          px->width, px->height,
  338.          pitch, px->mask.image, px->texture[TEX_MASK],
  339.          px->mask.handle, px->mask.name, px->mask.buffer);
  340.  
  341.     return 0;
  342.  
  343. err_1:
  344.     user_free(px->mask.buffer);
  345.     close.handle = px->mask.handle;
  346.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  347. err_0:
  348.     return -1;
  349. };
  350.  
  351. static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h)
  352. {
  353.     const char *vs_src =
  354.         "attribute vec4 v_position;\n"
  355.         "attribute vec4 v_texcoord0;\n"
  356.         "varying vec2 source_texture;\n"
  357.         "void main()\n"
  358.         "{\n"
  359.         "   gl_Position = v_position;\n"
  360.         "   source_texture = v_texcoord0.xy;\n"
  361.         "}\n";
  362.  
  363.     const char *fs_i965 =
  364.         "varying vec2 source_texture;\n"
  365.         "uniform sampler2D sampler_src;\n"
  366.         "uniform sampler2D sampler_mask;\n"
  367.         "void main()\n"
  368.         "{\n"
  369.         "   float ca = texture2D(sampler_mask, source_texture).r;\n"
  370.         "   gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n"
  371.         "}\n";
  372.  
  373.     struct drm_i915_fb_info fb;
  374.     struct render *px;
  375.     GLint  vs_shader, fs_shader;
  376.     int    ret;
  377.  
  378.     px = (struct render*)malloc(sizeof(struct render));
  379.     if(px == NULL)
  380.         goto err_0;
  381.  
  382.     px->fd  = get_service("DISPLAY");
  383.  
  384.     __builtin_memset(&fb, 0, sizeof(fb));
  385.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  386.     {   DBG("failed to get framebuffer info\n");
  387.         goto err_1;
  388.     };
  389.  
  390.     px->dpy     = dpy;
  391.     px->context = context;
  392.     px->dx      = dx;
  393.     px->dy      = dy;
  394.     px->width   = w;
  395.     px->height  = h;
  396.     px->scr_width  = fb.width;
  397.     px->scr_height = fb.height;
  398.  
  399.     glGenTextures(2, px->texture);
  400.     if(glGetError() != GL_NO_ERROR)
  401.        goto err_1;
  402.  
  403.     glGenFramebuffers(1, &px->framebuffer);
  404.     if(glGetError() != GL_NO_ERROR)
  405.        goto err_2;
  406.  
  407.     glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer);
  408.     if(glGetError() != GL_NO_ERROR)
  409.        goto err_3;
  410.  
  411.     if(update_fb(px, fb.name, fb.pitch))
  412.        goto err_4;
  413.  
  414.     glMatrixMode(GL_PROJECTION);
  415.     glLoadIdentity();
  416.     glMatrixMode(GL_MODELVIEW);
  417.     glLoadIdentity();
  418.  
  419.     if(create_mask(px))
  420.         goto err_4;
  421.  
  422.     px->blit_prog = glCreateProgram();
  423.     if(px->blit_prog == 0)
  424.         goto err_4;
  425.  
  426.     vs_shader = create_shader(GL_VERTEX_SHADER, vs_src);
  427.     if(vs_shader == 0)
  428.         goto err_4;
  429.  
  430.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_i965);
  431.     if(fs_shader == 0)
  432.         goto err_4;
  433.  
  434.     glAttachShader(px->blit_prog, vs_shader);
  435.     glAttachShader(px->blit_prog, fs_shader);
  436.     glBindAttribLocation(px->blit_prog, 0, "v_position");
  437.     glBindAttribLocation(px->blit_prog, 1, "v_texcoord0");
  438.  
  439.     glLinkProgram(px->blit_prog);
  440.     glGetProgramiv(px->blit_prog, GL_LINK_STATUS, &ret);
  441.     if (!ret)
  442.     {
  443.         GLchar *info;
  444.         GLint size;
  445.  
  446.         glGetProgramiv(px->blit_prog, GL_INFO_LOG_LENGTH, &size);
  447.         info = malloc(size);
  448.  
  449.         glGetProgramInfoLog(px->blit_prog, size, NULL, info);
  450.         DBG("Failed to link: %s\n", info);
  451.         DBG("GLSL link failure\n");
  452.         free(info);
  453.         goto err_4;
  454.     }
  455.  
  456.     px->sampler = glGetUniformLocation(px->blit_prog,"sampler_src");
  457.     px->sm_mask = glGetUniformLocation(px->blit_prog,"sampler_mask");
  458.  
  459.     glUseProgram(px->blit_prog);
  460.     glUniform1i(px->sampler, 0);
  461.     glUniform1i(px->sm_mask, 1);
  462.  
  463.     glEnableClientState(GL_VERTEX_ARRAY);
  464.  
  465.     glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices);
  466.     glEnableVertexAttribArray(0);
  467.  
  468.     glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src);
  469.     glEnableVertexAttribArray(1);
  470.  
  471.     glEnable(GL_BLEND);
  472.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  473.  
  474.     px->tc_src[0]    = 0.0;
  475.     px->tc_src[1]    = 0.0;
  476.     px->tc_src[1*2]  = 1.0;
  477.     px->tc_src[1*2+1]= 0.0;
  478.     px->tc_src[2*2]  = 1.0;
  479.     px->tc_src[2*2+1]= 1.0;
  480.     px->tc_src[3*2]  = 0.0;
  481.     px->tc_src[3*2+1]= 1.0;
  482.  
  483.     DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n",
  484.         px->screen,fb.width, fb.height, fb.pitch, fb.name);
  485.  
  486.     return px;
  487.  
  488. err_4:
  489.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  490. err_3:
  491.     glDeleteFramebuffers(1, &px->framebuffer);
  492. err_2:
  493.     glDeleteTextures(2, px->texture);
  494. err_1:
  495.     free(px);
  496. err_0:
  497.     return NULL;
  498. };
  499.  
  500. static struct render *px;
  501.  
  502. static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height)
  503. {
  504.     struct bitmap *bitmap;
  505.  
  506.     bitmap = malloc(sizeof(struct bitmap));
  507.     if(bitmap == NULL)
  508.         return NULL;
  509.  
  510.     glGenTextures(1, &bitmap->tex);
  511.     if(glGetError() != GL_NO_ERROR)
  512.        goto err_0;
  513.  
  514.     bitmap->width   = width;
  515.     bitmap->height  = height;
  516.     bitmap->pitch   = (width*4 + 15) & ~15;
  517.  
  518.     if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height,
  519.                          EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0)
  520.     {
  521.         return bitmap;
  522.     };
  523.  
  524.     glDeleteTextures(1, &bitmap->tex);
  525. err_0:
  526.     free(bitmap);
  527.     return NULL;
  528. };
  529.  
  530. static int hw_destroy_bitmap(bitmap_t * bitmap)
  531. {
  532.     struct drm_gem_close close;
  533.  
  534.     glDeleteTextures(1, &bitmap->tex);
  535.     eglDestroyImageKHR(px->dpy, bitmap->image);
  536.     user_free(bitmap->buffer);
  537.     close.handle = bitmap->handle;
  538.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  539.     free(bitmap);
  540. };
  541.  
  542. static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch)
  543. {
  544.     *pitch = bitmap->pitch;
  545.  
  546.     return bitmap->buffer;
  547. };
  548.  
  549. static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height)
  550. {
  551.     return 0;
  552. }
  553.  
  554. char proc_info[1024];
  555.  
  556. static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y,
  557.                    uint32_t w, uint32_t h, int src_x, int src_y)
  558. {
  559.     struct drm_i915_mask_update update;
  560.     struct drm_i915_fb_info fb;
  561.  
  562.     uint32_t winx, winy, winw, winh;
  563.     uint8_t  state;
  564.     float xscale, yscale;
  565.     int r, b;
  566.     float *vertices  = px->vertices;
  567.  
  568.     get_proc_info(proc_info);
  569.  
  570.     state  = *(uint8_t*)(proc_info+70);
  571.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  572.         return;
  573.  
  574.     winx = *(uint32_t*)(proc_info+34);
  575.     winy = *(uint32_t*)(proc_info+38);
  576.     winw = *(uint32_t*)(proc_info+42)+1;
  577.     winh = *(uint32_t*)(proc_info+46)+1;
  578.  
  579.     __builtin_memset(&fb, 0, sizeof(fb));
  580.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  581.     {
  582.         DBG("failed to get framebuffer info\n");
  583.         return;
  584.     };
  585.  
  586.     if( fb.width  != px->scr_width ||
  587.         fb.height != px->scr_height )
  588.     {
  589.         px->scr_width  = fb.width;
  590.         px->scr_height = fb.height;
  591.  
  592.         eglDestroyImageKHR(px->dpy, px->screen);
  593.  
  594.         if(update_fb(px, fb.name, fb.pitch))
  595.             return;
  596.     };
  597.  
  598.     update.handle = px->mask.handle;
  599.     update.dx     = px->dx;
  600.     update.dy     = px->dy;
  601.     update.width  = px->width;
  602.     update.height = px->height;
  603.     update.bo_pitch = (px->width+15) & ~15;
  604.     update.bo_map = (int)px->mask.buffer;
  605.  
  606.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  607.     {
  608.         return;
  609.     }
  610.  
  611.     xscale = 1.0/px->scr_width;
  612.     yscale = 1.0/px->scr_height;
  613.  
  614.     r = winx + px->dx + px->width;
  615.     b = winy + px->dy + px->height;
  616.  
  617.     float t0, t1, t2, t5;
  618.  
  619. //    render->tc_src[1*2]  = 1.0;
  620. //    render->tc_src[2*2]  = 1.0;
  621. //    render->tc_src[2*2+1]= 1.0;
  622. //    render->tc_src[3*2+1]= 1.0;
  623.  
  624.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  625.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  626.  
  627.     vertices[2 * 2] = t2;
  628.     vertices[3 * 2] = t0;
  629.  
  630.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  631.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  632.     vertices[1*2+1] = t1;
  633.     vertices[3*2+1] = t5;
  634.  
  635.     glActiveTexture(GL_TEXTURE0);
  636.     glBindTexture(GL_TEXTURE_2D, bitmap->tex);
  637.  
  638.     glActiveTexture(GL_TEXTURE1);
  639.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  640.  
  641.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  642.  
  643.     glFlush();
  644.  
  645.     return;
  646. };
  647.  
  648. static int hw_create_client(int x, int y, uint32_t width, uint32_t height)
  649. {
  650.     px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height);
  651.  
  652.     return !px;
  653. };
  654.  
  655. static int hw_resize_client(int x, int y, uint32_t width, uint32_t height)
  656. {
  657.     if( x != px->dx ||
  658.         y != px->dy ||
  659.         width != px->width ||
  660.         height != px->height )
  661.     {
  662.         struct drm_i915_mask_update update;
  663.  
  664.         px->dx     = x;
  665.         px->dy     = y;
  666.         px->width  = width;
  667.         px->height = height;
  668.         update_mask(px);
  669.  
  670.         update.handle = px->mask.handle;
  671.         update.dx     = px->dx;
  672.         update.dy     = px->dy;
  673.         update.width  = px->width;
  674.         update.height = px->height;
  675.         update.bo_pitch = (px->width+15) & ~15;
  676.         update.bo_map = (int)px->mask.buffer;
  677.         update.forced = 1;
  678.  
  679.         drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update);
  680.     };
  681.  
  682.     return 0;
  683. };
  684.  
  685. static void hw_fini(void)
  686. {
  687.     struct drm_gem_close close;
  688.  
  689.     DBG("%s\n", __FUNCTION__);
  690.  
  691.     eglDestroyImageKHR(px->dpy, px->mask.image);
  692.     user_free(px->mask.buffer);
  693.     close.handle = px->mask.handle;
  694.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  695.  
  696.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  697.     glDeleteFramebuffers(1, &px->framebuffer);
  698.     eglDestroyImageKHR(px->dpy, px->screen);
  699.     glDeleteTextures(2, px->texture);
  700.     egl_destroy(px->dpy, px->context);
  701.     free(px);
  702. };
  703.  
  704. static struct pix_driver gl_driver =
  705. {
  706.     HW_TEX_BLIT,
  707.     hw_create_bitmap,
  708.     hw_destroy_bitmap,
  709.     hw_lock_bitmap,
  710.     hw_resize_bitmap,
  711.     hw_blit,
  712.     hw_create_client,
  713.     hw_resize_client,
  714.     hw_fini
  715. };
  716.  
  717. struct pix_driver *DrvInit(uint32_t service)
  718. {
  719.     EGLDisplay     dpy;
  720.     EGLConfig      config;
  721.     EGLContext     context;
  722.     int            ret;
  723.  
  724.     ret = egl_initialize(&dpy, &config, &context);
  725.     if( ret )
  726.         return NULL;
  727.  
  728.     return &gl_driver;
  729.  
  730. err_0:
  731.     egl_destroy(dpy, context);
  732.     return NULL;
  733. }
  734.  
  735.  
  736.