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/extensions/Xfixes.h>
39
#include <X11/extensions/Xdamage.h>
40
#include "glxclient.h"
41
#include "glcontextmodes.h"
45
#include <sys/types.h>
48
#include "dri_common.h"
50
typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
51
typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
53
struct __GLXDRIdisplayPrivateRec {
57
** XFree86-DRI version information
64
struct __GLXDRIcontextPrivateRec {
66
__DRIcontext *driContext;
68
__GLXscreenConfigs *psc;
72
* Given a display pointer and screen number, determine the name of
73
* the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
74
* Return True for success, False for failure.
76
static Bool driGetDriverName(Display *dpy, int scrNum, char **driverName)
80
int driverMajor, driverMinor, driverPatch;
84
if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
85
ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
89
ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
93
b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
94
&driverPatch, driverName);
96
ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum);
100
InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
101
driverMajor, driverMinor, driverPatch, *driverName, scrNum);
107
* Exported function for querying the DRI driver for a given screen.
109
* The returned char pointer points to a static array that will be
110
* overwritten by subsequent calls.
112
PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) {
115
if (driGetDriverName(dpy, scrNum, &driverName)) {
119
len = strlen (driverName);
122
memcpy (ret, driverName, len+1);
130
* Exported function for obtaining a driver's option list (UTF-8 encoded XML).
132
* The returned char pointer points directly into the driver. Therefore
133
* it should be treated as a constant.
135
* If the driver was not found or does not support configuration NULL is
138
* Note: The driver remains opened after this function returns.
140
PUBLIC const char *glXGetDriverConfig (const char *driverName)
142
void *handle = driOpenDriver (driverName);
144
return dlsym (handle, "__driConfigOptions");
149
#ifdef XDAMAGE_1_1_INTERFACE
151
static GLboolean has_damage_post(Display *dpy)
153
static GLboolean inited = GL_FALSE;
154
static GLboolean has_damage;
159
if (XDamageQueryVersion(dpy, &major, &minor) &&
160
major == 1 && minor >= 1)
162
has_damage = GL_TRUE;
164
has_damage = GL_FALSE;
172
static void __glXReportDamage(__DRIdrawable *driDraw,
174
drm_clip_rect_t *rects, int num_rects,
175
GLboolean front_buffer,
179
XserverRegion region;
182
__GLXDRIdrawable *glxDraw = loaderPrivate;
183
__GLXscreenConfigs *psc = glxDraw->psc;
184
Display *dpy = psc->dpy;
187
if (!has_damage_post(dpy))
193
drawable = RootWindow(dpy, psc->scr);
197
drawable = glxDraw->xDrawable;
200
xrects = malloc(sizeof(XRectangle) * num_rects);
204
for (i = 0; i < num_rects; i++) {
205
xrects[i].x = rects[i].x1 + x_off;
206
xrects[i].y = rects[i].y1 + y_off;
207
xrects[i].width = rects[i].x2 - rects[i].x1;
208
xrects[i].height = rects[i].y2 - rects[i].y1;
210
region = XFixesCreateRegion(dpy, xrects, num_rects);
212
XDamageAdd(dpy, drawable, region);
213
XFixesDestroyRegion(dpy, region);
216
static const __DRIdamageExtension damageExtension = {
217
{ __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
224
__glXDRIGetDrawableInfo(__DRIdrawable *drawable,
225
unsigned int *index, unsigned int *stamp,
226
int *X, int *Y, int *W, int *H,
227
int *numClipRects, drm_clip_rect_t ** pClipRects,
228
int *backX, int *backY,
229
int *numBackClipRects, drm_clip_rect_t **pBackClipRects,
232
__GLXDRIdrawable *glxDraw = loaderPrivate;
233
__GLXscreenConfigs *psc = glxDraw->psc;
234
Display *dpy = psc->dpy;
236
return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
237
index, stamp, X, Y, W, H,
238
numClipRects, pClipRects,
240
numBackClipRects, pBackClipRects);
243
static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
244
{ __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION },
245
__glXDRIGetDrawableInfo
248
static const __DRIextension *loader_extensions[] = {
249
&systemTimeExtension.base,
250
&getDrawableInfoExtension.base,
251
#ifdef XDAMAGE_1_1_INTERFACE
252
&damageExtension.base,
257
#ifndef GLX_USE_APPLEGL
260
* Perform the required libGL-side initialization and call the client-side
261
* driver's \c __driCreateNewScreen function.
263
* \param dpy Display pointer.
264
* \param scrn Screen number on the display.
265
* \param psc DRI screen information.
266
* \param driDpy DRI display information.
267
* \param createNewScreen Pointer to the client-side driver's
268
* \c __driCreateNewScreen function.
269
* \returns A pointer to the \c __DRIscreenPrivate structure returned by
270
* the client-side driver on success, or \c NULL on failure.
273
CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
274
__GLXDRIdisplayPrivate * driDpy)
278
drmAddress pSAREA = MAP_FAILED;
280
__DRIversion ddx_version;
281
__DRIversion dri_version;
282
__DRIversion drm_version;
283
__DRIframebuffer framebuffer;
288
drmVersionPtr version;
293
const __DRIconfig **driver_configs;
295
/* DRI protocol version. */
296
dri_version.major = driDpy->driMajor;
297
dri_version.minor = driDpy->driMinor;
298
dri_version.patch = driDpy->driPatch;
300
framebuffer.base = MAP_FAILED;
301
framebuffer.dev_priv = NULL;
303
if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
304
ErrorMessageF("XF86DRIOpenConnection failed\n");
308
fd = drmOpenOnce(NULL, BusID, &newlyopened);
310
Xfree(BusID); /* No longer needed */
313
ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
317
if (drmGetMagic(fd, &magic)) {
318
ErrorMessageF("drmGetMagic failed\n");
322
version = drmGetVersion(fd);
324
drm_version.major = version->version_major;
325
drm_version.minor = version->version_minor;
326
drm_version.patch = version->version_patchlevel;
327
drmFreeVersion(version);
330
drm_version.major = -1;
331
drm_version.minor = -1;
332
drm_version.patch = -1;
335
if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
336
ErrorMessageF("XF86DRIAuthConnection failed\n");
340
/* Get device name (like "tdfx") and the ddx version numbers.
341
* We'll check the version in each DRI driver's "createNewScreen"
343
if (!XF86DRIGetClientDriverName(dpy, scrn,
348
ErrorMessageF("XF86DRIGetClientDriverName failed\n");
352
Xfree(driverName); /* No longer needed. */
355
* Get device-specific info. pDevPriv will point to a struct
356
* (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
357
* has information about the screen size, depth, pitch, ancilliary
358
* buffers, DRM mmap handles, etc.
360
if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
361
&framebuffer.size, &framebuffer.stride,
362
&framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
363
ErrorMessageF("XF86DRIGetDeviceInfo failed");
367
framebuffer.width = DisplayWidth(dpy, scrn);
368
framebuffer.height = DisplayHeight(dpy, scrn);
370
/* Map the framebuffer region. */
371
status = drmMap(fd, hFB, framebuffer.size,
372
(drmAddressPtr)&framebuffer.base);
374
ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
378
/* Map the SAREA region. Further mmap regions may be setup in
379
* each DRI driver's "createNewScreen" function.
381
status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
383
ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
387
psp = (*psc->legacy->createNewScreen)(scrn,
399
ErrorMessageF("Calling driver entry point failed");
403
psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
404
psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
409
if (pSAREA != MAP_FAILED)
410
drmUnmap(pSAREA, SAREA_MAX);
412
if (framebuffer.base != MAP_FAILED)
413
drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
415
if (framebuffer.dev_priv != NULL)
416
Xfree(framebuffer.dev_priv);
421
XF86DRICloseConnection(dpy, scrn);
423
ErrorMessageF("reverting to software direct rendering\n");
428
#else /* !GLX_USE_APPLEGL */
431
CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
432
__GLXDRIdisplayPrivate * driDpy)
437
#endif /* !GLX_USE_APPLEGL */
439
static void driDestroyContext(__GLXDRIcontext *context,
440
__GLXscreenConfigs *psc, Display *dpy)
442
__GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
444
(*psc->core->destroyContext)(pcp->driContext);
446
XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
450
static Bool driBindContext(__GLXDRIcontext *context,
451
__GLXDRIdrawable *draw, __GLXDRIdrawable *read)
453
__GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
454
const __DRIcoreExtension *core = pcp->psc->core;
456
return (*core->bindContext)(pcp->driContext,
461
static void driUnbindContext(__GLXDRIcontext *context)
463
__GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
464
const __DRIcoreExtension *core = pcp->psc->core;
466
(*core->unbindContext)(pcp->driContext);
469
static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc,
470
const __GLcontextModes *mode,
472
GLXContext shareList, int renderType)
474
__GLXDRIcontextPrivate *pcp, *pcp_shared;
475
drm_context_t hwContext;
476
__DRIcontext *shared = NULL;
477
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
479
if (!psc || !psc->driScreen)
483
pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
484
shared = pcp_shared->driContext;
487
pcp = Xmalloc(sizeof *pcp);
492
if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
494
&pcp->hwContextID, &hwContext)) {
500
(*psc->legacy->createNewContext)(psc->__driScreen,
506
if (pcp->driContext == NULL) {
507
XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
512
pcp->base.destroyContext = driDestroyContext;
513
pcp->base.bindContext = driBindContext;
514
pcp->base.unbindContext = driUnbindContext;
519
static void driDestroyDrawable(__GLXDRIdrawable *pdraw)
521
__GLXscreenConfigs *psc = pdraw->psc;
523
(*psc->core->destroyDrawable)(pdraw->driDrawable);
524
XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
528
static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc,
530
GLXDrawable drawable,
531
const __GLcontextModes *modes)
533
__GLXDRIdrawable *pdraw;
534
drm_drawable_t hwDrawable;
535
void *empty_attribute_list = NULL;
536
__GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
538
/* Old dri can't handle GLX 1.3+ drawable constructors. */
539
if (xDrawable != drawable)
542
pdraw = Xmalloc(sizeof(*pdraw));
546
pdraw->drawable = drawable;
549
if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable))
552
/* Create a new drawable */
554
(*psc->legacy->createNewDrawable)(psc->__driScreen,
558
empty_attribute_list,
561
if (!pdraw->driDrawable) {
562
XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
567
pdraw->destroyDrawable = driDestroyDrawable;
572
static void driSwapBuffers(__GLXDRIdrawable *pdraw)
574
(*pdraw->psc->core->swapBuffers)(pdraw->driDrawable);
577
static void driCopySubBuffer(__GLXDRIdrawable *pdraw,
578
int x, int y, int width, int height)
580
(*pdraw->psc->driCopySubBuffer->copySubBuffer)(pdraw->driDrawable,
581
x, y, width, height);
584
static void driDestroyScreen(__GLXscreenConfigs *psc)
586
/* Free the direct rendering per screen data */
587
if (psc->__driScreen)
588
(*psc->core->destroyScreen)(psc->__driScreen);
589
psc->__driScreen = NULL;
591
dlclose(psc->driver);
594
static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen,
595
__GLXdisplayPrivate *priv)
597
__GLXDRIdisplayPrivate *pdp;
599
const __DRIextension **extensions;
603
psp = Xmalloc(sizeof *psp);
607
/* Initialize per screen dynamic client GLX extensions */
608
psc->ext_list_first_time = GL_TRUE;
610
if (!driGetDriverName(priv->dpy, screen, &driverName)) {
615
psc->driver = driOpenDriver(driverName);
617
if (psc->driver == NULL) {
622
extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
623
if (extensions == NULL) {
624
ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
629
for (i = 0; extensions[i]; i++) {
630
if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
631
psc->core = (__DRIcoreExtension *) extensions[i];
632
if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
633
psc->legacy = (__DRIlegacyExtension *) extensions[i];
636
if (psc->core == NULL || psc->legacy == NULL) {
641
pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
643
CallCreateNewScreen(psc->dpy, screen, psc, pdp);
644
if (psc->__driScreen == NULL) {
645
dlclose(psc->driver);
650
driBindExtensions(psc, 0);
651
if (psc->driCopySubBuffer)
652
psp->copySubBuffer = driCopySubBuffer;
654
psp->destroyScreen = driDestroyScreen;
655
psp->createContext = driCreateContext;
656
psp->createDrawable = driCreateDrawable;
657
psp->swapBuffers = driSwapBuffers;
664
/* Called from __glXFreeDisplayPrivate.
666
static void driDestroyDisplay(__GLXDRIdisplay *dpy)
672
* Allocate, initialize and return a __DRIdisplayPrivate object.
673
* This is called from __glXInitialize() when we are given a new
676
_X_HIDDEN __GLXDRIdisplay *driCreateDisplay(Display *dpy)
678
__GLXDRIdisplayPrivate *pdpyp;
679
int eventBase, errorBase;
680
int major, minor, patch;
682
if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
686
if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
690
pdpyp = Xmalloc(sizeof *pdpyp);
695
pdpyp->driMajor = major;
696
pdpyp->driMinor = minor;
697
pdpyp->driPatch = patch;
699
pdpyp->base.destroyDisplay = driDestroyDisplay;
700
pdpyp->base.createScreen = driCreateScreen;
705
#endif /* GLX_DIRECT_RENDERING */