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