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
);
187 const __DRIextension
**extensions
;
192 extensions
= driGetDriverExtensions(handle
, driverName
);
194 for (int i
= 0; extensions
[i
]; i
++) {
195 if (strcmp(extensions
[i
]->name
, __DRI_CONFIG_OPTIONS
) == 0)
196 return ((__DRIconfigOptionsExtension
*)extensions
[i
])->xml
;
200 /* Fall back to the old method */
201 return dlsym(handle
, "__driConfigOptions");
204 #ifdef XDAMAGE_1_1_INTERFACE
207 has_damage_post(Display
* dpy
)
209 static GLboolean inited
= GL_FALSE
;
210 static GLboolean has_damage
;
215 if (XDamageQueryVersion(dpy
, &major
, &minor
) &&
216 major
== 1 && minor
>= 1) {
217 has_damage
= GL_TRUE
;
220 has_damage
= GL_FALSE
;
229 __glXReportDamage(__DRIdrawable
* driDraw
,
231 drm_clip_rect_t
* rects
, int num_rects
,
232 GLboolean front_buffer
, void *loaderPrivate
)
235 XserverRegion region
;
238 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
239 struct glx_screen
*psc
= glxDraw
->psc
;
240 Display
*dpy
= psc
->dpy
;
243 if (!has_damage_post(dpy
))
249 drawable
= RootWindow(dpy
, psc
->scr
);
254 drawable
= glxDraw
->xDrawable
;
257 xrects
= malloc(sizeof(XRectangle
) * num_rects
);
261 for (i
= 0; i
< num_rects
; i
++) {
262 xrects
[i
].x
= rects
[i
].x1
+ x_off
;
263 xrects
[i
].y
= rects
[i
].y1
+ y_off
;
264 xrects
[i
].width
= rects
[i
].x2
- rects
[i
].x1
;
265 xrects
[i
].height
= rects
[i
].y2
- rects
[i
].y1
;
267 region
= XFixesCreateRegion(dpy
, xrects
, num_rects
);
269 XDamageAdd(dpy
, drawable
, region
);
270 XFixesDestroyRegion(dpy
, region
);
273 static const __DRIdamageExtension damageExtension
= {
274 {__DRI_DAMAGE
, __DRI_DAMAGE_VERSION
},
281 __glXDRIGetDrawableInfo(__DRIdrawable
* drawable
,
282 unsigned int *index
, unsigned int *stamp
,
283 int *X
, int *Y
, int *W
, int *H
,
284 int *numClipRects
, drm_clip_rect_t
** pClipRects
,
285 int *backX
, int *backY
,
286 int *numBackClipRects
,
287 drm_clip_rect_t
** pBackClipRects
,
290 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
291 struct glx_screen
*psc
= glxDraw
->psc
;
292 Display
*dpy
= psc
->dpy
;
294 return XF86DRIGetDrawableInfo(dpy
, psc
->scr
, glxDraw
->drawable
,
295 index
, stamp
, X
, Y
, W
, H
,
296 numClipRects
, pClipRects
,
298 numBackClipRects
, pBackClipRects
);
301 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension
= {
302 .base
= {__DRI_GET_DRAWABLE_INFO
, 1 },
304 .getDrawableInfo
= __glXDRIGetDrawableInfo
307 static const __DRIextension
*loader_extensions
[] = {
308 &systemTimeExtension
.base
,
309 &getDrawableInfoExtension
.base
,
310 #ifdef XDAMAGE_1_1_INTERFACE
311 &damageExtension
.base
,
317 * Perform the required libGL-side initialization and call the client-side
318 * driver's \c __driCreateNewScreen function.
320 * \param dpy Display pointer.
321 * \param scrn Screen number on the display.
322 * \param psc DRI screen information.
323 * \param driDpy DRI display information.
324 * \param createNewScreen Pointer to the client-side driver's
325 * \c __driCreateNewScreen function.
326 * \returns A pointer to the \c __DRIscreen structure returned by
327 * the client-side driver on success, or \c NULL on failure.
330 CallCreateNewScreen(Display
*dpy
, int scrn
, struct dri_screen
*psc
,
331 struct dri_display
* driDpy
)
335 drmAddress pSAREA
= MAP_FAILED
;
337 __DRIversion ddx_version
;
338 __DRIversion dri_version
;
339 __DRIversion drm_version
;
340 __DRIframebuffer framebuffer
;
345 drmVersionPtr version
;
350 const __DRIconfig
**driver_configs
;
351 struct glx_config
*visual
, *configs
= NULL
, *visuals
= NULL
;
353 /* DRI protocol version. */
354 dri_version
.major
= driDpy
->driMajor
;
355 dri_version
.minor
= driDpy
->driMinor
;
356 dri_version
.patch
= driDpy
->driPatch
;
358 framebuffer
.base
= MAP_FAILED
;
359 framebuffer
.dev_priv
= NULL
;
360 framebuffer
.size
= 0;
362 if (!XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
363 ErrorMessageF("XF86DRIOpenConnection failed\n");
367 fd
= drmOpenOnce(NULL
, BusID
, &newlyopened
);
369 free(BusID
); /* No longer needed */
372 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd
));
376 if (drmGetMagic(fd
, &magic
)) {
377 ErrorMessageF("drmGetMagic failed\n");
381 version
= drmGetVersion(fd
);
383 drm_version
.major
= version
->version_major
;
384 drm_version
.minor
= version
->version_minor
;
385 drm_version
.patch
= version
->version_patchlevel
;
386 drmFreeVersion(version
);
389 drm_version
.major
= -1;
390 drm_version
.minor
= -1;
391 drm_version
.patch
= -1;
394 if (newlyopened
&& !XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
395 ErrorMessageF("XF86DRIAuthConnection failed\n");
399 /* Get device name (like "radeon") and the ddx version numbers.
400 * We'll check the version in each DRI driver's "createNewScreen"
402 if (!XF86DRIGetClientDriverName(dpy
, scrn
,
405 &ddx_version
.patch
, &driverName
)) {
406 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
410 free(driverName
); /* No longer needed. */
413 * Get device-specific info. pDevPriv will point to a struct
414 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
415 * has information about the screen size, depth, pitch, ancilliary
416 * buffers, DRM mmap handles, etc.
418 if (!XF86DRIGetDeviceInfo(dpy
, scrn
, &hFB
, &junk
,
419 &framebuffer
.size
, &framebuffer
.stride
,
420 &framebuffer
.dev_priv_size
,
421 &framebuffer
.dev_priv
)) {
422 ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
426 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
427 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
429 /* Map the framebuffer region. */
430 status
= drmMap(fd
, hFB
, framebuffer
.size
,
431 (drmAddressPtr
) & framebuffer
.base
);
433 ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status
));
437 /* Map the SAREA region. Further mmap regions may be setup in
438 * each DRI driver's "createNewScreen" function.
440 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
442 ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status
));
446 psp
= (*psc
->legacy
->createNewScreen
) (scrn
,
454 &driver_configs
, psc
);
457 ErrorMessageF("Calling driver entry point failed\n");
461 configs
= driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
462 visuals
= driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
464 if (!configs
|| !visuals
)
467 glx_config_destroy_list(psc
->base
.configs
);
468 psc
->base
.configs
= configs
;
469 glx_config_destroy_list(psc
->base
.visuals
);
470 psc
->base
.visuals
= visuals
;
472 psc
->driver_configs
= driver_configs
;
474 /* Visuals with depth != screen depth are subject to automatic compositing
475 * in the X server, so DRI1 can't render to them properly. Mark them as
476 * non-conformant to prevent apps from picking them up accidentally.
478 for (visual
= psc
->base
.visuals
; visual
; visual
= visual
->next
) {
479 XVisualInfo
template;
480 XVisualInfo
*visuals
;
484 template.visualid
= visual
->visualID
;
486 visuals
= XGetVisualInfo(dpy
, mask
, &template, &num_visuals
);
489 if (num_visuals
> 0 && visuals
->depth
!= DefaultDepth(dpy
, scrn
))
490 visual
->visualRating
= GLX_NON_CONFORMANT_CONFIG
;
500 glx_config_destroy_list(configs
);
502 glx_config_destroy_list(visuals
);
504 if (pSAREA
!= MAP_FAILED
)
505 drmUnmap(pSAREA
, SAREA_MAX
);
507 if (framebuffer
.base
!= MAP_FAILED
)
508 drmUnmap((drmAddress
) framebuffer
.base
, framebuffer
.size
);
510 free(framebuffer
.dev_priv
);
515 XF86DRICloseConnection(dpy
, scrn
);
517 ErrorMessageF("reverting to software direct rendering\n");
523 dri_destroy_context(struct glx_context
* context
)
525 struct dri_context
*pcp
= (struct dri_context
*) context
;
526 struct dri_screen
*psc
= (struct dri_screen
*) context
->psc
;
528 driReleaseDrawables(&pcp
->base
);
530 free((char *) context
->extensions
);
532 (*psc
->core
->destroyContext
) (pcp
->driContext
);
534 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
539 dri_bind_context(struct glx_context
*context
, struct glx_context
*old
,
540 GLXDrawable draw
, GLXDrawable read
)
542 struct dri_context
*pcp
= (struct dri_context
*) context
;
543 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
544 struct dri_drawable
*pdraw
, *pread
;
546 pdraw
= (struct dri_drawable
*) driFetchDrawable(context
, draw
);
547 pread
= (struct dri_drawable
*) driFetchDrawable(context
, read
);
549 driReleaseDrawables(&pcp
->base
);
551 if (pdraw
== NULL
|| pread
== NULL
)
552 return GLXBadDrawable
;
554 if ((*psc
->core
->bindContext
) (pcp
->driContext
,
555 pdraw
->driDrawable
, pread
->driDrawable
))
558 return GLXBadContext
;
562 dri_unbind_context(struct glx_context
*context
, struct glx_context
*new)
564 struct dri_context
*pcp
= (struct dri_context
*) context
;
565 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
567 (*psc
->core
->unbindContext
) (pcp
->driContext
);
570 static const struct glx_context_vtable dri_context_vtable
= {
579 NULL
, /* get_proc_address */
582 static struct glx_context
*
583 dri_create_context(struct glx_screen
*base
,
584 struct glx_config
*config_base
,
585 struct glx_context
*shareList
, int renderType
)
587 struct dri_context
*pcp
, *pcp_shared
;
588 struct dri_screen
*psc
= (struct dri_screen
*) base
;
589 drm_context_t hwContext
;
590 __DRIcontext
*shared
= NULL
;
591 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
593 if (!psc
->base
.driScreen
)
596 /* Check the renderType value */
597 if (!validate_renderType_against_config(config_base
, renderType
))
601 /* If the shareList context is not a DRI context, we cannot possibly
602 * create a DRI context that shares it.
604 if (shareList
->vtable
->destroy
!= dri_destroy_context
) {
608 pcp_shared
= (struct dri_context
*) shareList
;
609 shared
= pcp_shared
->driContext
;
612 pcp
= calloc(1, sizeof *pcp
);
616 if (!glx_context_init(&pcp
->base
, &psc
->base
, &config
->base
)) {
621 pcp
->base
.renderType
= renderType
;
623 if (!XF86DRICreateContextWithConfig(psc
->base
.dpy
, psc
->base
.scr
,
624 config
->base
.visualID
,
625 &pcp
->hwContextID
, &hwContext
)) {
631 (*psc
->legacy
->createNewContext
) (psc
->driScreen
,
633 renderType
, shared
, hwContext
, pcp
);
634 if (pcp
->driContext
== NULL
) {
635 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
640 pcp
->base
.vtable
= &dri_context_vtable
;
646 driDestroyDrawable(__GLXDRIdrawable
* pdraw
)
648 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
649 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
651 (*psc
->core
->destroyDrawable
) (pdp
->driDrawable
);
652 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, pdraw
->drawable
);
656 static __GLXDRIdrawable
*
657 driCreateDrawable(struct glx_screen
*base
,
659 GLXDrawable drawable
, struct glx_config
*config_base
)
661 drm_drawable_t hwDrawable
;
662 void *empty_attribute_list
= NULL
;
663 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
664 struct dri_screen
*psc
= (struct dri_screen
*) base
;
665 struct dri_drawable
*pdp
;
667 /* Old dri can't handle GLX 1.3+ drawable constructors. */
668 if (xDrawable
!= drawable
)
671 pdp
= calloc(1, sizeof *pdp
);
675 pdp
->base
.drawable
= drawable
;
676 pdp
->base
.psc
= &psc
->base
;
678 if (!XF86DRICreateDrawable(psc
->base
.dpy
, psc
->base
.scr
,
679 drawable
, &hwDrawable
)) {
684 /* Create a new drawable */
686 (*psc
->legacy
->createNewDrawable
) (psc
->driScreen
,
690 empty_attribute_list
, pdp
);
692 if (!pdp
->driDrawable
) {
693 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, drawable
);
698 pdp
->base
.destroyDrawable
= driDestroyDrawable
;
704 driSwapBuffers(__GLXDRIdrawable
* pdraw
, int64_t unused1
, int64_t unused2
,
705 int64_t unused3
, Bool flush
)
707 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
708 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
714 (*psc
->core
->swapBuffers
) (pdp
->driDrawable
);
719 driCopySubBuffer(__GLXDRIdrawable
* pdraw
,
720 int x
, int y
, int width
, int height
, Bool flush
)
722 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
723 struct dri_screen
*psc
= (struct dri_screen
*) pdp
->base
.psc
;
729 (*psc
->driCopySubBuffer
->copySubBuffer
) (pdp
->driDrawable
,
730 x
, y
, width
, height
);
734 driDestroyScreen(struct glx_screen
*base
)
736 struct dri_screen
*psc
= (struct dri_screen
*) base
;
738 /* Free the direct rendering per screen data */
740 (*psc
->core
->destroyScreen
) (psc
->driScreen
);
741 driDestroyConfigs(psc
->driver_configs
);
742 psc
->driScreen
= NULL
;
744 dlclose(psc
->driver
);
748 driSetSwapInterval(__GLXDRIdrawable
*pdraw
, int interval
)
750 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
753 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
755 if (psc
->swapControl
!= NULL
) {
756 psc
->swapControl
->setSwapInterval(pdp
->driDrawable
, interval
);
760 return GLX_BAD_CONTEXT
;
764 driGetSwapInterval(__GLXDRIdrawable
*pdraw
)
766 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
769 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
771 if (psc
->swapControl
!= NULL
)
772 return psc
->swapControl
->getSwapInterval(pdp
->driDrawable
);
777 /* Bind DRI1 specific extensions */
779 driBindExtensions(struct dri_screen
*psc
, const __DRIextension
**extensions
)
783 for (i
= 0; extensions
[i
]; i
++) {
784 /* No DRI2 support for swap_control at the moment, since SwapBuffers
785 * is done by the X server */
786 if (strcmp(extensions
[i
]->name
, __DRI_SWAP_CONTROL
) == 0) {
787 psc
->swapControl
= (__DRIswapControlExtension
*) extensions
[i
];
788 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_swap_control");
789 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_swap_control");
792 if (strcmp(extensions
[i
]->name
, __DRI_MEDIA_STREAM_COUNTER
) == 0) {
793 psc
->msc
= (__DRImediaStreamCounterExtension
*) extensions
[i
];
794 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_video_sync");
797 if (strcmp(extensions
[i
]->name
, __DRI_COPY_SUB_BUFFER
) == 0) {
798 psc
->driCopySubBuffer
= (__DRIcopySubBufferExtension
*) extensions
[i
];
799 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_copy_sub_buffer");
802 if (strcmp(extensions
[i
]->name
, __DRI_READ_DRAWABLE
) == 0) {
803 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_make_current_read");
805 /* Ignore unknown extensions */
809 static const struct glx_screen_vtable dri_screen_vtable
= {
814 static struct glx_screen
*
815 driCreateScreen(int screen
, struct glx_display
*priv
)
817 struct dri_display
*pdp
;
819 const __DRIextension
**extensions
;
820 struct dri_screen
*psc
;
824 psc
= calloc(1, sizeof *psc
);
828 if (!glx_screen_init(&psc
->base
, screen
, priv
)) {
833 if (!driGetDriverName(priv
->dpy
, screen
, &driverName
)) {
837 psc
->driver
= driOpenDriver(driverName
);
838 if (psc
->driver
== NULL
)
841 extensions
= dlsym(psc
->driver
, __DRI_DRIVER_EXTENSIONS
);
842 if (extensions
== NULL
) {
843 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
847 for (i
= 0; extensions
[i
]; i
++) {
848 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
849 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
850 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
851 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
854 if (psc
->core
== NULL
|| psc
->legacy
== NULL
)
857 pdp
= (struct dri_display
*) priv
->driDisplay
;
859 CallCreateNewScreen(psc
->base
.dpy
, screen
, psc
, pdp
);
860 if (psc
->driScreen
== NULL
)
863 extensions
= psc
->core
->getExtensions(psc
->driScreen
);
864 driBindExtensions(psc
, extensions
);
866 psc
->base
.vtable
= &dri_screen_vtable
;
868 psc
->base
.driScreen
= psp
;
869 if (psc
->driCopySubBuffer
)
870 psp
->copySubBuffer
= driCopySubBuffer
;
872 psp
->destroyScreen
= driDestroyScreen
;
873 psp
->createDrawable
= driCreateDrawable
;
874 psp
->swapBuffers
= driSwapBuffers
;
876 psp
->setSwapInterval
= driSetSwapInterval
;
877 psp
->getSwapInterval
= driGetSwapInterval
;
884 CriticalErrorMessageF("failed to load driver: %s\n", driverName
);
889 dlclose(psc
->driver
);
890 glx_screen_cleanup(&psc
->base
);
896 /* Called from __glXFreeDisplayPrivate.
899 driDestroyDisplay(__GLXDRIdisplay
* dpy
)
905 * Allocate, initialize and return a __DRIdisplayPrivate object.
906 * This is called from __glXInitialize() when we are given a new
909 _X_HIDDEN __GLXDRIdisplay
*
910 driCreateDisplay(Display
* dpy
)
912 struct dri_display
*pdpyp
;
913 int eventBase
, errorBase
;
914 int major
, minor
, patch
;
916 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
920 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
924 pdpyp
= malloc(sizeof *pdpyp
);
929 pdpyp
->driMajor
= major
;
930 pdpyp
->driMinor
= minor
;
931 pdpyp
->driPatch
= patch
;
933 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
934 pdpyp
->base
.createScreen
= driCreateScreen
;
939 #endif /* GLX_DIRECT_RENDERING */