Subversion Repositories Kolibri OS

Rev

Rev 6334 | 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_i965 =
  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.     const char *fs_i915 =
  376.         "uniform sampler2D tex_rgba;\n"
  377.         "uniform sampler2D tex_mask;\n"
  378.         "varying vec2 tex_coord;\n"
  379.         "void main()\n"
  380.         "{\n"
  381.         "   float ca = texture2D(tex_mask, tex_coord).a;\n"
  382.         "   gl_FragColor = vec4(texture2D(tex_rgba, tex_coord).rgb, ca);\n"
  383.         "}\n";
  384.  
  385.     GLuint prog;
  386.     GLint  vs_shader, fs_shader;
  387.     const char *fs_src;
  388.     char *drv_name;
  389.     int ret;
  390.  
  391.     prog = glCreateProgram();
  392.     if(prog == 0)
  393.         goto err;
  394.  
  395.     vs_shader = create_shader(GL_VERTEX_SHADER, vs_src);
  396.     if(vs_shader == 0)
  397.         goto err;
  398.  
  399.     drv_name = (char*)glGetString(0x1F04);
  400.     printf("Render: %s\n", drv_name);
  401.  
  402.     if(strstr(drv_name, "i965"))
  403.         fs_src = fs_i965;
  404.     else if(strstr(drv_name, "i915"))
  405.         fs_src = fs_i915;
  406.     else fs_src = NULL;
  407.  
  408.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src);
  409.     if(fs_shader == 0)
  410.         goto err;
  411.  
  412.     glAttachShader(prog, vs_shader);
  413.     glAttachShader(prog, fs_shader);
  414.     glBindAttribLocation(prog, 0, "v_position");
  415.     glBindAttribLocation(prog, 1, "v_texcoord0");
  416.  
  417.     glLinkProgram(prog);
  418.     glGetProgramiv(prog, GL_LINK_STATUS, &ret);
  419.     if (!ret)
  420.     {
  421.         GLchar *info;
  422.         GLint size;
  423.  
  424.         glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
  425.         info = malloc(size);
  426.  
  427.         glGetProgramInfoLog(prog, size, NULL, info);
  428.         DBG("Failed to link: %s\n", info);
  429.         DBG("GLSL link failure\n");
  430.         free(info);
  431.         goto err;
  432.     }
  433.  
  434.     shader->sampler0  = glGetUniformLocation(prog,"tex_rgba");
  435.     shader->sm_mask   = glGetUniformLocation(prog,"tex_mask");
  436.     shader->blit_prog = prog;
  437.     return prog;
  438. err:
  439.     return 0;
  440. }
  441.  
  442. static GLuint create_y_uv_shader(struct shader *shader)
  443. {
  444.     const char *vs_src =
  445.         "attribute vec4 v_position;\n"
  446.         "attribute vec4 v_texcoord0;\n"
  447.         "varying vec2 tex_coord;\n"
  448.         "void main()\n"
  449.         "{\n"
  450.         "   gl_Position = v_position;\n"
  451.         "   tex_coord   = v_texcoord0.xy;\n"
  452.         "}\n";
  453.  
  454.     const char *fs_y_uv =
  455.         "uniform sampler2D tex_src_y;\n"
  456.         "uniform sampler2D tex_src_uv;\n"
  457.         "uniform sampler2D tex_mask;\n"
  458.         "varying vec2 tex_coord;\n"
  459.         "void main()\n"
  460.         "{\n"
  461.         "   float y = 1.16438356 * (texture2D(tex_src_y, tex_coord).x - 0.0625);\n"
  462.         "   float u = texture2D(tex_src_uv, tex_coord).r - 0.5;\n"
  463.         "   float v = texture2D(tex_src_uv, tex_coord).g - 0.5;\n"
  464.         "   gl_FragColor.r = y + 1.59602678 * v;\n"          \
  465.         "   gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
  466.         "   gl_FragColor.b = y + 2.01723214 * u;\n"          \
  467.         "   gl_FragColor.a = texture2D(tex_mask, tex_coord).r;\n"
  468.         "}\n";
  469.  
  470.     GLuint prog;
  471.     GLint  vs_shader, fs_shader;
  472.     int ret;
  473.  
  474.     prog = glCreateProgram();
  475.     if(prog == 0)
  476.         goto err;
  477.  
  478.     vs_shader = create_shader(GL_VERTEX_SHADER, vs_src);
  479.     if(vs_shader == 0)
  480.         goto err;
  481.  
  482.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_y_uv);
  483.     if(fs_shader == 0)
  484.         goto err;
  485.  
  486.     glAttachShader(prog, vs_shader);
  487.     glAttachShader(prog, fs_shader);
  488.     glBindAttribLocation(prog, 0, "v_position");
  489.     glBindAttribLocation(prog, 1, "v_texcoord0");
  490.  
  491.     glLinkProgram(prog);
  492.     glGetProgramiv(prog, GL_LINK_STATUS, &ret);
  493.     if (!ret)
  494.     {
  495.         GLchar *info;
  496.         GLint size;
  497.  
  498.         glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
  499.         info = malloc(size);
  500.  
  501.         glGetProgramInfoLog(prog, size, NULL, info);
  502.         DBG("Failed to link: %s\n", info);
  503.         DBG("GLSL link failure\n");
  504.         free(info);
  505.         goto err;
  506.     }
  507.  
  508.     shader->sampler0  = glGetUniformLocation(prog,"tex_src_y");
  509.     shader->sampler1  = glGetUniformLocation(prog,"tex_src_uv");
  510.     shader->sm_mask   = glGetUniformLocation(prog,"tex_mask");
  511.     shader->blit_prog = prog;
  512.     return prog;
  513. err:
  514.     return 0;
  515. }
  516.  
  517. static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h)
  518. {
  519.  
  520.     struct drm_i915_fb_info fb;
  521.     struct render *px;
  522.  
  523.     int    ret;
  524.  
  525.     px = (struct render*)malloc(sizeof(struct render));
  526.     if(px == NULL)
  527.         goto err_0;
  528.  
  529.     px->fd  = get_service("DISPLAY");
  530.  
  531.     __builtin_memset(&fb, 0, sizeof(fb));
  532.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  533.     {   DBG("failed to get framebuffer info\n");
  534.         goto err_1;
  535.     };
  536.  
  537.     px->dpy     = dpy;
  538.     px->context = context;
  539.     px->dx      = dx;
  540.     px->dy      = dy;
  541.     px->width   = w;
  542.     px->height  = h;
  543.     px->scr_width  = fb.width;
  544.     px->scr_height = fb.height;
  545.  
  546.     glGenTextures(2, px->texture);
  547.     if(glGetError() != GL_NO_ERROR)
  548.        goto err_1;
  549.  
  550.     glGenFramebuffers(1, &px->framebuffer);
  551.     if(glGetError() != GL_NO_ERROR)
  552.        goto err_2;
  553.  
  554.     glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer);
  555.     if(glGetError() != GL_NO_ERROR)
  556.        goto err_3;
  557.  
  558.     if(update_fb(px, fb.name, fb.pitch))
  559.        goto err_4;
  560.  
  561.     glMatrixMode(GL_PROJECTION);
  562.     glLoadIdentity();
  563.     glMatrixMode(GL_MODELVIEW);
  564.     glLoadIdentity();
  565.  
  566.     if(create_mask(px))
  567.         goto err_4;
  568.  
  569.     create_y_uv_shader(&px->shader_y_uv);
  570.     create_rgba_shader(&px->shader_rgba);
  571.  
  572.     glEnableClientState(GL_VERTEX_ARRAY);
  573.  
  574.     glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices);
  575.     glEnableVertexAttribArray(0);
  576.  
  577.     glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src);
  578.     glEnableVertexAttribArray(1);
  579.  
  580.     glEnable(GL_BLEND);
  581.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  582.  
  583.     px->tc_src[0]    = 0.0;
  584.     px->tc_src[1]    = 0.0;
  585.     px->tc_src[1*2]  = 1.0;
  586.     px->tc_src[1*2+1]= 0.0;
  587.     px->tc_src[2*2]  = 1.0;
  588.     px->tc_src[2*2+1]= 1.0;
  589.     px->tc_src[3*2]  = 0.0;
  590.     px->tc_src[3*2+1]= 1.0;
  591.  
  592.     DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n",
  593.         px->screen,fb.width, fb.height, fb.pitch, fb.name);
  594.  
  595.     return px;
  596.  
  597. err_4:
  598.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  599. err_3:
  600.     glDeleteFramebuffers(1, &px->framebuffer);
  601. err_2:
  602.     glDeleteTextures(2, px->texture);
  603. err_1:
  604.     free(px);
  605. err_0:
  606.     return NULL;
  607. };
  608.  
  609. static struct render *px;
  610.  
  611. static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height)
  612. {
  613.     struct bitmap *bitmap;
  614.  
  615.     bitmap = malloc(sizeof(struct bitmap));
  616.     if(bitmap == NULL)
  617.         return NULL;
  618.  
  619.     glGenTextures(1, &bitmap->tex);
  620.     if(glGetError() != GL_NO_ERROR)
  621.        goto err_0;
  622.  
  623.     bitmap->width   = width;
  624.     bitmap->height  = height;
  625.     bitmap->pitch   = (width*4 + 15) & ~15;
  626.  
  627.     if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height,
  628.                          EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0)
  629.     {
  630.         return bitmap;
  631.     };
  632.  
  633.     glDeleteTextures(1, &bitmap->tex);
  634. err_0:
  635.     free(bitmap);
  636.     return NULL;
  637. };
  638.  
  639. static int hw_destroy_planar(planar_t *planar)
  640. {
  641.     glDeleteTextures(planar->num_planes, &planar->tex[0]);
  642.  
  643.     if(planar->image[2] != NULL)
  644.         eglDestroyImageKHR(px->dpy, planar->image[2]);
  645.     if(planar->image[1] != NULL)
  646.         eglDestroyImageKHR(px->dpy, planar->image[1]);
  647.     if(planar->image[0] != NULL)
  648.         eglDestroyImageKHR(px->dpy, planar->image[0]);
  649.     if(planar->planar_image != NULL)
  650.         eglDestroyImageKHR(px->dpy, planar->planar_image);
  651.     free(planar);
  652.     return 0;
  653. };
  654.  
  655. static planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height,
  656.                             uint32_t offset0, uint32_t pitch0,
  657.                             uint32_t offset1, uint32_t pitch1,
  658.                             uint32_t offset2, uint32_t pitch2)
  659. {
  660.     struct drm_gem_close close;
  661.     planar_t *planar;
  662.     EGLImageKHR img;
  663.     int num_planes;
  664.     int i;
  665.  
  666.     EGLint attribs[] = {
  667.         EGL_WIDTH, width,
  668.         EGL_HEIGHT,height,
  669.         EGL_DRM_BUFFER_FORMAT_MESA, format,
  670.         EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0,
  671.         EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0,
  672.         EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1,
  673.         EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1,
  674.         EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2,
  675.         EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2,
  676.         EGL_NONE, EGL_NONE
  677.     };
  678.  
  679.     switch (format)
  680.     {
  681.         case WL_DRM_FORMAT_NV12:
  682.             num_planes = 2;
  683.             break;
  684.         case EGL_TEXTURE_Y_U_V_WL:
  685.             num_planes = 3;
  686.             break;
  687.         case EGL_TEXTURE_Y_XUXV_WL:
  688.             num_planes = 2;
  689.             break;
  690.         default:
  691.             num_planes = 0;
  692.     }
  693.  
  694. //    printf("%s num_planes %d\n", __FUNCTION__, num_planes);
  695.  
  696.     if(num_planes == 0)
  697.         goto fail;
  698.  
  699.     planar = calloc(1, sizeof(struct planar));
  700.     if(planar == NULL)
  701.         goto fail;
  702.  
  703.     img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs);
  704.     if(img == NULL)
  705.         goto err_0;
  706.  
  707.     planar->width  = width;
  708.     planar->height = height;
  709.     planar->name   = name;
  710.     planar->num_planes = num_planes;
  711.     planar->planar_image = img;
  712.  
  713.     planar->offset[0] = offset0;
  714.     planar->offset[1] = offset1;
  715.     planar->offset[2] = offset2;
  716.  
  717.     planar->pitch[0] = pitch0;
  718.     planar->pitch[1] = pitch1;
  719.     planar->pitch[2] = pitch2;
  720.  
  721.     glGenTextures(num_planes, &planar->tex[0]);
  722.     if(glGetError() != GL_NO_ERROR)
  723.        goto err_0;
  724.  
  725.     for(i = 0; i < num_planes; i++)
  726.     {
  727.         EGLImageKHR image;
  728.         EGLint attr[3];
  729.         attr[0] = EGL_WAYLAND_PLANE_WL;
  730.         attr[1] = i;
  731.         attr[2] = EGL_NONE;
  732.  
  733.         image = eglCreateImageKHR(px->dpy, px->context,
  734.                                    EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)img, attr);
  735.         if(image == NULL)
  736.             goto err_1;
  737.  
  738.         planar->image[i] = image;
  739.         glBindTexture(GL_TEXTURE_2D, planar->tex[i]);
  740.         if(glGetError() != GL_NO_ERROR)
  741.         {
  742.             goto err_1;
  743.         };
  744.  
  745.         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
  746.         if(glGetError() != GL_NO_ERROR)
  747.         {
  748.             goto err_1;
  749.         }
  750.  
  751.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  752.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  753.     };
  754.  
  755.     return planar;
  756.  
  757. err_1:
  758.     hw_destroy_planar(planar);
  759.     return NULL;
  760.  
  761. err_0:
  762.     free(planar);
  763. fail:
  764.     return NULL;
  765. }
  766.  
  767. static int hw_destroy_bitmap(bitmap_t * bitmap)
  768. {
  769.     struct drm_gem_close close;
  770.  
  771.     glDeleteTextures(1, &bitmap->tex);
  772.     eglDestroyImageKHR(px->dpy, bitmap->image);
  773.     user_free(bitmap->buffer);
  774.     close.handle = bitmap->handle;
  775.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  776.     free(bitmap);
  777.     return 0;
  778. };
  779.  
  780. static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch)
  781. {
  782.     *pitch = bitmap->pitch;
  783.  
  784.     return bitmap->buffer;
  785. };
  786.  
  787. static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height)
  788. {
  789.     return 0;
  790. }
  791.  
  792. char proc_info[1024];
  793.  
  794. static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y,
  795.                    uint32_t w, uint32_t h, int src_x, int src_y)
  796. {
  797.     struct drm_i915_mask_update update;
  798.     struct drm_i915_fb_info fb;
  799.  
  800.     uint32_t winx, winy, winw, winh;
  801.     uint8_t  state;
  802.     float xscale, yscale;
  803.     int r, b;
  804.     float *vertices  = px->vertices;
  805.  
  806.     get_proc_info(proc_info);
  807.  
  808.     state  = *(uint8_t*)(proc_info+70);
  809.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  810.         return 0;
  811.  
  812.     winx = *(uint32_t*)(proc_info+34);
  813.     winy = *(uint32_t*)(proc_info+38);
  814.     winw = *(uint32_t*)(proc_info+42)+1;
  815.     winh = *(uint32_t*)(proc_info+46)+1;
  816.  
  817.     __builtin_memset(&fb, 0, sizeof(fb));
  818.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  819.     {
  820.         DBG("failed to get framebuffer info\n");
  821.         return 0;
  822.     };
  823.  
  824.     if( fb.width  != px->scr_width ||
  825.         fb.height != px->scr_height )
  826.     {
  827.         px->scr_width  = fb.width;
  828.         px->scr_height = fb.height;
  829.  
  830.         eglDestroyImageKHR(px->dpy, px->screen);
  831.  
  832.         if(update_fb(px, fb.name, fb.pitch))
  833.             return 0;
  834.     };
  835.  
  836.     update.handle = px->mask.handle;
  837.     update.dx     = px->dx;
  838.     update.dy     = px->dy;
  839.     update.width  = px->width;
  840.     update.height = px->height;
  841.     update.bo_pitch = (px->width+15) & ~15;
  842.     update.bo_map = (int)px->mask.buffer;
  843.  
  844.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  845.     {
  846.         return 0;
  847.     }
  848.  
  849.     xscale = 1.0/px->scr_width;
  850.     yscale = 1.0/px->scr_height;
  851.  
  852.     r = winx + px->dx + px->width;
  853.     b = winy + px->dy + px->height;
  854.  
  855.     float t0, t1, t2, t5;
  856.  
  857. //    render->tc_src[1*2]  = 1.0;
  858. //    render->tc_src[2*2]  = 1.0;
  859. //    render->tc_src[2*2+1]= 1.0;
  860. //    render->tc_src[3*2+1]= 1.0;
  861.  
  862.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  863.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  864.  
  865.     vertices[2 * 2] = t2;
  866.     vertices[3 * 2] = t0;
  867.  
  868.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  869.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  870.     vertices[1*2+1] = t1;
  871.     vertices[3*2+1] = t5;
  872.  
  873.     struct shader *shader = &px->shader_rgba;
  874.  
  875.     glUseProgram(shader->blit_prog);
  876.     glUniform1i(shader->sampler0, 0);
  877.     glUniform1i(shader->sm_mask, 1);
  878.  
  879.     glActiveTexture(GL_TEXTURE0);
  880.     glBindTexture(GL_TEXTURE_2D, bitmap->tex);
  881.  
  882.     glActiveTexture(GL_TEXTURE1);
  883.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  884.  
  885.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  886.  
  887.     glFlush();
  888.  
  889.     return 0;
  890. };
  891.  
  892. static int hw_blit_planar(planar_t *planar, int dst_x, int dst_y,
  893.                    uint32_t w, uint32_t h, int src_x, int src_y)
  894. {
  895.     struct drm_i915_mask_update update;
  896.     struct drm_i915_fb_info fb;
  897.  
  898.     uint32_t winx, winy, winw, winh;
  899.     uint8_t  state;
  900.     float xscale, yscale;
  901.     int r, b;
  902.     float *vertices  = px->vertices;
  903.  
  904.     get_proc_info(proc_info);
  905.  
  906.     state  = *(uint8_t*)(proc_info+70);
  907.     if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED))
  908.         return 0;
  909.  
  910.     winx = *(uint32_t*)(proc_info+34);
  911.     winy = *(uint32_t*)(proc_info+38);
  912.     winw = *(uint32_t*)(proc_info+42)+1;
  913.     winh = *(uint32_t*)(proc_info+46)+1;
  914.  
  915.     __builtin_memset(&fb, 0, sizeof(fb));
  916.     if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb))
  917.     {
  918.         DBG("failed to get framebuffer info\n");
  919.         return 0;
  920.     };
  921.  
  922.     if( fb.width  != px->scr_width ||
  923.         fb.height != px->scr_height )
  924.     {
  925.         px->scr_width  = fb.width;
  926.         px->scr_height = fb.height;
  927.  
  928.         eglDestroyImageKHR(px->dpy, px->screen);
  929.  
  930.         if(update_fb(px, fb.name, fb.pitch))
  931.             return 0;
  932.     };
  933.  
  934.     update.handle = px->mask.handle;
  935.     update.dx     = px->dx;
  936.     update.dy     = px->dy;
  937.     update.width  = px->width;
  938.     update.height = px->height;
  939.     update.bo_pitch = (px->width+15) & ~15;
  940.     update.bo_map = (int)px->mask.buffer;
  941.  
  942.     if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update))
  943.     {
  944.         return 0;
  945.     }
  946.  
  947.     xscale = 1.0/px->scr_width;
  948.     yscale = 1.0/px->scr_height;
  949.  
  950.     r = winx + px->dx + px->width;
  951.     b = winy + px->dy + px->height;
  952.  
  953.     float t0, t1, t2, t5;
  954.  
  955. //    render->tc_src[1*2]  = 1.0;
  956. //    render->tc_src[2*2]  = 1.0;
  957. //    render->tc_src[2*2+1]= 1.0;
  958. //    render->tc_src[3*2+1]= 1.0;
  959.  
  960.     vertices[0]     = t0 = 2*(winx+px->dx)*xscale - 1.0;
  961.     vertices[1 * 2] = t2 = 2*r*xscale - 1.0;
  962.  
  963.     vertices[2 * 2] = t2;
  964.     vertices[3 * 2] = t0;
  965.  
  966.     vertices[1]     = t1 = 2*(winy+px->dy)*yscale - 1.0;
  967.     vertices[2*2+1] = t5 = 2*b*yscale - 1.0;
  968.     vertices[1*2+1] = t1;
  969.     vertices[3*2+1] = t5;
  970.  
  971.     struct shader *shader = &px->shader_y_uv;
  972.  
  973.     glUseProgram(shader->blit_prog);
  974.     glUniform1i(shader->sampler0, 0);
  975.     glUniform1i(shader->sampler1, 1);
  976.     glUniform1i(shader->sm_mask, 2);
  977.  
  978.     glActiveTexture(GL_TEXTURE0);
  979.     glBindTexture(GL_TEXTURE_2D, planar->tex[0]);
  980.  
  981.     glActiveTexture(GL_TEXTURE1);
  982.     glBindTexture(GL_TEXTURE_2D, planar->tex[1]);
  983.  
  984.     glActiveTexture(GL_TEXTURE2);
  985.     glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]);
  986.  
  987.     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  988.  
  989.     glFlush();
  990.  
  991.     return 0;
  992. };
  993.  
  994. static int hw_create_client(int x, int y, uint32_t width, uint32_t height)
  995. {
  996.     px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height);
  997.  
  998.     return !px;
  999. };
  1000.  
  1001. static int hw_resize_client(int x, int y, uint32_t width, uint32_t height)
  1002. {
  1003.     if( x != px->dx ||
  1004.         y != px->dy ||
  1005.         width != px->width ||
  1006.         height != px->height )
  1007.     {
  1008.         struct drm_i915_mask_update update;
  1009.  
  1010.         px->dx     = x;
  1011.         px->dy     = y;
  1012.         px->width  = width;
  1013.         px->height = height;
  1014.         update_mask(px);
  1015.  
  1016.         update.handle = px->mask.handle;
  1017.         update.dx     = px->dx;
  1018.         update.dy     = px->dy;
  1019.         update.width  = px->width;
  1020.         update.height = px->height;
  1021.         update.bo_pitch = (px->width+15) & ~15;
  1022.         update.bo_map = (int)px->mask.buffer;
  1023.         update.forced = 1;
  1024.  
  1025.         drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update);
  1026.     };
  1027.  
  1028.     return 0;
  1029. };
  1030.  
  1031. static void hw_fini(void)
  1032. {
  1033.     struct drm_gem_close close;
  1034.  
  1035.     DBG("%s\n", __FUNCTION__);
  1036.  
  1037.     eglDestroyImageKHR(px->dpy, px->mask.image);
  1038.     user_free(px->mask.buffer);
  1039.     close.handle = px->mask.handle;
  1040.     drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close);
  1041.  
  1042.     glBindFramebuffer(GL_FRAMEBUFFER, 0);
  1043.     glDeleteFramebuffers(1, &px->framebuffer);
  1044.     eglDestroyImageKHR(px->dpy, px->screen);
  1045.     glDeleteTextures(2, px->texture);
  1046.     egl_destroy(px->dpy, px->context);
  1047.     free(px);
  1048. };
  1049.  
  1050. static struct pix_driver gl_driver =
  1051. {
  1052.     HW_TEX_BLIT,
  1053.     hw_create_bitmap,
  1054.     hw_destroy_bitmap,
  1055.     hw_lock_bitmap,
  1056.     hw_resize_bitmap,
  1057.     hw_blit,
  1058.     hw_create_client,
  1059.     hw_resize_client,
  1060.     hw_fini,
  1061.     hw_create_planar,
  1062.     hw_destroy_planar,
  1063.     hw_blit_planar
  1064. };
  1065.  
  1066. struct pix_driver *DrvInit(uint32_t service)
  1067. {
  1068.     EGLDisplay     dpy;
  1069.     EGLConfig      config;
  1070.     EGLContext     context;
  1071.     int            ret;
  1072.  
  1073.     ret = egl_initialize(&dpy, &config, &context);
  1074.     if( ret )
  1075.         return NULL;
  1076.  
  1077.     return &gl_driver;
  1078.  
  1079. err_0:
  1080.     egl_destroy(dpy, context);
  1081.     return NULL;
  1082. }
  1083.  
  1084.  
  1085.