Subversion Repositories Kolibri OS

Rev

Rev 4517 | Rev 4525 | 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 <sys/time.h>
  5.  
  6. #include "render.h"
  7. #include <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.         glDeleteProgram(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.         "attribute vec4 v_texcoord1;\n"
  93.             "varying vec2 source_texture;\n"
  94.         "varying vec2 mask_texture;\n"
  95.         "void main()\n"
  96.             "{\n"
  97.             "   gl_Position = v_position;\n"
  98.             "   source_texture = v_texcoord0.xy;\n"
  99.         "   mask_texture   = v_texcoord1.xy;\n"
  100.             "}\n";
  101.  
  102.         const char *fs_src =
  103.             "varying vec2 source_texture;\n"
  104.         "varying vec2 mask_texture;\n"
  105.         "uniform sampler2D sampler_src;\n"
  106.         "uniform sampler2D sampler_mask;\n"
  107.             "void main()\n"
  108.             "{\n"
  109.         "   float ca = texture2D(sampler_mask, mask_texture).r;\n"
  110.         "   gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n"
  111.             "}\n";
  112.  
  113.     EGLint config_attribs[14];
  114.     EGLConfig config;
  115.     EGLint num_configs;
  116.  
  117.     EGLContext context;
  118.  
  119.     struct drm_i915_fb_info fb;
  120.     GLint  vs_shader, fs_shader;
  121.     GLenum status;
  122.     GLint ret;
  123.     int fd;
  124.     struct render *render;
  125.  
  126.  
  127.     fd = get_service("DISPLAY");
  128.  
  129.     memset(&fb, 0, sizeof(fb));
  130.     ret = drm_ioctl(fd, SRV_FBINFO, &fb);
  131.     if( ret != 0 )
  132.     {   printf("failed to get framebuffer info\n");
  133.         goto err;
  134.     };
  135.  
  136.     render = (struct render*)malloc(sizeof(struct render));
  137.     if(render == NULL)
  138.         goto err;
  139.  
  140.     render->fd  = fd;
  141.     render->dpy = dpy;
  142.     render->dx  = dx;
  143.     render->dy  = dy;
  144.  
  145.     if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width))
  146.         goto err1;
  147.  
  148.     if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height))
  149.         goto err1;
  150.  
  151.     render->scr_width  = fb.width;
  152.     render->scr_height = fb.height;
  153.  
  154.     render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT);
  155.     if(render->front == EGL_NO_IMAGE_KHR)
  156.         goto err1;
  157.  
  158.     render->back  = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK);
  159.     if( render->back == EGL_NO_IMAGE_KHR)
  160.         goto err2;
  161.  
  162.  
  163.     context = eglGetCurrentContext();
  164.  
  165.     config_attribs[0] = EGL_RED_SIZE;
  166.     config_attribs[1] = 1;
  167.     config_attribs[2] = EGL_GREEN_SIZE;
  168.     config_attribs[3] = 1;
  169.     config_attribs[4] = EGL_BLUE_SIZE;
  170.     config_attribs[5] = 1;
  171.     config_attribs[6] = EGL_DEPTH_SIZE;
  172.     config_attribs[7] = 1;
  173.  
  174.     config_attribs[8] = EGL_SURFACE_TYPE;
  175.     config_attribs[9] = EGL_WINDOW_BIT;
  176.  
  177.     config_attribs[10] = EGL_RENDERABLE_TYPE;
  178.     config_attribs[11] = EGL_OPENGL_BIT;
  179.     config_attribs[12] = EGL_NONE;
  180.  
  181.     if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs)
  182.     {
  183.         printf("failed to choose a config");
  184.         goto err3;
  185.     }
  186.  
  187.     render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
  188.     if (!context)
  189.     {
  190.         printf("failed to create context");
  191.         goto err3;
  192.     };
  193.  
  194.     if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context))
  195.     {
  196.         printf("failed to make window current");
  197.         goto err4;
  198.     };
  199.  
  200.  
  201.     glGenTextures(2, render->tx_buffers);
  202.     if(glGetError() != GL_NO_ERROR)
  203.        goto err5;
  204.  
  205.     glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]);
  206.     if(glGetError() != GL_NO_ERROR)
  207.        goto err6;
  208.  
  209.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  210.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  211.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front);
  212.     if(glGetError() != GL_NO_ERROR)
  213.        goto err6;
  214.  
  215.     glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]);
  216.     if(glGetError() != GL_NO_ERROR)
  217.        goto err6;
  218.  
  219.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  220.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  221.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back);
  222.     if(glGetError() != GL_NO_ERROR)
  223.        goto err6;
  224.  
  225.     glBindTexture(GL_TEXTURE_2D, 0);
  226.  
  227.     render->back_buffer = EGL_DRM_BUFFER_BACK;
  228.  
  229.  
  230.     render->screen = px_create_image(dpy,context,fb.width,fb.height,
  231.                                      fb.pitch,fb.name);
  232.     if(render->screen == EGL_NO_IMAGE_KHR)
  233.         goto err6;
  234.  
  235.     glGenTextures(1, &render->tx_screen);
  236.     if(glGetError() != GL_NO_ERROR)
  237.        goto err6;
  238.  
  239.     glBindTexture(GL_TEXTURE_2D, render->tx_screen);
  240.     if(glGetError() != GL_NO_ERROR)
  241.        goto err7;
  242.  
  243.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  244.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  245.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen);
  246.     if(glGetError() != GL_NO_ERROR)
  247.        goto err7;
  248.  
  249.     glBindTexture(GL_TEXTURE_2D, 0);
  250.  
  251.     create_mask(render);
  252.  
  253.     glGenFramebuffers(1, &render->framebuffer);
  254.     if(glGetError() != GL_NO_ERROR)
  255.        goto err8;
  256.  
  257.     glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer);
  258.     if(glGetError() != GL_NO_ERROR)
  259.        goto err9;
  260.  
  261.     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
  262.                            GL_TEXTURE_2D, render->tx_screen,0);
  263.  
  264.     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
  265.     if (status != GL_FRAMEBUFFER_COMPLETE)
  266.     {
  267.         const char *str;
  268.         switch (status)
  269.         {
  270.             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  271.                  str = "incomplete attachment";
  272.                  break;
  273.             case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  274.                 str = "incomplete/missing attachment";
  275.                 break;
  276.             case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
  277.                 str = "incomplete draw buffer";
  278.                 break;
  279.             case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
  280.                 str = "incomplete read buffer";
  281.                 break;
  282.             case GL_FRAMEBUFFER_UNSUPPORTED:
  283.                 str = "unsupported";
  284.                 break;
  285.             case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
  286.                 str = "incomplete multiple";
  287.                 break;
  288.             default:
  289.                 str = "unknown error";
  290.                 break;
  291.         }
  292.         printf("destination is framebuffer incomplete: %s [%#x]\n", str, status);
  293.         goto err9;
  294.     }
  295.  
  296.     glViewport(0, 0, render->scr_width, render->scr_height);
  297.     glMatrixMode(GL_PROJECTION);
  298.         glLoadIdentity();
  299.         glMatrixMode(GL_MODELVIEW);
  300.         glLoadIdentity();
  301.  
  302.     render->blit_prog = glCreateProgram();
  303.     if(render->blit_prog == 0)
  304.         goto err9;
  305.  
  306.     vs_shader = create_shader(GL_VERTEX_SHADER,vs_src);
  307.     if(vs_shader == 0)
  308.         goto err10;
  309.  
  310.     fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src);
  311.     if(fs_shader == 0)
  312.         goto err11;
  313.  
  314.     glAttachShader(render->blit_prog, vs_shader);
  315.     glAttachShader(render->blit_prog, fs_shader);
  316.     glBindAttribLocation(render->blit_prog, 0, "v_position");
  317.     glBindAttribLocation(render->blit_prog, 1, "v_texcoord0");
  318.     glBindAttribLocation(render->blit_prog, 2, "v_texcoord1");
  319.  
  320.     glLinkProgram(render->blit_prog);
  321.     glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret);
  322.     if (!ret)
  323.     {
  324.         GLchar *info;
  325.         GLint size;
  326.  
  327.         glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size);
  328.         info = malloc(size);
  329.  
  330.         glGetProgramInfoLog(render->blit_prog, size, NULL, info);
  331.         printf("Failed to link: %s\n", info);
  332.         printf("GLSL link failure\n");
  333.         free(info);
  334.     }
  335.  
  336.     render->sampler = glGetUniformLocation(render->blit_prog,"sampler_src");
  337.     render->sm_mask = glGetUniformLocation(render->blit_prog,"sampler_mask");
  338.  
  339.     glUseProgram(render->blit_prog);
  340.     glUniform1i(render->sampler, 0);
  341.     glUniform1i(render->sm_mask, 1);
  342.  
  343.     glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices);
  344.     glEnableVertexAttribArray(0);
  345.  
  346.     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->tc_src);
  347.     glEnableVertexAttribArray(1);
  348.  
  349.     glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->tc_mask);
  350.     glEnableVertexAttribArray(2);
  351.  
  352.     glEnable(GL_BLEND);
  353.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  354.  
  355.     glActiveTexture(GL_TEXTURE1);
  356.     glBindTexture(GL_TEXTURE_2D, render->tx_mask);
  357.     glTexParameteri(GL_TEXTURE_2D,
  358.                   GL_TEXTURE_MIN_FILTER,
  359.                   GL_NEAREST);
  360.     glTexParameteri(GL_TEXTURE_2D,
  361.                   GL_TEXTURE_MAG_FILTER,
  362.                   GL_NEAREST);
  363.  
  364.     eglMakeCurrent(dpy, surface, surface, context);
  365.  
  366.     return render;
  367.  
  368. err11:
  369.     glDeleteShader(vs_shader);
  370. err10:
  371.     glDeleteProgram(render->blit_prog);
  372. err9:
  373.     glDeleteFramebuffers(1, &render->framebuffer);
  374. err8:
  375.     eglDestroyImageKHR(dpy, render->screen);
  376. err7:
  377.     glDeleteTextures(1, &render->tx_screen);
  378. err6:
  379.     glDeleteTextures(2, render->tx_buffers);
  380. err5:
  381.     eglMakeCurrent(dpy, surface, surface, context);
  382. err4:
  383.     eglDestroyContext(dpy, render->context);
  384. err3:
  385.     eglDestroyImageKHR(dpy, render->back);
  386. err2:
  387.     eglDestroyImageKHR(dpy, render->front);
  388. err1:
  389.     free(render);
  390. err:
  391.     return NULL;
  392. };
  393.  
  394.  
  395.  
  396.  
  397. void create_mask(struct render *render)
  398. {
  399.     static EGLint attrib[] =
  400.     {
  401.         EGL_GL_TEXTURE_LEVEL_KHR, 0,
  402.         EGL_NONE
  403.     };
  404.     struct drm_i915_gem_mmap_gtt mmap_arg;
  405.     EGLint handle, stride;
  406.     int winw, winh, pitch;
  407.     void *data;
  408.  
  409.     glGenTextures(1, &render->tx_mask);
  410.     if(glGetError() != GL_NO_ERROR)
  411.        goto err1;
  412.  
  413.     glBindTexture(GL_TEXTURE_2D, render->tx_mask);
  414.     if(glGetError() != GL_NO_ERROR)
  415.        goto err2;
  416.  
  417.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  418.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  419.  
  420.     winw = render->width+10;
  421.     winh = render->height+20+5;
  422.  
  423.     pitch = (winw+3) & -4;
  424.  
  425.     data = user_alloc(pitch * winh);
  426.  
  427.     memset(data, 0x20, pitch * winh);
  428.  
  429.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, winw, winh, 0,
  430.                  GL_RED,GL_UNSIGNED_BYTE, data);
  431.  
  432.     user_free(data);
  433.  
  434.     if(glGetError() != GL_NO_ERROR)
  435.        goto err2;
  436.  
  437.     render->mask = eglCreateImageKHR(render->dpy, render->context,
  438.                                      EGL_GL_TEXTURE_2D_KHR,(EGLClientBuffer)render->tx_mask,attrib);
  439.  
  440.     if(render->mask == EGL_NO_IMAGE_KHR)
  441.         goto err2;
  442.  
  443.     if(!eglExportDRMImageMESA(render->dpy, render->mask, NULL, &handle, &stride))
  444.         goto err3;
  445.  
  446.     glBindTexture(GL_TEXTURE_2D, 0);
  447.  
  448.     mmap_arg.handle = handle;
  449.     mmap_arg.offset = 0;
  450. //    mmap_arg.size = stride * winh;
  451.     if (drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg))
  452.     {
  453.         printf("%s: failed to mmap image %p handle=%d, %d bytes, into CPU domain\n",
  454.                __FUNCTION__, render->mask, handle, stride*winh);
  455.         goto err3;
  456.     }
  457.  
  458.     render->mask_buffer = (void *)(uintptr_t)mmap_arg.offset;
  459.     render->mask_handle = handle;
  460.  
  461.     printf("%s: mmap image %p handle=%d, stride %d %d bytes to %p\n",
  462.            __FUNCTION__, render->mask, handle, stride, stride*winh, render->mask_buffer);
  463.  
  464.     return;
  465.  
  466. err3:
  467.     eglDestroyImageKHR(render->dpy, render->mask);
  468. err2:
  469.     glBindTexture(GL_TEXTURE_2D, 0);
  470. err1:
  471.     glDeleteTextures(1, &render->tx_mask);
  472. };
  473.