glx: cleanup unneeded headers
[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);
1094 struct dri3_buffer *buffer = priv->buffers[id];
1095
1096 if (!buffer)
1097 return b;
1098 if (!buffer->busy)
1099 return b;
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 int back = dri3_find_back(c, priv);
1127
1128 if (back < 0)
1129 return NULL;
1130
1131 priv->cur_back = back;
1132 buf_id = DRI3_BACK_ID(priv->cur_back);
1133 } else {
1134 buf_id = DRI3_FRONT_ID;
1135 }
1136
1137 buffer = priv->buffers[buf_id];
1138
1139 /* Allocate a new buffer if there isn't an old one, or if that
1140 * old one is the wrong size
1141 */
1142 if (!buffer || buffer->width != priv->width || buffer->height != priv->height) {
1143 struct dri3_buffer *new_buffer;
1144
1145 /* Allocate the new buffers
1146 */
1147 new_buffer = dri3_alloc_render_buffer(priv->base.psc,
1148 priv->base.xDrawable,
1149 format, priv->width, priv->height, priv->depth);
1150 if (!new_buffer)
1151 return NULL;
1152
1153 /* When resizing, copy the contents of the old buffer, waiting for that
1154 * copy to complete using our fences before proceeding
1155 */
1156 switch (buffer_type) {
1157 case dri3_buffer_back:
1158 if (buffer) {
1159 dri3_fence_reset(c, new_buffer);
1160 dri3_fence_await(c, buffer);
1161 dri3_copy_area(c,
1162 buffer->pixmap,
1163 new_buffer->pixmap,
1164 dri3_drawable_gc(priv),
1165 0, 0, 0, 0, priv->width, priv->height);
1166 dri3_fence_trigger(c, new_buffer);
1167 dri3_free_render_buffer(priv, buffer);
1168 }
1169 break;
1170 case dri3_buffer_front:
1171 dri3_fence_reset(c, new_buffer);
1172 dri3_copy_area(c,
1173 priv->base.xDrawable,
1174 new_buffer->pixmap,
1175 dri3_drawable_gc(priv),
1176 0, 0, 0, 0, priv->width, priv->height);
1177 dri3_fence_trigger(c, new_buffer);
1178 break;
1179 }
1180 buffer = new_buffer;
1181 buffer->buffer_type = buffer_type;
1182 priv->buffers[buf_id] = buffer;
1183 }
1184 dri3_fence_await(c, buffer);
1185
1186 /* Return the requested buffer */
1187 return buffer;
1188 }
1189
1190 /** dri3_free_buffers
1191 *
1192 * Free the front bufffer or all of the back buffers. Used
1193 * when the application changes which buffers it needs
1194 */
1195 static void
1196 dri3_free_buffers(__DRIdrawable *driDrawable,
1197 enum dri3_buffer_type buffer_type,
1198 void *loaderPrivate)
1199 {
1200 struct dri3_drawable *priv = loaderPrivate;
1201 struct dri3_buffer *buffer;
1202 int first_id;
1203 int n_id;
1204 int buf_id;
1205
1206 switch (buffer_type) {
1207 case dri3_buffer_back:
1208 first_id = DRI3_BACK_ID(0);
1209 n_id = DRI3_MAX_BACK;
1210 break;
1211 case dri3_buffer_front:
1212 first_id = DRI3_FRONT_ID;
1213 n_id = 1;
1214 }
1215
1216 for (buf_id = first_id; buf_id < first_id + n_id; buf_id++) {
1217 buffer = priv->buffers[buf_id];
1218 if (buffer) {
1219 dri3_free_render_buffer(priv, buffer);
1220 priv->buffers[buf_id] = NULL;
1221 }
1222 }
1223 }
1224
1225 /** dri3_get_buffers
1226 *
1227 * The published buffer allocation API.
1228 * Returns all of the necessary buffers, allocating
1229 * as needed.
1230 */
1231 static int
1232 dri3_get_buffers(__DRIdrawable *driDrawable,
1233 unsigned int format,
1234 uint32_t *stamp,
1235 void *loaderPrivate,
1236 uint32_t buffer_mask,
1237 struct __DRIimageList *buffers)
1238 {
1239 struct dri3_drawable *priv = loaderPrivate;
1240 struct dri3_buffer *front, *back;
1241
1242 buffers->image_mask = 0;
1243 buffers->front = NULL;
1244 buffers->back = NULL;
1245
1246 front = NULL;
1247 back = NULL;
1248
1249 if (!dri3_update_drawable(driDrawable, loaderPrivate))
1250 return false;
1251
1252 /* pixmaps always have front buffers */
1253 if (priv->is_pixmap)
1254 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
1255
1256 if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
1257 if (priv->is_pixmap)
1258 front = dri3_get_pixmap_buffer(driDrawable,
1259 format,
1260 dri3_buffer_front,
1261 loaderPrivate);
1262 else
1263 front = dri3_get_buffer(driDrawable,
1264 format,
1265 dri3_buffer_front,
1266 loaderPrivate);
1267
1268 if (!front)
1269 return false;
1270 } else {
1271 dri3_free_buffers(driDrawable, dri3_buffer_front, loaderPrivate);
1272 priv->have_fake_front = 0;
1273 }
1274
1275 if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
1276 back = dri3_get_buffer(driDrawable,
1277 format,
1278 dri3_buffer_back,
1279 loaderPrivate);
1280 if (!back)
1281 return false;
1282 priv->have_back = 1;
1283 } else {
1284 dri3_free_buffers(driDrawable, dri3_buffer_back, loaderPrivate);
1285 priv->have_back = 0;
1286 }
1287
1288 if (front) {
1289 buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
1290 buffers->front = front->image;
1291 priv->have_fake_front = !priv->is_pixmap;
1292 }
1293
1294 if (back) {
1295 buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
1296 buffers->back = back->image;
1297 }
1298
1299 priv->stamp = stamp;
1300
1301 return true;
1302 }
1303
1304 /* The image loader extension record for DRI3
1305 */
1306 static const __DRIimageLoaderExtension imageLoaderExtension = {
1307 .base = { __DRI_IMAGE_LOADER, 1 },
1308
1309 .getBuffers = dri3_get_buffers,
1310 .flushFrontBuffer = dri3_flush_front_buffer,
1311 };
1312
1313 /** dri3_swap_buffers
1314 *
1315 * Make the current back buffer visible using the present extension
1316 */
1317 static int64_t
1318 dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
1319 int64_t remainder, Bool flush)
1320 {
1321 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
1322 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
1323 Display *dpy = priv->base.psc->dpy;
1324 xcb_connection_t *c = XGetXCBConnection(dpy);
1325 int buf_id = DRI3_BACK_ID(priv->cur_back);
1326 int64_t ret = 0;
1327
1328 unsigned flags = __DRI2_FLUSH_DRAWABLE;
1329 if (flush)
1330 flags |= __DRI2_FLUSH_CONTEXT;
1331 dri3_flush(psc, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
1332
1333 dri3_flush_present_events(priv);
1334
1335 if (priv->buffers[buf_id] && !priv->is_pixmap) {
1336 dri3_fence_reset(c, priv->buffers[buf_id]);
1337
1338 /* Compute when we want the frame shown by taking the last known successful
1339 * MSC and adding in a swap interval for each outstanding swap request
1340 */
1341 ++priv->send_sbc;
1342 if (target_msc == 0)
1343 target_msc = priv->msc + priv->swap_interval * (priv->send_sbc - priv->recv_sbc);
1344
1345 priv->buffers[buf_id]->busy = 1;
1346 xcb_present_pixmap(c,
1347 priv->base.xDrawable,
1348 priv->buffers[buf_id]->pixmap,
1349 (uint32_t) priv->send_sbc,
1350 0, /* valid */
1351 0, /* update */
1352 0, /* x_off */
1353 0, /* y_off */
1354 None, /* target_crtc */
1355 None,
1356 priv->buffers[buf_id]->sync_fence,
1357 XCB_PRESENT_OPTION_NONE,
1358 target_msc,
1359 divisor,
1360 remainder, 0, NULL);
1361 ret = (int64_t) priv->send_sbc;
1362
1363 /* If there's a fake front, then copy the source back buffer
1364 * to the fake front to keep it up to date. This needs
1365 * to reset the fence and make future users block until
1366 * the X server is done copying the bits
1367 */
1368 if (priv->have_fake_front) {
1369 dri3_fence_reset(c, priv->buffers[DRI3_FRONT_ID]);
1370 dri3_copy_area(c,
1371 priv->buffers[buf_id]->pixmap,
1372 priv->buffers[DRI3_FRONT_ID]->pixmap,
1373 dri3_drawable_gc(priv),
1374 0, 0, 0, 0, priv->width, priv->height);
1375 dri3_fence_trigger(c, priv->buffers[DRI3_FRONT_ID]);
1376 }
1377 xcb_flush(c);
1378 if (priv->stamp)
1379 ++(*priv->stamp);
1380 }
1381
1382 return ret;
1383 }
1384
1385 /** dri3_open
1386 *
1387 * Wrapper around xcb_dri3_open
1388 */
1389 static int
1390 dri3_open(Display *dpy,
1391 Window root,
1392 CARD32 provider)
1393 {
1394 xcb_dri3_open_cookie_t cookie;
1395 xcb_dri3_open_reply_t *reply;
1396 xcb_connection_t *c = XGetXCBConnection(dpy);
1397 int fd;
1398
1399 cookie = xcb_dri3_open(c,
1400 root,
1401 provider);
1402
1403 reply = xcb_dri3_open_reply(c, cookie, NULL);
1404 if (!reply)
1405 return -1;
1406
1407 if (reply->nfd != 1) {
1408 free(reply);
1409 return -1;
1410 }
1411
1412 fd = xcb_dri3_open_reply_fds(c, reply)[0];
1413 fcntl(fd, F_SETFD, FD_CLOEXEC);
1414
1415 return fd;
1416 }
1417
1418
1419 /** dri3_destroy_screen
1420 */
1421 static void
1422 dri3_destroy_screen(struct glx_screen *base)
1423 {
1424 struct dri3_screen *psc = (struct dri3_screen *) base;
1425
1426 /* Free the direct rendering per screen data */
1427 (*psc->core->destroyScreen) (psc->driScreen);
1428 driDestroyConfigs(psc->driver_configs);
1429 close(psc->fd);
1430 free(psc);
1431 }
1432
1433 /** dri3_set_swap_interval
1434 *
1435 * Record the application swap interval specification,
1436 */
1437 static int
1438 dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
1439 {
1440 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
1441 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1442 struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
1443
1444 if (psc->config)
1445 psc->config->configQueryi(psc->driScreen,
1446 "vblank_mode", &vblank_mode);
1447
1448 switch (vblank_mode) {
1449 case DRI_CONF_VBLANK_NEVER:
1450 if (interval != 0)
1451 return GLX_BAD_VALUE;
1452 break;
1453 case DRI_CONF_VBLANK_ALWAYS_SYNC:
1454 if (interval <= 0)
1455 return GLX_BAD_VALUE;
1456 break;
1457 default:
1458 break;
1459 }
1460
1461 priv->swap_interval = interval;
1462 dri3_update_num_back(priv);
1463
1464 return 0;
1465 }
1466
1467 /** dri3_get_swap_interval
1468 *
1469 * Return the stored swap interval
1470 */
1471 static int
1472 dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
1473 {
1474 struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
1475
1476 return priv->swap_interval;
1477 }
1478
1479 static void
1480 dri3_bind_tex_image(Display * dpy,
1481 GLXDrawable drawable,
1482 int buffer, const int *attrib_list)
1483 {
1484 struct glx_context *gc = __glXGetCurrentContext();
1485 struct dri3_context *pcp = (struct dri3_context *) gc;
1486 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
1487 struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
1488 struct dri3_screen *psc;
1489
1490 if (pdraw != NULL) {
1491 psc = (struct dri3_screen *) base->psc;
1492
1493 (*psc->f->invalidate)(pdraw->driDrawable);
1494
1495 XSync(dpy, false);
1496
1497 (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
1498 pdraw->base.textureTarget,
1499 pdraw->base.textureFormat,
1500 pdraw->driDrawable);
1501 }
1502 }
1503
1504 static void
1505 dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
1506 {
1507 struct glx_context *gc = __glXGetCurrentContext();
1508 struct dri3_context *pcp = (struct dri3_context *) gc;
1509 __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
1510 struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
1511 struct dri3_screen *psc;
1512
1513 if (pdraw != NULL) {
1514 psc = (struct dri3_screen *) base->psc;
1515
1516 if (psc->texBuffer->releaseTexBuffer)
1517 (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
1518 pdraw->base.textureTarget,
1519 pdraw->driDrawable);
1520 }
1521 }
1522
1523 static const struct glx_context_vtable dri3_context_vtable = {
1524 dri3_destroy_context,
1525 dri3_bind_context,
1526 dri3_unbind_context,
1527 dri3_wait_gl,
1528 dri3_wait_x,
1529 DRI_glXUseXFont,
1530 dri3_bind_tex_image,
1531 dri3_release_tex_image,
1532 NULL, /* get_proc_address */
1533 };
1534
1535 /** dri3_bind_extensions
1536 *
1537 * Enable all of the extensions supported on DRI3
1538 */
1539 static void
1540 dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
1541 const char *driverName)
1542 {
1543 const __DRIextension **extensions;
1544 unsigned mask;
1545 int i;
1546
1547 extensions = psc->core->getExtensions(psc->driScreen);
1548
1549 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
1550 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
1551 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
1552 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
1553 __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
1554
1555 mask = psc->image_driver->getAPIMask(psc->driScreen);
1556
1557 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
1558 __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
1559
1560 if ((mask & (1 << __DRI_API_GLES2)) != 0)
1561 __glXEnableDirectExtension(&psc->base,
1562 "GLX_EXT_create_context_es2_profile");
1563
1564 for (i = 0; extensions[i]; i++) {
1565 if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
1566 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
1567 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
1568 }
1569
1570 if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
1571 psc->f = (__DRI2flushExtension *) extensions[i];
1572 /* internal driver extension, no GL extension exposed */
1573 }
1574
1575 if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
1576 psc->config = (__DRI2configQueryExtension *) extensions[i];
1577
1578 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
1579 __glXEnableDirectExtension(&psc->base,
1580 "GLX_ARB_create_context_robustness");
1581 }
1582 }
1583
1584 static const struct glx_screen_vtable dri3_screen_vtable = {
1585 dri3_create_context,
1586 dri3_create_context_attribs
1587 };
1588
1589 /** dri3_create_screen
1590 *
1591 * Initialize DRI3 on the specified screen.
1592 *
1593 * Opens the DRI device, locates the appropriate DRI driver
1594 * and loads that.
1595 *
1596 * Checks to see if the driver supports the necessary extensions
1597 *
1598 * Initializes the driver for the screen and sets up our structures
1599 */
1600
1601 static struct glx_screen *
1602 dri3_create_screen(int screen, struct glx_display * priv)
1603 {
1604 xcb_connection_t *c = XGetXCBConnection(priv->dpy);
1605 const __DRIconfig **driver_configs;
1606 const __DRIextension **extensions;
1607 const struct dri3_display *const pdp = (struct dri3_display *)
1608 priv->dri3Display;
1609 struct dri3_screen *psc;
1610 __GLXDRIscreen *psp;
1611 struct glx_config *configs = NULL, *visuals = NULL;
1612 char *driverName, *deviceName;
1613 int i;
1614
1615 psc = calloc(1, sizeof *psc);
1616 if (psc == NULL)
1617 return NULL;
1618
1619 psc->fd = -1;
1620
1621 if (!glx_screen_init(&psc->base, screen, priv)) {
1622 free(psc);
1623 return NULL;
1624 }
1625
1626 psc->fd = dri3_open(priv->dpy, RootWindow(priv->dpy, screen), None);
1627 if (psc->fd < 0) {
1628 int conn_error = xcb_connection_has_error(c);
1629
1630 glx_screen_cleanup(&psc->base);
1631 free(psc);
1632 InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen);
1633
1634 if (conn_error)
1635 ErrorMessageF("Connection closed during DRI3 initialization failure");
1636
1637 return NULL;
1638 }
1639 deviceName = NULL;
1640
1641 driverName = loader_get_driver_for_fd(psc->fd, 0);
1642 if (!driverName) {
1643 ErrorMessageF("No driver found\n");
1644 goto handle_error;
1645 }
1646
1647 psc->driver = driOpenDriver(driverName);
1648 if (psc->driver == NULL) {
1649 ErrorMessageF("driver pointer missing\n");
1650 goto handle_error;
1651 }
1652
1653 extensions = driGetDriverExtensions(psc->driver, driverName);
1654 if (extensions == NULL)
1655 goto handle_error;
1656
1657 for (i = 0; extensions[i]; i++) {
1658 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
1659 psc->core = (__DRIcoreExtension *) extensions[i];
1660 if (strcmp(extensions[i]->name, __DRI_IMAGE_DRIVER) == 0)
1661 psc->image_driver = (__DRIimageDriverExtension *) extensions[i];
1662 }
1663
1664
1665 if (psc->core == NULL) {
1666 ErrorMessageF("core dri driver extension not found\n");
1667 goto handle_error;
1668 }
1669
1670 if (psc->image_driver == NULL) {
1671 ErrorMessageF("image driver extension not found\n");
1672 goto handle_error;
1673 }
1674
1675 psc->driScreen =
1676 psc->image_driver->createNewScreen2(screen, psc->fd,
1677 (const __DRIextension **)
1678 &pdp->loader_extensions[0],
1679 extensions,
1680 &driver_configs, psc);
1681
1682 if (psc->driScreen == NULL) {
1683 ErrorMessageF("failed to create dri screen\n");
1684 goto handle_error;
1685 }
1686
1687 extensions = (*psc->core->getExtensions)(psc->driScreen);
1688
1689 for (i = 0; extensions[i]; i++) {
1690 if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
1691 psc->image = (__DRIimageExtension *) extensions[i];
1692 }
1693
1694 if (psc->image == NULL) {
1695 ErrorMessageF("image extension not found\n");
1696 goto handle_error;
1697 }
1698
1699 dri3_bind_extensions(psc, priv, driverName);
1700
1701 if (!psc->f || psc->f->base.version < 4) {
1702 ErrorMessageF("Version 4 or later of flush extension not found\n");
1703 goto handle_error;
1704 }
1705
1706 if (!psc->texBuffer || psc->texBuffer->base.version < 2 ||
1707 !psc->texBuffer->setTexBuffer2)
1708 {
1709 ErrorMessageF("Version 2 or later of texBuffer extension not found\n");
1710 goto handle_error;
1711 }
1712
1713 configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
1714 visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
1715
1716 if (!configs || !visuals)
1717 goto handle_error;
1718
1719 glx_config_destroy_list(psc->base.configs);
1720 psc->base.configs = configs;
1721 glx_config_destroy_list(psc->base.visuals);
1722 psc->base.visuals = visuals;
1723
1724 psc->driver_configs = driver_configs;
1725
1726 psc->base.vtable = &dri3_screen_vtable;
1727 psp = &psc->vtable;
1728 psc->base.driScreen = psp;
1729 psp->destroyScreen = dri3_destroy_screen;
1730 psp->createDrawable = dri3_create_drawable;
1731 psp->swapBuffers = dri3_swap_buffers;
1732
1733 psp->getDrawableMSC = dri3_drawable_get_msc;
1734 psp->waitForMSC = dri3_wait_for_msc;
1735 psp->waitForSBC = dri3_wait_for_sbc;
1736 psp->setSwapInterval = dri3_set_swap_interval;
1737 psp->getSwapInterval = dri3_get_swap_interval;
1738 __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
1739
1740 psp->copySubBuffer = dri3_copy_sub_buffer;
1741 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
1742
1743 free(driverName);
1744 free(deviceName);
1745
1746 return &psc->base;
1747
1748 handle_error:
1749 CriticalErrorMessageF("failed to load driver: %s\n", driverName);
1750
1751 if (configs)
1752 glx_config_destroy_list(configs);
1753 if (visuals)
1754 glx_config_destroy_list(visuals);
1755 if (psc->driScreen)
1756 psc->core->destroyScreen(psc->driScreen);
1757 psc->driScreen = NULL;
1758 if (psc->fd >= 0)
1759 close(psc->fd);
1760 if (psc->driver)
1761 dlclose(psc->driver);
1762
1763 free(driverName);
1764 free(deviceName);
1765 glx_screen_cleanup(&psc->base);
1766 free(psc);
1767
1768 return NULL;
1769 }
1770
1771 /** dri_destroy_display
1772 *
1773 * Called from __glXFreeDisplayPrivate.
1774 */
1775 static void
1776 dri3_destroy_display(__GLXDRIdisplay * dpy)
1777 {
1778 free(dpy);
1779 }
1780
1781 /** dri3_create_display
1782 *
1783 * Allocate, initialize and return a __DRIdisplayPrivate object.
1784 * This is called from __glXInitialize() when we are given a new
1785 * display pointer. This is public to that function, but hidden from
1786 * outside of libGL.
1787 */
1788 _X_HIDDEN __GLXDRIdisplay *
1789 dri3_create_display(Display * dpy)
1790 {
1791 struct dri3_display *pdp;
1792 int i;
1793 xcb_connection_t *c = XGetXCBConnection(dpy);
1794 xcb_dri3_query_version_cookie_t dri3_cookie;
1795 xcb_dri3_query_version_reply_t *dri3_reply;
1796 xcb_present_query_version_cookie_t present_cookie;
1797 xcb_present_query_version_reply_t *present_reply;
1798 xcb_generic_error_t *error;
1799 const xcb_query_extension_reply_t *extension;
1800
1801 xcb_prefetch_extension_data(c, &xcb_dri3_id);
1802 xcb_prefetch_extension_data(c, &xcb_present_id);
1803
1804 extension = xcb_get_extension_data(c, &xcb_dri3_id);
1805 if (!(extension && extension->present))
1806 return NULL;
1807
1808 extension = xcb_get_extension_data(c, &xcb_present_id);
1809 if (!(extension && extension->present))
1810 return NULL;
1811
1812 dri3_cookie = xcb_dri3_query_version(c,
1813 XCB_DRI3_MAJOR_VERSION,
1814 XCB_DRI3_MINOR_VERSION);
1815
1816
1817 present_cookie = xcb_present_query_version(c,
1818 XCB_PRESENT_MAJOR_VERSION,
1819 XCB_PRESENT_MINOR_VERSION);
1820
1821 pdp = malloc(sizeof *pdp);
1822 if (pdp == NULL)
1823 return NULL;
1824
1825 dri3_reply = xcb_dri3_query_version_reply(c, dri3_cookie, &error);
1826 if (!dri3_reply) {
1827 free(error);
1828 goto no_extension;
1829 }
1830
1831 pdp->dri3Major = dri3_reply->major_version;
1832 pdp->dri3Minor = dri3_reply->minor_version;
1833 free(dri3_reply);
1834
1835 present_reply = xcb_present_query_version_reply(c, present_cookie, &error);
1836 if (!present_reply) {
1837 free(error);
1838 goto no_extension;
1839 }
1840 pdp->presentMajor = present_reply->major_version;
1841 pdp->presentMinor = present_reply->minor_version;
1842 free(present_reply);
1843
1844 pdp->base.destroyDisplay = dri3_destroy_display;
1845 pdp->base.createScreen = dri3_create_screen;
1846
1847 loader_set_logger(dri_message);
1848 i = 0;
1849
1850 pdp->loader_extensions[i++] = &imageLoaderExtension.base;
1851
1852 pdp->loader_extensions[i++] = &systemTimeExtension.base;
1853
1854 pdp->loader_extensions[i++] = NULL;
1855
1856 return &pdp->base;
1857 no_extension:
1858 free(pdp);
1859 return NULL;
1860 }
1861
1862 #endif /* GLX_DIRECT_RENDERING */