Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/time.h>
  5.  
  6. #include "render.h"
  7. #include <drm/i915_drm.h>
  8. #include <kos32sys.h>
  9.  
  10. void create_mask(struct render *render);
  11.  
  12. static int drm_ioctl(int fd, unsigned long request, void *arg)
  13. {
  14.     ioctl_t  io;
  15.  
  16.     io.handle   = fd;
  17.     io.io_code  = request;
  18.     io.input    = arg;
  19.     io.inp_size = 64;
  20.     io.output   = NULL;
  21.     io.out_size = 0;
  22.  
  23.     return call_service(&io);
  24. }
  25.  
  26. static EGLImageKHR px_create_image(EGLDisplay display, EGLContext context,
  27.                          int width, int height, int stride, int name)
  28. {
  29.         EGLImageKHR image;
  30.         EGLint attribs[] = {
  31.                 EGL_WIDTH, 0,
  32.                 EGL_HEIGHT, 0,
  33.                 EGL_DRM_BUFFER_STRIDE_MESA, 0,
  34.                 EGL_DRM_BUFFER_FORMAT_MESA,
  35.                 EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
  36.                 EGL_DRM_BUFFER_USE_MESA,
  37.                 EGL_DRM_BUFFER_USE_SHARE_MESA |
  38.                     EGL_DRM_BUFFER_USE_SCANOUT_MESA,
  39.                 EGL_NONE
  40.         };
  41.         attribs[1] = width;
  42.         attribs[3] = height;
  43.         attribs[5] = stride/4;
  44.  
  45.     printf("%s w:%d :%d pitch:%d handle %d\n", __FUNCTION__,
  46.            width, height, stride, name);
  47.  
  48.         image = eglCreateImageKHR(display, context, EGL_DRM_BUFFER_MESA,
  49.                                                  (void *) (uintptr_t)name, attribs);
  50.  
  51.         return image;
  52. }
  53.  
  54. static GLint create_shader(GLenum type, const char *source)
  55. {
  56.         GLint ok;
  57.     GLint shader;
  58.  
  59.     shader = glCreateShader(type);
  60.     if(shader == 0)
  61.         goto err;
  62.  
  63.     glShaderSource(shader, 1, (const GLchar **) &source, NULL);
  64.     glCompileShader(shader);
  65.     glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
  66.         if (!ok) {
  67.                 GLchar *info;
  68.                 GLint size;
  69.  
  70.         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
  71.                 info = malloc(size);
  72.  
  73.         glGetShaderInfoLog(shader, size, NULL, info);
  74.                 printf("Failed to compile %s: %s\n",
  75.                 type == GL_FRAGMENT_SHADER ? "FS" : "VS",info);
  76.                 printf("Program source:\n%s", source);
  77.                 printf("GLSL compile failure\n");
  78.         free(info);
  79.         glDeleteShader(shader);
  80.         shader = 0;
  81.         }
  82. err:
  83.     return shader;
  84. }
  85.  
  86.  
  87. struct render* create_render(EGLDisplay dpy, EGLSurface surface, int dx, int dy)
  88. {
  89.     const char *vs_src =
  90.             "attribute vec4 v_position;\n"
  91.             "attribute vec4 v_texcoord0;\n"
  92.             "varying vec2 source_texture;\n"
  93.         "void main()\n"
  94.             "{\n"
  95.             "   gl_Position = v_position;\n"
  96.             "   source_texture = v_texcoord0.xy;\n"
  97.             "}\n";
  98.  
  99.     const char *fs_i965 =
  100.             "varying vec2 source_texture;\n"
  101.         "uniform sampler2D sampler_src;\n"
  102.         "uniform sampler2D sampler_mask;\n"
  103.             "void main()\n"
  104.             "{\n"
  105.         "   float ca = texture2D(sampler_mask, source_texture).r;\n"
  106.         "   gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n"
  107.             "}\n";
  108.  
  109.     const char *fs_i915 =
  110.         "varying vec2 source_texture;\n"
  111.         "uniform sampler2D sampler_src;\n"
  112.         "uniform sampler2D sampler_mask;\n"
  113.         "void main()\n"
  114.         "{\n"
  115.         "   float ca = texture2D(sampler_mask, source_texture).a;\n"
  116.         "   gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n"
  117.         "}\n";
  118.  
  119.     EGLint config_attribs[14];
  120.     EGLConfig config;
  121.     EGLint num_configs;
  122.  
  123.     EGLContext context;
  124.  
  125.     struct drm_i915_fb_info fb;
  126.     GLint  vs_shader, fs_shader;
  127.     GLenum status;
  128.     GLint ret;
  129.     int fd;
  130.     struct render *render;
  131.     char *drv_name;
  132.     const char *fs_src;
  133.  
  134.  
  135.     fd = get_service("DISPLAY");
  136.  
  137.     memset(&fb, 0, sizeof(fb));
  138.     ret = drm_ioctl(fd, SRV_FBINFO, &fb);
  139.     if( ret != 0 )
  140.     {   printf("failed to get framebuffer info\n");
  141.         goto err;
  142.     };
  143.  
  144.     render = (struct render*)malloc(sizeof(struct render));
  145.     if(render == NULL)
  146.         goto err;
  147.  
  148.     render->fd  = fd;
  149.     render->dpy = dpy;
  150.     render->dx  = dx;
  151.     render->dy  = dy;
  152.  
  153.     if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width))
  154.         goto err1;
  155.  
  156.     if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height))
  157.         goto err1;
  158.  
  159.     render->scr_width  = fb.width;
  160.     render->scr_height = fb.height;
  161.  
  162.     render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT);
  163.     if(render->front == EGL_NO_IMAGE_KHR)
  164.         goto err1;
  165.  
  166.     render->back  = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK);
  167.     if( render->back == EGL_NO_IMAGE_KHR)
  168.         goto err2;
  169.  
  170.  
  171.     context = eglGetCurrentContext();
  172.  
  173.     config_attribs[0] = EGL_RED_SIZE;
  174.     config_attribs[1] = 1;
  175.     config_attribs[2] = EGL_GREEN_SIZE;
  176.     config_attribs[3] = 1;
  177.     config_attribs[4] = EGL_BLUE_SIZE;
  178.     config_attribs[5] = 1;
  179.     config_attribs[6] = EGL_DEPTH_SIZE;
  180.     config_attribs[7] = 1;
  181.  
  182.     config_attribs[8] = EGL_SURFACE_TYPE;
  183.     config_attribs[9] = EGL_WINDOW_BIT;
  184.  
  185.     config_attribs[10] = EGL_RENDERABLE_TYPE;
  186.     config_attribs[11] = EGL_OPENGL_BIT;
  187.     config_attribs[12] = EGL_NONE;
  188.  
  189.     if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs)
  190.     {
  191.         printf("failed to choose a config");
  192.         goto err3;
  193.     }
  194.  
  195.     render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
  196.     if (!context)
  197.     {
  198.         printf("failed to create context");
  199.         goto err3;
  200.     };
  201.  
  202.     if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context))
  203.     {
  204.         printf("failed to make window current");
  205.         goto err4;
  206.     };
  207.  
  208.  
  209.     glGenTextures(2, render->tx_buffers);
  210.     if(glGetError() != GL_NO_ERROR)
  211.        goto err5;
  212.  
  213.     glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]);
  214.     if(glGetError() != GL_NO_ERROR)
  215.        goto err6;
  216.  
  217.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  218.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  219.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front);
  220.     if(glGetError() != GL_NO_ERROR)
  221.        goto err6;
  222.  
  223.     glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]);
  224.     if(glGetError() != GL_NO_ERROR)
  225.        goto err6;
  226.  
  227.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  228.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  229.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back);
  230.     if(glGetError() != GL_NO_ERROR)
  231.        goto err6;
  232.  
  233.     glBindTexture(GL_TEXTURE_2D, 0);
  234.  
  235.     render->back_buffer = EGL_DRM_BUFFER_FRONT;
  236.  
  237.     render->screen = px_create_image(dpy,context,fb.width,fb.height,
  238.                                      fb.pitch,fb.name);
  239.     if(render->screen == EGL_NO_IMAGE_KHR)
  240.         goto err6;
  241.  
  242.     glGenTextures(1, &render->tx_screen);
  243.     if(glGetError() != GL_NO_ERROR)
  244.        goto err6;
  245.  
  246.     glBindTexture(GL_TEXTURE_2D, render->tx_screen);
  247.     if(glGetError() != GL_NO_ERROR)
  248.        goto err7;
  249.  
  250.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  251.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  252.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen);
  253.     if(glGetError() != GL_NO_ERROR)
  254.        goto err7;
  255.  
  256.     glBindTexture(GL_TEXTURE_2D, 0);
  257.  
  258.     create_mask(render);
  259.  
  260.     glGenFramebuffers(1, &render->framebuffer);
  261.     if(glGetError() != GL_NO_ERROR)
  262.        goto err8;
  263.  
  264.     glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer);
  265.     if(glGetError() != GL_NO_ERROR)
  266.        goto err9;
  267.  
  268.     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
  269.                            GL_TEXTURE_2D, render->tx_screen,0);
  270.  
  271.     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  272.     if (status != GL_FRAMEBUFFER_COMPLETE)
  273.     {
  274.         const char *str;
  275.         switch (status)
  276.         {
  277.             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  278.                  str = "incomplete attachment";
  279.                  break;
  280.             case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  281.                 str = "incomplete/missing attachment";
  282.                 break;
  283.             case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
  284.                 str = "incomplete draw buffer";
  285.                 break;
  286.             case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
  287.                 str = "incomplete read buffer";
  288.                 break;
  289.             case GL_FRAMEBUFFER_UNSUPPORTED:
  290.                 str = "unsupported";
  291.                 break;
  292.             case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
  293.                 str = "incomplete multiple";
  294.                 break;
  295.             default:
  296.                 str = "unknown error";
  297.                 break;
  298.         }
  299.         printf("destination is framebuffer incomplete: %s [%#x]\n", str, status);
  300.         goto err9;
  301.     }
  302.  
  303.     glViewport(0, 0, render->scr_width, render->scr_height);
  304.     glMatrixMode(GL_PROJECTION);
  305.         glLoadIdentity();
  306.         glMatrixMode(GL_MODELVIEW);
  307.         glLoadIdentity();
  308.  
  309.     drv_name = (char*)glGetString(0x1F04);
  310.     printf("Render: %s\n", drv_name);
  311.  
  312.     if(strstr(drv_name, "i965"))
  313.         fs_src = fs_i965;
  314.     else if(strstr(drv_name, "i915"))
  315.         fs_src = fs_i915;
  316.     else fs_src = NULL;
  317.  
  318.     render->blit_prog = glCreateProgram();
  319.     if(render->blit_prog == 0)
  320.         goto err9;
  321.  
  322.     vs_shader = create_shader(GL_VERTEX_SHADER,vs_src);
  323.     if(vs_shader == 0)
  324.         goto err10;
  325.  
  326.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src);
  327.     if(fs_shader == 0)
  328.         goto err11;
  329.  
  330.     glAttachShader(render->blit_prog, vs_shader);
  331.     glAttachShader(render->blit_prog, fs_shader);
  332.     glBindAttribLocation(render->blit_prog, 0, "v_position");
  333.     glBindAttribLocation(render->blit_prog, 1, "v_texcoord0");
  334.  
  335.     glLinkProgram(render->blit_prog);
  336.     glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret);
  337.     if (!ret)
  338.     {
  339.         GLchar *info;
  340.         GLint size;
  341.  
  342.         glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size);
  343.         info = malloc(size);
  344.  
  345.         glGetProgramInfoLog(render->blit_prog, size, NULL, info);
  346.         printf("Failed to link: %s\n", info);
  347.         printf("GLSL link failure\n");
  348.         free(info);
  349.         goto err12;
  350.     }
  351.  
  352.     render->sampler = glGetUniformLocation(render->blit_prog,"sampler_src");
  353.     render->sm_mask = glGetUniformLocation(render->blit_prog,"sampler_mask");
  354.  
  355.     glUseProgram(render->blit_prog);
  356.     glUniform1i(render->sampler, 0);
  357.     glUniform1i(render->sm_mask, 1);
  358.  
  359.     glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices);
  360.     glEnableVertexAttribArray(0);
  361.  
  362.     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->tc_src);
  363.     glEnableVertexAttribArray(1);
  364.  
  365.     render->tc_src[0]    = 0.0;
  366.     render->tc_src[1]    = 0.0;
  367.     render->tc_src[1*2]  = 1.0;
  368.     render->tc_src[1*2+1]= 0.0;
  369.     render->tc_src[2*2]  = 1.0;
  370.     render->tc_src[2*2+1]= 1.0;
  371.     render->tc_src[3*2]  = 0.0;
  372.     render->tc_src[3*2+1]= 1.0;
  373.  
  374.     glEnable(GL_BLEND);
  375.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  376.  
  377.     glActiveTexture(GL_TEXTURE1);
  378.     glBindTexture(GL_TEXTURE_2D, render->tx_mask);
  379.     glTexParameteri(GL_TEXTURE_2D,
  380.                   GL_TEXTURE_MIN_FILTER,
  381.                   GL_NEAREST);
  382.     glTexParameteri(GL_TEXTURE_2D,
  383.                   GL_TEXTURE_MAG_FILTER,
  384.                   GL_NEAREST);
  385.  
  386.     eglMakeCurrent(dpy, surface, surface, context);
  387.  
  388.     return render;
  389.  
  390. err12:
  391.     glDeleteShader(fs_shader);
  392. err11:
  393.     glDeleteShader(vs_shader);
  394. err10:
  395.     glDeleteProgram(render->blit_prog);
  396. err9:
  397.     glDeleteFramebuffers(1, &render->framebuffer);
  398. err8:
  399.     eglDestroyImageKHR(dpy, render->screen);
  400. err7:
  401.     glDeleteTextures(1, &render->tx_screen);
  402. err6:
  403.     glDeleteTextures(2, render->tx_buffers);
  404. err5:
  405.     eglMakeCurrent(dpy, surface, surface, context);
  406. err4:
  407.     eglDestroyContext(dpy, render->context);
  408. err3:
  409.     eglDestroyImageKHR(dpy, render->back);
  410. err2:
  411.     eglDestroyImageKHR(dpy, render->front);
  412. err1:
  413.     free(render);
  414. err:
  415.     return NULL;
  416. };
  417.  
  418.  
  419. void create_mask(struct render *render)
  420. {
  421.     struct drm_i915_gem_create create;
  422.     struct drm_gem_close close;
  423.     struct drm_gem_flink flink;
  424.  
  425.     struct drm_i915_gem_mmap mmap_arg;
  426.     EGLint handle, stride;
  427.     int winw, winh, pitch;
  428.     void *data;
  429.     int ret;
  430.     GLuint mask_handle, mask_name;
  431.     EGLImageKHR mask_image;
  432.  
  433.     glGenTextures(1, &render->tx_mask);
  434.     if(glGetError() != GL_NO_ERROR)
  435.        return;
  436.  
  437.     glBindTexture(GL_TEXTURE_2D, render->tx_mask);
  438.     if(glGetError() != GL_NO_ERROR)
  439.        goto err1;
  440.  
  441.     pitch = (render->width+15) & ~15;
  442.  
  443.     create.size = pitch *render->height;
  444.     create.handle = 0;
  445.     ret = drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
  446.     if(ret != 0)
  447.         goto err1;
  448.  
  449.     mask_handle = create.handle;
  450.     flink.handle = create.handle;
  451.     ret = drm_ioctl(render->fd, DRM_IOCTL_GEM_FLINK, &flink);
  452.     if (ret != 0)
  453.         goto err2;
  454.  
  455.     mask_name = flink.name;
  456.  
  457.     printf("create mask bo handle %d name %d\n", create.handle, flink.name);
  458.  
  459.     EGLint attribs[] = {
  460.         EGL_WIDTH, 0,
  461.         EGL_HEIGHT, 0,
  462.         EGL_DRM_BUFFER_STRIDE_MESA, 0,
  463.         EGL_DRM_BUFFER_FORMAT_MESA,
  464.         EGL_DRM_BUFFER_FORMAT_R8_MESA,
  465.         EGL_DRM_BUFFER_USE_MESA,
  466.         EGL_DRM_BUFFER_USE_SHARE_MESA,
  467.         EGL_NONE
  468.     };
  469.     attribs[1] = pitch;
  470.     attribs[3] = render->height;
  471.     attribs[5] = pitch;
  472.  
  473.     mask_image = eglCreateImageKHR(render->dpy, render->context, EGL_DRM_BUFFER_MESA,
  474.                          (void *) (uintptr_t)mask_name, attribs);
  475.     printf("create mask image %p\n", mask_image);
  476.     if(mask_image == NULL)
  477.         goto err2;
  478.  
  479.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  480.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  481.  
  482.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mask_image);
  483.  
  484.     if(glGetError() != GL_NO_ERROR)
  485.        goto err3;
  486.  
  487.     glBindTexture(GL_TEXTURE_2D, 0);
  488.  
  489.     mmap_arg.handle = mask_handle;
  490.     mmap_arg.offset = 0;
  491.     mmap_arg.size = pitch * render->height;
  492.     if (drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))
  493.     {
  494.         printf("%s: failed to mmap image %p handle=%d, %d bytes, into CPU domain\n",
  495.                __FUNCTION__, mask_image, mask_handle, pitch * render->height);
  496.         goto err3;
  497.     }
  498.  
  499.     render->mask_handle = mask_handle;
  500.     render->mask_name   = mask_name;
  501.     render->mask_buffer = (void *)(uintptr_t)mmap_arg.addr_ptr;
  502.     render->mask_image = mask_image;
  503.  
  504.     return;
  505.  
  506. err3:
  507.     eglDestroyImageKHR(render->dpy, mask_image);
  508. err2:
  509.     close.handle = mask_handle;
  510.     (void)drm_ioctl(render->fd, DRM_IOCTL_GEM_CLOSE, &close);
  511.     glBindTexture(GL_TEXTURE_2D, 0);
  512. err1:
  513.     glDeleteTextures(1, &render->tx_mask);
  514. };
  515.