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 #ifdef GLX_DIRECT_RENDERING
38 #include <X11/Xlibint.h>
39 #include <X11/extensions/Xext.h>
40 #include <X11/extensions/extutil.h>
41 #include <X11/extensions/Xfixes.h>
42 #include <X11/extensions/Xdamage.h>
44 #include "glxclient.h"
49 #include <sys/types.h>
51 #include "glcontextmodes.h"
62 typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate
;
63 typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate
;
64 typedef struct __GLXDRIconfigPrivateRec __GLXDRIconfigPrivate
;
66 struct __GLXDRIdisplayPrivateRec
{
70 ** XFree86-DRI version information
77 struct __GLXDRIcontextPrivateRec
{
79 __DRIcontext
*driContext
;
81 __GLXscreenConfigs
*psc
;
84 struct __GLXDRIconfigPrivateRec
{
85 __GLcontextModes modes
;
86 const __DRIconfig
*driConfig
;
89 #ifndef DEFAULT_DRIVER_DIR
90 /* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
91 #define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri"
94 static void InfoMessageF(const char *f
, ...)
99 if ((env
= getenv("LIBGL_DEBUG")) && strstr(env
, "verbose")) {
100 fprintf(stderr
, "libGL: ");
102 vfprintf(stderr
, f
, args
);
107 extern void ErrorMessageF(const char *f
, ...);
110 * Print error to stderr, unless LIBGL_DEBUG=="quiet".
112 _X_HIDDEN
void ErrorMessageF(const char *f
, ...)
117 if ((env
= getenv("LIBGL_DEBUG")) && !strstr(env
, "quiet")) {
118 fprintf(stderr
, "libGL error: ");
120 vfprintf(stderr
, f
, args
);
125 extern void *driOpenDriver(const char *driverName
);
128 * Try to \c dlopen the named driver.
130 * This function adds the "_dri.so" suffix to the driver name and searches the
131 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
132 * order to find the driver.
134 * \param driverName - a name like "tdfx", "i810", "mga", etc.
137 * A handle from \c dlopen, or \c NULL if driver file not found.
139 _X_HIDDEN
void *driOpenDriver(const char *driverName
)
141 void *glhandle
, *handle
;
142 const char *libPaths
, *p
, *next
;
143 char realDriverName
[200];
146 /* Attempt to make sure libGL symbols will be visible to the driver */
147 glhandle
= dlopen("libGL.so.1", RTLD_NOW
| RTLD_GLOBAL
);
150 if (geteuid() == getuid()) {
151 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
152 libPaths
= getenv("LIBGL_DRIVERS_PATH");
154 libPaths
= getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
156 if (libPaths
== NULL
)
157 libPaths
= DEFAULT_DRIVER_DIR
;
160 for (p
= libPaths
; *p
; p
= next
) {
161 next
= strchr(p
, ':');
171 snprintf(realDriverName
, sizeof realDriverName
,
172 "%.*s/tls/%s_dri.so", len
, p
, driverName
);
173 InfoMessageF("OpenDriver: trying %s\n", realDriverName
);
174 handle
= dlopen(realDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
177 if ( handle
== NULL
) {
178 snprintf(realDriverName
, sizeof realDriverName
,
179 "%.*s/%s_dri.so", len
, p
, driverName
);
180 InfoMessageF("OpenDriver: trying %s\n", realDriverName
);
181 handle
= dlopen(realDriverName
, RTLD_NOW
| RTLD_GLOBAL
);
184 if ( handle
!= NULL
)
187 ErrorMessageF("dlopen %s failed (%s)\n", realDriverName
, dlerror());
191 ErrorMessageF("unable to load driver: %s_dri.so\n", driverName
);
201 * Given a display pointer and screen number, determine the name of
202 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
203 * Return True for success, False for failure.
205 static Bool
GetDriverName(Display
*dpy
, int scrNum
, char **driverName
)
209 int driverMajor
, driverMinor
, driverPatch
;
213 if (!XF86DRIQueryDirectRenderingCapable(dpy
, scrNum
, &directCapable
)) {
214 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
217 if (!directCapable
) {
218 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
222 b
= XF86DRIGetClientDriverName(dpy
, scrNum
, &driverMajor
, &driverMinor
,
223 &driverPatch
, driverName
);
225 ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum
);
229 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
230 driverMajor
, driverMinor
, driverPatch
, *driverName
, scrNum
);
237 * Given a display pointer and screen number, return a __DRIdriver handle.
238 * Return NULL if anything goes wrong.
240 static void *driGetDriver(Display
*dpy
, int scrNum
)
245 if (GetDriverName(dpy
, scrNum
, &driverName
)) {
246 ret
= driOpenDriver(driverName
);
255 * Exported function for querying the DRI driver for a given screen.
257 * The returned char pointer points to a static array that will be
258 * overwritten by subsequent calls.
260 PUBLIC
const char *glXGetScreenDriver (Display
*dpy
, int scrNum
) {
263 if (GetDriverName(dpy
, scrNum
, &driverName
)) {
267 len
= strlen (driverName
);
270 memcpy (ret
, driverName
, len
+1);
279 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
281 * The returned char pointer points directly into the driver. Therefore
282 * it should be treated as a constant.
284 * If the driver was not found or does not support configuration NULL is
287 * Note: The driver remains opened after this function returns.
289 PUBLIC
const char *glXGetDriverConfig (const char *driverName
)
291 void *handle
= driOpenDriver (driverName
);
293 return dlsym (handle
, "__driConfigOptions");
299 driFilterModes(__GLcontextModes
** server_modes
,
300 const __GLcontextModes
* driver_modes
);
303 driFilterModes(__GLcontextModes
** server_modes
,
304 const __GLcontextModes
* driver_modes
)
306 __GLcontextModes
* m
;
307 __GLcontextModes
** prev_next
;
308 const __GLcontextModes
* check
;
310 if (driver_modes
== NULL
) {
311 fprintf(stderr
, "libGL warning: 3D driver returned no fbconfigs.\n");
315 /* For each mode in server_modes, check to see if a matching mode exists
316 * in driver_modes. If not, then the mode is not available.
319 prev_next
= server_modes
;
320 for ( m
= *prev_next
; m
!= NULL
; m
= *prev_next
) {
321 GLboolean do_delete
= GL_TRUE
;
323 for ( check
= driver_modes
; check
!= NULL
; check
= check
->next
) {
324 if ( _gl_context_modes_are_same( m
, check
) ) {
325 do_delete
= GL_FALSE
;
330 /* The 3D has to support all the modes that match the GLX visuals
331 * sent from the X server.
333 if ( do_delete
&& (m
->visualID
!= 0) ) {
334 do_delete
= GL_FALSE
;
336 /* don't warn for this visual (Novell #247471 / X.Org #6689) */
337 if (m
->visualRating
!= GLX_NON_CONFORMANT_CONFIG
) {
338 fprintf(stderr
, "libGL warning: 3D driver claims to not "
339 "support visual 0x%02x\n", m
->visualID
);
344 *prev_next
= m
->next
;
347 _gl_context_modes_destroy( m
);
350 prev_next
= & m
->next
;
355 #ifdef XDAMAGE_1_1_INTERFACE
357 static GLboolean
has_damage_post(Display
*dpy
)
359 static GLboolean inited
= GL_FALSE
;
360 static GLboolean has_damage
;
365 if (XDamageQueryVersion(dpy
, &major
, &minor
) &&
366 major
== 1 && minor
>= 1)
368 has_damage
= GL_TRUE
;
370 has_damage
= GL_FALSE
;
378 static void __glXReportDamage(__DRIdrawable
*driDraw
,
380 drm_clip_rect_t
*rects
, int num_rects
,
381 GLboolean front_buffer
,
385 XserverRegion region
;
388 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
389 __GLXscreenConfigs
*psc
= glxDraw
->psc
;
390 Display
*dpy
= psc
->dpy
;
393 if (!has_damage_post(dpy
))
399 drawable
= RootWindow(dpy
, psc
->scr
);
403 drawable
= glxDraw
->xDrawable
;
406 xrects
= malloc(sizeof(XRectangle
) * num_rects
);
410 for (i
= 0; i
< num_rects
; i
++) {
411 xrects
[i
].x
= rects
[i
].x1
+ x_off
;
412 xrects
[i
].y
= rects
[i
].y1
+ y_off
;
413 xrects
[i
].width
= rects
[i
].x2
- rects
[i
].x1
;
414 xrects
[i
].height
= rects
[i
].y2
- rects
[i
].y1
;
416 region
= XFixesCreateRegion(dpy
, xrects
, num_rects
);
418 XDamageAdd(dpy
, drawable
, region
);
419 XFixesDestroyRegion(dpy
, region
);
422 static const __DRIdamageExtension damageExtension
= {
423 { __DRI_DAMAGE
, __DRI_DAMAGE_VERSION
},
430 __glXDRIGetDrawableInfo(__DRIdrawable
*drawable
,
431 unsigned int *index
, unsigned int *stamp
,
432 int *X
, int *Y
, int *W
, int *H
,
433 int *numClipRects
, drm_clip_rect_t
** pClipRects
,
434 int *backX
, int *backY
,
435 int *numBackClipRects
, drm_clip_rect_t
**pBackClipRects
,
438 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
439 __GLXscreenConfigs
*psc
= glxDraw
->psc
;
440 Display
*dpy
= psc
->dpy
;
442 return XF86DRIGetDrawableInfo(dpy
, psc
->scr
, glxDraw
->drawable
,
443 index
, stamp
, X
, Y
, W
, H
,
444 numClipRects
, pClipRects
,
446 numBackClipRects
, pBackClipRects
);
449 _X_HIDDEN
const __DRIsystemTimeExtension systemTimeExtension
= {
450 { __DRI_SYSTEM_TIME
, __DRI_SYSTEM_TIME_VERSION
},
455 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension
= {
456 { __DRI_GET_DRAWABLE_INFO
, __DRI_GET_DRAWABLE_INFO_VERSION
},
457 __glXDRIGetDrawableInfo
460 static const __DRIextension
*loader_extensions
[] = {
461 &systemTimeExtension
.base
,
462 &getDrawableInfoExtension
.base
,
464 #ifdef XDAMAGE_1_1_INTERFACE
465 &damageExtension
.base
,
471 #define __ATTRIB(attrib, field) \
472 { attrib, offsetof(__GLcontextModes, field) }
474 static const struct { unsigned int attrib
, offset
; } attribMap
[] = {
475 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE
, rgbBits
),
476 __ATTRIB(__DRI_ATTRIB_LEVEL
, level
),
477 __ATTRIB(__DRI_ATTRIB_RED_SIZE
, redBits
),
478 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE
, greenBits
),
479 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE
, blueBits
),
480 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE
, alphaBits
),
481 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE
, depthBits
),
482 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE
, stencilBits
),
483 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE
, accumRedBits
),
484 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE
, accumGreenBits
),
485 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE
, accumBlueBits
),
486 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE
, accumAlphaBits
),
487 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS
, sampleBuffers
),
488 __ATTRIB(__DRI_ATTRIB_SAMPLES
, samples
),
489 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER
, doubleBufferMode
),
490 __ATTRIB(__DRI_ATTRIB_STEREO
, stereoMode
),
491 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS
, numAuxBuffers
),
493 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE
, transparentPixel
),
494 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE
, transparentIndex
),
495 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE
, transparentRed
),
496 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE
, transparentGreen
),
497 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE
, transparentBlue
),
498 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE
, transparentAlpha
),
499 __ATTRIB(__DRI_ATTRIB_RED_MASK
, redMask
),
500 __ATTRIB(__DRI_ATTRIB_GREEN_MASK
, greenMask
),
501 __ATTRIB(__DRI_ATTRIB_BLUE_MASK
, blueMask
),
502 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK
, alphaMask
),
504 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH
, maxPbufferWidth
),
505 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT
, maxPbufferHeight
),
506 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS
, maxPbufferPixels
),
507 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH
, optimalPbufferWidth
),
508 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT
, optimalPbufferHeight
),
510 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD
, swapMethod
),
512 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB
, bindToTextureRgb
),
513 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA
, bindToTextureRgba
),
514 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE
, bindToMipmapTexture
),
515 __ATTRIB(__DRI_ATTRIB_YINVERTED
, yInverted
),
518 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
521 scalarEqual(__GLcontextModes
*mode
, unsigned int attrib
, unsigned int value
)
523 unsigned int driValue
;
526 for (i
= 0; i
< ARRAY_SIZE(attribMap
); i
++)
527 if (attribMap
[i
].attrib
== attrib
) {
528 driValue
= *(unsigned int *) ((char *) mode
+ attribMap
[i
].offset
);
529 return driValue
== value
;
532 return GL_TRUE
; /* Is a non-existing attribute equal to value? */
536 driConfigEqual(const __DRIcoreExtension
*core
,
537 __GLcontextModes
*modes
, const __DRIconfig
*driConfig
)
539 unsigned int attrib
, value
, glxValue
;
543 while (core
->indexConfigAttrib(driConfig
, i
++, &attrib
, &value
)) {
545 case __DRI_ATTRIB_RENDER_TYPE
:
547 if (value
& __DRI_ATTRIB_RGBA_BIT
) {
548 glxValue
|= GLX_RGBA_BIT
;
549 } else if (value
& __DRI_ATTRIB_COLOR_INDEX_BIT
) {
550 glxValue
|= GLX_COLOR_INDEX_BIT
;
552 if (glxValue
!= modes
->renderType
)
556 case __DRI_ATTRIB_CONFIG_CAVEAT
:
557 if (value
& __DRI_ATTRIB_NON_CONFORMANT_CONFIG
)
558 glxValue
= GLX_NON_CONFORMANT_CONFIG
;
559 else if (value
& __DRI_ATTRIB_SLOW_BIT
)
560 glxValue
= GLX_SLOW_CONFIG
;
563 if (glxValue
!= modes
->visualRating
)
567 case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS
:
569 if (value
& __DRI_ATTRIB_TEXTURE_1D_BIT
)
570 glxValue
|= GLX_TEXTURE_1D_BIT_EXT
;
571 if (value
& __DRI_ATTRIB_TEXTURE_2D_BIT
)
572 glxValue
|= GLX_TEXTURE_2D_BIT_EXT
;
573 if (value
& __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT
)
574 glxValue
|= GLX_TEXTURE_RECTANGLE_BIT_EXT
;
575 if (glxValue
!= modes
->bindToTextureTargets
)
580 if (!scalarEqual(modes
, attrib
, value
))
588 static __GLcontextModes
*
589 createDriMode(const __DRIcoreExtension
*core
,
590 __GLcontextModes
*modes
, const __DRIconfig
**driConfigs
)
592 __GLXDRIconfigPrivate
*config
;
595 for (i
= 0; driConfigs
[i
]; i
++) {
596 if (driConfigEqual(core
, modes
, driConfigs
[i
]))
600 if (driConfigs
[i
] == NULL
)
603 config
= Xmalloc(sizeof *config
);
607 config
->modes
= *modes
;
608 config
->driConfig
= driConfigs
[i
];
610 return &config
->modes
;
613 extern __GLcontextModes
*
614 driConvertConfigs(const __DRIcoreExtension
*core
,
615 __GLcontextModes
*modes
, const __DRIconfig
**configs
);
617 _X_HIDDEN __GLcontextModes
*
618 driConvertConfigs(const __DRIcoreExtension
*core
,
619 __GLcontextModes
*modes
, const __DRIconfig
**configs
)
621 __GLcontextModes head
, *tail
, *m
;
625 for (m
= modes
; m
; m
= m
->next
) {
626 tail
->next
= createDriMode(core
, m
, configs
);
627 if (tail
->next
== NULL
) {
628 /* no matching dri config for m */
636 _gl_context_modes_destroy(modes
);
642 * Perform the required libGL-side initialization and call the client-side
643 * driver's \c __driCreateNewScreen function.
645 * \param dpy Display pointer.
646 * \param scrn Screen number on the display.
647 * \param psc DRI screen information.
648 * \param driDpy DRI display information.
649 * \param createNewScreen Pointer to the client-side driver's
650 * \c __driCreateNewScreen function.
651 * \returns A pointer to the \c __DRIscreenPrivate structure returned by
652 * the client-side driver on success, or \c NULL on failure.
654 * \todo This function needs to be modified to remove context-modes from the
655 * list stored in the \c __GLXscreenConfigsRec to match the list
656 * returned by the client-side driver.
659 CallCreateNewScreen(Display
*dpy
, int scrn
, __GLXscreenConfigs
*psc
,
660 __GLXDRIdisplayPrivate
* driDpy
)
663 #ifndef GLX_USE_APPLEGL
665 drmAddress pSAREA
= MAP_FAILED
;
667 __DRIversion ddx_version
;
668 __DRIversion dri_version
;
669 __DRIversion drm_version
;
670 __DRIframebuffer framebuffer
;
673 const char * err_msg
;
674 const char * err_extra
;
675 const __DRIconfig
**driver_configs
;
677 dri_version
.major
= driDpy
->driMajor
;
678 dri_version
.minor
= driDpy
->driMinor
;
679 dri_version
.patch
= driDpy
->driPatch
;
681 err_msg
= "XF86DRIOpenConnection";
684 framebuffer
.base
= MAP_FAILED
;
685 framebuffer
.dev_priv
= NULL
;
687 if (XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
689 fd
= drmOpenOnce(NULL
,BusID
, &newlyopened
);
690 Xfree(BusID
); /* No longer needed */
692 err_msg
= "open DRM";
693 err_extra
= strerror( -fd
);
698 err_msg
= "drmGetMagic";
701 if (!drmGetMagic(fd
, &magic
)) {
702 drmVersionPtr version
= drmGetVersion(fd
);
704 drm_version
.major
= version
->version_major
;
705 drm_version
.minor
= version
->version_minor
;
706 drm_version
.patch
= version
->version_patchlevel
;
707 drmFreeVersion(version
);
710 drm_version
.major
= -1;
711 drm_version
.minor
= -1;
712 drm_version
.patch
= -1;
715 err_msg
= "XF86DRIAuthConnection";
716 if (!newlyopened
|| XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
720 * Get device name (like "tdfx") and the ddx version
721 * numbers. We'll check the version in each DRI driver's
722 * "createNewScreen" function.
724 err_msg
= "XF86DRIGetClientDriverName";
725 if (XF86DRIGetClientDriverName(dpy
, scrn
,
733 /* No longer needed. */
738 * Get device-specific info. pDevPriv will point to a struct
739 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
740 * that has information about the screen size, depth, pitch,
741 * ancilliary buffers, DRM mmap handles, etc.
743 err_msg
= "XF86DRIGetDeviceInfo";
744 if (XF86DRIGetDeviceInfo(dpy
, scrn
,
749 &framebuffer
.dev_priv_size
,
750 &framebuffer
.dev_priv
)) {
751 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
752 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
755 * Map the framebuffer region.
757 status
= drmMap(fd
, hFB
, framebuffer
.size
,
758 (drmAddressPtr
)&framebuffer
.base
);
760 err_msg
= "drmMap of framebuffer";
761 err_extra
= strerror( -status
);
765 * Map the SAREA region. Further mmap regions
766 * may be setup in each DRI driver's
767 * "createNewScreen" function.
769 status
= drmMap(fd
, hSAREA
, SAREA_MAX
,
772 err_msg
= "drmMap of sarea";
773 err_extra
= strerror( -status
);
776 err_msg
= "InitDriver";
778 psp
= (*psc
->legacy
->createNewScreen
)(scrn
,
791 driConvertConfigs(psc
->core
,
795 driConvertConfigs(psc
->core
,
809 if ( pSAREA
!= MAP_FAILED
) {
810 (void)drmUnmap(pSAREA
, SAREA_MAX
);
813 if ( framebuffer
.base
!= MAP_FAILED
) {
814 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
817 if ( framebuffer
.dev_priv
!= NULL
) {
818 Xfree(framebuffer
.dev_priv
);
822 (void)drmCloseOnce(fd
);
825 (void)XF86DRICloseConnection(dpy
, scrn
);
827 if ( err_extra
!= NULL
) {
828 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
832 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
835 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
837 #endif /* !GLX_USE_APPLEGL */
842 static void driDestroyContext(__GLXDRIcontext
*context
,
843 __GLXscreenConfigs
*psc
, Display
*dpy
)
845 __GLXDRIcontextPrivate
*pcp
= (__GLXDRIcontextPrivate
*) context
;
847 (*psc
->core
->destroyContext
)(pcp
->driContext
);
849 XF86DRIDestroyContext(psc
->dpy
, psc
->scr
, pcp
->hwContextID
);
852 static Bool
driBindContext(__GLXDRIcontext
*context
,
853 __GLXDRIdrawable
*draw
, __GLXDRIdrawable
*read
)
855 __GLXDRIcontextPrivate
*pcp
= (__GLXDRIcontextPrivate
*) context
;
856 const __DRIcoreExtension
*core
= pcp
->psc
->core
;
858 return (*core
->bindContext
)(pcp
->driContext
,
863 static void driUnbindContext(__GLXDRIcontext
*context
)
865 __GLXDRIcontextPrivate
*pcp
= (__GLXDRIcontextPrivate
*) context
;
866 const __DRIcoreExtension
*core
= pcp
->psc
->core
;
868 (*core
->unbindContext
)(pcp
->driContext
);
871 static __GLXDRIcontext
*driCreateContext(__GLXscreenConfigs
*psc
,
872 const __GLcontextModes
*mode
,
874 GLXContext shareList
, int renderType
)
876 __GLXDRIcontextPrivate
*pcp
, *pcp_shared
;
877 drm_context_t hwContext
;
878 __DRIcontext
*shared
= NULL
;
879 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) mode
;
881 if (psc
&& psc
->driScreen
) {
883 pcp_shared
= (__GLXDRIcontextPrivate
*) shareList
->driContext
;
884 shared
= pcp_shared
->driContext
;
887 pcp
= Xmalloc(sizeof *pcp
);
892 if (!XF86DRICreateContextWithConfig(psc
->dpy
, psc
->scr
,
894 &pcp
->hwContextID
, &hwContext
)) {
900 (*psc
->legacy
->createNewContext
)(psc
->__driScreen
,
906 if (pcp
->driContext
== NULL
) {
907 XF86DRIDestroyContext(psc
->dpy
, psc
->scr
, pcp
->hwContextID
);
912 pcp
->base
.destroyContext
= driDestroyContext
;
913 pcp
->base
.bindContext
= driBindContext
;
914 pcp
->base
.unbindContext
= driUnbindContext
;
922 static void driDestroyDrawable(__GLXDRIdrawable
*pdraw
)
924 __GLXscreenConfigs
*psc
= pdraw
->psc
;
926 (*psc
->core
->destroyDrawable
)(pdraw
->driDrawable
);
927 XF86DRIDestroyDrawable(psc
->dpy
, psc
->scr
, pdraw
->drawable
);
931 static __GLXDRIdrawable
*driCreateDrawable(__GLXscreenConfigs
*psc
,
933 GLXDrawable drawable
,
934 const __GLcontextModes
*modes
)
936 __GLXDRIdrawable
*pdraw
;
937 drm_drawable_t hwDrawable
;
938 void *empty_attribute_list
= NULL
;
939 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) modes
;
941 /* Old dri can't handle GLX 1.3+ drawable constructors. */
942 if (xDrawable
!= drawable
)
945 pdraw
= Xmalloc(sizeof(*pdraw
));
949 pdraw
->drawable
= drawable
;
952 if (!XF86DRICreateDrawable(psc
->dpy
, psc
->scr
, drawable
, &hwDrawable
))
955 /* Create a new drawable */
957 (*psc
->legacy
->createNewDrawable
)(psc
->__driScreen
,
961 empty_attribute_list
,
964 if (!pdraw
->driDrawable
) {
965 XF86DRIDestroyDrawable(psc
->dpy
, psc
->scr
, drawable
);
970 pdraw
->destroyDrawable
= driDestroyDrawable
;
975 static void driDestroyScreen(__GLXscreenConfigs
*psc
)
977 /* Free the direct rendering per screen data */
978 if (psc
->__driScreen
)
979 (*psc
->core
->destroyScreen
)(psc
->__driScreen
);
980 psc
->__driScreen
= NULL
;
982 dlclose(psc
->driver
);
986 driBindExtensions(__GLXscreenConfigs
*psc
);
988 static __GLXDRIscreen
*driCreateScreen(__GLXscreenConfigs
*psc
, int screen
,
989 __GLXdisplayPrivate
*priv
)
991 __GLXDRIdisplayPrivate
*pdp
;
993 const __DRIextension
**extensions
;
996 psp
= Xmalloc(sizeof *psp
);
1000 /* Initialize per screen dynamic client GLX extensions */
1001 psc
->ext_list_first_time
= GL_TRUE
;
1003 psc
->driver
= driGetDriver(priv
->dpy
, screen
);
1004 if (psc
->driver
== NULL
) {
1009 extensions
= dlsym(psc
->driver
, __DRI_DRIVER_EXTENSIONS
);
1010 if (extensions
== NULL
) {
1011 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
1016 for (i
= 0; extensions
[i
]; i
++) {
1017 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
1018 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
1019 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
1020 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
1023 if (psc
->core
== NULL
|| psc
->legacy
== NULL
) {
1028 pdp
= (__GLXDRIdisplayPrivate
*) priv
->driDisplay
;
1030 CallCreateNewScreen(psc
->dpy
, screen
, psc
, pdp
);
1031 if (psc
->__driScreen
== NULL
) {
1032 dlclose(psc
->driver
);
1037 driBindExtensions(psc
);
1039 psp
->destroyScreen
= driDestroyScreen
;
1040 psp
->createContext
= driCreateContext
;
1041 psp
->createDrawable
= driCreateDrawable
;
1046 /* Called from __glXFreeDisplayPrivate.
1048 static void driDestroyDisplay(__GLXDRIdisplay
*dpy
)
1054 * Allocate, initialize and return a __DRIdisplayPrivate object.
1055 * This is called from __glXInitialize() when we are given a new
1058 _X_HIDDEN __GLXDRIdisplay
*driCreateDisplay(Display
*dpy
)
1060 __GLXDRIdisplayPrivate
*pdpyp
;
1061 int eventBase
, errorBase
;
1062 int major
, minor
, patch
;
1064 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
1068 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
1072 pdpyp
= Xmalloc(sizeof *pdpyp
);
1077 pdpyp
->driMajor
= major
;
1078 pdpyp
->driMinor
= minor
;
1079 pdpyp
->driPatch
= patch
;
1081 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
1082 pdpyp
->base
.createScreen
= driCreateScreen
;
1084 return &pdpyp
->base
;
1087 #endif /* GLX_DIRECT_RENDERING */