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 __GLXscreenConfigs base
;
66 __GLXDRIscreen driScreen
;
67 const __DRIlegacyExtension
*legacy
;
68 const __DRIcoreExtension
*core
;
76 __DRIcontext
*driContext
;
78 __GLXscreenConfigs
*psc
;
82 * Given a display pointer and screen number, determine the name of
83 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
84 * Return True for success, False for failure.
87 driGetDriverName(Display
* dpy
, int scrNum
, char **driverName
)
92 int driverMajor
, driverMinor
, driverPatch
;
96 if (XF86DRIQueryExtension(dpy
, &event
, &error
)) { /* DRI1 */
97 if (!XF86DRIQueryDirectRenderingCapable(dpy
, scrNum
, &directCapable
)) {
98 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
101 if (!directCapable
) {
102 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
106 b
= XF86DRIGetClientDriverName(dpy
, scrNum
, &driverMajor
, &driverMinor
,
107 &driverPatch
, driverName
);
109 ErrorMessageF("Cannot determine driver name for screen %d\n",
114 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
115 driverMajor
, driverMinor
, driverPatch
, *driverName
,
120 else if (DRI2QueryExtension(dpy
, &event
, &error
)) { /* DRI2 */
122 Bool ret
= DRI2Connect(dpy
, RootWindow(dpy
, scrNum
), driverName
, &dev
);
134 * Exported function for querying the DRI driver for a given screen.
136 * The returned char pointer points to a static array that will be
137 * overwritten by subsequent calls.
140 glXGetScreenDriver(Display
* dpy
, int scrNum
)
144 if (driGetDriverName(dpy
, scrNum
, &driverName
)) {
148 len
= strlen(driverName
);
151 memcpy(ret
, driverName
, len
+ 1);
159 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
161 * The returned char pointer points directly into the driver. Therefore
162 * it should be treated as a constant.
164 * If the driver was not found or does not support configuration NULL is
167 * Note: The driver remains opened after this function returns.
170 glXGetDriverConfig(const char *driverName
)
172 void *handle
= driOpenDriver(driverName
);
174 return dlsym(handle
, "__driConfigOptions");
179 #ifdef XDAMAGE_1_1_INTERFACE
182 has_damage_post(Display
* dpy
)
184 static GLboolean inited
= GL_FALSE
;
185 static GLboolean has_damage
;
190 if (XDamageQueryVersion(dpy
, &major
, &minor
) &&
191 major
== 1 && minor
>= 1) {
192 has_damage
= GL_TRUE
;
195 has_damage
= GL_FALSE
;
204 __glXReportDamage(__DRIdrawable
* driDraw
,
206 drm_clip_rect_t
* rects
, int num_rects
,
207 GLboolean front_buffer
, void *loaderPrivate
)
210 XserverRegion region
;
213 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
214 __GLXscreenConfigs
*psc
= glxDraw
->psc
;
215 Display
*dpy
= psc
->dpy
;
218 if (!has_damage_post(dpy
))
224 drawable
= RootWindow(dpy
, psc
->scr
);
229 drawable
= glxDraw
->xDrawable
;
232 xrects
= malloc(sizeof(XRectangle
) * num_rects
);
236 for (i
= 0; i
< num_rects
; i
++) {
237 xrects
[i
].x
= rects
[i
].x1
+ x_off
;
238 xrects
[i
].y
= rects
[i
].y1
+ y_off
;
239 xrects
[i
].width
= rects
[i
].x2
- rects
[i
].x1
;
240 xrects
[i
].height
= rects
[i
].y2
- rects
[i
].y1
;
242 region
= XFixesCreateRegion(dpy
, xrects
, num_rects
);
244 XDamageAdd(dpy
, drawable
, region
);
245 XFixesDestroyRegion(dpy
, region
);
248 static const __DRIdamageExtension damageExtension
= {
249 {__DRI_DAMAGE
, __DRI_DAMAGE_VERSION
},
256 __glXDRIGetDrawableInfo(__DRIdrawable
* drawable
,
257 unsigned int *index
, unsigned int *stamp
,
258 int *X
, int *Y
, int *W
, int *H
,
259 int *numClipRects
, drm_clip_rect_t
** pClipRects
,
260 int *backX
, int *backY
,
261 int *numBackClipRects
,
262 drm_clip_rect_t
** pBackClipRects
,
265 __GLXDRIdrawable
*glxDraw
= loaderPrivate
;
266 __GLXscreenConfigs
*psc
= glxDraw
->psc
;
267 Display
*dpy
= psc
->dpy
;
269 return XF86DRIGetDrawableInfo(dpy
, psc
->scr
, glxDraw
->drawable
,
270 index
, stamp
, X
, Y
, W
, H
,
271 numClipRects
, pClipRects
,
273 numBackClipRects
, pBackClipRects
);
276 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension
= {
277 {__DRI_GET_DRAWABLE_INFO
, __DRI_GET_DRAWABLE_INFO_VERSION
},
278 __glXDRIGetDrawableInfo
281 static const __DRIextension
*loader_extensions
[] = {
282 &systemTimeExtension
.base
,
283 &getDrawableInfoExtension
.base
,
284 #ifdef XDAMAGE_1_1_INTERFACE
285 &damageExtension
.base
,
291 * Perform the required libGL-side initialization and call the client-side
292 * driver's \c __driCreateNewScreen function.
294 * \param dpy Display pointer.
295 * \param scrn Screen number on the display.
296 * \param psc DRI screen information.
297 * \param driDpy DRI display information.
298 * \param createNewScreen Pointer to the client-side driver's
299 * \c __driCreateNewScreen function.
300 * \returns A pointer to the \c __DRIscreen structure returned by
301 * the client-side driver on success, or \c NULL on failure.
304 CallCreateNewScreen(Display
*dpy
, int scrn
, struct dri_screen
*psc
,
305 struct dri_display
* driDpy
)
309 drmAddress pSAREA
= MAP_FAILED
;
311 __DRIversion ddx_version
;
312 __DRIversion dri_version
;
313 __DRIversion drm_version
;
314 __DRIframebuffer framebuffer
;
319 drmVersionPtr version
;
324 const __DRIconfig
**driver_configs
;
325 __GLcontextModes
*visual
;
327 /* DRI protocol version. */
328 dri_version
.major
= driDpy
->driMajor
;
329 dri_version
.minor
= driDpy
->driMinor
;
330 dri_version
.patch
= driDpy
->driPatch
;
332 framebuffer
.base
= MAP_FAILED
;
333 framebuffer
.dev_priv
= NULL
;
334 framebuffer
.size
= 0;
336 if (!XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
337 ErrorMessageF("XF86DRIOpenConnection failed\n");
341 fd
= drmOpenOnce(NULL
, BusID
, &newlyopened
);
343 Xfree(BusID
); /* No longer needed */
346 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd
));
350 if (drmGetMagic(fd
, &magic
)) {
351 ErrorMessageF("drmGetMagic failed\n");
355 version
= drmGetVersion(fd
);
357 drm_version
.major
= version
->version_major
;
358 drm_version
.minor
= version
->version_minor
;
359 drm_version
.patch
= version
->version_patchlevel
;
360 drmFreeVersion(version
);
363 drm_version
.major
= -1;
364 drm_version
.minor
= -1;
365 drm_version
.patch
= -1;
368 if (newlyopened
&& !XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
369 ErrorMessageF("XF86DRIAuthConnection failed\n");
373 /* Get device name (like "tdfx") and the ddx version numbers.
374 * We'll check the version in each DRI driver's "createNewScreen"
376 if (!XF86DRIGetClientDriverName(dpy
, scrn
,
379 &ddx_version
.patch
, &driverName
)) {
380 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
384 Xfree(driverName
); /* No longer needed. */
387 * Get device-specific info. pDevPriv will point to a struct
388 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
389 * has information about the screen size, depth, pitch, ancilliary
390 * buffers, DRM mmap handles, etc.
392 if (!XF86DRIGetDeviceInfo(dpy
, scrn
, &hFB
, &junk
,
393 &framebuffer
.size
, &framebuffer
.stride
,
394 &framebuffer
.dev_priv_size
,
395 &framebuffer
.dev_priv
)) {
396 ErrorMessageF("XF86DRIGetDeviceInfo failed");
400 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
401 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
403 /* Map the framebuffer region. */
404 status
= drmMap(fd
, hFB
, framebuffer
.size
,
405 (drmAddressPtr
) & framebuffer
.base
);
407 ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status
));
411 /* Map the SAREA region. Further mmap regions may be setup in
412 * each DRI driver's "createNewScreen" function.
414 status
= drmMap(fd
, hSAREA
, SAREA_MAX
, &pSAREA
);
416 ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status
));
420 psp
= (*psc
->legacy
->createNewScreen
) (scrn
,
428 &driver_configs
, psc
);
431 ErrorMessageF("Calling driver entry point failed");
436 driConvertConfigs(psc
->core
, psc
->base
.configs
, driver_configs
);
438 driConvertConfigs(psc
->core
, psc
->base
.visuals
, driver_configs
);
440 psc
->base
.driver_configs
= driver_configs
;
442 /* Visuals with depth != screen depth are subject to automatic compositing
443 * in the X server, so DRI1 can't render to them properly. Mark them as
444 * non-conformant to prevent apps from picking them up accidentally.
446 for (visual
= psc
->base
.visuals
; visual
; visual
= visual
->next
) {
447 XVisualInfo
template;
448 XVisualInfo
*visuals
;
452 template.visualid
= visual
->visualID
;
454 visuals
= XGetVisualInfo(dpy
, mask
, &template, &num_visuals
);
457 if (num_visuals
> 0 && visuals
->depth
!= DefaultDepth(dpy
, scrn
))
458 visual
->visualRating
= GLX_NON_CONFORMANT_CONFIG
;
467 if (pSAREA
!= MAP_FAILED
)
468 drmUnmap(pSAREA
, SAREA_MAX
);
470 if (framebuffer
.base
!= MAP_FAILED
)
471 drmUnmap((drmAddress
) framebuffer
.base
, framebuffer
.size
);
473 if (framebuffer
.dev_priv
!= NULL
)
474 Xfree(framebuffer
.dev_priv
);
479 XF86DRICloseConnection(dpy
, scrn
);
481 ErrorMessageF("reverting to software direct rendering\n");
487 driDestroyContext(__GLXDRIcontext
* context
,
488 __GLXscreenConfigs
*base
, Display
* dpy
)
490 struct dri_context
*pcp
= (struct dri_context
*) context
;
491 struct dri_screen
*psc
= (struct dri_screen
*) base
;
493 (*psc
->core
->destroyContext
) (pcp
->driContext
);
495 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
500 driBindContext(__GLXDRIcontext
*context
,
501 __GLXDRIdrawable
*draw
, __GLXDRIdrawable
*read
)
503 struct dri_context
*pcp
= (struct dri_context
*) context
;
504 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->psc
;
506 return (*psc
->core
->bindContext
) (pcp
->driContext
,
507 draw
->driDrawable
, read
->driDrawable
);
511 driUnbindContext(__GLXDRIcontext
* context
)
513 struct dri_context
*pcp
= (struct dri_context
*) context
;
514 struct dri_screen
*psc
= (struct dri_screen
*) pcp
->psc
;
516 (*psc
->core
->unbindContext
) (pcp
->driContext
);
519 static __GLXDRIcontext
*
520 driCreateContext(__GLXscreenConfigs
*base
,
521 const __GLcontextModes
* mode
,
522 GLXContext gc
, GLXContext shareList
, int renderType
)
524 struct dri_context
*pcp
, *pcp_shared
;
525 struct dri_screen
*psc
= (struct dri_screen
*) base
;
526 drm_context_t hwContext
;
527 __DRIcontext
*shared
= NULL
;
528 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) mode
;
530 if (!psc
->base
.driScreen
)
534 pcp_shared
= (struct dri_context
*) shareList
->driContext
;
535 shared
= pcp_shared
->driContext
;
538 pcp
= Xmalloc(sizeof *pcp
);
542 pcp
->psc
= &psc
->base
;
543 if (!XF86DRICreateContextWithConfig(psc
->base
.dpy
, psc
->base
.scr
,
545 &pcp
->hwContextID
, &hwContext
)) {
551 (*psc
->legacy
->createNewContext
) (psc
->base
.__driScreen
,
553 renderType
, shared
, hwContext
, pcp
);
554 if (pcp
->driContext
== NULL
) {
555 XF86DRIDestroyContext(psc
->base
.dpy
, psc
->base
.scr
, pcp
->hwContextID
);
560 pcp
->base
.destroyContext
= driDestroyContext
;
561 pcp
->base
.bindContext
= driBindContext
;
562 pcp
->base
.unbindContext
= driUnbindContext
;
568 driDestroyDrawable(__GLXDRIdrawable
* pdraw
)
570 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
572 (*psc
->core
->destroyDrawable
) (pdraw
->driDrawable
);
573 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, pdraw
->drawable
);
577 static __GLXDRIdrawable
*
578 driCreateDrawable(__GLXscreenConfigs
*base
,
580 GLXDrawable drawable
, const __GLcontextModes
* modes
)
582 __GLXDRIdrawable
*pdraw
;
583 drm_drawable_t hwDrawable
;
584 void *empty_attribute_list
= NULL
;
585 __GLXDRIconfigPrivate
*config
= (__GLXDRIconfigPrivate
*) modes
;
586 struct dri_screen
*psc
= (struct dri_screen
*) base
;
588 /* Old dri can't handle GLX 1.3+ drawable constructors. */
589 if (xDrawable
!= drawable
)
592 pdraw
= Xmalloc(sizeof(*pdraw
));
596 pdraw
->drawable
= drawable
;
597 pdraw
->psc
= &psc
->base
;
599 if (!XF86DRICreateDrawable(psc
->base
.dpy
, psc
->base
.scr
,
600 drawable
, &hwDrawable
)) {
605 /* Create a new drawable */
607 (*psc
->legacy
->createNewDrawable
) (psc
->base
.__driScreen
,
611 empty_attribute_list
, pdraw
);
613 if (!pdraw
->driDrawable
) {
614 XF86DRIDestroyDrawable(psc
->base
.dpy
, psc
->base
.scr
, drawable
);
619 pdraw
->destroyDrawable
= driDestroyDrawable
;
625 driSwapBuffers(__GLXDRIdrawable
* pdraw
, int64_t unused1
, int64_t unused2
,
628 struct dri_screen
*psc
= (struct dri_screen
*) pdraw
->psc
;
630 (*psc
->core
->swapBuffers
) (pdraw
->driDrawable
);
635 driCopySubBuffer(__GLXDRIdrawable
* pdraw
,
636 int x
, int y
, int width
, int height
)
638 (*pdraw
->psc
->driCopySubBuffer
->copySubBuffer
) (pdraw
->driDrawable
,
639 x
, y
, width
, height
);
643 driDestroyScreen(__GLXscreenConfigs
*base
)
645 struct dri_screen
*psc
= (struct dri_screen
*) base
;
647 /* Free the direct rendering per screen data */
648 if (psc
->base
.__driScreen
)
649 (*psc
->core
->destroyScreen
) (psc
->base
.__driScreen
);
650 psc
->base
.__driScreen
= NULL
;
652 dlclose(psc
->driver
);
655 static const struct glx_context_vtable dri_context_vtable
= {
660 static __GLXscreenConfigs
*
661 driCreateScreen(int screen
, __GLXdisplayPrivate
*priv
)
663 struct dri_display
*pdp
;
665 const __DRIextension
**extensions
;
666 struct dri_screen
*psc
;
670 psc
= Xcalloc(1, sizeof *psc
);
674 memset(psc
, 0, sizeof *psc
);
675 if (!glx_screen_init(&psc
->base
, screen
, priv
))
678 if (!driGetDriverName(priv
->dpy
, screen
, &driverName
)) {
683 psc
->driver
= driOpenDriver(driverName
);
685 if (psc
->driver
== NULL
) {
690 extensions
= dlsym(psc
->driver
, __DRI_DRIVER_EXTENSIONS
);
691 if (extensions
== NULL
) {
692 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
697 for (i
= 0; extensions
[i
]; i
++) {
698 if (strcmp(extensions
[i
]->name
, __DRI_CORE
) == 0)
699 psc
->core
= (__DRIcoreExtension
*) extensions
[i
];
700 if (strcmp(extensions
[i
]->name
, __DRI_LEGACY
) == 0)
701 psc
->legacy
= (__DRIlegacyExtension
*) extensions
[i
];
704 if (psc
->core
== NULL
|| psc
->legacy
== NULL
) {
709 pdp
= (struct dri_display
*) priv
->driDisplay
;
710 psc
->base
.__driScreen
=
711 CallCreateNewScreen(psc
->base
.dpy
, screen
, psc
, pdp
);
712 if (psc
->base
.__driScreen
== NULL
) {
713 dlclose(psc
->driver
);
718 extensions
= psc
->core
->getExtensions(psc
->base
.__driScreen
);
719 driBindExtensions(&psc
->base
, extensions
);
720 driBindCommonExtensions(&psc
->base
, extensions
);
722 psp
= &psc
->driScreen
;
723 psc
->base
.driScreen
= psp
;
724 if (psc
->base
.driCopySubBuffer
)
725 psp
->copySubBuffer
= driCopySubBuffer
;
727 psp
->destroyScreen
= driDestroyScreen
;
728 psp
->createContext
= driCreateContext
;
729 psp
->createDrawable
= driCreateDrawable
;
730 psp
->swapBuffers
= driSwapBuffers
;
734 psc
->base
.direct_context_vtable
= &dri_context_vtable
;
739 /* Called from __glXFreeDisplayPrivate.
742 driDestroyDisplay(__GLXDRIdisplay
* dpy
)
748 * Allocate, initialize and return a __DRIdisplayPrivate object.
749 * This is called from __glXInitialize() when we are given a new
752 _X_HIDDEN __GLXDRIdisplay
*
753 driCreateDisplay(Display
* dpy
)
755 struct dri_display
*pdpyp
;
756 int eventBase
, errorBase
;
757 int major
, minor
, patch
;
759 if (!XF86DRIQueryExtension(dpy
, &eventBase
, &errorBase
)) {
763 if (!XF86DRIQueryVersion(dpy
, &major
, &minor
, &patch
)) {
767 pdpyp
= Xmalloc(sizeof *pdpyp
);
772 pdpyp
->driMajor
= major
;
773 pdpyp
->driMinor
= minor
;
774 pdpyp
->driPatch
= patch
;
776 pdpyp
->base
.destroyDisplay
= driDestroyDisplay
;
777 pdpyp
->base
.createScreen
= driCreateScreen
;
782 #endif /* GLX_DIRECT_RENDERING */