Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2011 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19.  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20.  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Kristian Høgsberg <krh@bitplanet.net>
  26.  */
  27.  
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <xf86drm.h>
  32. //#include <dlfcn.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include <unistd.h>
  37. #include <kos32sys.h>
  38. #include <pixlib2.h>
  39.  
  40. #define EGL_EGLEXT_PROTOTYPES
  41. #include <EGL/egl.h>
  42. #include <EGL/eglext.h>
  43.  
  44. #include "egl_dri2.h"
  45.  
  46. int sna_bitmap_from_handle(bitmap_t *bitmap, uint32_t handle);
  47. void sna_set_bo_handle(bitmap_t *bitmap, int handle);
  48. int sna_blit_tex(bitmap_t *bitmap, int scale, int dst_x, int dst_y,
  49.                   int w, int h, int src_x, int src_y);
  50.  
  51. static struct gbm_bo *
  52. lock_front_buffer(struct gbm_surface *_surf)
  53. {
  54.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  55.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  56.    struct gbm_bo *bo;
  57.  
  58.    if (dri2_surf->current == NULL) {
  59.       _eglError(EGL_BAD_SURFACE, "no front buffer");
  60.       return NULL;
  61.    }
  62.  
  63.    bo = dri2_surf->current->bo;
  64.    dri2_surf->current->locked = 1;
  65.    dri2_surf->current = NULL;
  66.  
  67.    return bo;
  68. }
  69.  
  70. static void
  71. release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
  72. {
  73.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  74.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  75.    int i;
  76.  
  77.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  78.       if (dri2_surf->color_buffers[i].bo == bo) {
  79.          dri2_surf->color_buffers[i].locked = 0;
  80.       }
  81.    }
  82. }
  83.  
  84. static int
  85. has_free_buffers(struct gbm_surface *_surf)
  86. {
  87.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  88.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  89.    int i;
  90.  
  91.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  92.       if (!dri2_surf->color_buffers[i].locked)
  93.          return 1;
  94.  
  95.    return 0;
  96. }
  97.  
  98. static _EGLSurface *
  99. dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
  100.                     _EGLConfig *conf, EGLNativeWindowType window,
  101.                     const EGLint *attrib_list)
  102. {
  103.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  104.    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  105.    struct dri2_egl_surface *dri2_surf;
  106.    struct gbm_dri_surface *surf;
  107.  
  108.    (void) drv;
  109.  
  110.    dri2_surf = calloc(1, sizeof *dri2_surf);
  111.    if (!dri2_surf) {
  112.       _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
  113.       return NULL;
  114.    }
  115.  
  116.    if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
  117.       goto cleanup_surf;
  118.  
  119.    switch (type) {
  120.    case EGL_WINDOW_BIT:
  121.       if (!window)
  122.          return NULL;
  123.       surf = gbm_dri_surface((struct gbm_surface *) window);
  124.       dri2_surf->gbm_surf = surf;
  125.       dri2_surf->base.Width =  surf->base.width;
  126.       dri2_surf->base.Height = surf->base.height;
  127.       surf->dri_private = dri2_surf;
  128.       break;
  129.    default:
  130.       goto cleanup_surf;
  131.    }
  132.  
  133.    dri2_surf->dri_drawable =
  134.       (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
  135.                                             dri2_conf->dri_double_config,
  136.                                             dri2_surf->gbm_surf);
  137.  
  138.    if (dri2_surf->dri_drawable == NULL) {
  139.       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
  140.       goto cleanup_surf;
  141.    }
  142.  
  143.    return &dri2_surf->base;
  144.  
  145.  cleanup_surf:
  146.    free(dri2_surf);
  147.  
  148.    return NULL;
  149. }
  150.  
  151. static _EGLSurface *
  152. dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
  153.                            _EGLConfig *conf, EGLNativeWindowType window,
  154.                            const EGLint *attrib_list)
  155. {
  156.    return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
  157.                               window, attrib_list);
  158. }
  159.  
  160. static EGLBoolean
  161. dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  162. {
  163.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  164.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  165.    int i;
  166.  
  167.    if (!_eglPutSurface(surf))
  168.       return EGL_TRUE;
  169.  
  170.    (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
  171.  
  172.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  173.       if (dri2_surf->color_buffers[i].bo)
  174.          gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
  175.    }
  176.  
  177.    for (i = 0; i < __DRI_BUFFER_COUNT; i++) {
  178.       if (dri2_surf->dri_buffers[i])
  179.          dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
  180.                                        dri2_surf->dri_buffers[i]);
  181.    }
  182.  
  183.    free(surf);
  184.  
  185.    return EGL_TRUE;
  186. }
  187.  
  188. static int
  189. get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
  190. {
  191.    struct dri2_egl_display *dri2_dpy =
  192.       dri2_egl_display(dri2_surf->base.Resource.Display);
  193.    struct gbm_dri_bo *bo;
  194.    struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
  195.    int i, name, pitch;
  196.  
  197.    if (dri2_surf->back == NULL) {
  198.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  199.          if (!dri2_surf->color_buffers[i].locked) {
  200.             dri2_surf->back = &dri2_surf->color_buffers[i];
  201.             break;
  202.          }
  203.       }
  204.    }
  205.  
  206.    if (dri2_surf->back == NULL)
  207.       return -1;
  208.    if (dri2_surf->back->bo == NULL)
  209.       dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
  210.                                           surf->base.width, surf->base.height,
  211.                                           surf->base.format, surf->base.flags);
  212.    if (dri2_surf->back->bo == NULL)
  213.       return -1;
  214.  
  215.    bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
  216.  
  217.    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
  218.    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  219.  
  220.    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
  221.    buffer->name = name;
  222.    buffer->pitch = pitch;
  223.    buffer->cpp = 4;
  224.    buffer->flags = 0;
  225.  
  226.    return 0;
  227. }
  228.  
  229. static int
  230. get_aux_bo(struct dri2_egl_surface *dri2_surf,
  231.            unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
  232. {
  233.    struct dri2_egl_display *dri2_dpy =
  234.       dri2_egl_display(dri2_surf->base.Resource.Display);
  235.    __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
  236.  
  237.    if (b == NULL) {
  238.       b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
  239.                                          attachment, format,
  240.                                          dri2_surf->base.Width,
  241.                                          dri2_surf->base.Height);
  242.       dri2_surf->dri_buffers[attachment] = b;
  243.    }
  244.    if (b == NULL)
  245.       return -1;
  246.  
  247.    memcpy(buffer, b, sizeof *buffer);
  248.  
  249.    return 0;
  250. }
  251.  
  252. static __DRIbuffer *
  253. dri2_get_buffers_with_format(__DRIdrawable *driDrawable,
  254.                              int *width, int *height,
  255.                              unsigned int *attachments, int count,
  256.                              int *out_count, void *loaderPrivate)
  257. {
  258.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  259.    int i, j;
  260.  
  261.    dri2_surf->buffer_count = 0;
  262.    for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
  263.       assert(attachments[i] < __DRI_BUFFER_COUNT);
  264.       assert(dri2_surf->buffer_count < 5);
  265.  
  266.       switch (attachments[i]) {
  267.       case __DRI_BUFFER_BACK_LEFT:
  268.          if (get_back_bo(dri2_surf, &dri2_surf->buffers[j]) < 0) {
  269.             _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
  270.             return NULL;
  271.          }
  272.          break;
  273.       default:
  274.          if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
  275.                         &dri2_surf->buffers[j]) < 0) {
  276.             _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
  277.             return NULL;
  278.          }
  279.          break;
  280.       }
  281.    }
  282.  
  283.    *out_count = j;
  284.    if (j == 0)
  285.       return NULL;
  286.  
  287.    *width = dri2_surf->base.Width;
  288.    *height = dri2_surf->base.Height;
  289.  
  290.    return dri2_surf->buffers;
  291. }
  292.  
  293. static __DRIbuffer *
  294. dri2_get_buffers(__DRIdrawable * driDrawable,
  295.                  int *width, int *height,
  296.                  unsigned int *attachments, int count,
  297.                  int *out_count, void *loaderPrivate)
  298. {
  299.    unsigned int *attachments_with_format;
  300.    __DRIbuffer *buffer;
  301.    const unsigned int format = 32;
  302.    int i;
  303.  
  304.    attachments_with_format = calloc(count * 2, sizeof(unsigned int));
  305.    if (!attachments_with_format) {
  306.       *out_count = 0;
  307.       return NULL;
  308.    }
  309.  
  310.    for (i = 0; i < count; ++i) {
  311.       attachments_with_format[2*i] = attachments[i];
  312.       attachments_with_format[2*i + 1] = format;
  313.    }
  314.  
  315.    buffer =
  316.       dri2_get_buffers_with_format(driDrawable,
  317.                                    width, height,
  318.                                    attachments_with_format, count,
  319.                                    out_count, loaderPrivate);
  320.  
  321.    free(attachments_with_format);
  322.  
  323.    return buffer;
  324. }
  325.  
  326. static void
  327. dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  328. {
  329.    (void) driDrawable;
  330.    (void) loaderPrivate;
  331. }
  332.  
  333. static EGLBoolean
  334. dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  335. {
  336.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  337.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  338.    __DRIbuffer buffer;
  339.    static bitmap_t bm;
  340.  
  341.    int i;
  342.  
  343.    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  344.       if (dri2_surf->current)
  345.         _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
  346.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  347.          if (dri2_surf->color_buffers[i].age > 0)
  348.             dri2_surf->color_buffers[i].age++;
  349.  
  350.       if ( (dri2_surf->back != NULL) &&
  351.            (dri2_surf->back->bo != NULL))
  352.       {
  353.         struct gbm_dri_bo *bo;
  354.         bo = (struct gbm_dri_bo *)dri2_surf->back->bo;
  355.  
  356.         if(bm.width == 0)
  357.         {
  358.             printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
  359.                 __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
  360.                               bo->base.base.height, (int)bo->base.base.stride,
  361.                               bo->base.base.format);
  362.  
  363.             bm.width      = bo->base.base.width;
  364.             bm.height     = bo->base.base.height;
  365.             bm.pitch      = (int)bo->base.base.stride;
  366.             bm.max_width  = bo->base.base.width;
  367.             bm.max_height = bo->base.base.height;
  368.             bm.flags      = HW_TEX_BLIT;
  369.  
  370.             if( sna_bitmap_from_handle(&bm, bo->base.base.handle.s32))
  371.             {
  372.                 printf("sna_bitmap_from_handle failed\n");
  373.             }
  374.         }
  375.         if( bm.handle != 0)
  376.         {
  377.             sna_set_bo_handle(&bm, bo->base.base.handle.s32);
  378.             sna_blit_tex(&bm, 0, 5, 22, bm.width, bm.height, 0, 0);
  379.         }
  380.       }
  381.  
  382.       dri2_surf->current = dri2_surf->back;
  383.       dri2_surf->current->age = 1;
  384.       dri2_surf->back = NULL;
  385.    }
  386.  
  387.    (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
  388.    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  389.  
  390.    return EGL_TRUE;
  391. }
  392.  
  393. static EGLint
  394. dri2_query_buffer_age(_EGLDriver *drv,
  395.                       _EGLDisplay *disp, _EGLSurface *surface)
  396. {
  397.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
  398.    __DRIbuffer buffer;
  399.  
  400.    if (get_back_bo(dri2_surf, &buffer) < 0) {
  401.       _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
  402.       return 0;
  403.    }
  404.  
  405.    return dri2_surf->back->age;
  406. }
  407.  
  408. static _EGLImage *
  409. dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
  410.                              EGLClientBuffer buffer, const EGLint *attr_list)
  411. {
  412.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  413.    struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
  414.    struct dri2_egl_image *dri2_img;
  415.  
  416.    dri2_img = malloc(sizeof *dri2_img);
  417.    if (!dri2_img) {
  418.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  419.       return NULL;
  420.    }
  421.  
  422.    if (!_eglInitImage(&dri2_img->base, disp)) {
  423.       free(dri2_img);
  424.       return NULL;
  425.    }
  426.  
  427.    dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
  428.    if (dri2_img->dri_image == NULL) {
  429.       free(dri2_img);
  430.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  431.       return NULL;
  432.    }
  433.  
  434.    return &dri2_img->base;
  435. }
  436.  
  437. static _EGLImage *
  438. dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  439.                           _EGLContext *ctx, EGLenum target,
  440.                           EGLClientBuffer buffer, const EGLint *attr_list)
  441. {
  442.    (void) drv;
  443.  
  444.    switch (target) {
  445.    case EGL_NATIVE_PIXMAP_KHR:
  446.       return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
  447.    default:
  448.       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
  449.    }
  450. }
  451.  
  452. #if 0
  453. static int
  454. dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
  455. {
  456.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  457.  
  458.    return drmAuthMagic(dri2_dpy->fd, id);
  459. }
  460. #endif
  461.  
  462. EGLBoolean
  463. dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
  464. {
  465.    struct dri2_egl_display *dri2_dpy;
  466.    struct gbm_device *gbm;
  467.    int fd = -1;
  468.    int i;
  469.  
  470.    dri2_dpy = calloc(1, sizeof *dri2_dpy);
  471.    if (!dri2_dpy)
  472.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  473.  
  474.    disp->DriverData = (void *) dri2_dpy;
  475.  
  476.    gbm = disp->PlatformDisplay;
  477.    if (gbm == NULL) {
  478.       fd = get_service("DISPLAY");
  479.       dri2_dpy->own_device = 1;
  480.       gbm = gbm_create_device(fd);
  481.       if (gbm == NULL)
  482.          return EGL_FALSE;
  483.    }
  484.  
  485.    if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
  486.       free(dri2_dpy);
  487.       return EGL_FALSE;
  488.    }
  489.  
  490.    dri2_dpy->gbm_dri = gbm_dri_device(gbm);
  491.    if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
  492.       free(dri2_dpy);
  493.       return EGL_FALSE;
  494.    }
  495.  
  496.    dri2_dpy->fd = fd;
  497.    dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd);
  498.    dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
  499.  
  500.    dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
  501.    dri2_dpy->core = dri2_dpy->gbm_dri->core;
  502.    dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
  503.    dri2_dpy->image = dri2_dpy->gbm_dri->image;
  504.    dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
  505.    dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
  506.  
  507.    dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
  508.    dri2_dpy->gbm_dri->lookup_user_data = disp;
  509.  
  510.    dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers;
  511.    dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer;
  512.    dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format;
  513.  
  514.    dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
  515.    dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
  516.    dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
  517.  
  518.    dri2_setup_screen(disp);
  519.  
  520.    for (i = 0; dri2_dpy->driver_configs[i]; i++)
  521.       dri2_add_config(disp, dri2_dpy->driver_configs[i],
  522.                       i + 1, 0, EGL_WINDOW_BIT, NULL, NULL);
  523.  
  524.    drv->API.CreateWindowSurface = dri2_create_window_surface;
  525.    drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
  526.    drv->API.DestroySurface = dri2_destroy_surface;
  527.    drv->API.SwapBuffers = dri2_swap_buffers;
  528.    drv->API.CreateImageKHR = dri2_drm_create_image_khr;
  529.    drv->API.QueryBufferAge = dri2_query_buffer_age;
  530.  
  531.    disp->Extensions.EXT_buffer_age = EGL_TRUE;
  532.  
  533. #ifdef HAVE_WAYLAND_PLATFORM
  534.    disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
  535. #endif
  536. //   dri2_dpy->authenticate = dri2_drm_authenticate;
  537.  
  538.    /* we're supporting EGL 1.4 */
  539.    disp->VersionMajor = 1;
  540.    disp->VersionMinor = 4;
  541.  
  542.    return EGL_TRUE;
  543. }
  544.