2
* Copyright © 2006 Red Hat, Inc
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of Red Hat,
9
* Inc not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior
11
* permission. Red Hat, Inc makes no representations about the
12
* suitability of this software for any purpose. It is provided "as
13
* is" without express or implied warranty.
15
* RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
#ifdef HAVE_DIX_CONFIG_H
25
#include <dix-config.h>
37
#include <GL/internal/dri_interface.h>
39
#include <windowstr.h>
42
#define _XF86DRI_SERVER_
43
#include <drm_sarea.h>
45
#include <xf86dristr.h>
50
#define DRI_NEW_INTERFACE_ONLY
51
#include "glxserver.h"
53
#include "glcontextmodes.h"
55
#include "g_disptab.h"
56
#include "g_disptab_EXT.h"
57
#include "glapitable.h"
63
#define STRINGIFY(macro_or_string) STRINGIFY_ARG (macro_or_string)
64
#define STRINGIFY_ARG(contents) #contents
66
typedef struct __GLXDRIscreen __GLXDRIscreen;
67
typedef struct __GLXDRIcontext __GLXDRIcontext;
68
typedef struct __GLXDRIdrawable __GLXDRIdrawable;
70
struct __GLXDRIscreen {
73
__DRIscreen driScreen;
77
struct __GLXDRIcontext {
80
__DRIcontext driContext;
83
struct __GLXDRIdrawable {
86
__DRIdrawable *driDrawable;
90
* 20021121 - Initial version
91
* 20021128 - Added __glXWindowExists() function
92
* 20021207 - Added support for dynamic GLX extensions,
93
* GLX_SGI_swap_control, GLX_SGI_video_sync,
94
* GLX_OML_sync_control, and GLX_MESA_swap_control.
95
* Never officially released. Do NOT test against
96
* this version. Use 20030317 instead.
97
* 20030317 - Added support GLX_SGIX_fbconfig,
98
* GLX_MESA_swap_frame_usage, GLX_OML_swap_method,
99
* GLX_{ARB,SGIS}_multisample, and
100
* GLX_SGIX_visual_select_group.
101
* 20030606 - Added support for GLX_SGI_make_current_read.
102
* 20030813 - Made support for dynamic extensions multi-head aware.
103
* 20030818 - Added support for GLX_MESA_allocate_memory in place of the
104
* deprecated GLX_NV_vertex_array_range & GLX_MESA_agp_offset
106
* 20031201 - Added support for the first round of DRI interface changes.
107
* Do NOT test against this version! It has binary
108
* compatibility bugs, use 20040317 instead.
109
* 20040317 - Added the 'mode' field to __DRIcontextRec.
110
* 20040415 - Added support for bindContext3 and unbindContext3.
111
* 20040602 - Add __glXGetDrawableInfo. I though that was there
113
* 20050727 - Gut all the old interfaces. This breaks compatability with
114
* any DRI driver built to any previous version.
116
#define INTERNAL_VERSION 20050727
118
static const char CREATE_NEW_SCREEN_FUNC[] =
119
"__driCreateNewScreen_" STRINGIFY (INTERNAL_VERSION);
122
__glXDRIleaveServer(void)
126
for (i = 0; i < screenInfo.numScreens; i++)
127
DRIDoBlockHandler(i, NULL, NULL, NULL);
131
__glXDRIenterServer(void)
135
for (i = 0; i < screenInfo.numScreens; i++)
136
DRIDoWakeupHandler(i, NULL, 0, NULL);
140
__glXDRIdrawableDestroy(__GLXdrawable *private)
143
(*glxPriv->driDrawable.destroyDrawable)(NULL,
144
glxPriv->driDrawable.private);
151
__glXDRIdrawableResize(__GLXdrawable *glxPriv)
153
/* Nothing to do here, the DRI driver asks the server for drawable
154
* geometry when it sess the SAREA timestamps change.*/
160
__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate)
162
__GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
163
__GLXDRIscreen *screen;
165
/* FIXME: We're jumping through hoops here to get the DRIdrawable
166
* which the dri driver tries to keep to it self... cf. FIXME in
169
screen = (__GLXDRIscreen *) __glXgetActiveScreen(private->base.pDraw->pScreen->myNum);
170
private->driDrawable = (screen->driScreen.getDrawable)(NULL,
171
private->base.drawId,
172
screen->driScreen.private);
174
(*private->driDrawable->swapBuffers)(NULL,
175
private->driDrawable->private);
180
static __GLXdrawable *
181
__glXDRIcontextCreateDrawable(__GLXcontext *context,
185
__GLXDRIdrawable *private;
187
private = xalloc(sizeof *private);
191
memset(private, 0, sizeof *private);
193
if (!__glXDrawableInit(&private->base, context, pDraw, drawId)) {
198
private->base.destroy = __glXDRIdrawableDestroy;
199
private->base.resize = __glXDRIdrawableResize;
200
private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
203
/* FIXME: It would only be natural that we called
204
* driScreen->createNewDrawable here but the DRI drivers manage
205
* them a little oddly. FIXME: describe this better.*/
207
/* The last argument is 'attrs', which is used with pbuffers which
208
* we currently don't support. */
210
glxPriv->driDrawable.private =
211
(pGlxScreen->driScreen.createNewDrawable)(NULL, modes,
213
&glxPriv->driDrawable,
218
return &private->base;
223
__glXDRIcontextDestroy(__GLXcontext *baseContext)
225
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
227
context->driContext.destroyContext(NULL,
228
context->base.pScreen->myNum,
229
context->driContext.private);
230
__glXContextDestroy(&context->base);
235
__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
237
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
239
return (*context->driContext.bindContext)(NULL,
240
context->base.pScreen->myNum,
241
baseContext->drawPriv->drawId,
242
baseContext->readPriv->drawId,
243
&context->driContext);
247
__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
249
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
251
return (*context->driContext.unbindContext)(NULL,
252
context->base.pScreen->myNum,
253
baseContext->drawPriv->drawId,
254
baseContext->readPriv->drawId,
255
&context->driContext);
259
__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
262
__GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
263
__GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
265
/* FIXME: We will need to add DRIcontext::copyContext for this. */
274
__glXDRIcontextForceCurrent(__GLXcontext *baseContext)
276
__GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
278
return (*context->driContext.bindContext)(NULL,
279
context->base.pScreen->myNum,
280
baseContext->drawPriv->drawId,
281
baseContext->readPriv->drawId,
282
&context->driContext);
286
glxCountBits(int word)
299
glxFillAlphaChannel (PixmapPtr pixmap)
302
CARD32 *pixels = (CARD32 *)pixmap->devPrivate.ptr;
303
CARD32 rowstride = pixmap->devKind / 4;
306
x = pixmap->drawable.x;
307
y = pixmap->drawable.y;
309
for (i = y; i < pixmap->drawable.height + y; ++i)
311
for (j = x; j < pixmap->drawable.width + x; ++j)
313
int index = i * rowstride + j;
315
pixels[index] |= 0xFF000000;
321
* (sticking this here for lack of a better place)
322
* Known issues with the GLX_EXT_texture_from_pixmap implementation:
323
* - In general we ignore the fbconfig, lots of examples follow
324
* - No fbconfig handling for multiple mipmap levels
325
* - No fbconfig handling for 1D textures
326
* - No fbconfig handling for TEXTURE_TARGET
327
* - No fbconfig exposure of Y inversion state
328
* - No GenerateMipmapEXT support (due to no FBO support)
329
* - No damage tracking between binds
330
* - No support for anything but 16bpp and 32bpp-sparse pixmaps
334
__glXDRIbindTexImage(__GLXcontext *baseContext,
336
__GLXpixmap *glxPixmap)
342
pixmap = (PixmapPtr) glxPixmap->pDraw;
343
bpp = pixmap->drawable.depth >= 24 ? 4 : 2; /* XXX 24bpp packed, 8, etc */
345
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
346
pixmap->devKind / bpp) );
347
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS,
348
pixmap->drawable.y) );
349
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS,
350
pixmap->drawable.x) );
352
if (pixmap->drawable.depth == 24)
353
glxFillAlphaChannel(pixmap);
355
npot = !(glxCountBits(pixmap->drawable.width) == 1 &&
356
glxCountBits(pixmap->drawable.height) == 1) /* ||
357
strstr(CALL_GetString(GL_EXTENSIONS,
358
"GL_ARB_texture_non_power_of_two")) */ ;
360
CALL_TexImage2D( GET_DISPATCH(),
361
( npot ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D,
364
pixmap->drawable.width,
365
pixmap->drawable.height,
367
bpp == 4 ? GL_BGRA : GL_RGB,
368
bpp == 4 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
369
pixmap->devPrivate.ptr ) );
375
__glXDRIreleaseTexImage(__GLXcontext *baseContext,
382
static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
383
__glXDRIbindTexImage,
384
__glXDRIreleaseTexImage
388
__glXDRIscreenDestroy(__GLXscreen *baseScreen)
390
__GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
392
screen->driScreen.destroyScreen(NULL,
393
screen->base.pScreen->myNum,
394
screen->driScreen.private);
396
dlclose(screen->driver);
398
__glXScreenDestroy(baseScreen);
403
static __GLXcontext *
404
__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
405
__GLcontextModes *modes,
406
__GLXcontext *baseShareContext)
408
__GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
409
__GLXDRIcontext *context, *shareContext;
412
shareContext = (__GLXDRIcontext *) baseShareContext;
414
sharePrivate = shareContext->driContext.private;
418
context = xalloc(sizeof *context);
422
memset(context, 0, sizeof *context);
423
context->base.destroy = __glXDRIcontextDestroy;
424
context->base.makeCurrent = __glXDRIcontextMakeCurrent;
425
context->base.loseCurrent = __glXDRIcontextLoseCurrent;
426
context->base.copy = __glXDRIcontextCopy;
427
context->base.forceCurrent = __glXDRIcontextForceCurrent;
428
context->base.createDrawable = __glXDRIcontextCreateDrawable;
430
context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
432
context->driContext.private =
433
screen->driScreen.createNewContext(NULL, modes,
436
&context->driContext);
438
context->driContext.mode = modes;
440
return &context->base;
444
filter_modes(__GLcontextModes **server_modes,
445
const __GLcontextModes *driver_modes)
447
__GLcontextModes * m;
448
__GLcontextModes ** prev_next;
449
const __GLcontextModes * check;
450
unsigned modes_count = 0;
452
if ( driver_modes == NULL ) {
453
LogMessage(X_WARNING,
454
"AIGLX: 3D driver returned no fbconfigs.\n");
458
/* For each mode in server_modes, check to see if a matching mode exists
459
* in driver_modes. If not, then the mode is not available.
462
prev_next = server_modes;
463
for ( m = *prev_next ; m != NULL ; m = *prev_next ) {
464
GLboolean do_delete = GL_TRUE;
466
for ( check = driver_modes ; check != NULL ; check = check->next ) {
467
if ( _gl_context_modes_are_same( m, check ) ) {
468
do_delete = GL_FALSE;
473
/* The 3D has to support all the modes that match the GLX visuals
474
* sent from the X server.
476
if ( do_delete && (m->visualID != 0) ) {
477
do_delete = GL_FALSE;
479
LogMessage(X_WARNING,
480
"AIGLX: 3D driver claims to not support "
481
"visual 0x%02x\n", m->visualID);
485
*prev_next = m->next;
488
_gl_context_modes_destroy( m );
492
prev_next = & m->next;
500
static __DRIfuncPtr getProcAddress(const char *proc_name)
505
static __DRIscreen *findScreen(__DRInativeDisplay *dpy, int scrn)
507
__GLXDRIscreen *screen =
508
(__GLXDRIscreen *) __glXgetActiveScreen(scrn);
510
return &screen->driScreen;
513
static GLboolean windowExists(__DRInativeDisplay *dpy, __DRIid draw)
515
WindowPtr pWin = (WindowPtr) LookupIDByType(draw, RT_WINDOW);
517
return pWin == NULL ? GL_FALSE : GL_TRUE;
520
static GLboolean createContext(__DRInativeDisplay *dpy, int screen,
521
int configID, void *contextID,
522
drm_context_t *hw_context)
530
pScreen = screenInfo.screens[screen];
532
/* Find the requested X visual */
533
visual = pScreen->visuals;
534
for (i = 0; i < pScreen->numVisuals; i++, visual++)
535
if (visual->vid == configID)
537
if (i == pScreen->numVisuals)
540
fakeID = FakeClientID(0);
541
*(XID *) contextID = fakeID;
543
__glXDRIenterServer();
544
retval = DRICreateContext(pScreen, visual, fakeID, hw_context);
545
__glXDRIleaveServer();
549
static GLboolean destroyContext(__DRInativeDisplay *dpy, int screen,
554
__glXDRIenterServer();
555
retval = DRIDestroyContext(screenInfo.screens[screen], context);
556
__glXDRIleaveServer();
561
createDrawable(__DRInativeDisplay *dpy, int screen,
562
__DRIid drawable, drm_drawable_t *hHWDrawable)
564
DrawablePtr pDrawable;
567
pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE);
571
__glXDRIenterServer();
572
retval = DRICreateDrawable(screenInfo.screens[screen],
576
__glXDRIleaveServer();
581
destroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable)
583
DrawablePtr pDrawable;
586
pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE);
590
__glXDRIenterServer();
591
retval = DRIDestroyDrawable(screenInfo.screens[screen],
594
__glXDRIleaveServer();
599
getDrawableInfo(__DRInativeDisplay *dpy, int screen,
600
__DRIid drawable, unsigned int *index, unsigned int *stamp,
601
int *x, int *y, int *width, int *height,
602
int *numClipRects, drm_clip_rect_t **ppClipRects,
603
int *backX, int *backY,
604
int *numBackClipRects, drm_clip_rect_t **ppBackClipRects)
606
DrawablePtr pDrawable;
607
drm_clip_rect_t *pClipRects, *pBackClipRects;
611
pDrawable = (DrawablePtr) LookupIDByClass(drawable, RC_DRAWABLE);
613
ErrorF("getDrawableInfo failed to look up window\n");
625
*numBackClipRects = 0;
626
*ppBackClipRects = NULL;
631
__glXDRIenterServer();
632
retval = DRIGetDrawableInfo(screenInfo.screens[screen],
633
pDrawable, index, stamp,
635
numClipRects, &pClipRects,
637
numBackClipRects, &pBackClipRects);
638
__glXDRIleaveServer();
640
if (*numClipRects > 0) {
641
size = sizeof (drm_clip_rect_t) * *numClipRects;
642
*ppClipRects = xalloc (size);
643
if (*ppClipRects != NULL)
644
memcpy (*ppClipRects, pClipRects, size);
650
if (*numBackClipRects > 0) {
651
size = sizeof (drm_clip_rect_t) * *numBackClipRects;
652
*ppBackClipRects = xalloc (size);
653
if (*ppBackClipRects != NULL)
654
memcpy (*ppBackClipRects, pBackClipRects, size);
657
*ppBackClipRects = NULL;
671
if (gettimeofday(&tv, NULL) == 0) {
672
ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
679
/* Table of functions that we export to the driver. */
680
static const __DRIinterfaceMethods interface_methods = {
683
_gl_context_modes_create,
684
_gl_context_modes_destroy,
697
NULL, /* glXGetMscRateOML, */
700
static const char dri_driver_path[] = DRI_DRIVER_PATH;
703
__glXDRIscreenProbe(ScreenPtr pScreen)
705
PFNCREATENEWSCREENFUNC createNewScreen;
707
drmAddress pSAREA = NULL;
709
__DRIversion ddx_version;
710
__DRIversion dri_version;
711
__DRIversion drm_version;
712
__DRIframebuffer framebuffer;
715
int api_ver = INTERNAL_VERSION;
717
drmVersionPtr version;
721
__GLcontextModes * driver_modes;
722
__GLXDRIscreen *screen;
723
void *dev_priv = NULL;
727
if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable")) {
728
LogMessage(X_ERROR, "AIGLX: DRI module not loaded\n");
732
if (!DRIQueryDirectRenderingCapable(pScreen, &isCapable) || !isCapable) {
734
"AIGLX: Screen %d is not DRI capable\n", pScreen->myNum);
738
screen = xalloc(sizeof *screen);
741
memset(screen, 0, sizeof *screen);
743
screen->base.destroy = __glXDRIscreenDestroy;
744
screen->base.createContext = __glXDRIscreenCreateContext;
745
screen->base.pScreen = pScreen;
747
/* DRI protocol version. */
748
dri_version.major = XF86DRI_MAJOR_VERSION;
749
dri_version.minor = XF86DRI_MINOR_VERSION;
750
dri_version.patch = XF86DRI_PATCH_VERSION;
752
framebuffer.base = NULL;
753
framebuffer.dev_priv = NULL;
755
if (!DRIOpenConnection(pScreen, &hSAREA, &BusID)) {
756
LogMessage(X_ERROR, "AIGLX error: DRIOpenConnection failed\n");
760
fd = drmOpen(NULL, BusID);
763
LogMessage(X_ERROR, "AIGLX error: drmOpen failed (%s)\n",
768
if (drmGetMagic(fd, &magic)) {
769
LogMessage(X_ERROR, "AIGLX error: drmGetMagic failed\n");
773
version = drmGetVersion(fd);
775
drm_version.major = version->version_major;
776
drm_version.minor = version->version_minor;
777
drm_version.patch = version->version_patchlevel;
778
drmFreeVersion(version);
781
drm_version.major = -1;
782
drm_version.minor = -1;
783
drm_version.patch = -1;
786
if (!DRIAuthConnection(pScreen, magic)) {
787
LogMessage(X_ERROR, "AIGLX error: DRIAuthConnection failed\n");
791
/* Get device name (like "tdfx") and the ddx version numbers.
792
* We'll check the version in each DRI driver's "createNewScreen"
794
if (!DRIGetClientDriverName(pScreen,
799
LogMessage(X_ERROR, "AIGLX error: DRIGetClientDriverName failed\n");
803
snprintf(filename, sizeof filename, "%s/%s_dri.so",
804
dri_driver_path, driverName);
806
screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
807
if (screen->driver == NULL) {
808
LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
809
filename, dlerror());
813
createNewScreen = dlsym(screen->driver, CREATE_NEW_SCREEN_FUNC);
814
if (createNewScreen == NULL) {
815
LogMessage(X_ERROR, "AIGLX error: dlsym for %s failed (%s)\n",
816
CREATE_NEW_SCREEN_FUNC, dlerror());
821
* Get device-specific info. pDevPriv will point to a struct
822
* (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
823
* has information about the screen size, depth, pitch, ancilliary
824
* buffers, DRM mmap handles, etc.
826
if (!DRIGetDeviceInfo(pScreen, &hFB, &junk,
827
&framebuffer.size, &framebuffer.stride,
828
&framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
829
LogMessage(X_ERROR, "AIGLX error: XF86DRIGetDeviceInfo failed");
833
/* Sigh... the DRI interface is broken; the DRI driver will free
834
* the dev private pointer using _mesa_free() on screen destroy,
835
* but we can't use _mesa_malloc() here. In fact, the DRI driver
836
* shouldn't free data it didn't allocate itself, but what can you
838
dev_priv = xalloc(framebuffer.dev_priv_size);
839
if (dev_priv == NULL) {
840
LogMessage(X_ERROR, "AIGLX error: dev_priv allocation failed");
843
memcpy(dev_priv, framebuffer.dev_priv, framebuffer.dev_priv_size);
844
framebuffer.dev_priv = dev_priv;
846
framebuffer.width = pScreen->width;
847
framebuffer.height = pScreen->height;
849
/* Map the framebuffer region. */
850
status = drmMap(fd, hFB, framebuffer.size,
851
(drmAddressPtr)&framebuffer.base);
853
LogMessage(X_ERROR, "AIGLX error: drmMap of framebuffer failed (%s)",
858
/* Map the SAREA region. Further mmap regions may be setup in
859
* each DRI driver's "createNewScreen" function.
861
status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
863
LogMessage(X_ERROR, "AIGLX error: drmMap of SAREA failed (%s)",
869
screen->driScreen.private =
870
(*createNewScreen)(NULL, pScreen->myNum,
883
if (screen->driScreen.private == NULL) {
884
LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed");
888
__glXScreenInit(&screen->base, pScreen);
890
filter_modes(&screen->base.modes, driver_modes);
891
_gl_context_modes_destroy(driver_modes);
893
__glXsetEnterLeaveServerFuncs(__glXDRIenterServer, __glXDRIleaveServer);
896
"AIGLX: Loaded and initialized %s\n", filename);
898
return &screen->base;
902
drmUnmap(pSAREA, SAREA_MAX);
904
if (framebuffer.base != NULL)
905
drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
907
if (dev_priv != NULL)
913
DRICloseConnection(pScreen);
916
dlclose(screen->driver);
920
LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
925
__GLXprovider __glXDRIProvider = {