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.    {
  199.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  200.       {
  201.         if(dri2_surf->color_buffers[i].locked)
  202.         {
  203.             dri2_surf->color_buffers[i].locked = 0;
  204.             continue;
  205.         }
  206.         dri2_surf->back = &dri2_surf->color_buffers[i];
  207.       }
  208.    }
  209.  
  210.     if (dri2_surf->back == NULL)
  211.         return -1;
  212.     if (dri2_surf->back->bo == NULL)
  213.         dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
  214.                                           surf->base.width, surf->base.height,
  215.                                           surf->base.format, surf->base.flags);
  216.     if (dri2_surf->back->bo == NULL)
  217.         return -1;
  218.  
  219.     bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
  220.  
  221.     dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
  222.     dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  223.  
  224.     buffer->attachment = __DRI_BUFFER_BACK_LEFT;
  225.     buffer->name = name;
  226.     buffer->pitch = pitch;
  227.     buffer->cpp = 4;
  228.     buffer->flags = 0;
  229.  
  230.     dri2_surf->back->locked = 1;
  231.  
  232.     return 0;
  233. }
  234.  
  235. static int
  236. get_aux_bo(struct dri2_egl_surface *dri2_surf,
  237.            unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
  238. {
  239.    struct dri2_egl_display *dri2_dpy =
  240.       dri2_egl_display(dri2_surf->base.Resource.Display);
  241.    __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
  242.  
  243.    if (b == NULL) {
  244.       b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
  245.                                          attachment, format,
  246.                                          dri2_surf->base.Width,
  247.                                          dri2_surf->base.Height);
  248.       dri2_surf->dri_buffers[attachment] = b;
  249.    }
  250.    if (b == NULL)
  251.       return -1;
  252.  
  253.    memcpy(buffer, b, sizeof *buffer);
  254.  
  255.    return 0;
  256. }
  257.  
  258. static __DRIbuffer *
  259. dri2_get_buffers_with_format(__DRIdrawable *driDrawable,
  260.                              int *width, int *height,
  261.                              unsigned int *attachments, int count,
  262.                              int *out_count, void *loaderPrivate)
  263. {
  264.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  265.    int i, j;
  266.  
  267. //   printf("dri2_get_buffers_with_format count %d\n", count);
  268.  
  269.    dri2_surf->buffer_count = 0;
  270.    for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
  271.       assert(attachments[i] < __DRI_BUFFER_COUNT);
  272.       assert(dri2_surf->buffer_count < 5);
  273.  
  274. //      printf("attachments %d\n",attachments[i]);
  275.  
  276.       switch (attachments[i]) {
  277.       case __DRI_BUFFER_BACK_LEFT:
  278.         if (get_back_bo(dri2_surf, &dri2_surf->buffers[j]) < 0) {
  279.             _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
  280.             return NULL;
  281.         }
  282.         break;
  283.       default:
  284.         if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
  285.                         &dri2_surf->buffers[j]) < 0) {
  286.             _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
  287.             return NULL;
  288.         }
  289.         break;
  290.       }
  291.    }
  292.  
  293.    *out_count = j;
  294.    if (j == 0)
  295.       return NULL;
  296.  
  297.    *width = dri2_surf->base.Width;
  298.    *height = dri2_surf->base.Height;
  299.  
  300.    return dri2_surf->buffers;
  301. }
  302.  
  303. static __DRIbuffer *
  304. dri2_get_buffers(__DRIdrawable * driDrawable,
  305.                  int *width, int *height,
  306.                  unsigned int *attachments, int count,
  307.                  int *out_count, void *loaderPrivate)
  308. {
  309.    unsigned int *attachments_with_format;
  310.    __DRIbuffer *buffer;
  311.    const unsigned int format = 32;
  312.    int i;
  313.  
  314.    attachments_with_format = calloc(count * 2, sizeof(unsigned int));
  315.    if (!attachments_with_format) {
  316.       *out_count = 0;
  317.       return NULL;
  318.    }
  319.  
  320.    for (i = 0; i < count; ++i) {
  321.       attachments_with_format[2*i] = attachments[i];
  322.       attachments_with_format[2*i + 1] = format;
  323.    }
  324.  
  325.    buffer =
  326.       dri2_get_buffers_with_format(driDrawable,
  327.                                    width, height,
  328.                                    attachments_with_format, count,
  329.                                    out_count, loaderPrivate);
  330.  
  331.    free(attachments_with_format);
  332.  
  333.    return buffer;
  334. }
  335.  
  336. static void
  337. dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  338. {
  339.    (void) driDrawable;
  340.    (void) loaderPrivate;
  341. }
  342.  
  343. static EGLBoolean
  344. dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  345. {
  346.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  347.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  348.    __DRIbuffer buffer;
  349.    static bitmap_t bm;
  350.  
  351.    int i;
  352.  
  353.    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  354.       if (dri2_surf->current)
  355.         _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
  356.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  357.          if (dri2_surf->color_buffers[i].age > 0)
  358.             dri2_surf->color_buffers[i].age++;
  359.  
  360. #if 1
  361.  
  362.       if ( (dri2_surf->back != NULL) &&
  363.            (dri2_surf->back->bo != NULL))
  364.       {
  365.         struct gbm_dri_bo *bo;
  366.         bo = (struct gbm_dri_bo *)dri2_surf->back->bo;
  367.  
  368.         if(bm.width == 0)
  369.         {
  370. //            printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
  371. //                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
  372.  //                             bo->base.base.height, (int)bo->base.base.stride,
  373. //                              bo->base.base.format);
  374.  
  375.             bm.width      = bo->base.base.width;
  376.             bm.height     = bo->base.base.height;
  377.             bm.pitch      = (int)bo->base.base.stride;
  378.             bm.max_width  = bo->base.base.width;
  379.             bm.max_height = bo->base.base.height;
  380.             bm.flags      = HW_TEX_BLIT;
  381.  
  382.             if( sna_bitmap_from_handle(&bm, bo->base.base.handle.s32))
  383.             {
  384.                 printf("sna_bitmap_from_handle failed\n");
  385.             }
  386.         }
  387.         if( bm.handle != 0)
  388.         {
  389. //           printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
  390. //                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
  391. //                              bo->base.base.height, (int)bo->base.base.stride,
  392. //                              bo->base.base.format);
  393.  
  394.             sna_set_bo_handle(&bm, bo->base.base.handle.s32);
  395.             sna_blit_tex(&bm, 0, 5, 20, bm.width, bm.height, 0, 0);
  396.         }
  397.       }
  398. #endif
  399.  
  400.       dri2_surf->current = dri2_surf->back;
  401.       dri2_surf->current->age = 1;
  402.       dri2_surf->back = NULL;
  403.    }
  404.  
  405.    (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
  406.    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  407.  
  408.    return EGL_TRUE;
  409. }
  410.  
  411. static EGLint
  412. dri2_query_buffer_age(_EGLDriver *drv,
  413.                       _EGLDisplay *disp, _EGLSurface *surface)
  414. {
  415.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
  416.    __DRIbuffer buffer;
  417.  
  418.    if (get_back_bo(dri2_surf, &buffer) < 0) {
  419.       _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
  420.       return 0;
  421.    }
  422.  
  423.    return dri2_surf->back->age;
  424. }
  425.  
  426. static _EGLImage *
  427. dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
  428.                              EGLClientBuffer buffer, const EGLint *attr_list)
  429. {
  430.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  431.    struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
  432.    struct dri2_egl_image *dri2_img;
  433.  
  434.    dri2_img = malloc(sizeof *dri2_img);
  435.    if (!dri2_img) {
  436.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  437.       return NULL;
  438.    }
  439.  
  440.    if (!_eglInitImage(&dri2_img->base, disp)) {
  441.       free(dri2_img);
  442.       return NULL;
  443.    }
  444.  
  445.    dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
  446.    if (dri2_img->dri_image == NULL) {
  447.       free(dri2_img);
  448.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  449.       return NULL;
  450.    }
  451.  
  452.    return &dri2_img->base;
  453. }
  454.  
  455. static _EGLImage *
  456. dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  457.                           _EGLContext *ctx, EGLenum target,
  458.                           EGLClientBuffer buffer, const EGLint *attr_list)
  459. {
  460.    (void) drv;
  461.  
  462.    switch (target) {
  463.    case EGL_NATIVE_PIXMAP_KHR:
  464.       return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
  465.    default:
  466.       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
  467.    }
  468. }
  469.  
  470. #if 0
  471. static int
  472. dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
  473. {
  474.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  475.  
  476.    return drmAuthMagic(dri2_dpy->fd, id);
  477. }
  478. #endif
  479.  
  480. EGLBoolean
  481. dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
  482. {
  483.    struct dri2_egl_display *dri2_dpy;
  484.    struct gbm_device *gbm;
  485.    int fd = -1;
  486.    int i;
  487.  
  488.    dri2_dpy = calloc(1, sizeof *dri2_dpy);
  489.    if (!dri2_dpy)
  490.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  491.  
  492.    disp->DriverData = (void *) dri2_dpy;
  493.  
  494.    gbm = disp->PlatformDisplay;
  495.    if (gbm == NULL) {
  496.       fd = get_service("DISPLAY");
  497.       dri2_dpy->own_device = 1;
  498.       gbm = gbm_create_device(fd);
  499.       if (gbm == NULL)
  500.          return EGL_FALSE;
  501.    }
  502.  
  503.    if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
  504.       free(dri2_dpy);
  505.       return EGL_FALSE;
  506.    }
  507.  
  508.    dri2_dpy->gbm_dri = gbm_dri_device(gbm);
  509.    if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
  510.       free(dri2_dpy);
  511.       return EGL_FALSE;
  512.    }
  513.  
  514.    dri2_dpy->fd = fd;
  515.    dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd);
  516.    dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
  517.  
  518.    dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
  519.    dri2_dpy->core = dri2_dpy->gbm_dri->core;
  520.    dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
  521.    dri2_dpy->image = dri2_dpy->gbm_dri->image;
  522.    dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
  523.    dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
  524.  
  525.    dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
  526.    dri2_dpy->gbm_dri->lookup_user_data = disp;
  527.  
  528.    dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers;
  529.    dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer;
  530.    dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format;
  531.  
  532.    dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
  533.    dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
  534.    dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
  535.  
  536.    dri2_setup_screen(disp);
  537.  
  538.    for (i = 0; dri2_dpy->driver_configs[i]; i++)
  539.       dri2_add_config(disp, dri2_dpy->driver_configs[i],
  540.                       i + 1, 0, EGL_WINDOW_BIT, NULL, NULL);
  541.  
  542.    drv->API.CreateWindowSurface = dri2_create_window_surface;
  543.    drv->API.DestroySurface = dri2_destroy_surface;
  544.    drv->API.SwapBuffers = dri2_swap_buffers;
  545.    drv->API.CreateImageKHR = dri2_drm_create_image_khr;
  546.    drv->API.QueryBufferAge = dri2_query_buffer_age;
  547.  
  548.    disp->Extensions.EXT_buffer_age = EGL_TRUE;
  549.  
  550. #ifdef HAVE_WAYLAND_PLATFORM
  551.    disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
  552. #endif
  553. //   dri2_dpy->authenticate = dri2_drm_authenticate;
  554.  
  555.    /* we're supporting EGL 1.4 */
  556.    disp->VersionMajor = 1;
  557.    disp->VersionMinor = 4;
  558.  
  559.    return EGL_TRUE;
  560. }
  561.