Subversion Repositories Kolibri OS

Rev

Rev 4502 | Rev 4523 | 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. //          "precision mediump float;\n"
  101.             "varying vec2 source_texture;\n"
  102.             "uniform sampler2D sampler;\n"
  103.             "void main()\n"
  104.             "{\n"
  105.             "   vec3 cg = texture2D(sampler, source_texture).rgb;\n"
  106.             "   gl_FragColor = vec4(cg.r,cg.g,cg.b,1.0);\n"
  107.             "}\n";
  108.     EGLint config_attribs[14];
  109.     EGLConfig config;
  110.     EGLint num_configs;
  111.  
  112.     EGLContext context;
  113.  
  114.     struct drm_i915_fb_info fb;
  115.     GLint  vs_shader, fs_shader;
  116.     GLenum status;
  117.     GLint ret;
  118.     int fd;
  119.     struct render *render;
  120.  
  121.  
  122.     fd = get_service("DISPLAY");
  123.  
  124.     memset(&fb, 0, sizeof(fb));
  125.     ret = drm_ioctl(fd, SRV_FBINFO, &fb);
  126.     if( ret != 0 )
  127.     {   printf("failed to get framebuffer info\n");
  128.         goto err;
  129.     };
  130.  
  131.     render = (struct render*)malloc(sizeof(struct render));
  132.     if(render == NULL)
  133.         goto err;
  134.  
  135.     render->fd  = fd;
  136.     render->dpy = dpy;
  137.     render->dx  = dx;
  138.     render->dy  = dy;
  139.  
  140.     if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width))
  141.         goto err1;
  142.  
  143.     if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height))
  144.         goto err1;
  145.  
  146.     render->scr_width  = fb.width;
  147.     render->scr_height = fb.height;
  148.  
  149.     render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT);
  150.     if(render->front == EGL_NO_IMAGE_KHR)
  151.         goto err1;
  152.  
  153.     render->back  = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK);
  154.     if( render->back == EGL_NO_IMAGE_KHR)
  155.         goto err2;
  156.  
  157.  
  158.     context = eglGetCurrentContext();
  159.  
  160.     config_attribs[0] = EGL_RED_SIZE;
  161.     config_attribs[1] = 1;
  162.     config_attribs[2] = EGL_GREEN_SIZE;
  163.     config_attribs[3] = 1;
  164.     config_attribs[4] = EGL_BLUE_SIZE;
  165.     config_attribs[5] = 1;
  166.     config_attribs[6] = EGL_DEPTH_SIZE;
  167.     config_attribs[7] = 1;
  168.  
  169.     config_attribs[8] = EGL_SURFACE_TYPE;
  170.     config_attribs[9] = EGL_WINDOW_BIT;
  171.  
  172.     config_attribs[10] = EGL_RENDERABLE_TYPE;
  173.     config_attribs[11] = EGL_OPENGL_BIT;
  174.     config_attribs[12] = EGL_NONE;
  175.  
  176.     if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs)
  177.     {
  178.         printf("failed to choose a config");
  179.         goto err3;
  180.     }
  181.  
  182.     render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL);
  183.     if (!context)
  184.     {
  185.         printf("failed to create context");
  186.         goto err3;
  187.     };
  188.  
  189.     if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context))
  190.     {
  191.         printf("failed to make window current");
  192.         goto err4;
  193.     };
  194.  
  195.  
  196.     glGenTextures(2, render->tx_buffers);
  197.     if(glGetError() != GL_NO_ERROR)
  198.        goto err5;
  199.  
  200.     glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]);
  201.     if(glGetError() != GL_NO_ERROR)
  202.        goto err6;
  203.  
  204.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  205.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  206.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front);
  207.     if(glGetError() != GL_NO_ERROR)
  208.        goto err6;
  209.  
  210.     glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]);
  211.     if(glGetError() != GL_NO_ERROR)
  212.        goto err6;
  213.  
  214.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  215.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  216.     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back);
  217.     if(glGetError() != GL_NO_ERROR)
  218.        goto err6;
  219.  
  220.     glBindTexture(GL_TEXTURE_2D, 0);
  221.  
  222.     render->back_buffer = EGL_DRM_BUFFER_BACK;
  223.  
  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");
  331.  
  332.     glUseProgram(render->blit_prog);
  333.     glUniform1i(render->sampler, 0);
  334.  
  335.     glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices);
  336.     glEnableVertexAttribArray(0);
  337.  
  338.     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->texcoords);
  339.     glEnableVertexAttribArray(1);
  340.  
  341.     eglMakeCurrent(dpy, surface, surface, context);
  342.  
  343.     return render;
  344.  
  345. err11:
  346.     glDeleteShader(vs_shader);
  347. err10:
  348.     glDeleteProgram(render->blit_prog);
  349. err9:
  350.     glDeleteFramebuffers(1, &render->framebuffer);
  351. err8:
  352.     eglDestroyImageKHR(dpy, render->screen);
  353. err7:
  354.     glDeleteTextures(1, &render->tx_screen);
  355. err6:
  356.     glDeleteTextures(2, render->tx_buffers);
  357. err5:
  358.     eglMakeCurrent(dpy, surface, surface, context);
  359. err4:
  360.     eglDestroyContext(dpy, render->context);
  361. err3:
  362.     eglDestroyImageKHR(dpy, render->back);
  363. err2:
  364.     eglDestroyImageKHR(dpy, render->front);
  365. err1:
  366.     free(render);
  367. err:
  368.     return NULL;
  369. };
  370.  
  371.  
  372.  
  373.  
  374. void create_mask(struct render *render)
  375. {
  376.     static EGLint attrib[] =
  377.     {
  378.         EGL_GL_TEXTURE_LEVEL_KHR, 0,
  379.         EGL_NONE
  380.     };
  381.     struct drm_i915_gem_mmap mmap_arg;
  382.     EGLint handle, stride;
  383.     int pitch;
  384.     void *data;
  385.  
  386.     glGenTextures(1, &render->tx_mask);
  387.     if(glGetError() != GL_NO_ERROR)
  388.        goto err1;
  389.  
  390.     glBindTexture(GL_TEXTURE_2D, render->tx_mask);
  391.     if(glGetError() != GL_NO_ERROR)
  392.        goto err2;
  393.  
  394.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  395.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  396.  
  397.     pitch = (render->width+3) & -4;
  398.  
  399.     data = user_alloc(pitch*render->height);
  400.  
  401.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, render->width, render->height, 0,
  402.                  GL_RED,GL_UNSIGNED_BYTE, data);
  403.  
  404.     user_free(data);
  405.  
  406.     if(glGetError() != GL_NO_ERROR)
  407.        goto err2;
  408.  
  409.     render->mask = eglCreateImageKHR(render->dpy, render->context,
  410.                                      EGL_GL_TEXTURE_2D_KHR,(EGLClientBuffer)render->tx_mask,attrib);
  411.  
  412.     if(render->mask == EGL_NO_IMAGE_KHR)
  413.         goto err2;
  414.  
  415.     if(!eglExportDRMImageMESA(render->dpy, render->mask, NULL, &handle, &stride))
  416.         goto err3;
  417.  
  418.     glBindTexture(GL_TEXTURE_2D, 0);
  419.  
  420.     mmap_arg.handle = handle;
  421.     mmap_arg.offset = 0;
  422.     mmap_arg.size = stride * render->height;
  423.     if (drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))
  424.     {
  425.         printf("%s: failed to mmap image %p handle=%d, %d bytes, into CPU domain\n",
  426.                __FUNCTION__, render->mask, handle, stride*render->height);
  427.         goto err3;
  428.     }
  429.  
  430.     render->mask_buffer = (void *)(uintptr_t)mmap_arg.addr_ptr;
  431.  
  432.     printf("%s: mmap image %p handle=%d, %d bytes to %p\n",
  433.            __FUNCTION__, render->mask, handle, stride*render->height, render->mask_buffer);
  434.  
  435.     return;
  436.  
  437. err3:
  438.     eglDestroyImageKHR(render->dpy, render->mask);
  439. err2:
  440.     glBindTexture(GL_TEXTURE_2D, 0);
  441. err1:
  442.     glDeleteTextures(1, &render->tx_mask);
  443. };
  444.