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