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"
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
;
93 static const struct glx_context_vtable dri_context_vtable
;
96 * Given a display pointer and screen number, determine the name of
97 * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
98 * Return True for success, False for failure.
101 driGetDriverName(Display
* dpy
, int scrNum
, char **driverName
)
106 int driverMajor
, driverMinor
, driverPatch
;
110 if (XF86DRIQueryExtension(dpy
, &event
, &error
)) { /* DRI1 */
111 if (!XF86DRIQueryDirectRenderingCapable(dpy
, scrNum
, &directCapable
)) {
112 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
115 if (!directCapable
) {
116 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
120 b
= XF86DRIGetClientDriverName(dpy
, scrNum
, &driverMajor
, &driverMinor
,
121 &driverPatch
, driverName
);
123 ErrorMessageF("Cannot determine driver name for screen %d\n",
128 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
129 driverMajor
, driverMinor
, driverPatch
, *driverName
,
134 else if (DRI2QueryExtension(dpy
, &event
, &error
)) { /* DRI2 */
136 Bool ret
= DRI2Connect(dpy
, RootWindow(dpy
, scrNum
), driverName
, &dev
);
148 * Exported function for querying the DRI driver for a given screen.
150 * The returned char pointer points to a static array that will be
151 * overwritten by subsequent calls.
153 _X_EXPORT
const char *
154 glXGetScreenDriver(Display
* dpy
, int scrNum
)
158 if (driGetDriverName(dpy
, scrNum
, &driverName
)) {
162 len
= strlen(driverName
);
165 memcpy(ret
, driverName
, len
+ 1);
173 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
175 * The returned char pointer points directly into the driver. Therefore
176 * it should be treated as a constant.
178 * If the driver was not found or does not support configuration NULL is
181 * Note: The driver remains opened after this function returns.
183 _X_EXPORT
const char *
184 glXGetDriverConfig(const char *driverName
)
186 void *handle
= driOpenDriver(driverName
);
188 return dlsym(handle
, "__driConfigOptions");
193 #ifdef XDAMAGE_1_1_INTERFACE
196 has_damage_post(Display
* dpy
)
198 static GLboolean inited
= GL_FALSE
;
199 static GLboolean has_damage
;
204 if (XDamageQueryVersion(dpy
, &major
, &minor
) &&
205 major
== 1 && minor
>= 1) {
206 has_damage
= GL_TRUE
;
209 has_damage
= GL_FALSE
;
218 __glXReportDamage(__DRIdrawable
* driDraw
,
220 drm_clip_rect_t
* rects
, int num_rects
,
221 GLboolean front_buffer
, void *loaderPrivate
)
224 XserverRegion region
;
227 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
228 struct glx_screen
*psc
= glxDraw
->psc
;
229 Display
*dpy
= psc
->dpy
;
232 if (!has_damage_post(dpy
))
238 drawable
= RootWindow(dpy
, psc
->scr
);
243 drawable
= glxDraw
->xDrawable
;
246 xrects
= malloc(sizeof(XRectangle
) * num_rects
);
250 for (i
= 0; i
< num_rects
; i
++) {
251 xrects
[i
].x
= rects
[i
].x1
+ x_off
;
252 xrects
[i
].y
= rects
[i
].y1
+ y_off
;
253 xrects
[i
].width
= rects
[i
].x2
- rects
[i
].x1
;
254 xrects
[i
].height
= rects
[i
].y2
- rects
[i
].y1
;
256 region
= XFixesCreateRegion(dpy
, xrects
, num_rects
);
258 XDamageAdd(dpy
, drawable
, region
);
259 XFixesDestroyRegion(dpy
, region
);
262 static const __DRIdamageExtension damageExtension
= {
263 {__DRI_DAMAGE
, __DRI_DAMAGE_VERSION
},
270 __glXDRIGetDrawableInfo(__DRIdrawable
* drawable
,
271 unsigned int *index
, unsigned int *stamp
,
272 int *X
, int *Y
, int *W
, int *H
,
273 int *numClipRects
, drm_clip_rect_t
** pClipRects
,
274 int *backX
, int *backY
,
275 int *numBackClipRects
,
276 drm_clip_rect_t
** pBackClipRects
,
279 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
280 struct glx_screen
*psc
= glxDraw
->psc
;
281 Display
*dpy
= psc
->dpy
;
283 return XF86DRIGetDrawableInfo(dpy
, psc
->scr
, glxDraw
->drawable
,
284 index
, stamp
, X
, Y
, W
, H
,
285 numClipRects
, pClipRects
,
287 numBackClipRects
, pBackClipRects
);
290 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension
= {
291 {__DRI_GET_DRAWABLE_INFO
, __DRI_GET_DRAWABLE_INFO_VERSION
},
292 __glXDRIGetDrawableInfo
295 static const __DRIextension
*loader_extensions
[] = {
296 &systemTimeExtension
.base
,
297 &getDrawableInfoExtension
.base
,
298 #ifdef XDAMAGE_1_1_INTERFACE
299 &damageExtension
.base
,
305 * Perform the required libGL-side initialization and call the client-side
306 * driver's \c __driCreateNewScreen function.
308 * \param dpy Display pointer.
309 * \param scrn Screen number on the display.
310 * \param psc DRI screen information.
311 * \param driDpy DRI display information.
312 * \param createNewScreen Pointer to the client-side driver's
313 * \c __driCreateNewScreen function.
314 * \returns A pointer to the \c __DRIscreen structure returned by
315 * the client-side driver on success, or \c NULL on failure.
318 CallCreateNewScreen(Display
*dpy
, int scrn
, struct dri_screen
*psc
,
319 struct dri_display
* driDpy
)
323 drmAddress pSAREA
= MAP_FAILED
;
325 __DRIversion ddx_version
;
326 __DRIversion dri_version
;
327 __DRIversion drm_version
;
328 __DRIframebuffer framebuffer
;
333 drmVersionPtr version
;
338 const __DRIconfig
**driver_configs
;
339 struct glx_config
*visual
, *configs
= NULL
, *visuals
= NULL
;
341 /* DRI protocol version. */
342 dri_version
.major
= driDpy
->driMajor
;
343 dri_version
.minor
= driDpy
->driMinor
;
344 dri_version
.patch
= driDpy
->driPatch
;
346 framebuffer
.base
= MAP_FAILED
;
347 framebuffer
.dev_priv
= NULL
;
348 framebuffer
.size
= 0;
350 if (!XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
351 ErrorMessageF("XF86DRIOpenConnection failed\n");
355 fd
= drmOpenOnce(NULL
, BusID
, &newlyopened
);
357 Xfree(BusID
); /* No longer needed */
360 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd
));
364 if (drmGetMagic(fd
, &magic
)) {
365 ErrorMessageF("drmGetMagic failed\n");
369 version
= drmGetVersion(fd
);
371 drm_version
.major
= version
->version_major
;
372 drm_version
.minor
= version
->version_minor
;
373 drm_version
.patch
= version
->version_patchlevel
;
374 drmFreeVersion(version
);
377 drm_version
.major
= -1;
378 drm_version
.minor
= -1;
379 drm_version
.patch
= -1;
382 if (newlyopened
&& !XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
383 ErrorMessageF("XF86DRIAuthConnection failed\n");
387 /* Get device name (like "radeon") and the ddx version numbers.
388 * We'll check the version in each DRI driver's "createNewScreen"
390 if (!XF86DRIGetClientDriverName(dpy
, scrn
,
393 &ddx_version
.patch
, &driverName
)) {
394 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
398 Xfree(driverName
); /* No longer needed. */
401 * Get device-specific info. pDevPriv will point to a struct
402 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
403 * has information about the screen size, depth, pitch, ancilliary
404 * buffers, DRM mmap handles, etc.
406 if (!XF86DRIGetDeviceInfo(dpy
, scrn
, &hFB
, &junk
,
407 &framebuffer
.size
, &framebuffer
.stride
,
408 &framebuffer
.dev_priv_size
,
409 &framebuffer
.dev_priv
)) {
410 ErrorMessageF("XF86DRIGetDeviceInfo failed");
414 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
415 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
417 /* Map the framebuffer region. */
418 status
= drmMap(fd
, hFB
, framebuffer
.size
,
419 (drmAddressPtr
) & framebuffer
.base
);
421 ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status
));
425 /* Map the SAREA region. Further mmap regions may be setup in
426 * each DRI driver's "createNewScreen" function.
428 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
430 ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status
));
434 psp
= (*psc
->legacy
->createNewScreen
) (scrn
,
442 &driver_configs
, psc
);
445 ErrorMessageF("Calling driver entry point failed");
449 configs
= driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
450 visuals
= driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
452 if (!configs
|| !visuals
)
455 glx_config_destroy_list(psc
->base
.configs
);
456 psc
->base
.configs
= configs
;
457 glx_config_destroy_list(psc
->base
.visuals
);
458 psc
->base
.visuals
= visuals
;
460 psc
->driver_configs
= driver_configs
;
462 /* Visuals with depth != screen depth are subject to automatic compositing
463 * in the X server, so DRI1 can't render to them properly. Mark them as
464 * non-conformant to prevent apps from picking them up accidentally.
466 for (visual
= psc
->base
.visuals
; visual
; visual
= visual
->next
) {
467 XVisualInfo
template;
468 XVisualInfo
*visuals
;
472 template.visualid
= visual
->visualID
;
474 visuals
= XGetVisualInfo(dpy
, mask
, &template, &num_visuals
);
477 if (num_visuals
> 0 && visuals
->depth
!= DefaultDepth(dpy
, scrn
))
478 visual
->visualRating
= GLX_NON_CONFORMANT_CONFIG
;
488 glx_config_destroy_list(configs
);
490 glx_config_destroy_list(visuals
);
492 if (pSAREA
!= MAP_FAILED
)
493 drmUnmap(pSAREA
, SAREA_MAX
);
495 if (framebuffer
.base
!= MAP_FAILED
)
496 drmUnmap((drmAddress
) framebuffer
.base
, framebuffer
.size
);
498 if (framebuffer
.dev_priv
!= NULL
)
499 Xfree(framebuffer
.dev_priv
);
504 XF86DRICloseConnection(dpy
, scrn
);
506 ErrorMessageF("reverting to software direct rendering\n");
512 dri_destroy_context(struct glx_context
* context
)
514 struct dri_context
*pcp
= (struct dri_context
*) context
;
515 struct dri_screen
*psc
= (struct dri_screen
*) context
->psc
;
517 driReleaseDrawables(&pcp
->base
);
520 glx_send_destroy_context(psc
->base
.dpy
, context
->xid
);
522 if (context
->extensions
)
523 XFree((char *) context
->extensions
);
525 (*psc
->core
->destroyContext
) (pcp
->driContext
);
527 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
532 dri_bind_context(struct glx_context
*context
, struct glx_context
*old
,
533 GLXDrawable draw
, GLXDrawable read
)
535 struct dri_context
*pcp
= (struct dri_context
*) context
;
536 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
537 struct dri_drawable
*pdraw
, *pread
;
539 pdraw
= (struct dri_drawable
*) driFetchDrawable(context
, draw
);
540 pread
= (struct dri_drawable
*) driFetchDrawable(context
, read
);
542 driReleaseDrawables(&pcp
->base
);
544 if (pdraw
== NULL
|| pread
== NULL
)
545 return GLXBadDrawable
;
547 if ((*psc
->core
->bindContext
) (pcp
->driContext
,
548 pdraw
->driDrawable
, pread
->driDrawable
))
551 return GLXBadContext
;
555 dri_unbind_context(struct glx_context
*context
, struct glx_context
*new)
557 struct dri_context
*pcp
= (struct dri_context
*) context
;
558 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
560 (*psc
->core
->unbindContext
) (pcp
->driContext
);
563 static const struct glx_context_vtable dri_context_vtable
= {
572 NULL
, /* get_proc_address */
575 static struct glx_context
*
576 dri_create_context(struct glx_screen
*base
,
577 struct glx_config
*config_base
,
578 struct glx_context
*shareList
, int renderType
)
580 struct dri_context
*pcp
, *pcp_shared
;
581 struct dri_screen
*psc
= (struct dri_screen
*) base
;
582 drm_context_t hwContext
;
583 __DRIcontext
*shared
= NULL
;
584 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
586 if (!psc
->base
.driScreen
)
590 /* If the shareList context is not a DRI context, we cannot possibly
591 * create a DRI context that shares it.
593 if (shareList
->vtable
->destroy
!= dri_destroy_context
) {
597 pcp_shared
= (struct dri_context
*) shareList
;
598 shared
= pcp_shared
->driContext
;
601 pcp
= Xmalloc(sizeof *pcp
);
605 memset(pcp
, 0, sizeof *pcp
);
606 if (!glx_context_init(&pcp
->base
, &psc
->base
, &config
->base
)) {
611 if (!XF86DRICreateContextWithConfig(psc
->base
.dpy
, psc
->base
.scr
,
612 config
->base
.visualID
,
613 &pcp
->hwContextID
, &hwContext
)) {
619 (*psc
->legacy
->createNewContext
) (psc
->driScreen
,
621 renderType
, shared
, hwContext
, pcp
);
622 if (pcp
->driContext
== NULL
) {
623 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
628 pcp
->base
.vtable
= &dri_context_vtable
;
634 driDestroyDrawable(__GLXDRIdrawable
* pdraw
)
636 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
637 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
639 (*psc
->core
->destroyDrawable
) (pdp
->driDrawable
);
640 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, pdraw
->drawable
);
644 static __GLXDRIdrawable
*
645 driCreateDrawable(struct glx_screen
*base
,
647 GLXDrawable drawable
, struct glx_config
*config_base
)
649 drm_drawable_t hwDrawable
;
650 void *empty_attribute_list
= NULL
;
651 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
652 struct dri_screen
*psc
= (struct dri_screen
*) base
;
653 struct dri_drawable
*pdp
;
655 /* Old dri can't handle GLX 1.3+ drawable constructors. */
656 if (xDrawable
!= drawable
)
659 pdp
= Xmalloc(sizeof *pdp
);
663 memset(pdp
, 0, sizeof *pdp
);
664 pdp
->base
.drawable
= drawable
;
665 pdp
->base
.psc
= &psc
->base
;
667 if (!XF86DRICreateDrawable(psc
->base
.dpy
, psc
->base
.scr
,
668 drawable
, &hwDrawable
)) {
673 /* Create a new drawable */
675 (*psc
->legacy
->createNewDrawable
) (psc
->driScreen
,
679 empty_attribute_list
, pdp
);
681 if (!pdp
->driDrawable
) {
682 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, drawable
);
687 pdp
->base
.destroyDrawable
= driDestroyDrawable
;
693 driSwapBuffers(__GLXDRIdrawable
* pdraw
, int64_t unused1
, int64_t unused2
,
696 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
697 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
699 (*psc
->core
->swapBuffers
) (pdp
->driDrawable
);
704 driCopySubBuffer(__GLXDRIdrawable
* pdraw
,
705 int x
, int y
, int width
, int height
)
707 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
708 struct dri_screen
*psc
= (struct dri_screen
*) pdp
->base
.psc
;
710 (*psc
->driCopySubBuffer
->copySubBuffer
) (pdp
->driDrawable
,
711 x
, y
, width
, height
);
715 driDestroyScreen(struct glx_screen
*base
)
717 struct dri_screen
*psc
= (struct dri_screen
*) base
;
719 /* Free the direct rendering per screen data */
721 (*psc
->core
->destroyScreen
) (psc
->driScreen
);
722 driDestroyConfigs(psc
->driver_configs
);
723 psc
->driScreen
= NULL
;
725 dlclose(psc
->driver
);
728 #ifdef __DRI_SWAP_BUFFER_COUNTER
731 driDrawableGetMSC(struct glx_screen
*base
, __GLXDRIdrawable
*pdraw
,
732 int64_t *ust
, int64_t *msc
, int64_t *sbc
)
734 struct dri_screen
*psc
= (struct dri_screen
*) base
;
735 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
737 if (pdp
&& psc
->sbc
&& psc
->msc
)
738 return ( (*psc
->msc
->getMSC
)(psc
->driScreen
, msc
) == 0 &&
739 (*psc
->sbc
->getSBC
)(pdp
->driDrawable
, sbc
) == 0 &&
740 __glXGetUST(ust
) == 0 );
744 driWaitForMSC(__GLXDRIdrawable
*pdraw
, int64_t target_msc
, int64_t divisor
,
745 int64_t remainder
, int64_t *ust
, int64_t *msc
, int64_t *sbc
)
747 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
748 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
750 if (pdp
!= NULL
&& psc
->msc
!= NULL
) {
751 ret
= (*psc
->msc
->waitForMSC
) (pdp
->driDrawable
, target_msc
,
752 divisor
, remainder
, msc
, sbc
);
754 /* __glXGetUST returns zero on success and non-zero on failure.
755 * This function returns True on success and False on failure.
757 return ret
== 0 && __glXGetUST(ust
) == 0;
762 driWaitForSBC(__GLXDRIdrawable
*pdraw
, int64_t target_sbc
, int64_t *ust
,
763 int64_t *msc
, int64_t *sbc
)
765 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
767 if (pdp
!= NULL
&& psc
->sbc
!= NULL
) {
769 (*psc
->sbc
->waitForSBC
) (pdp
->driDrawable
, target_sbc
, msc
, sbc
);
771 /* __glXGetUST returns zero on success and non-zero on failure.
772 * This function returns True on success and False on failure.
774 return ((ret
== 0) && (__glXGetUST(ust
) == 0));
777 return DRI2WaitSBC(pdp
->base
.psc
->dpy
,
778 pdp
->base
.xDrawable
, target_sbc
, ust
, msc
, sbc
);
784 driSetSwapInterval(__GLXDRIdrawable
*pdraw
, int interval
)
786 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
787 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
789 if (psc
->swapControl
!= NULL
&& pdraw
!= NULL
) {
790 psc
->swapControl
->setSwapInterval(pdp
->driDrawable
, interval
);
794 return GLX_BAD_CONTEXT
;
798 driGetSwapInterval(__GLXDRIdrawable
*pdraw
)
800 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
801 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
803 if (psc
->swapControl
!= NULL
&& pdraw
!= NULL
)
804 return psc
->swapControl
->getSwapInterval(pdp
->driDrawable
);
809 /* Bind DRI1 specific extensions */
811 driBindExtensions(struct dri_screen
*psc
, const __DRIextension
**extensions
)
815 for (i
= 0; extensions
[i
]; i
++) {
816 /* No DRI2 support for swap_control at the moment, since SwapBuffers
817 * is done by the X server */
818 if (strcmp(extensions
[i
]->name
, __DRI_SWAP_CONTROL
) == 0) {
819 psc
->swapControl
= (__DRIswapControlExtension
*) extensions
[i
];
820 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_swap_control");
821 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_swap_control");
824 if (strcmp(extensions
[i
]->name
, __DRI_MEDIA_STREAM_COUNTER
) == 0) {
825 psc
->msc
= (__DRImediaStreamCounterExtension
*) extensions
[i
];
826 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_video_sync");
829 if (strcmp(extensions
[i
]->name
, __DRI_COPY_SUB_BUFFER
) == 0) {
830 psc
->driCopySubBuffer
= (__DRIcopySubBufferExtension
*) extensions
[i
];
831 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_copy_sub_buffer");
834 if (strcmp(extensions
[i
]->name
, __DRI_READ_DRAWABLE
) == 0) {
835 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_make_current_read");
837 /* Ignore unknown extensions */
841 static const struct glx_screen_vtable dri_screen_vtable
= {
845 static struct glx_screen
*
846 driCreateScreen(int screen
, struct glx_display
*priv
)
848 struct dri_display
*pdp
;
850 const __DRIextension
**extensions
;
851 struct dri_screen
*psc
;
855 psc
= Xcalloc(1, sizeof *psc
);
859 memset(psc
, 0, sizeof *psc
);
860 if (!glx_screen_init(&psc
->base
, screen
, priv
)) {
865 if (!driGetDriverName(priv
->dpy
, screen
, &driverName
)) {
869 psc
->driver
= driOpenDriver(driverName
);
871 if (psc
->driver
== NULL
)
874 extensions
= dlsym(psc
->driver
, __DRI_DRIVER_EXTENSIONS
);
875 if (extensions
== NULL
) {
876 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
880 for (i
= 0; extensions
[i
]; i
++) {
881 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
882 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
883 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
884 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
887 if (psc
->core
== NULL
|| psc
->legacy
== NULL
)
890 pdp
= (struct dri_display
*) priv
->driDisplay
;
892 CallCreateNewScreen(psc
->base
.dpy
, screen
, psc
, pdp
);
893 if (psc
->driScreen
== NULL
)
896 extensions
= psc
->core
->getExtensions(psc
->driScreen
);
897 driBindExtensions(psc
, extensions
);
899 psc
->base
.vtable
= &dri_screen_vtable
;
901 psc
->base
.driScreen
= psp
;
902 if (psc
->driCopySubBuffer
)
903 psp
->copySubBuffer
= driCopySubBuffer
;
905 psp
->destroyScreen
= driDestroyScreen
;
906 psp
->createDrawable
= driCreateDrawable
;
907 psp
->swapBuffers
= driSwapBuffers
;
909 #ifdef __DRI_SWAP_BUFFER_COUNTER
910 psp
->getDrawableMSC
= driDrawableGetMSC
;
911 psp
->waitForMSC
= driWaitForMSC
;
912 psp
->waitForSBC
= driWaitForSBC
;
915 psp
->setSwapInterval
= driSetSwapInterval
;
916 psp
->getSwapInterval
= driGetSwapInterval
;
922 dlclose(psc
->driver
);
923 glx_screen_cleanup(&psc
->base
);
929 /* Called from __glXFreeDisplayPrivate.
932 driDestroyDisplay(__GLXDRIdisplay
* dpy
)
938 * Allocate, initialize and return a __DRIdisplayPrivate object.
939 * This is called from __glXInitialize() when we are given a new
942 _X_HIDDEN __GLXDRIdisplay
*
943 driCreateDisplay(Display
* dpy
)
945 struct dri_display
*pdpyp
;
946 int eventBase
, errorBase
;
947 int major
, minor
, patch
;
949 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
953 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
957 pdpyp
= Xmalloc(sizeof *pdpyp
);
962 pdpyp
->driMajor
= major
;
963 pdpyp
->driMinor
= minor
;
964 pdpyp
->driPatch
= patch
;
966 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
967 pdpyp
->base
.createScreen
= driCreateScreen
;
972 #endif /* GLX_DIRECT_RENDERING */