2 * Copyright © 2011-2012 Intel Corporation
3 * Copyright © 2012 Collabora, Ltd.
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:
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
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.
26 * Kristian Høgsberg <krh@bitplanet.net>
27 * Benjamin Franzke <benjaminfranzke@googlemail.com>
39 #include <drm_fourcc.h>
43 #include "egl_dri2_fallbacks.h"
45 #include "util/u_vector.h"
46 #include "eglglobals.h"
48 #include <wayland-egl-backend.h>
49 #include <wayland-client.h>
50 #include "wayland-drm-client-protocol.h"
51 #include "linux-dmabuf-unstable-v1-client-protocol.h"
54 * The index of entries in this table is used as a bitmask in
55 * dri2_dpy->formats, which tracks the formats supported by our server.
57 static const struct dri2_wl_visual
{
58 const char *format_name
;
59 uint32_t wl_drm_format
;
60 uint32_t wl_shm_format
;
63 unsigned int rgba_masks
[4];
64 } dri2_wl_visuals
[] = {
67 WL_DRM_FORMAT_XRGB2101010
, WL_SHM_FORMAT_XRGB2101010
,
68 __DRI_IMAGE_FORMAT_XRGB2101010
, 32,
69 { 0x3ff00000, 0x000ffc00, 0x000003ff, 0x00000000 }
73 WL_DRM_FORMAT_ARGB2101010
, WL_SHM_FORMAT_ARGB2101010
,
74 __DRI_IMAGE_FORMAT_ARGB2101010
, 32,
75 { 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }
79 WL_DRM_FORMAT_XBGR2101010
, WL_SHM_FORMAT_XBGR2101010
,
80 __DRI_IMAGE_FORMAT_XBGR2101010
, 32,
81 { 0x000003ff, 0x000ffc00, 0x3ff00000, 0x00000000 }
85 WL_DRM_FORMAT_ABGR2101010
, WL_SHM_FORMAT_ABGR2101010
,
86 __DRI_IMAGE_FORMAT_ABGR2101010
, 32,
87 { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }
91 WL_DRM_FORMAT_XRGB8888
, WL_SHM_FORMAT_XRGB8888
,
92 __DRI_IMAGE_FORMAT_XRGB8888
, 32,
93 { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }
97 WL_DRM_FORMAT_ARGB8888
, WL_SHM_FORMAT_ARGB8888
,
98 __DRI_IMAGE_FORMAT_ARGB8888
, 32,
99 { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }
103 WL_DRM_FORMAT_RGB565
, WL_SHM_FORMAT_RGB565
,
104 __DRI_IMAGE_FORMAT_RGB565
, 16,
105 { 0xf800, 0x07e0, 0x001f, 0x0000 }
110 dri2_wl_visual_idx_from_config(struct dri2_egl_display
*dri2_dpy
,
111 const __DRIconfig
*config
)
113 unsigned int red
, green
, blue
, alpha
;
115 dri2_dpy
->core
->getConfigAttrib(config
, __DRI_ATTRIB_RED_MASK
, &red
);
116 dri2_dpy
->core
->getConfigAttrib(config
, __DRI_ATTRIB_GREEN_MASK
, &green
);
117 dri2_dpy
->core
->getConfigAttrib(config
, __DRI_ATTRIB_BLUE_MASK
, &blue
);
118 dri2_dpy
->core
->getConfigAttrib(config
, __DRI_ATTRIB_ALPHA_MASK
, &alpha
);
120 for (unsigned int i
= 0; i
< ARRAY_SIZE(dri2_wl_visuals
); i
++) {
121 const struct dri2_wl_visual
*wl_visual
= &dri2_wl_visuals
[i
];
123 if (red
== wl_visual
->rgba_masks
[0] &&
124 green
== wl_visual
->rgba_masks
[1] &&
125 blue
== wl_visual
->rgba_masks
[2] &&
126 alpha
== wl_visual
->rgba_masks
[3]) {
135 dri2_wl_visual_idx_from_fourcc(uint32_t fourcc
)
137 for (int i
= 0; i
< ARRAY_SIZE(dri2_wl_visuals
); i
++) {
138 /* wl_drm format codes overlap with DRIImage FourCC codes for all formats
140 if (dri2_wl_visuals
[i
].wl_drm_format
== fourcc
)
148 dri2_wl_visual_idx_from_dri_image_format(uint32_t dri_image_format
)
150 for (int i
= 0; i
< ARRAY_SIZE(dri2_wl_visuals
); i
++) {
151 if (dri2_wl_visuals
[i
].dri_image_format
== dri_image_format
)
159 dri2_wl_visual_idx_from_shm_format(uint32_t shm_format
)
161 for (int i
= 0; i
< ARRAY_SIZE(dri2_wl_visuals
); i
++) {
162 if (dri2_wl_visuals
[i
].wl_shm_format
== shm_format
)
170 roundtrip(struct dri2_egl_display
*dri2_dpy
)
172 return wl_display_roundtrip_queue(dri2_dpy
->wl_dpy
, dri2_dpy
->wl_queue
);
176 wl_buffer_release(void *data
, struct wl_buffer
*buffer
)
178 struct dri2_egl_surface
*dri2_surf
= data
;
181 for (i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); ++i
)
182 if (dri2_surf
->color_buffers
[i
].wl_buffer
== buffer
)
185 if (i
== ARRAY_SIZE(dri2_surf
->color_buffers
)) {
186 wl_buffer_destroy(buffer
);
190 dri2_surf
->color_buffers
[i
].locked
= false;
193 static const struct wl_buffer_listener wl_buffer_listener
= {
194 .release
= wl_buffer_release
198 resize_callback(struct wl_egl_window
*wl_win
, void *data
)
200 struct dri2_egl_surface
*dri2_surf
= data
;
201 struct dri2_egl_display
*dri2_dpy
=
202 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
204 dri2_dpy
->flush
->invalidate(dri2_surf
->dri_drawable
);
208 destroy_window_callback(void *data
)
210 struct dri2_egl_surface
*dri2_surf
= data
;
211 dri2_surf
->wl_win
= NULL
;
214 static struct wl_surface
*
215 get_wl_surface_proxy(struct wl_egl_window
*window
)
217 /* Version 3 of wl_egl_window introduced a version field at the same
218 * location where a pointer to wl_surface was stored. Thus, if
219 * window->version is dereferencable, we've been given an older version of
220 * wl_egl_window, and window->version points to wl_surface */
221 if (_eglPointerIsDereferencable((void *)(window
->version
))) {
222 return wl_proxy_create_wrapper((void *)(window
->version
));
224 return wl_proxy_create_wrapper(window
->surface
);
228 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
231 dri2_wl_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
232 _EGLConfig
*conf
, void *native_window
,
233 const EGLint
*attrib_list
)
235 __DRIcreateNewDrawableFunc createNewDrawable
;
236 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
237 struct dri2_egl_config
*dri2_conf
= dri2_egl_config(conf
);
238 struct wl_egl_window
*window
= native_window
;
239 struct dri2_egl_surface
*dri2_surf
;
241 const __DRIconfig
*config
;
243 dri2_surf
= calloc(1, sizeof *dri2_surf
);
245 _eglError(EGL_BAD_ALLOC
, "dri2_create_surface");
249 if (!dri2_init_surface(&dri2_surf
->base
, disp
, EGL_WINDOW_BIT
, conf
,
253 config
= dri2_get_dri_config(dri2_conf
, EGL_WINDOW_BIT
,
254 dri2_surf
->base
.GLColorspace
);
257 _eglError(EGL_BAD_MATCH
, "Unsupported surfacetype/colorspace configuration");
261 dri2_surf
->base
.Width
= window
->width
;
262 dri2_surf
->base
.Height
= window
->height
;
264 visual_idx
= dri2_wl_visual_idx_from_config(dri2_dpy
, config
);
265 assert(visual_idx
!= -1);
267 if (dri2_dpy
->wl_dmabuf
|| dri2_dpy
->wl_drm
) {
268 dri2_surf
->format
= dri2_wl_visuals
[visual_idx
].wl_drm_format
;
270 assert(dri2_dpy
->wl_shm
);
271 dri2_surf
->format
= dri2_wl_visuals
[visual_idx
].wl_shm_format
;
274 dri2_surf
->wl_queue
= wl_display_create_queue(dri2_dpy
->wl_dpy
);
275 if (!dri2_surf
->wl_queue
) {
276 _eglError(EGL_BAD_ALLOC
, "dri2_create_surface");
280 if (dri2_dpy
->wl_drm
) {
281 dri2_surf
->wl_drm_wrapper
= wl_proxy_create_wrapper(dri2_dpy
->wl_drm
);
282 if (!dri2_surf
->wl_drm_wrapper
) {
283 _eglError(EGL_BAD_ALLOC
, "dri2_create_surface");
286 wl_proxy_set_queue((struct wl_proxy
*)dri2_surf
->wl_drm_wrapper
,
287 dri2_surf
->wl_queue
);
290 dri2_surf
->wl_dpy_wrapper
= wl_proxy_create_wrapper(dri2_dpy
->wl_dpy
);
291 if (!dri2_surf
->wl_dpy_wrapper
) {
292 _eglError(EGL_BAD_ALLOC
, "dri2_create_surface");
295 wl_proxy_set_queue((struct wl_proxy
*)dri2_surf
->wl_dpy_wrapper
,
296 dri2_surf
->wl_queue
);
298 dri2_surf
->wl_surface_wrapper
= get_wl_surface_proxy(window
);
299 if (!dri2_surf
->wl_surface_wrapper
) {
300 _eglError(EGL_BAD_ALLOC
, "dri2_create_surface");
301 goto cleanup_dpy_wrapper
;
303 wl_proxy_set_queue((struct wl_proxy
*)dri2_surf
->wl_surface_wrapper
,
304 dri2_surf
->wl_queue
);
306 dri2_surf
->wl_win
= window
;
307 dri2_surf
->wl_win
->driver_private
= dri2_surf
;
308 dri2_surf
->wl_win
->destroy_window_callback
= destroy_window_callback
;
310 dri2_surf
->wl_win
->resize_callback
= resize_callback
;
312 if (dri2_dpy
->image_driver
)
313 createNewDrawable
= dri2_dpy
->image_driver
->createNewDrawable
;
314 else if (dri2_dpy
->dri2
)
315 createNewDrawable
= dri2_dpy
->dri2
->createNewDrawable
;
317 createNewDrawable
= dri2_dpy
->swrast
->createNewDrawable
;
319 dri2_surf
->dri_drawable
= (*createNewDrawable
)(dri2_dpy
->dri_screen
, config
,
321 if (dri2_surf
->dri_drawable
== NULL
) {
322 _eglError(EGL_BAD_ALLOC
, "createNewDrawable");
323 goto cleanup_surf_wrapper
;
326 dri2_surf
->base
.SwapInterval
= dri2_dpy
->default_swap_interval
;
328 return &dri2_surf
->base
;
330 cleanup_surf_wrapper
:
331 wl_proxy_wrapper_destroy(dri2_surf
->wl_surface_wrapper
);
333 wl_proxy_wrapper_destroy(dri2_surf
->wl_dpy_wrapper
);
335 if (dri2_surf
->wl_drm_wrapper
)
336 wl_proxy_wrapper_destroy(dri2_surf
->wl_drm_wrapper
);
338 wl_event_queue_destroy(dri2_surf
->wl_queue
);
346 dri2_wl_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*disp
,
347 _EGLConfig
*conf
, void *native_window
,
348 const EGLint
*attrib_list
)
350 /* From the EGL_EXT_platform_wayland spec, version 3:
352 * It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
353 * that belongs to Wayland. Any such call fails and generates
356 _eglError(EGL_BAD_PARAMETER
, "cannot create EGL pixmap surfaces on "
362 * Called via eglDestroySurface(), drv->API.DestroySurface().
365 dri2_wl_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*surf
)
367 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
368 struct dri2_egl_surface
*dri2_surf
= dri2_egl_surface(surf
);
372 dri2_dpy
->core
->destroyDrawable(dri2_surf
->dri_drawable
);
374 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
375 if (dri2_surf
->color_buffers
[i
].wl_buffer
)
376 wl_buffer_destroy(dri2_surf
->color_buffers
[i
].wl_buffer
);
377 if (dri2_surf
->color_buffers
[i
].dri_image
)
378 dri2_dpy
->image
->destroyImage(dri2_surf
->color_buffers
[i
].dri_image
);
379 if (dri2_surf
->color_buffers
[i
].linear_copy
)
380 dri2_dpy
->image
->destroyImage(dri2_surf
->color_buffers
[i
].linear_copy
);
381 if (dri2_surf
->color_buffers
[i
].data
)
382 munmap(dri2_surf
->color_buffers
[i
].data
,
383 dri2_surf
->color_buffers
[i
].data_size
);
387 dri2_egl_surface_free_local_buffers(dri2_surf
);
389 if (dri2_surf
->throttle_callback
)
390 wl_callback_destroy(dri2_surf
->throttle_callback
);
392 if (dri2_surf
->wl_win
) {
393 dri2_surf
->wl_win
->driver_private
= NULL
;
394 dri2_surf
->wl_win
->resize_callback
= NULL
;
395 dri2_surf
->wl_win
->destroy_window_callback
= NULL
;
398 wl_proxy_wrapper_destroy(dri2_surf
->wl_surface_wrapper
);
399 wl_proxy_wrapper_destroy(dri2_surf
->wl_dpy_wrapper
);
400 if (dri2_surf
->wl_drm_wrapper
)
401 wl_proxy_wrapper_destroy(dri2_surf
->wl_drm_wrapper
);
402 wl_event_queue_destroy(dri2_surf
->wl_queue
);
404 dri2_fini_surface(surf
);
411 dri2_wl_release_buffers(struct dri2_egl_surface
*dri2_surf
)
413 struct dri2_egl_display
*dri2_dpy
=
414 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
416 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
417 if (dri2_surf
->color_buffers
[i
].wl_buffer
&&
418 !dri2_surf
->color_buffers
[i
].locked
)
419 wl_buffer_destroy(dri2_surf
->color_buffers
[i
].wl_buffer
);
420 if (dri2_surf
->color_buffers
[i
].dri_image
)
421 dri2_dpy
->image
->destroyImage(dri2_surf
->color_buffers
[i
].dri_image
);
422 if (dri2_surf
->color_buffers
[i
].linear_copy
)
423 dri2_dpy
->image
->destroyImage(dri2_surf
->color_buffers
[i
].linear_copy
);
424 if (dri2_surf
->color_buffers
[i
].data
)
425 munmap(dri2_surf
->color_buffers
[i
].data
,
426 dri2_surf
->color_buffers
[i
].data_size
);
428 dri2_surf
->color_buffers
[i
].wl_buffer
= NULL
;
429 dri2_surf
->color_buffers
[i
].dri_image
= NULL
;
430 dri2_surf
->color_buffers
[i
].linear_copy
= NULL
;
431 dri2_surf
->color_buffers
[i
].data
= NULL
;
432 dri2_surf
->color_buffers
[i
].locked
= false;
436 dri2_egl_surface_free_local_buffers(dri2_surf
);
440 get_back_bo(struct dri2_egl_surface
*dri2_surf
)
442 struct dri2_egl_display
*dri2_dpy
=
443 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
446 unsigned int dri_image_format
;
450 visual_idx
= dri2_wl_visual_idx_from_fourcc(dri2_surf
->format
);
451 assert(visual_idx
!= -1);
452 dri_image_format
= dri2_wl_visuals
[visual_idx
].dri_image_format
;
453 modifiers
= u_vector_tail(&dri2_dpy
->wl_modifiers
[visual_idx
]);
454 num_modifiers
= u_vector_length(&dri2_dpy
->wl_modifiers
[visual_idx
]);
456 /* There might be a buffer release already queued that wasn't processed */
457 wl_display_dispatch_queue_pending(dri2_dpy
->wl_dpy
, dri2_surf
->wl_queue
);
459 while (dri2_surf
->back
== NULL
) {
460 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
461 /* Get an unlocked buffer, preferrably one with a dri_buffer
462 * already allocated. */
463 if (dri2_surf
->color_buffers
[i
].locked
)
465 if (dri2_surf
->back
== NULL
)
466 dri2_surf
->back
= &dri2_surf
->color_buffers
[i
];
467 else if (dri2_surf
->back
->dri_image
== NULL
)
468 dri2_surf
->back
= &dri2_surf
->color_buffers
[i
];
474 /* If we don't have a buffer, then block on the server to release one for
475 * us, and try again. wl_display_dispatch_queue will process any pending
476 * events, however not all servers flush on issuing a buffer release
477 * event. So, we spam the server with roundtrips as they always cause a
480 if (wl_display_roundtrip_queue(dri2_dpy
->wl_dpy
,
481 dri2_surf
->wl_queue
) < 0)
485 if (dri2_surf
->back
== NULL
)
488 use_flags
= __DRI_IMAGE_USE_SHARE
| __DRI_IMAGE_USE_BACKBUFFER
;
490 if (dri2_dpy
->is_different_gpu
&&
491 dri2_surf
->back
->linear_copy
== NULL
) {
492 /* The LINEAR modifier should be a perfect alias of the LINEAR use
493 * flag; try the new interface first before the old, then fall back. */
494 if (dri2_dpy
->image
->base
.version
>= 15 &&
495 dri2_dpy
->image
->createImageWithModifiers
) {
496 uint64_t linear_mod
= DRM_FORMAT_MOD_LINEAR
;
498 dri2_surf
->back
->linear_copy
=
499 dri2_dpy
->image
->createImageWithModifiers(dri2_dpy
->dri_screen
,
500 dri2_surf
->base
.Width
,
501 dri2_surf
->base
.Height
,
507 dri2_surf
->back
->linear_copy
=
508 dri2_dpy
->image
->createImage(dri2_dpy
->dri_screen
,
509 dri2_surf
->base
.Width
,
510 dri2_surf
->base
.Height
,
513 __DRI_IMAGE_USE_LINEAR
,
516 if (dri2_surf
->back
->linear_copy
== NULL
)
520 if (dri2_surf
->back
->dri_image
== NULL
) {
521 /* If our DRIImage implementation does not support
522 * createImageWithModifiers, then fall back to the old createImage,
523 * and hope it allocates an image which is acceptable to the winsys.
525 if (num_modifiers
&& dri2_dpy
->image
->base
.version
>= 15 &&
526 dri2_dpy
->image
->createImageWithModifiers
) {
527 dri2_surf
->back
->dri_image
=
528 dri2_dpy
->image
->createImageWithModifiers(dri2_dpy
->dri_screen
,
529 dri2_surf
->base
.Width
,
530 dri2_surf
->base
.Height
,
536 dri2_surf
->back
->dri_image
=
537 dri2_dpy
->image
->createImage(dri2_dpy
->dri_screen
,
538 dri2_surf
->base
.Width
,
539 dri2_surf
->base
.Height
,
541 dri2_dpy
->is_different_gpu
?
546 dri2_surf
->back
->age
= 0;
548 if (dri2_surf
->back
->dri_image
== NULL
)
551 dri2_surf
->back
->locked
= true;
558 back_bo_to_dri_buffer(struct dri2_egl_surface
*dri2_surf
, __DRIbuffer
*buffer
)
560 struct dri2_egl_display
*dri2_dpy
=
561 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
565 image
= dri2_surf
->back
->dri_image
;
567 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NAME
, &name
);
568 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &pitch
);
570 buffer
->attachment
= __DRI_BUFFER_BACK_LEFT
;
572 buffer
->pitch
= pitch
;
578 update_buffers(struct dri2_egl_surface
*dri2_surf
)
580 struct dri2_egl_display
*dri2_dpy
=
581 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
583 if (dri2_surf
->base
.Width
!= dri2_surf
->wl_win
->width
||
584 dri2_surf
->base
.Height
!= dri2_surf
->wl_win
->height
) {
586 dri2_wl_release_buffers(dri2_surf
);
588 dri2_surf
->base
.Width
= dri2_surf
->wl_win
->width
;
589 dri2_surf
->base
.Height
= dri2_surf
->wl_win
->height
;
590 dri2_surf
->dx
= dri2_surf
->wl_win
->dx
;
591 dri2_surf
->dy
= dri2_surf
->wl_win
->dy
;
594 if (get_back_bo(dri2_surf
) < 0) {
595 _eglError(EGL_BAD_ALLOC
, "failed to allocate color buffer");
599 /* If we have an extra unlocked buffer at this point, we had to do triple
600 * buffering for a while, but now can go back to just double buffering.
601 * That means we can free any unlocked buffer now. */
602 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
603 if (!dri2_surf
->color_buffers
[i
].locked
&&
604 dri2_surf
->color_buffers
[i
].wl_buffer
) {
605 wl_buffer_destroy(dri2_surf
->color_buffers
[i
].wl_buffer
);
606 dri2_dpy
->image
->destroyImage(dri2_surf
->color_buffers
[i
].dri_image
);
607 if (dri2_dpy
->is_different_gpu
)
608 dri2_dpy
->image
->destroyImage(dri2_surf
->color_buffers
[i
].linear_copy
);
609 dri2_surf
->color_buffers
[i
].wl_buffer
= NULL
;
610 dri2_surf
->color_buffers
[i
].dri_image
= NULL
;
611 dri2_surf
->color_buffers
[i
].linear_copy
= NULL
;
619 dri2_wl_get_buffers_with_format(__DRIdrawable
* driDrawable
,
620 int *width
, int *height
,
621 unsigned int *attachments
, int count
,
622 int *out_count
, void *loaderPrivate
)
624 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
627 if (update_buffers(dri2_surf
) < 0)
630 for (i
= 0, j
= 0; i
< 2 * count
; i
+= 2, j
++) {
633 switch (attachments
[i
]) {
634 case __DRI_BUFFER_BACK_LEFT
:
635 back_bo_to_dri_buffer(dri2_surf
, &dri2_surf
->buffers
[j
]);
638 local
= dri2_egl_surface_alloc_local_buffer(dri2_surf
, attachments
[i
],
642 _eglError(EGL_BAD_ALLOC
, "failed to allocate local buffer");
645 dri2_surf
->buffers
[j
] = *local
;
654 *width
= dri2_surf
->base
.Width
;
655 *height
= dri2_surf
->base
.Height
;
657 return dri2_surf
->buffers
;
661 dri2_wl_get_buffers(__DRIdrawable
* driDrawable
,
662 int *width
, int *height
,
663 unsigned int *attachments
, int count
,
664 int *out_count
, void *loaderPrivate
)
666 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
667 unsigned int *attachments_with_format
;
669 int visual_idx
= dri2_wl_visual_idx_from_fourcc(dri2_surf
->format
);
671 if (visual_idx
== -1)
674 attachments_with_format
= calloc(count
, 2 * sizeof(unsigned int));
675 if (!attachments_with_format
) {
680 for (int i
= 0; i
< count
; ++i
) {
681 attachments_with_format
[2*i
] = attachments
[i
];
682 attachments_with_format
[2*i
+ 1] = dri2_wl_visuals
[visual_idx
].bpp
;
686 dri2_wl_get_buffers_with_format(driDrawable
,
688 attachments_with_format
, count
,
689 out_count
, loaderPrivate
);
691 free(attachments_with_format
);
697 image_get_buffers(__DRIdrawable
*driDrawable
,
701 uint32_t buffer_mask
,
702 struct __DRIimageList
*buffers
)
704 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
706 if (update_buffers(dri2_surf
) < 0)
709 buffers
->image_mask
= __DRI_IMAGE_BUFFER_BACK
;
710 buffers
->back
= dri2_surf
->back
->dri_image
;
716 dri2_wl_flush_front_buffer(__DRIdrawable
* driDrawable
, void *loaderPrivate
)
719 (void) loaderPrivate
;
722 static const __DRIdri2LoaderExtension dri2_loader_extension
= {
723 .base
= { __DRI_DRI2_LOADER
, 3 },
725 .getBuffers
= dri2_wl_get_buffers
,
726 .flushFrontBuffer
= dri2_wl_flush_front_buffer
,
727 .getBuffersWithFormat
= dri2_wl_get_buffers_with_format
,
730 static const __DRIimageLoaderExtension image_loader_extension
= {
731 .base
= { __DRI_IMAGE_LOADER
, 1 },
733 .getBuffers
= image_get_buffers
,
734 .flushFrontBuffer
= dri2_wl_flush_front_buffer
,
738 wayland_throttle_callback(void *data
,
739 struct wl_callback
*callback
,
742 struct dri2_egl_surface
*dri2_surf
= data
;
744 dri2_surf
->throttle_callback
= NULL
;
745 wl_callback_destroy(callback
);
748 static const struct wl_callback_listener throttle_listener
= {
749 .done
= wayland_throttle_callback
753 get_fourcc(struct dri2_egl_display
*dri2_dpy
,
754 __DRIimage
*image
, int *fourcc
)
760 query
= dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FOURCC
,
765 query
= dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
,
770 visual_idx
= dri2_wl_visual_idx_from_dri_image_format(dri_format
);
771 if (visual_idx
== -1)
774 *fourcc
= dri2_wl_visuals
[visual_idx
].wl_drm_format
;
778 static struct wl_buffer
*
779 create_wl_buffer(struct dri2_egl_display
*dri2_dpy
,
780 struct dri2_egl_surface
*dri2_surf
,
783 struct wl_buffer
*ret
;
785 int width
, height
, fourcc
, num_planes
;
786 uint64_t modifier
= DRM_FORMAT_MOD_INVALID
;
788 query
= dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_WIDTH
, &width
);
789 query
&= dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_HEIGHT
,
791 query
&= get_fourcc(dri2_dpy
, image
, &fourcc
);
795 query
= dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NUM_PLANES
,
800 if (dri2_dpy
->image
->base
.version
>= 15) {
803 query
= dri2_dpy
->image
->queryImage(image
,
804 __DRI_IMAGE_ATTRIB_MODIFIER_UPPER
,
806 query
&= dri2_dpy
->image
->queryImage(image
,
807 __DRI_IMAGE_ATTRIB_MODIFIER_LOWER
,
810 modifier
= (uint64_t) mod_hi
<< 32;
811 modifier
|= (uint64_t) (mod_lo
& 0xffffffff);
815 if (dri2_dpy
->wl_dmabuf
&& modifier
!= DRM_FORMAT_MOD_INVALID
) {
816 struct zwp_linux_buffer_params_v1
*params
;
819 /* We don't need a wrapper for wl_dmabuf objects, because we have to
820 * create the intermediate params object; we can set the queue on this,
821 * and the wl_buffer inherits it race-free. */
822 params
= zwp_linux_dmabuf_v1_create_params(dri2_dpy
->wl_dmabuf
);
824 wl_proxy_set_queue((struct wl_proxy
*) params
, dri2_surf
->wl_queue
);
826 for (i
= 0; i
< num_planes
; i
++) {
831 p_image
= dri2_dpy
->image
->fromPlanar(image
, i
, NULL
);
837 query
= dri2_dpy
->image
->queryImage(p_image
,
838 __DRI_IMAGE_ATTRIB_FD
,
840 query
&= dri2_dpy
->image
->queryImage(p_image
,
841 __DRI_IMAGE_ATTRIB_STRIDE
,
843 query
&= dri2_dpy
->image
->queryImage(p_image
,
844 __DRI_IMAGE_ATTRIB_OFFSET
,
846 if (image
!= p_image
)
847 dri2_dpy
->image
->destroyImage(p_image
);
852 zwp_linux_buffer_params_v1_destroy(params
);
856 zwp_linux_buffer_params_v1_add(params
, fd
, i
, offset
, stride
,
857 modifier
>> 32, modifier
& 0xffffffff);
861 ret
= zwp_linux_buffer_params_v1_create_immed(params
, width
, height
,
863 zwp_linux_buffer_params_v1_destroy(params
);
864 } else if (dri2_dpy
->capabilities
& WL_DRM_CAPABILITY_PRIME
) {
865 struct wl_drm
*wl_drm
=
866 dri2_surf
? dri2_surf
->wl_drm_wrapper
: dri2_dpy
->wl_drm
;
872 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FD
, &fd
);
873 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
874 ret
= wl_drm_create_prime_buffer(wl_drm
, fd
, width
, height
, fourcc
, 0,
878 struct wl_drm
*wl_drm
=
879 dri2_surf
? dri2_surf
->wl_drm_wrapper
: dri2_dpy
->wl_drm
;
885 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_NAME
, &name
);
886 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_STRIDE
, &stride
);
887 ret
= wl_drm_create_buffer(wl_drm
, name
, width
, height
, stride
, fourcc
);
894 try_damage_buffer(struct dri2_egl_surface
*dri2_surf
,
898 if (wl_proxy_get_version((struct wl_proxy
*) dri2_surf
->wl_surface_wrapper
)
899 < WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION
)
902 for (int i
= 0; i
< n_rects
; i
++) {
903 const int *rect
= &rects
[i
* 4];
905 wl_surface_damage_buffer(dri2_surf
->wl_surface_wrapper
,
907 dri2_surf
->base
.Height
- rect
[1] - rect
[3],
913 * Called via eglSwapBuffers(), drv->API.SwapBuffers().
916 dri2_wl_swap_buffers_with_damage(_EGLDriver
*drv
,
922 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
923 struct dri2_egl_surface
*dri2_surf
= dri2_egl_surface(draw
);
925 while (dri2_surf
->throttle_callback
!= NULL
)
926 if (wl_display_dispatch_queue(dri2_dpy
->wl_dpy
,
927 dri2_surf
->wl_queue
) == -1)
930 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++)
931 if (dri2_surf
->color_buffers
[i
].age
> 0)
932 dri2_surf
->color_buffers
[i
].age
++;
934 /* Make sure we have a back buffer in case we're swapping without ever
936 if (get_back_bo(dri2_surf
) < 0)
937 return _eglError(EGL_BAD_ALLOC
, "dri2_swap_buffers");
939 if (draw
->SwapInterval
> 0) {
940 dri2_surf
->throttle_callback
=
941 wl_surface_frame(dri2_surf
->wl_surface_wrapper
);
942 wl_callback_add_listener(dri2_surf
->throttle_callback
,
943 &throttle_listener
, dri2_surf
);
946 dri2_surf
->back
->age
= 1;
947 dri2_surf
->current
= dri2_surf
->back
;
948 dri2_surf
->back
= NULL
;
950 if (!dri2_surf
->current
->wl_buffer
) {
953 if (dri2_dpy
->is_different_gpu
)
954 image
= dri2_surf
->current
->linear_copy
;
956 image
= dri2_surf
->current
->dri_image
;
958 dri2_surf
->current
->wl_buffer
=
959 create_wl_buffer(dri2_dpy
, dri2_surf
, image
);
961 wl_buffer_add_listener(dri2_surf
->current
->wl_buffer
,
962 &wl_buffer_listener
, dri2_surf
);
965 wl_surface_attach(dri2_surf
->wl_surface_wrapper
,
966 dri2_surf
->current
->wl_buffer
,
967 dri2_surf
->dx
, dri2_surf
->dy
);
969 dri2_surf
->wl_win
->attached_width
= dri2_surf
->base
.Width
;
970 dri2_surf
->wl_win
->attached_height
= dri2_surf
->base
.Height
;
971 /* reset resize growing parameters */
975 /* If the compositor doesn't support damage_buffer, we deliberately
976 * ignore the damage region and post maximum damage, due to
977 * https://bugs.freedesktop.org/78190 */
978 if (!n_rects
|| !try_damage_buffer(dri2_surf
, rects
, n_rects
))
979 wl_surface_damage(dri2_surf
->wl_surface_wrapper
,
980 0, 0, INT32_MAX
, INT32_MAX
);
982 if (dri2_dpy
->is_different_gpu
) {
983 _EGLContext
*ctx
= _eglGetCurrentContext();
984 struct dri2_egl_context
*dri2_ctx
= dri2_egl_context(ctx
);
985 dri2_dpy
->image
->blitImage(dri2_ctx
->dri_context
,
986 dri2_surf
->current
->linear_copy
,
987 dri2_surf
->current
->dri_image
,
988 0, 0, dri2_surf
->base
.Width
,
989 dri2_surf
->base
.Height
,
990 0, 0, dri2_surf
->base
.Width
,
991 dri2_surf
->base
.Height
, 0);
994 dri2_flush_drawable_for_swapbuffers(disp
, draw
);
995 dri2_dpy
->flush
->invalidate(dri2_surf
->dri_drawable
);
997 wl_surface_commit(dri2_surf
->wl_surface_wrapper
);
999 /* If we're not waiting for a frame callback then we'll at least throttle
1000 * to a sync callback so that we always give a chance for the compositor to
1001 * handle the commit and send a release event before checking for a free
1003 if (dri2_surf
->throttle_callback
== NULL
) {
1004 dri2_surf
->throttle_callback
= wl_display_sync(dri2_surf
->wl_dpy_wrapper
);
1005 wl_callback_add_listener(dri2_surf
->throttle_callback
,
1006 &throttle_listener
, dri2_surf
);
1009 wl_display_flush(dri2_dpy
->wl_dpy
);
1015 dri2_wl_query_buffer_age(_EGLDriver
*drv
,
1016 _EGLDisplay
*disp
, _EGLSurface
*surface
)
1018 struct dri2_egl_surface
*dri2_surf
= dri2_egl_surface(surface
);
1020 if (get_back_bo(dri2_surf
) < 0) {
1021 _eglError(EGL_BAD_ALLOC
, "dri2_query_buffer_age");
1025 return dri2_surf
->back
->age
;
1029 dri2_wl_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*draw
)
1031 return dri2_wl_swap_buffers_with_damage(drv
, disp
, draw
, NULL
, 0);
1034 static struct wl_buffer
*
1035 dri2_wl_create_wayland_buffer_from_image(_EGLDriver
*drv
,
1039 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
1040 struct dri2_egl_image
*dri2_img
= dri2_egl_image(img
);
1041 __DRIimage
*image
= dri2_img
->dri_image
;
1042 struct wl_buffer
*buffer
;
1043 int format
, visual_idx
;
1045 /* Check the upstream display supports this buffer's format. */
1046 dri2_dpy
->image
->queryImage(image
, __DRI_IMAGE_ATTRIB_FORMAT
, &format
);
1047 visual_idx
= dri2_wl_visual_idx_from_dri_image_format(format
);
1048 if (visual_idx
== -1)
1051 if (!(dri2_dpy
->formats
& (1 << visual_idx
)))
1054 buffer
= create_wl_buffer(dri2_dpy
, NULL
, image
);
1056 /* The buffer object will have been created with our internal event queue
1057 * because it is using wl_dmabuf/wl_drm as a proxy factory. We want the
1058 * buffer to be used by the application so we'll reset it to the display's
1059 * default event queue. This isn't actually racy, as the only event the
1060 * buffer can get is a buffer release, which doesn't happen with an explicit
1063 wl_proxy_set_queue((struct wl_proxy
*) buffer
, NULL
);
1068 _eglError(EGL_BAD_MATCH
, "unsupported image format");
1073 dri2_wl_authenticate(_EGLDisplay
*disp
, uint32_t id
)
1075 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
1078 if (dri2_dpy
->is_render_node
) {
1079 _eglLog(_EGL_WARNING
, "wayland-egl: client asks server to "
1080 "authenticate for render-nodes");
1083 dri2_dpy
->authenticated
= false;
1085 wl_drm_authenticate(dri2_dpy
->wl_drm
, id
);
1086 if (roundtrip(dri2_dpy
) < 0)
1089 if (!dri2_dpy
->authenticated
)
1092 /* reset authenticated */
1093 dri2_dpy
->authenticated
= true;
1099 drm_handle_device(void *data
, struct wl_drm
*drm
, const char *device
)
1101 struct dri2_egl_display
*dri2_dpy
= data
;
1104 dri2_dpy
->device_name
= strdup(device
);
1105 if (!dri2_dpy
->device_name
)
1108 dri2_dpy
->fd
= loader_open_device(dri2_dpy
->device_name
);
1109 if (dri2_dpy
->fd
== -1) {
1110 _eglLog(_EGL_WARNING
, "wayland-egl: could not open %s (%s)",
1111 dri2_dpy
->device_name
, strerror(errno
));
1115 if (drmGetNodeTypeFromFd(dri2_dpy
->fd
) == DRM_NODE_RENDER
) {
1116 dri2_dpy
->authenticated
= true;
1118 drmGetMagic(dri2_dpy
->fd
, &magic
);
1119 wl_drm_authenticate(dri2_dpy
->wl_drm
, magic
);
1124 drm_handle_format(void *data
, struct wl_drm
*drm
, uint32_t format
)
1126 struct dri2_egl_display
*dri2_dpy
= data
;
1127 int visual_idx
= dri2_wl_visual_idx_from_fourcc(format
);
1129 if (visual_idx
== -1)
1132 dri2_dpy
->formats
|= (1 << visual_idx
);
1136 drm_handle_capabilities(void *data
, struct wl_drm
*drm
, uint32_t value
)
1138 struct dri2_egl_display
*dri2_dpy
= data
;
1140 dri2_dpy
->capabilities
= value
;
1144 drm_handle_authenticated(void *data
, struct wl_drm
*drm
)
1146 struct dri2_egl_display
*dri2_dpy
= data
;
1148 dri2_dpy
->authenticated
= true;
1151 static const struct wl_drm_listener drm_listener
= {
1152 .device
= drm_handle_device
,
1153 .format
= drm_handle_format
,
1154 .authenticated
= drm_handle_authenticated
,
1155 .capabilities
= drm_handle_capabilities
1159 dmabuf_ignore_format(void *data
, struct zwp_linux_dmabuf_v1
*dmabuf
,
1162 /* formats are implicitly advertised by the 'modifier' event, so ignore */
1166 dmabuf_handle_modifier(void *data
, struct zwp_linux_dmabuf_v1
*dmabuf
,
1167 uint32_t format
, uint32_t modifier_hi
,
1168 uint32_t modifier_lo
)
1170 struct dri2_egl_display
*dri2_dpy
= data
;
1171 int visual_idx
= dri2_wl_visual_idx_from_fourcc(format
);
1174 if (visual_idx
== -1)
1177 if (modifier_hi
== (DRM_FORMAT_MOD_INVALID
>> 32) &&
1178 modifier_lo
== (DRM_FORMAT_MOD_INVALID
& 0xffffffff))
1181 dri2_dpy
->formats
|= (1 << visual_idx
);
1183 mod
= u_vector_add(&dri2_dpy
->wl_modifiers
[visual_idx
]);
1184 *mod
= (uint64_t) modifier_hi
<< 32;
1185 *mod
|= (uint64_t) (modifier_lo
& 0xffffffff);
1188 static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener
= {
1189 .format
= dmabuf_ignore_format
,
1190 .modifier
= dmabuf_handle_modifier
,
1194 registry_handle_global_drm(void *data
, struct wl_registry
*registry
,
1195 uint32_t name
, const char *interface
,
1198 struct dri2_egl_display
*dri2_dpy
= data
;
1200 if (strcmp(interface
, "wl_drm") == 0) {
1202 wl_registry_bind(registry
, name
, &wl_drm_interface
, MIN2(version
, 2));
1203 wl_drm_add_listener(dri2_dpy
->wl_drm
, &drm_listener
, dri2_dpy
);
1204 } else if (strcmp(interface
, "zwp_linux_dmabuf_v1") == 0 && version
>= 3) {
1205 dri2_dpy
->wl_dmabuf
=
1206 wl_registry_bind(registry
, name
, &zwp_linux_dmabuf_v1_interface
,
1208 zwp_linux_dmabuf_v1_add_listener(dri2_dpy
->wl_dmabuf
, &dmabuf_listener
,
1214 registry_handle_global_remove(void *data
, struct wl_registry
*registry
,
1219 static const struct wl_registry_listener registry_listener_drm
= {
1220 .global
= registry_handle_global_drm
,
1221 .global_remove
= registry_handle_global_remove
1225 dri2_wl_setup_swap_interval(_EGLDisplay
*disp
)
1227 /* We can't use values greater than 1 on Wayland because we are using the
1228 * frame callback to synchronise the frame and the only way we be sure to
1229 * get a frame callback is to attach a new buffer. Therefore we can't just
1230 * sit drawing nothing to wait until the next ‘n’ frame callbacks */
1232 dri2_setup_swap_interval(disp
, 1);
1235 static const struct dri2_egl_display_vtbl dri2_wl_display_vtbl
= {
1236 .authenticate
= dri2_wl_authenticate
,
1237 .create_window_surface
= dri2_wl_create_window_surface
,
1238 .create_pixmap_surface
= dri2_wl_create_pixmap_surface
,
1239 .create_pbuffer_surface
= dri2_fallback_create_pbuffer_surface
,
1240 .destroy_surface
= dri2_wl_destroy_surface
,
1241 .create_image
= dri2_create_image_khr
,
1242 .swap_buffers
= dri2_wl_swap_buffers
,
1243 .swap_buffers_with_damage
= dri2_wl_swap_buffers_with_damage
,
1244 .swap_buffers_region
= dri2_fallback_swap_buffers_region
,
1245 .set_damage_region
= dri2_fallback_set_damage_region
,
1246 .post_sub_buffer
= dri2_fallback_post_sub_buffer
,
1247 .copy_buffers
= dri2_fallback_copy_buffers
,
1248 .query_buffer_age
= dri2_wl_query_buffer_age
,
1249 .create_wayland_buffer_from_image
= dri2_wl_create_wayland_buffer_from_image
,
1250 .get_sync_values
= dri2_fallback_get_sync_values
,
1251 .get_dri_drawable
= dri2_surface_get_dri_drawable
,
1254 static const __DRIextension
*dri2_loader_extensions
[] = {
1255 &dri2_loader_extension
.base
,
1256 &image_loader_extension
.base
,
1257 &image_lookup_extension
.base
,
1258 &use_invalidate
.base
,
1262 static const __DRIextension
*image_loader_extensions
[] = {
1263 &image_loader_extension
.base
,
1264 &image_lookup_extension
.base
,
1265 &use_invalidate
.base
,
1270 dri2_wl_add_configs_for_visuals(_EGLDriver
*drv
, _EGLDisplay
*disp
)
1272 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
1273 unsigned int format_count
[ARRAY_SIZE(dri2_wl_visuals
)] = { 0 };
1274 unsigned int count
= 0;
1276 for (unsigned i
= 0; dri2_dpy
->driver_configs
[i
]; i
++) {
1277 for (unsigned j
= 0; j
< ARRAY_SIZE(dri2_wl_visuals
); j
++) {
1278 struct dri2_egl_config
*dri2_conf
;
1280 if (!(dri2_dpy
->formats
& (1 << j
)))
1283 dri2_conf
= dri2_add_config(disp
, dri2_dpy
->driver_configs
[i
],
1284 count
+ 1, EGL_WINDOW_BIT
, NULL
, dri2_wl_visuals
[j
].rgba_masks
);
1286 if (dri2_conf
->base
.ConfigID
== count
+ 1)
1293 for (unsigned i
= 0; i
< ARRAY_SIZE(format_count
); i
++) {
1294 if (!format_count
[i
]) {
1295 _eglLog(_EGL_DEBUG
, "No DRI config supports native format %s",
1296 dri2_wl_visuals
[i
].format_name
);
1300 return (count
!= 0);
1304 dri2_initialize_wayland_drm(_EGLDriver
*drv
, _EGLDisplay
*disp
)
1306 struct dri2_egl_display
*dri2_dpy
;
1308 loader_set_logger(_eglLog
);
1310 dri2_dpy
= calloc(1, sizeof *dri2_dpy
);
1312 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
1315 disp
->DriverData
= (void *) dri2_dpy
;
1316 if (disp
->PlatformDisplay
== NULL
) {
1317 dri2_dpy
->wl_dpy
= wl_display_connect(NULL
);
1318 if (dri2_dpy
->wl_dpy
== NULL
)
1320 dri2_dpy
->own_device
= true;
1322 dri2_dpy
->wl_dpy
= disp
->PlatformDisplay
;
1325 dri2_dpy
->wl_modifiers
=
1326 calloc(ARRAY_SIZE(dri2_wl_visuals
), sizeof(*dri2_dpy
->wl_modifiers
));
1327 if (!dri2_dpy
->wl_modifiers
)
1329 for (int i
= 0; i
< ARRAY_SIZE(dri2_wl_visuals
); i
++) {
1330 if (!u_vector_init(&dri2_dpy
->wl_modifiers
[i
], sizeof(uint64_t), 32))
1334 dri2_dpy
->wl_queue
= wl_display_create_queue(dri2_dpy
->wl_dpy
);
1336 dri2_dpy
->wl_dpy_wrapper
= wl_proxy_create_wrapper(dri2_dpy
->wl_dpy
);
1337 if (dri2_dpy
->wl_dpy_wrapper
== NULL
)
1340 wl_proxy_set_queue((struct wl_proxy
*) dri2_dpy
->wl_dpy_wrapper
,
1341 dri2_dpy
->wl_queue
);
1343 if (dri2_dpy
->own_device
)
1344 wl_display_dispatch_pending(dri2_dpy
->wl_dpy
);
1346 dri2_dpy
->wl_registry
= wl_display_get_registry(dri2_dpy
->wl_dpy_wrapper
);
1347 wl_registry_add_listener(dri2_dpy
->wl_registry
,
1348 ®istry_listener_drm
, dri2_dpy
);
1349 if (roundtrip(dri2_dpy
) < 0 || dri2_dpy
->wl_drm
== NULL
)
1352 if (roundtrip(dri2_dpy
) < 0 || dri2_dpy
->fd
== -1)
1355 if (roundtrip(dri2_dpy
) < 0 || !dri2_dpy
->authenticated
)
1358 dri2_dpy
->fd
= loader_get_user_preferred_fd(dri2_dpy
->fd
,
1359 &dri2_dpy
->is_different_gpu
);
1360 if (dri2_dpy
->is_different_gpu
) {
1361 free(dri2_dpy
->device_name
);
1362 dri2_dpy
->device_name
= loader_get_device_name_for_fd(dri2_dpy
->fd
);
1363 if (!dri2_dpy
->device_name
) {
1364 _eglError(EGL_BAD_ALLOC
, "wayland-egl: failed to get device name "
1365 "for requested GPU");
1370 /* we have to do the check now, because loader_get_user_preferred_fd
1371 * will return a render-node when the requested gpu is different
1372 * to the server, but also if the client asks for the same gpu than
1373 * the server by requesting its pci-id */
1374 dri2_dpy
->is_render_node
= drmGetNodeTypeFromFd(dri2_dpy
->fd
) == DRM_NODE_RENDER
;
1376 dri2_dpy
->driver_name
= loader_get_driver_for_fd(dri2_dpy
->fd
);
1377 if (dri2_dpy
->driver_name
== NULL
) {
1378 _eglError(EGL_BAD_ALLOC
, "DRI2: failed to get driver name");
1382 /* render nodes cannot use Gem names, and thus do not support
1383 * the __DRI_DRI2_LOADER extension */
1384 if (!dri2_dpy
->is_render_node
) {
1385 dri2_dpy
->loader_extensions
= dri2_loader_extensions
;
1386 if (!dri2_load_driver(disp
)) {
1387 _eglError(EGL_BAD_ALLOC
, "DRI2: failed to load driver");
1391 dri2_dpy
->loader_extensions
= image_loader_extensions
;
1392 if (!dri2_load_driver_dri3(disp
)) {
1393 _eglError(EGL_BAD_ALLOC
, "DRI3: failed to load driver");
1398 if (!dri2_create_screen(disp
))
1401 if (!dri2_setup_extensions(disp
))
1404 dri2_setup_screen(disp
);
1406 dri2_wl_setup_swap_interval(disp
);
1408 /* To use Prime, we must have _DRI_IMAGE v7 at least.
1409 * createImageFromFds support indicates that Prime export/import
1410 * is supported by the driver. Fall back to
1411 * gem names if we don't have Prime support. */
1413 if (dri2_dpy
->image
->base
.version
< 7 ||
1414 dri2_dpy
->image
->createImageFromFds
== NULL
)
1415 dri2_dpy
->capabilities
&= ~WL_DRM_CAPABILITY_PRIME
;
1417 /* We cannot use Gem names with render-nodes, only prime fds (dma-buf).
1418 * The server needs to accept them */
1419 if (dri2_dpy
->is_render_node
&&
1420 !(dri2_dpy
->capabilities
& WL_DRM_CAPABILITY_PRIME
)) {
1421 _eglLog(_EGL_WARNING
, "wayland-egl: display is not render-node capable");
1425 if (dri2_dpy
->is_different_gpu
&&
1426 (dri2_dpy
->image
->base
.version
< 9 ||
1427 dri2_dpy
->image
->blitImage
== NULL
)) {
1428 _eglLog(_EGL_WARNING
, "wayland-egl: Different GPU selected, but the "
1429 "Image extension in the driver is not "
1430 "compatible. Version 9 or later and blitImage() "
1435 if (!dri2_wl_add_configs_for_visuals(drv
, disp
)) {
1436 _eglError(EGL_NOT_INITIALIZED
, "DRI2: failed to add configs");
1440 dri2_set_WL_bind_wayland_display(drv
, disp
);
1441 /* When cannot convert EGLImage to wl_buffer when on a different gpu,
1442 * because the buffer of the EGLImage has likely a tiling mode the server
1443 * gpu won't support. These is no way to check for now. Thus do not support the
1445 if (!dri2_dpy
->is_different_gpu
)
1446 disp
->Extensions
.WL_create_wayland_buffer_from_image
= EGL_TRUE
;
1448 disp
->Extensions
.EXT_buffer_age
= EGL_TRUE
;
1450 disp
->Extensions
.EXT_swap_buffers_with_damage
= EGL_TRUE
;
1452 /* Fill vtbl last to prevent accidentally calling virtual function during
1455 dri2_dpy
->vtbl
= &dri2_wl_display_vtbl
;
1460 dri2_display_destroy(disp
);
1465 dri2_wl_swrast_get_stride_for_format(int format
, int w
)
1467 int visual_idx
= dri2_wl_visual_idx_from_shm_format(format
);
1469 assume(visual_idx
!= -1);
1471 return w
* (dri2_wl_visuals
[visual_idx
].bpp
/ 8);
1475 * Taken from weston shared/os-compatibility.c
1478 #ifndef HAVE_MKOSTEMP
1481 set_cloexec_or_close(int fd
)
1488 flags
= fcntl(fd
, F_GETFD
);
1492 if (fcntl(fd
, F_SETFD
, flags
| FD_CLOEXEC
) == -1)
1505 * Taken from weston shared/os-compatibility.c
1509 create_tmpfile_cloexec(char *tmpname
)
1513 #ifdef HAVE_MKOSTEMP
1514 fd
= mkostemp(tmpname
, O_CLOEXEC
);
1518 fd
= mkstemp(tmpname
);
1520 fd
= set_cloexec_or_close(fd
);
1529 * Taken from weston shared/os-compatibility.c
1531 * Create a new, unique, anonymous file of the given size, and
1532 * return the file descriptor for it. The file descriptor is set
1533 * CLOEXEC. The file is immediately suitable for mmap()'ing
1534 * the given size at offset zero.
1536 * The file should not have a permanent backing store like a disk,
1537 * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
1539 * The file name is deleted from the file system.
1541 * The file is suitable for buffer sharing between processes by
1542 * transmitting the file descriptor over Unix sockets using the
1543 * SCM_RIGHTS methods.
1545 * If the C library implements posix_fallocate(), it is used to
1546 * guarantee that disk space is available for the file at the
1547 * given size. If disk space is insufficent, errno is set to ENOSPC.
1548 * If posix_fallocate() is not supported, program may receive
1549 * SIGBUS on accessing mmap()'ed file contents instead.
1552 os_create_anonymous_file(off_t size
)
1554 static const char templ
[] = "/mesa-shared-XXXXXX";
1560 path
= getenv("XDG_RUNTIME_DIR");
1566 name
= malloc(strlen(path
) + sizeof(templ
));
1571 strcat(name
, templ
);
1573 fd
= create_tmpfile_cloexec(name
);
1580 ret
= ftruncate(fd
, size
);
1591 dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface
*dri2_surf
,
1592 int format
, int w
, int h
,
1593 void **data
, int *size
,
1594 struct wl_buffer
**buffer
)
1596 struct dri2_egl_display
*dri2_dpy
=
1597 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
1598 struct wl_shm_pool
*pool
;
1599 int fd
, stride
, size_map
;
1602 stride
= dri2_wl_swrast_get_stride_for_format(format
, w
);
1603 size_map
= h
* stride
;
1605 /* Create a sharable buffer */
1606 fd
= os_create_anonymous_file(size_map
);
1610 data_map
= mmap(NULL
, size_map
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
1611 if (data_map
== MAP_FAILED
) {
1616 /* Share it in a wl_buffer */
1617 pool
= wl_shm_create_pool(dri2_dpy
->wl_shm
, fd
, size_map
);
1618 wl_proxy_set_queue((struct wl_proxy
*)pool
, dri2_surf
->wl_queue
);
1619 *buffer
= wl_shm_pool_create_buffer(pool
, 0, w
, h
, stride
, format
);
1620 wl_shm_pool_destroy(pool
);
1629 swrast_update_buffers(struct dri2_egl_surface
*dri2_surf
)
1631 struct dri2_egl_display
*dri2_dpy
=
1632 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
1634 /* we need to do the following operations only once per frame */
1635 if (dri2_surf
->back
)
1638 if (dri2_surf
->base
.Width
!= dri2_surf
->wl_win
->width
||
1639 dri2_surf
->base
.Height
!= dri2_surf
->wl_win
->height
) {
1641 dri2_wl_release_buffers(dri2_surf
);
1643 dri2_surf
->base
.Width
= dri2_surf
->wl_win
->width
;
1644 dri2_surf
->base
.Height
= dri2_surf
->wl_win
->height
;
1645 dri2_surf
->dx
= dri2_surf
->wl_win
->dx
;
1646 dri2_surf
->dy
= dri2_surf
->wl_win
->dy
;
1647 dri2_surf
->current
= NULL
;
1650 /* find back buffer */
1652 /* There might be a buffer release already queued that wasn't processed */
1653 wl_display_dispatch_queue_pending(dri2_dpy
->wl_dpy
, dri2_surf
->wl_queue
);
1655 /* try get free buffer already created */
1656 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
1657 if (!dri2_surf
->color_buffers
[i
].locked
&&
1658 dri2_surf
->color_buffers
[i
].wl_buffer
) {
1659 dri2_surf
->back
= &dri2_surf
->color_buffers
[i
];
1664 /* else choose any another free location */
1665 if (!dri2_surf
->back
) {
1666 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
1667 if (!dri2_surf
->color_buffers
[i
].locked
) {
1668 dri2_surf
->back
= &dri2_surf
->color_buffers
[i
];
1669 if (!dri2_wl_swrast_allocate_buffer(dri2_surf
,
1671 dri2_surf
->base
.Width
,
1672 dri2_surf
->base
.Height
,
1673 &dri2_surf
->back
->data
,
1674 &dri2_surf
->back
->data_size
,
1675 &dri2_surf
->back
->wl_buffer
)) {
1676 _eglError(EGL_BAD_ALLOC
, "failed to allocate color buffer");
1679 wl_buffer_add_listener(dri2_surf
->back
->wl_buffer
,
1680 &wl_buffer_listener
, dri2_surf
);
1686 if (!dri2_surf
->back
) {
1687 _eglError(EGL_BAD_ALLOC
, "failed to find free buffer");
1691 dri2_surf
->back
->locked
= true;
1693 /* If we have an extra unlocked buffer at this point, we had to do triple
1694 * buffering for a while, but now can go back to just double buffering.
1695 * That means we can free any unlocked buffer now. */
1696 for (int i
= 0; i
< ARRAY_SIZE(dri2_surf
->color_buffers
); i
++) {
1697 if (!dri2_surf
->color_buffers
[i
].locked
&&
1698 dri2_surf
->color_buffers
[i
].wl_buffer
) {
1699 wl_buffer_destroy(dri2_surf
->color_buffers
[i
].wl_buffer
);
1700 munmap(dri2_surf
->color_buffers
[i
].data
,
1701 dri2_surf
->color_buffers
[i
].data_size
);
1702 dri2_surf
->color_buffers
[i
].wl_buffer
= NULL
;
1703 dri2_surf
->color_buffers
[i
].data
= NULL
;
1711 dri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface
*dri2_surf
)
1713 /* if there has been a resize: */
1714 if (!dri2_surf
->current
)
1717 return dri2_surf
->current
->data
;
1721 dri2_wl_swrast_get_backbuffer_data(struct dri2_egl_surface
*dri2_surf
)
1723 assert(dri2_surf
->back
);
1724 return dri2_surf
->back
->data
;
1728 dri2_wl_swrast_commit_backbuffer(struct dri2_egl_surface
*dri2_surf
)
1730 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
1732 while (dri2_surf
->throttle_callback
!= NULL
)
1733 if (wl_display_dispatch_queue(dri2_dpy
->wl_dpy
,
1734 dri2_surf
->wl_queue
) == -1)
1737 if (dri2_surf
->base
.SwapInterval
> 0) {
1738 dri2_surf
->throttle_callback
=
1739 wl_surface_frame(dri2_surf
->wl_surface_wrapper
);
1740 wl_callback_add_listener(dri2_surf
->throttle_callback
,
1741 &throttle_listener
, dri2_surf
);
1744 dri2_surf
->current
= dri2_surf
->back
;
1745 dri2_surf
->back
= NULL
;
1747 wl_surface_attach(dri2_surf
->wl_surface_wrapper
,
1748 dri2_surf
->current
->wl_buffer
,
1749 dri2_surf
->dx
, dri2_surf
->dy
);
1751 dri2_surf
->wl_win
->attached_width
= dri2_surf
->base
.Width
;
1752 dri2_surf
->wl_win
->attached_height
= dri2_surf
->base
.Height
;
1753 /* reset resize growing parameters */
1757 wl_surface_damage(dri2_surf
->wl_surface_wrapper
,
1758 0, 0, INT32_MAX
, INT32_MAX
);
1759 wl_surface_commit(dri2_surf
->wl_surface_wrapper
);
1761 /* If we're not waiting for a frame callback then we'll at least throttle
1762 * to a sync callback so that we always give a chance for the compositor to
1763 * handle the commit and send a release event before checking for a free
1765 if (dri2_surf
->throttle_callback
== NULL
) {
1766 dri2_surf
->throttle_callback
= wl_display_sync(dri2_surf
->wl_dpy_wrapper
);
1767 wl_callback_add_listener(dri2_surf
->throttle_callback
,
1768 &throttle_listener
, dri2_surf
);
1771 wl_display_flush(dri2_dpy
->wl_dpy
);
1775 dri2_wl_swrast_get_drawable_info(__DRIdrawable
* draw
,
1776 int *x
, int *y
, int *w
, int *h
,
1777 void *loaderPrivate
)
1779 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
1781 (void) swrast_update_buffers(dri2_surf
);
1784 *w
= dri2_surf
->base
.Width
;
1785 *h
= dri2_surf
->base
.Height
;
1789 dri2_wl_swrast_get_image(__DRIdrawable
* read
,
1790 int x
, int y
, int w
, int h
,
1791 char *data
, void *loaderPrivate
)
1793 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
1794 int copy_width
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, w
);
1795 int x_offset
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, x
);
1796 int src_stride
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, dri2_surf
->base
.Width
);
1797 int dst_stride
= copy_width
;
1800 src
= dri2_wl_swrast_get_frontbuffer_data(dri2_surf
);
1802 memset(data
, 0, copy_width
* h
);
1806 assert(data
!= src
);
1807 assert(copy_width
<= src_stride
);
1810 src
+= y
* src_stride
;
1813 if (copy_width
> src_stride
-x_offset
)
1814 copy_width
= src_stride
-x_offset
;
1815 if (h
> dri2_surf
->base
.Height
-y
)
1816 h
= dri2_surf
->base
.Height
-y
;
1819 memcpy(dst
, src
, copy_width
);
1826 dri2_wl_swrast_put_image2(__DRIdrawable
* draw
, int op
,
1827 int x
, int y
, int w
, int h
, int stride
,
1828 char *data
, void *loaderPrivate
)
1830 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
1831 int copy_width
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, w
);
1832 int dst_stride
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, dri2_surf
->base
.Width
);
1833 int x_offset
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, x
);
1836 assert(copy_width
<= stride
);
1838 (void) swrast_update_buffers(dri2_surf
);
1839 dst
= dri2_wl_swrast_get_backbuffer_data(dri2_surf
);
1841 /* partial copy, copy old content */
1842 if (copy_width
< dst_stride
)
1843 dri2_wl_swrast_get_image(draw
, 0, 0,
1844 dri2_surf
->base
.Width
, dri2_surf
->base
.Height
,
1845 dst
, loaderPrivate
);
1848 dst
+= y
* dst_stride
;
1852 /* drivers expect we do these checks (and some rely on it) */
1853 if (copy_width
> dst_stride
-x_offset
)
1854 copy_width
= dst_stride
-x_offset
;
1855 if (h
> dri2_surf
->base
.Height
-y
)
1856 h
= dri2_surf
->base
.Height
-y
;
1859 memcpy(dst
, src
, copy_width
);
1863 dri2_wl_swrast_commit_backbuffer(dri2_surf
);
1867 dri2_wl_swrast_put_image(__DRIdrawable
* draw
, int op
,
1868 int x
, int y
, int w
, int h
,
1869 char *data
, void *loaderPrivate
)
1871 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
1874 stride
= dri2_wl_swrast_get_stride_for_format(dri2_surf
->format
, w
);
1875 dri2_wl_swrast_put_image2(draw
, op
, x
, y
, w
, h
,
1876 stride
, data
, loaderPrivate
);
1880 dri2_wl_swrast_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*disp
, _EGLSurface
*draw
)
1882 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
1883 struct dri2_egl_surface
*dri2_surf
= dri2_egl_surface(draw
);
1885 dri2_dpy
->core
->swapBuffers(dri2_surf
->dri_drawable
);
1890 shm_handle_format(void *data
, struct wl_shm
*shm
, uint32_t format
)
1892 struct dri2_egl_display
*dri2_dpy
= data
;
1893 int visual_idx
= dri2_wl_visual_idx_from_shm_format(format
);
1895 if (visual_idx
== -1)
1898 dri2_dpy
->formats
|= (1 << visual_idx
);
1901 static const struct wl_shm_listener shm_listener
= {
1902 .format
= shm_handle_format
1906 registry_handle_global_swrast(void *data
, struct wl_registry
*registry
,
1907 uint32_t name
, const char *interface
,
1910 struct dri2_egl_display
*dri2_dpy
= data
;
1912 if (strcmp(interface
, "wl_shm") == 0) {
1914 wl_registry_bind(registry
, name
, &wl_shm_interface
, 1);
1915 wl_shm_add_listener(dri2_dpy
->wl_shm
, &shm_listener
, dri2_dpy
);
1919 static const struct wl_registry_listener registry_listener_swrast
= {
1920 .global
= registry_handle_global_swrast
,
1921 .global_remove
= registry_handle_global_remove
1924 static const struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl
= {
1925 .authenticate
= NULL
,
1926 .create_window_surface
= dri2_wl_create_window_surface
,
1927 .create_pixmap_surface
= dri2_wl_create_pixmap_surface
,
1928 .create_pbuffer_surface
= dri2_fallback_create_pbuffer_surface
,
1929 .destroy_surface
= dri2_wl_destroy_surface
,
1930 .create_image
= dri2_create_image_khr
,
1931 .swap_buffers
= dri2_wl_swrast_swap_buffers
,
1932 .swap_buffers_with_damage
= dri2_fallback_swap_buffers_with_damage
,
1933 .swap_buffers_region
= dri2_fallback_swap_buffers_region
,
1934 .post_sub_buffer
= dri2_fallback_post_sub_buffer
,
1935 .copy_buffers
= dri2_fallback_copy_buffers
,
1936 .query_buffer_age
= dri2_fallback_query_buffer_age
,
1937 .create_wayland_buffer_from_image
= dri2_fallback_create_wayland_buffer_from_image
,
1938 .get_sync_values
= dri2_fallback_get_sync_values
,
1939 .get_dri_drawable
= dri2_surface_get_dri_drawable
,
1942 static const __DRIswrastLoaderExtension swrast_loader_extension
= {
1943 .base
= { __DRI_SWRAST_LOADER
, 2 },
1945 .getDrawableInfo
= dri2_wl_swrast_get_drawable_info
,
1946 .putImage
= dri2_wl_swrast_put_image
,
1947 .getImage
= dri2_wl_swrast_get_image
,
1948 .putImage2
= dri2_wl_swrast_put_image2
,
1951 static const __DRIextension
*swrast_loader_extensions
[] = {
1952 &swrast_loader_extension
.base
,
1953 &image_lookup_extension
.base
,
1958 dri2_initialize_wayland_swrast(_EGLDriver
*drv
, _EGLDisplay
*disp
)
1960 struct dri2_egl_display
*dri2_dpy
;
1962 loader_set_logger(_eglLog
);
1964 dri2_dpy
= calloc(1, sizeof *dri2_dpy
);
1966 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
1969 disp
->DriverData
= (void *) dri2_dpy
;
1970 if (disp
->PlatformDisplay
== NULL
) {
1971 dri2_dpy
->wl_dpy
= wl_display_connect(NULL
);
1972 if (dri2_dpy
->wl_dpy
== NULL
)
1974 dri2_dpy
->own_device
= true;
1976 dri2_dpy
->wl_dpy
= disp
->PlatformDisplay
;
1979 dri2_dpy
->wl_queue
= wl_display_create_queue(dri2_dpy
->wl_dpy
);
1981 dri2_dpy
->wl_dpy_wrapper
= wl_proxy_create_wrapper(dri2_dpy
->wl_dpy
);
1982 if (dri2_dpy
->wl_dpy_wrapper
== NULL
)
1985 wl_proxy_set_queue((struct wl_proxy
*) dri2_dpy
->wl_dpy_wrapper
,
1986 dri2_dpy
->wl_queue
);
1988 if (dri2_dpy
->own_device
)
1989 wl_display_dispatch_pending(dri2_dpy
->wl_dpy
);
1991 dri2_dpy
->wl_registry
= wl_display_get_registry(dri2_dpy
->wl_dpy_wrapper
);
1992 wl_registry_add_listener(dri2_dpy
->wl_registry
,
1993 ®istry_listener_swrast
, dri2_dpy
);
1995 if (roundtrip(dri2_dpy
) < 0 || dri2_dpy
->wl_shm
== NULL
)
1998 if (roundtrip(dri2_dpy
) < 0 || dri2_dpy
->formats
== 0)
2001 dri2_dpy
->driver_name
= strdup("swrast");
2002 if (!dri2_load_driver_swrast(disp
))
2005 dri2_dpy
->loader_extensions
= swrast_loader_extensions
;
2007 if (!dri2_create_screen(disp
))
2010 if (!dri2_setup_extensions(disp
))
2013 dri2_setup_screen(disp
);
2015 dri2_wl_setup_swap_interval(disp
);
2017 if (!dri2_wl_add_configs_for_visuals(drv
, disp
)) {
2018 _eglError(EGL_NOT_INITIALIZED
, "DRI2: failed to add configs");
2022 /* Fill vtbl last to prevent accidentally calling virtual function during
2025 dri2_dpy
->vtbl
= &dri2_wl_swrast_display_vtbl
;
2030 dri2_display_destroy(disp
);
2035 dri2_initialize_wayland(_EGLDriver
*drv
, _EGLDisplay
*disp
)
2037 EGLBoolean initialized
= EGL_FALSE
;
2039 if (!disp
->Options
.ForceSoftware
)
2040 initialized
= dri2_initialize_wayland_drm(drv
, disp
);
2043 initialized
= dri2_initialize_wayland_swrast(drv
, disp
);
2050 dri2_teardown_wayland(struct dri2_egl_display
*dri2_dpy
)
2052 if (dri2_dpy
->wl_drm
)
2053 wl_drm_destroy(dri2_dpy
->wl_drm
);
2054 if (dri2_dpy
->wl_dmabuf
)
2055 zwp_linux_dmabuf_v1_destroy(dri2_dpy
->wl_dmabuf
);
2056 if (dri2_dpy
->wl_shm
)
2057 wl_shm_destroy(dri2_dpy
->wl_shm
);
2058 if (dri2_dpy
->wl_registry
)
2059 wl_registry_destroy(dri2_dpy
->wl_registry
);
2060 if (dri2_dpy
->wl_queue
)
2061 wl_event_queue_destroy(dri2_dpy
->wl_queue
);
2062 if (dri2_dpy
->wl_dpy_wrapper
)
2063 wl_proxy_wrapper_destroy(dri2_dpy
->wl_dpy_wrapper
);
2065 for (int i
= 0; dri2_dpy
->wl_modifiers
&& i
< ARRAY_SIZE(dri2_wl_visuals
); i
++)
2066 u_vector_finish(&dri2_dpy
->wl_modifiers
[i
]);
2067 free(dri2_dpy
->wl_modifiers
);
2069 if (dri2_dpy
->own_device
)
2070 wl_display_disconnect(dri2_dpy
->wl_dpy
);