Subversion Repositories Kolibri OS

Rev

Rev 6115 | Rev 6142 | 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 planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height,
  619.                             uint32_t offset0, uint32_t pitch0,
  620.                             uint32_t offset1, uint32_t pitch1,
  621.                             uint32_t offset2, uint32_t pitch2)
  622. {
  623.     struct drm_gem_close close;
  624.     planar_t *planar;
  625.     EGLImageKHR img;
  626.     int num_planes;
  627.     int i;
  628.  
  629.     EGLint attribs[] = {
  630.         EGL_WIDTH, width,
  631.         EGL_HEIGHT,height,
  632.         EGL_DRM_BUFFER_FORMAT_MESA, format,
  633.         EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0,
  634.         EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0,
  635.         EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1,
  636.         EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1,
  637.         EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2,
  638.         EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2,
  639.         EGL_NONE, EGL_NONE
  640.     };
  641.  
  642.     switch (format)
  643.     {
  644.         case WL_DRM_FORMAT_NV12:
  645.             num_planes = 2;
  646.             break;
  647.         case EGL_TEXTURE_Y_U_V_WL:
  648.             num_planes = 3;
  649.             break;
  650.         case EGL_TEXTURE_Y_XUXV_WL:
  651.             num_planes = 2;
  652.             break;
  653.         default:
  654.             num_planes = 0;
  655.     }
  656.  
  657. //    printf("%s num_planes %d\n", __FUNCTION__, num_planes);
  658.  
  659.     if(num_planes == 0)
  660.         goto fail;
  661.  
  662.     planar = calloc(1, sizeof(struct planar));
  663.     if(planar == NULL)
  664.         goto fail;
  665.  
  666.     img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs);
  667.     if(img == NULL)
  668.         goto err_0;
  669.  
  670.     planar->width  = width;
  671.     planar->height = height;
  672.     planar->name   = name;
  673.     planar->planar_image = img;
  674.  
  675.     planar->offset[0] = offset0;
  676.     planar->offset[1] = offset1;
  677.     planar->offset[2] = offset2;
  678.  
  679.     planar->pitch[0] = pitch0;
  680.     planar->pitch[1] = pitch1;
  681.     planar->pitch[2] = pitch2;
  682.  
  683.     glGenTextures(num_planes, &planar->tex[0]);
  684.  
  685.     for(i = 0; i < num_planes; i++)
  686.     {
  687.         EGLImageKHR image;
  688.         EGLint attr[3];
  689.         attr[0] = EGL_WAYLAND_PLANE_WL;
  690.         attr[1] = i;
  691.         attr[2] = EGL_NONE;
  692.  
  693.         image = eglCreateImageKHR(px->dpy, px->context,
  694.                                    EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)img, attr);
  695.  
  696.         planar->image[i] = image;
  697.         glBindTexture(GL_TEXTURE_2D, planar->tex[i]);
  698.  
  699.         if(glGetError() != GL_NO_ERROR)
  700.         {
  701.             goto fail;
  702.         };
  703.  
  704.         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
  705.         if(glGetError() != GL_NO_ERROR)
  706.         {
  707.             goto fail;
  708.         }
  709.  
  710.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  711.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  712.     };
  713.  
  714.     return planar;
  715.  
  716. err_0:
  717.     free(planar);
  718. fail:
  719.  
  720.     return NULL;
  721. }
  722.  
  723.  
  724. static int hw_destroy_bitmap(bitmap_t * bitmap)
  725. {
  726.     struct drm_gem_close close;
  727.  
  728.     glDeleteTextures(1, &bitmap->tex);
  729.     eglDestroyImageKHR(px->dpy, bitmap->image);
  730.     user_free(bitmap->buffer);
  731.     close.handle = bitmap->handle;
  732.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  733.     free(bitmap);
  734. };
  735.  
  736. static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch)
  737. {
  738.     *pitch = bitmap->pitch;
  739.  
  740.     return bitmap->buffer;
  741. };
  742.  
  743. static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height)
  744. {
  745.     return 0;
  746. }
  747.  
  748. char proc_info[1024];
  749.  
  750. static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y,
  751.                    uint32_t w, uint32_t h, int src_x, int src_y)
  752. {
  753.     struct drm_i915_mask_update update;
  754.     struct drm_i915_fb_info fb;
  755.  
  756.     uint32_t winx, winy, winw, winh;
  757.     uint8_t  state;
  758.     float xscale, yscale;
  759.     int r, b;
  760.     float *vertices  = px->vertices;
  761.  
  762.     get_proc_info(proc_info);
  763.  
  764.     state  = *(uint8_t*)(proc_info+70);
  765.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  766.         return;
  767.  
  768.     winx = *(uint32_t*)(proc_info+34);
  769.     winy = *(uint32_t*)(proc_info+38);
  770.     winw = *(uint32_t*)(proc_info+42)+1;
  771.     winh = *(uint32_t*)(proc_info+46)+1;
  772.  
  773.     __builtin_memset(&fb, 0, sizeof(fb));
  774.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  775.     {
  776.         DBG("failed to get framebuffer info\n");
  777.         return;
  778.     };
  779.  
  780.     if( fb.width  != px->scr_width ||
  781.         fb.height != px->scr_height )
  782.     {
  783.         px->scr_width  = fb.width;
  784.         px->scr_height = fb.height;
  785.  
  786.         eglDestroyImageKHR(px->dpy, px->screen);
  787.  
  788.         if(update_fb(px, fb.name, fb.pitch))
  789.             return;
  790.     };
  791.  
  792.     update.handle = px->mask.handle;
  793.     update.dx     = px->dx;
  794.     update.dy     = px->dy;
  795.     update.width  = px->width;
  796.     update.height = px->height;
  797.     update.bo_pitch = (px->width+15) & ~15;
  798.     update.bo_map = (int)px->mask.buffer;
  799.  
  800.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  801.     {
  802.         return;
  803.     }
  804.  
  805.     xscale = 1.0/px->scr_width;
  806.     yscale = 1.0/px->scr_height;
  807.  
  808.     r = winx + px->dx + px->width;
  809.     b = winy + px->dy + px->height;
  810.  
  811.     float t0, t1, t2, t5;
  812.  
  813. //    render->tc_src[1*2]  = 1.0;
  814. //    render->tc_src[2*2]  = 1.0;
  815. //    render->tc_src[2*2+1]= 1.0;
  816. //    render->tc_src[3*2+1]= 1.0;
  817.  
  818.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  819.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  820.  
  821.     vertices[2 * 2] = t2;
  822.     vertices[3 * 2] = t0;
  823.  
  824.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  825.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  826.     vertices[1*2+1] = t1;
  827.     vertices[3*2+1] = t5;
  828.  
  829.     struct shader *shader = &px->shader_rgba;
  830.  
  831.     glUseProgram(shader->blit_prog);
  832.     glUniform1i(shader->sampler0, 0);
  833.     glUniform1i(shader->sm_mask, 1);
  834.  
  835.     glActiveTexture(GL_TEXTURE0);
  836.     glBindTexture(GL_TEXTURE_2D, bitmap->tex);
  837.  
  838.     glActiveTexture(GL_TEXTURE1);
  839.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  840.  
  841.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  842.  
  843.     glFlush();
  844.  
  845.     return;
  846. };
  847.  
  848. static int hw_blit_planar(planar_t *planar, int dst_x, int dst_y,
  849.                    uint32_t w, uint32_t h, int src_x, int src_y)
  850. {
  851.     struct drm_i915_mask_update update;
  852.     struct drm_i915_fb_info fb;
  853.  
  854.     uint32_t winx, winy, winw, winh;
  855.     uint8_t  state;
  856.     float xscale, yscale;
  857.     int r, b;
  858.     float *vertices  = px->vertices;
  859.  
  860.     get_proc_info(proc_info);
  861.  
  862.     state  = *(uint8_t*)(proc_info+70);
  863.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  864.         return;
  865.  
  866.     winx = *(uint32_t*)(proc_info+34);
  867.     winy = *(uint32_t*)(proc_info+38);
  868.     winw = *(uint32_t*)(proc_info+42)+1;
  869.     winh = *(uint32_t*)(proc_info+46)+1;
  870.  
  871.     __builtin_memset(&fb, 0, sizeof(fb));
  872.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  873.     {
  874.         DBG("failed to get framebuffer info\n");
  875.         return;
  876.     };
  877.  
  878.     if( fb.width  != px->scr_width ||
  879.         fb.height != px->scr_height )
  880.     {
  881.         px->scr_width  = fb.width;
  882.         px->scr_height = fb.height;
  883.  
  884.         eglDestroyImageKHR(px->dpy, px->screen);
  885.  
  886.         if(update_fb(px, fb.name, fb.pitch))
  887.             return;
  888.     };
  889.  
  890.     update.handle = px->mask.handle;
  891.     update.dx     = px->dx;
  892.     update.dy     = px->dy;
  893.     update.width  = px->width;
  894.     update.height = px->height;
  895.     update.bo_pitch = (px->width+15) & ~15;
  896.     update.bo_map = (int)px->mask.buffer;
  897.  
  898.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  899.     {
  900.         return;
  901.     }
  902.  
  903.     xscale = 1.0/px->scr_width;
  904.     yscale = 1.0/px->scr_height;
  905.  
  906.     r = winx + px->dx + px->width;
  907.     b = winy + px->dy + px->height;
  908.  
  909.     float t0, t1, t2, t5;
  910.  
  911. //    render->tc_src[1*2]  = 1.0;
  912. //    render->tc_src[2*2]  = 1.0;
  913. //    render->tc_src[2*2+1]= 1.0;
  914. //    render->tc_src[3*2+1]= 1.0;
  915.  
  916.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  917.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  918.  
  919.     vertices[2 * 2] = t2;
  920.     vertices[3 * 2] = t0;
  921.  
  922.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  923.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  924.     vertices[1*2+1] = t1;
  925.     vertices[3*2+1] = t5;
  926.  
  927.     struct shader *shader = &px->shader_y_uv;
  928.  
  929.     glUseProgram(shader->blit_prog);
  930.     glUniform1i(shader->sampler0, 0);
  931.     glUniform1i(shader->sampler1, 1);
  932.     glUniform1i(shader->sm_mask, 2);
  933.  
  934.     glActiveTexture(GL_TEXTURE0);
  935.     glBindTexture(GL_TEXTURE_2D, planar->tex[0]);
  936.  
  937.     glActiveTexture(GL_TEXTURE1);
  938.     glBindTexture(GL_TEXTURE_2D, planar->tex[1]);
  939.  
  940.     glActiveTexture(GL_TEXTURE2);
  941.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  942.  
  943.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  944.  
  945.     glFlush();
  946.  
  947.     return;
  948. };
  949.  
  950. static int hw_create_client(int x, int y, uint32_t width, uint32_t height)
  951. {
  952.     px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height);
  953.  
  954.     return !px;
  955. };
  956.  
  957. static int hw_resize_client(int x, int y, uint32_t width, uint32_t height)
  958. {
  959.     if( x != px->dx ||
  960.         y != px->dy ||
  961.         width != px->width ||
  962.         height != px->height )
  963.     {
  964.         struct drm_i915_mask_update update;
  965.  
  966.         px->dx     = x;
  967.         px->dy     = y;
  968.         px->width  = width;
  969.         px->height = height;
  970.         update_mask(px);
  971.  
  972.         update.handle = px->mask.handle;
  973.         update.dx     = px->dx;
  974.         update.dy     = px->dy;
  975.         update.width  = px->width;
  976.         update.height = px->height;
  977.         update.bo_pitch = (px->width+15) & ~15;
  978.         update.bo_map = (int)px->mask.buffer;
  979.         update.forced = 1;
  980.  
  981.         drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update);
  982.     };
  983.  
  984.     return 0;
  985. };
  986.  
  987. static void hw_fini(void)
  988. {
  989.     struct drm_gem_close close;
  990.  
  991.     DBG("%s\n", __FUNCTION__);
  992.  
  993.     eglDestroyImageKHR(px->dpy, px->mask.image);
  994.     user_free(px->mask.buffer);
  995.     close.handle = px->mask.handle;
  996.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  997.  
  998.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  999.     glDeleteFramebuffers(1, &px->framebuffer);
  1000.     eglDestroyImageKHR(px->dpy, px->screen);
  1001.     glDeleteTextures(2, px->texture);
  1002.     egl_destroy(px->dpy, px->context);
  1003.     free(px);
  1004. };
  1005.  
  1006. static struct pix_driver gl_driver =
  1007. {
  1008.     HW_TEX_BLIT,
  1009.     hw_create_bitmap,
  1010.     hw_destroy_bitmap,
  1011.     hw_lock_bitmap,
  1012.     hw_resize_bitmap,
  1013.     hw_blit,
  1014.     hw_create_client,
  1015.     hw_resize_client,
  1016.     hw_fini,
  1017.     hw_create_planar,
  1018.     hw_blit_planar
  1019. };
  1020.  
  1021. struct pix_driver *DrvInit(uint32_t service)
  1022. {
  1023.     EGLDisplay     dpy;
  1024.     EGLConfig      config;
  1025.     EGLContext     context;
  1026.     int            ret;
  1027.  
  1028.     ret = egl_initialize(&dpy, &config, &context);
  1029.     if( ret )
  1030.         return NULL;
  1031.  
  1032.     return &gl_driver;
  1033.  
  1034. err_0:
  1035.     egl_destroy(dpy, context);
  1036.     return NULL;
  1037. }
  1038.  
  1039.  
  1040.