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 glxValue
;
526 for (i
= 0; i
< ARRAY_SIZE(attribMap
); i
++)
527 if (attribMap
[i
].attrib
== attrib
) {
528 glxValue
= *(unsigned int *) ((char *) mode
+ attribMap
[i
].offset
);
529 return glxValue
== GLX_DONT_CARE
|| glxValue
== 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 (modes
->bindToTextureTargets
!= GLX_DONT_CARE
&&
576 glxValue
!= modes
->bindToTextureTargets
)
581 if (!scalarEqual(modes
, attrib
, value
))
589 static __GLcontextModes
*
590 createDriMode(const __DRIcoreExtension
*core
,
591 __GLcontextModes
*modes
, const __DRIconfig
**driConfigs
)
593 __GLXDRIconfigPrivate
*config
;
596 for (i
= 0; driConfigs
[i
]; i
++) {
597 if (driConfigEqual(core
, modes
, driConfigs
[i
]))
601 if (driConfigs
[i
] == NULL
)
604 config
= Xmalloc(sizeof *config
);
608 config
->modes
= *modes
;
609 config
->driConfig
= driConfigs
[i
];
611 return &config
->modes
;
614 extern __GLcontextModes
*
615 driConvertConfigs(const __DRIcoreExtension
*core
,
616 __GLcontextModes
*modes
, const __DRIconfig
**configs
);
618 _X_HIDDEN __GLcontextModes
*
619 driConvertConfigs(const __DRIcoreExtension
*core
,
620 __GLcontextModes
*modes
, const __DRIconfig
**configs
)
622 __GLcontextModes head
, *tail
, *m
;
626 for (m
= modes
; m
; m
= m
->next
) {
627 tail
->next
= createDriMode(core
, m
, configs
);
628 if (tail
->next
== NULL
) {
629 /* no matching dri config for m */
637 _gl_context_modes_destroy(modes
);
643 * Perform the required libGL-side initialization and call the client-side
644 * driver's \c __driCreateNewScreen function.
646 * \param dpy Display pointer.
647 * \param scrn Screen number on the display.
648 * \param psc DRI screen information.
649 * \param driDpy DRI display information.
650 * \param createNewScreen Pointer to the client-side driver's
651 * \c __driCreateNewScreen function.
652 * \returns A pointer to the \c __DRIscreenPrivate structure returned by
653 * the client-side driver on success, or \c NULL on failure.
655 * \todo This function needs to be modified to remove context-modes from the
656 * list stored in the \c __GLXscreenConfigsRec to match the list
657 * returned by the client-side driver.
660 CallCreateNewScreen(Display
*dpy
, int scrn
, __GLXscreenConfigs
*psc
,
661 __GLXDRIdisplayPrivate
* driDpy
)
664 #ifndef GLX_USE_APPLEGL
666 drmAddress pSAREA
= MAP_FAILED
;
668 __DRIversion ddx_version
;
669 __DRIversion dri_version
;
670 __DRIversion drm_version
;
671 __DRIframebuffer framebuffer
;
674 const char * err_msg
;
675 const char * err_extra
;
676 const __DRIconfig
**driver_configs
;
678 dri_version
.major
= driDpy
->driMajor
;
679 dri_version
.minor
= driDpy
->driMinor
;
680 dri_version
.patch
= driDpy
->driPatch
;
682 err_msg
= "XF86DRIOpenConnection";
685 framebuffer
.base
= MAP_FAILED
;
686 framebuffer
.dev_priv
= NULL
;
688 if (XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
690 fd
= drmOpenOnce(NULL
,BusID
, &newlyopened
);
691 Xfree(BusID
); /* No longer needed */
693 err_msg
= "open DRM";
694 err_extra
= strerror( -fd
);
699 err_msg
= "drmGetMagic";
702 if (!drmGetMagic(fd
, &magic
)) {
703 drmVersionPtr version
= drmGetVersion(fd
);
705 drm_version
.major
= version
->version_major
;
706 drm_version
.minor
= version
->version_minor
;
707 drm_version
.patch
= version
->version_patchlevel
;
708 drmFreeVersion(version
);
711 drm_version
.major
= -1;
712 drm_version
.minor
= -1;
713 drm_version
.patch
= -1;
716 err_msg
= "XF86DRIAuthConnection";
717 if (!newlyopened
|| XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
721 * Get device name (like "tdfx") and the ddx version
722 * numbers. We'll check the version in each DRI driver's
723 * "createNewScreen" function.
725 err_msg
= "XF86DRIGetClientDriverName";
726 if (XF86DRIGetClientDriverName(dpy
, scrn
,
734 /* No longer needed. */
739 * Get device-specific info. pDevPriv will point to a struct
740 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
741 * that has information about the screen size, depth, pitch,
742 * ancilliary buffers, DRM mmap handles, etc.
744 err_msg
= "XF86DRIGetDeviceInfo";
745 if (XF86DRIGetDeviceInfo(dpy
, scrn
,
750 &framebuffer
.dev_priv_size
,
751 &framebuffer
.dev_priv
)) {
752 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
753 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
756 * Map the framebuffer region.
758 status
= drmMap(fd
, hFB
, framebuffer
.size
,
759 (drmAddressPtr
)&framebuffer
.base
);
761 err_msg
= "drmMap of framebuffer";
762 err_extra
= strerror( -status
);
766 * Map the SAREA region. Further mmap regions
767 * may be setup in each DRI driver's
768 * "createNewScreen" function.
770 status
= drmMap(fd
, hSAREA
, SAREA_MAX
,
773 err_msg
= "drmMap of sarea";
774 err_extra
= strerror( -status
);
777 err_msg
= "InitDriver";
779 psp
= (*psc
->legacy
->createNewScreen
)(scrn
,
792 driConvertConfigs(psc
->core
,
796 driConvertConfigs(psc
->core
,
810 if ( pSAREA
!= MAP_FAILED
) {
811 (void)drmUnmap(pSAREA
, SAREA_MAX
);
814 if ( framebuffer
.base
!= MAP_FAILED
) {
815 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
818 if ( framebuffer
.dev_priv
!= NULL
) {
819 Xfree(framebuffer
.dev_priv
);
823 (void)drmCloseOnce(fd
);
826 (void)XF86DRICloseConnection(dpy
, scrn
);
828 if ( err_extra
!= NULL
) {
829 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
833 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
836 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
838 #endif /* !GLX_USE_APPLEGL */
843 static void driDestroyContext(__GLXDRIcontext
*context
,
844 __GLXscreenConfigs
*psc
, Display
*dpy
)
846 __GLXDRIcontextPrivate
*pcp
= (__GLXDRIcontextPrivate
*) context
;
848 (*psc
->core
->destroyContext
)(pcp
->driContext
);
850 XF86DRIDestroyContext(psc
->dpy
, psc
->scr
, pcp
->hwContextID
);
853 static Bool
driBindContext(__GLXDRIcontext
*context
,
854 __GLXDRIdrawable
*draw
, __GLXDRIdrawable
*read
)
856 __GLXDRIcontextPrivate
*pcp
= (__GLXDRIcontextPrivate
*) context
;
857 const __DRIcoreExtension
*core
= pcp
->psc
->core
;
859 return (*core
->bindContext
)(pcp
->driContext
,
864 static void driUnbindContext(__GLXDRIcontext
*context
)
866 __GLXDRIcontextPrivate
*pcp
= (__GLXDRIcontextPrivate
*) context
;
867 const __DRIcoreExtension
*core
= pcp
->psc
->core
;
869 (*core
->unbindContext
)(pcp
->driContext
);
872 static __GLXDRIcontext
*driCreateContext(__GLXscreenConfigs
*psc
,
873 const __GLcontextModes
*mode
,
875 GLXContext shareList
, int renderType
)
877 __GLXDRIcontextPrivate
*pcp
, *pcp_shared
;
878 drm_context_t hwContext
;
879 __DRIcontext
*shared
= NULL
;
880 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) mode
;
882 if (psc
&& psc
->driScreen
) {
884 pcp_shared
= (__GLXDRIcontextPrivate
*) shareList
->driContext
;
885 shared
= pcp_shared
->driContext
;
888 pcp
= Xmalloc(sizeof *pcp
);
893 if (!XF86DRICreateContextWithConfig(psc
->dpy
, psc
->scr
,
895 &pcp
->hwContextID
, &hwContext
)) {
901 (*psc
->legacy
->createNewContext
)(psc
->__driScreen
,
907 if (pcp
->driContext
== NULL
) {
908 XF86DRIDestroyContext(psc
->dpy
, psc
->scr
, pcp
->hwContextID
);
913 pcp
->base
.destroyContext
= driDestroyContext
;
914 pcp
->base
.bindContext
= driBindContext
;
915 pcp
->base
.unbindContext
= driUnbindContext
;
923 static void driDestroyDrawable(__GLXDRIdrawable
*pdraw
)
925 __GLXscreenConfigs
*psc
= pdraw
->psc
;
927 (*psc
->core
->destroyDrawable
)(pdraw
->driDrawable
);
928 XF86DRIDestroyDrawable(psc
->dpy
, psc
->scr
, pdraw
->drawable
);
932 static __GLXDRIdrawable
*driCreateDrawable(__GLXscreenConfigs
*psc
,
934 GLXDrawable drawable
,
935 const __GLcontextModes
*modes
)
937 __GLXDRIdrawable
*pdraw
;
938 drm_drawable_t hwDrawable
;
939 void *empty_attribute_list
= NULL
;
940 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) modes
;
942 /* Old dri can't handle GLX 1.3+ drawable constructors. */
943 if (xDrawable
!= drawable
)
946 pdraw
= Xmalloc(sizeof(*pdraw
));
950 pdraw
->drawable
= drawable
;
953 if (!XF86DRICreateDrawable(psc
->dpy
, psc
->scr
, drawable
, &hwDrawable
))
956 /* Create a new drawable */
958 (*psc
->legacy
->createNewDrawable
)(psc
->__driScreen
,
962 empty_attribute_list
,
965 if (!pdraw
->driDrawable
) {
966 XF86DRIDestroyDrawable(psc
->dpy
, psc
->scr
, drawable
);
971 pdraw
->destroyDrawable
= driDestroyDrawable
;
976 static void driDestroyScreen(__GLXscreenConfigs
*psc
)
978 /* Free the direct rendering per screen data */
979 if (psc
->__driScreen
)
980 (*psc
->core
->destroyScreen
)(psc
->__driScreen
);
981 psc
->__driScreen
= NULL
;
983 dlclose(psc
->driver
);
987 driBindExtensions(__GLXscreenConfigs
*psc
);
989 static __GLXDRIscreen
*driCreateScreen(__GLXscreenConfigs
*psc
, int screen
,
990 __GLXdisplayPrivate
*priv
)
992 __GLXDRIdisplayPrivate
*pdp
;
994 const __DRIextension
**extensions
;
997 psp
= Xmalloc(sizeof *psp
);
1001 /* Initialize per screen dynamic client GLX extensions */
1002 psc
->ext_list_first_time
= GL_TRUE
;
1004 psc
->driver
= driGetDriver(priv
->dpy
, screen
);
1005 if (psc
->driver
== NULL
) {
1010 extensions
= dlsym(psc
->driver
, __DRI_DRIVER_EXTENSIONS
);
1011 if (extensions
== NULL
) {
1012 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
1017 for (i
= 0; extensions
[i
]; i
++) {
1018 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
1019 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
1020 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
1021 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
1024 if (psc
->core
== NULL
|| psc
->legacy
== NULL
) {
1029 pdp
= (__GLXDRIdisplayPrivate
*) priv
->driDisplay
;
1031 CallCreateNewScreen(psc
->dpy
, screen
, psc
, pdp
);
1032 if (psc
->__driScreen
== NULL
) {
1033 dlclose(psc
->driver
);
1038 driBindExtensions(psc
);
1040 psp
->destroyScreen
= driDestroyScreen
;
1041 psp
->createContext
= driCreateContext
;
1042 psp
->createDrawable
= driCreateDrawable
;
1047 /* Called from __glXFreeDisplayPrivate.
1049 static void driDestroyDisplay(__GLXDRIdisplay
*dpy
)
1055 * Allocate, initialize and return a __DRIdisplayPrivate object.
1056 * This is called from __glXInitialize() when we are given a new
1059 _X_HIDDEN __GLXDRIdisplay
*driCreateDisplay(Display
*dpy
)
1061 __GLXDRIdisplayPrivate
*pdpyp
;
1062 int eventBase
, errorBase
;
1063 int major
, minor
, patch
;
1065 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
1069 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
1073 pdpyp
= Xmalloc(sizeof *pdpyp
);
1078 pdpyp
->driMajor
= major
;
1079 pdpyp
->driMinor
= minor
;
1080 pdpyp
->driPatch
= patch
;
1082 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
1083 pdpyp
->base
.createScreen
= driCreateScreen
;
1085 return &pdpyp
->base
;
1088 #endif /* GLX_DIRECT_RENDERING */