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 #ifdef XDAMAGE_1_1_INTERFACE
385 &damageExtension
.base
,
391 * Perform the required libGL-side initialization and call the client-side
392 * driver's \c __driCreateNewScreen function.
394 * \param dpy Display pointer.
395 * \param scrn Screen number on the display.
396 * \param psc DRI screen information.
397 * \param driDpy DRI display information.
398 * \param createNewScreen Pointer to the client-side driver's
399 * \c __driCreateNewScreen function.
400 * \returns A pointer to the \c __DRIscreen structure returned by
401 * the client-side driver on success, or \c NULL on failure.
404 CallCreateNewScreen(Display
*dpy
, int scrn
, struct dri_screen
*psc
,
405 struct dri_display
* driDpy
)
409 drmAddress pSAREA
= MAP_FAILED
;
411 __DRIversion ddx_version
;
412 __DRIversion dri_version
;
413 __DRIversion drm_version
;
414 __DRIframebuffer framebuffer
;
419 drmVersionPtr version
;
424 const __DRIconfig
**driver_configs
;
425 struct glx_config
*visual
, *configs
= NULL
, *visuals
= NULL
;
427 /* DRI protocol version. */
428 dri_version
.major
= driDpy
->driMajor
;
429 dri_version
.minor
= driDpy
->driMinor
;
430 dri_version
.patch
= driDpy
->driPatch
;
432 framebuffer
.base
= MAP_FAILED
;
433 framebuffer
.dev_priv
= NULL
;
434 framebuffer
.size
= 0;
436 if (!XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
437 ErrorMessageF("XF86DRIOpenConnection failed\n");
441 fd
= drmOpenOnce(NULL
, BusID
, &newlyopened
);
443 free(BusID
); /* No longer needed */
446 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd
));
450 if (drmGetMagic(fd
, &magic
)) {
451 ErrorMessageF("drmGetMagic failed\n");
455 version
= drmGetVersion(fd
);
457 drm_version
.major
= version
->version_major
;
458 drm_version
.minor
= version
->version_minor
;
459 drm_version
.patch
= version
->version_patchlevel
;
460 drmFreeVersion(version
);
463 drm_version
.major
= -1;
464 drm_version
.minor
= -1;
465 drm_version
.patch
= -1;
468 if (newlyopened
&& !XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
469 ErrorMessageF("XF86DRIAuthConnection failed\n");
473 /* Get device name (like "radeon") and the ddx version numbers.
474 * We'll check the version in each DRI driver's "createNewScreen"
476 if (!XF86DRIGetClientDriverName(dpy
, scrn
,
479 &ddx_version
.patch
, &driverName
)) {
480 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
484 free(driverName
); /* No longer needed. */
487 * Get device-specific info. pDevPriv will point to a struct
488 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
489 * has information about the screen size, depth, pitch, ancilliary
490 * buffers, DRM mmap handles, etc.
492 if (!XF86DRIGetDeviceInfo(dpy
, scrn
, &hFB
, &junk
,
493 &framebuffer
.size
, &framebuffer
.stride
,
494 &framebuffer
.dev_priv_size
,
495 &framebuffer
.dev_priv
)) {
496 ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
500 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
501 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
503 /* Map the framebuffer region. */
504 status
= drmMap(fd
, hFB
, framebuffer
.size
,
505 (drmAddressPtr
) & framebuffer
.base
);
507 ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status
));
511 /* Map the SAREA region. Further mmap regions may be setup in
512 * each DRI driver's "createNewScreen" function.
514 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
516 ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status
));
520 psp
= (*psc
->legacy
->createNewScreen
) (scrn
,
528 &driver_configs
, psc
);
531 ErrorMessageF("Calling driver entry point failed\n");
535 configs
= driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
536 visuals
= driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
538 if (!configs
|| !visuals
) {
539 ErrorMessageF("No matching fbConfigs or visuals found\n");
543 glx_config_destroy_list(psc
->base
.configs
);
544 psc
->base
.configs
= configs
;
545 glx_config_destroy_list(psc
->base
.visuals
);
546 psc
->base
.visuals
= visuals
;
548 psc
->driver_configs
= driver_configs
;
550 /* Visuals with depth != screen depth are subject to automatic compositing
551 * in the X server, so DRI1 can't render to them properly. Mark them as
552 * non-conformant to prevent apps from picking them up accidentally.
554 for (visual
= psc
->base
.visuals
; visual
; visual
= visual
->next
) {
556 XVisualInfo
*visuals
;
560 templ
.visualid
= visual
->visualID
;
562 visuals
= XGetVisualInfo(dpy
, mask
, &templ
, &num_visuals
);
565 if (num_visuals
> 0 && visuals
->depth
!= DefaultDepth(dpy
, scrn
))
566 visual
->visualRating
= GLX_NON_CONFORMANT_CONFIG
;
576 glx_config_destroy_list(configs
);
578 glx_config_destroy_list(visuals
);
580 if (pSAREA
!= MAP_FAILED
)
581 drmUnmap(pSAREA
, SAREA_MAX
);
583 if (framebuffer
.base
!= MAP_FAILED
)
584 drmUnmap((drmAddress
) framebuffer
.base
, framebuffer
.size
);
586 free(framebuffer
.dev_priv
);
591 XF86DRICloseConnection(dpy
, scrn
);
593 ErrorMessageF("reverting to software direct rendering\n");
599 dri_destroy_context(struct glx_context
* context
)
601 struct dri_context
*pcp
= (struct dri_context
*) context
;
602 struct dri_screen
*psc
= (struct dri_screen
*) context
->psc
;
604 driReleaseDrawables(&pcp
->base
);
606 free((char *) context
->extensions
);
608 (*psc
->core
->destroyContext
) (pcp
->driContext
);
610 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
615 dri_bind_context(struct glx_context
*context
, struct glx_context
*old
,
616 GLXDrawable draw
, GLXDrawable read
)
618 struct dri_context
*pcp
= (struct dri_context
*) context
;
619 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
620 struct dri_drawable
*pdraw
, *pread
;
622 pdraw
= (struct dri_drawable
*) driFetchDrawable(context
, draw
);
623 pread
= (struct dri_drawable
*) driFetchDrawable(context
, read
);
625 driReleaseDrawables(&pcp
->base
);
627 if (pdraw
== NULL
|| pread
== NULL
)
628 return GLXBadDrawable
;
630 if ((*psc
->core
->bindContext
) (pcp
->driContext
,
631 pdraw
->driDrawable
, pread
->driDrawable
))
634 return GLXBadContext
;
638 dri_unbind_context(struct glx_context
*context
, struct glx_context
*new)
640 struct dri_context
*pcp
= (struct dri_context
*) context
;
641 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->base
.psc
;
643 (*psc
->core
->unbindContext
) (pcp
->driContext
);
646 static const struct glx_context_vtable dri_context_vtable
= {
647 .destroy
= dri_destroy_context
,
648 .bind
= dri_bind_context
,
649 .unbind
= dri_unbind_context
,
652 .use_x_font
= DRI_glXUseXFont
,
653 .bind_tex_image
= NULL
,
654 .release_tex_image
= NULL
,
655 .get_proc_address
= NULL
,
658 static struct glx_context
*
659 dri_create_context(struct glx_screen
*base
,
660 struct glx_config
*config_base
,
661 struct glx_context
*shareList
, int renderType
)
663 struct dri_context
*pcp
, *pcp_shared
;
664 struct dri_screen
*psc
= (struct dri_screen
*) base
;
665 drm_context_t hwContext
;
666 __DRIcontext
*shared
= NULL
;
667 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
669 if (!psc
->base
.driScreen
)
672 /* Check the renderType value */
673 if (!validate_renderType_against_config(config_base
, renderType
))
677 /* If the shareList context is not a DRI context, we cannot possibly
678 * create a DRI context that shares it.
680 if (shareList
->vtable
->destroy
!= dri_destroy_context
) {
684 pcp_shared
= (struct dri_context
*) shareList
;
685 shared
= pcp_shared
->driContext
;
688 pcp
= calloc(1, sizeof *pcp
);
692 if (!glx_context_init(&pcp
->base
, &psc
->base
, &config
->base
)) {
697 pcp
->base
.renderType
= renderType
;
699 if (!XF86DRICreateContextWithConfig(psc
->base
.dpy
, psc
->base
.scr
,
700 config
->base
.visualID
,
701 &pcp
->hwContextID
, &hwContext
)) {
707 (*psc
->legacy
->createNewContext
) (psc
->driScreen
,
709 renderType
, shared
, hwContext
, pcp
);
710 if (pcp
->driContext
== NULL
) {
711 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
716 pcp
->base
.vtable
= &dri_context_vtable
;
722 driDestroyDrawable(__GLXDRIdrawable
* pdraw
)
724 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
725 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
727 (*psc
->core
->destroyDrawable
) (pdp
->driDrawable
);
728 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, pdraw
->drawable
);
732 static __GLXDRIdrawable
*
733 driCreateDrawable(struct glx_screen
*base
,
735 GLXDrawable drawable
, struct glx_config
*config_base
)
737 drm_drawable_t hwDrawable
;
738 void *empty_attribute_list
= NULL
;
739 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) config_base
;
740 struct dri_screen
*psc
= (struct dri_screen
*) base
;
741 struct dri_drawable
*pdp
;
743 /* Old dri can't handle GLX 1.3+ drawable constructors. */
744 if (xDrawable
!= drawable
)
747 pdp
= calloc(1, sizeof *pdp
);
751 pdp
->base
.drawable
= drawable
;
752 pdp
->base
.psc
= &psc
->base
;
754 if (!XF86DRICreateDrawable(psc
->base
.dpy
, psc
->base
.scr
,
755 drawable
, &hwDrawable
)) {
760 /* Create a new drawable */
762 (*psc
->legacy
->createNewDrawable
) (psc
->driScreen
,
766 empty_attribute_list
, pdp
);
768 if (!pdp
->driDrawable
) {
769 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, drawable
);
774 pdp
->base
.destroyDrawable
= driDestroyDrawable
;
780 driSwapBuffers(__GLXDRIdrawable
* pdraw
, int64_t unused1
, int64_t unused2
,
781 int64_t unused3
, Bool flush
)
783 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
784 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
790 (*psc
->core
->swapBuffers
) (pdp
->driDrawable
);
795 driCopySubBuffer(__GLXDRIdrawable
* pdraw
,
796 int x
, int y
, int width
, int height
, Bool flush
)
798 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
799 struct dri_screen
*psc
= (struct dri_screen
*) pdp
->base
.psc
;
805 (*psc
->driCopySubBuffer
->copySubBuffer
) (pdp
->driDrawable
,
806 x
, y
, width
, height
);
810 driDestroyScreen(struct glx_screen
*base
)
812 struct dri_screen
*psc
= (struct dri_screen
*) base
;
814 /* Free the direct rendering per screen data */
816 (*psc
->core
->destroyScreen
) (psc
->driScreen
);
817 driDestroyConfigs(psc
->driver_configs
);
818 psc
->driScreen
= NULL
;
820 dlclose(psc
->driver
);
824 driSetSwapInterval(__GLXDRIdrawable
*pdraw
, int interval
)
826 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
829 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
831 if (psc
->swapControl
!= NULL
) {
832 psc
->swapControl
->setSwapInterval(pdp
->driDrawable
, interval
);
836 return GLX_BAD_CONTEXT
;
840 driGetSwapInterval(__GLXDRIdrawable
*pdraw
)
842 struct dri_drawable
*pdp
= (struct dri_drawable
*) pdraw
;
845 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
847 if (psc
->swapControl
!= NULL
)
848 return psc
->swapControl
->getSwapInterval(pdp
->driDrawable
);
853 /* Bind DRI1 specific extensions */
855 driBindExtensions(struct dri_screen
*psc
, const __DRIextension
**extensions
)
859 for (i
= 0; extensions
[i
]; i
++) {
860 /* No DRI2 support for swap_control at the moment, since SwapBuffers
861 * is done by the X server */
862 if (strcmp(extensions
[i
]->name
, __DRI_SWAP_CONTROL
) == 0) {
863 psc
->swapControl
= (__DRIswapControlExtension
*) extensions
[i
];
864 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_swap_control");
865 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_swap_control");
868 if (strcmp(extensions
[i
]->name
, __DRI_MEDIA_STREAM_COUNTER
) == 0) {
869 psc
->msc
= (__DRImediaStreamCounterExtension
*) extensions
[i
];
870 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_video_sync");
873 if (strcmp(extensions
[i
]->name
, __DRI_COPY_SUB_BUFFER
) == 0) {
874 psc
->driCopySubBuffer
= (__DRIcopySubBufferExtension
*) extensions
[i
];
875 __glXEnableDirectExtension(&psc
->base
, "GLX_MESA_copy_sub_buffer");
878 if (strcmp(extensions
[i
]->name
, __DRI_READ_DRAWABLE
) == 0) {
879 __glXEnableDirectExtension(&psc
->base
, "GLX_SGI_make_current_read");
881 /* Ignore unknown extensions */
885 static const struct glx_screen_vtable dri_screen_vtable
= {
886 .create_context
= dri_create_context
,
887 .create_context_attribs
= NULL
,
888 .query_renderer_integer
= NULL
,
889 .query_renderer_string
= NULL
,
892 static struct glx_screen
*
893 driCreateScreen(int screen
, struct glx_display
*priv
)
895 struct dri_display
*pdp
;
897 const __DRIextension
**extensions
;
898 struct dri_screen
*psc
;
902 psc
= calloc(1, sizeof *psc
);
906 if (!glx_screen_init(&psc
->base
, screen
, priv
)) {
911 if (!driGetDriverName(priv
->dpy
, screen
, &driverName
)) {
915 extensions
= driOpenDriver(driverName
, &psc
->driver
);
916 if (extensions
== NULL
) {
917 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
921 for (i
= 0; extensions
[i
]; i
++) {
922 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
923 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
924 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
925 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
928 if (psc
->core
== NULL
|| psc
->legacy
== NULL
)
931 pdp
= (struct dri_display
*) priv
->driDisplay
;
933 CallCreateNewScreen(psc
->base
.dpy
, screen
, psc
, pdp
);
934 if (psc
->driScreen
== NULL
)
937 extensions
= psc
->core
->getExtensions(psc
->driScreen
);
938 driBindExtensions(psc
, extensions
);
940 psc
->base
.vtable
= &dri_screen_vtable
;
942 psc
->base
.driScreen
= psp
;
943 if (psc
->driCopySubBuffer
)
944 psp
->copySubBuffer
= driCopySubBuffer
;
946 psp
->destroyScreen
= driDestroyScreen
;
947 psp
->createDrawable
= driCreateDrawable
;
948 psp
->swapBuffers
= driSwapBuffers
;
950 psp
->setSwapInterval
= driSetSwapInterval
;
951 psp
->getSwapInterval
= driGetSwapInterval
;
958 CriticalErrorMessageF("failed to load driver: %s\n", driverName
);
963 dlclose(psc
->driver
);
964 glx_screen_cleanup(&psc
->base
);
970 /* Called from __glXFreeDisplayPrivate.
973 driDestroyDisplay(__GLXDRIdisplay
* dpy
)
979 * Allocate, initialize and return a __DRIdisplayPrivate object.
980 * This is called from __glXInitialize() when we are given a new
983 _X_HIDDEN __GLXDRIdisplay
*
984 driCreateDisplay(Display
* dpy
)
986 struct dri_display
*pdpyp
;
987 int eventBase
, errorBase
;
988 int major
, minor
, patch
;
990 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
994 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
998 pdpyp
= malloc(sizeof *pdpyp
);
1003 pdpyp
->driMajor
= major
;
1004 pdpyp
->driMinor
= minor
;
1005 pdpyp
->driPatch
= patch
;
1007 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
1008 pdpyp
->base
.createScreen
= driCreateScreen
;
1010 return &pdpyp
->base
;
1013 #endif /* GLX_DIRECT_RENDERING */