1 /**************************************************************************
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Kevin E. Martin <kevin@precisioninsight.com>
31 * Brian Paul <brian@precisioninsight.com>
35 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
38 #include <X11/extensions/Xfixes.h>
39 #include <X11/extensions/Xdamage.h>
40 #include "glxclient.h"
43 #include "dri_sarea.h"
45 #include <sys/types.h>
48 #include "dri_common.h"
55 ** XFree86-DRI version information
64 struct glx_screen base
;
66 __DRIscreen
*driScreen
;
67 __GLXDRIscreen vtable
;
68 const __DRIlegacyExtension
*legacy
;
69 const __DRIcoreExtension
*core
;
70 const __DRIswapControlExtension
*swapControl
;
71 const __DRImediaStreamCounterExtension
*msc
;
72 const __DRIconfig
**driver_configs
;
73 const __DRIcopySubBufferExtension
*driCopySubBuffer
;
81 struct glx_context base
;
82 __DRIcontext
*driContext
;
88 __GLXDRIdrawable base
;
90 __DRIdrawable
*driDrawable
;
94 * Given a display pointer and screen number, determine the name of
95 * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
96 * Return True for success, False for failure.
99 driGetDriverName(Display
* dpy
, int scrNum
, char **driverName
)
104 int driverMajor
, driverMinor
, driverPatch
;
108 if (XF86DRIQueryExtension(dpy
, &event
, &error
)) { /* DRI1 */
109 if (!XF86DRIQueryDirectRenderingCapable(dpy
, scrNum
, &directCapable
)) {
110 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
113 if (!directCapable
) {
114 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
118 b
= XF86DRIGetClientDriverName(dpy
, scrNum
, &driverMajor
, &driverMinor
,
119 &driverPatch
, driverName
);
121 ErrorMessageF("Cannot determine driver name for screen %d\n",
126 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
127 driverMajor
, driverMinor
, driverPatch
, *driverName
,
132 else if (DRI2QueryExtension(dpy
, &event
, &error
)) { /* DRI2 */
134 Bool ret
= DRI2Connect(dpy
, RootWindow(dpy
, scrNum
), driverName
, &dev
);
146 * Exported function for querying the DRI driver for a given screen.
148 * The returned char pointer points to a static array that will be
149 * overwritten by subsequent calls.
151 _GLX_PUBLIC
const char *
152 glXGetScreenDriver(Display
* dpy
, int scrNum
)
156 if (driGetDriverName(dpy
, scrNum
, &driverName
)) {
160 len
= strlen(driverName
);
163 memcpy(ret
, driverName
, len
+ 1);
170 /* glXGetDriverConfig must return a pointer with a static lifetime. To avoid
171 * keeping drivers loaded and other leaks, we keep a cache of results here that
172 * is cleared by an atexit handler.
174 struct driver_config_entry
{
175 struct driver_config_entry
*next
;
180 static pthread_mutex_t driver_config_mutex
= PTHREAD_MUTEX_INITIALIZER
;
181 static struct driver_config_entry
*driver_config_cache
= NULL
;
183 /* Called as an atexit function. Otherwise, this would have to be called with
184 * driver_config_mutex locked.
187 clear_driver_config_cache()
189 while (driver_config_cache
) {
190 struct driver_config_entry
*e
= driver_config_cache
;
191 driver_config_cache
= e
->next
;
200 get_driver_config(const char *driverName
)
202 void *handle
= driOpenDriver(driverName
);
203 const __DRIextension
**extensions
;
210 extensions
= driGetDriverExtensions(handle
, driverName
);
212 for (int i
= 0; extensions
[i
]; i
++) {
213 if (strcmp(extensions
[i
]->name
, __DRI_CONFIG_OPTIONS
) != 0)
216 __DRIconfigOptionsExtension
*ext
=
217 (__DRIconfigOptionsExtension
*)extensions
[i
];
219 if (ext
->base
.version
>= 2)
220 config
= ext
->getXml(driverName
);
222 config
= strdup(ext
->xml
);
229 /* Fall back to the old method */
230 config
= dlsym(handle
, "__driConfigOptions");
232 config
= strdup(config
);
241 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
243 * The returned char pointer points directly into the driver. Therefore
244 * it should be treated as a constant.
246 * If the driver was not found or does not support configuration NULL is
249 _GLX_PUBLIC
const char *
250 glXGetDriverConfig(const char *driverName
)
252 struct driver_config_entry
*e
;
254 pthread_mutex_lock(&driver_config_mutex
);
256 for (e
= driver_config_cache
; e
; e
= e
->next
) {
257 if (strcmp(e
->driverName
, driverName
) == 0)
261 e
= malloc(sizeof(*e
));
265 e
->config
= get_driver_config(driverName
);
266 e
->driverName
= strdup(driverName
);
267 if (!e
->config
|| !e
->driverName
) {
275 e
->next
= driver_config_cache
;
276 driver_config_cache
= e
;
279 atexit(clear_driver_config_cache
);
282 pthread_mutex_unlock(&driver_config_mutex
);
284 return e
? e
->config
: NULL
;
288 has_damage_post(Display
* dpy
)
290 static GLboolean inited
= GL_FALSE
;
291 static GLboolean has_damage
;
296 if (XDamageQueryVersion(dpy
, &major
, &minor
) &&
297 major
== 1 && minor
>= 1) {
298 has_damage
= GL_TRUE
;
301 has_damage
= GL_FALSE
;
310 __glXReportDamage(__DRIdrawable
* driDraw
,
312 drm_clip_rect_t
* rects
, int num_rects
,
313 GLboolean front_buffer
, void *loaderPrivate
)
316 XserverRegion region
;
319 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
320 struct glx_screen
*psc
= glxDraw
->psc
;
321 Display
*dpy
= psc
->dpy
;
324 if (!has_damage_post(dpy
))
330 drawable
= RootWindow(dpy
, psc
->scr
);
335 drawable
= glxDraw
->xDrawable
;
338 xrects
= malloc(sizeof(XRectangle
) * num_rects
);
342 for (i
= 0; i
< num_rects
; i
++) {
343 xrects
[i
].x
= rects
[i
].x1
+ x_off
;
344 xrects
[i
].y
= rects
[i
].y1
+ y_off
;
345 xrects
[i
].width
= rects
[i
].x2
- rects
[i
].x1
;
346 xrects
[i
].height
= rects
[i
].y2
- rects
[i
].y1
;
348 region
= XFixesCreateRegion(dpy
, xrects
, num_rects
);
350 XDamageAdd(dpy
, drawable
, region
);
351 XFixesDestroyRegion(dpy
, region
);
354 static const __DRIdamageExtension damageExtension
= {
355 .base
= {__DRI_DAMAGE
, 1 },
357 .reportDamage
= __glXReportDamage
,
361 __glXDRIGetDrawableInfo(__DRIdrawable
* drawable
,
362 unsigned int *index
, unsigned int *stamp
,
363 int *X
, int *Y
, int *W
, int *H
,
364 int *numClipRects
, drm_clip_rect_t
** pClipRects
,
365 int *backX
, int *backY
,
366 int *numBackClipRects
,
367 drm_clip_rect_t
** pBackClipRects
,
370 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
371 struct glx_screen
*psc
= glxDraw
->psc
;
372 Display
*dpy
= psc
->dpy
;
374 return XF86DRIGetDrawableInfo(dpy
, psc
->scr
, glxDraw
->drawable
,
375 index
, stamp
, X
, Y
, W
, H
,
376 numClipRects
, pClipRects
,
378 numBackClipRects
, pBackClipRects
);
381 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension
= {
382 .base
= {__DRI_GET_DRAWABLE_INFO
, 1 },
384 .getDrawableInfo
= __glXDRIGetDrawableInfo
387 static const __DRIextension
*loader_extensions
[] = {
388 &systemTimeExtension
.base
,
389 &getDrawableInfoExtension
.base
,
390 #ifdef XDAMAGE_1_1_INTERFACE
391 &damageExtension
.base
,
397 * Perform the required libGL-side initialization and call the client-side
398 * driver's \c __driCreateNewScreen function.
400 * \param dpy Display pointer.
401 * \param scrn Screen number on the display.
402 * \param psc DRI screen information.
403 * \param driDpy DRI display information.
404 * \param createNewScreen Pointer to the client-side driver's
405 * \c __driCreateNewScreen function.
406 * \returns A pointer to the \c __DRIscreen structure returned by
407 * the client-side driver on success, or \c NULL on failure.
410 CallCreateNewScreen(Display
*dpy
, int scrn
, struct dri_screen
*psc
,
411 struct dri_display
* driDpy
)
415 drmAddress pSAREA
= MAP_FAILED
;
417 __DRIversion ddx_version
;
418 __DRIversion dri_version
;
419 __DRIversion drm_version
;
420 __DRIframebuffer framebuffer
;
425 drmVersionPtr version
;
430 const __DRIconfig
**driver_configs
;
431 struct glx_config
*visual
, *configs
= NULL
, *visuals
= NULL
;
433 /* DRI protocol version. */
434 dri_version
.major
= driDpy
->driMajor
;
435 dri_version
.minor
= driDpy
->driMinor
;
436 dri_version
.patch
= driDpy
->driPatch
;
438 framebuffer
.base
= MAP_FAILED
;
439 framebuffer
.dev_priv
= NULL
;
440 framebuffer
.size
= 0;
442 if (!XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
443 ErrorMessageF("XF86DRIOpenConnection failed\n");
447 fd
= drmOpenOnce(NULL
, BusID
, &newlyopened
);
449 free(BusID
); /* No longer needed */
452 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd
));
456 if (drmGetMagic(fd
, &magic
)) {
457 ErrorMessageF("drmGetMagic failed\n");
461 version
= drmGetVersion(fd
);
463 drm_version
.major
= version
->version_major
;
464 drm_version
.minor
= version
->version_minor
;
465 drm_version
.patch
= version
->version_patchlevel
;
466 drmFreeVersion(version
);
469 drm_version
.major
= -1;
470 drm_version
.minor
= -1;
471 drm_version
.patch
= -1;
474 if (newlyopened
&& !XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
475 ErrorMessageF("XF86DRIAuthConnection failed\n");
479 /* Get device name (like "radeon") and the ddx version numbers.
480 * We'll check the version in each DRI driver's "createNewScreen"
482 if (!XF86DRIGetClientDriverName(dpy
, scrn
,
485 &ddx_version
.patch
, &driverName
)) {
486 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
490 free(driverName
); /* No longer needed. */
493 * Get device-specific info. pDevPriv will point to a struct
494 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
495 * has information about the screen size, depth, pitch, ancilliary
496 * buffers, DRM mmap handles, etc.
498 if (!XF86DRIGetDeviceInfo(dpy
, scrn
, &hFB
, &junk
,
499 &framebuffer
.size
, &framebuffer
.stride
,
500 &framebuffer
.dev_priv_size
,
501 &framebuffer
.dev_priv
)) {
502 ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
506 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
507 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
509 /* Map the framebuffer region. */
510 status
= drmMap(fd
, hFB
, framebuffer
.size
,
511 (drmAddressPtr
) & framebuffer
.base
);
513 ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status
));
517 /* Map the SAREA region. Further mmap regions may be setup in
518 * each DRI driver's "createNewScreen" function.
520 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
522 ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status
));
526 psp
= (*psc
->legacy
->createNewScreen
) (scrn
,
534 &driver_configs
, psc
);
537 ErrorMessageF("Calling driver entry point failed\n");
541 configs
= driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
542 visuals
= driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
544 if (!configs
|| !visuals
) {
545 ErrorMessageF("No matching fbConfigs or visuals found\n");
549 glx_config_destroy_list(psc
->base
.configs
);
550 psc
->base
.configs
= configs
;
551 glx_config_destroy_list(psc
->base
.visuals
);
552 psc
->base
.visuals
= visuals
;
554 psc
->driver_configs
= driver_configs
;
556 /* Visuals with depth != screen depth are subject to automatic compositing
557 * in the X server, so DRI1 can't render to them properly. Mark them as
558 * non-conformant to prevent apps from picking them up accidentally.
560 for (visual
= psc
->base
.visuals
; visual
; visual
= visual
->next
) {
562 XVisualInfo
*visuals
;
566 templ
.visualid
= visual
->visualID
;
568 visuals
= XGetVisualInfo(dpy
, mask
, &templ
, &num_visuals
);
571 if (num_visuals
> 0 && visuals
->depth
!= DefaultDepth(dpy
, scrn
))
572 visual
->visualRating
= GLX_NON_CONFORMANT_CONFIG
;
582 glx_config_destroy_list(configs
);
584 glx_config_destroy_list(visuals
);
586 if (pSAREA
!= MAP_FAILED
)
587 drmUnmap(pSAREA
, SAREA_MAX
);
589 if (framebuffer
.base
!= MAP_FAILED
)
590 drmUnmap((drmAddress
) framebuffer
.base
, framebuffer
.size
);
592 free(framebuffer
.dev_priv
);
597 XF86DRICloseConnection(dpy
, scrn
);
599 ErrorMessageF("reverting to software direct rendering\n");
605 dri_destroy_context(struct glx_context
* context
)
607 struct dri_context
*pcp
= (struct dri_context
*) context
;
608 struct dri_screen
*psc
= (struct dri_screen
*) context
->psc
;
610 driReleaseDrawables(&pcp
->base
);
612 free((char *) context
->extensions
);
614 (*psc
->core
->destroyContext
) (pcp
->driContext
);
616 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
621 dri_bind_context(struct glx_context
*context
, struct glx_context
*old
,
622 GLXDrawable draw
, GLXDrawable read
)
624 struct dri_context
*pcp
= (struct dri_context
*) context
;
625 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
626 struct dri_drawable
*pdraw
, *pread
;
628 pdraw
= (struct dri_drawable
*) driFetchDrawable(context
, draw
);
629 pread
= (struct dri_drawable
*) driFetchDrawable(context
, read
);
631 driReleaseDrawables(&pcp
->base
);
633 if (pdraw
== NULL
|| pread
== NULL
)
634 return GLXBadDrawable
;
636 if ((*psc
->core
->bindContext
) (pcp
->driContext
,
637 pdraw
->driDrawable
, pread
->driDrawable
))
640 return GLXBadContext
;
644 dri_unbind_context(struct glx_context
*context
, struct glx_context
*new)
646 struct dri_context
*pcp
= (struct dri_context
*) context
;
647 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
649 (*psc
->core
->unbindContext
) (pcp
->driContext
);
652 static const struct glx_context_vtable dri_context_vtable
= {
653 .destroy
= dri_destroy_context
,
654 .bind
= dri_bind_context
,
655 .unbind
= dri_unbind_context
,
658 .use_x_font
= DRI_glXUseXFont
,
659 .bind_tex_image
= NULL
,
660 .release_tex_image
= NULL
,
661 .get_proc_address
= NULL
,
664 static struct glx_context
*
665 dri_create_context(struct glx_screen
*base
,
666 struct glx_config
*config_base
,
667 struct glx_context
*shareList
, int renderType
)
669 struct dri_context
*pcp
, *pcp_shared
;
670 struct dri_screen
*psc
= (struct dri_screen
*) base
;
671 drm_context_t hwContext
;
672 __DRIcontext
*shared
= NULL
;
673 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
675 if (!psc
->base
.driScreen
)
678 /* Check the renderType value */
679 if (!validate_renderType_against_config(config_base
, renderType
))
683 /* If the shareList context is not a DRI context, we cannot possibly
684 * create a DRI context that shares it.
686 if (shareList
->vtable
->destroy
!= dri_destroy_context
) {
690 pcp_shared
= (struct dri_context
*) shareList
;
691 shared
= pcp_shared
->driContext
;
694 pcp
= calloc(1, sizeof *pcp
);
698 if (!glx_context_init(&pcp
->base
, &psc
->base
, &config
->base
)) {
703 pcp
->base
.renderType
= renderType
;
705 if (!XF86DRICreateContextWithConfig(psc
->base
.dpy
, psc
->base
.scr
,
706 config
->base
.visualID
,
707 &pcp
->hwContextID
, &hwContext
)) {
713 (*psc
->legacy
->createNewContext
) (psc
->driScreen
,
715 renderType
, shared
, hwContext
, pcp
);
716 if (pcp
->driContext
== NULL
) {
717 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
722 pcp
->base
.vtable
= &dri_context_vtable
;
728 driDestroyDrawable(__GLXDRIdrawable
* pdraw
)
730 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
731 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
733 (*psc
->core
->destroyDrawable
) (pdp
->driDrawable
);
734 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, pdraw
->drawable
);
738 static __GLXDRIdrawable
*
739 driCreateDrawable(struct glx_screen
*base
,
741 GLXDrawable drawable
, struct glx_config
*config_base
)
743 drm_drawable_t hwDrawable
;
744 void *empty_attribute_list
= NULL
;
745 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
746 struct dri_screen
*psc
= (struct dri_screen
*) base
;
747 struct dri_drawable
*pdp
;
749 /* Old dri can't handle GLX 1.3+ drawable constructors. */
750 if (xDrawable
!= drawable
)
753 pdp
= calloc(1, sizeof *pdp
);
757 pdp
->base
.drawable
= drawable
;
758 pdp
->base
.psc
= &psc
->base
;
760 if (!XF86DRICreateDrawable(psc
->base
.dpy
, psc
->base
.scr
,
761 drawable
, &hwDrawable
)) {
766 /* Create a new drawable */
768 (*psc
->legacy
->createNewDrawable
) (psc
->driScreen
,
772 empty_attribute_list
, pdp
);
774 if (!pdp
->driDrawable
) {
775 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, drawable
);
780 pdp
->base
.destroyDrawable
= driDestroyDrawable
;
786 driSwapBuffers(__GLXDRIdrawable
* pdraw
, int64_t unused1
, int64_t unused2
,
787 int64_t unused3
, Bool flush
)
789 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
790 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
796 (*psc
->core
->swapBuffers
) (pdp
->driDrawable
);
801 driCopySubBuffer(__GLXDRIdrawable
* pdraw
,
802 int x
, int y
, int width
, int height
, Bool flush
)
804 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
805 struct dri_screen
*psc
= (struct dri_screen
*) pdp
->base
.psc
;
811 (*psc
->driCopySubBuffer
->copySubBuffer
) (pdp
->driDrawable
,
812 x
, y
, width
, height
);
816 driDestroyScreen(struct glx_screen
*base
)
818 struct dri_screen
*psc
= (struct dri_screen
*) base
;
820 /* Free the direct rendering per screen data */
822 (*psc
->core
->destroyScreen
) (psc
->driScreen
);
823 driDestroyConfigs(psc
->driver_configs
);
824 psc
->driScreen
= NULL
;
826 dlclose(psc
->driver
);
830 driSetSwapInterval(__GLXDRIdrawable
*pdraw
, int interval
)
832 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
835 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
837 if (psc
->swapControl
!= NULL
) {
838 psc
->swapControl
->setSwapInterval(pdp
->driDrawable
, interval
);
842 return GLX_BAD_CONTEXT
;
846 driGetSwapInterval(__GLXDRIdrawable
*pdraw
)
848 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
851 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
853 if (psc
->swapControl
!= NULL
)
854 return psc
->swapControl
->getSwapInterval(pdp
->driDrawable
);
859 /* Bind DRI1 specific extensions */
861 driBindExtensions(struct dri_screen
*psc
, const __DRIextension
**extensions
)
865 for (i
= 0; extensions
[i
]; i
++) {
866 /* No DRI2 support for swap_control at the moment, since SwapBuffers
867 * is done by the X server */
868 if (strcmp(extensions
[i
]->name
, __DRI_SWAP_CONTROL
) == 0) {
869 psc
->swapControl
= (__DRIswapControlExtension
*) extensions
[i
];
870 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_swap_control");
871 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_swap_control");
874 if (strcmp(extensions
[i
]->name
, __DRI_MEDIA_STREAM_COUNTER
) == 0) {
875 psc
->msc
= (__DRImediaStreamCounterExtension
*) extensions
[i
];
876 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_video_sync");
879 if (strcmp(extensions
[i
]->name
, __DRI_COPY_SUB_BUFFER
) == 0) {
880 psc
->driCopySubBuffer
= (__DRIcopySubBufferExtension
*) extensions
[i
];
881 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_copy_sub_buffer");
884 if (strcmp(extensions
[i
]->name
, __DRI_READ_DRAWABLE
) == 0) {
885 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_make_current_read");
887 /* Ignore unknown extensions */
891 static const struct glx_screen_vtable dri_screen_vtable
= {
892 .create_context
= dri_create_context
,
893 .create_context_attribs
= NULL
,
894 .query_renderer_integer
= NULL
,
895 .query_renderer_string
= NULL
,
898 static struct glx_screen
*
899 driCreateScreen(int screen
, struct glx_display
*priv
)
901 struct dri_display
*pdp
;
903 const __DRIextension
**extensions
;
904 struct dri_screen
*psc
;
908 psc
= calloc(1, sizeof *psc
);
912 if (!glx_screen_init(&psc
->base
, screen
, priv
)) {
917 if (!driGetDriverName(priv
->dpy
, screen
, &driverName
)) {
921 psc
->driver
= driOpenDriver(driverName
);
922 if (psc
->driver
== NULL
)
925 extensions
= dlsym(psc
->driver
, __DRI_DRIVER_EXTENSIONS
);
926 if (extensions
== NULL
) {
927 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
931 for (i
= 0; extensions
[i
]; i
++) {
932 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
933 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
934 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
935 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
938 if (psc
->core
== NULL
|| psc
->legacy
== NULL
)
941 pdp
= (struct dri_display
*) priv
->driDisplay
;
943 CallCreateNewScreen(psc
->base
.dpy
, screen
, psc
, pdp
);
944 if (psc
->driScreen
== NULL
)
947 extensions
= psc
->core
->getExtensions(psc
->driScreen
);
948 driBindExtensions(psc
, extensions
);
950 psc
->base
.vtable
= &dri_screen_vtable
;
952 psc
->base
.driScreen
= psp
;
953 if (psc
->driCopySubBuffer
)
954 psp
->copySubBuffer
= driCopySubBuffer
;
956 psp
->destroyScreen
= driDestroyScreen
;
957 psp
->createDrawable
= driCreateDrawable
;
958 psp
->swapBuffers
= driSwapBuffers
;
960 psp
->setSwapInterval
= driSetSwapInterval
;
961 psp
->getSwapInterval
= driGetSwapInterval
;
968 CriticalErrorMessageF("failed to load driver: %s\n", driverName
);
973 dlclose(psc
->driver
);
974 glx_screen_cleanup(&psc
->base
);
980 /* Called from __glXFreeDisplayPrivate.
983 driDestroyDisplay(__GLXDRIdisplay
* dpy
)
989 * Allocate, initialize and return a __DRIdisplayPrivate object.
990 * This is called from __glXInitialize() when we are given a new
993 _X_HIDDEN __GLXDRIdisplay
*
994 driCreateDisplay(Display
* dpy
)
996 struct dri_display
*pdpyp
;
997 int eventBase
, errorBase
;
998 int major
, minor
, patch
;
1000 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
1004 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
1008 pdpyp
= malloc(sizeof *pdpyp
);
1013 pdpyp
->driMajor
= major
;
1014 pdpyp
->driMinor
= minor
;
1015 pdpyp
->driPatch
= patch
;
1017 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
1018 pdpyp
->base
.createScreen
= driCreateScreen
;
1020 return &pdpyp
->base
;
1023 #endif /* GLX_DIRECT_RENDERING */