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 "drm-uapi/drm_fourcc.h"
40#include <sys/mman.h>
41
42#include "egl_dri2.h"
43#include "loader_dri_helper.h"
44#include "loader.h"
45#include "util/u_vector.h"
46#include "util/anon_file.h"
47#include "eglglobals.h"
48
49#include <wayland-egl-backend.h>
50#include <wayland-client.h>
51#include "wayland-drm-client-protocol.h"
52#include "linux-dmabuf-unstable-v1-client-protocol.h"
53
54/*
55 * The index of entries in this table is used as a bitmask in
56 * dri2_dpy->formats, which tracks the formats supported by our server.
57 */
58static const struct dri2_wl_visual {
59   const char *format_name;
60   uint32_t wl_drm_format;
61   uint32_t wl_shm_format;
62   int dri_image_format;
63   /* alt_dri_image_format is a substitute wl_buffer format to use for a
64    * wl-server unsupported dri_image_format, ie. some other dri_image_format in
65    * the table, of the same precision but with different channel ordering, or
66    * __DRI_IMAGE_FORMAT_NONE if an alternate format is not needed or supported.
67    * The code checks if alt_dri_image_format can be used as a fallback for a
68    * dri_image_format for a given wl-server implementation.
69    */
70   int alt_dri_image_format;
71   int bpp;
72   int rgba_shifts[4];
73   unsigned int rgba_sizes[4];
74} dri2_wl_visuals[] = {
75   {
76      "ABGR16F",
77      WL_DRM_FORMAT_ABGR16F, WL_SHM_FORMAT_ABGR16161616F,
78      __DRI_IMAGE_FORMAT_ABGR16161616F, 0, 64,
79      { 0, 16, 32, 48 },
80      { 16, 16, 16, 16 },
81   },
82   {
83      "XBGR16F",
84      WL_DRM_FORMAT_XBGR16F, WL_SHM_FORMAT_XBGR16161616F,
85      __DRI_IMAGE_FORMAT_XBGR16161616F, 0, 64,
86      { 0, 16, 32, -1 },
87      { 16, 16, 16, 0 },
88   },
89   {
90      "XRGB2101010",
91      WL_DRM_FORMAT_XRGB2101010, WL_SHM_FORMAT_XRGB2101010,
92      __DRI_IMAGE_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 32,
93      { 20, 10, 0, -1 },
94      { 10, 10, 10, 0 },
95   },
96   {
97      "ARGB2101010",
98      WL_DRM_FORMAT_ARGB2101010, WL_SHM_FORMAT_ARGB2101010,
99      __DRI_IMAGE_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 32,
100      { 20, 10, 0, 30 },
101      { 10, 10, 10, 2 },
102   },
103   {
104      "XBGR2101010",
105      WL_DRM_FORMAT_XBGR2101010, WL_SHM_FORMAT_XBGR2101010,
106      __DRI_IMAGE_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 32,
107      { 0, 10, 20, -1 },
108      { 10, 10, 10, 0 },
109   },
110   {
111      "ABGR2101010",
112      WL_DRM_FORMAT_ABGR2101010, WL_SHM_FORMAT_ABGR2101010,
113      __DRI_IMAGE_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 32,
114      { 0, 10, 20, 30 },
115      { 10, 10, 10, 2 },
116   },
117   {
118      "XRGB8888",
119      WL_DRM_FORMAT_XRGB8888, WL_SHM_FORMAT_XRGB8888,
120      __DRI_IMAGE_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_NONE, 32,
121      { 16, 8, 0, -1 },
122      { 8, 8, 8, 0 },
123   },
124   {
125      "ARGB8888",
126      WL_DRM_FORMAT_ARGB8888, WL_SHM_FORMAT_ARGB8888,
127      __DRI_IMAGE_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_NONE, 32,
128      { 16, 8, 0, 24 },
129      { 8, 8, 8, 8 },
130   },
131   {
132      "ABGR8888",
133      WL_DRM_FORMAT_ABGR8888, WL_SHM_FORMAT_ABGR8888,
134      __DRI_IMAGE_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_NONE, 32,
135      { 0, 8, 16, 24 },
136      { 8, 8, 8, 8 },
137   },
138   {
139      "XBGR8888",
140      WL_DRM_FORMAT_XBGR8888, WL_SHM_FORMAT_XBGR8888,
141      __DRI_IMAGE_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_NONE, 32,
142      { 0, 8, 16, -1 },
143      { 8, 8, 8, 0 },
144   },
145   {
146      "RGB565",
147      WL_DRM_FORMAT_RGB565, WL_SHM_FORMAT_RGB565,
148      __DRI_IMAGE_FORMAT_RGB565, __DRI_IMAGE_FORMAT_NONE, 16,
149      { 11, 5, 0, -1 },
150      { 5, 6, 5, 0 },
151   },
152};
153
154static_assert(ARRAY_SIZE(dri2_wl_visuals) <= EGL_DRI2_MAX_FORMATS,
155              "dri2_egl_display::formats is not large enough for "
156              "the formats in dri2_wl_visuals");
157
158static int
159dri2_wl_visual_idx_from_config(struct dri2_egl_display *dri2_dpy,
160                               const __DRIconfig *config,
161                               bool force_opaque)
162{
163   int shifts[4];
164   unsigned int sizes[4];
165
166   dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes);
167
168   for (unsigned int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) {
169      const struct dri2_wl_visual *wl_visual = &dri2_wl_visuals[i];
170
171      int cmp_rgb_shifts = memcmp(shifts, wl_visual->rgba_shifts,
172                                  3 * sizeof(shifts[0]));
173      int cmp_rgb_sizes = memcmp(sizes, wl_visual->rgba_sizes,
174                                 3 * sizeof(sizes[0]));
175
176      if (cmp_rgb_shifts == 0 && cmp_rgb_sizes == 0 &&
177          wl_visual->rgba_shifts[3] == (force_opaque ? -1 : shifts[3]) &&
178          wl_visual->rgba_sizes[3] == (force_opaque ? 0 : sizes[3])) {
179         return i;
180      }
181   }
182
183   return -1;
184}
185
186static int
187dri2_wl_visual_idx_from_fourcc(uint32_t fourcc)
188{
189   for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) {
190      /* wl_drm format codes overlap with DRIImage FourCC codes for all formats
191       * we support. */
192      if (dri2_wl_visuals[i].wl_drm_format == fourcc)
193         return i;
194   }
195
196   return -1;
197}
198
199static int
200dri2_wl_visual_idx_from_dri_image_format(uint32_t dri_image_format)
201{
202   for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) {
203      if (dri2_wl_visuals[i].dri_image_format == dri_image_format)
204         return i;
205   }
206
207   return -1;
208}
209
210static int
211dri2_wl_visual_idx_from_shm_format(uint32_t shm_format)
212{
213   for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) {
214      if (dri2_wl_visuals[i].wl_shm_format == shm_format)
215         return i;
216   }
217
218   return -1;
219}
220
221bool
222dri2_wl_is_format_supported(void* user_data, uint32_t format)
223{
224   _EGLDisplay *disp = (_EGLDisplay *) user_data;
225   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
226   int j = dri2_wl_visual_idx_from_fourcc(format);
227
228   if (j == -1)
229      return false;
230
231   for (int i = 0; dri2_dpy->driver_configs[i]; i++)
232      if (j == dri2_wl_visual_idx_from_config(dri2_dpy,
233                                              dri2_dpy->driver_configs[i],
234                                              false))
235         return true;
236
237   return false;
238}
239
240static int
241roundtrip(struct dri2_egl_display *dri2_dpy)
242{
243   return wl_display_roundtrip_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
244}
245
246static void
247wl_buffer_release(void *data, struct wl_buffer *buffer)
248{
249   struct dri2_egl_surface *dri2_surf = data;
250   int i;
251
252   for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); ++i)
253      if (dri2_surf->color_buffers[i].wl_buffer == buffer)
254         break;
255
256   assert (i < ARRAY_SIZE(dri2_surf->color_buffers));
257
258   if (dri2_surf->color_buffers[i].wl_release) {
259      wl_buffer_destroy(buffer);
260      dri2_surf->color_buffers[i].wl_release = false;
261      dri2_surf->color_buffers[i].wl_buffer = NULL;
262   }
263
264   dri2_surf->color_buffers[i].locked = false;
265}
266
267static const struct wl_buffer_listener wl_buffer_listener = {
268   .release = wl_buffer_release
269};
270
271static void
272resize_callback(struct wl_egl_window *wl_win, void *data)
273{
274   struct dri2_egl_surface *dri2_surf = data;
275   struct dri2_egl_display *dri2_dpy =
276      dri2_egl_display(dri2_surf->base.Resource.Display);
277
278   if (dri2_surf->base.Width == wl_win->width &&
279       dri2_surf->base.Height == wl_win->height)
280      return;
281
282   dri2_surf->resized = true;
283
284   /* Update the surface size as soon as native window is resized; from user
285    * pov, this makes the effect that resize is done immediately after native
286    * window resize, without requiring to wait until the first draw.
287    *
288    * A more detailed and lengthy explanation can be found at
289    * https://lists.freedesktop.org/archives/mesa-dev/2018-June/196474.html
290    */
291   if (!dri2_surf->back) {
292      dri2_surf->base.Width = wl_win->width;
293      dri2_surf->base.Height = wl_win->height;
294   }
295   dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
296}
297
298static void
299destroy_window_callback(void *data)
300{
301   struct dri2_egl_surface *dri2_surf = data;
302   dri2_surf->wl_win = NULL;
303}
304
305static struct wl_surface *
306get_wl_surface_proxy(struct wl_egl_window *window)
307{
308    /* Version 3 of wl_egl_window introduced a version field at the same
309     * location where a pointer to wl_surface was stored. Thus, if
310     * window->version is dereferenceable, we've been given an older version of
311     * wl_egl_window, and window->version points to wl_surface */
312   if (_eglPointerIsDereferencable((void *)(window->version))) {
313      return wl_proxy_create_wrapper((void *)(window->version));
314   }
315   return wl_proxy_create_wrapper(window->surface);
316}
317
318/**
319 * Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
320 */
321static _EGLSurface *
322dri2_wl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
323                              void *native_window, const EGLint *attrib_list)
324{
325   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
326   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
327   struct wl_egl_window *window = native_window;
328   struct dri2_egl_surface *dri2_surf;
329   int visual_idx;
330   const __DRIconfig *config;
331
332   if (!window) {
333      _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface");
334      return NULL;
335   }
336
337   if (window->driver_private) {
338      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
339      return NULL;
340   }
341
342   dri2_surf = calloc(1, sizeof *dri2_surf);
343   if (!dri2_surf) {
344      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
345      return NULL;
346   }
347
348   if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf,
349                          attrib_list, false, native_window))
350      goto cleanup_surf;
351
352   config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
353                                dri2_surf->base.GLColorspace);
354
355   if (!config) {
356      _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
357      goto cleanup_surf;
358   }
359
360   dri2_surf->base.Width = window->width;
361   dri2_surf->base.Height = window->height;
362
363#ifndef NDEBUG
364   /* Enforce that every visual has an opaque variant (requirement to support
365    * EGL_EXT_present_opaque)
366    */
367   for (unsigned int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) {
368      const struct dri2_wl_visual *transparent_visual = &dri2_wl_visuals[i];
369      if (transparent_visual->rgba_sizes[3] == 0) {
370         continue;
371      }
372
373      bool found_opaque_equivalent = false;
374      for (unsigned int j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) {
375         const struct dri2_wl_visual *opaque_visual = &dri2_wl_visuals[j];
376         if (opaque_visual->rgba_sizes[3] != 0) {
377            continue;
378         }
379
380         int cmp_rgb_shifts = memcmp(transparent_visual->rgba_shifts,
381                                     opaque_visual->rgba_shifts,
382                                     3 * sizeof(opaque_visual->rgba_shifts[0]));
383         int cmp_rgb_sizes = memcmp(transparent_visual->rgba_sizes,
384                                    opaque_visual->rgba_sizes,
385                                    3 * sizeof(opaque_visual->rgba_sizes[0]));
386
387         if (cmp_rgb_shifts == 0 && cmp_rgb_sizes == 0) {
388            found_opaque_equivalent = true;
389            break;
390         }
391      }
392
393      assert(found_opaque_equivalent);
394   }
395#endif
396
397   visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config,
398                                               dri2_surf->base.PresentOpaque);
399   assert(visual_idx != -1);
400
401   if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) {
402      dri2_surf->format = dri2_wl_visuals[visual_idx].wl_drm_format;
403   } else {
404      assert(dri2_dpy->wl_shm);
405      dri2_surf->format = dri2_wl_visuals[visual_idx].wl_shm_format;
406   }
407
408   dri2_surf->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
409   if (!dri2_surf->wl_queue) {
410      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
411      goto cleanup_surf;
412   }
413
414   if (dri2_dpy->wl_drm) {
415      dri2_surf->wl_drm_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_drm);
416      if (!dri2_surf->wl_drm_wrapper) {
417         _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
418         goto cleanup_queue;
419      }
420      wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_drm_wrapper,
421                         dri2_surf->wl_queue);
422   }
423
424   dri2_surf->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy);
425   if (!dri2_surf->wl_dpy_wrapper) {
426      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
427      goto cleanup_drm;
428   }
429   wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_dpy_wrapper,
430                      dri2_surf->wl_queue);
431
432   dri2_surf->wl_surface_wrapper = get_wl_surface_proxy(window);
433   if (!dri2_surf->wl_surface_wrapper) {
434      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
435      goto cleanup_dpy_wrapper;
436   }
437   wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_surface_wrapper,
438                      dri2_surf->wl_queue);
439
440   dri2_surf->wl_win = window;
441   dri2_surf->wl_win->driver_private = dri2_surf;
442   dri2_surf->wl_win->destroy_window_callback = destroy_window_callback;
443   if (dri2_dpy->flush)
444      dri2_surf->wl_win->resize_callback = resize_callback;
445
446   if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
447       goto cleanup_surf_wrapper;
448
449   dri2_surf->base.SwapInterval = dri2_dpy->default_swap_interval;
450
451   return &dri2_surf->base;
452
453 cleanup_surf_wrapper:
454   wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
455 cleanup_dpy_wrapper:
456   wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
457 cleanup_drm:
458   if (dri2_surf->wl_drm_wrapper)
459      wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper);
460 cleanup_queue:
461   wl_event_queue_destroy(dri2_surf->wl_queue);
462 cleanup_surf:
463   free(dri2_surf);
464
465   return NULL;
466}
467
468static _EGLSurface *
469dri2_wl_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
470                              void *native_window, const EGLint *attrib_list)
471{
472   /* From the EGL_EXT_platform_wayland spec, version 3:
473    *
474    *   It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
475    *   that belongs to Wayland. Any such call fails and generates
476    *   EGL_BAD_PARAMETER.
477    */
478   _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on "
479             "Wayland");
480   return NULL;
481}
482
483/**
484 * Called via eglDestroySurface(), drv->DestroySurface().
485 */
486static EGLBoolean
487dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
488{
489   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
490   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
491
492   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
493
494   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
495      if (dri2_surf->color_buffers[i].wl_buffer)
496         wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
497      if (dri2_surf->color_buffers[i].dri_image)
498         dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
499      if (dri2_surf->color_buffers[i].linear_copy)
500         dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
501      if (dri2_surf->color_buffers[i].data)
502         munmap(dri2_surf->color_buffers[i].data,
503                dri2_surf->color_buffers[i].data_size);
504   }
505
506   if (dri2_dpy->dri2)
507      dri2_egl_surface_free_local_buffers(dri2_surf);
508
509   if (dri2_surf->throttle_callback)
510      wl_callback_destroy(dri2_surf->throttle_callback);
511
512   if (dri2_surf->wl_win) {
513      dri2_surf->wl_win->driver_private = NULL;
514      dri2_surf->wl_win->resize_callback = NULL;
515      dri2_surf->wl_win->destroy_window_callback = NULL;
516   }
517
518   wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
519   wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
520   if (dri2_surf->wl_drm_wrapper)
521      wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper);
522   wl_event_queue_destroy(dri2_surf->wl_queue);
523
524   dri2_fini_surface(surf);
525   free(surf);
526
527   return EGL_TRUE;
528}
529
530static void
531dri2_wl_release_buffers(struct dri2_egl_surface *dri2_surf)
532{
533   struct dri2_egl_display *dri2_dpy =
534      dri2_egl_display(dri2_surf->base.Resource.Display);
535
536   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
537      if (dri2_surf->color_buffers[i].wl_buffer) {
538         if (dri2_surf->color_buffers[i].locked) {
539            dri2_surf->color_buffers[i].wl_release = true;
540         } else {
541            wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
542            dri2_surf->color_buffers[i].wl_buffer = NULL;
543         }
544      }
545      if (dri2_surf->color_buffers[i].dri_image)
546         dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
547      if (dri2_surf->color_buffers[i].linear_copy)
548         dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
549      if (dri2_surf->color_buffers[i].data)
550         munmap(dri2_surf->color_buffers[i].data,
551                dri2_surf->color_buffers[i].data_size);
552
553      dri2_surf->color_buffers[i].dri_image = NULL;
554      dri2_surf->color_buffers[i].linear_copy = NULL;
555      dri2_surf->color_buffers[i].data = NULL;
556   }
557
558   if (dri2_dpy->dri2)
559      dri2_egl_surface_free_local_buffers(dri2_surf);
560}
561
562static int
563get_back_bo(struct dri2_egl_surface *dri2_surf)
564{
565   struct dri2_egl_display *dri2_dpy =
566      dri2_egl_display(dri2_surf->base.Resource.Display);
567   int use_flags;
568   int visual_idx;
569   unsigned int dri_image_format;
570   unsigned int linear_dri_image_format;
571   uint64_t *modifiers;
572   int num_modifiers;
573
574   visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
575   assert(visual_idx != -1);
576   dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format;
577   linear_dri_image_format = dri_image_format;
578   modifiers = u_vector_tail(&dri2_dpy->wl_modifiers[visual_idx]);
579   num_modifiers = u_vector_length(&dri2_dpy->wl_modifiers[visual_idx]);
580
581   if (num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) {
582      /* For the purposes of this function, an INVALID modifier on its own
583       * means the modifiers aren't supported.
584       */
585      num_modifiers = 0;
586   }
587
588   /* Substitute dri image format if server does not support original format */
589   if (!BITSET_TEST(dri2_dpy->formats, visual_idx))
590      linear_dri_image_format = dri2_wl_visuals[visual_idx].alt_dri_image_format;
591
592   /* These asserts hold, as long as dri2_wl_visuals[] is self-consistent and
593    * the PRIME substitution logic in dri2_wl_add_configs_for_visuals() is free
594    * of bugs.
595    */
596   assert(linear_dri_image_format != __DRI_IMAGE_FORMAT_NONE);
597   assert(BITSET_TEST(dri2_dpy->formats,
598          dri2_wl_visual_idx_from_dri_image_format(linear_dri_image_format)));
599
600   /* There might be a buffer release already queued that wasn't processed */
601   wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue);
602
603   while (dri2_surf->back == NULL) {
604      for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
605         /* Get an unlocked buffer, preferably one with a dri_buffer
606          * already allocated. */
607         if (dri2_surf->color_buffers[i].locked)
608            continue;
609         if (dri2_surf->back == NULL)
610            dri2_surf->back = &dri2_surf->color_buffers[i];
611         else if (dri2_surf->back->dri_image == NULL)
612            dri2_surf->back = &dri2_surf->color_buffers[i];
613      }
614
615      if (dri2_surf->back)
616         break;
617
618      /* If we don't have a buffer, then block on the server to release one for
619       * us, and try again. wl_display_dispatch_queue will process any pending
620       * events, however not all servers flush on issuing a buffer release
621       * event. So, we spam the server with roundtrips as they always cause a
622       * client flush.
623       */
624      if (wl_display_roundtrip_queue(dri2_dpy->wl_dpy,
625                                     dri2_surf->wl_queue) < 0)
626          return -1;
627   }
628
629   if (dri2_surf->back == NULL)
630      return -1;
631
632   use_flags = __DRI_IMAGE_USE_SHARE | __DRI_IMAGE_USE_BACKBUFFER;
633
634   if (dri2_surf->base.ProtectedContent) {
635      /* Protected buffers can't be read from another GPU */
636      if (dri2_dpy->is_different_gpu)
637         return -1;
638      use_flags |= __DRI_IMAGE_USE_PROTECTED;
639   }
640
641   if (dri2_dpy->is_different_gpu &&
642       dri2_surf->back->linear_copy == NULL) {
643      /* The LINEAR modifier should be a perfect alias of the LINEAR use
644       * flag; try the new interface first before the old, then fall back. */
645      uint64_t linear_mod = DRM_FORMAT_MOD_LINEAR;
646
647      dri2_surf->back->linear_copy =
648            loader_dri_create_image(dri2_dpy->dri_screen, dri2_dpy->image,
649                                    dri2_surf->base.Width,
650                                    dri2_surf->base.Height,
651                                    linear_dri_image_format,
652                                    use_flags | __DRI_IMAGE_USE_LINEAR,
653                                    &linear_mod, 1, NULL);
654
655      if (dri2_surf->back->linear_copy == NULL)
656          return -1;
657   }
658
659   if (dri2_surf->back->dri_image == NULL) {
660      /* If our DRIImage implementation does not support
661       * createImageWithModifiers, then fall back to the old createImage,
662       * and hope it allocates an image which is acceptable to the winsys.
663        */
664      dri2_surf->back->dri_image =
665            loader_dri_create_image(dri2_dpy->dri_screen, dri2_dpy->image,
666                                    dri2_surf->base.Width,
667                                    dri2_surf->base.Height,
668                                    dri_image_format,
669                                    dri2_dpy->is_different_gpu ? 0 : use_flags,
670                                    modifiers, num_modifiers, NULL);
671
672      dri2_surf->back->age = 0;
673   }
674   if (dri2_surf->back->dri_image == NULL)
675      return -1;
676
677   dri2_surf->back->locked = true;
678
679   return 0;
680}
681
682
683static void
684back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
685{
686   struct dri2_egl_display *dri2_dpy =
687      dri2_egl_display(dri2_surf->base.Resource.Display);
688   __DRIimage *image;
689   int name, pitch;
690
691   image = dri2_surf->back->dri_image;
692
693   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
694   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
695
696   buffer->attachment = __DRI_BUFFER_BACK_LEFT;
697   buffer->name = name;
698   buffer->pitch = pitch;
699   buffer->cpp = 4;
700   buffer->flags = 0;
701}
702
703static int
704update_buffers(struct dri2_egl_surface *dri2_surf)
705{
706   struct dri2_egl_display *dri2_dpy =
707      dri2_egl_display(dri2_surf->base.Resource.Display);
708
709   if (dri2_surf->wl_win &&
710       (dri2_surf->base.Width != dri2_surf->wl_win->width ||
711        dri2_surf->base.Height != dri2_surf->wl_win->height)) {
712
713      dri2_surf->base.Width  = dri2_surf->wl_win->width;
714      dri2_surf->base.Height = dri2_surf->wl_win->height;
715      dri2_surf->dx = dri2_surf->wl_win->dx;
716      dri2_surf->dy = dri2_surf->wl_win->dy;
717   }
718
719   if (dri2_surf->resized) {
720       dri2_wl_release_buffers(dri2_surf);
721       dri2_surf->resized = false;
722   }
723
724   if (get_back_bo(dri2_surf) < 0) {
725      _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
726      return -1;
727   }
728
729   /* If we have an extra unlocked buffer at this point, we had to do triple
730    * buffering for a while, but now can go back to just double buffering.
731    * That means we can free any unlocked buffer now. */
732   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
733      if (!dri2_surf->color_buffers[i].locked &&
734          dri2_surf->color_buffers[i].wl_buffer) {
735         wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
736         dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image);
737         if (dri2_dpy->is_different_gpu)
738            dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy);
739         dri2_surf->color_buffers[i].wl_buffer = NULL;
740         dri2_surf->color_buffers[i].dri_image = NULL;
741         dri2_surf->color_buffers[i].linear_copy = NULL;
742      }
743   }
744
745   return 0;
746}
747
748static int
749update_buffers_if_needed(struct dri2_egl_surface *dri2_surf)
750{
751   if (dri2_surf->back != NULL)
752      return 0;
753
754   return update_buffers(dri2_surf);
755}
756
757static __DRIbuffer *
758dri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable,
759                                int *width, int *height,
760                                unsigned int *attachments, int count,
761                                int *out_count, void *loaderPrivate)
762{
763   struct dri2_egl_surface *dri2_surf = loaderPrivate;
764   int i, j;
765
766   if (update_buffers(dri2_surf) < 0)
767      return NULL;
768
769   for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
770      __DRIbuffer *local;
771
772      switch (attachments[i]) {
773      case __DRI_BUFFER_BACK_LEFT:
774         back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
775         break;
776      default:
777         local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i],
778                                                     attachments[i + 1]);
779
780         if (!local) {
781            _eglError(EGL_BAD_ALLOC, "failed to allocate local buffer");
782            return NULL;
783         }
784         dri2_surf->buffers[j] = *local;
785         break;
786      }
787   }
788
789   *out_count = j;
790   if (j == 0)
791      return NULL;
792
793   *width = dri2_surf->base.Width;
794   *height = dri2_surf->base.Height;
795
796   return dri2_surf->buffers;
797}
798
799static __DRIbuffer *
800dri2_wl_get_buffers(__DRIdrawable * driDrawable,
801                    int *width, int *height,
802                    unsigned int *attachments, int count,
803                    int *out_count, void *loaderPrivate)
804{
805   struct dri2_egl_surface *dri2_surf = loaderPrivate;
806   unsigned int *attachments_with_format;
807   __DRIbuffer *buffer;
808   int visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
809
810   if (visual_idx == -1)
811      return NULL;
812
813   attachments_with_format = calloc(count, 2 * sizeof(unsigned int));
814   if (!attachments_with_format) {
815      *out_count = 0;
816      return NULL;
817   }
818
819   for (int i = 0; i < count; ++i) {
820      attachments_with_format[2*i] = attachments[i];
821      attachments_with_format[2*i + 1] = dri2_wl_visuals[visual_idx].bpp;
822   }
823
824   buffer =
825      dri2_wl_get_buffers_with_format(driDrawable,
826                                      width, height,
827                                      attachments_with_format, count,
828                                      out_count, loaderPrivate);
829
830   free(attachments_with_format);
831
832   return buffer;
833}
834
835static int
836image_get_buffers(__DRIdrawable *driDrawable,
837                  unsigned int format,
838                  uint32_t *stamp,
839                  void *loaderPrivate,
840                  uint32_t buffer_mask,
841                  struct __DRIimageList *buffers)
842{
843   struct dri2_egl_surface *dri2_surf = loaderPrivate;
844
845   if (update_buffers(dri2_surf) < 0)
846      return 0;
847
848   buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
849   buffers->back = dri2_surf->back->dri_image;
850
851   return 1;
852}
853
854static void
855dri2_wl_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
856{
857   (void) driDrawable;
858   (void) loaderPrivate;
859}
860
861static unsigned
862dri2_wl_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
863{
864   switch (cap) {
865   case DRI_LOADER_CAP_FP16:
866      return 1;
867   case DRI_LOADER_CAP_RGBA_ORDERING:
868      return 1;
869   default:
870      return 0;
871   }
872}
873
874static const __DRIdri2LoaderExtension dri2_loader_extension = {
875   .base = { __DRI_DRI2_LOADER, 4 },
876
877   .getBuffers           = dri2_wl_get_buffers,
878   .flushFrontBuffer     = dri2_wl_flush_front_buffer,
879   .getBuffersWithFormat = dri2_wl_get_buffers_with_format,
880   .getCapability        = dri2_wl_get_capability,
881};
882
883static const __DRIimageLoaderExtension image_loader_extension = {
884   .base = { __DRI_IMAGE_LOADER, 2 },
885
886   .getBuffers          = image_get_buffers,
887   .flushFrontBuffer    = dri2_wl_flush_front_buffer,
888   .getCapability       = dri2_wl_get_capability,
889};
890
891static void
892wayland_throttle_callback(void *data,
893                          struct wl_callback *callback,
894                          uint32_t time)
895{
896   struct dri2_egl_surface *dri2_surf = data;
897
898   dri2_surf->throttle_callback = NULL;
899   wl_callback_destroy(callback);
900}
901
902static const struct wl_callback_listener throttle_listener = {
903   .done = wayland_throttle_callback
904};
905
906static EGLBoolean
907get_fourcc(struct dri2_egl_display *dri2_dpy,
908           __DRIimage *image, int *fourcc)
909{
910   EGLBoolean query;
911   int dri_format;
912   int visual_idx;
913
914   query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FOURCC,
915                                       fourcc);
916   if (query)
917      return true;
918
919   query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT,
920                                       &dri_format);
921   if (!query)
922      return false;
923
924   visual_idx = dri2_wl_visual_idx_from_dri_image_format(dri_format);
925   if (visual_idx == -1)
926      return false;
927
928   *fourcc = dri2_wl_visuals[visual_idx].wl_drm_format;
929   return true;
930}
931
932static struct wl_buffer *
933create_wl_buffer(struct dri2_egl_display *dri2_dpy,
934                 struct dri2_egl_surface *dri2_surf,
935                 __DRIimage *image)
936{
937   struct wl_buffer *ret;
938   EGLBoolean query;
939   int width, height, fourcc, num_planes;
940   uint64_t modifier = DRM_FORMAT_MOD_INVALID;
941
942   query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width);
943   query &= dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT,
944                                        &height);
945   query &= get_fourcc(dri2_dpy, image, &fourcc);
946   if (!query)
947      return NULL;
948
949   query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES,
950                                       &num_planes);
951   if (!query)
952      num_planes = 1;
953
954   if (dri2_dpy->image->base.version >= 15) {
955      int mod_hi, mod_lo;
956
957      query = dri2_dpy->image->queryImage(image,
958                                          __DRI_IMAGE_ATTRIB_MODIFIER_UPPER,
959                                          &mod_hi);
960      query &= dri2_dpy->image->queryImage(image,
961                                           __DRI_IMAGE_ATTRIB_MODIFIER_LOWER,
962                                           &mod_lo);
963      if (query) {
964         modifier = combine_u32_into_u64(mod_hi, mod_lo);
965      }
966   }
967
968   bool supported_modifier = false;
969   bool mod_invalid_supported = false;
970   int visual_idx = dri2_wl_visual_idx_from_fourcc(fourcc);
971   assert(visual_idx != -1);
972
973   uint64_t *mod;
974   u_vector_foreach(mod, &dri2_dpy->wl_modifiers[visual_idx]) {
975      if (*mod == DRM_FORMAT_MOD_INVALID) {
976         mod_invalid_supported = true;
977      }
978      if (*mod == modifier) {
979         supported_modifier = true;
980         break;
981      }
982   }
983   if (!supported_modifier && mod_invalid_supported) {
984      /* If the server has advertised DRM_FORMAT_MOD_INVALID then we trust
985       * that the client has allocated the buffer with the right implicit
986       * modifier for the format, even though it's allocated a buffer the
987       * server hasn't explicitly claimed to support. */
988      modifier = DRM_FORMAT_MOD_INVALID;
989      supported_modifier = true;
990   }
991
992   if (dri2_dpy->wl_dmabuf && supported_modifier) {
993      struct zwp_linux_buffer_params_v1 *params;
994      int i;
995
996      /* We don't need a wrapper for wl_dmabuf objects, because we have to
997       * create the intermediate params object; we can set the queue on this,
998       * and the wl_buffer inherits it race-free. */
999      params = zwp_linux_dmabuf_v1_create_params(dri2_dpy->wl_dmabuf);
1000      if (dri2_surf)
1001         wl_proxy_set_queue((struct wl_proxy *) params, dri2_surf->wl_queue);
1002
1003      for (i = 0; i < num_planes; i++) {
1004         __DRIimage *p_image;
1005         int stride, offset;
1006         int fd = -1;
1007
1008         p_image = dri2_dpy->image->fromPlanar(image, i, NULL);
1009         if (!p_image) {
1010            assert(i == 0);
1011            p_image = image;
1012         }
1013
1014         query = dri2_dpy->image->queryImage(p_image,
1015                                             __DRI_IMAGE_ATTRIB_FD,
1016                                             &fd);
1017         query &= dri2_dpy->image->queryImage(p_image,
1018                                              __DRI_IMAGE_ATTRIB_STRIDE,
1019                                              &stride);
1020         query &= dri2_dpy->image->queryImage(p_image,
1021                                              __DRI_IMAGE_ATTRIB_OFFSET,
1022                                              &offset);
1023         if (image != p_image)
1024            dri2_dpy->image->destroyImage(p_image);
1025
1026         if (!query) {
1027            if (fd >= 0)
1028               close(fd);
1029            zwp_linux_buffer_params_v1_destroy(params);
1030            return NULL;
1031         }
1032
1033         zwp_linux_buffer_params_v1_add(params, fd, i, offset, stride,
1034                                        modifier >> 32, modifier & 0xffffffff);
1035         close(fd);
1036      }
1037
1038      ret = zwp_linux_buffer_params_v1_create_immed(params, width, height,
1039                                                    fourcc, 0);
1040      zwp_linux_buffer_params_v1_destroy(params);
1041   } else if (dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) {
1042      struct wl_drm *wl_drm =
1043         dri2_surf ? dri2_surf->wl_drm_wrapper : dri2_dpy->wl_drm;
1044      int fd, stride;
1045
1046      if (num_planes > 1)
1047         return NULL;
1048
1049      dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd);
1050      dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
1051      ret = wl_drm_create_prime_buffer(wl_drm, fd, width, height, fourcc, 0,
1052                                       stride, 0, 0, 0, 0);
1053      close(fd);
1054   } else {
1055      struct wl_drm *wl_drm =
1056         dri2_surf ? dri2_surf->wl_drm_wrapper : dri2_dpy->wl_drm;
1057      int name, stride;
1058
1059      if (num_planes > 1)
1060         return NULL;
1061
1062      dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
1063      dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride);
1064      ret = wl_drm_create_buffer(wl_drm, name, width, height, stride, fourcc);
1065   }
1066
1067   return ret;
1068}
1069
1070static EGLBoolean
1071try_damage_buffer(struct dri2_egl_surface *dri2_surf,
1072                  const EGLint *rects,
1073                  EGLint n_rects)
1074{
1075   if (wl_proxy_get_version((struct wl_proxy *) dri2_surf->wl_surface_wrapper)
1076       < WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
1077      return EGL_FALSE;
1078
1079   for (int i = 0; i < n_rects; i++) {
1080      const int *rect = &rects[i * 4];
1081
1082      wl_surface_damage_buffer(dri2_surf->wl_surface_wrapper,
1083                               rect[0],
1084                               dri2_surf->base.Height - rect[1] - rect[3],
1085                               rect[2], rect[3]);
1086   }
1087   return EGL_TRUE;
1088}
1089
1090/**
1091 * Called via eglSwapBuffers(), drv->SwapBuffers().
1092 */
1093static EGLBoolean
1094dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
1095                                 _EGLSurface *draw,
1096                                 const EGLint *rects,
1097                                 EGLint n_rects)
1098{
1099   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1100   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1101
1102   if (!dri2_surf->wl_win)
1103      return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers");
1104
1105   while (dri2_surf->throttle_callback != NULL)
1106      if (wl_display_dispatch_queue(dri2_dpy->wl_dpy,
1107                                    dri2_surf->wl_queue) == -1)
1108         return -1;
1109
1110   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
1111      if (dri2_surf->color_buffers[i].age > 0)
1112         dri2_surf->color_buffers[i].age++;
1113
1114   /* Make sure we have a back buffer in case we're swapping without ever
1115    * rendering. */
1116   if (update_buffers_if_needed(dri2_surf) < 0)
1117      return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
1118
1119   if (draw->SwapInterval > 0) {
1120      dri2_surf->throttle_callback =
1121         wl_surface_frame(dri2_surf->wl_surface_wrapper);
1122      wl_callback_add_listener(dri2_surf->throttle_callback,
1123                               &throttle_listener, dri2_surf);
1124   }
1125
1126   dri2_surf->back->age = 1;
1127   dri2_surf->current = dri2_surf->back;
1128   dri2_surf->back = NULL;
1129
1130   if (!dri2_surf->current->wl_buffer) {
1131      __DRIimage *image;
1132
1133      if (dri2_dpy->is_different_gpu)
1134         image = dri2_surf->current->linear_copy;
1135      else
1136         image = dri2_surf->current->dri_image;
1137
1138      dri2_surf->current->wl_buffer =
1139         create_wl_buffer(dri2_dpy, dri2_surf, image);
1140
1141      dri2_surf->current->wl_release = false;
1142
1143      wl_buffer_add_listener(dri2_surf->current->wl_buffer,
1144                             &wl_buffer_listener, dri2_surf);
1145   }
1146
1147   wl_surface_attach(dri2_surf->wl_surface_wrapper,
1148                     dri2_surf->current->wl_buffer,
1149                     dri2_surf->dx, dri2_surf->dy);
1150
1151   dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
1152   dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
1153   /* reset resize growing parameters */
1154   dri2_surf->dx = 0;
1155   dri2_surf->dy = 0;
1156
1157   /* If the compositor doesn't support damage_buffer, we deliberately
1158    * ignore the damage region and post maximum damage, due to
1159    * https://bugs.freedesktop.org/78190 */
1160   if (!n_rects || !try_damage_buffer(dri2_surf, rects, n_rects))
1161      wl_surface_damage(dri2_surf->wl_surface_wrapper,
1162                        0, 0, INT32_MAX, INT32_MAX);
1163
1164   if (dri2_dpy->is_different_gpu) {
1165      _EGLContext *ctx = _eglGetCurrentContext();
1166      struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1167      dri2_dpy->image->blitImage(dri2_ctx->dri_context,
1168                                 dri2_surf->current->linear_copy,
1169                                 dri2_surf->current->dri_image,
1170                                 0, 0, dri2_surf->base.Width,
1171                                 dri2_surf->base.Height,
1172                                 0, 0, dri2_surf->base.Width,
1173                                 dri2_surf->base.Height, 0);
1174   }
1175
1176   dri2_flush_drawable_for_swapbuffers(disp, draw);
1177   dri2_dpy->flush->invalidate(dri2_surf->dri_drawable);
1178
1179   wl_surface_commit(dri2_surf->wl_surface_wrapper);
1180
1181   /* If we're not waiting for a frame callback then we'll at least throttle
1182    * to a sync callback so that we always give a chance for the compositor to
1183    * handle the commit and send a release event before checking for a free
1184    * buffer */
1185   if (dri2_surf->throttle_callback == NULL) {
1186      dri2_surf->throttle_callback = wl_display_sync(dri2_surf->wl_dpy_wrapper);
1187      wl_callback_add_listener(dri2_surf->throttle_callback,
1188                               &throttle_listener, dri2_surf);
1189   }
1190
1191   wl_display_flush(dri2_dpy->wl_dpy);
1192
1193   return EGL_TRUE;
1194}
1195
1196static EGLint
1197dri2_wl_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
1198{
1199   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
1200
1201   if (update_buffers_if_needed(dri2_surf) < 0) {
1202      _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
1203      return -1;
1204   }
1205
1206   return dri2_surf->back->age;
1207}
1208
1209static EGLBoolean
1210dri2_wl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
1211{
1212   return dri2_wl_swap_buffers_with_damage(disp, draw, NULL, 0);
1213}
1214
1215static struct wl_buffer *
1216dri2_wl_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img)
1217{
1218   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1219   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
1220   __DRIimage *image = dri2_img->dri_image;
1221   struct wl_buffer *buffer;
1222   int format, visual_idx;
1223
1224   /* Check the upstream display supports this buffer's format. */
1225   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
1226   visual_idx = dri2_wl_visual_idx_from_dri_image_format(format);
1227   if (visual_idx == -1)
1228      goto bad_format;
1229
1230   if (!BITSET_TEST(dri2_dpy->formats, visual_idx))
1231      goto bad_format;
1232
1233   buffer = create_wl_buffer(dri2_dpy, NULL, image);
1234
1235   /* The buffer object will have been created with our internal event queue
1236    * because it is using wl_dmabuf/wl_drm as a proxy factory. We want the
1237    * buffer to be used by the application so we'll reset it to the display's
1238    * default event queue. This isn't actually racy, as the only event the
1239    * buffer can get is a buffer release, which doesn't happen with an explicit
1240    * attach. */
1241   if (buffer)
1242      wl_proxy_set_queue((struct wl_proxy *) buffer, NULL);
1243
1244   return buffer;
1245
1246bad_format:
1247   _eglError(EGL_BAD_MATCH, "unsupported image format");
1248   return NULL;
1249}
1250
1251static int
1252dri2_wl_authenticate(_EGLDisplay *disp, uint32_t id)
1253{
1254   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1255   int ret = 0;
1256
1257   if (dri2_dpy->is_render_node) {
1258      _eglLog(_EGL_WARNING, "wayland-egl: client asks server to "
1259                            "authenticate for render-nodes");
1260      return 0;
1261   }
1262   dri2_dpy->authenticated = false;
1263
1264   wl_drm_authenticate(dri2_dpy->wl_drm, id);
1265   if (roundtrip(dri2_dpy) < 0)
1266      ret = -1;
1267
1268   if (!dri2_dpy->authenticated)
1269      ret = -1;
1270
1271   /* reset authenticated */
1272   dri2_dpy->authenticated = true;
1273
1274   return ret;
1275}
1276
1277static void
1278drm_handle_device(void *data, struct wl_drm *drm, const char *device)
1279{
1280   struct dri2_egl_display *dri2_dpy = data;
1281   drm_magic_t magic;
1282
1283   dri2_dpy->device_name = strdup(device);
1284   if (!dri2_dpy->device_name)
1285      return;
1286
1287   dri2_dpy->fd = loader_open_device(dri2_dpy->device_name);
1288   if (dri2_dpy->fd == -1) {
1289      _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
1290              dri2_dpy->device_name, strerror(errno));
1291      free(dri2_dpy->device_name);
1292      dri2_dpy->device_name = NULL;
1293      return;
1294   }
1295
1296   if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER) {
1297      dri2_dpy->authenticated = true;
1298   } else {
1299      if (drmGetMagic(dri2_dpy->fd, &magic)) {
1300         close(dri2_dpy->fd);
1301         dri2_dpy->fd = -1;
1302         free(dri2_dpy->device_name);
1303         dri2_dpy->device_name = NULL;
1304         _eglLog(_EGL_WARNING, "wayland-egl: drmGetMagic failed");
1305         return;
1306      }
1307      wl_drm_authenticate(dri2_dpy->wl_drm, magic);
1308   }
1309}
1310
1311static void
1312drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
1313{
1314   struct dri2_egl_display *dri2_dpy = data;
1315   int visual_idx = dri2_wl_visual_idx_from_fourcc(format);
1316
1317   if (visual_idx == -1)
1318      return;
1319
1320   BITSET_SET(dri2_dpy->formats, visual_idx);
1321}
1322
1323static void
1324drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
1325{
1326   struct dri2_egl_display *dri2_dpy = data;
1327
1328   dri2_dpy->capabilities = value;
1329}
1330
1331static void
1332drm_handle_authenticated(void *data, struct wl_drm *drm)
1333{
1334   struct dri2_egl_display *dri2_dpy = data;
1335
1336   dri2_dpy->authenticated = true;
1337}
1338
1339static const struct wl_drm_listener drm_listener = {
1340   .device = drm_handle_device,
1341   .format = drm_handle_format,
1342   .authenticated = drm_handle_authenticated,
1343   .capabilities = drm_handle_capabilities
1344};
1345
1346static void
1347dmabuf_ignore_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
1348                     uint32_t format)
1349{
1350   /* formats are implicitly advertised by the 'modifier' event, so ignore */
1351}
1352
1353static void
1354dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
1355                       uint32_t format, uint32_t modifier_hi,
1356                       uint32_t modifier_lo)
1357{
1358   struct dri2_egl_display *dri2_dpy = data;
1359   int visual_idx = dri2_wl_visual_idx_from_fourcc(format);
1360   uint64_t *mod;
1361
1362   if (visual_idx == -1)
1363      return;
1364
1365   BITSET_SET(dri2_dpy->formats, visual_idx);
1366
1367   mod = u_vector_add(&dri2_dpy->wl_modifiers[visual_idx]);
1368   *mod = combine_u32_into_u64(modifier_hi, modifier_lo);
1369}
1370
1371static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
1372   .format = dmabuf_ignore_format,
1373   .modifier = dmabuf_handle_modifier,
1374};
1375
1376static void
1377registry_handle_global_drm(void *data, struct wl_registry *registry,
1378                           uint32_t name, const char *interface,
1379                           uint32_t version)
1380{
1381   struct dri2_egl_display *dri2_dpy = data;
1382
1383   if (strcmp(interface, "wl_drm") == 0) {
1384      dri2_dpy->wl_drm =
1385         wl_registry_bind(registry, name, &wl_drm_interface, MIN2(version, 2));
1386      wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy);
1387   } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) {
1388      dri2_dpy->wl_dmabuf =
1389         wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface,
1390                          MIN2(version, 3));
1391      zwp_linux_dmabuf_v1_add_listener(dri2_dpy->wl_dmabuf, &dmabuf_listener,
1392                                       dri2_dpy);
1393   }
1394}
1395
1396static void
1397registry_handle_global_remove(void *data, struct wl_registry *registry,
1398                              uint32_t name)
1399{
1400}
1401
1402static const struct wl_registry_listener registry_listener_drm = {
1403   .global = registry_handle_global_drm,
1404   .global_remove = registry_handle_global_remove
1405};
1406
1407static void
1408dri2_wl_setup_swap_interval(_EGLDisplay *disp)
1409{
1410   /* We can't use values greater than 1 on Wayland because we are using the
1411    * frame callback to synchronise the frame and the only way we be sure to
1412    * get a frame callback is to attach a new buffer. Therefore we can't just
1413    * sit drawing nothing to wait until the next ‘n’ frame callbacks */
1414
1415   dri2_setup_swap_interval(disp, 1);
1416}
1417
1418static const struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
1419   .authenticate = dri2_wl_authenticate,
1420   .create_window_surface = dri2_wl_create_window_surface,
1421   .create_pixmap_surface = dri2_wl_create_pixmap_surface,
1422   .destroy_surface = dri2_wl_destroy_surface,
1423   .create_image = dri2_create_image_khr,
1424   .swap_buffers = dri2_wl_swap_buffers,
1425   .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage,
1426   .query_buffer_age = dri2_wl_query_buffer_age,
1427   .create_wayland_buffer_from_image = dri2_wl_create_wayland_buffer_from_image,
1428   .get_dri_drawable = dri2_surface_get_dri_drawable,
1429};
1430
1431static const __DRIextension *dri2_loader_extensions[] = {
1432   &dri2_loader_extension.base,
1433   &image_loader_extension.base,
1434   &image_lookup_extension.base,
1435   &use_invalidate.base,
1436   NULL,
1437};
1438
1439static const __DRIextension *image_loader_extensions[] = {
1440   &image_loader_extension.base,
1441   &image_lookup_extension.base,
1442   &use_invalidate.base,
1443   NULL,
1444};
1445
1446static EGLBoolean
1447dri2_wl_add_configs_for_visuals(_EGLDisplay *disp)
1448{
1449   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1450   unsigned int format_count[ARRAY_SIZE(dri2_wl_visuals)] = { 0 };
1451   unsigned int count = 0;
1452   bool assigned;
1453
1454   for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
1455      assigned = false;
1456
1457      for (unsigned j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) {
1458         struct dri2_egl_config *dri2_conf;
1459
1460         if (!BITSET_TEST(dri2_dpy->formats, j))
1461            continue;
1462
1463         dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
1464               count + 1, EGL_WINDOW_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
1465         if (dri2_conf) {
1466            if (dri2_conf->base.ConfigID == count + 1)
1467               count++;
1468            format_count[j]++;
1469            assigned = true;
1470         }
1471      }
1472
1473      if (!assigned && dri2_dpy->is_different_gpu) {
1474         struct dri2_egl_config *dri2_conf;
1475         int alt_dri_image_format, c, s;
1476
1477         /* No match for config. Try if we can blitImage convert to a visual */
1478         c = dri2_wl_visual_idx_from_config(dri2_dpy,
1479                                            dri2_dpy->driver_configs[i],
1480                                            false);
1481
1482         if (c == -1)
1483            continue;
1484
1485         /* Find optimal target visual for blitImage conversion, if any. */
1486         alt_dri_image_format = dri2_wl_visuals[c].alt_dri_image_format;
1487         s = dri2_wl_visual_idx_from_dri_image_format(alt_dri_image_format);
1488
1489         if (s == -1 || !BITSET_TEST(dri2_dpy->formats, s))
1490            continue;
1491
1492         /* Visual s works for the Wayland server, and c can be converted into s
1493          * by our client gpu during PRIME blitImage conversion to a linear
1494          * wl_buffer, so add visual c as supported by the client renderer.
1495          */
1496         dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
1497                                     count + 1, EGL_WINDOW_BIT, NULL,
1498                                     dri2_wl_visuals[c].rgba_shifts,
1499                                     dri2_wl_visuals[c].rgba_sizes);
1500         if (dri2_conf) {
1501            if (dri2_conf->base.ConfigID == count + 1)
1502               count++;
1503            format_count[c]++;
1504            if (format_count[c] == 1)
1505               _eglLog(_EGL_DEBUG, "Client format %s to server format %s via "
1506                       "PRIME blitImage.", dri2_wl_visuals[c].format_name,
1507                       dri2_wl_visuals[s].format_name);
1508         }
1509      }
1510   }
1511
1512   for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) {
1513      if (!format_count[i]) {
1514         _eglLog(_EGL_DEBUG, "No DRI config supports native format %s",
1515                 dri2_wl_visuals[i].format_name);
1516      }
1517   }
1518
1519   return (count != 0);
1520}
1521
1522static EGLBoolean
1523dri2_initialize_wayland_drm(_EGLDisplay *disp)
1524{
1525   _EGLDevice *dev;
1526   struct dri2_egl_display *dri2_dpy;
1527
1528   dri2_dpy = calloc(1, sizeof *dri2_dpy);
1529   if (!dri2_dpy)
1530      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1531
1532   dri2_dpy->fd = -1;
1533   disp->DriverData = (void *) dri2_dpy;
1534   if (disp->PlatformDisplay == NULL) {
1535      dri2_dpy->wl_dpy = wl_display_connect(NULL);
1536      if (dri2_dpy->wl_dpy == NULL)
1537         goto cleanup;
1538      dri2_dpy->own_device = true;
1539   } else {
1540      dri2_dpy->wl_dpy = disp->PlatformDisplay;
1541   }
1542
1543   dri2_dpy->wl_modifiers =
1544      calloc(ARRAY_SIZE(dri2_wl_visuals), sizeof(*dri2_dpy->wl_modifiers));
1545   if (!dri2_dpy->wl_modifiers)
1546      goto cleanup;
1547   for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) {
1548      if (!u_vector_init_pow2(&dri2_dpy->wl_modifiers[i], 4, sizeof(uint64_t)))
1549         goto cleanup;
1550   }
1551
1552   dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
1553
1554   dri2_dpy->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy);
1555   if (dri2_dpy->wl_dpy_wrapper == NULL)
1556      goto cleanup;
1557
1558   wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_dpy_wrapper,
1559                      dri2_dpy->wl_queue);
1560
1561   if (dri2_dpy->own_device)
1562      wl_display_dispatch_pending(dri2_dpy->wl_dpy);
1563
1564   dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy_wrapper);
1565   wl_registry_add_listener(dri2_dpy->wl_registry,
1566                            &registry_listener_drm, dri2_dpy);
1567   if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_drm == NULL)
1568      goto cleanup;
1569
1570   if (roundtrip(dri2_dpy) < 0 || dri2_dpy->fd == -1)
1571      goto cleanup;
1572
1573   if (!dri2_dpy->authenticated &&
1574       (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated))
1575      goto cleanup;
1576
1577   dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
1578                                               &dri2_dpy->is_different_gpu);
1579   dev = _eglAddDevice(dri2_dpy->fd, false);
1580   if (!dev) {
1581      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
1582      goto cleanup;
1583   }
1584
1585   disp->Device = dev;
1586
1587   if (dri2_dpy->is_different_gpu) {
1588      free(dri2_dpy->device_name);
1589      dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
1590      if (!dri2_dpy->device_name) {
1591         _eglError(EGL_BAD_ALLOC, "wayland-egl: failed to get device name "
1592                                  "for requested GPU");
1593         goto cleanup;
1594      }
1595   }
1596
1597   /* we have to do the check now, because loader_get_user_preferred_fd
1598    * will return a render-node when the requested gpu is different
1599    * to the server, but also if the client asks for the same gpu than
1600    * the server by requesting its pci-id */
1601   dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER;
1602
1603   dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
1604   if (dri2_dpy->driver_name == NULL) {
1605      _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
1606      goto cleanup;
1607   }
1608
1609   /* render nodes cannot use Gem names, and thus do not support
1610    * the __DRI_DRI2_LOADER extension */
1611   if (!dri2_dpy->is_render_node) {
1612      dri2_dpy->loader_extensions = dri2_loader_extensions;
1613      if (!dri2_load_driver(disp)) {
1614         _eglError(EGL_BAD_ALLOC, "DRI2: failed to load driver");
1615         goto cleanup;
1616      }
1617   } else {
1618      dri2_dpy->loader_extensions = image_loader_extensions;
1619      if (!dri2_load_driver_dri3(disp)) {
1620         _eglError(EGL_BAD_ALLOC, "DRI3: failed to load driver");
1621         goto cleanup;
1622      }
1623   }
1624
1625   if (!dri2_create_screen(disp))
1626      goto cleanup;
1627
1628   if (!dri2_setup_extensions(disp))
1629      goto cleanup;
1630
1631   dri2_setup_screen(disp);
1632
1633   dri2_wl_setup_swap_interval(disp);
1634
1635   /* To use Prime, we must have _DRI_IMAGE v7 at least.
1636    * createImageFromFds support indicates that Prime export/import
1637    * is supported by the driver. Fall back to
1638    * gem names if we don't have Prime support. */
1639
1640   if (dri2_dpy->image->base.version < 7 ||
1641       dri2_dpy->image->createImageFromFds == NULL)
1642      dri2_dpy->capabilities &= ~WL_DRM_CAPABILITY_PRIME;
1643
1644   /* We cannot use Gem names with render-nodes, only prime fds (dma-buf).
1645    * The server needs to accept them */
1646   if (dri2_dpy->is_render_node &&
1647       !(dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME)) {
1648      _eglLog(_EGL_WARNING, "wayland-egl: display is not render-node capable");
1649      goto cleanup;
1650   }
1651
1652   if (dri2_dpy->is_different_gpu &&
1653       (dri2_dpy->image->base.version < 9 ||
1654        dri2_dpy->image->blitImage == NULL)) {
1655      _eglLog(_EGL_WARNING, "wayland-egl: Different GPU selected, but the "
1656                            "Image extension in the driver is not "
1657                            "compatible. Version 9 or later and blitImage() "
1658                            "are required");
1659      goto cleanup;
1660   }
1661
1662   if (!dri2_wl_add_configs_for_visuals(disp)) {
1663      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to add configs");
1664      goto cleanup;
1665   }
1666
1667   dri2_set_WL_bind_wayland_display(disp);
1668   /* When cannot convert EGLImage to wl_buffer when on a different gpu,
1669    * because the buffer of the EGLImage has likely a tiling mode the server
1670    * gpu won't support. These is no way to check for now. Thus do not support the
1671    * extension */
1672   if (!dri2_dpy->is_different_gpu)
1673      disp->Extensions.WL_create_wayland_buffer_from_image = EGL_TRUE;
1674
1675   disp->Extensions.EXT_buffer_age = EGL_TRUE;
1676
1677   disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE;
1678
1679   disp->Extensions.EXT_present_opaque = EGL_TRUE;
1680
1681   /* Fill vtbl last to prevent accidentally calling virtual function during
1682    * initialization.
1683    */
1684   dri2_dpy->vtbl = &dri2_wl_display_vtbl;
1685
1686   return EGL_TRUE;
1687
1688 cleanup:
1689   dri2_display_destroy(disp);
1690   return EGL_FALSE;
1691}
1692
1693static int
1694dri2_wl_swrast_get_stride_for_format(int format, int w)
1695{
1696   int visual_idx = dri2_wl_visual_idx_from_shm_format(format);
1697
1698   assume(visual_idx != -1);
1699
1700   return w * (dri2_wl_visuals[visual_idx].bpp / 8);
1701}
1702
1703static EGLBoolean
1704dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf,
1705                               int format, int w, int h,
1706                               void **data, int *size,
1707                               struct wl_buffer **buffer)
1708{
1709   struct dri2_egl_display *dri2_dpy =
1710      dri2_egl_display(dri2_surf->base.Resource.Display);
1711   struct wl_shm_pool *pool;
1712   int fd, stride, size_map;
1713   void *data_map;
1714
1715   stride = dri2_wl_swrast_get_stride_for_format(format, w);
1716   size_map = h * stride;
1717
1718   /* Create a shareable buffer */
1719   fd = os_create_anonymous_file(size_map, NULL);
1720   if (fd < 0)
1721      return EGL_FALSE;
1722
1723   data_map = mmap(NULL, size_map, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1724   if (data_map == MAP_FAILED) {
1725      close(fd);
1726      return EGL_FALSE;
1727   }
1728
1729   /* Share it in a wl_buffer */
1730   pool = wl_shm_create_pool(dri2_dpy->wl_shm, fd, size_map);
1731   wl_proxy_set_queue((struct wl_proxy *)pool, dri2_surf->wl_queue);
1732   *buffer = wl_shm_pool_create_buffer(pool, 0, w, h, stride, format);
1733   wl_shm_pool_destroy(pool);
1734   close(fd);
1735
1736   *data = data_map;
1737   *size = size_map;
1738   return EGL_TRUE;
1739}
1740
1741static int
1742swrast_update_buffers(struct dri2_egl_surface *dri2_surf)
1743{
1744   struct dri2_egl_display *dri2_dpy =
1745      dri2_egl_display(dri2_surf->base.Resource.Display);
1746
1747   /* we need to do the following operations only once per frame */
1748   if (dri2_surf->back)
1749      return 0;
1750
1751   if (dri2_surf->wl_win &&
1752       (dri2_surf->base.Width != dri2_surf->wl_win->width ||
1753        dri2_surf->base.Height != dri2_surf->wl_win->height)) {
1754
1755      dri2_wl_release_buffers(dri2_surf);
1756
1757      dri2_surf->base.Width  = dri2_surf->wl_win->width;
1758      dri2_surf->base.Height = dri2_surf->wl_win->height;
1759      dri2_surf->dx = dri2_surf->wl_win->dx;
1760      dri2_surf->dy = dri2_surf->wl_win->dy;
1761      dri2_surf->current = NULL;
1762   }
1763
1764   /* find back buffer */
1765
1766   /* There might be a buffer release already queued that wasn't processed */
1767   wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue);
1768
1769   /* try get free buffer already created */
1770   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
1771      if (!dri2_surf->color_buffers[i].locked &&
1772          dri2_surf->color_buffers[i].wl_buffer) {
1773          dri2_surf->back = &dri2_surf->color_buffers[i];
1774          break;
1775      }
1776   }
1777
1778   /* else choose any another free location */
1779   if (!dri2_surf->back) {
1780      for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
1781         if (!dri2_surf->color_buffers[i].locked) {
1782             dri2_surf->back = &dri2_surf->color_buffers[i];
1783             if (!dri2_wl_swrast_allocate_buffer(dri2_surf,
1784                                                 dri2_surf->format,
1785                                                 dri2_surf->base.Width,
1786                                                 dri2_surf->base.Height,
1787                                                 &dri2_surf->back->data,
1788                                                 &dri2_surf->back->data_size,
1789                                                 &dri2_surf->back->wl_buffer)) {
1790                _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer");
1791                 return -1;
1792             }
1793             wl_buffer_add_listener(dri2_surf->back->wl_buffer,
1794                                    &wl_buffer_listener, dri2_surf);
1795             break;
1796         }
1797      }
1798   }
1799
1800   if (!dri2_surf->back) {
1801      _eglError(EGL_BAD_ALLOC, "failed to find free buffer");
1802      return -1;
1803   }
1804
1805   dri2_surf->back->locked = true;
1806
1807   /* If we have an extra unlocked buffer at this point, we had to do triple
1808    * buffering for a while, but now can go back to just double buffering.
1809    * That means we can free any unlocked buffer now. */
1810   for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
1811      if (!dri2_surf->color_buffers[i].locked &&
1812          dri2_surf->color_buffers[i].wl_buffer) {
1813         wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer);
1814         munmap(dri2_surf->color_buffers[i].data,
1815                dri2_surf->color_buffers[i].data_size);
1816         dri2_surf->color_buffers[i].wl_buffer = NULL;
1817         dri2_surf->color_buffers[i].data = NULL;
1818      }
1819   }
1820
1821   return 0;
1822}
1823
1824static void*
1825dri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface *dri2_surf)
1826{
1827   /* if there has been a resize: */
1828   if (!dri2_surf->current)
1829      return NULL;
1830
1831   return dri2_surf->current->data;
1832}
1833
1834static void*
1835dri2_wl_swrast_get_backbuffer_data(struct dri2_egl_surface *dri2_surf)
1836{
1837   assert(dri2_surf->back);
1838   return dri2_surf->back->data;
1839}
1840
1841static void
1842dri2_wl_swrast_commit_backbuffer(struct dri2_egl_surface *dri2_surf)
1843{
1844   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
1845
1846   while (dri2_surf->throttle_callback != NULL)
1847      if (wl_display_dispatch_queue(dri2_dpy->wl_dpy,
1848                                    dri2_surf->wl_queue) == -1)
1849         return;
1850
1851   if (dri2_surf->base.SwapInterval > 0) {
1852      dri2_surf->throttle_callback =
1853         wl_surface_frame(dri2_surf->wl_surface_wrapper);
1854      wl_callback_add_listener(dri2_surf->throttle_callback,
1855                               &throttle_listener, dri2_surf);
1856   }
1857
1858   dri2_surf->current = dri2_surf->back;
1859   dri2_surf->back = NULL;
1860
1861   wl_surface_attach(dri2_surf->wl_surface_wrapper,
1862                     dri2_surf->current->wl_buffer,
1863                     dri2_surf->dx, dri2_surf->dy);
1864
1865   dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
1866   dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
1867   /* reset resize growing parameters */
1868   dri2_surf->dx = 0;
1869   dri2_surf->dy = 0;
1870
1871   wl_surface_damage(dri2_surf->wl_surface_wrapper,
1872                     0, 0, INT32_MAX, INT32_MAX);
1873   wl_surface_commit(dri2_surf->wl_surface_wrapper);
1874
1875   /* If we're not waiting for a frame callback then we'll at least throttle
1876    * to a sync callback so that we always give a chance for the compositor to
1877    * handle the commit and send a release event before checking for a free
1878    * buffer */
1879   if (dri2_surf->throttle_callback == NULL) {
1880      dri2_surf->throttle_callback = wl_display_sync(dri2_surf->wl_dpy_wrapper);
1881      wl_callback_add_listener(dri2_surf->throttle_callback,
1882                               &throttle_listener, dri2_surf);
1883   }
1884
1885   wl_display_flush(dri2_dpy->wl_dpy);
1886}
1887
1888static void
1889dri2_wl_swrast_get_drawable_info(__DRIdrawable * draw,
1890                                 int *x, int *y, int *w, int *h,
1891                                 void *loaderPrivate)
1892{
1893   struct dri2_egl_surface *dri2_surf = loaderPrivate;
1894
1895   (void) swrast_update_buffers(dri2_surf);
1896   *x = 0;
1897   *y = 0;
1898   *w = dri2_surf->base.Width;
1899   *h = dri2_surf->base.Height;
1900}
1901
1902static void
1903dri2_wl_swrast_get_image(__DRIdrawable * read,
1904                         int x, int y, int w, int h,
1905                         char *data, void *loaderPrivate)
1906{
1907   struct dri2_egl_surface *dri2_surf = loaderPrivate;
1908   int copy_width = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w);
1909   int x_offset = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, x);
1910   int src_stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, dri2_surf->base.Width);
1911   int dst_stride = copy_width;
1912   char *src, *dst;
1913
1914   src = dri2_wl_swrast_get_frontbuffer_data(dri2_surf);
1915   if (!src) {
1916      memset(data, 0, copy_width * h);
1917      return;
1918   }
1919
1920   assert(data != src);
1921   assert(copy_width <= src_stride);
1922
1923   src += x_offset;
1924   src += y * src_stride;
1925   dst = data;
1926
1927   if (copy_width > src_stride-x_offset)
1928      copy_width = src_stride-x_offset;
1929   if (h > dri2_surf->base.Height-y)
1930      h = dri2_surf->base.Height-y;
1931
1932   for (; h>0; h--) {
1933      memcpy(dst, src, copy_width);
1934      src += src_stride;
1935      dst += dst_stride;
1936   }
1937}
1938
1939static void
1940dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
1941                         int x, int y, int w, int h, int stride,
1942                         char *data, void *loaderPrivate)
1943{
1944   struct dri2_egl_surface *dri2_surf = loaderPrivate;
1945   int copy_width = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w);
1946   int dst_stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, dri2_surf->base.Width);
1947   int x_offset = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, x);
1948   char *src, *dst;
1949
1950   assert(copy_width <= stride);
1951
1952   (void) swrast_update_buffers(dri2_surf);
1953   dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
1954
1955   /* partial copy, copy old content */
1956   if (copy_width < dst_stride)
1957      dri2_wl_swrast_get_image(draw, 0, 0,
1958                               dri2_surf->base.Width, dri2_surf->base.Height,
1959                               dst, loaderPrivate);
1960
1961   dst += x_offset;
1962   dst += y * dst_stride;
1963
1964   src = data;
1965
1966   /* drivers expect we do these checks (and some rely on it) */
1967   if (copy_width > dst_stride-x_offset)
1968      copy_width = dst_stride-x_offset;
1969   if (h > dri2_surf->base.Height-y)
1970      h = dri2_surf->base.Height-y;
1971
1972   for (; h>0; h--) {
1973      memcpy(dst, src, copy_width);
1974      src += stride;
1975      dst += dst_stride;
1976   }
1977   dri2_wl_swrast_commit_backbuffer(dri2_surf);
1978}
1979
1980static void
1981dri2_wl_swrast_put_image(__DRIdrawable * draw, int op,
1982                         int x, int y, int w, int h,
1983                         char *data, void *loaderPrivate)
1984{
1985   struct dri2_egl_surface *dri2_surf = loaderPrivate;
1986   int stride;
1987
1988   stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w);
1989   dri2_wl_swrast_put_image2(draw, op, x, y, w, h,
1990                             stride, data, loaderPrivate);
1991}
1992
1993static EGLBoolean
1994dri2_wl_swrast_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
1995{
1996   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1997   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1998
1999   if (!dri2_surf->wl_win)
2000      return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers");
2001
2002   dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
2003   return EGL_TRUE;
2004}
2005
2006static void
2007shm_handle_format(void *data, struct wl_shm *shm, uint32_t format)
2008{
2009   struct dri2_egl_display *dri2_dpy = data;
2010   int visual_idx = dri2_wl_visual_idx_from_shm_format(format);
2011
2012   if (visual_idx == -1)
2013      return;
2014
2015   BITSET_SET(dri2_dpy->formats, visual_idx);
2016}
2017
2018static const struct wl_shm_listener shm_listener = {
2019   .format = shm_handle_format
2020};
2021
2022static void
2023registry_handle_global_swrast(void *data, struct wl_registry *registry,
2024                              uint32_t name, const char *interface,
2025                              uint32_t version)
2026{
2027   struct dri2_egl_display *dri2_dpy = data;
2028
2029   if (strcmp(interface, "wl_shm") == 0) {
2030      dri2_dpy->wl_shm =
2031         wl_registry_bind(registry, name, &wl_shm_interface, 1);
2032      wl_shm_add_listener(dri2_dpy->wl_shm, &shm_listener, dri2_dpy);
2033   }
2034}
2035
2036static const struct wl_registry_listener registry_listener_swrast = {
2037   .global = registry_handle_global_swrast,
2038   .global_remove = registry_handle_global_remove
2039};
2040
2041static const struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl = {
2042   .authenticate = NULL,
2043   .create_window_surface = dri2_wl_create_window_surface,
2044   .create_pixmap_surface = dri2_wl_create_pixmap_surface,
2045   .destroy_surface = dri2_wl_destroy_surface,
2046   .create_image = dri2_create_image_khr,
2047   .swap_buffers = dri2_wl_swrast_swap_buffers,
2048   .get_dri_drawable = dri2_surface_get_dri_drawable,
2049};
2050
2051static const __DRIswrastLoaderExtension swrast_loader_extension = {
2052   .base = { __DRI_SWRAST_LOADER, 2 },
2053
2054   .getDrawableInfo = dri2_wl_swrast_get_drawable_info,
2055   .putImage        = dri2_wl_swrast_put_image,
2056   .getImage        = dri2_wl_swrast_get_image,
2057   .putImage2       = dri2_wl_swrast_put_image2,
2058};
2059
2060static const __DRIextension *swrast_loader_extensions[] = {
2061   &swrast_loader_extension.base,
2062   &image_lookup_extension.base,
2063   NULL,
2064};
2065
2066static EGLBoolean
2067dri2_initialize_wayland_swrast(_EGLDisplay *disp)
2068{
2069   _EGLDevice *dev;
2070   struct dri2_egl_display *dri2_dpy;
2071
2072   dri2_dpy = calloc(1, sizeof *dri2_dpy);
2073   if (!dri2_dpy)
2074      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
2075
2076   dri2_dpy->fd = -1;
2077   disp->DriverData = (void *) dri2_dpy;
2078   if (disp->PlatformDisplay == NULL) {
2079      dri2_dpy->wl_dpy = wl_display_connect(NULL);
2080      if (dri2_dpy->wl_dpy == NULL)
2081         goto cleanup;
2082      dri2_dpy->own_device = true;
2083   } else {
2084      dri2_dpy->wl_dpy = disp->PlatformDisplay;
2085   }
2086
2087   dev = _eglAddDevice(dri2_dpy->fd, true);
2088   if (!dev) {
2089      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
2090      goto cleanup;
2091   }
2092
2093   disp->Device = dev;
2094
2095   dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
2096
2097   dri2_dpy->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy);
2098   if (dri2_dpy->wl_dpy_wrapper == NULL)
2099      goto cleanup;
2100
2101   wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_dpy_wrapper,
2102                      dri2_dpy->wl_queue);
2103
2104   if (dri2_dpy->own_device)
2105      wl_display_dispatch_pending(dri2_dpy->wl_dpy);
2106
2107   dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy_wrapper);
2108   wl_registry_add_listener(dri2_dpy->wl_registry,
2109                            &registry_listener_swrast, dri2_dpy);
2110
2111   if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_shm == NULL)
2112      goto cleanup;
2113
2114   if (roundtrip(dri2_dpy) < 0 || !BITSET_TEST_RANGE(dri2_dpy->formats,
2115                                                     0, EGL_DRI2_MAX_FORMATS))
2116      goto cleanup;
2117
2118   dri2_dpy->driver_name = strdup("swrast");
2119   if (!dri2_load_driver_swrast(disp))
2120      goto cleanup;
2121
2122   dri2_dpy->loader_extensions = swrast_loader_extensions;
2123
2124   if (!dri2_create_screen(disp))
2125      goto cleanup;
2126
2127   if (!dri2_setup_extensions(disp))
2128      goto cleanup;
2129
2130   dri2_setup_screen(disp);
2131
2132   dri2_wl_setup_swap_interval(disp);
2133
2134   if (!dri2_wl_add_configs_for_visuals(disp)) {
2135      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to add configs");
2136      goto cleanup;
2137   }
2138
2139   /* Fill vtbl last to prevent accidentally calling virtual function during
2140    * initialization.
2141    */
2142   dri2_dpy->vtbl = &dri2_wl_swrast_display_vtbl;
2143
2144   return EGL_TRUE;
2145
2146 cleanup:
2147   dri2_display_destroy(disp);
2148   return EGL_FALSE;
2149}
2150
2151EGLBoolean
2152dri2_initialize_wayland(_EGLDisplay *disp)
2153{
2154   if (disp->Options.ForceSoftware)
2155      return dri2_initialize_wayland_swrast(disp);
2156   else
2157      return dri2_initialize_wayland_drm(disp);
2158}
2159
2160void
2161dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy)
2162{
2163   if (dri2_dpy->wl_drm)
2164      wl_drm_destroy(dri2_dpy->wl_drm);
2165   if (dri2_dpy->wl_dmabuf)
2166      zwp_linux_dmabuf_v1_destroy(dri2_dpy->wl_dmabuf);
2167   if (dri2_dpy->wl_shm)
2168      wl_shm_destroy(dri2_dpy->wl_shm);
2169   if (dri2_dpy->wl_registry)
2170      wl_registry_destroy(dri2_dpy->wl_registry);
2171   if (dri2_dpy->wl_queue)
2172      wl_event_queue_destroy(dri2_dpy->wl_queue);
2173   if (dri2_dpy->wl_dpy_wrapper)
2174      wl_proxy_wrapper_destroy(dri2_dpy->wl_dpy_wrapper);
2175
2176   for (int i = 0; dri2_dpy->wl_modifiers && i < ARRAY_SIZE(dri2_wl_visuals); i++)
2177      u_vector_finish(&dri2_dpy->wl_modifiers[i]);
2178   free(dri2_dpy->wl_modifiers);
2179
2180   if (dri2_dpy->own_device)
2181      wl_display_disconnect(dri2_dpy->wl_dpy);
2182}
2183