Subversion Repositories Kolibri OS

Rev

Rev 4379 | 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. void* load_library(const char *name);
  47. void *get_proc_address(void *module, char *proc_name);
  48.  
  49. int (*blit_bitmap_from_handle)(bitmap_t *bitmap, uint32_t handle);
  50. void (*blit_set_bo_handle)(bitmap_t *bitmap, int handle);
  51. int (*blit_blit_tex)(bitmap_t *bitmap, int scale, int vsync, int dst_x, int dst_y,
  52.                   int w, int h, int src_x, int src_y);
  53.  
  54. static struct gbm_bo *
  55. lock_front_buffer(struct gbm_surface *_surf)
  56. {
  57.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  58.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  59.    struct gbm_bo *bo;
  60.  
  61.    if (dri2_surf->current == NULL) {
  62.       _eglError(EGL_BAD_SURFACE, "no front buffer");
  63.       return NULL;
  64.    }
  65.  
  66.    bo = dri2_surf->current->bo;
  67.    dri2_surf->current->locked = 1;
  68.    dri2_surf->current = NULL;
  69.  
  70.    return bo;
  71. }
  72.  
  73. static void
  74. release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
  75. {
  76.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  77.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  78.    int i;
  79.  
  80.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  81.       if (dri2_surf->color_buffers[i].bo == bo) {
  82.          dri2_surf->color_buffers[i].locked = 0;
  83.       }
  84.    }
  85. }
  86.  
  87. static int
  88. has_free_buffers(struct gbm_surface *_surf)
  89. {
  90.    struct gbm_dri_surface *surf = (struct gbm_dri_surface *) _surf;
  91.    struct dri2_egl_surface *dri2_surf = surf->dri_private;
  92.    int i;
  93.  
  94.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  95.       if (!dri2_surf->color_buffers[i].locked)
  96.          return 1;
  97.  
  98.    return 0;
  99. }
  100.  
  101. static _EGLSurface *
  102. dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
  103.                     _EGLConfig *conf, EGLNativeWindowType window,
  104.                     const EGLint *attrib_list)
  105. {
  106.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  107.    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  108.    struct dri2_egl_surface *dri2_surf;
  109.    struct gbm_dri_surface *surf;
  110.  
  111.    (void) drv;
  112.  
  113.    dri2_surf = calloc(1, sizeof *dri2_surf);
  114.    if (!dri2_surf) {
  115.       _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
  116.       return NULL;
  117.    }
  118.  
  119.    if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
  120.       goto cleanup_surf;
  121.  
  122.    switch (type) {
  123.    case EGL_WINDOW_BIT:
  124.       if (!window)
  125.          return NULL;
  126.       surf = gbm_dri_surface((struct gbm_surface *) window);
  127.       dri2_surf->gbm_surf = surf;
  128.       dri2_surf->base.Width =  surf->base.width;
  129.       dri2_surf->base.Height = surf->base.height;
  130.       surf->dri_private = dri2_surf;
  131.       break;
  132.    default:
  133.       goto cleanup_surf;
  134.    }
  135.  
  136.    dri2_surf->dri_drawable =
  137.       (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
  138.                                             dri2_conf->dri_double_config,
  139.                                             dri2_surf->gbm_surf);
  140.  
  141.    if (dri2_surf->dri_drawable == NULL) {
  142.       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
  143.       goto cleanup_surf;
  144.    }
  145.  
  146.    return &dri2_surf->base;
  147.  
  148.  cleanup_surf:
  149.    free(dri2_surf);
  150.  
  151.    return NULL;
  152. }
  153.  
  154. static _EGLSurface *
  155. dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
  156.                            _EGLConfig *conf, EGLNativeWindowType window,
  157.                            const EGLint *attrib_list)
  158. {
  159.    return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
  160.                               window, attrib_list);
  161. }
  162.  
  163. static EGLBoolean
  164. dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  165. {
  166.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  167.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  168.    int i;
  169.  
  170.    if (!_eglPutSurface(surf))
  171.       return EGL_TRUE;
  172.  
  173.    (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
  174.  
  175.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  176.       if (dri2_surf->color_buffers[i].bo)
  177.          gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
  178.    }
  179.  
  180.    for (i = 0; i < __DRI_BUFFER_COUNT; i++) {
  181.       if (dri2_surf->dri_buffers[i])
  182.          dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
  183.                                        dri2_surf->dri_buffers[i]);
  184.    }
  185.  
  186.    free(surf);
  187.  
  188.    return EGL_TRUE;
  189. }
  190.  
  191. static int
  192. get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
  193. {
  194.    struct dri2_egl_display *dri2_dpy =
  195.       dri2_egl_display(dri2_surf->base.Resource.Display);
  196.    struct gbm_dri_bo *bo;
  197.    struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
  198.    int i, name, pitch;
  199.  
  200.    if (dri2_surf->back == NULL)
  201.    {
  202.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  203.       {
  204.         if(dri2_surf->color_buffers[i].locked)
  205.         {
  206.             dri2_surf->color_buffers[i].locked = 0;
  207.             continue;
  208.         }
  209.         dri2_surf->back = &dri2_surf->color_buffers[i];
  210.       }
  211.    }
  212.  
  213.     if (dri2_surf->back == NULL)
  214.         return -1;
  215.     if (dri2_surf->back->bo == NULL)
  216.         dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base.base,
  217.                                           surf->base.width, surf->base.height,
  218.                                           surf->base.format, surf->base.flags);
  219.     if (dri2_surf->back->bo == NULL)
  220.         return -1;
  221.  
  222.     bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
  223.  
  224.     dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
  225.     dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  226.  
  227.     buffer->attachment = __DRI_BUFFER_BACK_LEFT;
  228.     buffer->name = name;
  229.     buffer->pitch = pitch;
  230.     buffer->cpp = 4;
  231.     buffer->flags = 0;
  232.  
  233.     dri2_surf->back->locked = 1;
  234.  
  235.     return 0;
  236. }
  237.  
  238. static int
  239. get_aux_bo(struct dri2_egl_surface *dri2_surf,
  240.            unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
  241. {
  242.    struct dri2_egl_display *dri2_dpy =
  243.       dri2_egl_display(dri2_surf->base.Resource.Display);
  244.    __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
  245.  
  246.    if (b == NULL) {
  247.       b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
  248.                                          attachment, format,
  249.                                          dri2_surf->base.Width,
  250.                                          dri2_surf->base.Height);
  251.       dri2_surf->dri_buffers[attachment] = b;
  252.    }
  253.    if (b == NULL)
  254.       return -1;
  255.  
  256.    memcpy(buffer, b, sizeof *buffer);
  257.  
  258.    return 0;
  259. }
  260.  
  261. static __DRIbuffer *
  262. dri2_get_buffers_with_format(__DRIdrawable *driDrawable,
  263.                              int *width, int *height,
  264.                              unsigned int *attachments, int count,
  265.                              int *out_count, void *loaderPrivate)
  266. {
  267.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  268.    int i, j;
  269.  
  270.    dri2_surf->buffer_count = 0;
  271.    for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
  272.       assert(attachments[i] < __DRI_BUFFER_COUNT);
  273.       assert(dri2_surf->buffer_count < 5);
  274.  
  275.       switch (attachments[i]) {
  276.       case __DRI_BUFFER_BACK_LEFT:
  277.         if (get_back_bo(dri2_surf, &dri2_surf->buffers[j]) < 0) {
  278.             _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
  279.             return NULL;
  280.         }
  281.         break;
  282.       default:
  283.         if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
  284.                         &dri2_surf->buffers[j]) < 0) {
  285.             _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
  286.             return NULL;
  287.         }
  288.         break;
  289.       }
  290.    }
  291.  
  292.    *out_count = j;
  293.    if (j == 0)
  294.       return NULL;
  295.  
  296.    *width = dri2_surf->base.Width;
  297.    *height = dri2_surf->base.Height;
  298.  
  299.    return dri2_surf->buffers;
  300. }
  301.  
  302. static __DRIbuffer *
  303. dri2_get_buffers(__DRIdrawable * driDrawable,
  304.                  int *width, int *height,
  305.                  unsigned int *attachments, int count,
  306.                  int *out_count, void *loaderPrivate)
  307. {
  308.    unsigned int *attachments_with_format;
  309.    __DRIbuffer *buffer;
  310.    const unsigned int format = 32;
  311.    int i;
  312.  
  313.    attachments_with_format = calloc(count * 2, sizeof(unsigned int));
  314.    if (!attachments_with_format) {
  315.       *out_count = 0;
  316.       return NULL;
  317.    }
  318.  
  319.    for (i = 0; i < count; ++i) {
  320.       attachments_with_format[2*i] = attachments[i];
  321.       attachments_with_format[2*i + 1] = format;
  322.    }
  323.  
  324.    buffer =
  325.       dri2_get_buffers_with_format(driDrawable,
  326.                                    width, height,
  327.                                    attachments_with_format, count,
  328.                                    out_count, loaderPrivate);
  329.  
  330.    free(attachments_with_format);
  331.  
  332.    return buffer;
  333. }
  334.  
  335. static void
  336. dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  337. {
  338.    (void) driDrawable;
  339.    (void) loaderPrivate;
  340. }
  341.  
  342. static EGLBoolean
  343. dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  344. {
  345.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  346.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  347.    __DRIbuffer buffer;
  348.    static bitmap_t bm;
  349.  
  350.    int i;
  351.  
  352.    if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  353.       if (dri2_surf->current)
  354.         _eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
  355.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  356.          if (dri2_surf->color_buffers[i].age > 0)
  357.             dri2_surf->color_buffers[i].age++;
  358.  
  359. #if 1
  360.  
  361.       if ( (dri2_surf->back != NULL) &&
  362.            (dri2_surf->back->bo != NULL))
  363.       {
  364.         struct gbm_dri_bo *bo;
  365.         bo = (struct gbm_dri_bo *)dri2_surf->back->bo;
  366.  
  367.         if(bm.width == 0)
  368.         {
  369. //            printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
  370. //                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
  371.  //                             bo->base.base.height, (int)bo->base.base.stride,
  372. //                              bo->base.base.format);
  373.  
  374.             bm.width      = bo->base.base.width;
  375.             bm.height     = bo->base.base.height;
  376.             bm.pitch      = (int)bo->base.base.stride;
  377.             bm.max_width  = bo->base.base.width;
  378.             bm.max_height = bo->base.base.height;
  379.             bm.flags      = HW_TEX_BLIT;
  380.  
  381.             if( blit_bitmap_from_handle(&bm, bo->base.base.handle.s32))
  382.             {
  383.                 printf("sna_bitmap_from_handle failed\n");
  384.             }
  385.         }
  386.         if( bm.handle != 0)
  387.         {
  388. //           printf("%s bo: %p handle: %d width: %d height: %d pitch %d format %x\n",
  389. //                __FUNCTION__, bo, bo->base.base.handle.s32, bo->base.base.width,
  390. //                              bo->base.base.height, (int)bo->base.base.stride,
  391. //                              bo->base.base.format);
  392.  
  393.             blit_set_bo_handle(&bm, bo->base.base.handle.s32);
  394.             blit_blit_tex(&bm, 0, 0, 5, 20, bm.width, bm.height, 0, 0);
  395.         }
  396.       }
  397. #endif
  398.  
  399.       dri2_surf->current = dri2_surf->back;
  400.       dri2_surf->current->age = 1;
  401.       dri2_surf->back = NULL;
  402.    }
  403.  
  404.    (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
  405.    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  406.  
  407.    return EGL_TRUE;
  408. }
  409.  
  410. static EGLint
  411. dri2_query_buffer_age(_EGLDriver *drv,
  412.                       _EGLDisplay *disp, _EGLSurface *surface)
  413. {
  414.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
  415.    __DRIbuffer buffer;
  416.  
  417.    if (get_back_bo(dri2_surf, &buffer) < 0) {
  418.       _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
  419.       return 0;
  420.    }
  421.  
  422.    return dri2_surf->back->age;
  423. }
  424.  
  425. static _EGLImage *
  426. dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
  427.                              EGLClientBuffer buffer, const EGLint *attr_list)
  428. {
  429.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  430.    struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *) buffer);
  431.    struct dri2_egl_image *dri2_img;
  432.  
  433.    dri2_img = malloc(sizeof *dri2_img);
  434.    if (!dri2_img) {
  435.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  436.       return NULL;
  437.    }
  438.  
  439.    if (!_eglInitImage(&dri2_img->base, disp)) {
  440.       free(dri2_img);
  441.       return NULL;
  442.    }
  443.  
  444.    dri2_img->dri_image = dri2_dpy->image->dupImage(dri_bo->image, dri2_img);
  445.    if (dri2_img->dri_image == NULL) {
  446.       free(dri2_img);
  447.       _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
  448.       return NULL;
  449.    }
  450.  
  451.    return &dri2_img->base;
  452. }
  453.  
  454. static _EGLImage *
  455. dri2_drm_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
  456.                           _EGLContext *ctx, EGLenum target,
  457.                           EGLClientBuffer buffer, const EGLint *attr_list)
  458. {
  459.    (void) drv;
  460.  
  461.    switch (target) {
  462.    case EGL_NATIVE_PIXMAP_KHR:
  463.       return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
  464.    default:
  465.       return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
  466.    }
  467. }
  468.  
  469. #if 0
  470. static int
  471. dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
  472. {
  473.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  474.  
  475.    return drmAuthMagic(dri2_dpy->fd, id);
  476. }
  477. #endif
  478.  
  479. EGLBoolean
  480. dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
  481. {
  482.    struct dri2_egl_display *dri2_dpy;
  483.    struct gbm_device *gbm;
  484.    void *lib;
  485.  
  486.    int fd = -1;
  487.    int i;
  488.  
  489.    dri2_dpy = calloc(1, sizeof *dri2_dpy);
  490.    if (!dri2_dpy)
  491.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  492.  
  493.    disp->DriverData = (void *) dri2_dpy;
  494.  
  495.    gbm = disp->PlatformDisplay;
  496.    if (gbm == NULL) {
  497.       fd = get_service("DISPLAY");
  498.       dri2_dpy->own_device = 1;
  499.       gbm = gbm_create_device(fd);
  500.       if (gbm == NULL)
  501.          return EGL_FALSE;
  502.    }
  503.  
  504.    if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
  505.       free(dri2_dpy);
  506.       return EGL_FALSE;
  507.    }
  508.  
  509.    dri2_dpy->gbm_dri = gbm_dri_device(gbm);
  510.    if (dri2_dpy->gbm_dri->base.type != GBM_DRM_DRIVER_TYPE_DRI) {
  511.       free(dri2_dpy);
  512.       return EGL_FALSE;
  513.    }
  514.  
  515.  
  516.    lib = load_library("intel-sna.drv");
  517.    if(lib)
  518.    {
  519.        blit_bitmap_from_handle = get_proc_address(lib,"sna_bitmap_from_handle");
  520.        blit_set_bo_handle = get_proc_address(lib,"sna_set_bo_handle");
  521.        blit_blit_tex = get_proc_address(lib,"sna_blit_tex");
  522.    }
  523.    else
  524.    {
  525.        lib = load_library("intel-uxa.drv");
  526.        if(lib)
  527.        {
  528.            blit_bitmap_from_handle = get_proc_address(lib,"uxa_bitmap_from_handle");
  529.            blit_set_bo_handle = get_proc_address(lib,"uxa_set_bo_handle");
  530.            blit_blit_tex = get_proc_address(lib,"uxa_blit_tex");
  531.        }
  532.        else return EGL_FALSE;
  533.    }
  534.  
  535.    dri2_dpy->fd = fd;
  536.    dri2_dpy->device_name = strdup("drm device"); //dri2_get_device_name_for_fd(dri2_dpy->fd);
  537.    dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
  538.  
  539.    dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
  540.    dri2_dpy->core = dri2_dpy->gbm_dri->core;
  541.    dri2_dpy->dri2 = dri2_dpy->gbm_dri->dri2;
  542.    dri2_dpy->image = dri2_dpy->gbm_dri->image;
  543.    dri2_dpy->flush = dri2_dpy->gbm_dri->flush;
  544.    dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
  545.  
  546.    dri2_dpy->gbm_dri->lookup_image = dri2_lookup_egl_image;
  547.    dri2_dpy->gbm_dri->lookup_user_data = disp;
  548.  
  549.    dri2_dpy->gbm_dri->get_buffers = dri2_get_buffers;
  550.    dri2_dpy->gbm_dri->flush_front_buffer = dri2_flush_front_buffer;
  551.    dri2_dpy->gbm_dri->get_buffers_with_format = dri2_get_buffers_with_format;
  552.  
  553.    dri2_dpy->gbm_dri->base.base.surface_lock_front_buffer = lock_front_buffer;
  554.    dri2_dpy->gbm_dri->base.base.surface_release_buffer = release_buffer;
  555.    dri2_dpy->gbm_dri->base.base.surface_has_free_buffers = has_free_buffers;
  556.  
  557.    dri2_setup_screen(disp);
  558.  
  559.    for (i = 0; dri2_dpy->driver_configs[i]; i++)
  560.       dri2_add_config(disp, dri2_dpy->driver_configs[i],
  561.                       i + 1, 0, EGL_WINDOW_BIT, NULL, NULL);
  562.  
  563.    drv->API.CreateWindowSurface = dri2_create_window_surface;
  564.    drv->API.DestroySurface = dri2_destroy_surface;
  565.    drv->API.SwapBuffers = dri2_swap_buffers;
  566.    drv->API.CreateImageKHR = dri2_drm_create_image_khr;
  567.    drv->API.QueryBufferAge = dri2_query_buffer_age;
  568.  
  569.    disp->Extensions.EXT_buffer_age = EGL_TRUE;
  570.  
  571. #ifdef HAVE_WAYLAND_PLATFORM
  572.    disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
  573. #endif
  574. //   dri2_dpy->authenticate = dri2_drm_authenticate;
  575.  
  576.    /* we're supporting EGL 1.4 */
  577.    disp->VersionMajor = 1;
  578.    disp->VersionMinor = 4;
  579.  
  580.    return EGL_TRUE;
  581. }
  582.