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