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>
38 #include <GL/glxtokens.h>
40 #include <windowstr.h>
44 #define _XF86DRI_SERVER_
45 #include <drm_sarea.h>
47 #include <X11/dri/xf86driproto.h>
54 #define DRI_NEW_INTERFACE_ONLY
55 #include "glxserver.h"
57 #include "glxdricommon.h"
59 #include "g_disptab.h"
60 #include "glapitable.h"
64 #include "extension_string.h"
66 typedef struct __GLXDRIscreen __GLXDRIscreen;
67 typedef struct __GLXDRIcontext __GLXDRIcontext;
68 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
70 struct __GLXDRIscreen {
72 __DRIscreen *driScreen;
75 xf86EnterVTProc *enterVT;
76 xf86LeaveVTProc *leaveVT;
78 const __DRIcoreExtension *core;
79 const __DRIlegacyExtension *legacy;
80 const __DRIcopySubBufferExtension *copySubBuffer;
81 const __DRIswapControlExtension *swapControl;
83 #ifdef __DRI_TEX_OFFSET
84 const __DRItexOffsetExtension *texOffset;
85 DRITexOffsetStartProcPtr texOffsetStart;
86 DRITexOffsetFinishProcPtr texOffsetFinish;
87 __GLXDRIdrawable *texOffsetOverride[16];
88 GLuint lastTexOffsetOverride;
91 unsigned char glx_enable_bits[__GLX_EXT_BYTES];
94 struct __GLXDRIcontext {
96 __DRIcontext *driContext;
100 struct __GLXDRIdrawable {
102 __DRIdrawable *driDrawable;
104 /* Pulled in from old __GLXpixmap */
105 #ifdef __DRI_TEX_OFFSET
107 __GLXDRIcontext *ctx;
108 unsigned long long offset;
114 __glXDRIleaveServer(GLboolean rendering)
118 for (i = 0; rendering && i < screenInfo.numScreens; i++) {
119 __GLXDRIscreen * const screen =
120 (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]);
121 GLuint lastOverride = screen->lastTexOffsetOverride;
124 __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
127 for (j = 0; j < lastOverride; j++) {
128 __GLXDRIdrawable *pGlxPix = texOffsetOverride[j];
130 if (pGlxPix && pGlxPix->texname) {
132 screen->texOffsetStart((PixmapPtr)pGlxPix->base.pDraw);
138 DRIBlockHandler(NULL, NULL, NULL);
140 for (i = 0; rendering && i < screenInfo.numScreens; i++) {
141 __GLXDRIscreen * const screen =
142 (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]);
143 GLuint lastOverride = screen->lastTexOffsetOverride;
146 __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
149 for (j = 0; j < lastOverride; j++) {
150 __GLXDRIdrawable *pGlxPix = texOffsetOverride[j];
152 if (pGlxPix && pGlxPix->texname) {
153 screen->texOffset->setTexOffset(pGlxPix->ctx->driContext,
156 pGlxPix->base.pDraw->depth,
157 ((PixmapPtr)pGlxPix->base.pDraw)->devKind);
165 __glXDRIenterServer(GLboolean rendering)
169 for (i = 0; rendering && i < screenInfo.numScreens; i++) {
170 __GLXDRIscreen * const screen = (__GLXDRIscreen *)
171 glxGetScreen(screenInfo.screens[i]);
173 if (screen->lastTexOffsetOverride) {
174 CALL_Flush(GET_DISPATCH(), ());
179 DRIWakeupHandler(NULL, 0, NULL);
184 __glXDRIdoReleaseTexImage(__GLXDRIscreen *screen, __GLXDRIdrawable *drawable)
186 GLuint lastOverride = screen->lastTexOffsetOverride;
189 __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
192 for (i = 0; i < lastOverride; i++) {
193 if (texOffsetOverride[i] == drawable) {
194 if (screen->texOffsetFinish)
195 screen->texOffsetFinish((PixmapPtr)drawable->base.pDraw);
197 texOffsetOverride[i] = NULL;
199 if (i + 1 == lastOverride) {
203 if (texOffsetOverride[i]) {
204 lastOverride = i + 1;
209 screen->lastTexOffsetOverride = lastOverride;
220 __glXDRIdrawableDestroy(__GLXdrawable *drawable)
222 __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
223 __GLXDRIscreen *screen;
226 for (i = 0; i < screenInfo.numScreens; i++) {
227 screen = (__GLXDRIscreen *) glxGetScreen(screenInfo.screens[i]);
228 __glXDRIdoReleaseTexImage(screen, private);
231 /* If the X window was destroyed, the dri DestroyWindow hook will
232 * aready have taken care of this, so only call if pDraw isn't NULL. */
233 if (drawable->pDraw != NULL) {
234 screen = (__GLXDRIscreen *) glxGetScreen(drawable->pDraw->pScreen);
235 (*screen->core->destroyDrawable)(private->driDrawable);
237 __glXenterServer(GL_FALSE);
238 DRIDestroyDrawable(drawable->pDraw->pScreen,
239 serverClient, drawable->pDraw);
240 __glXleaveServer(GL_FALSE);
243 __glXDrawableRelease(drawable);
249 __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate)
251 __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
252 __GLXDRIscreen *screen =
253 (__GLXDRIscreen *) glxGetScreen(basePrivate->pDraw->pScreen);
255 (*screen->core->swapBuffers)(private->driDrawable);
262 __glXDRIdrawableSwapInterval(__GLXdrawable *baseDrawable, int interval)
264 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseDrawable;
265 __GLXDRIscreen *screen =
266 (__GLXDRIscreen *) glxGetScreen(baseDrawable->pDraw->pScreen);
268 if (screen->swapControl)
269 screen->swapControl->setSwapInterval(draw->driDrawable, interval);
276 __glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate,
277 int x, int y, int w, int h)
279 __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate;
280 __GLXDRIscreen *screen = (__GLXDRIscreen *)
281 glxGetScreen(basePrivate->pDraw->pScreen);
283 if (screen->copySubBuffer)
284 screen->copySubBuffer->copySubBuffer(private->driDrawable, x, y, w, h);
288 __glXDRIcontextDestroy(__GLXcontext *baseContext)
290 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
291 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
294 screen->core->destroyContext(context->driContext);
296 __glXenterServer(GL_FALSE);
297 retval = DRIDestroyContext(baseContext->pGlxScreen->pScreen,
298 context->hwContextID);
299 __glXleaveServer(GL_FALSE);
301 __glXContextDestroy(&context->base);
306 __glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
308 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
309 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
310 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
311 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
313 return (*screen->core->bindContext)(context->driContext,
319 __glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
321 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
322 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
324 return (*screen->core->unbindContext)(context->driContext);
328 __glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
331 __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
332 __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
333 __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
335 return (*screen->core->copyContext)(dst->driContext,
336 src->driContext, mask);
340 __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
342 __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
343 __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
344 __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
345 __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
347 return (*screen->core->bindContext)(context->driContext,
353 glxFillAlphaChannel (CARD32 *pixels, CARD32 rowstride, int width, int height)
360 for (i = 0; i < height; i++)
371 testTexOffset(__GLXDRIscreen * const screen, PixmapPtr pPixmap)
375 if (!screen->texOffsetStart || !screen->texOffset)
378 __glXenterServer(GL_FALSE);
379 ret = screen->texOffsetStart(pPixmap) != ~0ULL;
380 __glXleaveServer(GL_FALSE);
386 * (sticking this here for lack of a better place)
387 * Known issues with the GLX_EXT_texture_from_pixmap implementation:
388 * - In general we ignore the fbconfig, lots of examples follow
389 * - No fbconfig handling for multiple mipmap levels
390 * - No fbconfig handling for 1D textures
391 * - No fbconfig handling for TEXTURE_TARGET
392 * - No fbconfig exposure of Y inversion state
393 * - No GenerateMipmapEXT support (due to no FBO support)
394 * - No support for anything but 16bpp and 32bpp-sparse pixmaps
398 __glXDRIbindTexImage(__GLXcontext *baseContext,
400 __GLXdrawable *glxPixmap)
402 RegionPtr pRegion = NULL;
404 int bpp, override = 0, texname;
406 ScreenPtr pScreen = glxPixmap->pDraw->pScreen;
407 __GLXDRIdrawable *driDraw = (__GLXDRIdrawable *) glxPixmap;
408 __GLXDRIscreen * const screen = (__GLXDRIscreen *) glxGetScreen(pScreen);
410 CALL_GetIntegerv(GET_DISPATCH(), (glxPixmap->target == GL_TEXTURE_2D ?
411 GL_TEXTURE_BINDING_2D :
412 GL_TEXTURE_BINDING_RECTANGLE_NV,
416 return __glXError(GLXBadContextState);
418 pixmap = (PixmapPtr) glxPixmap->pDraw;
420 if (testTexOffset(screen, pixmap)) {
421 __GLXDRIdrawable **texOffsetOverride = screen->texOffsetOverride;
422 int i, firstEmpty = 16;
424 for (i = 0; i < 16; i++) {
425 if (texOffsetOverride[i] == driDraw)
428 if (firstEmpty == 16 && !texOffsetOverride[i])
432 if (firstEmpty == 16) {
433 ErrorF("%s: Failed to register texture offset override\n", __func__);
437 if (firstEmpty >= screen->lastTexOffsetOverride)
438 screen->lastTexOffsetOverride = firstEmpty + 1;
440 texOffsetOverride[firstEmpty] = driDraw;
445 driDraw->ctx = (__GLXDRIcontext*)baseContext;
447 if (texname == driDraw->texname)
450 driDraw->texname = texname;
452 screen->texOffset->setTexOffset(driDraw->ctx->driContext, texname, 0,
453 pixmap->drawable.depth,
458 if (!driDraw->pDamage) {
460 driDraw->pDamage = DamageCreate(NULL, NULL, DamageReportNone,
461 TRUE, pScreen, NULL);
462 if (!driDraw->pDamage)
465 DamageRegister ((DrawablePtr) pixmap, driDraw->pDamage);
470 pRegion = DamageRegion(driDraw->pDamage);
471 if (RegionNil(pRegion))
475 /* XXX 24bpp packed, 8, etc */
476 if (pixmap->drawable.depth >= 24) {
480 #if X_BYTE_ORDER == X_BIG_ENDIAN
481 !override ? GL_UNSIGNED_INT_8_8_8_8_REV :
487 type = GL_UNSIGNED_SHORT_5_6_5;
495 unsigned pitch = PixmapBytePad(pixmap->drawable.width,
496 pixmap->drawable.depth);
498 data = malloc(pitch * pixmap->drawable.height);
500 __glXenterServer(GL_FALSE);
501 pScreen->GetImage(&pixmap->drawable, 0 /*pixmap->drawable.x*/,
502 0 /*pixmap->drawable.y*/, pixmap->drawable.width,
503 pixmap->drawable.height, ZPixmap, ~0, data);
504 __glXleaveServer(GL_FALSE);
506 if (pixmap->drawable.depth == 24)
507 glxFillAlphaChannel(data,
509 pixmap->drawable.width,
510 pixmap->drawable.height);
512 CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
514 CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
515 CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
518 CALL_TexImage2D( GET_DISPATCH(),
522 pixmap->drawable.width,
523 pixmap->drawable.height,
530 } else if (!override) {
534 numRects = RegionNumRects (pRegion);
535 p = RegionRects (pRegion);
537 CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
538 CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
540 for (i = 0; i < numRects; i++)
542 unsigned pitch = PixmapBytePad(p[i].x2 - p[i].x1,
543 pixmap->drawable.depth);
544 void *data = malloc(pitch * (p[i].y2 - p[i].y1));
546 __glXenterServer(GL_FALSE);
547 pScreen->GetImage(&pixmap->drawable, /*pixmap->drawable.x +*/ p[i].x1,
548 /*pixmap->drawable.y*/ + p[i].y1, p[i].x2 - p[i].x1,
549 p[i].y2 - p[i].y1, ZPixmap, ~0, data);
550 __glXleaveServer(GL_FALSE);
552 if (pixmap->drawable.depth == 24)
553 glxFillAlphaChannel(data,
558 CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
561 CALL_TexSubImage2D( GET_DISPATCH(),
565 p[i].x2 - p[i].x1, p[i].y2 - p[i].y1,
575 DamageEmpty(driDraw->pDamage);
581 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
583 __GLXdrawable *pixmap)
585 __GLXDRIscreen *screen =
586 (__GLXDRIscreen *) glxGetScreen(pixmap->pDraw->pScreen);
587 __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) pixmap;
589 __glXDRIdoReleaseTexImage(screen, drawable);
594 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
595 __glXDRIbindTexImage,
596 __glXDRIreleaseTexImage
600 __glXDRIscreenDestroy(__GLXscreen *baseScreen)
602 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
604 screen->core->destroyScreen(screen->driScreen);
606 dlclose(screen->driver);
608 __glXScreenDestroy(baseScreen);
613 static __GLXcontext *
614 __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
615 __GLXconfig *glxConfig,
616 __GLXcontext *baseShareContext)
618 __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
619 __GLXDRIcontext *context, *shareContext;
620 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
624 __DRIcontext *driShare;
625 drm_context_t hwContext;
626 ScreenPtr pScreen = baseScreen->pScreen;
628 shareContext = (__GLXDRIcontext *) baseShareContext;
630 driShare = shareContext->driContext;
634 if (baseShareContext && baseShareContext->isDirect)
637 context = calloc(1, sizeof *context);
641 context->base.destroy = __glXDRIcontextDestroy;
642 context->base.makeCurrent = __glXDRIcontextMakeCurrent;
643 context->base.loseCurrent = __glXDRIcontextLoseCurrent;
644 context->base.copy = __glXDRIcontextCopy;
645 context->base.forceCurrent = __glXDRIcontextForceCurrent;
647 context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
648 /* Find the requested X visual */
649 visual = pScreen->visuals;
650 for (i = 0; i < pScreen->numVisuals; i++, visual++)
651 if (visual->vid == glxConfig->visualID)
653 if (i == pScreen->numVisuals)
656 context->hwContextID = FakeClientID(0);
658 __glXenterServer(GL_FALSE);
659 retval = DRICreateContext(baseScreen->pScreen, visual,
660 context->hwContextID, &hwContext);
661 __glXleaveServer(GL_FALSE);
666 context->driContext =
667 screen->legacy->createNewContext(screen->driScreen,
674 if (context->driContext == NULL) {
675 __glXenterServer(GL_FALSE);
676 retval = DRIDestroyContext(baseScreen->pScreen, context->hwContextID);
677 __glXleaveServer(GL_FALSE);
682 return &context->base;
685 static __GLXdrawable *
686 __glXDRIscreenCreateDrawable(ClientPtr client,
692 __GLXconfig *glxConfig)
694 __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
695 __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
696 __GLXDRIdrawable *private;
698 drm_drawable_t hwDrawable;
700 private = calloc(1, sizeof *private);
704 if (!__glXDrawableInit(&private->base, screen,
705 pDraw, type, glxDrawId, glxConfig)) {
710 private->base.destroy = __glXDRIdrawableDestroy;
711 private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
712 private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
713 private->base.waitX = NULL;
714 private->base.waitGL = NULL;
716 __glXenterServer(GL_FALSE);
717 retval = DRICreateDrawable(screen->pScreen, serverClient,
719 __glXleaveServer(GL_FALSE);
726 /* The last argument is 'attrs', which is used with pbuffers which
727 * we currently don't support. */
729 private->driDrawable =
730 (driScreen->legacy->createNewDrawable)(driScreen->driScreen,
732 hwDrawable, 0, NULL, private);
734 if (private->driDrawable == NULL) {
735 __glXenterServer(GL_FALSE);
736 DRIDestroyDrawable(screen->pScreen, serverClient, pDraw);
737 __glXleaveServer(GL_FALSE);
742 return &private->base;
746 getDrawableInfo(__DRIdrawable *driDrawable,
747 unsigned int *index, unsigned int *stamp,
748 int *x, int *y, int *width, int *height,
749 int *numClipRects, drm_clip_rect_t **ppClipRects,
750 int *backX, int *backY,
751 int *numBackClipRects, drm_clip_rect_t **ppBackClipRects,
754 __GLXDRIdrawable *drawable = data;
756 drm_clip_rect_t *pClipRects, *pBackClipRects;
760 /* If the X window has been destroyed, give up here. */
761 if (drawable->base.pDraw == NULL)
764 pScreen = drawable->base.pDraw->pScreen;
765 __glXenterServer(GL_FALSE);
766 retval = DRIGetDrawableInfo(pScreen, drawable->base.pDraw, index, stamp,
768 numClipRects, &pClipRects,
770 numBackClipRects, &pBackClipRects);
771 __glXleaveServer(GL_FALSE);
773 if (retval && *numClipRects > 0) {
774 size = sizeof (drm_clip_rect_t) * *numClipRects;
775 *ppClipRects = malloc(size);
777 /* Clip cliprects to screen dimensions (redirected windows) */
778 if (*ppClipRects != NULL) {
781 for (i = 0, j = 0; i < *numClipRects; i++) {
782 (*ppClipRects)[j].x1 = max(pClipRects[i].x1, 0);
783 (*ppClipRects)[j].y1 = max(pClipRects[i].y1, 0);
784 (*ppClipRects)[j].x2 = min(pClipRects[i].x2, pScreen->width);
785 (*ppClipRects)[j].y2 = min(pClipRects[i].y2, pScreen->height);
787 if ((*ppClipRects)[j].x1 < (*ppClipRects)[j].x2 &&
788 (*ppClipRects)[j].y1 < (*ppClipRects)[j].y2) {
793 if (*numClipRects != j) {
795 *ppClipRects = realloc(*ppClipRects,
796 sizeof (drm_clip_rect_t) *
807 if (retval && *numBackClipRects > 0) {
808 size = sizeof (drm_clip_rect_t) * *numBackClipRects;
809 *ppBackClipRects = malloc(size);
810 if (*ppBackClipRects != NULL)
811 memcpy (*ppBackClipRects, pBackClipRects, size);
813 *numBackClipRects = 0;
816 *ppBackClipRects = NULL;
817 *numBackClipRects = 0;
823 static void __glXReportDamage(__DRIdrawable *driDraw,
825 drm_clip_rect_t *rects, int num_rects,
826 GLboolean front_buffer,
829 __GLXDRIdrawable *drawable = data;
830 DrawablePtr pDraw = drawable->base.pDraw;
833 __glXenterServer(GL_FALSE);
835 RegionInit(®ion, (BoxPtr) rects, num_rects);
836 RegionTranslate(®ion, pDraw->x, pDraw->y);
837 DamageDamageRegion(pDraw, ®ion);
838 RegionUninit(®ion);
840 __glXleaveServer(GL_FALSE);
843 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
844 { __DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION },
848 static const __DRIdamageExtension damageExtension = {
849 { __DRI_DAMAGE, __DRI_DAMAGE_VERSION },
853 static const __DRIextension *loader_extensions[] = {
854 &systemTimeExtension.base,
855 &getDrawableInfoExtension.base,
856 &damageExtension.base,
862 static const char dri_driver_path[] = DRI_DRIVER_PATH;
865 glxDRIEnterVT (int index, int flags)
867 ScrnInfoPtr scrn = xf86Screens[index];
869 __GLXDRIscreen *screen = (__GLXDRIscreen *)
870 glxGetScreen(screenInfo.screens[index]);
872 LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
874 scrn->EnterVT = screen->enterVT;
876 ret = scrn->EnterVT (index, flags);
878 screen->enterVT = scrn->EnterVT;
879 scrn->EnterVT = glxDRIEnterVT;
890 glxDRILeaveVT (int index, int flags)
892 ScrnInfoPtr scrn = xf86Screens[index];
893 __GLXDRIscreen *screen = (__GLXDRIscreen *)
894 glxGetScreen(screenInfo.screens[index]);
896 LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
900 scrn->LeaveVT = screen->leaveVT;
901 (*screen->leaveVT) (index, flags);
902 screen->leaveVT = scrn->LeaveVT;
903 scrn->LeaveVT = glxDRILeaveVT;
907 initializeExtensions(__GLXDRIscreen *screen)
909 const __DRIextension **extensions;
912 extensions = screen->core->getExtensions(screen->driScreen);
914 for (i = 0; extensions[i]; i++) {
915 #ifdef __DRI_READ_DRAWABLE
916 if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
917 __glXEnableExtension(screen->glx_enable_bits,
918 "GLX_SGI_make_current_read");
920 LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
924 #ifdef __DRI_COPY_SUB_BUFFER
925 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
926 screen->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
927 __glXEnableExtension(screen->glx_enable_bits,
928 "GLX_MESA_copy_sub_buffer");
930 LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
934 #ifdef __DRI_SWAP_CONTROL
935 if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
936 screen->swapControl = (__DRIswapControlExtension *) extensions[i];
937 __glXEnableExtension(screen->glx_enable_bits,
938 "GLX_SGI_swap_control");
939 __glXEnableExtension(screen->glx_enable_bits,
940 "GLX_MESA_swap_control");
942 LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
946 #ifdef __DRI_TEX_OFFSET
947 if (strcmp(extensions[i]->name, __DRI_TEX_OFFSET) == 0) {
948 screen->texOffset = (__DRItexOffsetExtension *) extensions[i];
949 LogMessage(X_INFO, "AIGLX: enabled GLX_texture_from_pixmap with driver support\n");
952 /* Ignore unknown extensions */
957 __glXDRIscreenProbe(ScreenPtr pScreen)
960 drmAddress pSAREA = NULL;
962 __DRIversion ddx_version;
963 __DRIversion dri_version;
964 __DRIversion drm_version;
965 __DRIframebuffer framebuffer;
969 drmVersionPtr version;
974 __GLXDRIscreen *screen;
978 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
979 const __DRIconfig **driConfigs;
980 const __DRIextension **extensions;
983 if (!xf86LoaderCheckSymbol("DRIQueryDirectRenderingCapable") ||
984 !DRIQueryDirectRenderingCapable(pScreen, &isCapable) ||
987 "AIGLX: Screen %d is not DRI capable\n", pScreen->myNum);
991 screen = calloc(1, sizeof *screen);
995 screen->base.destroy = __glXDRIscreenDestroy;
996 screen->base.createContext = __glXDRIscreenCreateContext;
997 screen->base.createDrawable = __glXDRIscreenCreateDrawable;
998 screen->base.swapInterval = __glXDRIdrawableSwapInterval;
999 screen->base.pScreen = pScreen;
1001 __glXInitExtensionEnableBits(screen->glx_enable_bits);
1003 /* DRI protocol version. */
1004 dri_version.major = XF86DRI_MAJOR_VERSION;
1005 dri_version.minor = XF86DRI_MINOR_VERSION;
1006 dri_version.patch = XF86DRI_PATCH_VERSION;
1008 if (!DRIOpenConnection(pScreen, &hSAREA, &BusID)) {
1009 LogMessage(X_ERROR, "AIGLX error: DRIOpenConnection failed\n");
1013 fd = drmOpenOnce(NULL, BusID, &newlyopened);
1016 LogMessage(X_ERROR, "AIGLX error: drmOpenOnce failed (%s)\n",
1021 if (drmGetMagic(fd, &magic)) {
1022 LogMessage(X_ERROR, "AIGLX error: drmGetMagic failed\n");
1026 version = drmGetVersion(fd);
1028 drm_version.major = version->version_major;
1029 drm_version.minor = version->version_minor;
1030 drm_version.patch = version->version_patchlevel;
1031 drmFreeVersion(version);
1034 drm_version.major = -1;
1035 drm_version.minor = -1;
1036 drm_version.patch = -1;
1039 if (newlyopened && !DRIAuthConnection(pScreen, magic)) {
1040 LogMessage(X_ERROR, "AIGLX error: DRIAuthConnection failed\n");
1044 /* Get device name (like "tdfx") and the ddx version numbers.
1045 * We'll check the version in each DRI driver's "createNewScreen"
1047 if (!DRIGetClientDriverName(pScreen,
1052 LogMessage(X_ERROR, "AIGLX error: DRIGetClientDriverName failed\n");
1056 snprintf(filename, sizeof filename, "%s/%s_dri.so",
1057 dri_driver_path, driverName);
1059 screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
1060 if (screen->driver == NULL) {
1061 LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
1062 filename, dlerror());
1066 extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS);
1067 if (extensions == NULL) {
1068 LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
1069 driverName, dlerror());
1073 for (i = 0; extensions[i]; i++) {
1074 if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
1075 extensions[i]->version >= __DRI_CORE_VERSION) {
1076 screen->core = (__DRIcoreExtension *) extensions[i];
1079 if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0 &&
1080 extensions[i]->version >= __DRI_LEGACY_VERSION) {
1081 screen->legacy = (__DRIlegacyExtension *) extensions[i];
1085 if (screen->core == NULL || screen->legacy == NULL) {
1087 "AIGLX error: %s does not export required DRI extension\n",
1093 * Get device-specific info. pDevPriv will point to a struct
1094 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
1095 * has information about the screen size, depth, pitch, ancilliary
1096 * buffers, DRM mmap handles, etc.
1098 if (!DRIGetDeviceInfo(pScreen, &hFB, &junk,
1099 &framebuffer.size, &framebuffer.stride,
1100 &framebuffer.dev_priv_size, &framebuffer.dev_priv)) {
1101 LogMessage(X_ERROR, "AIGLX error: XF86DRIGetDeviceInfo failed\n");
1105 framebuffer.width = pScreen->width;
1106 framebuffer.height = pScreen->height;
1108 /* Map the framebuffer region. */
1109 status = drmMap(fd, hFB, framebuffer.size,
1110 (drmAddressPtr)&framebuffer.base);
1112 LogMessage(X_ERROR, "AIGLX error: drmMap of framebuffer failed (%s)\n",
1117 /* Map the SAREA region. Further mmap regions may be setup in
1118 * each DRI driver's "createNewScreen" function.
1120 status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
1122 LogMessage(X_ERROR, "AIGLX error: drmMap of SAREA failed (%s)\n",
1128 (*screen->legacy->createNewScreen)(pScreen->myNum,
1139 if (screen->driScreen == NULL) {
1141 "AIGLX error: Calling driver entry point failed\n");
1145 screen->base.fbconfigs = glxConvertConfigs(screen->core,
1146 driConfigs, GLX_WINDOW_BIT);
1148 initializeExtensions(screen);
1150 DRIGetTexOffsetFuncs(pScreen, &screen->texOffsetStart,
1151 &screen->texOffsetFinish);
1153 __glXScreenInit(&screen->base, pScreen);
1155 /* The first call simply determines the length of the extension string.
1156 * This allows us to allocate some memory to hold the extension string,
1157 * but it requires that we call __glXGetExtensionString a second time.
1159 buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
1160 if (buffer_size > 0) {
1161 if (screen->base.GLXextensions != NULL) {
1162 free(screen->base.GLXextensions);
1165 screen->base.GLXextensions = xnfalloc(buffer_size);
1166 (void) __glXGetExtensionString(screen->glx_enable_bits,
1167 screen->base.GLXextensions);
1170 __glXsetEnterLeaveServerFuncs(__glXDRIenterServer, __glXDRIleaveServer);
1172 screen->enterVT = pScrn->EnterVT;
1173 pScrn->EnterVT = glxDRIEnterVT;
1174 screen->leaveVT = pScrn->LeaveVT;
1175 pScrn->LeaveVT = glxDRILeaveVT;
1178 "AIGLX: Loaded and initialized %s\n", filename);
1180 return &screen->base;
1184 drmUnmap(pSAREA, SAREA_MAX);
1186 if (framebuffer.base != NULL)
1187 drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
1192 DRICloseConnection(pScreen);
1195 dlclose(screen->driver);
1199 LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
1204 _X_EXPORT __GLXprovider __glXDRIProvider = {
1205 __glXDRIscreenProbe,