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