~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/egl/drivers/dri2/platform_x11_dri3.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

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