Add DRI3+Present loader
[mesa.git] / src / glx / dri3_glx.c
1 /*
2 * Copyright © 2013 Keith Packard
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 /*
24 * Portions of this code were adapted from dri2_glx.c which carries the
25 * following copyright:
26 *
27 * Copyright © 2008 Red Hat, Inc.
28 *
29 * Permission is hereby granted, free of charge, to any person obtaining a
30 * copy of this software and associated documentation files (the "Soft-
31 * ware"), to deal in the Software without restriction, including without
32 * limitation the rights to use, copy, modify, merge, publish, distribute,
33 * and/or sell copies of the Software, and to permit persons to whom the
34 * Software is furnished to do so, provided that the above copyright
35 * notice(s) and this permission notice appear in all copies of the Soft-
36 * ware and that both the above copyright notice(s) and this permission
37 * notice appear in supporting documentation.
38 *
39 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
40 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
41 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
42 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
43 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
44 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
45 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
46 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
47 * MANCE OF THIS SOFTWARE.
48 *
49 * Except as contained in this notice, the name of a copyright holder shall
50 * not be used in advertising or otherwise to promote the sale, use or
51 * other dealings in this Software without prior written authorization of
52 * the copyright holder.
53 *
54 * Authors:
55 * Kristian Høgsberg (krh@redhat.com)
56 */
57
58 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
59
60 #include <X11/Xlib.h>
61 #include <X11/extensions/Xfixes.h>
62 #include <X11/Xlib-xcb.h>
63 #include <X11/xshmfence.h>
64 #include <xcb/xcb.h>
65 #include <xcb/dri3.h>
66 #include <xcb/present.h>
67 #include <GL/gl.h>
68 #include "glapi.h"
69 #include "glxclient.h"
70 #include "xf86dri.h"
71 #include <dlfcn.h>
72 #include <fcntl.h>
73 #include <unistd.h>
74 #include <sys/types.h>
75 #include <sys/mman.h>
76 #include <sys/time.h>
77
78 #include "xf86drm.h"
79 #include "dri_common.h"
80 #include "dri3_priv.h"
81
82 static const struct glx_context_vtable dri3_context_vtable;
83
84 static inline void
85 dri3_fence_reset(xcb_connection_t *c, struct dri3_buffer *buffer)
86 {
87 xshmfence_reset(buffer->shm_fence);
88 }
89
90 static inline void
91 dri3_fence_set(struct dri3_buffer *buffer)
92 {
93 xshmfence_trigger(buffer->shm_fence);
94 }
95
96 static inline void
97 dri3_fence_trigger(xcb_connection_t *c, struct dri3_buffer *buffer)
98 {
99 xcb_sync_trigger_fence(c, buffer->sync_fence);
100 }
101
102 static inline void
103 dri3_fence_await(xcb_connection_t *c, struct dri3_buffer *buffer)
104 {
105 xcb_flush(c);
106 xshmfence_await(buffer->shm_fence);
107 }
108
109 static inline Bool
110 dri3_fence_triggered(struct dri3_buffer *buffer)
111 {
112 return xshmfence_query(buffer->shm_fence);
113 }
114
115 static void
116 dri3_destroy_context(struct glx_context *context)
117 {
118 struct dri3_context *pcp = (struct dri3_context *) context;
119 struct dri3_screen *psc = (struct dri3_screen *) context->psc;
120
121 driReleaseDrawables(&pcp->base);
122
123 free((char *) context->extensions);
124
125 (*psc->core->destroyContext) (pcp->driContext);
126
127 free(pcp);
128 }
129
130 static Bool
131 dri3_bind_context(struct glx_context *context, struct glx_context *old,
132 GLXDrawable draw, GLXDrawable read)
133 {
134 struct dri3_context *pcp = (struct dri3_context *) context;
135 struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
136 struct dri3_drawable *pdraw, *pread;
137
138 pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw);
139 pread = (struct dri3_drawable *) driFetchDrawable(context, read);
140
141 driReleaseDrawables(&pcp->base);
142
143 if (pdraw == NULL || pread == NULL)
144 return GLXBadDrawable;
145
146 if (!(*psc->core->bindContext) (pcp->driContext,
147 pdraw->driDrawable, pread->driDrawable))
148 return GLXBadContext;
149
150 return Success;
151 }
152
153 static void
154 dri3_unbind_context(struct glx_context *context, struct glx_context *new)
155 {
156 struct dri3_context *pcp = (struct dri3_context *) context;
157 struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
158
159 (*psc->core->unbindContext) (pcp->driContext);
160 }
161
162 static struct glx_context *
163 dri3_create_context(struct glx_screen *base,
164 struct glx_config *config_base,
165 struct glx_context *shareList, int renderType)
166 {
167 struct dri3_context *pcp, *pcp_shared;
168 struct dri3_screen *psc = (struct dri3_screen *) base;
169 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
170 __DRIcontext *shared = NULL;
171
172 if (shareList) {
173 /* If the shareList context is not a DRI3 context, we cannot possibly
174 * create a DRI3 context that shares it.
175 */
176 if (shareList->vtable->destroy != dri3_destroy_context) {
177 return NULL;
178 }
179
180 pcp_shared = (struct dri3_context *) shareList;
181 shared = pcp_shared->driContext;
182 }
183
184 pcp = calloc(1, sizeof *pcp);
185 if (pcp == NULL)
186 return NULL;
187
188 if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
189 free(pcp);
190 return NULL;
191 }
192
193 pcp->driContext =
194 (*psc->image_driver->createNewContext) (psc->driScreen,
195 config->driConfig, shared, pcp);
196
197 if (pcp->driContext == NULL) {
198 free(pcp);
199 return NULL;
200 }
201
202 pcp->base.vtable = &dri3_context_vtable;
203
204 return &pcp->base;
205 }
206
207 static struct glx_context *
208 dri3_create_context_attribs(struct glx_screen *base,
209 struct glx_config *config_base,
210 struct glx_context *shareList,
211 unsigned num_attribs,
212 const uint32_t *attribs,
213 unsigned *error)
214 {
215 struct dri3_context *pcp = NULL;
216 struct dri3_context *pcp_shared = NULL;
217 struct dri3_screen *psc = (struct dri3_screen *) base;
218 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
219 __DRIcontext *shared = NULL;
220
221 uint32_t minor_ver = 1;
222 uint32_t major_ver = 2;
223 uint32_t flags = 0;
224 unsigned api;
225 int reset = __DRI_CTX_RESET_NO_NOTIFICATION;
226 uint32_t ctx_attribs[2 * 5];
227 unsigned num_ctx_attribs = 0;
228 uint32_t render_type;
229
230 /* Remap the GLX tokens to DRI2 tokens.
231 */
232 if (!dri2_convert_glx_attribs(num_attribs, attribs,
233 &major_ver, &minor_ver,
234 &render_type, &flags, &api,
235 &reset, error))
236 goto error_exit;
237
238 /* Check the renderType value */
239 if (!validate_renderType_against_config(config_base, render_type))
240 goto error_exit;
241
242 if (shareList) {
243 pcp_shared = (struct dri3_context *) shareList;
244 shared = pcp_shared->driContext;
245 }
246
247 pcp = calloc(1, sizeof *pcp);
248 if (pcp == NULL) {
249 *error = __DRI_CTX_ERROR_NO_MEMORY;
250 goto error_exit;
251 }
252
253 if (!glx_context_init(&pcp->base, &psc->base, &config->base))
254 goto error_exit;
255
256 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
257 ctx_attribs[num_ctx_attribs++] = major_ver;
258 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
259 ctx_attribs[num_ctx_attribs++] = minor_ver;
260
261 /* Only send a value when the non-default value is requested. By doing
262 * this we don't have to check the driver's DRI3 version before sending the
263 * default value.
264 */
265 if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
266 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
267 ctx_attribs[num_ctx_attribs++] = reset;
268 }
269
270 if (flags != 0) {
271 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
272
273 /* The current __DRI_CTX_FLAG_* values are identical to the
274 * GLX_CONTEXT_*_BIT values.
275 */
276 ctx_attribs[num_ctx_attribs++] = flags;
277 }
278
279 pcp->driContext =
280 (*psc->image_driver->createContextAttribs) (psc->driScreen,
281 api,
282 config->driConfig,
283 shared,
284 num_ctx_attribs / 2,
285 ctx_attribs,
286 error,
287 pcp);
288
289 if (pcp->driContext == NULL)
290 goto error_exit;
291
292 pcp->base.vtable = &dri3_context_vtable;
293
294 return &pcp->base;
295
296 error_exit:
297 free(pcp);
298
299 return NULL;
300 }
301
302 static void
303 dri3_destroy_drawable(__GLXDRIdrawable *base)
304 {
305 struct dri3_screen *psc = (struct dri3_screen *) base->psc;
306 struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
307
308 (*psc->core->destroyDrawable) (pdraw->driDrawable);
309
310 free(pdraw);
311 }
312
313 static __GLXDRIdrawable *
314 dri3_create_drawable(struct glx_screen *base, XID xDrawable,
315 GLXDrawable drawable, struct glx_config *config_base)
316 {
317 struct dri3_drawable *pdraw;
318 struct dri3_screen *psc = (struct dri3_screen *) base;
319 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
320 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
321
322 pdraw = calloc(1, sizeof(*pdraw));
323 if (!pdraw)
324 return NULL;
325
326 pdraw->base.destroyDrawable = dri3_destroy_drawable;
327 pdraw->base.xDrawable = xDrawable;
328 pdraw->base.drawable = drawable;
329 pdraw->base.psc = &psc->base;
330 pdraw->swap_interval = 1; /* default may be overridden below */
331 pdraw->have_back = 0;
332 pdraw->have_fake_front = 0;
333
334 if (psc->config)
335 psc->config->configQueryi(psc->driScreen,
336 "vblank_mode", &vblank_mode);
337
338 switch (vblank_mode) {
339 case DRI_CONF_VBLANK_NEVER:
340 case DRI_CONF_VBLANK_DEF_INTERVAL_0:
341 pdraw->swap_interval = 0;
342 break;
343 case DRI_CONF_VBLANK_DEF_INTERVAL_1:
344 case DRI_CONF_VBLANK_ALWAYS_SYNC:
345 default:
346 pdraw->swap_interval = 1;
347 break;
348 }
349
350 (void) __glXInitialize(psc->base.dpy);
351
352 /* Create a new drawable */
353 pdraw->driDrawable =
354 (*psc->image_driver->createNewDrawable) (psc->driScreen,
355 config->driConfig, pdraw);
356
357 if (!pdraw->driDrawable) {
358 free(pdraw);
359 return NULL;
360 }
361
362 /*
363 * Make sure server has the same swap interval we do for the new
364 * drawable.
365 */
366 if (psc->vtable.setSwapInterval)
367 psc->vtable.setSwapInterval(&pdraw->base, pdraw->swap_interval);
368
369 return &pdraw->base;
370 }
371
372 /*
373 * Process one Present event
374 */
375 static void
376 dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_t *ge)
377 {
378 switch (ge->evtype) {
379 case XCB_PRESENT_CONFIGURE_NOTIFY: {
380 xcb_present_configure_notify_event_t *ce = (void *) ge;
381
382 priv->width = ce->width;
383 priv->height = ce->height;
384 break;
385 }
386 case XCB_PRESENT_COMPLETE_NOTIFY: {
387 xcb_present_complete_notify_event_t *ce = (void *) ge;
388
389 if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP)
390 priv->present_event_serial = ce->serial;
391 else
392 priv->present_msc_event_serial = ce->serial;
393 priv->ust = ce->ust;
394 priv->msc = ce->msc;
395 break;
396 }
397 case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
398 xcb_present_idle_notify_event_t *ie = (void *) ge;
399 int b;
400
401 for (b = 0; b < sizeof (priv->buffers) / sizeof (priv->buffers[0]); b++) {
402 struct dri3_buffer *buf = priv->buffers[b];
403
404 if (buf && buf->pixmap == ie->pixmap) {
405 buf->busy = 0;
406 break;
407 }
408 }
409 break;
410 }
411 }
412 free(ge);
413 }
414
415 static int
416 dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
417 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
418 {
419 xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
420 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
421 xcb_generic_event_t *ev;
422 xcb_present_generic_event_t *ge;
423
424 /* Ask for the an event for the target MSC */
425 ++priv->present_msc_request_serial;
426 xcb_present_notify_msc(c,
427 priv->base.xDrawable,
428 priv->present_msc_request_serial,
429 target_msc,
430 divisor,
431 remainder);
432
433 xcb_flush(c);
434
435 /* Wait for the event */
436 if (priv->special_event) {
437 while (priv->present_msc_request_serial != priv->present_msc_event_serial) {
438 ev = xcb_wait_for_special_event(c, priv->special_event);
439 if (!ev)
440 break;
441 ge = (void *) ev;
442 dri3_handle_present_event(priv, ge);
443 }
444 }
445
446 *ust = priv->ust;
447 *msc = priv->msc;
448 *sbc = priv->sbc;
449
450 return 1;
451 }
452
453 static int
454 dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
455 int64_t *ust, int64_t *msc, int64_t *sbc)
456 {
457 return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc,sbc);
458 }
459
460 /** dri3_wait_for_sbc
461 *
462 * Wait for the swap buffer count to increase. The only way this
463 * can happen is if some other thread is doing swap buffers as
464 * we no longer share swap buffer counts with other processes.
465 *
466 * I'm not sure this is actually useful as such, and so this
467 * implementation is a kludge that just polls once a second
468 */
469 static int
470 dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
471 int64_t *msc, int64_t *sbc)
472 {
473 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
474
475 while (priv->sbc < target_sbc) {
476 sleep(1);
477 }
478 return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc, sbc);
479 }
480
481 /**
482 * Asks the driver to flush any queued work necessary for serializing with the
483 * X command stream, and optionally the slightly more strict requirement of
484 * glFlush() equivalence (which would require flushing even if nothing had
485 * been drawn to a window system framebuffer, for example).
486 */
487 static void
488 dri3_flush(struct dri3_screen *psc,
489 struct dri3_drawable *draw,
490 unsigned flags,
491 enum __DRI2throttleReason throttle_reason)
492 {
493 struct glx_context *gc = __glXGetCurrentContext();
494
495 if (gc) {
496 struct dri3_context *dri3Ctx = (struct dri3_context *)gc;
497
498 (*psc->f->flush_with_flags)(dri3Ctx->driContext, draw->driDrawable, flags, throttle_reason);
499 }
500 }
501
502 static xcb_gcontext_t
503 dri3_drawable_gc(struct dri3_drawable *priv)
504 {
505 if (!priv->gc) {
506 uint32_t v;
507 xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
508
509 v = 0;
510 xcb_create_gc(c,
511 (priv->gc = xcb_generate_id(c)),
512 priv->base.xDrawable,
513 XCB_GC_GRAPHICS_EXPOSURES,
514 &v);
515 }
516 return priv->gc;
517 }
518
519 static struct dri3_buffer *
520 dri3_back_buffer(struct dri3_drawable *priv)
521 {
522 return priv->buffers[DRI3_BACK_ID(priv->cur_back)];
523 }
524
525 static struct dri3_buffer *
526 dri3_fake_front_buffer(struct dri3_drawable *priv)
527 {
528 return priv->buffers[DRI3_FRONT_ID];
529 }
530
531 static void
532 dri3_copy_area (xcb_connection_t *c /**< */,
533 xcb_drawable_t src_drawable /**< */,
534 xcb_drawable_t dst_drawable /**< */,
535 xcb_gcontext_t gc /**< */,
536 int16_t src_x /**< */,
537 int16_t src_y /**< */,
538 int16_t dst_x /**< */,
539 int16_t dst_y /**< */,
540 uint16_t width /**< */,
541 uint16_t height /**< */)
542 {
543 xcb_void_cookie_t cookie;
544
545 cookie = xcb_copy_area_checked(c,
546 src_drawable,
547 dst_drawable,
548 gc,
549 src_x,
550 src_y,
551 dst_x,
552 dst_y,
553 width,
554 height);
555 xcb_discard_reply(c, cookie.sequence);
556 }
557
558 static void
559 dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
560 int width, int height,
561 Bool flush)
562 {
563 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
564 struct dri3_screen *psc = (struct dri3_screen *) pdraw->psc;
565 xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
566 struct dri3_buffer *back = dri3_back_buffer(priv);
567
568 unsigned flags;
569
570 /* Check we have the right attachments */
571 if (!priv->have_back || priv->is_pixmap)
572 return;
573
574 flags = __DRI2_FLUSH_DRAWABLE;
575 if (flush)
576 flags |= __DRI2_FLUSH_CONTEXT;
577 dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
578
579 y = priv->height - y - height;
580
581 dri3_fence_reset(c, back);
582 dri3_copy_area(c,
583 dri3_back_buffer(priv)->pixmap,
584 priv->base.xDrawable,
585 dri3_drawable_gc(priv),
586 x, y, x, y, width, height);
587 dri3_fence_trigger(c, back);
588 /* Refresh the fake front (if present) after we just damaged the real
589 * front.
590 */
591 if (priv->have_fake_front) {
592 dri3_fence_reset(c, dri3_fake_front_buffer(priv));
593 dri3_copy_area(c,
594 dri3_back_buffer(priv)->pixmap,
595 dri3_fake_front_buffer(priv)->pixmap,
596 dri3_drawable_gc(priv),
597 x, y, x, y, width, height);
598 dri3_fence_trigger(c, dri3_fake_front_buffer(priv));
599 dri3_fence_await(c, dri3_fake_front_buffer(priv));
600 }
601 dri3_fence_await(c, back);
602 }
603
604 static void
605 dri3_copy_drawable(struct dri3_drawable *priv, Drawable dest, Drawable src)
606 {
607 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
608 xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
609
610 dri3_flush(psc, priv, __DRI2_FLUSH_DRAWABLE, 0);
611
612 dri3_fence_reset(c, dri3_fake_front_buffer(priv));
613 dri3_copy_area(c,
614 src, dest,
615 dri3_drawable_gc(priv),
616 0, 0, 0, 0, priv->width, priv->height);
617 dri3_fence_trigger(c, dri3_fake_front_buffer(priv));
618 dri3_fence_await(c, dri3_fake_front_buffer(priv));
619 }
620
621 static void
622 dri3_wait_x(struct glx_context *gc)
623 {
624 struct dri3_drawable *priv = (struct dri3_drawable *)
625 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
626
627 if (priv == NULL || !priv->have_fake_front)
628 return;
629
630 dri3_copy_drawable(priv, dri3_fake_front_buffer(priv)->pixmap, priv->base.xDrawable);
631 }
632
633 static void
634 dri3_wait_gl(struct glx_context *gc)
635 {
636 struct dri3_drawable *priv = (struct dri3_drawable *)
637 GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
638
639 if (priv == NULL || !priv->have_fake_front)
640 return;
641
642 dri3_copy_drawable(priv, priv->base.xDrawable, dri3_fake_front_buffer(priv)->pixmap);
643 }
644
645 /**
646 * Called by the driver when it needs to update the real front buffer with the
647 * contents of its fake front buffer.
648 */
649 static void
650 dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
651 {
652 struct glx_context *gc;
653 struct dri3_drawable *pdraw = loaderPrivate;
654 struct dri3_screen *psc;
655
656 if (!pdraw)
657 return;
658
659 if (!pdraw->base.psc)
660 return;
661
662 psc = (struct dri3_screen *) pdraw->base.psc;
663
664 (void) __glXInitialize(psc->base.dpy);
665
666 gc = __glXGetCurrentContext();
667
668 dri3_flush(psc, pdraw, __DRI2_FLUSH_DRAWABLE, __DRI2_THROTTLE_FLUSHFRONT);
669
670 dri3_wait_gl(gc);
671 }
672
673 static uint32_t
674 dri3_cpp_for_format(uint32_t format) {
675 switch (format) {
676 case __DRI_IMAGE_FORMAT_R8:
677 return 1;
678 case __DRI_IMAGE_FORMAT_RGB565:
679 case __DRI_IMAGE_FORMAT_GR88:
680 return 2;
681 case __DRI_IMAGE_FORMAT_XRGB8888:
682 case __DRI_IMAGE_FORMAT_ARGB8888:
683 case __DRI_IMAGE_FORMAT_ABGR8888:
684 case __DRI_IMAGE_FORMAT_XBGR8888:
685 case __DRI_IMAGE_FORMAT_XRGB2101010:
686 case __DRI_IMAGE_FORMAT_ARGB2101010:
687 case __DRI_IMAGE_FORMAT_SARGB8:
688 return 4;
689 case __DRI_IMAGE_FORMAT_NONE:
690 default:
691 return 0;
692 }
693 }
694
695
696 /** dri3_alloc_render_buffer
697 *
698 * Use the driver createImage function to construct a __DRIimage, then
699 * get a file descriptor for that and create an X pixmap from that
700 *
701 * Allocate an xshmfence for synchronization
702 */
703 static struct dri3_buffer *
704 dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw,
705 unsigned int format, int width, int height, int depth)
706 {
707 struct dri3_screen *psc = (struct dri3_screen *) glx_screen;
708 Display *dpy = glx_screen->dpy;
709 struct dri3_buffer *buffer;
710 xcb_connection_t *c = XGetXCBConnection(dpy);
711 xcb_pixmap_t pixmap;
712 xcb_sync_fence_t sync_fence;
713 int32_t *shm_fence;
714 int buffer_fd, fence_fd;
715 int stride;
716
717 /* Create an xshmfence object and
718 * prepare to send that to the X server
719 */
720
721 fence_fd = xshmfence_alloc_shm();
722 if (fence_fd < 0)
723 return NULL;
724 shm_fence = xshmfence_map_shm(fence_fd);
725 if (shm_fence == NULL)
726 goto no_shm_fence;
727
728 /* Allocate the image from the driver
729 */
730 buffer = calloc(1, sizeof (struct dri3_buffer));
731 if (!buffer)
732 goto no_buffer;
733
734 buffer->cpp = dri3_cpp_for_format(format);
735 if (!buffer->cpp)
736 goto no_image;
737
738 buffer->image = (*psc->image->createImage) (psc->driScreen,
739 width, height,
740 format,
741 __DRI_IMAGE_USE_SHARE|__DRI_IMAGE_USE_SCANOUT,
742 buffer);
743
744
745 if (!buffer->image)
746 goto no_image;
747
748 /* X wants the stride, so ask the image for it
749 */
750 if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride))
751 goto no_buffer_attrib;
752
753 buffer->pitch = stride;
754
755 if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_FD, &buffer_fd))
756 goto no_buffer_attrib;
757
758 xcb_dri3_pixmap_from_buffer(c,
759 (pixmap = xcb_generate_id(c)),
760 draw,
761 buffer->size,
762 width, height, buffer->pitch,
763 depth, buffer->cpp * 8,
764 buffer_fd);
765
766 xcb_dri3_fence_from_fd(c,
767 pixmap,
768 (sync_fence = xcb_generate_id(c)),
769 false,
770 fence_fd);
771
772 buffer->pixmap = pixmap;
773 buffer->sync_fence = sync_fence;
774 buffer->shm_fence = shm_fence;
775 buffer->width = width;
776 buffer->height = height;
777
778 /* Mark the buffer as idle
779 */
780 dri3_fence_set(buffer);
781
782 return buffer;
783
784 no_buffer_attrib:
785 (*psc->image->destroyImage)(buffer->image);
786 no_image:
787 free(buffer);
788 no_buffer:
789 xshmfence_unmap_shm(shm_fence);
790 no_shm_fence:
791 close(fence_fd);
792 return NULL;
793 }
794
795 /** dri3_free_render_buffer
796 *
797 * Free everything associated with one render buffer including pixmap, fence
798 * stuff and the driver image
799 */
800 static void
801 dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer)
802 {
803 struct dri3_screen *psc = (struct dri3_screen *) pdraw->base.psc;
804 xcb_connection_t *c = XGetXCBConnection(pdraw->base.psc->dpy);
805
806 xcb_free_pixmap(c, buffer->pixmap);
807 xcb_sync_destroy_fence(c, buffer->sync_fence);
808 xshmfence_unmap_shm(buffer->shm_fence);
809 (*psc->image->destroyImage)(buffer->image);
810 free(buffer);
811 }
812
813
814 /** dri3_flush_present_events
815 *
816 * Process any present events that have been received from the X server
817 */
818 static void
819 dri3_flush_present_events(struct dri3_drawable *priv)
820 {
821 xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
822
823 /* Check to see if any configuration changes have occurred
824 * since we were last invoked
825 */
826 if (priv->special_event) {
827 xcb_generic_event_t *ev;
828
829 while ((ev = xcb_poll_for_special_event(c, priv->special_event)) != NULL) {
830 xcb_present_generic_event_t *ge = (void *) ev;
831 dri3_handle_present_event(priv, ge);
832 }
833 }
834 }
835
836 /** dri3_update_drawable
837 *
838 * Called the first time we use the drawable and then
839 * after we receive present configure notify events to
840 * track the geometry of the drawable
841 */
842 static int
843 dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate)
844 {
845 struct dri3_drawable *priv = loaderPrivate;
846 xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
847
848 /* First time through, go get the current drawable geometry
849 */
850 if (priv->width == 0 || priv->height == 0 || priv->depth == 0) {
851 xcb_get_geometry_cookie_t geom_cookie;
852 xcb_get_geometry_reply_t *geom_reply;
853 xcb_void_cookie_t cookie;
854 xcb_generic_error_t *error;
855
856 /* Try to select for input on the window.
857 *
858 * If the drawable is a window, this will get our events
859 * delivered.
860 *
861 * Otherwise, we'll get a BadWindow error back from this request which
862 * will let us know that the drawable is a pixmap instead.
863 */
864
865
866 cookie = xcb_present_select_input_checked(c,
867 (priv->eid = xcb_generate_id(c)),
868 priv->base.xDrawable,
869 XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY|
870 XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
871 XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
872
873 /* Create an XCB event queue to hold present events outside of the usual
874 * application event queue
875 */
876 priv->special_event = xcb_register_for_special_xge(c,
877 &xcb_present_id,
878 priv->eid,
879 priv->stamp);
880
881 geom_cookie = xcb_get_geometry(c, priv->base.xDrawable);
882
883 geom_reply = xcb_get_geometry_reply(c, geom_cookie, NULL);
884
885 if (!geom_reply)
886 return false;
887
888 priv->width = geom_reply->width;
889 priv->height = geom_reply->height;
890 priv->depth = geom_reply->depth;
891 priv->is_pixmap = false;
892
893 free(geom_reply);
894
895 /* Check to see if our select input call failed. If it failed with a
896 * BadWindow error, then assume the drawable is a pixmap. Destroy the
897 * special event queue created above and mark the drawable as a pixmap
898 */
899
900 error = xcb_request_check(c, cookie);
901
902 if (error) {
903 if (error->error_code != BadWindow) {
904 free(error);
905 return false;
906 }
907 priv->is_pixmap = true;
908 xcb_unregister_for_special_event(c, priv->special_event);
909 priv->special_event = NULL;
910 }
911 }
912 dri3_flush_present_events(priv);
913 return true;
914 }
915
916 /* the DRIimage createImage function takes __DRI_IMAGE_FORMAT codes, while
917 * the createImageFromFds call takes __DRI_IMAGE_FOURCC codes. To avoid
918 * complete confusion, just deal in __DRI_IMAGE_FORMAT codes for now and
919 * translate to __DRI_IMAGE_FOURCC codes in the call to createImageFromFds
920 */
921 static int
922 image_format_to_fourcc(int format)
923 {
924
925 /* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */
926 switch (format) {
927 case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
928 case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
929 case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
930 case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
931 case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
932 }
933 return 0;
934 }
935
936 /** dri3_get_pixmap_buffer
937 *
938 * Get the DRM object for a pixmap from the X server and
939 * wrap that with a __DRIimage structure using createImageFromFds
940 */
941 static struct dri3_buffer *
942 dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
943 unsigned int format,
944 enum dri3_buffer_type buffer_type,
945 void *loaderPrivate)
946 {
947 struct dri3_drawable *pdraw = loaderPrivate;
948 int buf_id = buffer_type == dri3_pixmap_buf_id(buffer_type);
949 struct dri3_buffer *buffer = pdraw->buffers[buf_id];
950 Pixmap pixmap;
951 xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
952 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
953 int *fds;
954 Display *dpy;
955 struct dri3_screen *psc;
956 xcb_connection_t *c;
957 xcb_sync_fence_t sync_fence;
958 int32_t *shm_fence;
959 int fence_fd;
960 __DRIimage *image_planar;
961 int stride, offset;
962
963 if (buffer)
964 return buffer;
965
966 pixmap = pdraw->base.xDrawable;
967 psc = (struct dri3_screen *) pdraw->base.psc;
968 dpy = psc->base.dpy;
969 c = XGetXCBConnection(dpy);
970
971 buffer = calloc(1, sizeof (struct dri3_buffer));
972 if (!buffer)
973 goto no_buffer;
974
975 fence_fd = xshmfence_alloc_shm();
976 if (fence_fd < 0)
977 goto no_fence;
978 shm_fence = xshmfence_map_shm(fence_fd);
979 if (shm_fence == NULL) {
980 close (fence_fd);
981 goto no_fence;
982 }
983
984 xcb_dri3_fence_from_fd(c,
985 pixmap,
986 (sync_fence = xcb_generate_id(c)),
987 false,
988 fence_fd);
989
990 /* Get an FD for the pixmap object
991 */
992 bp_cookie = xcb_dri3_buffer_from_pixmap(c, pixmap);
993 bp_reply = xcb_dri3_buffer_from_pixmap_reply(c, bp_cookie, NULL);
994 if (!bp_reply)
995 goto no_image;
996 fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, bp_reply);
997
998 stride = bp_reply->stride;
999 offset = 0;
1000
1001 /* createImageFromFds creates a wrapper __DRIimage structure which
1002 * can deal with multiple planes for things like Yuv images. So, once
1003 * we've gotten the planar wrapper, pull the single plane out of it and
1004 * discard the wrapper.
1005 */
1006 image_planar = (*psc->image->createImageFromFds) (psc->driScreen,
1007 bp_reply->width,
1008 bp_reply->height,
1009 image_format_to_fourcc(format),
1010 fds, 1,
1011 &stride, &offset, buffer);
1012 close(fds[0]);
1013 if (!image_planar)
1014 goto no_image;
1015
1016 buffer->image = (*psc->image->fromPlanar)(image_planar, 0, buffer);
1017
1018 (*psc->image->destroyImage)(image_planar);
1019
1020 if (!buffer->image)
1021 goto no_image;
1022
1023 buffer->pixmap = pixmap;
1024 buffer->width = bp_reply->width;
1025 buffer->height = bp_reply->height;
1026 buffer->buffer_type = buffer_type;
1027 buffer->shm_fence = shm_fence;
1028 buffer->sync_fence = sync_fence;
1029
1030 pdraw->buffers[buf_id] = buffer;
1031 return buffer;
1032
1033 no_image:
1034 xcb_sync_destroy_fence(c, sync_fence);
1035 xshmfence_unmap_shm(shm_fence);
1036 no_fence:
1037 free(buffer);
1038 no_buffer:
1039 return NULL;
1040 }
1041
1042 /** dri3_find_back
1043 *
1044 * Find an idle back buffer. If there isn't one, then
1045 * wait for a present idle notify event from the X server
1046 */
1047 static int
1048 dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv)
1049 {
1050 int b;
1051 xcb_generic_event_t *ev;
1052 xcb_present_generic_event_t *ge;
1053
1054 for (;;) {
1055
1056 for (b = 0; b < DRI3_MAX_BACK; b++) {
1057 int id = DRI3_BACK_ID(b);
1058 struct dri3_buffer *buffer = priv->buffers[id];
1059
1060 if (!buffer)
1061 return b;
1062 if (!buffer->busy)
1063 return b;
1064 }
1065 ev = xcb_wait_for_special_event(c, priv->special_event);
1066 if (!ev)
1067 return -1;
1068 ge = (void *) ev;
1069 dri3_handle_present_event(priv, ge);
1070 }
1071 }
1072
1073 /** dri3_get_buffer
1074 *
1075 * Find a front or back buffer, allocating new ones as necessary
1076 */
1077 static struct dri3_buffer *
1078 dri3_get_buffer(__DRIdrawable *driDrawable,
1079 unsigned int format,
1080 enum dri3_buffer_type buffer_type,
1081 void *loaderPrivate)
1082 {
1083 struct dri3_drawable *priv = loaderPrivate;
1084 xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
1085 struct dri3_buffer *buffer;
1086 int buf_id;
1087
1088 if (buffer_type == dri3_buffer_back) {
1089 int back = dri3_find_back(c, priv);
1090
1091 if (back < 0)
1092 return NULL;
1093
1094 priv->cur_back = back;
1095 buf_id = DRI3_BACK_ID(priv->cur_back);
1096 } else {
1097 buf_id = DRI3_FRONT_ID;
1098 }
1099
1100 buffer = priv->buffers[buf_id];
1101
1102 /* Allocate a new buffer if there isn't an old one, or if that
1103 * old one is the wrong size
1104 */
1105 if (!buffer || buffer->width != priv->width || buffer->height != priv->height) {
1106 struct dri3_buffer *new_buffer;
1107
1108 /* Allocate the new buffers
1109 */
1110 new_buffer = dri3_alloc_render_buffer(priv->base.psc,
1111 priv->base.xDrawable,
1112 format, priv->width, priv->height, priv->depth);
1113 if (!new_buffer)
1114 return NULL;
1115
1116 /* When resizing, copy the contents of the old buffer, waiting for that
1117 * copy to complete using our fences before proceeding
1118 */
1119 switch (buffer_type) {
1120 case dri3_buffer_back:
1121 if (buffer) {
1122 dri3_fence_reset(c, new_buffer);
1123 dri3_fence_await(c, buffer);
1124 dri3_copy_area(c,
1125 buffer->pixmap,
1126 new_buffer->pixmap,
1127 dri3_drawable_gc(priv),
1128 0, 0, 0, 0, priv->width, priv->height);
1129 dri3_fence_trigger(c, new_buffer);
1130 dri3_free_render_buffer(priv, buffer);
1131 }
1132 break;
1133 case dri3_buffer_front:
1134 dri3_fence_reset(c, new_buffer);
1135 dri3_copy_area(c,
1136 priv->base.xDrawable,
1137 new_buffer->pixmap,
1138 dri3_drawable_gc(priv),
1139 0, 0, 0, 0, priv->width, priv->height);
1140 dri3_fence_trigger(c, new_buffer);
1141 break;
1142 }
1143 buffer = new_buffer;
1144 buffer->buffer_type = buffer_type;
1145 priv->buffers[buf_id] = buffer;
1146 }
1147 dri3_fence_await(c, buffer);
1148
1149 /* Return the requested buffer */
1150 return buffer;
1151 }
1152
1153 /** dri3_free_buffers
1154 *
1155 * Free the front bufffer or all of the back buffers. Used
1156 * when the application changes which buffers it needs
1157 */
1158 static void
1159 dri3_free_buffers(__DRIdrawable *driDrawable,
1160 enum dri3_buffer_type buffer_type,
1161 void *loaderPrivate)
1162 {
1163 struct dri3_drawable *priv = loaderPrivate;
1164 struct dri3_buffer *buffer;
1165 int first_id;
1166 int n_id;
1167 int buf_id;
1168
1169 switch (buffer_type) {
1170 case dri3_buffer_back:
1171 first_id = DRI3_BACK_ID(0);
1172 n_id = DRI3_MAX_BACK;
1173 break;
1174 case dri3_buffer_front:
1175 first_id = DRI3_FRONT_ID;
1176 n_id = 1;
1177 }
1178
1179 for (buf_id = first_id; buf_id < first_id + n_id; buf_id++) {
1180 buffer = priv->buffers[buf_id];
1181 if (buffer) {
1182 dri3_free_render_buffer(priv, buffer);
1183 priv->buffers[buf_id] = NULL;
1184 }
1185 }
1186 }
1187
1188 /** dri3_get_buffers
1189 *
1190 * The published buffer allocation API.
1191 * Returns all of the necessary buffers, allocating
1192 * as needed.
1193 */
1194 static int
1195 dri3_get_buffers(__DRIdrawable *driDrawable,
1196 unsigned int format,
1197 uint32_t *stamp,
1198 void *loaderPrivate,
1199 uint32_t buffer_mask,
1200 struct __DRIimageList *buffers)
1201 {
1202 struct dri3_drawable *priv = loaderPrivate;
1203 struct dri3_buffer *front, *back;
1204
1205 buffers->image_mask = 0;
1206 buffers->front = NULL;
1207 buffers->back = NULL;
1208
1209 front = NULL;
1210 back = NULL;
1211
1212 if (!dri3_update_drawable(driDrawable, loaderPrivate))
1213 return false;
1214
1215 /* pixmaps always have front buffers */
1216 if (priv->is_pixmap)
1217 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
1218
1219 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
1220 if (priv->is_pixmap)
1221 front = dri3_get_pixmap_buffer(driDrawable,
1222 format,
1223 dri3_buffer_front,
1224 loaderPrivate);
1225 else
1226 front = dri3_get_buffer(driDrawable,
1227 format,
1228 dri3_buffer_front,
1229 loaderPrivate);
1230
1231 if (!front)
1232 return false;
1233 } else {
1234 dri3_free_buffers(driDrawable, dri3_buffer_front, loaderPrivate);
1235 priv->have_fake_front = 0;
1236 }
1237
1238 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
1239 back = dri3_get_buffer(driDrawable,
1240 format,
1241 dri3_buffer_back,
1242 loaderPrivate);
1243 if (!back)
1244 return false;
1245 priv->have_back = 1;
1246 } else {
1247 dri3_free_buffers(driDrawable, dri3_buffer_back, loaderPrivate);
1248 priv->have_back = 0;
1249 }
1250
1251 if (front) {
1252 buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
1253 buffers->front = front->image;
1254 priv->have_fake_front = !priv->is_pixmap;
1255 }
1256
1257 if (back) {
1258 buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
1259 buffers->back = back->image;
1260 }
1261
1262 priv->stamp = stamp;
1263
1264 return true;
1265 }
1266
1267 /* The image loader extension record for DRI3
1268 */
1269 static const __DRIimageLoaderExtension imageLoaderExtension = {
1270 {__DRI_IMAGE_LOADER, __DRI_IMAGE_LOADER_VERSION},
1271 .getBuffers = dri3_get_buffers,
1272 .flushFrontBuffer = dri3_flush_front_buffer,
1273 };
1274
1275 /** dri3_swap_buffers
1276 *
1277 * Make the current back buffer visible using the present extension
1278 */
1279 static int64_t
1280 dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
1281 int64_t remainder, Bool flush)
1282 {
1283 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
1284 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
1285 Display *dpy = priv->base.psc->dpy;
1286 xcb_connection_t *c = XGetXCBConnection(dpy);
1287 int buf_id = DRI3_BACK_ID(priv->cur_back);
1288 int64_t ret = 0;
1289
1290 unsigned flags = __DRI2_FLUSH_DRAWABLE;
1291 if (flush)
1292 flags |= __DRI2_FLUSH_CONTEXT;
1293 dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
1294
1295 dri3_flush_present_events(priv);
1296
1297 if (priv->buffers[buf_id] && !priv->is_pixmap) {
1298 dri3_fence_reset(c, priv->buffers[buf_id]);
1299
1300 /* Compute when we want the frame shown by taking the last known successful
1301 * MSC and adding in a swap interval for each outstanding swap request
1302 */
1303 ++priv->present_request_serial;
1304 if (target_msc == 0)
1305 target_msc = priv->msc + priv->swap_interval * (priv->present_request_serial - priv->present_event_serial);
1306
1307 priv->buffers[buf_id]->busy = 1;
1308 xcb_present_pixmap(c,
1309 priv->base.xDrawable,
1310 priv->buffers[buf_id]->pixmap,
1311 priv->present_request_serial,
1312 0, /* valid */
1313 0, /* update */
1314 0, /* x_off */
1315 0, /* y_off */
1316 None, /* target_crtc */
1317 None,
1318 priv->buffers[buf_id]->sync_fence,
1319 XCB_PRESENT_OPTION_NONE,
1320 target_msc,
1321 divisor,
1322 remainder, 0, NULL);
1323 ret = ++priv->sbc;
1324
1325 /* If there's a fake front, then copy the source back buffer
1326 * to the fake front to keep it up to date. This needs
1327 * to reset the fence and make future users block until
1328 * the X server is done copying the bits
1329 */
1330 if (priv->have_fake_front) {
1331 dri3_fence_reset(c, priv->buffers[DRI3_FRONT_ID]);
1332 dri3_copy_area(c,
1333 priv->buffers[buf_id]->pixmap,
1334 priv->buffers[DRI3_FRONT_ID]->pixmap,
1335 dri3_drawable_gc(priv),
1336 0, 0, 0, 0, priv->width, priv->height);
1337 dri3_fence_trigger(c, priv->buffers[DRI3_FRONT_ID]);
1338 }
1339 xcb_flush(c);
1340 if (priv->stamp)
1341 ++(*priv->stamp);
1342 }
1343
1344 return ret;
1345 }
1346
1347 /** dri3_open
1348 *
1349 * Wrapper around xcb_dri3_open
1350 */
1351 static int
1352 dri3_open(Display *dpy,
1353 Window root,
1354 CARD32 provider)
1355 {
1356 xcb_dri3_open_cookie_t cookie;
1357 xcb_dri3_open_reply_t *reply;
1358 xcb_connection_t *c = XGetXCBConnection(dpy);
1359 xcb_generic_error_t *error;
1360 int fd;
1361
1362 cookie = xcb_dri3_open(c,
1363 root,
1364 provider);
1365
1366 reply = xcb_dri3_open_reply(c, cookie, &error);
1367 if (!reply)
1368 return -1;
1369
1370 if (reply->nfd != 1) {
1371 free(reply);
1372 return -1;
1373 }
1374
1375 fd = xcb_dri3_open_reply_fds(c, reply)[0];
1376 fcntl(fd, F_SETFD, FD_CLOEXEC);
1377
1378 return fd;
1379 }
1380
1381
1382 /** dri3_destroy_screen
1383 */
1384 static void
1385 dri3_destroy_screen(struct glx_screen *base)
1386 {
1387 struct dri3_screen *psc = (struct dri3_screen *) base;
1388
1389 /* Free the direct rendering per screen data */
1390 (*psc->core->destroyScreen) (psc->driScreen);
1391 driDestroyConfigs(psc->driver_configs);
1392 close(psc->fd);
1393 free(psc);
1394 }
1395
1396 /** dri3_set_swap_interval
1397 *
1398 * Record the application swap interval specification,
1399 */
1400 static int
1401 dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
1402 {
1403 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
1404 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1405 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
1406
1407 if (psc->config)
1408 psc->config->configQueryi(psc->driScreen,
1409 "vblank_mode", &vblank_mode);
1410
1411 switch (vblank_mode) {
1412 case DRI_CONF_VBLANK_NEVER:
1413 if (interval != 0)
1414 return GLX_BAD_VALUE;
1415 break;
1416 case DRI_CONF_VBLANK_ALWAYS_SYNC:
1417 if (interval <= 0)
1418 return GLX_BAD_VALUE;
1419 break;
1420 default:
1421 break;
1422 }
1423
1424 priv->swap_interval = interval;
1425
1426 return 0;
1427 }
1428
1429 /** dri3_get_swap_interval
1430 *
1431 * Return the stored swap interval
1432 */
1433 static int
1434 dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
1435 {
1436 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
1437
1438 return priv->swap_interval;
1439 }
1440
1441 static void
1442 dri3_bind_tex_image(Display * dpy,
1443 GLXDrawable drawable,
1444 int buffer, const int *attrib_list)
1445 {
1446 struct glx_context *gc = __glXGetCurrentContext();
1447 struct dri3_context *pcp = (struct dri3_context *) gc;
1448 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
1449 struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
1450 struct dri3_screen *psc;
1451
1452 if (pdraw != NULL) {
1453 psc = (struct dri3_screen *) base->psc;
1454
1455 (*psc->f->invalidate)(pdraw->driDrawable);
1456
1457 XSync(dpy, false);
1458
1459 (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
1460 pdraw->base.textureTarget,
1461 pdraw->base.textureFormat,
1462 pdraw->driDrawable);
1463 }
1464 }
1465
1466 static void
1467 dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
1468 {
1469 struct glx_context *gc = __glXGetCurrentContext();
1470 struct dri3_context *pcp = (struct dri3_context *) gc;
1471 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
1472 struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
1473 struct dri3_screen *psc;
1474
1475 if (pdraw != NULL) {
1476 psc = (struct dri3_screen *) base->psc;
1477
1478 if (psc->texBuffer->releaseTexBuffer)
1479 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
1480 pdraw->base.textureTarget,
1481 pdraw->driDrawable);
1482 }
1483 }
1484
1485 static const struct glx_context_vtable dri3_context_vtable = {
1486 dri3_destroy_context,
1487 dri3_bind_context,
1488 dri3_unbind_context,
1489 dri3_wait_gl,
1490 dri3_wait_x,
1491 DRI_glXUseXFont,
1492 dri3_bind_tex_image,
1493 dri3_release_tex_image,
1494 NULL, /* get_proc_address */
1495 };
1496
1497 /** dri3_bind_extensions
1498 *
1499 * Enable all of the extensions supported on DRI3
1500 */
1501 static void
1502 dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
1503 const char *driverName)
1504 {
1505 const __DRIextension **extensions;
1506 unsigned mask;
1507 int i;
1508
1509 extensions = psc->core->getExtensions(psc->driScreen);
1510
1511 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
1512 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
1513 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
1514 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
1515
1516 /*
1517 * GLX_INTEL_swap_event is broken on the server side, where it's
1518 * currently unconditionally enabled. This completely breaks
1519 * systems running on drivers which don't support that extension.
1520 * There's no way to test for its presence on this side, so instead
1521 * of disabling it unconditionally, just disable it for drivers
1522 * which are known to not support it, or for DDX drivers supporting
1523 * only an older (pre-ScheduleSwap) version of DRI2.
1524 *
1525 * This is a hack which is required until:
1526 * http://lists.x.org/archives/xorg-devel/2013-February/035449.html
1527 * is merged and updated xserver makes it's way into distros:
1528 */
1529 // if (pdp->swapAvailable && strcmp(driverName, "vmwgfx") != 0) {
1530 // __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
1531 // }
1532
1533 mask = psc->image_driver->getAPIMask(psc->driScreen);
1534
1535 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
1536 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
1537
1538 if ((mask & (1 << __DRI_API_GLES2)) != 0)
1539 __glXEnableDirectExtension(&psc->base,
1540 "GLX_EXT_create_context_es2_profile");
1541
1542 for (i = 0; extensions[i]; i++) {
1543 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
1544 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
1545 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
1546 }
1547
1548 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
1549 psc->f = (__DRI2flushExtension *) extensions[i];
1550 /* internal driver extension, no GL extension exposed */
1551 }
1552
1553 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
1554 psc->config = (__DRI2configQueryExtension *) extensions[i];
1555
1556 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
1557 __glXEnableDirectExtension(&psc->base,
1558 "GLX_ARB_create_context_robustness");
1559 }
1560 }
1561
1562 static const struct glx_screen_vtable dri3_screen_vtable = {
1563 dri3_create_context,
1564 dri3_create_context_attribs
1565 };
1566
1567 /** dri3_create_screen
1568 *
1569 * Initialize DRI3 on the specified screen.
1570 *
1571 * Opens the DRI device, locates the appropriate DRI driver
1572 * and loads that.
1573 *
1574 * Checks to see if the driver supports the necessary extensions
1575 *
1576 * Initializes the driver for the screen and sets up our structures
1577 */
1578
1579 static struct glx_screen *
1580 dri3_create_screen(int screen, struct glx_display * priv)
1581 {
1582 const __DRIconfig **driver_configs;
1583 const __DRIextension **extensions;
1584 const struct dri3_display *const pdp = (struct dri3_display *)
1585 priv->dri3Display;
1586 struct dri3_screen *psc;
1587 __GLXDRIscreen *psp;
1588 struct glx_config *configs = NULL, *visuals = NULL;
1589 char *driverName, *deviceName;
1590 int i;
1591
1592 psc = calloc(1, sizeof *psc);
1593 if (psc == NULL)
1594 return NULL;
1595
1596 psc->fd = -1;
1597
1598 if (!glx_screen_init(&psc->base, screen, priv)) {
1599 free(psc);
1600 return NULL;
1601 }
1602
1603 psc->fd = dri3_open(priv->dpy, RootWindow(priv->dpy, screen), None);
1604 if (psc->fd < 0) {
1605 glx_screen_cleanup(&psc->base);
1606 free(psc);
1607 InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen);
1608 return NULL;
1609 }
1610 deviceName = NULL;
1611
1612 driverName = dri3_get_driver_for_fd(psc->fd);
1613 if (!driverName) {
1614 ErrorMessageF("No driver found\n");
1615 goto handle_error;
1616 }
1617
1618 psc->driver = driOpenDriver(driverName);
1619 if (psc->driver == NULL) {
1620 ErrorMessageF("driver pointer missing\n");
1621 goto handle_error;
1622 }
1623
1624 extensions = driGetDriverExtensions(psc->driver, driverName);
1625 if (extensions == NULL)
1626 goto handle_error;
1627
1628 for (i = 0; extensions[i]; i++) {
1629 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
1630 psc->core = (__DRIcoreExtension *) extensions[i];
1631 if (strcmp(extensions[i]->name, __DRI_IMAGE_DRIVER) == 0)
1632 psc->image_driver = (__DRIimageDriverExtension *) extensions[i];
1633 }
1634
1635
1636 if (psc->core == NULL) {
1637 ErrorMessageF("core dri driver extension not found\n");
1638 goto handle_error;
1639 }
1640
1641 if (psc->image_driver == NULL) {
1642 ErrorMessageF("image driver extension not found\n");
1643 goto handle_error;
1644 }
1645
1646 psc->driScreen =
1647 psc->image_driver->createNewScreen2(screen, psc->fd,
1648 (const __DRIextension **)
1649 &pdp->loader_extensions[0],
1650 extensions,
1651 &driver_configs, psc);
1652
1653 if (psc->driScreen == NULL) {
1654 ErrorMessageF("failed to create dri screen\n");
1655 goto handle_error;
1656 }
1657
1658 extensions = (*psc->core->getExtensions)(psc->driScreen);
1659
1660 for (i = 0; extensions[i]; i++) {
1661 if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
1662 psc->image = (__DRIimageExtension *) extensions[i];
1663 }
1664
1665 if (psc->image == NULL) {
1666 ErrorMessageF("image extension not found\n");
1667 goto handle_error;
1668 }
1669
1670 dri3_bind_extensions(psc, priv, driverName);
1671
1672 if (!psc->f || psc->f->base.version < 4) {
1673 ErrorMessageF("Version 4 or later of flush extension not found\n");
1674 goto handle_error;
1675 }
1676
1677 if (!psc->texBuffer || psc->texBuffer->base.version < 2 ||
1678 !psc->texBuffer->setTexBuffer2)
1679 {
1680 ErrorMessageF("Version 2 or later of texBuffer extension not found\n");
1681 goto handle_error;
1682 }
1683
1684 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
1685 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
1686
1687 if (!configs || !visuals)
1688 goto handle_error;
1689
1690 glx_config_destroy_list(psc->base.configs);
1691 psc->base.configs = configs;
1692 glx_config_destroy_list(psc->base.visuals);
1693 psc->base.visuals = visuals;
1694
1695 psc->driver_configs = driver_configs;
1696
1697 psc->base.vtable = &dri3_screen_vtable;
1698 psp = &psc->vtable;
1699 psc->base.driScreen = psp;
1700 psp->destroyScreen = dri3_destroy_screen;
1701 psp->createDrawable = dri3_create_drawable;
1702 psp->swapBuffers = dri3_swap_buffers;
1703
1704 psp->getDrawableMSC = dri3_drawable_get_msc;
1705 psp->waitForMSC = dri3_wait_for_msc;
1706 psp->waitForSBC = dri3_wait_for_sbc;
1707 psp->setSwapInterval = dri3_set_swap_interval;
1708 psp->getSwapInterval = dri3_get_swap_interval;
1709 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
1710
1711 psp->copySubBuffer = dri3_copy_sub_buffer;
1712 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
1713
1714 free(driverName);
1715 free(deviceName);
1716
1717 return &psc->base;
1718
1719 handle_error:
1720 CriticalErrorMessageF("failed to load driver: %s\n", driverName);
1721
1722 if (configs)
1723 glx_config_destroy_list(configs);
1724 if (visuals)
1725 glx_config_destroy_list(visuals);
1726 if (psc->driScreen)
1727 psc->core->destroyScreen(psc->driScreen);
1728 psc->driScreen = NULL;
1729 if (psc->fd >= 0)
1730 close(psc->fd);
1731 if (psc->driver)
1732 dlclose(psc->driver);
1733
1734 free(driverName);
1735 free(deviceName);
1736 glx_screen_cleanup(&psc->base);
1737 free(psc);
1738
1739 return NULL;
1740 }
1741
1742 /** dri_destroy_display
1743 *
1744 * Called from __glXFreeDisplayPrivate.
1745 */
1746 static void
1747 dri3_destroy_display(__GLXDRIdisplay * dpy)
1748 {
1749 free(dpy);
1750 }
1751
1752 /** dri3_create_display
1753 *
1754 * Allocate, initialize and return a __DRIdisplayPrivate object.
1755 * This is called from __glXInitialize() when we are given a new
1756 * display pointer. This is public to that function, but hidden from
1757 * outside of libGL.
1758 */
1759 _X_HIDDEN __GLXDRIdisplay *
1760 dri3_create_display(Display * dpy)
1761 {
1762 struct dri3_display *pdp;
1763 int i;
1764 xcb_connection_t *c = XGetXCBConnection(dpy);
1765 xcb_dri3_query_version_cookie_t dri3_cookie;
1766 xcb_dri3_query_version_reply_t *dri3_reply;
1767 xcb_present_query_version_cookie_t present_cookie;
1768 xcb_present_query_version_reply_t *present_reply;
1769 xcb_generic_error_t *error;
1770 const xcb_query_extension_reply_t *extension;
1771
1772 xcb_prefetch_extension_data(c, &xcb_dri3_id);
1773 xcb_prefetch_extension_data(c, &xcb_present_id);
1774
1775 extension = xcb_get_extension_data(c, &xcb_dri3_id);
1776 if (!(extension && extension->present))
1777 return NULL;
1778
1779 extension = xcb_get_extension_data(c, &xcb_present_id);
1780 if (!(extension && extension->present))
1781 return NULL;
1782
1783 dri3_cookie = xcb_dri3_query_version(c,
1784 XCB_DRI3_MAJOR_VERSION,
1785 XCB_DRI3_MINOR_VERSION);
1786
1787
1788 present_cookie = xcb_present_query_version(c,
1789 XCB_PRESENT_MAJOR_VERSION,
1790 XCB_PRESENT_MINOR_VERSION);
1791
1792 pdp = malloc(sizeof *pdp);
1793 if (pdp == NULL)
1794 return NULL;
1795
1796 dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error);
1797 if (!dri3_reply) {
1798 free(error);
1799 goto no_extension;
1800 }
1801
1802 pdp->dri3Major = dri3_reply->major_version;
1803 pdp->dri3Minor = dri3_reply->minor_version;
1804 free(dri3_reply);
1805
1806 present_reply = xcb_present_query_version_reply(c, present_cookie, &error);
1807 if (!present_reply) {
1808 free(error);
1809 goto no_extension;
1810 }
1811 pdp->presentMajor = present_reply->major_version;
1812 pdp->presentMinor = present_reply->minor_version;
1813
1814 pdp->base.destroyDisplay = dri3_destroy_display;
1815 pdp->base.createScreen = dri3_create_screen;
1816
1817 i = 0;
1818
1819 pdp->loader_extensions[i++] = &imageLoaderExtension.base;
1820
1821 pdp->loader_extensions[i++] = &systemTimeExtension.base;
1822
1823 pdp->loader_extensions[i++] = NULL;
1824
1825 return &pdp->base;
1826 no_extension:
1827 free(pdp);
1828 return NULL;
1829 }
1830
1831 #endif /* GLX_DIRECT_RENDERING */