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 <stdint.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <xf86drm.h>
  33. #include <dlfcn.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38.  
  39. #include "egl_dri2.h"
  40. #include "egl_dri2_fallbacks.h"
  41. #include "loader.h"
  42.  
  43. static struct gbm_bo *
  44. lock_front_buffer(struct gbm_surface *_surf)
  45. {
  46.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  47.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  48.    struct gbm_dri_device *device = (struct gbm_dri_device *) _surf->gbm;
  49.    struct gbm_bo *bo;
  50.  
  51.    if (dri2_surf->current == NULL) {
  52.       _eglError(EGL_BAD_SURFACE, "no front buffer");
  53.       return NULL;
  54.    }
  55.  
  56.    bo = dri2_surf->current->bo;
  57.  
  58.    if (device->dri2) {
  59.       dri2_surf->current->locked = 1;
  60.       dri2_surf->current = NULL;
  61.    }
  62.  
  63.    return bo;
  64. }
  65.  
  66. static void
  67. release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
  68. {
  69.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  70.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  71.    int i;
  72.  
  73.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  74.       if (dri2_surf->color_buffers[i].bo == bo) {
  75.          dri2_surf->color_buffers[i].locked = 0;
  76.       }
  77.    }
  78. }
  79.  
  80. static int
  81. has_free_buffers(struct gbm_surface *_surf)
  82. {
  83.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  84.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  85.    int i;
  86.  
  87.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  88.       if (!dri2_surf->color_buffers[i].locked)
  89.          return 1;
  90.  
  91.    return 0;
  92. }
  93.  
  94. static _EGLSurface *
  95. dri2_drm_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
  96.                         _EGLConfig *conf, void *native_window,
  97.                         const EGLint *attrib_list)
  98. {
  99.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  100.    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  101.    struct dri2_egl_surface *dri2_surf;
  102.    struct gbm_surface *window = native_window;
  103.    struct gbm_dri_surface *surf;
  104.  
  105.    (void) drv;
  106.  
  107.    dri2_surf = calloc(1, sizeof *dri2_surf);
  108.    if (!dri2_surf) {
  109.       _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
  110.       return NULL;
  111.    }
  112.  
  113.    if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
  114.       goto cleanup_surf;
  115.  
  116.    switch (type) {
  117.    case EGL_WINDOW_BIT:
  118.       if (!window)
  119.          return NULL;
  120.       surf = gbm_dri_surface(window);
  121.       dri2_surf->gbm_surf = surf;
  122.       dri2_surf->base.Width =  surf->base.width;
  123.       dri2_surf->base.Height = surf->base.height;
  124.       surf->dri_private = dri2_surf;
  125.       break;
  126.    default:
  127.       goto cleanup_surf;
  128.    }
  129.  
  130.    if (dri2_dpy->dri2) {
  131.       dri2_surf->dri_drawable =
  132.          (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
  133.                                                dri2_conf->dri_double_config,
  134.                                                dri2_surf->gbm_surf);
  135.  
  136.    } else {
  137.       assert(dri2_dpy->swrast != NULL);
  138.       dri2_surf->dri_drawable =
  139.          (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
  140.                                                  dri2_conf->dri_double_config,
  141.                                                  dri2_surf->gbm_surf);
  142.  
  143.    }
  144.    if (dri2_surf->dri_drawable == NULL) {
  145.       _eglError(EGL_BAD_ALLOC, "createNewDrawable()");
  146.       goto cleanup_surf;
  147.    }
  148.  
  149.    return &dri2_surf->base;
  150.  
  151.  cleanup_surf:
  152.    free(dri2_surf);
  153.  
  154.    return NULL;
  155. }
  156.  
  157. static _EGLSurface *
  158. dri2_drm_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
  159.                                _EGLConfig *conf, void *native_window,
  160.                                const EGLint *attrib_list)
  161. {
  162.    return dri2_drm_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
  163.                                   native_window, attrib_list);
  164. }
  165.  
  166. static _EGLSurface *
  167. dri2_drm_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
  168.                                _EGLConfig *conf, void *native_window,
  169.                                const EGLint *attrib_list)
  170. {
  171.    /* From the EGL_MESA_platform_gbm spec, version 5:
  172.     *
  173.     *  It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
  174.     *  that belongs to the GBM platform. Any such call fails and generates
  175.     *  EGL_BAD_PARAMETER.
  176.     */
  177.    _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on GBM");
  178.    return NULL;
  179. }
  180.  
  181. static EGLBoolean
  182. dri2_drm_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  183. {
  184.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  185.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  186.    int i;
  187.  
  188.    if (!_eglPutSurface(surf))
  189.       return EGL_TRUE;
  190.  
  191.    (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
  192.  
  193.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  194.       if (dri2_surf->color_buffers[i].bo)
  195.          gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
  196.    }
  197.  
  198.    for (i = 0; i < __DRI_BUFFER_COUNT; i++) {
  199.       if (dri2_surf->dri_buffers[i])
  200.          dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
  201.                                        dri2_surf->dri_buffers[i]);
  202.    }
  203.  
  204.    free(surf);
  205.  
  206.    return EGL_TRUE;
  207. }
  208.  
  209. static int
  210. get_back_bo(struct dri2_egl_surface *dri2_surf)
  211. {
  212.    struct dri2_egl_display *dri2_dpy =
  213.       dri2_egl_display(dri2_surf->base.Resource.Display);
  214.    struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
  215.    int i;
  216.  
  217.    if (dri2_surf->back == NULL) {
  218.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  219.          if (!dri2_surf->color_buffers[i].locked) {
  220.             dri2_surf->back = &dri2_surf->color_buffers[i];
  221.             break;
  222.          }
  223.       }
  224.    }
  225.  
  226.    if (dri2_surf->back == NULL)
  227.       return -1;
  228.    if (dri2_surf->back->bo == NULL)
  229.       dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
  230.                                           surf->base.width, surf->base.height,
  231.                                           surf->base.format, surf->base.flags);
  232.    if (dri2_surf->back->bo == NULL)
  233.       return -1;
  234.  
  235.    return 0;
  236. }
  237.  
  238. static int
  239. get_swrast_front_bo(struct dri2_egl_surface *dri2_surf)
  240. {
  241.    struct dri2_egl_display *dri2_dpy =
  242.       dri2_egl_display(dri2_surf->base.Resource.Display);
  243.    struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
  244.  
  245.    if (dri2_surf->current == NULL) {
  246.       assert(!dri2_surf->color_buffers[0].locked);
  247.       dri2_surf->current = &dri2_surf->color_buffers[0];
  248.    }
  249.  
  250.    if (dri2_surf->current->bo == NULL)
  251.       dri2_surf->current->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
  252.                                              surf->base.width, surf->base.height,
  253.                                              surf->base.format, surf->base.flags);
  254.    if (dri2_surf->current->bo == NULL)
  255.       return -1;
  256.  
  257.    return 0;
  258. }
  259.  
  260. static void
  261. back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
  262. {
  263.    struct dri2_egl_display *dri2_dpy =
  264.       dri2_egl_display(dri2_surf->base.Resource.Display);
  265.    struct gbm_dri_bo *bo;
  266.    int name, pitch;
  267.  
  268.    bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
  269.  
  270.    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
  271.    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  272.  
  273.    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
  274.    buffer->name = name;
  275.    buffer->pitch = pitch;
  276.    buffer->cpp = 4;
  277.    buffer->flags = 0;
  278. }
  279.  
  280. static int
  281. get_aux_bo(struct dri2_egl_surface *dri2_surf,
  282.            unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
  283. {
  284.    struct dri2_egl_display *dri2_dpy =
  285.       dri2_egl_display(dri2_surf->base.Resource.Display);
  286.    __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
  287.  
  288.    if (b == NULL) {
  289.       b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
  290.                                          attachment, format,
  291.                                          dri2_surf->base.Width,
  292.                                          dri2_surf->base.Height);
  293.       dri2_surf->dri_buffers[attachment] = b;
  294.    }
  295.    if (b == NULL)
  296.       return -1;
  297.  
  298.    memcpy(buffer, b, sizeof *buffer);
  299.  
  300.    return 0;
  301. }
  302.  
  303. static __DRIbuffer *
  304. dri2_drm_get_buffers_with_format(__DRIdrawable *driDrawable,
  305.                              int *width, int *height,
  306.                              unsigned int *attachments, int count,
  307.                              int *out_count, void *loaderPrivate)
  308. {
  309.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  310.    int i, j;
  311.  
  312.    dri2_surf->buffer_count = 0;
  313.    for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
  314.       assert(attachments[i] < __DRI_BUFFER_COUNT);
  315.       assert(dri2_surf->buffer_count < 5);
  316.  
  317.       switch (attachments[i]) {
  318.       case __DRI_BUFFER_BACK_LEFT:
  319.          if (get_back_bo(dri2_surf) < 0) {
  320.             _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
  321.             return NULL;
  322.          }
  323.          back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
  324.          break;
  325.       default:
  326.          if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
  327.                         &dri2_surf->buffers[j]) < 0) {
  328.             _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
  329.             return NULL;
  330.          }
  331.          break;
  332.       }
  333.    }
  334.  
  335.    *out_count = j;
  336.    if (j == 0)
  337.       return NULL;
  338.  
  339.    *width = dri2_surf->base.Width;
  340.    *height = dri2_surf->base.Height;
  341.  
  342.    return dri2_surf->buffers;
  343. }
  344.  
  345. static __DRIbuffer *
  346. dri2_drm_get_buffers(__DRIdrawable * driDrawable,
  347.                      int *width, int *height,
  348.                      unsigned int *attachments, int count,
  349.                      int *out_count, void *loaderPrivate)
  350. {
  351.    unsigned int *attachments_with_format;
  352.    __DRIbuffer *buffer;
  353.    const unsigned int format = 32;
  354.    int i;
  355.  
  356.    attachments_with_format = calloc(count, 2 * sizeof(unsigned int));
  357.    if (!attachments_with_format) {
  358.       *out_count = 0;
  359.       return NULL;
  360.    }
  361.  
  362.    for (i = 0; i < count; ++i) {
  363.       attachments_with_format[2*i] = attachments[i];
  364.       attachments_with_format[2*i + 1] = format;
  365.    }
  366.  
  367.    buffer =
  368.       dri2_drm_get_buffers_with_format(driDrawable,
  369.                                        width, height,
  370.                                        attachments_with_format, count,
  371.                                        out_count, loaderPrivate);
  372.  
  373.    free(attachments_with_format);
  374.  
  375.    return buffer;
  376. }
  377.  
  378. static int
  379. dri2_drm_image_get_buffers(__DRIdrawable *driDrawable,
  380.                            unsigned int format,
  381.                            uint32_t *stamp,
  382.                            void *loaderPrivate,
  383.                            uint32_t buffer_mask,
  384.                            struct __DRIimageList *buffers)
  385. {
  386.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  387.    struct gbm_dri_bo *bo;
  388.  
  389.    if (get_back_bo(dri2_surf) < 0)
  390.       return 0;
  391.  
  392.    bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
  393.    buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
  394.    buffers->back = bo->image;
  395.  
  396.    return 1;
  397. }
  398.  
  399. static void
  400. dri2_drm_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  401. {
  402.    (void) driDrawable;
  403.    (void) loaderPrivate;
  404. }
  405.  
  406. static EGLBoolean
  407. dri2_drm_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  408. {
  409.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  410.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  411.    int i;
  412.  
  413.    if (dri2_dpy->swrast) {
  414.       (*dri2_dpy->core->swapBuffers)(dri2_surf->dri_drawable);
  415.    } else {
  416.       if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  417.          if (dri2_surf->current)
  418.             _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
  419.          for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  420.             if (dri2_surf->color_buffers[i].age > 0)
  421.                dri2_surf->color_buffers[i].age++;
  422.  
  423.          /* Make sure we have a back buffer in case we're swapping without
  424.           * ever rendering. */
  425.          if (get_back_bo(dri2_surf) < 0) {
  426.             _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
  427.             return EGL_FALSE;
  428.          }
  429.  
  430.          dri2_surf->current = dri2_surf->back;
  431.          dri2_surf->current->age = 1;
  432.          dri2_surf->back = NULL;
  433.       }
  434.  
  435.       dri2_flush_drawable_for_swapbuffers(disp, draw);
  436.       (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  437.    }
  438.  
  439.    return EGL_TRUE;
  440. }
  441.  
  442. static EGLint
  443. dri2_drm_query_buffer_age(_EGLDriver *drv,
  444.                           _EGLDisplay *disp, _EGLSurface *surface)
  445. {
  446.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
  447.  
  448.    if (get_back_bo(dri2_surf) < 0) {
  449.       _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
  450.       return 0;
  451.    }
  452.  
  453.    return dri2_surf->back->age;
  454. }
  455.  
  456. static _EGLImage *
  457. dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
  458.                                  EGLClientBuffer buffer, const EGLint *attr_list)
  459. {
  460.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  461.    struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
  462.    struct dri2_egl_image *dri2_img;
  463.  
  464.    dri2_img = malloc(sizeof *dri2_img);
  465.    if (!dri2_img) {
  466.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  467.       return NULL;
  468.    }
  469.  
  470.    if (!_eglInitImage(&dri2_img->base, disp)) {
  471.       free(dri2_img);
  472.       return NULL;
  473.    }
  474.  
  475.    dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
  476.    if (dri2_img->dri_image == NULL) {
  477.       free(dri2_img);
  478.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  479.       return NULL;
  480.    }
  481.  
  482.    return &dri2_img->base;
  483. }
  484.  
  485. static _EGLImage *
  486. dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  487.                           _EGLContext *ctx, EGLenum target,
  488.                           EGLClientBuffer buffer, const EGLint *attr_list)
  489. {
  490.    (void) drv;
  491.  
  492.    switch (target) {
  493.    case EGL_NATIVE_PIXMAP_KHR:
  494.       return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
  495.    default:
  496.       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
  497.    }
  498. }
  499.  
  500. #if 0
  501. static int
  502. dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
  503. {
  504.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  505.  
  506.    return drmAuthMagic(dri2_dpy->fd, id);
  507. }
  508. #endif
  509.  
  510. static void
  511. swrast_put_image2(__DRIdrawable *driDrawable,
  512.                   int            op,
  513.                   int            x,
  514.                   int            y,
  515.                   int            width,
  516.                   int            height,
  517.                   int            stride,
  518.                   char          *data,
  519.                   void          *loaderPrivate)
  520. {
  521.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  522.    int internal_stride, i;
  523.    struct gbm_dri_bo *bo;
  524.  
  525.    if (op != __DRI_SWRAST_IMAGE_OP_DRAW &&
  526.        op != __DRI_SWRAST_IMAGE_OP_SWAP)
  527.       return;
  528.  
  529.    if (get_swrast_front_bo(dri2_surf) < 0)
  530.       return;
  531.  
  532.    bo = gbm_dri_bo(dri2_surf->current->bo);
  533.    if (gbm_dri_bo_map(bo) == NULL)
  534.       return;
  535.  
  536.    internal_stride = bo->base.base.stride;
  537.  
  538.    for (i = 0; i < height; i++) {
  539.       memcpy(bo->map + (x + i) * internal_stride + y,
  540.              data + i * stride, stride);
  541.    }
  542.  
  543.    gbm_dri_bo_unmap(bo);
  544. }
  545.  
  546. static void
  547. swrast_get_image(__DRIdrawable *driDrawable,
  548.                  int            x,
  549.                  int            y,
  550.                  int            width,
  551.                  int            height,
  552.                  char          *data,
  553.                  void          *loaderPrivate)
  554. {
  555.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  556.    int internal_stride, stride, i;
  557.    struct gbm_dri_bo *bo;
  558.  
  559.    if (get_swrast_front_bo(dri2_surf) < 0)
  560.       return;
  561.  
  562.    bo = gbm_dri_bo(dri2_surf->current->bo);
  563.    if (gbm_dri_bo_map(bo) == NULL)
  564.       return;
  565.  
  566.    internal_stride = bo->base.base.stride;
  567.    stride = width * 4;
  568.  
  569.    for (i = 0; i < height; i++) {
  570.       memcpy(data + i * stride,
  571.              bo->map + (x + i) * internal_stride + y, stride);
  572.    }
  573.  
  574.    gbm_dri_bo_unmap(bo);
  575. }
  576.  
  577. static struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
  578.    .authenticate = dri2_drm_authenticate,
  579.    .create_window_surface = dri2_drm_create_window_surface,
  580.    .create_pixmap_surface = dri2_drm_create_pixmap_surface,
  581.    .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
  582.    .destroy_surface = dri2_drm_destroy_surface,
  583.    .create_image = dri2_drm_create_image_khr,
  584.    .swap_interval = dri2_fallback_swap_interval,
  585.    .swap_buffers = dri2_drm_swap_buffers,
  586.    .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
  587.    .swap_buffers_region = dri2_fallback_swap_buffers_region,
  588.    .post_sub_buffer = dri2_fallback_post_sub_buffer,
  589.    .copy_buffers = dri2_fallback_copy_buffers,
  590.    .query_buffer_age = dri2_drm_query_buffer_age,
  591.    .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
  592.    .get_sync_values = dri2_fallback_get_sync_values,
  593. };
  594.  
  595. EGLBoolean
  596. dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
  597. {
  598.    struct dri2_egl_display *dri2_dpy;
  599.    struct gbm_device *gbm;
  600.    void *lib;
  601.  
  602.    int fd = -1;
  603.    int i;
  604.  
  605.    loader_set_logger(_eglLog);
  606.  
  607.    dri2_dpy = calloc(1, sizeof *dri2_dpy);
  608.    if (!dri2_dpy)
  609.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  610.  
  611.    disp->DriverData = (void *) dri2_dpy;
  612.  
  613.    gbm = disp->PlatformDisplay;
  614.    if (gbm == NULL) {
  615.       fd = get_service("DISPLAY");
  616.       dri2_dpy->own_device = 1;
  617.       gbm = gbm_create_device(fd);
  618.       if (gbm == NULL)
  619.          return EGL_FALSE;
  620.    }
  621.  
  622.    if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
  623.       free(dri2_dpy);
  624.       return EGL_FALSE;
  625.    }
  626.  
  627.    dri2_dpy->gbm_dri = gbm_dri_device(gbm);
  628.    if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
  629.       free(dri2_dpy);
  630.       return EGL_FALSE;
  631.    }
  632.  
  633.    if (fd < 0) {
  634.       fd = dup(gbm_device_get_fd(gbm));
  635.       if (fd < 0) {
  636.          free(dri2_dpy);
  637.          return EGL_FALSE;
  638.       }
  639.    }
  640.  
  641.    dri2_dpy->fd = fd;
  642.    dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
  643.    dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->base.driver_name);
  644.  
  645.    dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
  646.    dri2_dpy->core = dri2_dpy->gbm_dri->core;
  647.    dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
  648.    dri2_dpy->image = dri2_dpy->gbm_dri->image;
  649.    dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
  650.    dri2_dpy->swrast = dri2_dpy->gbm_dri->swrast;
  651.    dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
  652.  
  653.    dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
  654.    dri2_dpy->gbm_dri->lookup_user_data = disp;
  655.  
  656.    dri2_dpy->gbm_dri->get_buffers = dri2_drm_get_buffers;
  657.    dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
  658.    dri2_dpy->gbm_dri->get_buffers_with_format = dri2_drm_get_buffers_with_format;
  659.    dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
  660.    dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2;
  661.    dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image;
  662.  
  663.    dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
  664.    dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
  665.    dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
  666.  
  667.    dri2_setup_screen(disp);
  668.  
  669.    for (i = 0; dri2_dpy->driver_configs[i]; i++) {
  670.       EGLint format, attr_list[3];
  671.       unsigned int red, alpha;
  672.  
  673.       dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
  674.                                        __DRI_ATTRIB_RED_MASK, &red);
  675.       dri2_dpy->core->getConfigAttrib(dri2_dpy->driver_configs[i],
  676.                                        __DRI_ATTRIB_ALPHA_MASK, &alpha);
  677.       if (red == 0x3ff00000 && alpha == 0x00000000)
  678.          format = GBM_FORMAT_XRGB2101010;
  679.       else if (red == 0x3ff00000 && alpha == 0xc0000000)
  680.          format = GBM_FORMAT_ARGB2101010;
  681.       else if (red == 0x00ff0000 && alpha == 0x00000000)
  682.          format = GBM_FORMAT_XRGB8888;
  683.       else if (red == 0x00ff0000 && alpha == 0xff000000)
  684.          format = GBM_FORMAT_ARGB8888;
  685.       else if (red == 0xf800)
  686.          format = GBM_FORMAT_RGB565;
  687.       else
  688.          continue;
  689.  
  690.       attr_list[0] = EGL_NATIVE_VISUAL_ID;
  691.       attr_list[1] = format;
  692.       attr_list[2] = EGL_NONE;
  693.  
  694.       dri2_add_config(disp, dri2_dpy->driver_configs[i],
  695.                       i + 1, EGL_WINDOW_BIT, attr_list, NULL);
  696.    }
  697.  
  698.    disp->Extensions.KHR_image_pixmap = EGL_TRUE;
  699.    if (dri2_dpy->dri2)
  700.       disp->Extensions.EXT_buffer_age = EGL_TRUE;
  701.  
  702. #ifdef HAVE_WAYLAND_PLATFORM
  703.    if (dri2_dpy->image) {
  704.        if (dri2_dpy->image->base.version >= 10 &&
  705.            dri2_dpy->image->getCapabilities != NULL) {
  706.            int capabilities;
  707.  
  708.            capabilities =
  709.                dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
  710.            disp->Extensions.WL_bind_wayland_display =
  711.                (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
  712.        } else
  713.            disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
  714.    }
  715. #endif
  716.  
  717.    /* we're supporting EGL 1.4 */
  718.    disp->VersionMajor = 1;
  719.    disp->VersionMinor = 4;
  720.  
  721.    /* Fill vtbl last to prevent accidentally calling virtual function during
  722.     * initialization.
  723.     */
  724.    dri2_dpy->vtbl = &dri2_drm_display_vtbl;
  725.  
  726.    return EGL_TRUE;
  727. }
  728.