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
)
204 const __DRIextension
**extensions
= driOpenDriver(driverName
, &handle
);
206 for (int i
= 0; extensions
[i
]; i
++) {
207 if (strcmp(extensions
[i
]->name
, __DRI_CONFIG_OPTIONS
) != 0)
210 __DRIconfigOptionsExtension
*ext
=
211 (__DRIconfigOptionsExtension
*)extensions
[i
];
213 if (ext
->base
.version
>= 2)
214 config
= ext
->getXml(driverName
);
216 config
= strdup(ext
->xml
);
223 /* Fall back to the old method */
224 config
= dlsym(handle
, "__driConfigOptions");
226 config
= strdup(config
);
235 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
237 * The returned char pointer points directly into the driver. Therefore
238 * it should be treated as a constant.
240 * If the driver was not found or does not support configuration NULL is
243 _GLX_PUBLIC
const char *
244 glXGetDriverConfig(const char *driverName
)
246 struct driver_config_entry
*e
;
248 pthread_mutex_lock(&driver_config_mutex
);
250 for (e
= driver_config_cache
; e
; e
= e
->next
) {
251 if (strcmp(e
->driverName
, driverName
) == 0)
255 e
= malloc(sizeof(*e
));
259 e
->config
= get_driver_config(driverName
);
260 e
->driverName
= strdup(driverName
);
261 if (!e
->config
|| !e
->driverName
) {
269 e
->next
= driver_config_cache
;
270 driver_config_cache
= e
;
273 atexit(clear_driver_config_cache
);
276 pthread_mutex_unlock(&driver_config_mutex
);
278 return e
? e
->config
: NULL
;
282 has_damage_post(Display
* dpy
)
284 static GLboolean inited
= GL_FALSE
;
285 static GLboolean has_damage
;
290 if (XDamageQueryVersion(dpy
, &major
, &minor
) &&
291 major
== 1 && minor
>= 1) {
292 has_damage
= GL_TRUE
;
295 has_damage
= GL_FALSE
;
304 __glXReportDamage(__DRIdrawable
* driDraw
,
306 drm_clip_rect_t
* rects
, int num_rects
,
307 GLboolean front_buffer
, void *loaderPrivate
)
310 XserverRegion region
;
313 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
314 struct glx_screen
*psc
= glxDraw
->psc
;
315 Display
*dpy
= psc
->dpy
;
318 if (!has_damage_post(dpy
))
324 drawable
= RootWindow(dpy
, psc
->scr
);
329 drawable
= glxDraw
->xDrawable
;
332 xrects
= malloc(sizeof(XRectangle
) * num_rects
);
336 for (i
= 0; i
< num_rects
; i
++) {
337 xrects
[i
].x
= rects
[i
].x1
+ x_off
;
338 xrects
[i
].y
= rects
[i
].y1
+ y_off
;
339 xrects
[i
].width
= rects
[i
].x2
- rects
[i
].x1
;
340 xrects
[i
].height
= rects
[i
].y2
- rects
[i
].y1
;
342 region
= XFixesCreateRegion(dpy
, xrects
, num_rects
);
344 XDamageAdd(dpy
, drawable
, region
);
345 XFixesDestroyRegion(dpy
, region
);
348 static const __DRIdamageExtension damageExtension
= {
349 .base
= {__DRI_DAMAGE
, 1 },
351 .reportDamage
= __glXReportDamage
,
355 __glXDRIGetDrawableInfo(__DRIdrawable
* drawable
,
356 unsigned int *index
, unsigned int *stamp
,
357 int *X
, int *Y
, int *W
, int *H
,
358 int *numClipRects
, drm_clip_rect_t
** pClipRects
,
359 int *backX
, int *backY
,
360 int *numBackClipRects
,
361 drm_clip_rect_t
** pBackClipRects
,
364 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
365 struct glx_screen
*psc
= glxDraw
->psc
;
366 Display
*dpy
= psc
->dpy
;
368 return XF86DRIGetDrawableInfo(dpy
, psc
->scr
, glxDraw
->drawable
,
369 index
, stamp
, X
, Y
, W
, H
,
370 numClipRects
, pClipRects
,
372 numBackClipRects
, pBackClipRects
);
375 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension
= {
376 .base
= {__DRI_GET_DRAWABLE_INFO
, 1 },
378 .getDrawableInfo
= __glXDRIGetDrawableInfo
381 static const __DRIextension
*loader_extensions
[] = {
382 &systemTimeExtension
.base
,
383 &getDrawableInfoExtension
.base
,
384 &damageExtension
.base
,
389 * Perform the required libGL-side initialization and call the client-side
390 * driver's \c __driCreateNewScreen function.
392 * \param dpy Display pointer.
393 * \param scrn Screen number on the display.
394 * \param psc DRI screen information.
395 * \param driDpy DRI display information.
396 * \param createNewScreen Pointer to the client-side driver's
397 * \c __driCreateNewScreen function.
398 * \returns A pointer to the \c __DRIscreen structure returned by
399 * the client-side driver on success, or \c NULL on failure.
402 CallCreateNewScreen(Display
*dpy
, int scrn
, struct dri_screen
*psc
,
403 struct dri_display
* driDpy
)
407 drmAddress pSAREA
= MAP_FAILED
;
409 __DRIversion ddx_version
;
410 __DRIversion dri_version
;
411 __DRIversion drm_version
;
412 __DRIframebuffer framebuffer
;
417 drmVersionPtr version
;
422 const __DRIconfig
**driver_configs
;
423 struct glx_config
*visual
, *configs
= NULL
, *visuals
= NULL
;
425 /* DRI protocol version. */
426 dri_version
.major
= driDpy
->driMajor
;
427 dri_version
.minor
= driDpy
->driMinor
;
428 dri_version
.patch
= driDpy
->driPatch
;
430 framebuffer
.base
= MAP_FAILED
;
431 framebuffer
.dev_priv
= NULL
;
432 framebuffer
.size
= 0;
434 if (!XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
435 ErrorMessageF("XF86DRIOpenConnection failed\n");
439 fd
= drmOpenOnce(NULL
, BusID
, &newlyopened
);
441 free(BusID
); /* No longer needed */
444 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd
));
448 if (drmGetMagic(fd
, &magic
)) {
449 ErrorMessageF("drmGetMagic failed\n");
453 version
= drmGetVersion(fd
);
455 drm_version
.major
= version
->version_major
;
456 drm_version
.minor
= version
->version_minor
;
457 drm_version
.patch
= version
->version_patchlevel
;
458 drmFreeVersion(version
);
461 drm_version
.major
= -1;
462 drm_version
.minor
= -1;
463 drm_version
.patch
= -1;
466 if (newlyopened
&& !XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
467 ErrorMessageF("XF86DRIAuthConnection failed\n");
471 /* Get device name (like "radeon") and the ddx version numbers.
472 * We'll check the version in each DRI driver's "createNewScreen"
474 if (!XF86DRIGetClientDriverName(dpy
, scrn
,
477 &ddx_version
.patch
, &driverName
)) {
478 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
482 free(driverName
); /* No longer needed. */
485 * Get device-specific info. pDevPriv will point to a struct
486 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
487 * has information about the screen size, depth, pitch, ancilliary
488 * buffers, DRM mmap handles, etc.
490 if (!XF86DRIGetDeviceInfo(dpy
, scrn
, &hFB
, &junk
,
491 &framebuffer
.size
, &framebuffer
.stride
,
492 &framebuffer
.dev_priv_size
,
493 &framebuffer
.dev_priv
)) {
494 ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
498 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
499 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
501 /* Map the framebuffer region. */
502 status
= drmMap(fd
, hFB
, framebuffer
.size
,
503 (drmAddressPtr
) & framebuffer
.base
);
505 ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status
));
509 /* Map the SAREA region. Further mmap regions may be setup in
510 * each DRI driver's "createNewScreen" function.
512 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
514 ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status
));
518 psp
= (*psc
->legacy
->createNewScreen
) (scrn
,
526 &driver_configs
, psc
);
529 ErrorMessageF("Calling driver entry point failed\n");
533 configs
= driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
534 visuals
= driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
536 if (!configs
|| !visuals
) {
537 ErrorMessageF("No matching fbConfigs or visuals found\n");
541 glx_config_destroy_list(psc
->base
.configs
);
542 psc
->base
.configs
= configs
;
543 glx_config_destroy_list(psc
->base
.visuals
);
544 psc
->base
.visuals
= visuals
;
546 psc
->driver_configs
= driver_configs
;
548 /* Visuals with depth != screen depth are subject to automatic compositing
549 * in the X server, so DRI1 can't render to them properly. Mark them as
550 * non-conformant to prevent apps from picking them up accidentally.
552 for (visual
= psc
->base
.visuals
; visual
; visual
= visual
->next
) {
554 XVisualInfo
*visuals
;
558 templ
.visualid
= visual
->visualID
;
560 visuals
= XGetVisualInfo(dpy
, mask
, &templ
, &num_visuals
);
563 if (num_visuals
> 0 && visuals
->depth
!= DefaultDepth(dpy
, scrn
))
564 visual
->visualRating
= GLX_NON_CONFORMANT_CONFIG
;
574 glx_config_destroy_list(configs
);
576 glx_config_destroy_list(visuals
);
578 if (pSAREA
!= MAP_FAILED
)
579 drmUnmap(pSAREA
, SAREA_MAX
);
581 if (framebuffer
.base
!= MAP_FAILED
)
582 drmUnmap((drmAddress
) framebuffer
.base
, framebuffer
.size
);
584 free(framebuffer
.dev_priv
);
589 XF86DRICloseConnection(dpy
, scrn
);
591 ErrorMessageF("reverting to software direct rendering\n");
597 dri_destroy_context(struct glx_context
* context
)
599 struct dri_context
*pcp
= (struct dri_context
*) context
;
600 struct dri_screen
*psc
= (struct dri_screen
*) context
->psc
;
602 driReleaseDrawables(&pcp
->base
);
604 free((char *) context
->extensions
);
606 (*psc
->core
->destroyContext
) (pcp
->driContext
);
608 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
613 dri_bind_context(struct glx_context
*context
, struct glx_context
*old
,
614 GLXDrawable draw
, GLXDrawable read
)
616 struct dri_context
*pcp
= (struct dri_context
*) context
;
617 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
618 struct dri_drawable
*pdraw
, *pread
;
620 pdraw
= (struct dri_drawable
*) driFetchDrawable(context
, draw
);
621 pread
= (struct dri_drawable
*) driFetchDrawable(context
, read
);
623 driReleaseDrawables(&pcp
->base
);
625 if (pdraw
== NULL
|| pread
== NULL
)
626 return GLXBadDrawable
;
628 if ((*psc
->core
->bindContext
) (pcp
->driContext
,
629 pdraw
->driDrawable
, pread
->driDrawable
))
632 return GLXBadContext
;
636 dri_unbind_context(struct glx_context
*context
, struct glx_context
*new)
638 struct dri_context
*pcp
= (struct dri_context
*) context
;
639 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
641 (*psc
->core
->unbindContext
) (pcp
->driContext
);
644 static const struct glx_context_vtable dri_context_vtable
= {
645 .destroy
= dri_destroy_context
,
646 .bind
= dri_bind_context
,
647 .unbind
= dri_unbind_context
,
650 .use_x_font
= DRI_glXUseXFont
,
651 .bind_tex_image
= NULL
,
652 .release_tex_image
= NULL
,
653 .get_proc_address
= NULL
,
656 static struct glx_context
*
657 dri_create_context(struct glx_screen
*base
,
658 struct glx_config
*config_base
,
659 struct glx_context
*shareList
, int renderType
)
661 struct dri_context
*pcp
, *pcp_shared
;
662 struct dri_screen
*psc
= (struct dri_screen
*) base
;
663 drm_context_t hwContext
;
664 __DRIcontext
*shared
= NULL
;
665 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
667 if (!psc
->base
.driScreen
)
670 /* Check the renderType value */
671 if (!validate_renderType_against_config(config_base
, renderType
))
675 /* If the shareList context is not a DRI context, we cannot possibly
676 * create a DRI context that shares it.
678 if (shareList
->vtable
->destroy
!= dri_destroy_context
) {
682 pcp_shared
= (struct dri_context
*) shareList
;
683 shared
= pcp_shared
->driContext
;
686 pcp
= calloc(1, sizeof *pcp
);
690 if (!glx_context_init(&pcp
->base
, &psc
->base
, &config
->base
)) {
695 pcp
->base
.renderType
= renderType
;
697 if (!XF86DRICreateContextWithConfig(psc
->base
.dpy
, psc
->base
.scr
,
698 config
->base
.visualID
,
699 &pcp
->hwContextID
, &hwContext
)) {
705 (*psc
->legacy
->createNewContext
) (psc
->driScreen
,
707 renderType
, shared
, hwContext
, pcp
);
708 if (pcp
->driContext
== NULL
) {
709 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
714 pcp
->base
.vtable
= &dri_context_vtable
;
720 driDestroyDrawable(__GLXDRIdrawable
* pdraw
)
722 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
723 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
725 (*psc
->core
->destroyDrawable
) (pdp
->driDrawable
);
726 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, pdraw
->drawable
);
730 static __GLXDRIdrawable
*
731 driCreateDrawable(struct glx_screen
*base
,
733 GLXDrawable drawable
, struct glx_config
*config_base
)
735 drm_drawable_t hwDrawable
;
736 void *empty_attribute_list
= NULL
;
737 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
738 struct dri_screen
*psc
= (struct dri_screen
*) base
;
739 struct dri_drawable
*pdp
;
741 /* Old dri can't handle GLX 1.3+ drawable constructors. */
742 if (xDrawable
!= drawable
)
745 pdp
= calloc(1, sizeof *pdp
);
749 pdp
->base
.drawable
= drawable
;
750 pdp
->base
.psc
= &psc
->base
;
752 if (!XF86DRICreateDrawable(psc
->base
.dpy
, psc
->base
.scr
,
753 drawable
, &hwDrawable
)) {
758 /* Create a new drawable */
760 (*psc
->legacy
->createNewDrawable
) (psc
->driScreen
,
764 empty_attribute_list
, pdp
);
766 if (!pdp
->driDrawable
) {
767 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, drawable
);
772 pdp
->base
.destroyDrawable
= driDestroyDrawable
;
778 driSwapBuffers(__GLXDRIdrawable
* pdraw
, int64_t unused1
, int64_t unused2
,
779 int64_t unused3
, Bool flush
)
781 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
782 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
788 (*psc
->core
->swapBuffers
) (pdp
->driDrawable
);
793 driCopySubBuffer(__GLXDRIdrawable
* pdraw
,
794 int x
, int y
, int width
, int height
, Bool flush
)
796 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
797 struct dri_screen
*psc
= (struct dri_screen
*) pdp
->base
.psc
;
803 (*psc
->driCopySubBuffer
->copySubBuffer
) (pdp
->driDrawable
,
804 x
, y
, width
, height
);
808 driDestroyScreen(struct glx_screen
*base
)
810 struct dri_screen
*psc
= (struct dri_screen
*) base
;
812 /* Free the direct rendering per screen data */
814 (*psc
->core
->destroyScreen
) (psc
->driScreen
);
815 driDestroyConfigs(psc
->driver_configs
);
816 psc
->driScreen
= NULL
;
818 dlclose(psc
->driver
);
822 driSetSwapInterval(__GLXDRIdrawable
*pdraw
, int interval
)
824 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
827 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
829 if (psc
->swapControl
!= NULL
) {
830 psc
->swapControl
->setSwapInterval(pdp
->driDrawable
, interval
);
834 return GLX_BAD_CONTEXT
;
838 driGetSwapInterval(__GLXDRIdrawable
*pdraw
)
840 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
843 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
845 if (psc
->swapControl
!= NULL
)
846 return psc
->swapControl
->getSwapInterval(pdp
->driDrawable
);
851 /* Bind DRI1 specific extensions */
853 driBindExtensions(struct dri_screen
*psc
, const __DRIextension
**extensions
)
857 for (i
= 0; extensions
[i
]; i
++) {
858 /* No DRI2 support for swap_control at the moment, since SwapBuffers
859 * is done by the X server */
860 if (strcmp(extensions
[i
]->name
, __DRI_SWAP_CONTROL
) == 0) {
861 psc
->swapControl
= (__DRIswapControlExtension
*) extensions
[i
];
862 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_swap_control");
863 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_swap_control");
866 if (strcmp(extensions
[i
]->name
, __DRI_MEDIA_STREAM_COUNTER
) == 0) {
867 psc
->msc
= (__DRImediaStreamCounterExtension
*) extensions
[i
];
868 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_video_sync");
871 if (strcmp(extensions
[i
]->name
, __DRI_COPY_SUB_BUFFER
) == 0) {
872 psc
->driCopySubBuffer
= (__DRIcopySubBufferExtension
*) extensions
[i
];
873 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_copy_sub_buffer");
876 if (strcmp(extensions
[i
]->name
, __DRI_READ_DRAWABLE
) == 0) {
877 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_make_current_read");
879 /* Ignore unknown extensions */
883 static const struct glx_screen_vtable dri_screen_vtable
= {
884 .create_context
= dri_create_context
,
885 .create_context_attribs
= NULL
,
886 .query_renderer_integer
= NULL
,
887 .query_renderer_string
= NULL
,
890 static struct glx_screen
*
891 driCreateScreen(int screen
, struct glx_display
*priv
)
893 struct dri_display
*pdp
;
895 const __DRIextension
**extensions
;
896 struct dri_screen
*psc
;
900 psc
= calloc(1, sizeof *psc
);
904 if (!glx_screen_init(&psc
->base
, screen
, priv
)) {
909 if (!driGetDriverName(priv
->dpy
, screen
, &driverName
)) {
913 extensions
= driOpenDriver(driverName
, &psc
->driver
);
914 if (extensions
== NULL
) {
915 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
919 for (i
= 0; extensions
[i
]; i
++) {
920 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
921 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
922 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
923 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
926 if (psc
->core
== NULL
|| psc
->legacy
== NULL
)
929 pdp
= (struct dri_display
*) priv
->driDisplay
;
931 CallCreateNewScreen(psc
->base
.dpy
, screen
, psc
, pdp
);
932 if (psc
->driScreen
== NULL
)
935 extensions
= psc
->core
->getExtensions(psc
->driScreen
);
936 driBindExtensions(psc
, extensions
);
938 psc
->base
.vtable
= &dri_screen_vtable
;
940 psc
->base
.driScreen
= psp
;
941 if (psc
->driCopySubBuffer
)
942 psp
->copySubBuffer
= driCopySubBuffer
;
944 psp
->destroyScreen
= driDestroyScreen
;
945 psp
->createDrawable
= driCreateDrawable
;
946 psp
->swapBuffers
= driSwapBuffers
;
948 psp
->setSwapInterval
= driSetSwapInterval
;
949 psp
->getSwapInterval
= driGetSwapInterval
;
956 CriticalErrorMessageF("failed to load driver: %s\n", driverName
);
961 dlclose(psc
->driver
);
962 glx_screen_cleanup(&psc
->base
);
968 /* Called from __glXFreeDisplayPrivate.
971 driDestroyDisplay(__GLXDRIdisplay
* dpy
)
977 * Allocate, initialize and return a __DRIdisplayPrivate object.
978 * This is called from __glXInitialize() when we are given a new
981 _X_HIDDEN __GLXDRIdisplay
*
982 driCreateDisplay(Display
* dpy
)
984 struct dri_display
*pdpyp
;
985 int eventBase
, errorBase
;
986 int major
, minor
, patch
;
988 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
992 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
996 pdpyp
= malloc(sizeof *pdpyp
);
1001 pdpyp
->driMajor
= major
;
1002 pdpyp
->driMinor
= minor
;
1003 pdpyp
->driPatch
= patch
;
1005 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
1006 pdpyp
->base
.createScreen
= driCreateScreen
;
1008 return &pdpyp
->base
;
1011 #endif /* GLX_DIRECT_RENDERING */