blob: e1bacd804a7c9450b23fbc8bd3d06334c9f8948d [file] [log] [blame]
Boyan Dingf35198b2015-07-21 23:44:00 +08001/*
2 * Copyright © 2015 Boyan Ding
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <stdbool.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27
28#include <xcb/xcb.h>
29#include <xcb/dri3.h>
30#include <xcb/present.h>
31
32#include <xf86drm.h>
Emil Velikov239e7ee2017-05-04 18:55:36 +010033#include "util/macros.h"
Boyan Dingf35198b2015-07-21 23:44:00 +080034
35#include "egl_dri2.h"
Boyan Dingf35198b2015-07-21 23:44:00 +080036#include "platform_x11_dri3.h"
37
38#include "loader.h"
39#include "loader_dri3_helper.h"
40
41static struct dri3_egl_surface *
42loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
43 size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
44 return (struct dri3_egl_surface *)(((void*) draw) - offset);
45}
46
Boyan Dingf35198b2015-07-21 23:44:00 +080047static void
48egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
49 int width, int height)
50{
51 struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
52
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +010053 dri3_surf->surf.base.Width = width;
54 dri3_surf->surf.base.Height = height;
Boyan Dingf35198b2015-07-21 23:44:00 +080055}
56
57static bool
58egl_dri3_in_current_context(struct loader_dri3_drawable *draw)
59{
60 struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
61 _EGLContext *ctx = _eglGetCurrentContext();
62
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +010063 return ctx->Resource.Display == dri3_surf->surf.base.Resource.Display;
Boyan Dingf35198b2015-07-21 23:44:00 +080064}
65
66static __DRIcontext *
67egl_dri3_get_dri_context(struct loader_dri3_drawable *draw)
68{
69 _EGLContext *ctx = _eglGetCurrentContext();
Dave Airlied98d6e62016-05-30 08:02:00 +100070 struct dri2_egl_context *dri2_ctx;
71 if (!ctx)
72 return NULL;
73 dri2_ctx = dri2_egl_context(ctx);
Boyan Dingf35198b2015-07-21 23:44:00 +080074 return dri2_ctx->dri_context;
75}
76
Thomas Hellstromf3867762018-02-09 09:37:19 +010077static __DRIscreen *
78egl_dri3_get_dri_screen(void)
79{
80 _EGLContext *ctx = _eglGetCurrentContext();
81 struct dri2_egl_context *dri2_ctx;
82 if (!ctx)
83 return NULL;
84 dri2_ctx = dri2_egl_context(ctx);
85 return dri2_egl_display(dri2_ctx->base.Resource.Display)->dri_screen;
86}
87
Boyan Dingf35198b2015-07-21 23:44:00 +080088static void
89egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
90{
91 struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +010092 _EGLDisplay *disp = dri3_surf->surf.base.Resource.Display;
Boyan Dingf35198b2015-07-21 23:44:00 +080093
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +010094 dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->surf.base);
Boyan Dingf35198b2015-07-21 23:44:00 +080095}
96
Emil Velikov9caacb32016-08-25 11:08:30 +010097static const struct loader_dri3_vtable egl_dri3_vtable = {
Boyan Dingf35198b2015-07-21 23:44:00 +080098 .set_drawable_size = egl_dri3_set_drawable_size,
99 .in_current_context = egl_dri3_in_current_context,
100 .get_dri_context = egl_dri3_get_dri_context,
Thomas Hellstromf3867762018-02-09 09:37:19 +0100101 .get_dri_screen = egl_dri3_get_dri_screen,
Boyan Dingf35198b2015-07-21 23:44:00 +0800102 .flush_drawable = egl_dri3_flush_drawable,
103 .show_fps = NULL,
104};
105
106static EGLBoolean
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200107dri3_destroy_surface(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
Boyan Dingf35198b2015-07-21 23:44:00 +0800108{
Eric Anholtb618d7e2018-08-07 11:37:28 -0700109 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
Boyan Dingf35198b2015-07-21 23:44:00 +0800110 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
Eric Anholtb618d7e2018-08-07 11:37:28 -0700111 xcb_drawable_t drawable = dri3_surf->loader_drawable.drawable;
Boyan Dingf35198b2015-07-21 23:44:00 +0800112
113 (void) drv;
114
Boyan Dingf35198b2015-07-21 23:44:00 +0800115 loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
116
Eric Anholtb618d7e2018-08-07 11:37:28 -0700117 if (surf->Type == EGL_PBUFFER_BIT)
118 xcb_free_pixmap (dri2_dpy->conn, drawable);
119
Zhongmin Wue013ce82017-09-15 18:32:42 +0100120 dri2_fini_surface(surf);
Boyan Dingf35198b2015-07-21 23:44:00 +0800121 free(surf);
122
123 return EGL_TRUE;
124}
125
126static EGLBoolean
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200127dri3_set_swap_interval(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
Boyan Dingf35198b2015-07-21 23:44:00 +0800128 EGLint interval)
129{
130 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
131
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +0100132 dri3_surf->surf.base.SwapInterval = interval;
Boyan Dingf35198b2015-07-21 23:44:00 +0800133 loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
134
135 return EGL_TRUE;
136}
137
Boyan Dingf35198b2015-07-21 23:44:00 +0800138static _EGLSurface *
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200139dri3_create_surface(const _EGLDriver *drv, _EGLDisplay *disp, EGLint type,
Boyan Dingf35198b2015-07-21 23:44:00 +0800140 _EGLConfig *conf, void *native_surface,
141 const EGLint *attrib_list)
142{
143 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
144 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
145 struct dri3_egl_surface *dri3_surf;
146 const __DRIconfig *dri_config;
147 xcb_drawable_t drawable;
Boyan Dingf35198b2015-07-21 23:44:00 +0800148
Boyan Dingf35198b2015-07-21 23:44:00 +0800149 (void) drv;
150
151 dri3_surf = calloc(1, sizeof *dri3_surf);
152 if (!dri3_surf) {
153 _eglError(EGL_BAD_ALLOC, "dri3_create_surface");
154 return NULL;
155 }
156
Paulo Zanoni04ecda32019-05-01 15:42:26 -0700157 if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf,
158 attrib_list, false, native_surface))
Boyan Dingf35198b2015-07-21 23:44:00 +0800159 goto cleanup_surf;
160
161 if (type == EGL_PBUFFER_BIT) {
Boyan Dingf35198b2015-07-21 23:44:00 +0800162 drawable = xcb_generate_id(dri2_dpy->conn);
163 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
Emil Velikov7c6babb2016-11-21 13:46:51 +0000164 drawable, dri2_dpy->screen->root,
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +0100165 dri3_surf->surf.base.Width, dri3_surf->surf.base.Height);
Matt Turner9c0dad02017-08-05 00:25:50 +0100166 } else {
167 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
168 drawable = (uintptr_t) native_surface;
Boyan Dingf35198b2015-07-21 23:44:00 +0800169 }
170
171 dri_config = dri2_get_dri_config(dri2_conf, type,
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +0100172 dri3_surf->surf.base.GLColorspace);
Boyan Dingf35198b2015-07-21 23:44:00 +0800173
Juan A. Suarez Romerofd4eba42018-05-02 16:20:16 +0000174 if (!dri_config) {
175 _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
176 goto cleanup_pixmap;
177 }
178
Boyan Dingf35198b2015-07-21 23:44:00 +0800179 if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
180 dri2_dpy->dri_screen,
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400181 dri2_dpy->is_different_gpu,
182 dri2_dpy->multibuffers_available,
183 dri_config,
Boyan Dingf35198b2015-07-21 23:44:00 +0800184 &dri2_dpy->loader_dri3_ext,
185 &egl_dri3_vtable,
186 &dri3_surf->loader_drawable)) {
187 _eglError(EGL_BAD_ALLOC, "dri3_surface_create");
188 goto cleanup_pixmap;
189 }
190
Yogesh Marathe0b3fc8f2017-09-15 18:32:41 +0100191 return &dri3_surf->surf.base;
Boyan Dingf35198b2015-07-21 23:44:00 +0800192
193 cleanup_pixmap:
194 if (type == EGL_PBUFFER_BIT)
195 xcb_free_pixmap(dri2_dpy->conn, drawable);
196 cleanup_surf:
197 free(dri3_surf);
198
199 return NULL;
200}
201
Frank Binns55058452016-06-17 18:41:21 +0100202static int
203dri3_authenticate(_EGLDisplay *disp, uint32_t id)
204{
Frank Binnsd6f669b2016-06-17 18:41:22 +0100205#ifdef HAVE_WAYLAND_PLATFORM
Frank Binns55058452016-06-17 18:41:21 +0100206 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
207
208 if (dri2_dpy->device_name) {
209 _eglLog(_EGL_WARNING,
210 "Wayland client render node authentication is unnecessary");
211 return 0;
212 }
213
214 _eglLog(_EGL_WARNING,
215 "Wayland client primary node authentication isn't supported");
Frank Binnsd6f669b2016-06-17 18:41:22 +0100216#endif
Frank Binns55058452016-06-17 18:41:21 +0100217
218 return -1;
219}
220
Boyan Dingf35198b2015-07-21 23:44:00 +0800221/**
Eric Engestromcc034482020-07-20 13:38:24 +0200222 * Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
Boyan Dingf35198b2015-07-21 23:44:00 +0800223 */
224static _EGLSurface *
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200225dri3_create_window_surface(const _EGLDriver *drv, _EGLDisplay *disp,
Boyan Dingf35198b2015-07-21 23:44:00 +0800226 _EGLConfig *conf, void *native_window,
227 const EGLint *attrib_list)
228{
229 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
230 _EGLSurface *surf;
231
232 surf = dri3_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
233 native_window, attrib_list);
234 if (surf != NULL)
235 dri3_set_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
236
237 return surf;
238}
239
240static _EGLSurface *
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200241dri3_create_pixmap_surface(const _EGLDriver *drv, _EGLDisplay *disp,
Boyan Dingf35198b2015-07-21 23:44:00 +0800242 _EGLConfig *conf, void *native_pixmap,
243 const EGLint *attrib_list)
244{
245 return dri3_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
246 native_pixmap, attrib_list);
247}
248
249static _EGLSurface *
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200250dri3_create_pbuffer_surface(const _EGLDriver *drv, _EGLDisplay *disp,
Boyan Dingf35198b2015-07-21 23:44:00 +0800251 _EGLConfig *conf, const EGLint *attrib_list)
252{
253 return dri3_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
Emil Velikov794df9a2017-08-05 00:25:51 +0100254 NULL, attrib_list);
Boyan Dingf35198b2015-07-21 23:44:00 +0800255}
256
257static EGLBoolean
258dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
259 EGLuint64KHR *ust, EGLuint64KHR *msc,
260 EGLuint64KHR *sbc)
261{
262 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface);
263
264 return loader_dri3_wait_for_msc(&dri3_surf->loader_drawable, 0, 0, 0,
265 (int64_t *) ust, (int64_t *) msc,
266 (int64_t *) sbc) ? EGL_TRUE : EGL_FALSE;
267}
268
Boyan Dingfcdc7982015-07-21 23:44:02 +0800269static _EGLImage *
270dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
271 EGLClientBuffer buffer, const EGLint *attr_list)
272{
273 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
274 struct dri2_egl_image *dri2_img;
275 xcb_drawable_t drawable;
276 xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
277 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
278 unsigned int format;
279
280 drawable = (xcb_drawable_t) (uintptr_t) buffer;
281 bp_cookie = xcb_dri3_buffer_from_pixmap(dri2_dpy->conn, drawable);
282 bp_reply = xcb_dri3_buffer_from_pixmap_reply(dri2_dpy->conn,
283 bp_cookie, NULL);
284 if (!bp_reply) {
285 _eglError(EGL_BAD_ALLOC, "xcb_dri3_buffer_from_pixmap");
286 return NULL;
287 }
288
Mario Kleiner61a02722018-06-13 06:04:13 +0200289 format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400290 if (format == __DRI_IMAGE_FORMAT_NONE) {
Boyan Dingfcdc7982015-07-21 23:44:02 +0800291 _eglError(EGL_BAD_PARAMETER,
292 "dri3_create_image_khr: unsupported pixmap depth");
293 free(bp_reply);
294 return EGL_NO_IMAGE_KHR;
295 }
296
297 dri2_img = malloc(sizeof *dri2_img);
298 if (!dri2_img) {
299 _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
Louis-Francis Ratté-Boulianneaad14cf2018-02-12 22:26:10 -0500300 free(bp_reply);
Boyan Dingfcdc7982015-07-21 23:44:02 +0800301 return EGL_NO_IMAGE_KHR;
302 }
303
Emil Velikovd42b0952017-06-20 15:22:39 +0100304 _eglInitImage(&dri2_img->base, disp);
Boyan Dingfcdc7982015-07-21 23:44:02 +0800305
306 dri2_img->dri_image = loader_dri3_create_image(dri2_dpy->conn,
307 bp_reply,
308 format,
309 dri2_dpy->dri_screen,
310 dri2_dpy->image,
311 dri2_img);
312
313 free(bp_reply);
314
315 return &dri2_img->base;
316}
317
Daniel Stone478fc2d2018-03-19 15:03:22 +0000318#ifdef HAVE_DRI3_MODIFIERS
Boyan Dingfcdc7982015-07-21 23:44:02 +0800319static _EGLImage *
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400320dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
321 EGLClientBuffer buffer,
322 const EGLint *attr_list)
323{
324 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
325 struct dri2_egl_image *dri2_img;
326 xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
327 xcb_dri3_buffers_from_pixmap_reply_t *bp_reply;
328 xcb_drawable_t drawable;
329 unsigned int format;
330
331 drawable = (xcb_drawable_t) (uintptr_t) buffer;
332 bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
333 bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn,
334 bp_cookie, NULL);
335
336 if (!bp_reply) {
337 _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
338 return EGL_NO_IMAGE_KHR;
339 }
340
Mario Kleiner61a02722018-06-13 06:04:13 +0200341 format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400342 if (format == __DRI_IMAGE_FORMAT_NONE) {
343 _eglError(EGL_BAD_PARAMETER,
344 "dri3_create_image_khr: unsupported pixmap depth");
345 free(bp_reply);
346 return EGL_NO_IMAGE_KHR;
347 }
348
349 dri2_img = malloc(sizeof *dri2_img);
350 if (!dri2_img) {
351 _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
352 free(bp_reply);
353 return EGL_NO_IMAGE_KHR;
354 }
355
356 _eglInitImage(&dri2_img->base, disp);
357
358 dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn,
359 bp_reply,
360 format,
361 dri2_dpy->dri_screen,
362 dri2_dpy->image,
363 dri2_img);
364 free(bp_reply);
365
366 if (!dri2_img->dri_image) {
367 _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
368 free(dri2_img);
369 return EGL_NO_IMAGE_KHR;
370 }
371
372 return &dri2_img->base;
373}
Daniel Stone478fc2d2018-03-19 15:03:22 +0000374#endif
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400375
376static _EGLImage *
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200377dri3_create_image_khr(const _EGLDriver *drv, _EGLDisplay *disp,
Boyan Dingfcdc7982015-07-21 23:44:02 +0800378 _EGLContext *ctx, EGLenum target,
379 EGLClientBuffer buffer, const EGLint *attr_list)
380{
Daniel Stone478fc2d2018-03-19 15:03:22 +0000381#ifdef HAVE_DRI3_MODIFIERS
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400382 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
Daniel Stone478fc2d2018-03-19 15:03:22 +0000383#endif
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400384
Boyan Dingfcdc7982015-07-21 23:44:02 +0800385 switch (target) {
386 case EGL_NATIVE_PIXMAP_KHR:
Daniel Stone478fc2d2018-03-19 15:03:22 +0000387#ifdef HAVE_DRI3_MODIFIERS
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400388 if (dri2_dpy->multibuffers_available)
389 return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer,
390 attr_list);
Daniel Stone478fc2d2018-03-19 15:03:22 +0000391#endif
Boyan Dingfcdc7982015-07-21 23:44:02 +0800392 return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
393 default:
394 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
395 }
396}
397
Boyan Dingf35198b2015-07-21 23:44:00 +0800398/**
399 * Called by the driver when it needs to update the real front buffer with the
400 * contents of its fake front buffer.
401 */
402static void
403dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
404{
Kenneth Graunkefc213942019-06-28 10:11:01 -0700405 struct loader_dri3_drawable *draw = loaderPrivate;
406 (void) driDrawable;
407
Boyan Dingf35198b2015-07-21 23:44:00 +0800408 /* There does not seem to be any kind of consensus on whether we should
409 * support front-buffer rendering or not:
410 * http://lists.freedesktop.org/archives/mesa-dev/2013-June/040129.html
411 */
Kenneth Graunkefc213942019-06-28 10:11:01 -0700412 if (!draw->is_pixmap)
413 _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
Boyan Dingf35198b2015-07-21 23:44:00 +0800414}
415
416const __DRIimageLoaderExtension dri3_image_loader_extension = {
417 .base = { __DRI_IMAGE_LOADER, 1 },
418
419 .getBuffers = loader_dri3_get_buffers,
420 .flushFrontBuffer = dri3_flush_front_buffer,
421};
422
423static EGLBoolean
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200424dri3_swap_buffers(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
Boyan Dingf35198b2015-07-21 23:44:00 +0800425{
426 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
427
Boyan Dingf35198b2015-07-21 23:44:00 +0800428 return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
429 0, 0, 0, 0,
430 draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
431}
432
433static EGLBoolean
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200434dri3_copy_buffers(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
Boyan Dingf35198b2015-07-21 23:44:00 +0800435 void *native_pixmap_target)
436{
437 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
438 xcb_pixmap_t target;
439
440 STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
441 target = (uintptr_t) native_pixmap_target;
442
443 loader_dri3_copy_drawable(&dri3_surf->loader_drawable, target,
444 dri3_surf->loader_drawable.drawable);
445
446 return EGL_TRUE;
447}
448
449static int
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200450dri3_query_buffer_age(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
Boyan Dingf35198b2015-07-21 23:44:00 +0800451{
452 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
453
454 return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
455}
456
Brendan King884f65e2017-02-17 15:12:21 +0000457static EGLBoolean
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200458dri3_query_surface(const _EGLDriver *drv, _EGLDisplay *disp,
Brendan King884f65e2017-02-17 15:12:21 +0000459 _EGLSurface *surf, EGLint attribute,
460 EGLint *value)
461{
462 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
463
464 switch (attribute) {
465 case EGL_WIDTH:
466 case EGL_HEIGHT:
467 loader_dri3_update_drawable_geometry(&dri3_surf->loader_drawable);
468 break;
469 default:
470 break;
471 }
472
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000473 return _eglQuerySurface(drv, disp, surf, attribute, value);
Brendan King884f65e2017-02-17 15:12:21 +0000474}
475
Boyan Dingf35198b2015-07-21 23:44:00 +0800476static __DRIdrawable *
477dri3_get_dri_drawable(_EGLSurface *surf)
478{
479 struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
480
481 return dri3_surf->loader_drawable.dri_drawable;
482}
483
Thomas Hellstrom2db95482017-08-10 15:35:39 +0200484static void
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000485dri3_close_screen_notify(_EGLDisplay *disp)
Thomas Hellstrom2db95482017-08-10 15:35:39 +0200486{
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000487 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
Thomas Hellstrom2db95482017-08-10 15:35:39 +0200488
489 loader_dri3_close_screen(dri2_dpy->dri_screen);
490}
491
Boyan Dingf35198b2015-07-21 23:44:00 +0800492struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
Frank Binns55058452016-06-17 18:41:21 +0100493 .authenticate = dri3_authenticate,
Boyan Dingf35198b2015-07-21 23:44:00 +0800494 .create_window_surface = dri3_create_window_surface,
495 .create_pixmap_surface = dri3_create_pixmap_surface,
496 .create_pbuffer_surface = dri3_create_pbuffer_surface,
497 .destroy_surface = dri3_destroy_surface,
Boyan Dingfcdc7982015-07-21 23:44:02 +0800498 .create_image = dri3_create_image_khr,
Boyan Dingf35198b2015-07-21 23:44:00 +0800499 .swap_interval = dri3_set_swap_interval,
500 .swap_buffers = dri3_swap_buffers,
Boyan Dingf35198b2015-07-21 23:44:00 +0800501 .copy_buffers = dri3_copy_buffers,
502 .query_buffer_age = dri3_query_buffer_age,
Brendan King884f65e2017-02-17 15:12:21 +0000503 .query_surface = dri3_query_surface,
Boyan Dingf35198b2015-07-21 23:44:00 +0800504 .get_sync_values = dri3_get_sync_values,
505 .get_dri_drawable = dri3_get_dri_drawable,
Thomas Hellstrom2db95482017-08-10 15:35:39 +0200506 .close_screen_notify = dri3_close_screen_notify,
Boyan Dingf35198b2015-07-21 23:44:00 +0800507};
508
Daniel Stone696762e2018-03-22 15:23:49 +0000509/* Only request versions of these protocols which we actually support. */
510#define DRI3_SUPPORTED_MAJOR 1
511#define PRESENT_SUPPORTED_MAJOR 1
512
513#ifdef HAVE_DRI3_MODIFIERS
514#define DRI3_SUPPORTED_MINOR 2
515#define PRESENT_SUPPORTED_MINOR 2
516#else
517#define PRESENT_SUPPORTED_MINOR 0
518#define DRI3_SUPPORTED_MINOR 0
519#endif
520
Boyan Dingf35198b2015-07-21 23:44:00 +0800521EGLBoolean
522dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
523{
524 xcb_dri3_query_version_reply_t *dri3_query;
525 xcb_dri3_query_version_cookie_t dri3_query_cookie;
526 xcb_present_query_version_reply_t *present_query;
527 xcb_present_query_version_cookie_t present_query_cookie;
528 xcb_generic_error_t *error;
Boyan Dingf35198b2015-07-21 23:44:00 +0800529 const xcb_query_extension_reply_t *extension;
530
531 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
532 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
533
534 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri3_id);
535 if (!(extension && extension->present))
536 return EGL_FALSE;
537
538 extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_present_id);
539 if (!(extension && extension->present))
540 return EGL_FALSE;
541
542 dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
Daniel Stone696762e2018-03-22 15:23:49 +0000543 DRI3_SUPPORTED_MAJOR,
544 DRI3_SUPPORTED_MINOR);
Boyan Dingf35198b2015-07-21 23:44:00 +0800545
546 present_query_cookie = xcb_present_query_version(dri2_dpy->conn,
Daniel Stone696762e2018-03-22 15:23:49 +0000547 PRESENT_SUPPORTED_MAJOR,
548 PRESENT_SUPPORTED_MINOR);
Boyan Dingf35198b2015-07-21 23:44:00 +0800549
550 dri3_query =
551 xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
552 if (dri3_query == NULL || error != NULL) {
Martin Peres4518eea2015-10-30 17:16:35 +0200553 _eglLog(_EGL_WARNING, "DRI3: failed to query the version");
Boyan Dingf35198b2015-07-21 23:44:00 +0800554 free(dri3_query);
555 free(error);
556 return EGL_FALSE;
557 }
Louis-Francis Ratté-Boulianne069fdd52017-07-07 02:54:26 -0400558
559 dri2_dpy->dri3_major_version = dri3_query->major_version;
560 dri2_dpy->dri3_minor_version = dri3_query->minor_version;
Boyan Dingf35198b2015-07-21 23:44:00 +0800561 free(dri3_query);
562
563 present_query =
564 xcb_present_query_version_reply(dri2_dpy->conn,
565 present_query_cookie, &error);
566 if (present_query == NULL || error != NULL) {
Martin Peres4518eea2015-10-30 17:16:35 +0200567 _eglLog(_EGL_WARNING, "DRI3: failed to query Present version");
Boyan Dingf35198b2015-07-21 23:44:00 +0800568 free(present_query);
569 free(error);
570 return EGL_FALSE;
571 }
Louis-Francis Ratté-Boulianne3160cb82017-10-06 01:26:51 -0400572
573 dri2_dpy->present_major_version = present_query->major_version;
574 dri2_dpy->present_minor_version = present_query->minor_version;
Boyan Dingf35198b2015-07-21 23:44:00 +0800575 free(present_query);
576
Emil Velikov7c6babb2016-11-21 13:46:51 +0000577 dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
Boyan Dingf35198b2015-07-21 23:44:00 +0800578 if (dri2_dpy->fd < 0) {
579 int conn_error = xcb_connection_has_error(dri2_dpy->conn);
Martin Peres4518eea2015-10-30 17:16:35 +0200580 _eglLog(_EGL_WARNING, "DRI3: Screen seems not DRI3 capable");
Boyan Dingf35198b2015-07-21 23:44:00 +0800581
582 if (conn_error)
Martin Peres4518eea2015-10-30 17:16:35 +0200583 _eglLog(_EGL_WARNING, "DRI3: Failed to initialize");
Boyan Dingf35198b2015-07-21 23:44:00 +0800584
585 return EGL_FALSE;
586 }
587
588 dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
589
Emil Velikovaf7abc52016-09-12 17:48:18 +0100590 dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
Boyan Dingf35198b2015-07-21 23:44:00 +0800591 if (!dri2_dpy->driver_name) {
Martin Peres4518eea2015-10-30 17:16:35 +0200592 _eglLog(_EGL_WARNING, "DRI3: No driver found");
Boyan Dingf35198b2015-07-21 23:44:00 +0800593 close(dri2_dpy->fd);
594 return EGL_FALSE;
595 }
596
Frank Binnsd6f669b2016-06-17 18:41:22 +0100597#ifdef HAVE_WAYLAND_PLATFORM
598 /* Only try to get a render device name since dri3 doesn't provide a
599 * mechanism for authenticating client opened device node fds. If this
600 * fails then don't advertise the extension. */
Frank Binns4c28c912016-06-17 18:41:20 +0100601 dri2_dpy->device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
Frank Binnsd6f669b2016-06-17 18:41:22 +0100602#endif
Boyan Dingf35198b2015-07-21 23:44:00 +0800603
604 return EGL_TRUE;
605}