Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/egl/drivers/dri2/platform_x11_dri3.c
4570 views
1
/*
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
#include <xcb/xfixes.h>
32
33
#include <xf86drm.h>
34
#include "util/macros.h"
35
36
#include "egl_dri2.h"
37
#include "platform_x11_dri3.h"
38
39
#include "loader.h"
40
#include "loader_dri3_helper.h"
41
42
static struct dri3_egl_surface *
43
loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
44
size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
45
return (struct dri3_egl_surface *)(((void*) draw) - offset);
46
}
47
48
static void
49
egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
50
int width, int height)
51
{
52
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
53
54
dri3_surf->surf.base.Width = width;
55
dri3_surf->surf.base.Height = height;
56
}
57
58
static bool
59
egl_dri3_in_current_context(struct loader_dri3_drawable *draw)
60
{
61
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
62
_EGLContext *ctx = _eglGetCurrentContext();
63
64
return ctx->Resource.Display == dri3_surf->surf.base.Resource.Display;
65
}
66
67
static __DRIcontext *
68
egl_dri3_get_dri_context(struct loader_dri3_drawable *draw)
69
{
70
_EGLContext *ctx = _eglGetCurrentContext();
71
struct dri2_egl_context *dri2_ctx;
72
if (!ctx)
73
return NULL;
74
dri2_ctx = dri2_egl_context(ctx);
75
return dri2_ctx->dri_context;
76
}
77
78
static __DRIscreen *
79
egl_dri3_get_dri_screen(void)
80
{
81
_EGLContext *ctx = _eglGetCurrentContext();
82
struct dri2_egl_context *dri2_ctx;
83
if (!ctx)
84
return NULL;
85
dri2_ctx = dri2_egl_context(ctx);
86
return dri2_egl_display(dri2_ctx->base.Resource.Display)->dri_screen;
87
}
88
89
static void
90
egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
91
{
92
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
93
_EGLDisplay *disp = dri3_surf->surf.base.Resource.Display;
94
95
dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->surf.base);
96
}
97
98
static const struct loader_dri3_vtable egl_dri3_vtable = {
99
.set_drawable_size = egl_dri3_set_drawable_size,
100
.in_current_context = egl_dri3_in_current_context,
101
.get_dri_context = egl_dri3_get_dri_context,
102
.get_dri_screen = egl_dri3_get_dri_screen,
103
.flush_drawable = egl_dri3_flush_drawable,
104
.show_fps = NULL,
105
};
106
107
static EGLBoolean
108
dri3_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
109
{
110
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
111
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
112
xcb_drawable_t drawable = dri3_surf->loader_drawable.drawable;
113
114
loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
115
116
if (surf->Type == EGL_PBUFFER_BIT)
117
xcb_free_pixmap (dri2_dpy->conn, drawable);
118
119
dri2_fini_surface(surf);
120
free(surf);
121
122
return EGL_TRUE;
123
}
124
125
static EGLBoolean
126
dri3_set_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
127
{
128
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
129
130
dri3_surf->surf.base.SwapInterval = interval;
131
loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
132
133
return EGL_TRUE;
134
}
135
136
static _EGLSurface *
137
dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
138
void *native_surface, const EGLint *attrib_list)
139
{
140
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
141
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
142
struct dri3_egl_surface *dri3_surf;
143
const __DRIconfig *dri_config;
144
xcb_drawable_t drawable;
145
146
dri3_surf = calloc(1, sizeof *dri3_surf);
147
if (!dri3_surf) {
148
_eglError(EGL_BAD_ALLOC, "dri3_create_surface");
149
return NULL;
150
}
151
152
if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf,
153
attrib_list, false, native_surface))
154
goto cleanup_surf;
155
156
if (type == EGL_PBUFFER_BIT) {
157
drawable = xcb_generate_id(dri2_dpy->conn);
158
xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
159
drawable, dri2_dpy->screen->root,
160
dri3_surf->surf.base.Width, dri3_surf->surf.base.Height);
161
} else {
162
STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
163
drawable = (uintptr_t) native_surface;
164
}
165
166
dri_config = dri2_get_dri_config(dri2_conf, type,
167
dri3_surf->surf.base.GLColorspace);
168
169
if (!dri_config) {
170
_eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
171
goto cleanup_pixmap;
172
}
173
174
if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
175
dri2_dpy->dri_screen,
176
dri2_dpy->is_different_gpu,
177
dri2_dpy->multibuffers_available,
178
dri_config,
179
&dri2_dpy->loader_dri3_ext,
180
&egl_dri3_vtable,
181
&dri3_surf->loader_drawable)) {
182
_eglError(EGL_BAD_ALLOC, "dri3_surface_create");
183
goto cleanup_pixmap;
184
}
185
186
if (dri3_surf->surf.base.ProtectedContent &&
187
dri2_dpy->is_different_gpu) {
188
_eglError(EGL_BAD_ALLOC, "dri3_surface_create");
189
goto cleanup_pixmap;
190
}
191
192
dri3_surf->loader_drawable.is_protected_content =
193
dri3_surf->surf.base.ProtectedContent;
194
195
return &dri3_surf->surf.base;
196
197
cleanup_pixmap:
198
if (type == EGL_PBUFFER_BIT)
199
xcb_free_pixmap(dri2_dpy->conn, drawable);
200
cleanup_surf:
201
free(dri3_surf);
202
203
return NULL;
204
}
205
206
static int
207
dri3_authenticate(_EGLDisplay *disp, uint32_t id)
208
{
209
#ifdef HAVE_WAYLAND_PLATFORM
210
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
211
212
if (dri2_dpy->device_name) {
213
_eglLog(_EGL_WARNING,
214
"Wayland client render node authentication is unnecessary");
215
return 0;
216
}
217
218
_eglLog(_EGL_WARNING,
219
"Wayland client primary node authentication isn't supported");
220
#endif
221
222
return -1;
223
}
224
225
/**
226
* Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
227
*/
228
static _EGLSurface *
229
dri3_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
230
void *native_window, const EGLint *attrib_list)
231
{
232
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
233
_EGLSurface *surf;
234
235
surf = dri3_create_surface(disp, EGL_WINDOW_BIT, conf,
236
native_window, attrib_list);
237
if (surf != NULL)
238
dri3_set_swap_interval(disp, surf, dri2_dpy->default_swap_interval);
239
240
return surf;
241
}
242
243
static _EGLSurface *
244
dri3_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
245
void *native_pixmap, const EGLint *attrib_list)
246
{
247
return dri3_create_surface(disp, EGL_PIXMAP_BIT, conf,
248
native_pixmap, attrib_list);
249
}
250
251
static _EGLSurface *
252
dri3_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
253
const EGLint *attrib_list)
254
{
255
return dri3_create_surface(disp, EGL_PBUFFER_BIT, conf,
256
NULL, attrib_list);
257
}
258
259
static EGLBoolean
260
dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
261
EGLuint64KHR *ust, EGLuint64KHR *msc,
262
EGLuint64KHR *sbc)
263
{
264
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface);
265
266
return loader_dri3_wait_for_msc(&dri3_surf->loader_drawable, 0, 0, 0,
267
(int64_t *) ust, (int64_t *) msc,
268
(int64_t *) sbc) ? EGL_TRUE : EGL_FALSE;
269
}
270
271
static _EGLImage *
272
dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
273
EGLClientBuffer buffer, const EGLint *attr_list)
274
{
275
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
276
struct dri2_egl_image *dri2_img;
277
xcb_drawable_t drawable;
278
xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
279
xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
280
unsigned int format;
281
282
drawable = (xcb_drawable_t) (uintptr_t) buffer;
283
bp_cookie = xcb_dri3_buffer_from_pixmap(dri2_dpy->conn, drawable);
284
bp_reply = xcb_dri3_buffer_from_pixmap_reply(dri2_dpy->conn,
285
bp_cookie, NULL);
286
if (!bp_reply) {
287
_eglError(EGL_BAD_ALLOC, "xcb_dri3_buffer_from_pixmap");
288
return NULL;
289
}
290
291
format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
292
if (format == __DRI_IMAGE_FORMAT_NONE) {
293
_eglError(EGL_BAD_PARAMETER,
294
"dri3_create_image_khr: unsupported pixmap depth");
295
free(bp_reply);
296
return EGL_NO_IMAGE_KHR;
297
}
298
299
dri2_img = malloc(sizeof *dri2_img);
300
if (!dri2_img) {
301
_eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
302
free(bp_reply);
303
return EGL_NO_IMAGE_KHR;
304
}
305
306
_eglInitImage(&dri2_img->base, disp);
307
308
dri2_img->dri_image = loader_dri3_create_image(dri2_dpy->conn,
309
bp_reply,
310
format,
311
dri2_dpy->dri_screen,
312
dri2_dpy->image,
313
dri2_img);
314
315
free(bp_reply);
316
317
return &dri2_img->base;
318
}
319
320
#ifdef HAVE_DRI3_MODIFIERS
321
static _EGLImage *
322
dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
323
EGLClientBuffer buffer,
324
const EGLint *attr_list)
325
{
326
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
327
struct dri2_egl_image *dri2_img;
328
xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
329
xcb_dri3_buffers_from_pixmap_reply_t *bp_reply;
330
xcb_drawable_t drawable;
331
unsigned int format;
332
333
drawable = (xcb_drawable_t) (uintptr_t) buffer;
334
bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
335
bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn,
336
bp_cookie, NULL);
337
338
if (!bp_reply) {
339
_eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
340
return EGL_NO_IMAGE_KHR;
341
}
342
343
format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
344
if (format == __DRI_IMAGE_FORMAT_NONE) {
345
_eglError(EGL_BAD_PARAMETER,
346
"dri3_create_image_khr: unsupported pixmap depth");
347
free(bp_reply);
348
return EGL_NO_IMAGE_KHR;
349
}
350
351
dri2_img = malloc(sizeof *dri2_img);
352
if (!dri2_img) {
353
_eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
354
free(bp_reply);
355
return EGL_NO_IMAGE_KHR;
356
}
357
358
_eglInitImage(&dri2_img->base, disp);
359
360
dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn,
361
bp_reply,
362
format,
363
dri2_dpy->dri_screen,
364
dri2_dpy->image,
365
dri2_img);
366
free(bp_reply);
367
368
if (!dri2_img->dri_image) {
369
_eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
370
free(dri2_img);
371
return EGL_NO_IMAGE_KHR;
372
}
373
374
return &dri2_img->base;
375
}
376
#endif
377
378
static _EGLImage *
379
dri3_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
380
EGLClientBuffer buffer, const EGLint *attr_list)
381
{
382
#ifdef HAVE_DRI3_MODIFIERS
383
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
384
#endif
385
386
switch (target) {
387
case EGL_NATIVE_PIXMAP_KHR:
388
#ifdef HAVE_DRI3_MODIFIERS
389
if (dri2_dpy->multibuffers_available)
390
return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer,
391
attr_list);
392
#endif
393
return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
394
default:
395
return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
396
}
397
}
398
399
/**
400
* Called by the driver when it needs to update the real front buffer with the
401
* contents of its fake front buffer.
402
*/
403
static void
404
dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
405
{
406
struct loader_dri3_drawable *draw = loaderPrivate;
407
(void) driDrawable;
408
409
/* There does not seem to be any kind of consensus on whether we should
410
* support front-buffer rendering or not:
411
* http://lists.freedesktop.org/archives/mesa-dev/2013-June/040129.html
412
*/
413
if (!draw->is_pixmap)
414
_eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
415
}
416
417
const __DRIimageLoaderExtension dri3_image_loader_extension = {
418
.base = { __DRI_IMAGE_LOADER, 1 },
419
420
.getBuffers = loader_dri3_get_buffers,
421
.flushFrontBuffer = dri3_flush_front_buffer,
422
};
423
424
static EGLBoolean
425
dri3_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *draw,
426
const EGLint *rects, EGLint n_rects)
427
{
428
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
429
430
return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
431
0, 0, 0, 0,
432
rects, n_rects,
433
draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
434
}
435
436
static EGLBoolean
437
dri3_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
438
{
439
return dri3_swap_buffers_with_damage(disp, draw, NULL, 0);
440
}
441
442
static EGLBoolean
443
dri3_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target)
444
{
445
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
446
xcb_pixmap_t target;
447
448
STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
449
target = (uintptr_t) native_pixmap_target;
450
451
loader_dri3_copy_drawable(&dri3_surf->loader_drawable, target,
452
dri3_surf->loader_drawable.drawable);
453
454
return EGL_TRUE;
455
}
456
457
static int
458
dri3_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
459
{
460
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
461
462
return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
463
}
464
465
static EGLBoolean
466
dri3_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
467
EGLint attribute, EGLint *value)
468
{
469
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
470
471
switch (attribute) {
472
case EGL_WIDTH:
473
case EGL_HEIGHT:
474
loader_dri3_update_drawable_geometry(&dri3_surf->loader_drawable);
475
break;
476
default:
477
break;
478
}
479
480
return _eglQuerySurface(disp, surf, attribute, value);
481
}
482
483
static __DRIdrawable *
484
dri3_get_dri_drawable(_EGLSurface *surf)
485
{
486
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
487
488
return dri3_surf->loader_drawable.dri_drawable;
489
}
490
491
static void
492
dri3_close_screen_notify(_EGLDisplay *disp)
493
{
494
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
495
496
loader_dri3_close_screen(dri2_dpy->dri_screen);
497
}
498
499
struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
500
.authenticate = dri3_authenticate,
501
.create_window_surface = dri3_create_window_surface,
502
.create_pixmap_surface = dri3_create_pixmap_surface,
503
.create_pbuffer_surface = dri3_create_pbuffer_surface,
504
.destroy_surface = dri3_destroy_surface,
505
.create_image = dri3_create_image_khr,
506
.swap_interval = dri3_set_swap_interval,
507
.swap_buffers = dri3_swap_buffers,
508
.swap_buffers_with_damage = dri3_swap_buffers_with_damage,
509
.copy_buffers = dri3_copy_buffers,
510
.query_buffer_age = dri3_query_buffer_age,
511
.query_surface = dri3_query_surface,
512
.get_sync_values = dri3_get_sync_values,
513
.get_dri_drawable = dri3_get_dri_drawable,
514
.close_screen_notify = dri3_close_screen_notify,
515
};
516
517
/* Only request versions of these protocols which we actually support. */
518
#define DRI3_SUPPORTED_MAJOR 1
519
#define PRESENT_SUPPORTED_MAJOR 1
520
521
#ifdef HAVE_DRI3_MODIFIERS
522
#define DRI3_SUPPORTED_MINOR 2
523
#define PRESENT_SUPPORTED_MINOR 2
524
#else
525
#define PRESENT_SUPPORTED_MINOR 0
526
#define DRI3_SUPPORTED_MINOR 0
527
#endif
528
529
EGLBoolean
530
dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
531
{
532
xcb_dri3_query_version_reply_t *dri3_query;
533
xcb_dri3_query_version_cookie_t dri3_query_cookie;
534
xcb_present_query_version_reply_t *present_query;
535
xcb_present_query_version_cookie_t present_query_cookie;
536
xcb_xfixes_query_version_reply_t *xfixes_query;
537
xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
538
xcb_generic_error_t *error;
539
const xcb_query_extension_reply_t *extension;
540
541
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
542
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
543
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
544
545
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri3_id);
546
if (!(extension && extension->present))
547
return EGL_FALSE;
548
549
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_present_id);
550
if (!(extension && extension->present))
551
return EGL_FALSE;
552
553
extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
554
if (!(extension && extension->present))
555
return EGL_FALSE;
556
557
dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
558
DRI3_SUPPORTED_MAJOR,
559
DRI3_SUPPORTED_MINOR);
560
561
present_query_cookie = xcb_present_query_version(dri2_dpy->conn,
562
PRESENT_SUPPORTED_MAJOR,
563
PRESENT_SUPPORTED_MINOR);
564
565
xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
566
XCB_XFIXES_MAJOR_VERSION,
567
XCB_XFIXES_MINOR_VERSION);
568
569
dri3_query =
570
xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
571
if (dri3_query == NULL || error != NULL) {
572
_eglLog(_EGL_WARNING, "DRI3: failed to query the version");
573
free(dri3_query);
574
free(error);
575
return EGL_FALSE;
576
}
577
578
dri2_dpy->dri3_major_version = dri3_query->major_version;
579
dri2_dpy->dri3_minor_version = dri3_query->minor_version;
580
free(dri3_query);
581
582
present_query =
583
xcb_present_query_version_reply(dri2_dpy->conn,
584
present_query_cookie, &error);
585
if (present_query == NULL || error != NULL) {
586
_eglLog(_EGL_WARNING, "DRI3: failed to query Present version");
587
free(present_query);
588
free(error);
589
return EGL_FALSE;
590
}
591
592
dri2_dpy->present_major_version = present_query->major_version;
593
dri2_dpy->present_minor_version = present_query->minor_version;
594
free(present_query);
595
596
xfixes_query =
597
xcb_xfixes_query_version_reply(dri2_dpy->conn,
598
xfixes_query_cookie, &error);
599
if (xfixes_query == NULL || error != NULL ||
600
xfixes_query->major_version < 2) {
601
_eglLog(_EGL_WARNING, "DRI3: failed to query xfixes version");
602
free(error);
603
free(xfixes_query);
604
return EGL_FALSE;
605
}
606
free(xfixes_query);
607
608
dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
609
if (dri2_dpy->fd < 0) {
610
int conn_error = xcb_connection_has_error(dri2_dpy->conn);
611
_eglLog(_EGL_WARNING, "DRI3: Screen seems not DRI3 capable");
612
613
if (conn_error)
614
_eglLog(_EGL_WARNING, "DRI3: Failed to initialize");
615
616
return EGL_FALSE;
617
}
618
619
dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
620
621
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
622
if (!dri2_dpy->driver_name) {
623
_eglLog(_EGL_WARNING, "DRI3: No driver found");
624
close(dri2_dpy->fd);
625
return EGL_FALSE;
626
}
627
628
#ifdef HAVE_WAYLAND_PLATFORM
629
/* Only try to get a render device name since dri3 doesn't provide a
630
* mechanism for authenticating client opened device node fds. If this
631
* fails then don't advertise the extension. */
632
dri2_dpy->device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
633
#endif
634
635
return EGL_TRUE;
636
}
637
638