2 * Copyright © 2013 Keith Packard
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.
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
24 * Portions of this code were adapted from dri2_glx.c which carries the
25 * following copyright:
27 * Copyright © 2008 Red Hat, Inc.
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.
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.
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.
55 * Kristian Høgsberg (krh@redhat.com)
58 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
61 #include <X11/extensions/Xfixes.h>
62 #include <X11/Xlib-xcb.h>
63 #include <X11/xshmfence.h>
66 #include <xcb/present.h>
68 #include "glxclient.h"
72 #include <sys/types.h>
76 #include "dri_common.h"
77 #include "dri3_priv.h"
81 static struct dri3_drawable
*
82 loader_drawable_to_dri3_drawable(struct loader_dri3_drawable
*draw
) {
83 size_t offset
= offsetof(struct dri3_drawable
, loader_drawable
);
86 return (struct dri3_drawable
*)(((void*) draw
) - offset
);
90 glx_dri3_set_drawable_size(struct loader_dri3_drawable
*draw
,
91 int width
, int height
)
97 glx_dri3_in_current_context(struct loader_dri3_drawable
*draw
)
99 struct dri3_drawable
*priv
= loader_drawable_to_dri3_drawable(draw
);
104 struct dri3_context
*pcp
= (struct dri3_context
*) __glXGetCurrentContext();
105 struct dri3_screen
*psc
= (struct dri3_screen
*) priv
->base
.psc
;
107 return (&pcp
->base
!= &dummyContext
) && pcp
->base
.psc
== &psc
->base
;
110 static __DRIcontext
*
111 glx_dri3_get_dri_context(struct loader_dri3_drawable
*draw
)
113 struct glx_context
*gc
= __glXGetCurrentContext();
114 struct dri3_context
*dri3Ctx
= (struct dri3_context
*) gc
;
116 return (gc
!= &dummyContext
) ? dri3Ctx
->driContext
: NULL
;
120 glx_dri3_get_dri_screen(void)
122 struct glx_context
*gc
= __glXGetCurrentContext();
123 struct dri3_context
*pcp
= (struct dri3_context
*) gc
;
124 struct dri3_screen
*psc
= (struct dri3_screen
*) pcp
->base
.psc
;
126 return (gc
!= &dummyContext
&& psc
) ? psc
->driScreen
: NULL
;
130 glx_dri3_flush_drawable(struct loader_dri3_drawable
*draw
, unsigned flags
)
132 loader_dri3_flush(draw
, flags
, __DRI2_THROTTLE_SWAPBUFFER
);
136 glx_dri3_show_fps(struct loader_dri3_drawable
*draw
, uint64_t current_ust
)
138 struct dri3_drawable
*priv
= loader_drawable_to_dri3_drawable(draw
);
139 const uint64_t interval
=
140 ((struct dri3_screen
*) priv
->base
.psc
)->show_fps_interval
;
147 /* DRI3+Present together uses microseconds for UST. */
148 if (priv
->previous_ust
+ interval
* 1000000 <= current_ust
) {
149 if (priv
->previous_ust
) {
150 fprintf(stderr
, "libGL: FPS = %.1f\n",
151 ((uint64_t) priv
->frames
* 1000000) /
152 (double)(current_ust
- priv
->previous_ust
));
155 priv
->previous_ust
= current_ust
;
159 static const struct loader_dri3_vtable glx_dri3_vtable
= {
160 .set_drawable_size
= glx_dri3_set_drawable_size
,
161 .in_current_context
= glx_dri3_in_current_context
,
162 .get_dri_context
= glx_dri3_get_dri_context
,
163 .get_dri_screen
= glx_dri3_get_dri_screen
,
164 .flush_drawable
= glx_dri3_flush_drawable
,
165 .show_fps
= glx_dri3_show_fps
,
169 static const struct glx_context_vtable dri3_context_vtable
;
172 dri3_destroy_context(struct glx_context
*context
)
174 struct dri3_context
*pcp
= (struct dri3_context
*) context
;
175 struct dri3_screen
*psc
= (struct dri3_screen
*) context
->psc
;
177 driReleaseDrawables(&pcp
->base
);
179 free((char *) context
->extensions
);
181 (*psc
->core
->destroyContext
) (pcp
->driContext
);
187 dri3_bind_context(struct glx_context
*context
, struct glx_context
*old
,
188 GLXDrawable draw
, GLXDrawable read
)
190 struct dri3_context
*pcp
= (struct dri3_context
*) context
;
191 struct dri3_screen
*psc
= (struct dri3_screen
*) pcp
->base
.psc
;
192 struct dri3_drawable
*pdraw
, *pread
;
193 __DRIdrawable
*dri_draw
= NULL
, *dri_read
= NULL
;
195 pdraw
= (struct dri3_drawable
*) driFetchDrawable(context
, draw
);
196 pread
= (struct dri3_drawable
*) driFetchDrawable(context
, read
);
198 driReleaseDrawables(&pcp
->base
);
201 dri_draw
= pdraw
->loader_drawable
.dri_drawable
;
202 else if (draw
!= None
)
203 return GLXBadDrawable
;
206 dri_read
= pread
->loader_drawable
.dri_drawable
;
207 else if (read
!= None
)
208 return GLXBadDrawable
;
210 if (!(*psc
->core
->bindContext
) (pcp
->driContext
, dri_draw
, dri_read
))
211 return GLXBadContext
;
214 (*psc
->f
->invalidate
)(dri_draw
);
215 if (dri_read
&& dri_read
!= dri_draw
)
216 (*psc
->f
->invalidate
)(dri_read
);
222 dri3_unbind_context(struct glx_context
*context
, struct glx_context
*new)
224 struct dri3_context
*pcp
= (struct dri3_context
*) context
;
225 struct dri3_screen
*psc
= (struct dri3_screen
*) pcp
->base
.psc
;
227 (*psc
->core
->unbindContext
) (pcp
->driContext
);
230 static struct glx_context
*
231 dri3_create_context_attribs(struct glx_screen
*base
,
232 struct glx_config
*config_base
,
233 struct glx_context
*shareList
,
234 unsigned num_attribs
,
235 const uint32_t *attribs
,
238 struct dri3_context
*pcp
= NULL
;
239 struct dri3_context
*pcp_shared
= NULL
;
240 struct dri3_screen
*psc
= (struct dri3_screen
*) base
;
241 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
242 __DRIcontext
*shared
= NULL
;
244 uint32_t minor_ver
= 1;
245 uint32_t major_ver
= 2;
248 int reset
= __DRI_CTX_RESET_NO_NOTIFICATION
;
249 int release
= __DRI_CTX_RELEASE_BEHAVIOR_FLUSH
;
250 uint32_t ctx_attribs
[2 * 6];
251 unsigned num_ctx_attribs
= 0;
252 uint32_t render_type
;
254 /* Remap the GLX tokens to DRI2 tokens.
256 if (!dri2_convert_glx_attribs(num_attribs
, attribs
,
257 &major_ver
, &minor_ver
,
258 &render_type
, &flags
, &api
,
259 &reset
, &release
, error
))
262 if (!dri2_check_no_error(flags
, shareList
, major_ver
, error
)) {
266 /* Check the renderType value */
267 if (!validate_renderType_against_config(config_base
, render_type
))
271 pcp_shared
= (struct dri3_context
*) shareList
;
272 shared
= pcp_shared
->driContext
;
275 pcp
= calloc(1, sizeof *pcp
);
277 *error
= __DRI_CTX_ERROR_NO_MEMORY
;
281 if (!glx_context_init(&pcp
->base
, &psc
->base
, config_base
))
284 ctx_attribs
[num_ctx_attribs
++] = __DRI_CTX_ATTRIB_MAJOR_VERSION
;
285 ctx_attribs
[num_ctx_attribs
++] = major_ver
;
286 ctx_attribs
[num_ctx_attribs
++] = __DRI_CTX_ATTRIB_MINOR_VERSION
;
287 ctx_attribs
[num_ctx_attribs
++] = minor_ver
;
289 /* Only send a value when the non-default value is requested. By doing
290 * this we don't have to check the driver's DRI3 version before sending the
293 if (reset
!= __DRI_CTX_RESET_NO_NOTIFICATION
) {
294 ctx_attribs
[num_ctx_attribs
++] = __DRI_CTX_ATTRIB_RESET_STRATEGY
;
295 ctx_attribs
[num_ctx_attribs
++] = reset
;
298 if (release
!= __DRI_CTX_RELEASE_BEHAVIOR_FLUSH
) {
299 ctx_attribs
[num_ctx_attribs
++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR
;
300 ctx_attribs
[num_ctx_attribs
++] = release
;
304 ctx_attribs
[num_ctx_attribs
++] = __DRI_CTX_ATTRIB_FLAGS
;
306 /* The current __DRI_CTX_FLAG_* values are identical to the
307 * GLX_CONTEXT_*_BIT values.
309 ctx_attribs
[num_ctx_attribs
++] = flags
;
311 if (flags
& __DRI_CTX_FLAG_NO_ERROR
)
312 pcp
->base
.noError
= GL_TRUE
;
316 (*psc
->image_driver
->createContextAttribs
) (psc
->driScreen
,
318 config
? config
->driConfig
326 if (pcp
->driContext
== NULL
)
329 pcp
->base
.vtable
= &dri3_context_vtable
;
339 static struct glx_context
*
340 dri3_create_context(struct glx_screen
*base
,
341 struct glx_config
*config_base
,
342 struct glx_context
*shareList
, int renderType
)
345 uint32_t attribs
[2] = { GLX_RENDER_TYPE
, renderType
};
347 return dri3_create_context_attribs(base
, config_base
, shareList
,
352 dri3_destroy_drawable(__GLXDRIdrawable
*base
)
354 struct dri3_drawable
*pdraw
= (struct dri3_drawable
*) base
;
356 loader_dri3_drawable_fini(&pdraw
->loader_drawable
);
361 static __GLXDRIdrawable
*
362 dri3_create_drawable(struct glx_screen
*base
, XID xDrawable
,
363 GLXDrawable drawable
, struct glx_config
*config_base
)
365 struct dri3_drawable
*pdraw
;
366 struct dri3_screen
*psc
= (struct dri3_screen
*) base
;
367 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
368 bool has_multibuffer
= false;
369 #ifdef HAVE_DRI3_MODIFIERS
370 const struct dri3_display
*const pdp
= (struct dri3_display
*)
371 base
->display
->dri3Display
;
374 pdraw
= calloc(1, sizeof(*pdraw
));
378 pdraw
->base
.destroyDrawable
= dri3_destroy_drawable
;
379 pdraw
->base
.xDrawable
= xDrawable
;
380 pdraw
->base
.drawable
= drawable
;
381 pdraw
->base
.psc
= &psc
->base
;
383 #ifdef HAVE_DRI3_MODIFIERS
384 if ((psc
->image
&& psc
->image
->base
.version
>= 15) &&
385 (pdp
->dri3Major
> 1 || (pdp
->dri3Major
== 1 && pdp
->dri3Minor
>= 2)) &&
386 (pdp
->presentMajor
> 1 ||
387 (pdp
->presentMajor
== 1 && pdp
->presentMinor
>= 2)))
388 has_multibuffer
= true;
391 (void) __glXInitialize(psc
->base
.dpy
);
393 if (loader_dri3_drawable_init(XGetXCBConnection(base
->dpy
),
394 xDrawable
, psc
->driScreen
,
395 psc
->is_different_gpu
, has_multibuffer
,
397 &psc
->loader_dri3_ext
, &glx_dri3_vtable
,
398 &pdraw
->loader_drawable
)) {
406 /** dri3_wait_for_msc
408 * Get the X server to send an event when the target msc/divisor/remainder is
412 dri3_wait_for_msc(__GLXDRIdrawable
*pdraw
, int64_t target_msc
, int64_t divisor
,
413 int64_t remainder
, int64_t *ust
, int64_t *msc
, int64_t *sbc
)
415 struct dri3_drawable
*priv
= (struct dri3_drawable
*) pdraw
;
417 loader_dri3_wait_for_msc(&priv
->loader_drawable
, target_msc
, divisor
,
418 remainder
, ust
, msc
, sbc
);
423 /** dri3_drawable_get_msc
425 * Return the current UST/MSC/SBC triplet by asking the server
429 dri3_drawable_get_msc(struct glx_screen
*psc
, __GLXDRIdrawable
*pdraw
,
430 int64_t *ust
, int64_t *msc
, int64_t *sbc
)
432 return dri3_wait_for_msc(pdraw
, 0, 0, 0, ust
, msc
,sbc
);
435 /** dri3_wait_for_sbc
437 * Wait for the completed swap buffer count to reach the specified
438 * target. Presumably the application knows that this will be reached with
439 * outstanding complete events, or we're going to be here awhile.
442 dri3_wait_for_sbc(__GLXDRIdrawable
*pdraw
, int64_t target_sbc
, int64_t *ust
,
443 int64_t *msc
, int64_t *sbc
)
445 struct dri3_drawable
*priv
= (struct dri3_drawable
*) pdraw
;
447 return loader_dri3_wait_for_sbc(&priv
->loader_drawable
, target_sbc
,
452 dri3_copy_sub_buffer(__GLXDRIdrawable
*pdraw
, int x
, int y
,
453 int width
, int height
,
456 struct dri3_drawable
*priv
= (struct dri3_drawable
*) pdraw
;
458 loader_dri3_copy_sub_buffer(&priv
->loader_drawable
, x
, y
,
459 width
, height
, flush
);
463 dri3_wait_x(struct glx_context
*gc
)
465 struct dri3_drawable
*priv
= (struct dri3_drawable
*)
466 GetGLXDRIDrawable(gc
->currentDpy
, gc
->currentDrawable
);
469 loader_dri3_wait_x(&priv
->loader_drawable
);
473 dri3_wait_gl(struct glx_context
*gc
)
475 struct dri3_drawable
*priv
= (struct dri3_drawable
*)
476 GetGLXDRIDrawable(gc
->currentDpy
, gc
->currentDrawable
);
479 loader_dri3_wait_gl(&priv
->loader_drawable
);
483 * Called by the driver when it needs to update the real front buffer with the
484 * contents of its fake front buffer.
487 dri3_flush_front_buffer(__DRIdrawable
*driDrawable
, void *loaderPrivate
)
489 struct loader_dri3_drawable
*draw
= loaderPrivate
;
490 struct dri3_drawable
*pdraw
= loader_drawable_to_dri3_drawable(draw
);
491 struct dri3_screen
*psc
;
496 if (!pdraw
->base
.psc
)
499 psc
= (struct dri3_screen
*) pdraw
->base
.psc
;
501 (void) __glXInitialize(psc
->base
.dpy
);
503 loader_dri3_flush(draw
, __DRI2_FLUSH_DRAWABLE
, __DRI2_THROTTLE_FLUSHFRONT
);
505 (*psc
->f
->invalidate
)(driDrawable
);
506 loader_dri3_wait_gl(draw
);
510 * Make sure all pending swapbuffers have been submitted to hardware
512 * \param driDrawable[in] Pointer to the dri drawable whose swaps we are
514 * \param loaderPrivate[in] Pointer to the corresponding struct
515 * loader_dri_drawable.
518 dri3_flush_swap_buffers(__DRIdrawable
*driDrawable
, void *loaderPrivate
)
520 struct loader_dri3_drawable
*draw
= loaderPrivate
;
521 struct dri3_drawable
*pdraw
= loader_drawable_to_dri3_drawable(draw
);
522 struct dri3_screen
*psc
;
527 if (!pdraw
->base
.psc
)
530 psc
= (struct dri3_screen
*) pdraw
->base
.psc
;
532 (void) __glXInitialize(psc
->base
.dpy
);
533 loader_dri3_swapbuffer_barrier(draw
);
537 dri_set_background_context(void *loaderPrivate
)
539 struct dri3_context
*pcp
= (struct dri3_context
*)loaderPrivate
;
540 __glXSetCurrentContext(&pcp
->base
);
544 dri_is_thread_safe(void *loaderPrivate
)
546 /* Unlike DRI2, DRI3 doesn't call GetBuffers/GetBuffersWithFormat
547 * during draw so we're safe here.
552 /* The image loader extension record for DRI3
554 static const __DRIimageLoaderExtension imageLoaderExtension
= {
555 .base
= { __DRI_IMAGE_LOADER
, 3 },
557 .getBuffers
= loader_dri3_get_buffers
,
558 .flushFrontBuffer
= dri3_flush_front_buffer
,
559 .flushSwapBuffers
= dri3_flush_swap_buffers
,
562 const __DRIuseInvalidateExtension dri3UseInvalidate
= {
563 .base
= { __DRI_USE_INVALIDATE
, 1 }
566 static const __DRIbackgroundCallableExtension driBackgroundCallable
= {
567 .base
= { __DRI_BACKGROUND_CALLABLE
, 2 },
569 .setBackgroundContext
= dri_set_background_context
,
570 .isThreadSafe
= dri_is_thread_safe
,
573 static const __DRIextension
*loader_extensions
[] = {
574 &imageLoaderExtension
.base
,
575 &dri3UseInvalidate
.base
,
576 &driBackgroundCallable
.base
,
580 /** dri3_swap_buffers
582 * Make the current back buffer visible using the present extension
585 dri3_swap_buffers(__GLXDRIdrawable
*pdraw
, int64_t target_msc
, int64_t divisor
,
586 int64_t remainder
, Bool flush
)
588 struct dri3_drawable
*priv
= (struct dri3_drawable
*) pdraw
;
589 unsigned flags
= __DRI2_FLUSH_DRAWABLE
;
592 flags
|= __DRI2_FLUSH_CONTEXT
;
594 return loader_dri3_swap_buffers_msc(&priv
->loader_drawable
,
595 target_msc
, divisor
, remainder
,
600 dri3_get_buffer_age(__GLXDRIdrawable
*pdraw
)
602 struct dri3_drawable
*priv
= (struct dri3_drawable
*)pdraw
;
604 return loader_dri3_query_buffer_age(&priv
->loader_drawable
);
607 /** dri3_destroy_screen
610 dri3_destroy_screen(struct glx_screen
*base
)
612 struct dri3_screen
*psc
= (struct dri3_screen
*) base
;
614 /* Free the direct rendering per screen data */
615 loader_dri3_close_screen(psc
->driScreen
);
616 (*psc
->core
->destroyScreen
) (psc
->driScreen
);
617 driDestroyConfigs(psc
->driver_configs
);
622 /** dri3_set_swap_interval
624 * Record the application swap interval specification,
627 dri3_set_swap_interval(__GLXDRIdrawable
*pdraw
, int interval
)
629 assert(pdraw
!= NULL
);
631 struct dri3_drawable
*priv
= (struct dri3_drawable
*) pdraw
;
632 GLint vblank_mode
= DRI_CONF_VBLANK_DEF_INTERVAL_1
;
633 struct dri3_screen
*psc
= (struct dri3_screen
*) priv
->base
.psc
;
636 psc
->config
->configQueryi(psc
->driScreen
,
637 "vblank_mode", &vblank_mode
);
639 switch (vblank_mode
) {
640 case DRI_CONF_VBLANK_NEVER
:
642 return GLX_BAD_VALUE
;
644 case DRI_CONF_VBLANK_ALWAYS_SYNC
:
646 return GLX_BAD_VALUE
;
652 priv
->swap_interval
= interval
;
653 loader_dri3_set_swap_interval(&priv
->loader_drawable
, interval
);
658 /** dri3_get_swap_interval
660 * Return the stored swap interval
663 dri3_get_swap_interval(__GLXDRIdrawable
*pdraw
)
665 assert(pdraw
!= NULL
);
667 struct dri3_drawable
*priv
= (struct dri3_drawable
*) pdraw
;
669 return priv
->swap_interval
;
673 dri3_bind_tex_image(Display
* dpy
,
674 GLXDrawable drawable
,
675 int buffer
, const int *attrib_list
)
677 struct glx_context
*gc
= __glXGetCurrentContext();
678 struct dri3_context
*pcp
= (struct dri3_context
*) gc
;
679 __GLXDRIdrawable
*base
= GetGLXDRIDrawable(dpy
, drawable
);
680 struct dri3_drawable
*pdraw
= (struct dri3_drawable
*) base
;
681 struct dri3_screen
*psc
;
684 psc
= (struct dri3_screen
*) base
->psc
;
686 (*psc
->f
->invalidate
)(pdraw
->loader_drawable
.dri_drawable
);
690 (*psc
->texBuffer
->setTexBuffer2
) (pcp
->driContext
,
691 pdraw
->base
.textureTarget
,
692 pdraw
->base
.textureFormat
,
693 pdraw
->loader_drawable
.dri_drawable
);
698 dri3_release_tex_image(Display
* dpy
, GLXDrawable drawable
, int buffer
)
700 struct glx_context
*gc
= __glXGetCurrentContext();
701 struct dri3_context
*pcp
= (struct dri3_context
*) gc
;
702 __GLXDRIdrawable
*base
= GetGLXDRIDrawable(dpy
, drawable
);
703 struct dri3_drawable
*pdraw
= (struct dri3_drawable
*) base
;
704 struct dri3_screen
*psc
;
707 psc
= (struct dri3_screen
*) base
->psc
;
709 if (psc
->texBuffer
->base
.version
>= 3 &&
710 psc
->texBuffer
->releaseTexBuffer
!= NULL
)
711 (*psc
->texBuffer
->releaseTexBuffer
) (pcp
->driContext
,
712 pdraw
->base
.textureTarget
,
713 pdraw
->loader_drawable
.dri_drawable
);
717 static const struct glx_context_vtable dri3_context_vtable
= {
718 .destroy
= dri3_destroy_context
,
719 .bind
= dri3_bind_context
,
720 .unbind
= dri3_unbind_context
,
721 .wait_gl
= dri3_wait_gl
,
722 .wait_x
= dri3_wait_x
,
723 .use_x_font
= DRI_glXUseXFont
,
724 .bind_tex_image
= dri3_bind_tex_image
,
725 .release_tex_image
= dri3_release_tex_image
,
726 .get_proc_address
= NULL
,
727 .interop_query_device_info
= dri3_interop_query_device_info
,
728 .interop_export_object
= dri3_interop_export_object
731 /** dri3_bind_extensions
733 * Enable all of the extensions supported on DRI3
736 dri3_bind_extensions(struct dri3_screen
*psc
, struct glx_display
* priv
,
737 const char *driverName
)
739 const __DRIextension
**extensions
;
743 extensions
= psc
->core
->getExtensions(psc
->driScreen
);
745 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_swap_control");
746 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_swap_control");
747 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_make_current_read");
748 __glXEnableDirectExtension(&psc
->base
, "GLX_INTEL_swap_event");
750 mask
= psc
->image_driver
->getAPIMask(psc
->driScreen
);
752 __glXEnableDirectExtension(&psc
->base
, "GLX_ARB_create_context");
753 __glXEnableDirectExtension(&psc
->base
, "GLX_ARB_create_context_profile");
755 if ((mask
& ((1 << __DRI_API_GLES
) |
756 (1 << __DRI_API_GLES2
) |
757 (1 << __DRI_API_GLES3
))) != 0) {
758 __glXEnableDirectExtension(&psc
->base
,
759 "GLX_EXT_create_context_es_profile");
760 __glXEnableDirectExtension(&psc
->base
,
761 "GLX_EXT_create_context_es2_profile");
764 for (i
= 0; extensions
[i
]; i
++) {
765 /* when on a different gpu than the server, the server pixmaps
766 * can have a tiling mode we can't read. Thus we can't create
767 * a texture from them.
769 if (!psc
->is_different_gpu
&&
770 (strcmp(extensions
[i
]->name
, __DRI_TEX_BUFFER
) == 0)) {
771 psc
->texBuffer
= (__DRItexBufferExtension
*) extensions
[i
];
772 __glXEnableDirectExtension(&psc
->base
, "GLX_EXT_texture_from_pixmap");
775 if ((strcmp(extensions
[i
]->name
, __DRI2_FLUSH
) == 0)) {
776 psc
->f
= (__DRI2flushExtension
*) extensions
[i
];
777 /* internal driver extension, no GL extension exposed */
780 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE
) == 0)
781 psc
->image
= (__DRIimageExtension
*) extensions
[i
];
783 if ((strcmp(extensions
[i
]->name
, __DRI2_CONFIG_QUERY
) == 0))
784 psc
->config
= (__DRI2configQueryExtension
*) extensions
[i
];
786 if (strcmp(extensions
[i
]->name
, __DRI2_ROBUSTNESS
) == 0)
787 __glXEnableDirectExtension(&psc
->base
,
788 "GLX_ARB_create_context_robustness");
790 if (strcmp(extensions
[i
]->name
, __DRI2_NO_ERROR
) == 0)
791 __glXEnableDirectExtension(&psc
->base
,
792 "GLX_ARB_create_context_no_error");
794 if (strcmp(extensions
[i
]->name
, __DRI2_RENDERER_QUERY
) == 0) {
795 psc
->rendererQuery
= (__DRI2rendererQueryExtension
*) extensions
[i
];
796 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_query_renderer");
799 if (strcmp(extensions
[i
]->name
, __DRI2_INTEROP
) == 0)
800 psc
->interop
= (__DRI2interopExtension
*)extensions
[i
];
802 if (strcmp(extensions
[i
]->name
, __DRI2_FLUSH_CONTROL
) == 0)
803 __glXEnableDirectExtension(&psc
->base
,
804 "GLX_ARB_context_flush_control");
808 static const struct glx_screen_vtable dri3_screen_vtable
= {
809 .create_context
= dri3_create_context
,
810 .create_context_attribs
= dri3_create_context_attribs
,
811 .query_renderer_integer
= dri3_query_renderer_integer
,
812 .query_renderer_string
= dri3_query_renderer_string
,
815 /** dri3_create_screen
817 * Initialize DRI3 on the specified screen.
819 * Opens the DRI device, locates the appropriate DRI driver
822 * Checks to see if the driver supports the necessary extensions
824 * Initializes the driver for the screen and sets up our structures
827 static struct glx_screen
*
828 dri3_create_screen(int screen
, struct glx_display
* priv
)
830 xcb_connection_t
*c
= XGetXCBConnection(priv
->dpy
);
831 const __DRIconfig
**driver_configs
;
832 const __DRIextension
**extensions
;
833 const struct dri3_display
*const pdp
= (struct dri3_display
*)
835 struct dri3_screen
*psc
;
837 struct glx_config
*configs
= NULL
, *visuals
= NULL
;
838 char *driverName
, *tmp
;
840 unsigned char disable
;
842 psc
= calloc(1, sizeof *psc
);
848 if (!glx_screen_init(&psc
->base
, screen
, priv
)) {
853 psc
->fd
= loader_dri3_open(c
, RootWindow(priv
->dpy
, screen
), None
);
855 int conn_error
= xcb_connection_has_error(c
);
857 glx_screen_cleanup(&psc
->base
);
859 InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen
);
862 ErrorMessageF("Connection closed during DRI3 initialization failure");
867 psc
->fd
= loader_get_user_preferred_fd(psc
->fd
, &psc
->is_different_gpu
);
869 driverName
= loader_get_driver_for_fd(psc
->fd
);
871 ErrorMessageF("No driver found\n");
875 extensions
= driOpenDriver(driverName
, &psc
->driver
);
876 if (extensions
== NULL
)
879 for (i
= 0; extensions
[i
]; i
++) {
880 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
881 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
882 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_DRIVER
) == 0)
883 psc
->image_driver
= (__DRIimageDriverExtension
*) extensions
[i
];
887 if (psc
->core
== NULL
) {
888 ErrorMessageF("core dri driver extension not found\n");
892 if (psc
->image_driver
== NULL
) {
893 ErrorMessageF("image driver extension not found\n");
898 psc
->image_driver
->createNewScreen2(screen
, psc
->fd
,
899 pdp
->loader_extensions
,
901 &driver_configs
, psc
);
903 if (psc
->driScreen
== NULL
) {
904 ErrorMessageF("failed to create dri screen\n");
908 dri3_bind_extensions(psc
, priv
, driverName
);
910 if (!psc
->image
|| psc
->image
->base
.version
< 7 || !psc
->image
->createImageFromFds
) {
911 ErrorMessageF("Version 7 or imageFromFds image extension not found\n");
915 if (!psc
->f
|| psc
->f
->base
.version
< 4) {
916 ErrorMessageF("Version 4 or later of flush extension not found\n");
920 if (psc
->is_different_gpu
&& psc
->image
->base
.version
< 9) {
921 ErrorMessageF("Different GPU, but image extension version 9 or later not found\n");
925 if (psc
->is_different_gpu
&& !psc
->image
->blitImage
) {
926 ErrorMessageF("Different GPU, but blitImage not implemented for this driver\n");
930 if (!psc
->is_different_gpu
&& (
931 !psc
->texBuffer
|| psc
->texBuffer
->base
.version
< 2 ||
932 !psc
->texBuffer
->setTexBuffer2
934 ErrorMessageF("Version 2 or later of texBuffer extension not found\n");
938 psc
->loader_dri3_ext
.core
= psc
->core
;
939 psc
->loader_dri3_ext
.image_driver
= psc
->image_driver
;
940 psc
->loader_dri3_ext
.flush
= psc
->f
;
941 psc
->loader_dri3_ext
.tex_buffer
= psc
->texBuffer
;
942 psc
->loader_dri3_ext
.image
= psc
->image
;
943 psc
->loader_dri3_ext
.config
= psc
->config
;
945 configs
= driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
946 visuals
= driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
948 if (!configs
|| !visuals
) {
949 ErrorMessageF("No matching fbConfigs or visuals found\n");
953 glx_config_destroy_list(psc
->base
.configs
);
954 psc
->base
.configs
= configs
;
955 glx_config_destroy_list(psc
->base
.visuals
);
956 psc
->base
.visuals
= visuals
;
958 psc
->driver_configs
= driver_configs
;
960 psc
->base
.vtable
= &dri3_screen_vtable
;
962 psc
->base
.driScreen
= psp
;
963 psp
->destroyScreen
= dri3_destroy_screen
;
964 psp
->createDrawable
= dri3_create_drawable
;
965 psp
->swapBuffers
= dri3_swap_buffers
;
967 psp
->getDrawableMSC
= dri3_drawable_get_msc
;
968 psp
->waitForMSC
= dri3_wait_for_msc
;
969 psp
->waitForSBC
= dri3_wait_for_sbc
;
970 psp
->setSwapInterval
= dri3_set_swap_interval
;
971 psp
->getSwapInterval
= dri3_get_swap_interval
;
972 if (psc
->config
->configQueryb(psc
->driScreen
,
973 "glx_disable_oml_sync_control",
974 &disable
) || !disable
)
975 __glXEnableDirectExtension(&psc
->base
, "GLX_OML_sync_control");
977 if (psc
->config
->configQueryb(psc
->driScreen
,
978 "glx_disable_sgi_video_sync",
979 &disable
) || !disable
)
980 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_video_sync");
982 psp
->copySubBuffer
= dri3_copy_sub_buffer
;
983 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_copy_sub_buffer");
985 psp
->getBufferAge
= dri3_get_buffer_age
;
986 if (psc
->config
->configQueryb(psc
->driScreen
,
987 "glx_disable_ext_buffer_age",
988 &disable
) || !disable
)
989 __glXEnableDirectExtension(&psc
->base
, "GLX_EXT_buffer_age");
993 tmp
= getenv("LIBGL_SHOW_FPS");
994 psc
->show_fps_interval
= tmp
? atoi(tmp
) : 0;
995 if (psc
->show_fps_interval
< 0)
996 psc
->show_fps_interval
= 0;
998 InfoMessageF("Using DRI3 for screen %d\n", screen
);
1003 CriticalErrorMessageF("failed to load driver: %s\n", driverName
);
1006 glx_config_destroy_list(configs
);
1008 glx_config_destroy_list(visuals
);
1010 psc
->core
->destroyScreen(psc
->driScreen
);
1011 psc
->driScreen
= NULL
;
1015 dlclose(psc
->driver
);
1018 glx_screen_cleanup(&psc
->base
);
1024 /** dri_destroy_display
1026 * Called from __glXFreeDisplayPrivate.
1029 dri3_destroy_display(__GLXDRIdisplay
* dpy
)
1034 /* Only request versions of these protocols which we actually support. */
1035 #define DRI3_SUPPORTED_MAJOR 1
1036 #define PRESENT_SUPPORTED_MAJOR 1
1038 #ifdef HAVE_DRI3_MODIFIERS
1039 #define DRI3_SUPPORTED_MINOR 2
1040 #define PRESENT_SUPPORTED_MINOR 2
1042 #define PRESENT_SUPPORTED_MINOR 0
1043 #define DRI3_SUPPORTED_MINOR 0
1046 /** dri3_create_display
1048 * Allocate, initialize and return a __DRIdisplayPrivate object.
1049 * This is called from __glXInitialize() when we are given a new
1050 * display pointer. This is public to that function, but hidden from
1053 _X_HIDDEN __GLXDRIdisplay
*
1054 dri3_create_display(Display
* dpy
)
1056 struct dri3_display
*pdp
;
1057 xcb_connection_t
*c
= XGetXCBConnection(dpy
);
1058 xcb_dri3_query_version_cookie_t dri3_cookie
;
1059 xcb_dri3_query_version_reply_t
*dri3_reply
;
1060 xcb_present_query_version_cookie_t present_cookie
;
1061 xcb_present_query_version_reply_t
*present_reply
;
1062 xcb_generic_error_t
*error
;
1063 const xcb_query_extension_reply_t
*extension
;
1065 xcb_prefetch_extension_data(c
, &xcb_dri3_id
);
1066 xcb_prefetch_extension_data(c
, &xcb_present_id
);
1068 extension
= xcb_get_extension_data(c
, &xcb_dri3_id
);
1069 if (!(extension
&& extension
->present
))
1072 extension
= xcb_get_extension_data(c
, &xcb_present_id
);
1073 if (!(extension
&& extension
->present
))
1076 dri3_cookie
= xcb_dri3_query_version(c
,
1077 DRI3_SUPPORTED_MAJOR
,
1078 DRI3_SUPPORTED_MINOR
);
1079 present_cookie
= xcb_present_query_version(c
,
1080 PRESENT_SUPPORTED_MAJOR
,
1081 PRESENT_SUPPORTED_MINOR
);
1083 pdp
= malloc(sizeof *pdp
);
1087 dri3_reply
= xcb_dri3_query_version_reply(c
, dri3_cookie
, &error
);
1093 pdp
->dri3Major
= dri3_reply
->major_version
;
1094 pdp
->dri3Minor
= dri3_reply
->minor_version
;
1097 present_reply
= xcb_present_query_version_reply(c
, present_cookie
, &error
);
1098 if (!present_reply
) {
1102 pdp
->presentMajor
= present_reply
->major_version
;
1103 pdp
->presentMinor
= present_reply
->minor_version
;
1104 free(present_reply
);
1106 pdp
->base
.destroyDisplay
= dri3_destroy_display
;
1107 pdp
->base
.createScreen
= dri3_create_screen
;
1109 loader_set_logger(dri_message
);
1111 pdp
->loader_extensions
= loader_extensions
;
1119 #endif /* GLX_DIRECT_RENDERING */