Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2011-2012 Intel Corporation
  3.  * Copyright © 2012 Collabora, Ltd.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19.  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20.  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21.  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Kristian Høgsberg <krh@bitplanet.net>
  27.  *    Benjamin Franzke <benjaminfranzke@googlemail.com>
  28.  */
  29.  
  30. #include <stdint.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <limits.h>
  34. #include <dlfcn.h>
  35. #include <errno.h>
  36. #include <unistd.h>
  37. #include <fcntl.h>
  38. #include <xf86drm.h>
  39. #include <sys/mman.h>
  40.  
  41. #include "egl_dri2.h"
  42. #include "egl_dri2_fallbacks.h"
  43. #include "loader.h"
  44.  
  45. #include <wayland-client.h>
  46. #include "wayland-drm-client-protocol.h"
  47.  
  48. enum wl_drm_format_flags {
  49.    HAS_ARGB8888 = 1,
  50.    HAS_XRGB8888 = 2,
  51.    HAS_RGB565 = 4,
  52. };
  53.  
  54. static EGLBoolean
  55. dri2_wl_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
  56.                       EGLint interval);
  57.  
  58. static void
  59. sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
  60. {
  61.    int *done = data;
  62.  
  63.    *done = 1;
  64.    wl_callback_destroy(callback);
  65. }
  66.  
  67. static const struct wl_callback_listener sync_listener = {
  68.    sync_callback
  69. };
  70.  
  71. static int
  72. roundtrip(struct dri2_egl_display *dri2_dpy)
  73. {
  74.    struct wl_callback *callback;
  75.    int done = 0, ret = 0;
  76.  
  77.    callback = wl_display_sync(dri2_dpy->wl_dpy);
  78.    wl_callback_add_listener(callback, &sync_listener, &done);
  79.    wl_proxy_set_queue((struct wl_proxy *) callback, dri2_dpy->wl_queue);
  80.    while (ret != -1 && !done)
  81.       ret = wl_display_dispatch_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
  82.  
  83.    if (!done)
  84.       wl_callback_destroy(callback);
  85.  
  86.    return ret;
  87. }
  88.  
  89. static void
  90. wl_buffer_release(void *data, struct wl_buffer *buffer)
  91. {
  92.    struct dri2_egl_surface *dri2_surf = data;
  93.    int i;
  94.  
  95.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); ++i)
  96.       if (dri2_surf->color_buffers[i].wl_buffer == buffer)
  97.          break;
  98.  
  99.    if (i == ARRAY_SIZE(dri2_surf->color_buffers)) {
  100.       wl_buffer_destroy(buffer);
  101.       return;
  102.    }
  103.  
  104.    dri2_surf->color_buffers[i].locked = 0;
  105. }
  106.  
  107. static struct wl_buffer_listener wl_buffer_listener = {
  108.    wl_buffer_release
  109. };
  110.  
  111. static void
  112. resize_callback(struct wl_egl_window *wl_win, void *data)
  113. {
  114.    struct dri2_egl_surface *dri2_surf = data;
  115.    struct dri2_egl_display *dri2_dpy =
  116.       dri2_egl_display(dri2_surf->base.Resource.Display);
  117.  
  118.    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  119. }
  120.  
  121. /**
  122.  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  123.  */
  124. static _EGLSurface *
  125. dri2_wl_create_surface(_EGLDriver *drv, _EGLDisplay *disp,
  126.                        _EGLConfig *conf, void *native_window,
  127.                        const EGLint *attrib_list)
  128. {
  129.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  130.    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  131.    struct wl_egl_window *window = native_window;
  132.    struct dri2_egl_surface *dri2_surf;
  133.  
  134.    (void) drv;
  135.  
  136.    dri2_surf = calloc(1, sizeof *dri2_surf);
  137.    if (!dri2_surf) {
  138.       _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
  139.       return NULL;
  140.    }
  141.    
  142.    if (!_eglInitSurface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list))
  143.       goto cleanup_surf;
  144.  
  145.    if (conf->RedSize == 5)
  146.       dri2_surf->format = WL_DRM_FORMAT_RGB565;
  147.    else if (conf->AlphaSize == 0)
  148.       dri2_surf->format = WL_DRM_FORMAT_XRGB8888;
  149.    else
  150.       dri2_surf->format = WL_DRM_FORMAT_ARGB8888;
  151.  
  152.    dri2_surf->wl_win = window;
  153.  
  154.    dri2_surf->wl_win->private = dri2_surf;
  155.    dri2_surf->wl_win->resize_callback = resize_callback;
  156.  
  157.    dri2_surf->base.Width =  -1;
  158.    dri2_surf->base.Height = -1;
  159.  
  160.    dri2_surf->dri_drawable =
  161.       (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
  162.                                             dri2_conf->dri_double_config,
  163.                                             dri2_surf);
  164.    if (dri2_surf->dri_drawable == NULL) {
  165.       _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
  166.       goto cleanup_dri_drawable;
  167.    }
  168.  
  169.    return &dri2_surf->base;
  170.  
  171.  cleanup_dri_drawable:
  172.    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
  173.  cleanup_surf:
  174.    free(dri2_surf);
  175.  
  176.    return NULL;
  177. }
  178.  
  179. /**
  180.  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  181.  */
  182. static _EGLSurface *
  183. dri2_wl_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
  184.                               _EGLConfig *conf, void *native_window,
  185.                               const EGLint *attrib_list)
  186. {
  187.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  188.    _EGLSurface *surf;
  189.  
  190.    surf = dri2_wl_create_surface(drv, disp, conf, native_window, attrib_list);
  191.  
  192.    if (surf != NULL)
  193.       dri2_wl_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
  194.  
  195.    return surf;
  196. }
  197.  
  198. static _EGLSurface *
  199. dri2_wl_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
  200.                               _EGLConfig *conf, void *native_window,
  201.                               const EGLint *attrib_list)
  202. {
  203.    /* From the EGL_EXT_platform_wayland spec, version 3:
  204.     *
  205.     *   It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
  206.     *   that belongs to Wayland. Any such call fails and generates
  207.     *   EGL_BAD_PARAMETER.
  208.     */
  209.    _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on "
  210.              "Wayland");
  211.    return NULL;
  212. }
  213.  
  214. /**
  215.  * Called via eglDestroySurface(), drv->API.DestroySurface().
  216.  */
  217. static EGLBoolean
  218. dri2_wl_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  219. {
  220.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  221.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
  222.    int i;
  223.  
  224.    (void) drv;
  225.  
  226.    if (!_eglPutSurface(surf))
  227.       return EGL_TRUE;
  228.  
  229.    (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
  230.  
  231.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  232.       if (dri2_surf->color_buffers[i].wl_buffer)
  233.          wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
  234.       if (dri2_surf->color_buffers[i].dri_image)
  235.          dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
  236.       if (dri2_surf->color_buffers[i].linear_copy)
  237.          dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
  238.       if (dri2_surf->color_buffers[i].data)
  239.          munmap(dri2_surf->color_buffers[i].data,
  240.                 dri2_surf->color_buffers[i].data_size);
  241.    }
  242.  
  243.    if (dri2_dpy->dri2) {
  244.       for (i = 0; i < __DRI_BUFFER_COUNT; i++)
  245.          if (dri2_surf->dri_buffers[i] &&
  246.              dri2_surf->dri_buffers[i]->attachment != __DRI_BUFFER_BACK_LEFT)
  247.             dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
  248.                                           dri2_surf->dri_buffers[i]);
  249.    }
  250.  
  251.    if (dri2_surf->throttle_callback)
  252.       wl_callback_destroy(dri2_surf->throttle_callback);
  253.  
  254.    dri2_surf->wl_win->private = NULL;
  255.    dri2_surf->wl_win->resize_callback = NULL;
  256.  
  257.    free(surf);
  258.  
  259.    return EGL_TRUE;
  260. }
  261.  
  262. static void
  263. dri2_wl_release_buffers(struct dri2_egl_surface *dri2_surf)
  264. {
  265.    struct dri2_egl_display *dri2_dpy =
  266.       dri2_egl_display(dri2_surf->base.Resource.Display);
  267.    int i;
  268.  
  269.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  270.       if (dri2_surf->color_buffers[i].wl_buffer &&
  271.           !dri2_surf->color_buffers[i].locked)
  272.          wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
  273.       if (dri2_surf->color_buffers[i].dri_image)
  274.          dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
  275.       if (dri2_surf->color_buffers[i].linear_copy)
  276.          dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
  277.       if (dri2_surf->color_buffers[i].data)
  278.          munmap(dri2_surf->color_buffers[i].data,
  279.                 dri2_surf->color_buffers[i].data_size);
  280.  
  281.       dri2_surf->color_buffers[i].wl_buffer = NULL;
  282.       dri2_surf->color_buffers[i].dri_image = NULL;
  283.       dri2_surf->color_buffers[i].linear_copy = NULL;
  284.       dri2_surf->color_buffers[i].data = NULL;
  285.       dri2_surf->color_buffers[i].locked = 0;
  286.    }
  287.  
  288.    if (dri2_dpy->dri2) {
  289.       for (i = 0; i < __DRI_BUFFER_COUNT; i++)
  290.          if (dri2_surf->dri_buffers[i] &&
  291.              dri2_surf->dri_buffers[i]->attachment != __DRI_BUFFER_BACK_LEFT)
  292.             dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen,
  293.                                           dri2_surf->dri_buffers[i]);
  294.    }
  295. }
  296.  
  297. static int
  298. get_back_bo(struct dri2_egl_surface *dri2_surf)
  299. {
  300.    struct dri2_egl_display *dri2_dpy =
  301.       dri2_egl_display(dri2_surf->base.Resource.Display);
  302.    int i;
  303.    unsigned int dri_image_format;
  304.  
  305.    /* currently supports three WL DRM formats,
  306.     * WL_DRM_FORMAT_ARGB8888, WL_DRM_FORMAT_XRGB8888,
  307.     * and WL_DRM_FORMAT_RGB565
  308.     */
  309.    switch (dri2_surf->format) {
  310.    case WL_DRM_FORMAT_ARGB8888:
  311.       dri_image_format = __DRI_IMAGE_FORMAT_ARGB8888;
  312.       break;
  313.    case WL_DRM_FORMAT_XRGB8888:
  314.       dri_image_format = __DRI_IMAGE_FORMAT_XRGB8888;
  315.       break;
  316.    case WL_DRM_FORMAT_RGB565:
  317.       dri_image_format = __DRI_IMAGE_FORMAT_RGB565;
  318.       break;
  319.    default:
  320.       /* format is not supported */
  321.       return -1;
  322.    }
  323.  
  324.    /* We always want to throttle to some event (either a frame callback or
  325.     * a sync request) after the commit so that we can be sure the
  326.     * compositor has had a chance to handle it and send us a release event
  327.     * before we look for a free buffer */
  328.    while (dri2_surf->throttle_callback != NULL)
  329.       if (wl_display_dispatch_queue(dri2_dpy->wl_dpy,
  330.                                     dri2_dpy->wl_queue) == -1)
  331.          return -1;
  332.  
  333.    if (dri2_surf->back == NULL) {
  334.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  335.          /* Get an unlocked buffer, preferrably one with a dri_buffer
  336.           * already allocated. */
  337.          if (dri2_surf->color_buffers[i].locked)
  338.             continue;
  339.          if (dri2_surf->back == NULL)
  340.             dri2_surf->back = &dri2_surf->color_buffers[i];
  341.          else if (dri2_surf->back->dri_image == NULL)
  342.             dri2_surf->back = &dri2_surf->color_buffers[i];
  343.       }
  344.    }
  345.  
  346.    if (dri2_surf->back == NULL)
  347.       return -1;
  348.  
  349.    if (dri2_dpy->is_different_gpu &&
  350.        dri2_surf->back->linear_copy == NULL) {
  351.        dri2_surf->back->linear_copy =
  352.           dri2_dpy->image->createImage(dri2_dpy->dri_screen,
  353.                                       dri2_surf->base.Width,
  354.                                       dri2_surf->base.Height,
  355.                                       dri_image_format,
  356.                                       __DRI_IMAGE_USE_SHARE |
  357.                                       __DRI_IMAGE_USE_LINEAR,
  358.                                       NULL);
  359.       if (dri2_surf->back->linear_copy == NULL)
  360.           return -1;
  361.    }
  362.  
  363.    if (dri2_surf->back->dri_image == NULL) {
  364.       dri2_surf->back->dri_image =
  365.          dri2_dpy->image->createImage(dri2_dpy->dri_screen,
  366.                                       dri2_surf->base.Width,
  367.                                       dri2_surf->base.Height,
  368.                                       dri_image_format,
  369.                                       dri2_dpy->is_different_gpu ?
  370.                                          0 : __DRI_IMAGE_USE_SHARE,
  371.                                       NULL);
  372.       dri2_surf->back->age = 0;
  373.    }
  374.    if (dri2_surf->back->dri_image == NULL)
  375.       return -1;
  376.  
  377.    dri2_surf->back->locked = 1;
  378.  
  379.    return 0;
  380. }
  381.  
  382.  
  383. static void
  384. back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
  385. {
  386.    struct dri2_egl_display *dri2_dpy =
  387.       dri2_egl_display(dri2_surf->base.Resource.Display);
  388.    __DRIimage *image;
  389.    int name, pitch;
  390.  
  391.    image = dri2_surf->back->dri_image;
  392.  
  393.    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
  394.    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  395.  
  396.    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
  397.    buffer->name = name;
  398.    buffer->pitch = pitch;
  399.    buffer->cpp = 4;
  400.    buffer->flags = 0;
  401. }
  402.  
  403. static int
  404. get_aux_bo(struct dri2_egl_surface *dri2_surf,
  405.            unsigned int attachment, unsigned int format, __DRIbuffer *buffer)
  406. {
  407.    struct dri2_egl_display *dri2_dpy =
  408.       dri2_egl_display(dri2_surf->base.Resource.Display);
  409.    __DRIbuffer *b = dri2_surf->dri_buffers[attachment];
  410.  
  411.    if (b == NULL) {
  412.       b = dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen,
  413.                                          attachment, format,
  414.                                          dri2_surf->base.Width,
  415.                                          dri2_surf->base.Height);
  416.       dri2_surf->dri_buffers[attachment] = b;
  417.    }
  418.    if (b == NULL)
  419.       return -1;
  420.  
  421.    memcpy(buffer, b, sizeof *buffer);
  422.  
  423.    return 0;
  424. }
  425.  
  426. static int
  427. update_buffers(struct dri2_egl_surface *dri2_surf)
  428. {
  429.    struct dri2_egl_display *dri2_dpy =
  430.       dri2_egl_display(dri2_surf->base.Resource.Display);
  431.    int i;
  432.  
  433.    if (dri2_surf->base.Width != dri2_surf->wl_win->width ||
  434.        dri2_surf->base.Height != dri2_surf->wl_win->height) {
  435.  
  436.       dri2_wl_release_buffers(dri2_surf);
  437.  
  438.       dri2_surf->base.Width  = dri2_surf->wl_win->width;
  439.       dri2_surf->base.Height = dri2_surf->wl_win->height;
  440.       dri2_surf->dx = dri2_surf->wl_win->dx;
  441.       dri2_surf->dy = dri2_surf->wl_win->dy;
  442.    }
  443.  
  444.    if (get_back_bo(dri2_surf) < 0) {
  445.       _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
  446.       return -1;
  447.    }
  448.  
  449.    /* If we have an extra unlocked buffer at this point, we had to do triple
  450.     * buffering for a while, but now can go back to just double buffering.
  451.     * That means we can free any unlocked buffer now. */
  452.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  453.       if (!dri2_surf->color_buffers[i].locked &&
  454.           dri2_surf->color_buffers[i].wl_buffer) {
  455.          wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
  456.          dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
  457.          if (dri2_dpy->is_different_gpu)
  458.             dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
  459.          dri2_surf->color_buffers[i].wl_buffer = NULL;
  460.          dri2_surf->color_buffers[i].dri_image = NULL;
  461.          dri2_surf->color_buffers[i].linear_copy = NULL;
  462.       }
  463.    }
  464.  
  465.    return 0;
  466. }
  467.  
  468. static __DRIbuffer *
  469. dri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable,
  470.                                 int *width, int *height,
  471.                                 unsigned int *attachments, int count,
  472.                                 int *out_count, void *loaderPrivate)
  473. {
  474.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  475.    int i, j;
  476.  
  477.    if (update_buffers(dri2_surf) < 0)
  478.       return NULL;
  479.  
  480.    for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
  481.       switch (attachments[i]) {
  482.       case __DRI_BUFFER_BACK_LEFT:
  483.          back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
  484.          break;
  485.       default:
  486.          if (get_aux_bo(dri2_surf, attachments[i], attachments[i + 1],
  487.                         &dri2_surf->buffers[j]) < 0) {
  488.             _eglError(EGL_BAD_ALLOC, "failed to allocate aux buffer");
  489.             return NULL;
  490.          }
  491.          break;
  492.       }
  493.    }
  494.  
  495.    *out_count = j;
  496.    if (j == 0)
  497.            return NULL;
  498.  
  499.    *width = dri2_surf->base.Width;
  500.    *height = dri2_surf->base.Height;
  501.  
  502.    return dri2_surf->buffers;
  503. }
  504.  
  505. static __DRIbuffer *
  506. dri2_wl_get_buffers(__DRIdrawable * driDrawable,
  507.                     int *width, int *height,
  508.                     unsigned int *attachments, int count,
  509.                     int *out_count, void *loaderPrivate)
  510. {
  511.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  512.    unsigned int *attachments_with_format;
  513.    __DRIbuffer *buffer;
  514.    unsigned int bpp;
  515.  
  516.    int i;
  517.  
  518.    switch (dri2_surf->format) {
  519.    case WL_DRM_FORMAT_ARGB8888:
  520.    case WL_DRM_FORMAT_XRGB8888:
  521.       bpp = 32;
  522.       break;
  523.    case WL_DRM_FORMAT_RGB565:
  524.       bpp = 16;
  525.       break;
  526.    default:
  527.       /* format is not supported */
  528.       return NULL;
  529.    }
  530.  
  531.    attachments_with_format = calloc(count, 2 * sizeof(unsigned int));
  532.    if (!attachments_with_format) {
  533.       *out_count = 0;
  534.       return NULL;
  535.    }
  536.  
  537.    for (i = 0; i < count; ++i) {
  538.       attachments_with_format[2*i] = attachments[i];
  539.       attachments_with_format[2*i + 1] = bpp;
  540.    }
  541.  
  542.    buffer =
  543.       dri2_wl_get_buffers_with_format(driDrawable,
  544.                                       width, height,
  545.                                       attachments_with_format, count,
  546.                                       out_count, loaderPrivate);
  547.  
  548.    free(attachments_with_format);
  549.  
  550.    return buffer;
  551. }
  552.  
  553. static int
  554. image_get_buffers(__DRIdrawable *driDrawable,
  555.                   unsigned int format,
  556.                   uint32_t *stamp,
  557.                   void *loaderPrivate,
  558.                   uint32_t buffer_mask,
  559.                   struct __DRIimageList *buffers)
  560. {
  561.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  562.  
  563.    if (update_buffers(dri2_surf) < 0)
  564.       return 0;
  565.  
  566.    buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
  567.    buffers->back = dri2_surf->back->dri_image;
  568.  
  569.    return 1;
  570. }
  571.  
  572. static void
  573. dri2_wl_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  574. {
  575.    (void) driDrawable;
  576.    (void) loaderPrivate;
  577. }
  578.  
  579. static const __DRIimageLoaderExtension image_loader_extension = {
  580.    .base = { __DRI_IMAGE_LOADER, 1 },
  581.  
  582.    .getBuffers          = image_get_buffers,
  583.    .flushFrontBuffer    = dri2_wl_flush_front_buffer,
  584. };
  585.  
  586. static void
  587. wayland_throttle_callback(void *data,
  588.                           struct wl_callback *callback,
  589.                           uint32_t time)
  590. {
  591.    struct dri2_egl_surface *dri2_surf = data;
  592.  
  593.    dri2_surf->throttle_callback = NULL;
  594.    wl_callback_destroy(callback);
  595. }
  596.  
  597. static const struct wl_callback_listener throttle_listener = {
  598.    wayland_throttle_callback
  599. };
  600.  
  601. static void
  602. create_wl_buffer(struct dri2_egl_surface *dri2_surf)
  603. {
  604.    struct dri2_egl_display *dri2_dpy =
  605.       dri2_egl_display(dri2_surf->base.Resource.Display);
  606.    __DRIimage *image;
  607.    int fd, stride, name;
  608.  
  609.    if (dri2_surf->current->wl_buffer != NULL)
  610.       return;
  611.  
  612.    if (dri2_dpy->is_different_gpu) {
  613.       image = dri2_surf->current->linear_copy;
  614.    } else {
  615.       image = dri2_surf->current->dri_image;
  616.    }
  617.    if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
  618.       dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
  619.       dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
  620.  
  621.       dri2_surf->current->wl_buffer =
  622.          wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
  623.                                     fd,
  624.                                     dri2_surf->base.Width,
  625.                                     dri2_surf->base.Height,
  626.                                     dri2_surf->format,
  627.                                     0, stride,
  628.                                     0, 0,
  629.                                     0, 0);
  630.       close(fd);
  631.    } else {
  632.       dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
  633.       dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
  634.  
  635.       dri2_surf->current->wl_buffer =
  636.          wl_drm_create_buffer(dri2_dpy->wl_drm,
  637.                               name,
  638.                               dri2_surf->base.Width,
  639.                               dri2_surf->base.Height,
  640.                               stride,
  641.                               dri2_surf->format);
  642.    }
  643.  
  644.    wl_proxy_set_queue((struct wl_proxy *) dri2_surf->current->wl_buffer,
  645.                       dri2_dpy->wl_queue);
  646.    wl_buffer_add_listener(dri2_surf->current->wl_buffer,
  647.                           &wl_buffer_listener, dri2_surf);
  648. }
  649.  
  650. /**
  651.  * Called via eglSwapBuffers(), drv->API.SwapBuffers().
  652.  */
  653. static EGLBoolean
  654. dri2_wl_swap_buffers_with_damage(_EGLDriver *drv,
  655.                                  _EGLDisplay *disp,
  656.                                  _EGLSurface *draw,
  657.                                  const EGLint *rects,
  658.                                  EGLint n_rects)
  659. {
  660.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  661.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  662.    int i;
  663.  
  664.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
  665.       if (dri2_surf->color_buffers[i].age > 0)
  666.          dri2_surf->color_buffers[i].age++;
  667.  
  668.    /* Make sure we have a back buffer in case we're swapping without ever
  669.     * rendering. */
  670.    if (get_back_bo(dri2_surf) < 0) {
  671.       _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
  672.       return EGL_FALSE;
  673.    }
  674.  
  675.    if (draw->SwapInterval > 0) {
  676.       dri2_surf->throttle_callback =
  677.          wl_surface_frame(dri2_surf->wl_win->surface);
  678.       wl_callback_add_listener(dri2_surf->throttle_callback,
  679.                                &throttle_listener, dri2_surf);
  680.       wl_proxy_set_queue((struct wl_proxy *) dri2_surf->throttle_callback,
  681.                          dri2_dpy->wl_queue);
  682.    }
  683.  
  684.    dri2_surf->back->age = 1;
  685.    dri2_surf->current = dri2_surf->back;
  686.    dri2_surf->back = NULL;
  687.  
  688.    create_wl_buffer(dri2_surf);
  689.  
  690.    wl_surface_attach(dri2_surf->wl_win->surface,
  691.                      dri2_surf->current->wl_buffer,
  692.                      dri2_surf->dx, dri2_surf->dy);
  693.  
  694.    dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
  695.    dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
  696.    /* reset resize growing parameters */
  697.    dri2_surf->dx = 0;
  698.    dri2_surf->dy = 0;
  699.  
  700.    if (n_rects == 0) {
  701.       wl_surface_damage(dri2_surf->wl_win->surface,
  702.                         0, 0, INT32_MAX, INT32_MAX);
  703.    } else {
  704.       for (i = 0; i < n_rects; i++) {
  705.          const int *rect = &rects[i * 4];
  706.          wl_surface_damage(dri2_surf->wl_win->surface,
  707.                            rect[0],
  708.                            dri2_surf->base.Height - rect[1] - rect[3],
  709.                            rect[2], rect[3]);
  710.       }
  711.    }
  712.  
  713.    if (dri2_dpy->is_different_gpu) {
  714.       _EGLContext *ctx = _eglGetCurrentContext();
  715.       struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
  716.       dri2_dpy->image->blitImage(dri2_ctx->dri_context,
  717.                                  dri2_surf->current->linear_copy,
  718.                                  dri2_surf->current->dri_image,
  719.                                  0, 0, dri2_surf->base.Width,
  720.                                  dri2_surf->base.Height,
  721.                                  0, 0, dri2_surf->base.Width,
  722.                                  dri2_surf->base.Height, 0);
  723.    }
  724.  
  725.    dri2_flush_drawable_for_swapbuffers(disp, draw);
  726.    (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
  727.  
  728.    wl_surface_commit(dri2_surf->wl_win->surface);
  729.  
  730.    /* If we're not waiting for a frame callback then we'll at least throttle
  731.     * to a sync callback so that we always give a chance for the compositor to
  732.     * handle the commit and send a release event before checking for a free
  733.     * buffer */
  734.    if (dri2_surf->throttle_callback == NULL) {
  735.       dri2_surf->throttle_callback = wl_display_sync(dri2_dpy->wl_dpy);
  736.       wl_callback_add_listener(dri2_surf->throttle_callback,
  737.                                &throttle_listener, dri2_surf);
  738.       wl_proxy_set_queue((struct wl_proxy *) dri2_surf->throttle_callback,
  739.                          dri2_dpy->wl_queue);
  740.    }
  741.  
  742.    wl_display_flush(dri2_dpy->wl_dpy);
  743.  
  744.    return EGL_TRUE;
  745. }
  746.  
  747. static EGLint
  748. dri2_wl_query_buffer_age(_EGLDriver *drv,
  749.                          _EGLDisplay *disp, _EGLSurface *surface)
  750. {
  751.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
  752.  
  753.    if (get_back_bo(dri2_surf) < 0) {
  754.       _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
  755.       return 0;
  756.    }
  757.  
  758.    return dri2_surf->back->age;
  759. }
  760.  
  761. static EGLBoolean
  762. dri2_wl_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  763. {
  764.    return dri2_wl_swap_buffers_with_damage (drv, disp, draw, NULL, 0);
  765. }
  766.  
  767. static struct wl_buffer *
  768. dri2_wl_create_wayland_buffer_from_image(_EGLDriver *drv,
  769.                                           _EGLDisplay *disp,
  770.                                           _EGLImage *img)
  771. {
  772.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  773.    struct dri2_egl_image *dri2_img = dri2_egl_image(img);
  774.    __DRIimage *image = dri2_img->dri_image;
  775.    struct wl_buffer *buffer;
  776.    int width, height, format, pitch;
  777.    enum wl_drm_format wl_format;
  778.  
  779.    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
  780.  
  781.    switch (format) {
  782.    case __DRI_IMAGE_FORMAT_ARGB8888:
  783.       if (!(dri2_dpy->formats & HAS_ARGB8888))
  784.          goto bad_format;
  785.       wl_format = WL_DRM_FORMAT_ARGB8888;
  786.       break;
  787.    case __DRI_IMAGE_FORMAT_XRGB8888:
  788.       if (!(dri2_dpy->formats & HAS_XRGB8888))
  789.          goto bad_format;
  790.       wl_format = WL_DRM_FORMAT_XRGB8888;
  791.       break;
  792.    default:
  793.       goto bad_format;
  794.    }
  795.  
  796.    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
  797.    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, &height);
  798.    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  799.  
  800.    if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
  801.       int fd;
  802.  
  803.       dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
  804.  
  805.       buffer =
  806.          wl_drm_create_prime_buffer(dri2_dpy->wl_drm,
  807.                                     fd,
  808.                                     width, height,
  809.                                     wl_format,
  810.                                     0, pitch,
  811.                                     0, 0,
  812.                                     0, 0);
  813.  
  814.       close(fd);
  815.    } else {
  816.       int name;
  817.  
  818.       dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
  819.  
  820.       buffer =
  821.          wl_drm_create_buffer(dri2_dpy->wl_drm,
  822.                               name,
  823.                               width, height,
  824.                               pitch,
  825.                               wl_format);
  826.    }
  827.  
  828.    /* The buffer object will have been created with our internal event queue
  829.     * because it is using the wl_drm object as a proxy factory. We want the
  830.     * buffer to be used by the application so we'll reset it to the display's
  831.     * default event queue */
  832.    if (buffer)
  833.       wl_proxy_set_queue((struct wl_proxy *) buffer, NULL);
  834.  
  835.    return buffer;
  836.  
  837. bad_format:
  838.    _eglError(EGL_BAD_MATCH, "unsupported image format");
  839.    return NULL;
  840. }
  841.  
  842. static char
  843. is_fd_render_node(int fd)
  844. {
  845.    struct stat render;
  846.  
  847.    if (fstat(fd, &render))
  848.       return 0;
  849.  
  850.    if (!S_ISCHR(render.st_mode))
  851.       return 0;
  852.  
  853.    if (render.st_rdev & 0x80)
  854.       return 1;
  855.    return 0;
  856. }
  857.  
  858. static int
  859. dri2_wl_authenticate(_EGLDisplay *disp, uint32_t id)
  860. {
  861.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  862.    int ret = 0;
  863.  
  864.    if (dri2_dpy->is_render_node) {
  865.       _eglLog(_EGL_WARNING, "wayland-egl: client asks server to "
  866.                             "authenticate for render-nodes");
  867.       return 0;
  868.    }
  869.    dri2_dpy->authenticated = 0;
  870.  
  871.    wl_drm_authenticate(dri2_dpy->wl_drm, id);
  872.    if (roundtrip(dri2_dpy) < 0)
  873.       ret = -1;
  874.  
  875.    if (!dri2_dpy->authenticated)
  876.       ret = -1;
  877.  
  878.    /* reset authenticated */
  879.    dri2_dpy->authenticated = 1;
  880.  
  881.    return ret;
  882. }
  883.  
  884. static void
  885. drm_handle_device(void *data, struct wl_drm *drm, const char *device)
  886. {
  887.    struct dri2_egl_display *dri2_dpy = data;
  888.    drm_magic_t magic;
  889.  
  890.    dri2_dpy->device_name = strdup(device);
  891.    if (!dri2_dpy->device_name)
  892.       return;
  893.  
  894. #ifdef O_CLOEXEC
  895.    dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
  896.    if (dri2_dpy->fd == -1 && errno == EINVAL)
  897. #endif
  898.    {
  899.       dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
  900.       if (dri2_dpy->fd != -1)
  901.          fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
  902.             FD_CLOEXEC);
  903.    }
  904.    if (dri2_dpy->fd == -1) {
  905.       _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
  906.               dri2_dpy->device_name, strerror(errno));
  907.       return;
  908.    }
  909.  
  910.    if (is_fd_render_node(dri2_dpy->fd)) {
  911.       dri2_dpy->authenticated = 1;
  912.    } else {
  913.       drmGetMagic(dri2_dpy->fd, &magic);
  914.       wl_drm_authenticate(dri2_dpy->wl_drm, magic);
  915.    }
  916. }
  917.  
  918. static void
  919. drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
  920. {
  921.    struct dri2_egl_display *dri2_dpy = data;
  922.  
  923.    switch (format) {
  924.    case WL_DRM_FORMAT_ARGB8888:
  925.       dri2_dpy->formats |= HAS_ARGB8888;
  926.       break;
  927.    case WL_DRM_FORMAT_XRGB8888:
  928.       dri2_dpy->formats |= HAS_XRGB8888;
  929.       break;
  930.    case WL_DRM_FORMAT_RGB565:
  931.       dri2_dpy->formats |= HAS_RGB565;
  932.       break;
  933.    }
  934. }
  935.  
  936. static void
  937. drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
  938. {
  939.    struct dri2_egl_display *dri2_dpy = data;
  940.  
  941.    dri2_dpy->capabilities = value;
  942. }
  943.  
  944. static void
  945. drm_handle_authenticated(void *data, struct wl_drm *drm)
  946. {
  947.    struct dri2_egl_display *dri2_dpy = data;
  948.  
  949.    dri2_dpy->authenticated = 1;
  950. }
  951.  
  952. static const struct wl_drm_listener drm_listener = {
  953.         drm_handle_device,
  954.         drm_handle_format,
  955.         drm_handle_authenticated,
  956.         drm_handle_capabilities
  957. };
  958.  
  959. static void
  960. registry_handle_global_drm(void *data, struct wl_registry *registry, uint32_t name,
  961.                        const char *interface, uint32_t version)
  962. {
  963.    struct dri2_egl_display *dri2_dpy = data;
  964.  
  965.    if (version > 1)
  966.       version = 2;
  967.    if (strcmp(interface, "wl_drm") == 0) {
  968.       dri2_dpy->wl_drm =
  969.          wl_registry_bind(registry, name, &wl_drm_interface, version);
  970.       wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
  971.    }
  972. }
  973.  
  974. static void
  975. registry_handle_global_remove(void *data, struct wl_registry *registry,
  976.                               uint32_t name)
  977. {
  978. }
  979.  
  980. static const struct wl_registry_listener registry_listener_drm = {
  981.    registry_handle_global_drm,
  982.    registry_handle_global_remove
  983. };
  984.  
  985. static EGLBoolean
  986. dri2_wl_swap_interval(_EGLDriver *drv,
  987.                    _EGLDisplay *disp,
  988.                    _EGLSurface *surf,
  989.                    EGLint interval)
  990. {
  991.    if (interval > surf->Config->MaxSwapInterval)
  992.       interval = surf->Config->MaxSwapInterval;
  993.    else if (interval < surf->Config->MinSwapInterval)
  994.       interval = surf->Config->MinSwapInterval;
  995.  
  996.    surf->SwapInterval = interval;
  997.  
  998.    return EGL_TRUE;
  999. }
  1000.  
  1001. static void
  1002. dri2_wl_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
  1003. {
  1004.    GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
  1005.  
  1006.    /* We can't use values greater than 1 on Wayland because we are using the
  1007.     * frame callback to synchronise the frame and the only way we be sure to
  1008.     * get a frame callback is to attach a new buffer. Therefore we can't just
  1009.     * sit drawing nothing to wait until the next ‘n’ frame callbacks */
  1010.  
  1011.    if (dri2_dpy->config)
  1012.       dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
  1013.                                      "vblank_mode", &vblank_mode);
  1014.    switch (vblank_mode) {
  1015.    case DRI_CONF_VBLANK_NEVER:
  1016.       dri2_dpy->min_swap_interval = 0;
  1017.       dri2_dpy->max_swap_interval = 0;
  1018.       dri2_dpy->default_swap_interval = 0;
  1019.       break;
  1020.    case DRI_CONF_VBLANK_ALWAYS_SYNC:
  1021.       dri2_dpy->min_swap_interval = 1;
  1022.       dri2_dpy->max_swap_interval = 1;
  1023.       dri2_dpy->default_swap_interval = 1;
  1024.       break;
  1025.    case DRI_CONF_VBLANK_DEF_INTERVAL_0:
  1026.       dri2_dpy->min_swap_interval = 0;
  1027.       dri2_dpy->max_swap_interval = 1;
  1028.       dri2_dpy->default_swap_interval = 0;
  1029.       break;
  1030.    default:
  1031.    case DRI_CONF_VBLANK_DEF_INTERVAL_1:
  1032.       dri2_dpy->min_swap_interval = 0;
  1033.       dri2_dpy->max_swap_interval = 1;
  1034.       dri2_dpy->default_swap_interval = 1;
  1035.       break;
  1036.    }
  1037. }
  1038.  
  1039. static struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
  1040.    .authenticate = dri2_wl_authenticate,
  1041.    .create_window_surface = dri2_wl_create_window_surface,
  1042.    .create_pixmap_surface = dri2_wl_create_pixmap_surface,
  1043.    .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
  1044.    .destroy_surface = dri2_wl_destroy_surface,
  1045.    .create_image = dri2_create_image_khr,
  1046.    .swap_interval = dri2_wl_swap_interval,
  1047.    .swap_buffers = dri2_wl_swap_buffers,
  1048.    .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage,
  1049.    .swap_buffers_region = dri2_fallback_swap_buffers_region,
  1050.    .post_sub_buffer = dri2_fallback_post_sub_buffer,
  1051.    .copy_buffers = dri2_fallback_copy_buffers,
  1052.    .query_buffer_age = dri2_wl_query_buffer_age,
  1053.    .create_wayland_buffer_from_image = dri2_wl_create_wayland_buffer_from_image,
  1054.    .get_sync_values = dri2_fallback_get_sync_values,
  1055. };
  1056.  
  1057. static EGLBoolean
  1058. dri2_initialize_wayland_drm(_EGLDriver *drv, _EGLDisplay *disp)
  1059. {
  1060.    struct dri2_egl_display *dri2_dpy;
  1061.    const __DRIconfig *config;
  1062.    uint32_t types;
  1063.    int i;
  1064.    static const unsigned int argb_masks[4] =
  1065.       { 0xff0000, 0xff00, 0xff, 0xff000000 };
  1066.    static const unsigned int rgb_masks[4] = { 0xff0000, 0xff00, 0xff, 0 };
  1067.    static const unsigned int rgb565_masks[4] = { 0xf800, 0x07e0, 0x001f, 0 };
  1068.  
  1069.    loader_set_logger(_eglLog);
  1070.  
  1071.    dri2_dpy = calloc(1, sizeof *dri2_dpy);
  1072.    if (!dri2_dpy)
  1073.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  1074.  
  1075.    disp->DriverData = (void *) dri2_dpy;
  1076.    if (disp->PlatformDisplay == NULL) {
  1077.       dri2_dpy->wl_dpy = wl_display_connect(NULL);
  1078.       if (dri2_dpy->wl_dpy == NULL)
  1079.          goto cleanup_dpy;
  1080.       dri2_dpy->own_device = 1;
  1081.    } else {
  1082.       dri2_dpy->wl_dpy = disp->PlatformDisplay;
  1083.    }
  1084.  
  1085.    dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
  1086.  
  1087.    if (dri2_dpy->own_device)
  1088.       wl_display_dispatch_pending(dri2_dpy->wl_dpy);
  1089.  
  1090.    dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy);
  1091.    wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_registry,
  1092.                       dri2_dpy->wl_queue);
  1093.    wl_registry_add_listener(dri2_dpy->wl_registry,
  1094.                             &registry_listener_drm, dri2_dpy);
  1095.    if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_drm == NULL)
  1096.       goto cleanup_registry;
  1097.  
  1098.    if (roundtrip(dri2_dpy) < 0 || dri2_dpy->fd == -1)
  1099.       goto cleanup_drm;
  1100.  
  1101.    if (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated)
  1102.       goto cleanup_fd;
  1103.  
  1104.    dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
  1105.                                                &dri2_dpy->is_different_gpu);
  1106.    if (dri2_dpy->is_different_gpu) {
  1107.       free(dri2_dpy->device_name);
  1108.       dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
  1109.       if (!dri2_dpy->device_name) {
  1110.          _eglError(EGL_BAD_ALLOC, "wayland-egl: failed to get device name "
  1111.                                   "for requested GPU");
  1112.          goto cleanup_fd;
  1113.       }
  1114.    }
  1115.  
  1116.    /* we have to do the check now, because loader_get_user_preferred_fd
  1117.     * will return a render-node when the requested gpu is different
  1118.     * to the server, but also if the client asks for the same gpu than
  1119.     * the server by requesting its pci-id */
  1120.    dri2_dpy->is_render_node = is_fd_render_node(dri2_dpy->fd);
  1121.  
  1122.    dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
  1123.    if (dri2_dpy->driver_name == NULL) {
  1124.       _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
  1125.       goto cleanup_fd;
  1126.    }
  1127.  
  1128.    if (!dri2_load_driver(disp))
  1129.       goto cleanup_driver_name;
  1130.  
  1131.    dri2_dpy->extensions[0] = &image_loader_extension.base;
  1132.    dri2_dpy->extensions[1] = &image_lookup_extension.base;
  1133.    dri2_dpy->extensions[2] = &use_invalidate.base;
  1134.  
  1135.    /* render nodes cannot use Gem names, and thus do not support
  1136.     * the __DRI_DRI2_LOADER extension */
  1137.    if (!dri2_dpy->is_render_node) {
  1138.       dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
  1139.       dri2_dpy->dri2_loader_extension.base.version = 3;
  1140.       dri2_dpy->dri2_loader_extension.getBuffers = dri2_wl_get_buffers;
  1141.       dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_wl_flush_front_buffer;
  1142.       dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
  1143.          dri2_wl_get_buffers_with_format;
  1144.       dri2_dpy->extensions[3] = &dri2_dpy->dri2_loader_extension.base;
  1145.       dri2_dpy->extensions[4] = NULL;
  1146.    } else
  1147.       dri2_dpy->extensions[3] = NULL;
  1148.  
  1149.    dri2_dpy->swap_available = EGL_TRUE;
  1150.  
  1151.    if (!dri2_create_screen(disp))
  1152.       goto cleanup_driver;
  1153.  
  1154.    dri2_wl_setup_swap_interval(dri2_dpy);
  1155.  
  1156.    /* To use Prime, we must have _DRI_IMAGE v7 at least.
  1157.     * createImageFromFds support indicates that Prime export/import
  1158.     * is supported by the driver. Fall back to
  1159.     * gem names if we don't have Prime support. */
  1160.  
  1161.    if (dri2_dpy->image->base.version < 7 ||
  1162.        dri2_dpy->image->createImageFromFds == NULL)
  1163.       dri2_dpy->capabilities &= ~WL_DRM_CAPABILITY_PRIME;
  1164.  
  1165.    /* We cannot use Gem names with render-nodes, only prime fds (dma-buf).
  1166.     * The server needs to accept them */
  1167.    if (dri2_dpy->is_render_node &&
  1168.        !(dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME)) {
  1169.       _eglLog(_EGL_WARNING, "wayland-egl: display is not render-node capable");
  1170.       goto cleanup_screen;
  1171.    }
  1172.  
  1173.    if (dri2_dpy->is_different_gpu &&
  1174.        (dri2_dpy->image->base.version < 9 ||
  1175.         dri2_dpy->image->blitImage == NULL)) {
  1176.       _eglLog(_EGL_WARNING, "wayland-egl: Different GPU selected, but the "
  1177.                             "Image extension in the driver is not "
  1178.                             "compatible. Version 9 or later and blitImage() "
  1179.                             "are required");
  1180.       goto cleanup_screen;
  1181.    }
  1182.  
  1183.    types = EGL_WINDOW_BIT;
  1184.    for (i = 0; dri2_dpy->driver_configs[i]; i++) {
  1185.       config = dri2_dpy->driver_configs[i];
  1186.       if (dri2_dpy->formats & HAS_XRGB8888)
  1187.          dri2_add_config(disp, config, i + 1, types, NULL, rgb_masks);
  1188.       if (dri2_dpy->formats & HAS_ARGB8888)
  1189.          dri2_add_config(disp, config, i + 1, types, NULL, argb_masks);
  1190.       if (dri2_dpy->formats & HAS_RGB565)
  1191.         dri2_add_config(disp, config, i + 1, types, NULL, rgb565_masks);
  1192.    }
  1193.  
  1194.    disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
  1195.    /* When cannot convert EGLImage to wl_buffer when on a different gpu,
  1196.     * because the buffer of the EGLImage has likely a tiling mode the server
  1197.     * gpu won't support. These is no way to check for now. Thus do not support the
  1198.     * extension */
  1199.    if (!dri2_dpy->is_different_gpu) {
  1200.       disp->Extensions.WL_create_wayland_buffer_from_image = EGL_TRUE;
  1201.    } else {
  1202.       dri2_wl_display_vtbl.create_wayland_buffer_from_image =
  1203.          dri2_fallback_create_wayland_buffer_from_image;
  1204.    }
  1205.    disp->Extensions.EXT_buffer_age = EGL_TRUE;
  1206.  
  1207.    disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
  1208.  
  1209.    /* we're supporting EGL 1.4 */
  1210.    disp->VersionMajor = 1;
  1211.    disp->VersionMinor = 4;
  1212.  
  1213.    /* Fill vtbl last to prevent accidentally calling virtual function during
  1214.     * initialization.
  1215.     */
  1216.    dri2_dpy->vtbl = &dri2_wl_display_vtbl;
  1217.  
  1218.    return EGL_TRUE;
  1219.  
  1220.  cleanup_screen:
  1221.    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
  1222.  cleanup_driver:
  1223.    dlclose(dri2_dpy->driver);
  1224.  cleanup_driver_name:
  1225.    free(dri2_dpy->driver_name);
  1226.  cleanup_fd:
  1227.    close(dri2_dpy->fd);
  1228.  cleanup_drm:
  1229.    free(dri2_dpy->device_name);
  1230.    wl_drm_destroy(dri2_dpy->wl_drm);
  1231.  cleanup_registry:
  1232.    wl_registry_destroy(dri2_dpy->wl_registry);
  1233.    wl_event_queue_destroy(dri2_dpy->wl_queue);
  1234.  cleanup_dpy:
  1235.    free(dri2_dpy);
  1236.    
  1237.    return EGL_FALSE;
  1238. }
  1239.  
  1240. static int
  1241. dri2_wl_swrast_get_stride_for_format(int format, int w)
  1242. {
  1243.    if (format == WL_SHM_FORMAT_RGB565)
  1244.       return 2 * w;
  1245.    else /* ARGB8888 || XRGB8888 */
  1246.       return 4 * w;
  1247. }
  1248.  
  1249. /*
  1250.  * Taken from weston shared/os-compatibility.c
  1251.  */
  1252.  
  1253. static int
  1254. set_cloexec_or_close(int fd)
  1255. {
  1256.    long flags;
  1257.  
  1258.    if (fd == -1)
  1259.       return -1;
  1260.  
  1261.    flags = fcntl(fd, F_GETFD);
  1262.    if (flags == -1)
  1263.       goto err;
  1264.  
  1265.    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
  1266.       goto err;
  1267.  
  1268.    return fd;
  1269.  
  1270. err:
  1271.    close(fd);
  1272.    return -1;
  1273. }
  1274.  
  1275. /*
  1276.  * Taken from weston shared/os-compatibility.c
  1277.  */
  1278.  
  1279. static int
  1280. create_tmpfile_cloexec(char *tmpname)
  1281. {
  1282.    int fd;
  1283.  
  1284. #ifdef HAVE_MKOSTEMP
  1285.    fd = mkostemp(tmpname, O_CLOEXEC);
  1286.    if (fd >= 0)
  1287.       unlink(tmpname);
  1288. #else
  1289.    fd = mkstemp(tmpname);
  1290.    if (fd >= 0) {
  1291.       fd = set_cloexec_or_close(fd);
  1292.       unlink(tmpname);
  1293.    }
  1294. #endif
  1295.  
  1296.    return fd;
  1297. }
  1298.  
  1299. /*
  1300.  * Taken from weston shared/os-compatibility.c
  1301.  *
  1302.  * Create a new, unique, anonymous file of the given size, and
  1303.  * return the file descriptor for it. The file descriptor is set
  1304.  * CLOEXEC. The file is immediately suitable for mmap()'ing
  1305.  * the given size at offset zero.
  1306.  *
  1307.  * The file should not have a permanent backing store like a disk,
  1308.  * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
  1309.  *
  1310.  * The file name is deleted from the file system.
  1311.  *
  1312.  * The file is suitable for buffer sharing between processes by
  1313.  * transmitting the file descriptor over Unix sockets using the
  1314.  * SCM_RIGHTS methods.
  1315.  *
  1316.  * If the C library implements posix_fallocate(), it is used to
  1317.  * guarantee that disk space is available for the file at the
  1318.  * given size. If disk space is insufficent, errno is set to ENOSPC.
  1319.  * If posix_fallocate() is not supported, program may receive
  1320.  * SIGBUS on accessing mmap()'ed file contents instead.
  1321.  */
  1322. static int
  1323. os_create_anonymous_file(off_t size)
  1324. {
  1325.    static const char template[] = "/mesa-shared-XXXXXX";
  1326.    const char *path;
  1327.    char *name;
  1328.    int fd;
  1329.    int ret;
  1330.  
  1331.    path = getenv("XDG_RUNTIME_DIR");
  1332.    if (!path) {
  1333.       errno = ENOENT;
  1334.       return -1;
  1335.    }
  1336.  
  1337.    name = malloc(strlen(path) + sizeof(template));
  1338.    if (!name)
  1339.       return -1;
  1340.  
  1341.    strcpy(name, path);
  1342.    strcat(name, template);
  1343.  
  1344.    fd = create_tmpfile_cloexec(name);
  1345.  
  1346.    free(name);
  1347.  
  1348.    if (fd < 0)
  1349.       return -1;
  1350.  
  1351.    ret = ftruncate(fd, size);
  1352.    if (ret < 0) {
  1353.       close(fd);
  1354.       return -1;
  1355.    }
  1356.  
  1357.    return fd;
  1358. }
  1359.  
  1360.  
  1361. static EGLBoolean
  1362. dri2_wl_swrast_allocate_buffer(struct dri2_egl_display *dri2_dpy,
  1363.                                int format, int w, int h,
  1364.                                void **data, int *size,
  1365.                                struct wl_buffer **buffer)
  1366. {
  1367.    struct wl_shm_pool *pool;
  1368.    int fd, stride, size_map;
  1369.    void *data_map;
  1370.  
  1371.    stride = dri2_wl_swrast_get_stride_for_format(format, w);
  1372.    size_map = h * stride;
  1373.  
  1374.    /* Create a sharable buffer */
  1375.    fd = os_create_anonymous_file(size_map);
  1376.    if (fd < 0)
  1377.       return EGL_FALSE;
  1378.  
  1379.    data_map = mmap(NULL, size_map, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  1380.    if (data_map == MAP_FAILED) {
  1381.       close(fd);
  1382.       return EGL_FALSE;
  1383.    }
  1384.  
  1385.    /* Share it in a wl_buffer */
  1386.    pool = wl_shm_create_pool(dri2_dpy->wl_shm, fd, size_map);
  1387.    *buffer = wl_shm_pool_create_buffer(pool, 0, w, h, stride, format);
  1388.    wl_shm_pool_destroy(pool);
  1389.    close(fd);
  1390.  
  1391.    *data = data_map;
  1392.    *size = size_map;
  1393.    return EGL_TRUE;
  1394. }
  1395.  
  1396. static int
  1397. swrast_update_buffers(struct dri2_egl_surface *dri2_surf)
  1398. {
  1399.    struct dri2_egl_display *dri2_dpy =
  1400.       dri2_egl_display(dri2_surf->base.Resource.Display);
  1401.    int i;
  1402.  
  1403.    /* we need to do the following operations only once per frame */
  1404.    if (dri2_surf->back)
  1405.       return 0;
  1406.  
  1407.    if (dri2_surf->base.Width != dri2_surf->wl_win->width ||
  1408.        dri2_surf->base.Height != dri2_surf->wl_win->height) {
  1409.  
  1410.       dri2_wl_release_buffers(dri2_surf);
  1411.  
  1412.       dri2_surf->base.Width  = dri2_surf->wl_win->width;
  1413.       dri2_surf->base.Height = dri2_surf->wl_win->height;
  1414.       dri2_surf->dx = dri2_surf->wl_win->dx;
  1415.       dri2_surf->dy = dri2_surf->wl_win->dy;
  1416.       dri2_surf->current = NULL;
  1417.    }
  1418.  
  1419.    /* find back buffer */
  1420.  
  1421.    /* We always want to throttle to some event (either a frame callback or
  1422.     * a sync request) after the commit so that we can be sure the
  1423.     * compositor has had a chance to handle it and send us a release event
  1424.     * before we look for a free buffer */
  1425.    while (dri2_surf->throttle_callback != NULL)
  1426.       if (wl_display_dispatch_queue(dri2_dpy->wl_dpy,
  1427.                                     dri2_dpy->wl_queue) == -1)
  1428.          return -1;
  1429.  
  1430.    /* try get free buffer already created */
  1431.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  1432.       if (!dri2_surf->color_buffers[i].locked &&
  1433.           dri2_surf->color_buffers[i].wl_buffer) {
  1434.           dri2_surf->back = &dri2_surf->color_buffers[i];
  1435.           break;
  1436.       }
  1437.    }
  1438.  
  1439.    /* else choose any another free location */
  1440.    if (!dri2_surf->back) {
  1441.       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  1442.          if (!dri2_surf->color_buffers[i].locked) {
  1443.              dri2_surf->back = &dri2_surf->color_buffers[i];
  1444.              if (!dri2_wl_swrast_allocate_buffer(dri2_dpy,
  1445.                                                  dri2_surf->format,
  1446.                                                  dri2_surf->base.Width,
  1447.                                                  dri2_surf->base.Height,
  1448.                                                  &dri2_surf->back->data,
  1449.                                                  &dri2_surf->back->data_size,
  1450.                                                  &dri2_surf->back->wl_buffer)) {
  1451.                 _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
  1452.                  return -1;
  1453.              }
  1454.              wl_proxy_set_queue((struct wl_proxy *) dri2_surf->back->wl_buffer,
  1455.                                 dri2_dpy->wl_queue);
  1456.              wl_buffer_add_listener(dri2_surf->back->wl_buffer,
  1457.                                     &wl_buffer_listener, dri2_surf);
  1458.              break;
  1459.          }
  1460.       }
  1461.    }
  1462.  
  1463.    if (!dri2_surf->back) {
  1464.       _eglError(EGL_BAD_ALLOC, "failed to find free buffer");
  1465.       return -1;
  1466.    }
  1467.  
  1468.    dri2_surf->back->locked = 1;
  1469.  
  1470.    /* If we have an extra unlocked buffer at this point, we had to do triple
  1471.     * buffering for a while, but now can go back to just double buffering.
  1472.     * That means we can free any unlocked buffer now. */
  1473.    for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
  1474.       if (!dri2_surf->color_buffers[i].locked &&
  1475.           dri2_surf->color_buffers[i].wl_buffer) {
  1476.          wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
  1477.          munmap(dri2_surf->color_buffers[i].data,
  1478.                 dri2_surf->color_buffers[i].data_size);
  1479.          dri2_surf->color_buffers[i].wl_buffer = NULL;
  1480.          dri2_surf->color_buffers[i].data = NULL;
  1481.       }
  1482.    }
  1483.  
  1484.    return 0;
  1485. }
  1486.  
  1487. static void*
  1488. dri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface *dri2_surf)
  1489. {
  1490.    /* if there has been a resize: */
  1491.    if (!dri2_surf->current)
  1492.       return NULL;
  1493.  
  1494.    return dri2_surf->current->data;
  1495. }
  1496.  
  1497. static void*
  1498. dri2_wl_swrast_get_backbuffer_data(struct dri2_egl_surface *dri2_surf)
  1499. {
  1500.    assert(dri2_surf->back);
  1501.    return dri2_surf->back->data;
  1502. }
  1503.  
  1504. static void
  1505. dri2_wl_swrast_commit_backbuffer(struct dri2_egl_surface *dri2_surf)
  1506. {
  1507.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
  1508.  
  1509.    if (dri2_surf->base.SwapInterval > 0) {
  1510.       dri2_surf->throttle_callback =
  1511.          wl_surface_frame(dri2_surf->wl_win->surface);
  1512.       wl_callback_add_listener(dri2_surf->throttle_callback,
  1513.                                &throttle_listener, dri2_surf);
  1514.       wl_proxy_set_queue((struct wl_proxy *) dri2_surf->throttle_callback,
  1515.                          dri2_dpy->wl_queue);
  1516.    }
  1517.  
  1518.    dri2_surf->current = dri2_surf->back;
  1519.    dri2_surf->back = NULL;
  1520.  
  1521.    wl_surface_attach(dri2_surf->wl_win->surface,
  1522.                      dri2_surf->current->wl_buffer,
  1523.                      dri2_surf->dx, dri2_surf->dy);
  1524.  
  1525.    dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
  1526.    dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
  1527.    /* reset resize growing parameters */
  1528.    dri2_surf->dx = 0;
  1529.    dri2_surf->dy = 0;
  1530.  
  1531.    wl_surface_damage(dri2_surf->wl_win->surface,
  1532.                      0, 0, INT32_MAX, INT32_MAX);
  1533.    wl_surface_commit(dri2_surf->wl_win->surface);
  1534.  
  1535.    /* If we're not waiting for a frame callback then we'll at least throttle
  1536.     * to a sync callback so that we always give a chance for the compositor to
  1537.     * handle the commit and send a release event before checking for a free
  1538.     * buffer */
  1539.    if (dri2_surf->throttle_callback == NULL) {
  1540.       dri2_surf->throttle_callback = wl_display_sync(dri2_dpy->wl_dpy);
  1541.       wl_callback_add_listener(dri2_surf->throttle_callback,
  1542.                                &throttle_listener, dri2_surf);
  1543.       wl_proxy_set_queue((struct wl_proxy *) dri2_surf->throttle_callback,
  1544.                          dri2_dpy->wl_queue);
  1545.    }
  1546.  
  1547.    wl_display_flush(dri2_dpy->wl_dpy);
  1548. }
  1549.  
  1550. static void
  1551. dri2_wl_swrast_get_drawable_info(__DRIdrawable * draw,
  1552.                                  int *x, int *y, int *w, int *h,
  1553.                                  void *loaderPrivate)
  1554. {
  1555.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  1556.  
  1557.    (void) swrast_update_buffers(dri2_surf);
  1558.    *x = 0;
  1559.    *y = 0;
  1560.    *w = dri2_surf->base.Width;
  1561.    *h = dri2_surf->base.Height;
  1562. }
  1563.  
  1564. static void
  1565. dri2_wl_swrast_get_image(__DRIdrawable * read,
  1566.                          int x, int y, int w, int h,
  1567.                          char *data, void *loaderPrivate)
  1568. {
  1569.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  1570.    int copy_width = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w);
  1571.    int x_offset = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, x);
  1572.    int src_stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, dri2_surf->base.Width);
  1573.    int dst_stride = copy_width;
  1574.    char *src, *dst;
  1575.  
  1576.    src = dri2_wl_swrast_get_frontbuffer_data(dri2_surf);
  1577.    if (!src) {
  1578.       memset(data, 0, copy_width * h);
  1579.       return;
  1580.    }
  1581.  
  1582.    assert(data != src);
  1583.    assert(copy_width <= src_stride);
  1584.  
  1585.    src += x_offset;
  1586.    src += y * src_stride;
  1587.    dst = data;
  1588.  
  1589.    if (copy_width > src_stride-x_offset)
  1590.       copy_width = src_stride-x_offset;
  1591.    if (h > dri2_surf->base.Height-y)
  1592.       h = dri2_surf->base.Height-y;
  1593.  
  1594.    for (; h>0; h--) {
  1595.       memcpy(dst, src, copy_width);
  1596.       src += src_stride;
  1597.       dst += dst_stride;
  1598.    }
  1599. }
  1600.  
  1601. static void
  1602. dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
  1603.                          int x, int y, int w, int h, int stride,
  1604.                          char *data, void *loaderPrivate)
  1605. {
  1606.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  1607.    int copy_width = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w);
  1608.    int dst_stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, dri2_surf->base.Width);
  1609.    int x_offset = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, x);
  1610.    char *src, *dst;
  1611.  
  1612.    assert(copy_width <= stride);
  1613.  
  1614.    (void) swrast_update_buffers(dri2_surf);
  1615.    dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
  1616.  
  1617.    /* partial copy, copy old content */
  1618.    if (copy_width < dst_stride)
  1619.       dri2_wl_swrast_get_image(draw, 0, 0,
  1620.                                dri2_surf->base.Width, dri2_surf->base.Height,
  1621.                                dst, loaderPrivate);
  1622.  
  1623.    dst += x_offset;
  1624.    dst += y * dst_stride;
  1625.  
  1626.    src = data;
  1627.  
  1628.    /* drivers expect we do these checks (and some rely on it) */
  1629.    if (copy_width > dst_stride-x_offset)
  1630.       copy_width = dst_stride-x_offset;
  1631.    if (h > dri2_surf->base.Height-y)
  1632.       h = dri2_surf->base.Height-y;
  1633.  
  1634.    for (; h>0; h--) {
  1635.       memcpy(dst, src, copy_width);
  1636.       src += stride;
  1637.       dst += dst_stride;
  1638.    }
  1639.    dri2_wl_swrast_commit_backbuffer(dri2_surf);
  1640. }
  1641.  
  1642. static void
  1643. dri2_wl_swrast_put_image(__DRIdrawable * draw, int op,
  1644.                          int x, int y, int w, int h,
  1645.                          char *data, void *loaderPrivate)
  1646. {
  1647.    struct dri2_egl_surface *dri2_surf = loaderPrivate;
  1648.    int stride;
  1649.  
  1650.    stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w);
  1651.    dri2_wl_swrast_put_image2(draw, op, x, y, w, h,
  1652.                              stride, data, loaderPrivate);
  1653. }
  1654.  
  1655. /**
  1656.  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  1657.  */
  1658. static _EGLSurface *
  1659. dri2_wl_swrast_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
  1660.                                      _EGLConfig *conf, void *native_window,
  1661.                                      const EGLint *attrib_list)
  1662. {
  1663.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1664.    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  1665.    struct wl_egl_window *window = native_window;
  1666.    struct dri2_egl_surface *dri2_surf;
  1667.  
  1668.    (void) drv;
  1669.  
  1670.    dri2_surf = calloc(1, sizeof *dri2_surf);
  1671.    if (!dri2_surf) {
  1672.       _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
  1673.       return NULL;
  1674.    }
  1675.  
  1676.    if (!_eglInitSurface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, attrib_list))
  1677.       goto cleanup_surf;
  1678.  
  1679.    if (conf->RedSize == 5)
  1680.       dri2_surf->format = WL_SHM_FORMAT_RGB565;
  1681.    else if (conf->AlphaSize == 0)
  1682.       dri2_surf->format = WL_SHM_FORMAT_XRGB8888;
  1683.    else
  1684.       dri2_surf->format = WL_SHM_FORMAT_ARGB8888;
  1685.  
  1686.    dri2_surf->wl_win = window;
  1687.  
  1688.    dri2_surf->base.Width = -1;
  1689.    dri2_surf->base.Height = -1;
  1690.  
  1691.    dri2_surf->dri_drawable =
  1692.       (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
  1693.                                               dri2_conf->dri_double_config,
  1694.                                               dri2_surf);
  1695.    if (dri2_surf->dri_drawable == NULL) {
  1696.       _eglError(EGL_BAD_ALLOC, "swrast->createNewDrawable");
  1697.       goto cleanup_dri_drawable;
  1698.    }
  1699.  
  1700.    dri2_wl_swap_interval(drv, disp, &dri2_surf->base,
  1701.                          dri2_dpy->default_swap_interval);
  1702.  
  1703.    return &dri2_surf->base;
  1704.  
  1705.  cleanup_dri_drawable:
  1706.    dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
  1707.  cleanup_surf:
  1708.    free(dri2_surf);
  1709.  
  1710.    return NULL;
  1711. }
  1712.  
  1713. static EGLBoolean
  1714. dri2_wl_swrast_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
  1715. {
  1716.    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  1717.    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  1718.  
  1719.    dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
  1720.    return EGL_TRUE;
  1721. }
  1722.  
  1723. static void
  1724. shm_handle_format(void *data, struct wl_shm *shm, uint32_t format)
  1725. {
  1726.    struct dri2_egl_display *dri2_dpy = data;
  1727.  
  1728.    switch (format) {
  1729.    case WL_SHM_FORMAT_ARGB8888:
  1730.       dri2_dpy->formats |= HAS_ARGB8888;
  1731.       break;
  1732.    case WL_SHM_FORMAT_XRGB8888:
  1733.       dri2_dpy->formats |= HAS_XRGB8888;
  1734.       break;
  1735.    case WL_SHM_FORMAT_RGB565:
  1736.       dri2_dpy->formats |= HAS_RGB565;
  1737.       break;
  1738.    }
  1739. }
  1740.  
  1741. static const struct wl_shm_listener shm_listener = {
  1742.    shm_handle_format
  1743. };
  1744.  
  1745. static void
  1746. registry_handle_global_swrast(void *data, struct wl_registry *registry, uint32_t name,
  1747.                               const char *interface, uint32_t version)
  1748. {
  1749.    struct dri2_egl_display *dri2_dpy = data;
  1750.  
  1751.    if (strcmp(interface, "wl_shm") == 0) {
  1752.       dri2_dpy->wl_shm =
  1753.          wl_registry_bind(registry, name, &wl_shm_interface, 1);
  1754.       wl_shm_add_listener(dri2_dpy->wl_shm, &shm_listener, dri2_dpy);
  1755.    }
  1756. }
  1757.  
  1758. static const struct wl_registry_listener registry_listener_swrast = {
  1759.    registry_handle_global_swrast,
  1760.    registry_handle_global_remove
  1761. };
  1762.  
  1763. static struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl = {
  1764.    .authenticate = NULL,
  1765.    .create_window_surface = dri2_wl_swrast_create_window_surface,
  1766.    .create_pixmap_surface = dri2_wl_create_pixmap_surface,
  1767.    .create_pbuffer_surface = dri2_fallback_create_pbuffer_surface,
  1768.    .destroy_surface = dri2_wl_destroy_surface,
  1769.    .create_image = dri2_fallback_create_image_khr,
  1770.    .swap_interval = dri2_wl_swap_interval,
  1771.    .swap_buffers = dri2_wl_swrast_swap_buffers,
  1772.    .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
  1773.    .swap_buffers_region = dri2_fallback_swap_buffers_region,
  1774.    .post_sub_buffer = dri2_fallback_post_sub_buffer,
  1775.    .copy_buffers = dri2_fallback_copy_buffers,
  1776.    .query_buffer_age = dri2_fallback_query_buffer_age,
  1777.    .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
  1778.    .get_sync_values = dri2_fallback_get_sync_values,
  1779. };
  1780.  
  1781. static EGLBoolean
  1782. dri2_initialize_wayland_swrast(_EGLDriver *drv, _EGLDisplay *disp)
  1783. {
  1784.    struct dri2_egl_display *dri2_dpy;
  1785.    const __DRIconfig *config;
  1786.    uint32_t types;
  1787.    int i;
  1788.    static const unsigned int argb_masks[4] =
  1789.       { 0xff0000, 0xff00, 0xff, 0xff000000 };
  1790.    static const unsigned int rgb_masks[4] = { 0xff0000, 0xff00, 0xff, 0 };
  1791.    static const unsigned int rgb565_masks[4] = { 0xf800, 0x07e0, 0x001f, 0 };
  1792.  
  1793.    loader_set_logger(_eglLog);
  1794.  
  1795.    dri2_dpy = calloc(1, sizeof *dri2_dpy);
  1796.    if (!dri2_dpy)
  1797.       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  1798.  
  1799.    disp->DriverData = (void *) dri2_dpy;
  1800.    if (disp->PlatformDisplay == NULL) {
  1801.       dri2_dpy->wl_dpy = wl_display_connect(NULL);
  1802.       if (dri2_dpy->wl_dpy == NULL)
  1803.          goto cleanup_dpy;
  1804.       dri2_dpy->own_device = 1;
  1805.    } else {
  1806.       dri2_dpy->wl_dpy = disp->PlatformDisplay;
  1807.    }
  1808.  
  1809.    dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
  1810.  
  1811.    if (dri2_dpy->own_device)
  1812.       wl_display_dispatch_pending(dri2_dpy->wl_dpy);
  1813.  
  1814.    dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy);
  1815.    wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_registry,
  1816.                       dri2_dpy->wl_queue);
  1817.    wl_registry_add_listener(dri2_dpy->wl_registry,
  1818.                             &registry_listener_swrast, dri2_dpy);
  1819.  
  1820.    if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_shm == NULL)
  1821.       goto cleanup_registry;
  1822.  
  1823.    if (roundtrip(dri2_dpy) < 0 || dri2_dpy->formats == 0)
  1824.       goto cleanup_shm;
  1825.  
  1826.    dri2_dpy->driver_name = strdup("swrast");
  1827.    if (!dri2_load_driver_swrast(disp))
  1828.       goto cleanup_shm;
  1829.  
  1830.    dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
  1831.    dri2_dpy->swrast_loader_extension.base.version = 2;
  1832.    dri2_dpy->swrast_loader_extension.getDrawableInfo = dri2_wl_swrast_get_drawable_info;
  1833.    dri2_dpy->swrast_loader_extension.putImage = dri2_wl_swrast_put_image;
  1834.    dri2_dpy->swrast_loader_extension.getImage = dri2_wl_swrast_get_image;
  1835.    dri2_dpy->swrast_loader_extension.putImage2 = dri2_wl_swrast_put_image2;
  1836.  
  1837.    dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
  1838.    dri2_dpy->extensions[1] = NULL;
  1839.  
  1840.    if (!dri2_create_screen(disp))
  1841.       goto cleanup_driver;
  1842.  
  1843.    dri2_wl_setup_swap_interval(dri2_dpy);
  1844.  
  1845.    types = EGL_WINDOW_BIT;
  1846.    for (i = 0; dri2_dpy->driver_configs[i]; i++) {
  1847.       config = dri2_dpy->driver_configs[i];
  1848.       if (dri2_dpy->formats & HAS_XRGB8888)
  1849.          dri2_add_config(disp, config, i + 1, types, NULL, rgb_masks);
  1850.       if (dri2_dpy->formats & HAS_ARGB8888)
  1851.          dri2_add_config(disp, config, i + 1, types, NULL, argb_masks);
  1852.       if (dri2_dpy->formats & HAS_RGB565)
  1853.         dri2_add_config(disp, config, i + 1, types, NULL, rgb565_masks);
  1854.    }
  1855.  
  1856.    /* we're supporting EGL 1.4 */
  1857.    disp->VersionMajor = 1;
  1858.    disp->VersionMinor = 4;
  1859.  
  1860.    /* Fill vtbl last to prevent accidentally calling virtual function during
  1861.     * initialization.
  1862.     */
  1863.    dri2_dpy->vtbl = &dri2_wl_swrast_display_vtbl;
  1864.  
  1865.    return EGL_TRUE;
  1866.  
  1867.  cleanup_driver:
  1868.    dlclose(dri2_dpy->driver);
  1869.  cleanup_shm:
  1870.    wl_shm_destroy(dri2_dpy->wl_shm);
  1871.  cleanup_registry:
  1872.    wl_registry_destroy(dri2_dpy->wl_registry);
  1873.    wl_event_queue_destroy(dri2_dpy->wl_queue);
  1874.  cleanup_dpy:
  1875.    free(dri2_dpy);
  1876.  
  1877.    return EGL_FALSE;
  1878. }
  1879.  
  1880. EGLBoolean
  1881. dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
  1882. {
  1883.    EGLBoolean initialized = EGL_TRUE;
  1884.  
  1885.    int hw_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
  1886.  
  1887.    if (hw_accel) {
  1888.       if (!dri2_initialize_wayland_drm(drv, disp)) {
  1889.          initialized = dri2_initialize_wayland_swrast(drv, disp);
  1890.       }
  1891.    } else {
  1892.       initialized = dri2_initialize_wayland_swrast(drv, disp);
  1893.    }
  1894.  
  1895.    return initialized;
  1896.  
  1897. }
  1898.