Subversion Repositories Kolibri OS

Rev

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