Subversion Repositories Kolibri OS

Rev

Rev 6137 | Rev 6334 | 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. #define LINE()    printf("%s line %d\n", __FUNCTION__,__LINE__)
  14.  
  15. static int drm_ioctl(int fd, unsigned long request, void *arg)
  16. {
  17.     ioctl_t  io;
  18.  
  19.     io.handle   = fd;
  20.     io.io_code  = request;
  21.     io.input    = arg;
  22.     io.inp_size = 64;
  23.     io.output   = NULL;
  24.     io.out_size = 0;
  25.  
  26.     return call_service(&io);
  27. }
  28.  
  29. static EGLImageKHR px_create_image(struct render *px,void *name,GLuint tex, EGLint *attribs)
  30. {
  31.     EGLImageKHR image;
  32.  
  33.     image = eglCreateImageKHR(px->dpy, px->context,
  34.                               EGL_DRM_BUFFER_MESA, name, attribs);
  35.     if(image == NULL)
  36.         goto err_0;
  37.  
  38.     glBindTexture(GL_TEXTURE_2D, tex);
  39.     if(glGetError() != GL_NO_ERROR)
  40.        goto err_1;
  41.  
  42.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
  43.     if(glGetError() != GL_NO_ERROR)
  44.        goto err_1;
  45.  
  46.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  47.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  48.  
  49.     return image;
  50.  
  51. err_1:
  52.     eglDestroyImageKHR(px->dpy, image);
  53. err_0:
  54.     return NULL;
  55. };
  56.  
  57. static int update_fb(struct render *px, int name, int pitch)
  58. {
  59.     GLenum      status;
  60.     EGLImageKHR screen;
  61.  
  62.     EGLint attribs[] = {
  63.         EGL_WIDTH, px->scr_width,
  64.         EGL_HEIGHT, px->scr_height,
  65.         EGL_DRM_BUFFER_STRIDE_MESA, pitch/4,
  66.         EGL_DRM_BUFFER_FORMAT_MESA,
  67.         EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
  68.         EGL_DRM_BUFFER_USE_MESA,
  69.         EGL_DRM_BUFFER_USE_SHARE_MESA |
  70.         EGL_DRM_BUFFER_USE_SCANOUT_MESA,
  71.         EGL_NONE
  72.     };
  73.     char *errmsg;
  74.  
  75.     px->screen = px_create_image(px,(void*)name, px->texture[TEX_SCREEN], attribs);
  76.     errmsg = "failed to create new screen image\n";
  77.     if(px->screen == EGL_NO_IMAGE_KHR)
  78.         goto err_0;
  79.  
  80.     px->screen = screen;
  81.  
  82.     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
  83.                        GL_TEXTURE_2D, px->texture[TEX_SCREEN],0);
  84.  
  85.     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  86.     if (status != GL_FRAMEBUFFER_COMPLETE)
  87.     {
  88.         const char *str;
  89.         switch (status)
  90.         {
  91.             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  92.                 str = "incomplete attachment";
  93.                 break;
  94.             case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  95.                 str = "incomplete/missing attachment";
  96.                 break;
  97.             case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
  98.                 str = "incomplete draw buffer";
  99.                 break;
  100.             case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
  101.                 str = "incomplete read buffer";
  102.                 break;
  103.             case GL_FRAMEBUFFER_UNSUPPORTED:
  104.                 str = "unsupported";
  105.                 break;
  106.             case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
  107.                 str = "incomplete multiple";
  108.                 break;
  109.             default:
  110.                 str = "unknown error";
  111.                 break;
  112.         }
  113.         DBG("destination framebuffer incomplete: %s [%#x]\n", str, status);
  114.  
  115.         return -1;
  116.     };
  117.  
  118.     DBG("framebuffer changed successfull\n");
  119.  
  120.     glViewport(0, 0, px->scr_width, px->scr_height);
  121.  
  122.     return 0;
  123.  
  124. err_0:
  125.     DBG("%s %s\n", __FUNCTION__, errmsg);
  126.  
  127.     return -1;
  128. };
  129.  
  130.  
  131.  
  132. static void *px_create_obj(struct render *px, size_t size,
  133.                            GLuint *handle, GLuint *name)
  134. {
  135.     struct drm_i915_gem_create create;
  136.     struct drm_i915_gem_mmap mmap_arg;
  137.     struct drm_gem_close close;
  138.     struct drm_gem_flink flink;
  139.  
  140.     create.size   = size;
  141.     create.handle = 0;
  142.  
  143.     if(drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_CREATE, &create))
  144.         goto err_0;
  145.  
  146.     *handle      = create.handle;
  147.     flink.handle = create.handle;
  148.     if (drm_ioctl(px->fd, DRM_IOCTL_GEM_FLINK, &flink))
  149.         goto err_1;
  150.  
  151.     *name = flink.name;
  152.  
  153.     mmap_arg.handle = *handle;
  154.     mmap_arg.offset = 0;
  155.     mmap_arg.size   = size;
  156.     if (drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))
  157.     {
  158.         DBG("%s: failed to mmap bitmap handle=%d, %d bytes, into CPU domain\n",
  159.                __FUNCTION__, *handle, size);
  160.         goto err_1;
  161.     };
  162.  
  163.     return (void*)(uintptr_t)mmap_arg.addr_ptr;
  164.  
  165. err_1:
  166.     close.handle = *handle;
  167.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  168. err_0:
  169.     return NULL;
  170. };
  171.  
  172. static int px_create_bitmap(struct render *px, struct bitmap *bitmap,
  173.                             size_t size, EGLint format)
  174. {
  175.     struct drm_gem_close close;
  176.     EGLint attribs[] = {
  177.         EGL_WIDTH, bitmap->width,
  178.         EGL_HEIGHT, bitmap->height,
  179.         EGL_DRM_BUFFER_STRIDE_MESA, 0,
  180.         EGL_DRM_BUFFER_FORMAT_MESA,
  181.         format,
  182.         EGL_DRM_BUFFER_USE_MESA,
  183.         EGL_DRM_BUFFER_USE_SHARE_MESA,
  184.         EGL_NONE
  185.     };
  186.  
  187.     bitmap->buffer = px_create_obj(px, size, &bitmap->handle, &bitmap->name);
  188.     if(bitmap->buffer == NULL)
  189.         goto err_0;
  190.  
  191.     switch(format)
  192.     {
  193.         case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  194.             attribs[5] = bitmap->pitch/4;
  195.             break;
  196.         case EGL_DRM_BUFFER_FORMAT_R8_MESA:
  197.             attribs[5] = bitmap->pitch;
  198.             break;
  199.         default:
  200.             DBG("%s invalid format %x\n",
  201.                     __FUNCTION__, format);
  202.             goto err_1;
  203.     }
  204.  
  205.     bitmap->image = px_create_image(px,(void*)bitmap->name,
  206.                                     bitmap->tex, attribs);
  207.     if(bitmap->image == NULL)
  208.         goto err_1;
  209.  
  210.     DBG("create bitmap:%p %dx%d pitch:%d\n"
  211.            "KHRimage:%p gl_tex:%d handle:%d name:%d\n"
  212.            "mapped at %x\n",
  213.             bitmap, bitmap->width, bitmap->height, bitmap->pitch,
  214.             bitmap->image, bitmap->tex, bitmap->handle, bitmap->name,
  215.             bitmap->buffer);
  216.  
  217.     return 0;
  218.  
  219. err_1:
  220.     user_free(bitmap->buffer);
  221.     close.handle = bitmap->handle;
  222.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  223. err_0:
  224.     return -1;
  225. }
  226.  
  227.  
  228. static int create_mask(struct render *px)
  229. {
  230.     struct drm_i915_mask_update update;
  231.     int    pitch;
  232.  
  233.     pitch = (px->width+15) & ~15;
  234.  
  235.     px->mask.width  = px->width;
  236.     px->mask.height = px->height;
  237.     px->mask.pitch  = pitch;
  238.     px->mask.tex    = px->texture[TEX_MASK];
  239.     px->mask_size   = pitch * px->height;
  240.  
  241.     if(px_create_bitmap(px, &px->mask, px->mask_size,
  242.                          EGL_DRM_BUFFER_FORMAT_R8_MESA) == 0)
  243.     {
  244.         update.handle = px->mask.handle;
  245.         update.dx     = px->dx;
  246.         update.dy     = px->dy;
  247.         update.width  = px->width;
  248.         update.height = px->height;
  249.         update.bo_pitch = (px->width+15) & ~15;
  250.         update.bo_map = (int)px->mask.buffer;
  251.         update.forced = 1;
  252.         drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update);
  253.         return 0;
  254.     };
  255.     return -1;
  256. };
  257.  
  258.  
  259. static int update_mask(struct render *px)
  260. {
  261.     struct drm_gem_close close;
  262.     EGLint attribs[] = {
  263.         EGL_WIDTH, 0,
  264.         EGL_HEIGHT, 0,
  265.         EGL_DRM_BUFFER_STRIDE_MESA, 0,
  266.         EGL_DRM_BUFFER_FORMAT_MESA,
  267.         EGL_DRM_BUFFER_FORMAT_R8_MESA,
  268.         EGL_DRM_BUFFER_USE_MESA,
  269.         EGL_DRM_BUFFER_USE_SHARE_MESA,
  270.         EGL_NONE
  271.     };
  272.     unsigned int size, pitch;
  273.  
  274.     eglDestroyImageKHR(px->dpy, px->mask.image);
  275.  
  276.     pitch = (px->width+15) & ~15;
  277.     size = pitch*px->height;
  278.  
  279.     if(size > px->mask_size)
  280.     {
  281.         user_free(px->mask.buffer);
  282.         close.handle = px->mask.handle;
  283.         drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  284.  
  285.         px->mask_size = size;
  286.  
  287.         px->mask.buffer = px_create_obj(px, px->mask_size,
  288.                                       &px->mask.handle, &px->mask.name);
  289.         if(px->mask.buffer == 0)
  290.             goto err_0;
  291.     };
  292.  
  293.     attribs[1] = px->width;
  294.     attribs[3] = px->height;
  295.     attribs[5] = pitch;
  296.  
  297.     px->mask.image = px_create_image(px,(void*)px->mask.name,
  298.                                      px->mask.tex, attribs);
  299.     if(px->mask.image == NULL)
  300.         goto err_1;
  301.  
  302.     DBG("create mask w:%d h:%d pitch:%d\n"
  303.         "KHRimage:%p gl_tex:%d handle:%d name:%d\n"
  304.         "mapped at %x\n",
  305.          px->width, px->height,
  306.          pitch, px->mask.image, px->texture[TEX_MASK],
  307.          px->mask.handle, px->mask.name, px->mask.buffer);
  308.  
  309.     return 0;
  310.  
  311. err_1:
  312.     user_free(px->mask.buffer);
  313.     close.handle = px->mask.handle;
  314.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  315. err_0:
  316.     return -1;
  317. };
  318.  
  319. static GLint create_shader(GLenum type, const char *source)
  320. {
  321.     GLint ok;
  322.     GLint shader;
  323.  
  324.     shader = glCreateShader(type);
  325.     if(shader == 0)
  326.         goto err;
  327.  
  328.     glShaderSource(shader, 1, (const GLchar **) &source, NULL);
  329.     glCompileShader(shader);
  330.     glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
  331.     if (!ok) {
  332.         GLchar *info;
  333.         GLint size;
  334.  
  335.         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
  336.         info = malloc(size);
  337.  
  338.         glGetShaderInfoLog(shader, size, NULL, info);
  339.         DBG("Failed to compile %s: %s\n",
  340.                 type == GL_FRAGMENT_SHADER ? "FS" : "VS",info);
  341.         DBG("Program source:\n%s", source);
  342.         DBG("GLSL compile failure\n");
  343.         free(info);
  344.         glDeleteShader(shader);
  345.         shader = 0;
  346.     };
  347.  
  348.     DBG("create shader %d\n", shader);
  349. err:
  350.     return shader;
  351. }
  352.  
  353. static GLuint create_rgba_shader(struct shader *shader)
  354. {
  355.     const char *vs_src =
  356.         "attribute vec4 v_position;\n"
  357.         "attribute vec4 v_texcoord0;\n"
  358.         "varying vec2 tex_coord;\n"
  359.         "void main()\n"
  360.         "{\n"
  361.         "   gl_Position = v_position;\n"
  362.         "   tex_coord   = v_texcoord0.xy;\n"
  363.         "}\n";
  364.  
  365.     const char *fs_rgba =
  366.         "uniform sampler2D tex_rgba;\n"
  367.         "uniform sampler2D tex_mask;\n"
  368.         "varying vec2 tex_coord;\n"
  369.         "void main()\n"
  370.         "{\n"
  371.         "   float ca = texture2D(tex_mask, tex_coord).r;\n"
  372.         "   gl_FragColor = vec4(texture2D(tex_rgba, tex_coord).rgb, ca);\n"
  373.         "}\n";
  374.  
  375.     GLuint prog;
  376.     GLint  vs_shader, fs_shader;
  377.     int ret;
  378.  
  379.     prog = glCreateProgram();
  380.     if(prog == 0)
  381.         goto err;
  382.  
  383.     vs_shader = create_shader(GL_VERTEX_SHADER, vs_src);
  384.     if(vs_shader == 0)
  385.         goto err;
  386.  
  387.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_rgba);
  388.     if(fs_shader == 0)
  389.         goto err;
  390.  
  391.     glAttachShader(prog, vs_shader);
  392.     glAttachShader(prog, fs_shader);
  393.     glBindAttribLocation(prog, 0, "v_position");
  394.     glBindAttribLocation(prog, 1, "v_texcoord0");
  395.  
  396.     glLinkProgram(prog);
  397.     glGetProgramiv(prog, GL_LINK_STATUS, &ret);
  398.     if (!ret)
  399.     {
  400.         GLchar *info;
  401.         GLint size;
  402.  
  403.         glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
  404.         info = malloc(size);
  405.  
  406.         glGetProgramInfoLog(prog, size, NULL, info);
  407.         DBG("Failed to link: %s\n", info);
  408.         DBG("GLSL link failure\n");
  409.         free(info);
  410.         goto err;
  411.     }
  412.  
  413.     shader->sampler0  = glGetUniformLocation(prog,"tex_rgba");
  414.     shader->sm_mask   = glGetUniformLocation(prog,"tex_mask");
  415.     shader->blit_prog = prog;
  416.     return prog;
  417. err:
  418.     return 0;
  419. }
  420.  
  421. static GLuint create_y_uv_shader(struct shader *shader)
  422. {
  423.     const char *vs_src =
  424.         "attribute vec4 v_position;\n"
  425.         "attribute vec4 v_texcoord0;\n"
  426.         "varying vec2 tex_coord;\n"
  427.         "void main()\n"
  428.         "{\n"
  429.         "   gl_Position = v_position;\n"
  430.         "   tex_coord   = v_texcoord0.xy;\n"
  431.         "}\n";
  432.  
  433.     const char *fs_y_uv =
  434.         "uniform sampler2D tex_src_y;\n"
  435.         "uniform sampler2D tex_src_uv;\n"
  436.         "uniform sampler2D tex_mask;\n"
  437.         "varying vec2 tex_coord;\n"
  438.         "void main()\n"
  439.         "{\n"
  440.         "   float y = 1.16438356 * (texture2D(tex_src_y, tex_coord).x - 0.0625);\n"
  441.         "   float u = texture2D(tex_src_uv, tex_coord).r - 0.5;\n"
  442.         "   float v = texture2D(tex_src_uv, tex_coord).g - 0.5;\n"
  443.         "   gl_FragColor.r = y + 1.59602678 * v;\n"          \
  444.         "   gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
  445.         "   gl_FragColor.b = y + 2.01723214 * u;\n"          \
  446.         "   gl_FragColor.a = texture2D(tex_mask, tex_coord).r;\n"
  447.         "}\n";
  448.  
  449.     GLuint prog;
  450.     GLint  vs_shader, fs_shader;
  451.     int ret;
  452.  
  453.     prog = glCreateProgram();
  454.     if(prog == 0)
  455.         goto err;
  456.  
  457.     vs_shader = create_shader(GL_VERTEX_SHADER, vs_src);
  458.     if(vs_shader == 0)
  459.         goto err;
  460.  
  461.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_y_uv);
  462.     if(fs_shader == 0)
  463.         goto err;
  464.  
  465.     glAttachShader(prog, vs_shader);
  466.     glAttachShader(prog, fs_shader);
  467.     glBindAttribLocation(prog, 0, "v_position");
  468.     glBindAttribLocation(prog, 1, "v_texcoord0");
  469.  
  470.     glLinkProgram(prog);
  471.     glGetProgramiv(prog, GL_LINK_STATUS, &ret);
  472.     if (!ret)
  473.     {
  474.         GLchar *info;
  475.         GLint size;
  476.  
  477.         glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
  478.         info = malloc(size);
  479.  
  480.         glGetProgramInfoLog(prog, size, NULL, info);
  481.         DBG("Failed to link: %s\n", info);
  482.         DBG("GLSL link failure\n");
  483.         free(info);
  484.         goto err;
  485.     }
  486.  
  487.     shader->sampler0  = glGetUniformLocation(prog,"tex_src_y");
  488.     shader->sampler1  = glGetUniformLocation(prog,"tex_src_uv");
  489.     shader->sm_mask   = glGetUniformLocation(prog,"tex_mask");
  490.     shader->blit_prog = prog;
  491.     return prog;
  492. err:
  493.     return 0;
  494. }
  495.  
  496. static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h)
  497. {
  498.  
  499.     struct drm_i915_fb_info fb;
  500.     struct render *px;
  501.  
  502.     int    ret;
  503.  
  504.     px = (struct render*)malloc(sizeof(struct render));
  505.     if(px == NULL)
  506.         goto err_0;
  507.  
  508.     px->fd  = get_service("DISPLAY");
  509.  
  510.     __builtin_memset(&fb, 0, sizeof(fb));
  511.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  512.     {   DBG("failed to get framebuffer info\n");
  513.         goto err_1;
  514.     };
  515.  
  516.     px->dpy     = dpy;
  517.     px->context = context;
  518.     px->dx      = dx;
  519.     px->dy      = dy;
  520.     px->width   = w;
  521.     px->height  = h;
  522.     px->scr_width  = fb.width;
  523.     px->scr_height = fb.height;
  524.  
  525.     glGenTextures(2, px->texture);
  526.     if(glGetError() != GL_NO_ERROR)
  527.        goto err_1;
  528.  
  529.     glGenFramebuffers(1, &px->framebuffer);
  530.     if(glGetError() != GL_NO_ERROR)
  531.        goto err_2;
  532.  
  533.     glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer);
  534.     if(glGetError() != GL_NO_ERROR)
  535.        goto err_3;
  536.  
  537.     if(update_fb(px, fb.name, fb.pitch))
  538.        goto err_4;
  539.  
  540.     glMatrixMode(GL_PROJECTION);
  541.     glLoadIdentity();
  542.     glMatrixMode(GL_MODELVIEW);
  543.     glLoadIdentity();
  544.  
  545.     if(create_mask(px))
  546.         goto err_4;
  547.  
  548.     create_y_uv_shader(&px->shader_y_uv);
  549.     create_rgba_shader(&px->shader_rgba);
  550.  
  551.     glEnableClientState(GL_VERTEX_ARRAY);
  552.  
  553.     glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices);
  554.     glEnableVertexAttribArray(0);
  555.  
  556.     glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src);
  557.     glEnableVertexAttribArray(1);
  558.  
  559.     glEnable(GL_BLEND);
  560.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  561.  
  562.     px->tc_src[0]    = 0.0;
  563.     px->tc_src[1]    = 0.0;
  564.     px->tc_src[1*2]  = 1.0;
  565.     px->tc_src[1*2+1]= 0.0;
  566.     px->tc_src[2*2]  = 1.0;
  567.     px->tc_src[2*2+1]= 1.0;
  568.     px->tc_src[3*2]  = 0.0;
  569.     px->tc_src[3*2+1]= 1.0;
  570.  
  571.     DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n",
  572.         px->screen,fb.width, fb.height, fb.pitch, fb.name);
  573.  
  574.     return px;
  575.  
  576. err_4:
  577.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  578. err_3:
  579.     glDeleteFramebuffers(1, &px->framebuffer);
  580. err_2:
  581.     glDeleteTextures(2, px->texture);
  582. err_1:
  583.     free(px);
  584. err_0:
  585.     return NULL;
  586. };
  587.  
  588. static struct render *px;
  589.  
  590. static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height)
  591. {
  592.     struct bitmap *bitmap;
  593.  
  594.     bitmap = malloc(sizeof(struct bitmap));
  595.     if(bitmap == NULL)
  596.         return NULL;
  597.  
  598.     glGenTextures(1, &bitmap->tex);
  599.     if(glGetError() != GL_NO_ERROR)
  600.        goto err_0;
  601.  
  602.     bitmap->width   = width;
  603.     bitmap->height  = height;
  604.     bitmap->pitch   = (width*4 + 15) & ~15;
  605.  
  606.     if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height,
  607.                          EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0)
  608.     {
  609.         return bitmap;
  610.     };
  611.  
  612.     glDeleteTextures(1, &bitmap->tex);
  613. err_0:
  614.     free(bitmap);
  615.     return NULL;
  616. };
  617.  
  618. static int hw_destroy_planar(planar_t *planar)
  619. {
  620.     glDeleteTextures(planar->num_planes, &planar->tex[0]);
  621.  
  622.     if(planar->image[2] != NULL)
  623.         eglDestroyImageKHR(px->dpy, planar->image[2]);
  624.     if(planar->image[1] != NULL)
  625.         eglDestroyImageKHR(px->dpy, planar->image[1]);
  626.     if(planar->image[0] != NULL)
  627.         eglDestroyImageKHR(px->dpy, planar->image[0]);
  628.     if(planar->planar_image != NULL)
  629.         eglDestroyImageKHR(px->dpy, planar->planar_image);
  630.     free(planar);
  631.     return 0;
  632. };
  633.  
  634. static planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height,
  635.                             uint32_t offset0, uint32_t pitch0,
  636.                             uint32_t offset1, uint32_t pitch1,
  637.                             uint32_t offset2, uint32_t pitch2)
  638. {
  639.     struct drm_gem_close close;
  640.     planar_t *planar;
  641.     EGLImageKHR img;
  642.     int num_planes;
  643.     int i;
  644.  
  645.     EGLint attribs[] = {
  646.         EGL_WIDTH, width,
  647.         EGL_HEIGHT,height,
  648.         EGL_DRM_BUFFER_FORMAT_MESA, format,
  649.         EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0,
  650.         EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0,
  651.         EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1,
  652.         EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1,
  653.         EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2,
  654.         EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2,
  655.         EGL_NONE, EGL_NONE
  656.     };
  657.  
  658.     switch (format)
  659.     {
  660.         case WL_DRM_FORMAT_NV12:
  661.             num_planes = 2;
  662.             break;
  663.         case EGL_TEXTURE_Y_U_V_WL:
  664.             num_planes = 3;
  665.             break;
  666.         case EGL_TEXTURE_Y_XUXV_WL:
  667.             num_planes = 2;
  668.             break;
  669.         default:
  670.             num_planes = 0;
  671.     }
  672.  
  673. //    printf("%s num_planes %d\n", __FUNCTION__, num_planes);
  674.  
  675.     if(num_planes == 0)
  676.         goto fail;
  677.  
  678.     planar = calloc(1, sizeof(struct planar));
  679.     if(planar == NULL)
  680.         goto fail;
  681.  
  682.     img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs);
  683.     if(img == NULL)
  684.         goto err_0;
  685.  
  686.     planar->width  = width;
  687.     planar->height = height;
  688.     planar->name   = name;
  689.     planar->num_planes = num_planes;
  690.     planar->planar_image = img;
  691.  
  692.     planar->offset[0] = offset0;
  693.     planar->offset[1] = offset1;
  694.     planar->offset[2] = offset2;
  695.  
  696.     planar->pitch[0] = pitch0;
  697.     planar->pitch[1] = pitch1;
  698.     planar->pitch[2] = pitch2;
  699.  
  700.     glGenTextures(num_planes, &planar->tex[0]);
  701.     if(glGetError() != GL_NO_ERROR)
  702.        goto err_0;
  703.  
  704.     for(i = 0; i < num_planes; i++)
  705.     {
  706.         EGLImageKHR image;
  707.         EGLint attr[3];
  708.         attr[0] = EGL_WAYLAND_PLANE_WL;
  709.         attr[1] = i;
  710.         attr[2] = EGL_NONE;
  711.  
  712.         image = eglCreateImageKHR(px->dpy, px->context,
  713.                                    EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)img, attr);
  714.         if(image == NULL)
  715.             goto err_1;
  716.  
  717.         planar->image[i] = image;
  718.         glBindTexture(GL_TEXTURE_2D, planar->tex[i]);
  719.         if(glGetError() != GL_NO_ERROR)
  720.         {
  721.             goto err_1;
  722.         };
  723.  
  724.         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
  725.         if(glGetError() != GL_NO_ERROR)
  726.         {
  727.             goto err_1;
  728.         }
  729.  
  730.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  731.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  732.     };
  733.  
  734.     return planar;
  735.  
  736. err_1:
  737.     hw_destroy_planar(planar);
  738.     return NULL;
  739.  
  740. err_0:
  741.     free(planar);
  742. fail:
  743.     return NULL;
  744. }
  745.  
  746. static int hw_destroy_bitmap(bitmap_t * bitmap)
  747. {
  748.     struct drm_gem_close close;
  749.  
  750.     glDeleteTextures(1, &bitmap->tex);
  751.     eglDestroyImageKHR(px->dpy, bitmap->image);
  752.     user_free(bitmap->buffer);
  753.     close.handle = bitmap->handle;
  754.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  755.     free(bitmap);
  756.     return 0;
  757. };
  758.  
  759. static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch)
  760. {
  761.     *pitch = bitmap->pitch;
  762.  
  763.     return bitmap->buffer;
  764. };
  765.  
  766. static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height)
  767. {
  768.     return 0;
  769. }
  770.  
  771. char proc_info[1024];
  772.  
  773. static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y,
  774.                    uint32_t w, uint32_t h, int src_x, int src_y)
  775. {
  776.     struct drm_i915_mask_update update;
  777.     struct drm_i915_fb_info fb;
  778.  
  779.     uint32_t winx, winy, winw, winh;
  780.     uint8_t  state;
  781.     float xscale, yscale;
  782.     int r, b;
  783.     float *vertices  = px->vertices;
  784.  
  785.     get_proc_info(proc_info);
  786.  
  787.     state  = *(uint8_t*)(proc_info+70);
  788.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  789.         return;
  790.  
  791.     winx = *(uint32_t*)(proc_info+34);
  792.     winy = *(uint32_t*)(proc_info+38);
  793.     winw = *(uint32_t*)(proc_info+42)+1;
  794.     winh = *(uint32_t*)(proc_info+46)+1;
  795.  
  796.     __builtin_memset(&fb, 0, sizeof(fb));
  797.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  798.     {
  799.         DBG("failed to get framebuffer info\n");
  800.         return;
  801.     };
  802.  
  803.     if( fb.width  != px->scr_width ||
  804.         fb.height != px->scr_height )
  805.     {
  806.         px->scr_width  = fb.width;
  807.         px->scr_height = fb.height;
  808.  
  809.         eglDestroyImageKHR(px->dpy, px->screen);
  810.  
  811.         if(update_fb(px, fb.name, fb.pitch))
  812.             return;
  813.     };
  814.  
  815.     update.handle = px->mask.handle;
  816.     update.dx     = px->dx;
  817.     update.dy     = px->dy;
  818.     update.width  = px->width;
  819.     update.height = px->height;
  820.     update.bo_pitch = (px->width+15) & ~15;
  821.     update.bo_map = (int)px->mask.buffer;
  822.  
  823.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  824.     {
  825.         return;
  826.     }
  827.  
  828.     xscale = 1.0/px->scr_width;
  829.     yscale = 1.0/px->scr_height;
  830.  
  831.     r = winx + px->dx + px->width;
  832.     b = winy + px->dy + px->height;
  833.  
  834.     float t0, t1, t2, t5;
  835.  
  836. //    render->tc_src[1*2]  = 1.0;
  837. //    render->tc_src[2*2]  = 1.0;
  838. //    render->tc_src[2*2+1]= 1.0;
  839. //    render->tc_src[3*2+1]= 1.0;
  840.  
  841.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  842.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  843.  
  844.     vertices[2 * 2] = t2;
  845.     vertices[3 * 2] = t0;
  846.  
  847.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  848.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  849.     vertices[1*2+1] = t1;
  850.     vertices[3*2+1] = t5;
  851.  
  852.     struct shader *shader = &px->shader_rgba;
  853.  
  854.     glUseProgram(shader->blit_prog);
  855.     glUniform1i(shader->sampler0, 0);
  856.     glUniform1i(shader->sm_mask, 1);
  857.  
  858.     glActiveTexture(GL_TEXTURE0);
  859.     glBindTexture(GL_TEXTURE_2D, bitmap->tex);
  860.  
  861.     glActiveTexture(GL_TEXTURE1);
  862.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  863.  
  864.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  865.  
  866.     glFlush();
  867.  
  868.     return;
  869. };
  870.  
  871. static int hw_blit_planar(planar_t *planar, int dst_x, int dst_y,
  872.                    uint32_t w, uint32_t h, int src_x, int src_y)
  873. {
  874.     struct drm_i915_mask_update update;
  875.     struct drm_i915_fb_info fb;
  876.  
  877.     uint32_t winx, winy, winw, winh;
  878.     uint8_t  state;
  879.     float xscale, yscale;
  880.     int r, b;
  881.     float *vertices  = px->vertices;
  882.  
  883.     get_proc_info(proc_info);
  884.  
  885.     state  = *(uint8_t*)(proc_info+70);
  886.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  887.         return;
  888.  
  889.     winx = *(uint32_t*)(proc_info+34);
  890.     winy = *(uint32_t*)(proc_info+38);
  891.     winw = *(uint32_t*)(proc_info+42)+1;
  892.     winh = *(uint32_t*)(proc_info+46)+1;
  893.  
  894.     __builtin_memset(&fb, 0, sizeof(fb));
  895.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  896.     {
  897.         DBG("failed to get framebuffer info\n");
  898.         return;
  899.     };
  900.  
  901.     if( fb.width  != px->scr_width ||
  902.         fb.height != px->scr_height )
  903.     {
  904.         px->scr_width  = fb.width;
  905.         px->scr_height = fb.height;
  906.  
  907.         eglDestroyImageKHR(px->dpy, px->screen);
  908.  
  909.         if(update_fb(px, fb.name, fb.pitch))
  910.             return;
  911.     };
  912.  
  913.     update.handle = px->mask.handle;
  914.     update.dx     = px->dx;
  915.     update.dy     = px->dy;
  916.     update.width  = px->width;
  917.     update.height = px->height;
  918.     update.bo_pitch = (px->width+15) & ~15;
  919.     update.bo_map = (int)px->mask.buffer;
  920.  
  921.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  922.     {
  923.         return;
  924.     }
  925.  
  926.     xscale = 1.0/px->scr_width;
  927.     yscale = 1.0/px->scr_height;
  928.  
  929.     r = winx + px->dx + px->width;
  930.     b = winy + px->dy + px->height;
  931.  
  932.     float t0, t1, t2, t5;
  933.  
  934. //    render->tc_src[1*2]  = 1.0;
  935. //    render->tc_src[2*2]  = 1.0;
  936. //    render->tc_src[2*2+1]= 1.0;
  937. //    render->tc_src[3*2+1]= 1.0;
  938.  
  939.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  940.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  941.  
  942.     vertices[2 * 2] = t2;
  943.     vertices[3 * 2] = t0;
  944.  
  945.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  946.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  947.     vertices[1*2+1] = t1;
  948.     vertices[3*2+1] = t5;
  949.  
  950.     struct shader *shader = &px->shader_y_uv;
  951.  
  952.     glUseProgram(shader->blit_prog);
  953.     glUniform1i(shader->sampler0, 0);
  954.     glUniform1i(shader->sampler1, 1);
  955.     glUniform1i(shader->sm_mask, 2);
  956.  
  957.     glActiveTexture(GL_TEXTURE0);
  958.     glBindTexture(GL_TEXTURE_2D, planar->tex[0]);
  959.  
  960.     glActiveTexture(GL_TEXTURE1);
  961.     glBindTexture(GL_TEXTURE_2D, planar->tex[1]);
  962.  
  963.     glActiveTexture(GL_TEXTURE2);
  964.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  965.  
  966.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  967.  
  968.     glFlush();
  969.  
  970.     return;
  971. };
  972.  
  973. static int hw_create_client(int x, int y, uint32_t width, uint32_t height)
  974. {
  975.     px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height);
  976.  
  977.     return !px;
  978. };
  979.  
  980. static int hw_resize_client(int x, int y, uint32_t width, uint32_t height)
  981. {
  982.     if( x != px->dx ||
  983.         y != px->dy ||
  984.         width != px->width ||
  985.         height != px->height )
  986.     {
  987.         struct drm_i915_mask_update update;
  988.  
  989.         px->dx     = x;
  990.         px->dy     = y;
  991.         px->width  = width;
  992.         px->height = height;
  993.         update_mask(px);
  994.  
  995.         update.handle = px->mask.handle;
  996.         update.dx     = px->dx;
  997.         update.dy     = px->dy;
  998.         update.width  = px->width;
  999.         update.height = px->height;
  1000.         update.bo_pitch = (px->width+15) & ~15;
  1001.         update.bo_map = (int)px->mask.buffer;
  1002.         update.forced = 1;
  1003.  
  1004.         drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update);
  1005.     };
  1006.  
  1007.     return 0;
  1008. };
  1009.  
  1010. static void hw_fini(void)
  1011. {
  1012.     struct drm_gem_close close;
  1013.  
  1014.     DBG("%s\n", __FUNCTION__);
  1015.  
  1016.     eglDestroyImageKHR(px->dpy, px->mask.image);
  1017.     user_free(px->mask.buffer);
  1018.     close.handle = px->mask.handle;
  1019.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  1020.  
  1021.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1022.     glDeleteFramebuffers(1, &px->framebuffer);
  1023.     eglDestroyImageKHR(px->dpy, px->screen);
  1024.     glDeleteTextures(2, px->texture);
  1025.     egl_destroy(px->dpy, px->context);
  1026.     free(px);
  1027. };
  1028.  
  1029. static struct pix_driver gl_driver =
  1030. {
  1031.     HW_TEX_BLIT,
  1032.     hw_create_bitmap,
  1033.     hw_destroy_bitmap,
  1034.     hw_lock_bitmap,
  1035.     hw_resize_bitmap,
  1036.     hw_blit,
  1037.     hw_create_client,
  1038.     hw_resize_client,
  1039.     hw_fini,
  1040.     hw_create_planar,
  1041.     hw_destroy_planar,
  1042.     hw_blit_planar
  1043. };
  1044.  
  1045. struct pix_driver *DrvInit(uint32_t service)
  1046. {
  1047.     EGLDisplay     dpy;
  1048.     EGLConfig      config;
  1049.     EGLContext     context;
  1050.     int            ret;
  1051.  
  1052.     ret = egl_initialize(&dpy, &config, &context);
  1053.     if( ret )
  1054.         return NULL;
  1055.  
  1056.     return &gl_driver;
  1057.  
  1058. err_0:
  1059.     egl_destroy(dpy, context);
  1060.     return NULL;
  1061. }
  1062.  
  1063.  
  1064.