diff options
Diffstat (limited to 'nx-X11/programs/Xserver/GL/dri')
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/Imakefile | 35 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/Imakefile.NX.reference | 35 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/Imakefile.XF86.reference | 34 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/dri-def.cpp | 50 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/dri.c | 2109 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/dri.h | 345 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/drimodule.c | 127 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/dristruct.h | 105 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/sarea.h | 94 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/GL/dri/xf86dri.c | 649 |
10 files changed, 3583 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/GL/dri/Imakefile b/nx-X11/programs/Xserver/GL/dri/Imakefile new file mode 100644 index 000000000..8ea938f8c --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/Imakefile @@ -0,0 +1,35 @@ +XCOMM $XFree86: xc/programs/Xserver/GL/dri/Imakefile,v 1.6 2001/04/28 13:55:36 dawes Exp $ + +#define IHaveModules +#include <Server.tmpl> + +#if DoLoadableServer +MSRC = drimodule.c +MOBJ = drimodule.o +#endif + + SRCS = xf86dri.c dri.c $(MSRC) + OBJS = xf86dri.o dri.o $(MOBJ) + + INCLUDES = -I$(SERVERSRC)/include -I$(INCLUDESRC) -I$(XINCLUDESRC) \ + -I$(EXTINCSRC) -I$(MESASRCDIR)/include \ + -I$(XF86OSSRC) -I$(XF86COMSRC) \ + -I../include -I../glx -I$(LIBSRC)/GL/include \ + -I$(DRMSRCDIR)/shared-core \ + -I$(SERVERSRC)/mi -I$(FONTINCSRC) + DEFINES = $(GLX_DEFINES) + +LinkSourceFile(xf86dri.h,$(MESASRCDIR)/src/glx/x11) +LinkSourceFile(xf86dristr.h,$(MESASRCDIR)/src/glx/x11) + +ModuleObjectRule() +LibraryModuleTarget(dri,$(OBJS)) +InstallLibraryModule(dri,$(MODULEDIR),extensions) + +DependTarget() + +InstallDriverSDKLibraryModule(dri,$(DRIVERSDKMODULEDIR),extensions) + +InstallDriverSDKNonExecFile(dri.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(sarea.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xf86dri.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/GL/dri/Imakefile.NX.reference b/nx-X11/programs/Xserver/GL/dri/Imakefile.NX.reference new file mode 100644 index 000000000..59fb0af84 --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/Imakefile.NX.reference @@ -0,0 +1,35 @@ +XCOMM $XFree86: xc/programs/Xserver/GL/dri/Imakefile,v 1.7 2003/02/11 21:34:04 tsi Exp $ + +#define IHaveModules +#include <Server.tmpl> + +#if DoLoadableServer +MSRC = drimodule.c +MOBJ = drimodule.o +#endif + + SRCS = xf86dri.c dri.c $(MSRC) + OBJS = xf86dri.o dri.o $(MOBJ) + + INCLUDES = -I$(SERVERSRC)/include -I$(INCLUDESRC) -I$(XINCLUDESRC) \ + -I$(EXTINCSRC) \ + -I$(XF86OSSRC) -I$(XF86COMSRC) \ + -I../include -I../glx -I$(LIBSRC)/GL/include \ + -I$(SERVERSRC)/mi -I$(FONTINCSRC) \ + -I../../hw/xfree86/os-support/bus + DEFINES = $(GLX_DEFINES) + +LinkSourceFile(xf86dri.h,$(LIBSRC)/GL/dri) +LinkSourceFile(xf86dristr.h,$(LIBSRC)/GL/dri) + +ModuleObjectRule() +LibraryModuleTarget(dri,$(OBJS)) +InstallLibraryModule(dri,$(MODULEDIR),extensions) + +DependTarget() + +InstallDriverSDKLibraryModule(dri,$(DRIVERSDKMODULEDIR),extensions) + +InstallDriverSDKNonExecFile(dri.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(sarea.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xf86dri.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/GL/dri/Imakefile.XF86.reference b/nx-X11/programs/Xserver/GL/dri/Imakefile.XF86.reference new file mode 100644 index 000000000..c8770f6d8 --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/Imakefile.XF86.reference @@ -0,0 +1,34 @@ +XCOMM $XFree86: xc/programs/Xserver/GL/dri/Imakefile,v 1.7 2003/02/11 21:34:04 tsi Exp $ + +#define IHaveModules +#include <Server.tmpl> + +#if DoLoadableServer +MSRC = drimodule.c +MOBJ = drimodule.o +#endif + + SRCS = xf86dri.c dri.c $(MSRC) + OBJS = xf86dri.o dri.o $(MOBJ) + + INCLUDES = -I$(SERVERSRC)/include -I$(INCLUDESRC) -I$(XINCLUDESRC) \ + -I$(EXTINCSRC) \ + -I$(XF86OSSRC) -I$(XF86COMSRC) \ + -I../include -I../glx -I$(LIBSRC)/GL/include \ + -I$(SERVERSRC)/mi -I$(FONTINCSRC) + DEFINES = $(GLX_DEFINES) + +LinkSourceFile(xf86dri.h,$(LIBSRC)/GL/dri) +LinkSourceFile(xf86dristr.h,$(LIBSRC)/GL/dri) + +ModuleObjectRule() +LibraryModuleTarget(dri,$(OBJS)) +InstallLibraryModule(dri,$(MODULEDIR),extensions) + +DependTarget() + +InstallDriverSDKLibraryModule(dri,$(DRIVERSDKMODULEDIR),extensions) + +InstallDriverSDKNonExecFile(dri.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(sarea.h,$(DRIVERSDKINCLUDEDIR)) +InstallDriverSDKNonExecFile(xf86dri.h,$(DRIVERSDKINCLUDEDIR)) diff --git a/nx-X11/programs/Xserver/GL/dri/dri-def.cpp b/nx-X11/programs/Xserver/GL/dri/dri-def.cpp new file mode 100644 index 000000000..0d1ab6872 --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/dri-def.cpp @@ -0,0 +1,50 @@ +LIBRARY DRI +VERSION LIBRARY_VERSION +EXPORTS + +XFree86DRIExtensionInit +DRIAuthConnection +DRIBlockHandler +DRIClipNotify +DRICloseConnection +DRICloseScreen +DRIContextPrivDelete +DRICopyWindow +DRICreateContext +DRICreateContextPriv +DRICreateContextPrivFromHandle +DRICreateDrawable +DRICreateInfoRec +DRIDestroyContext +DRIDestroyContextPriv +DRIDestroyDrawable +DRIDestroyInfoRec +DRIDoBlockHandler +DRIDoWakeupHandler +DRIDrawablePrivDelete +DRIExtensionInit +DRIFinishScreenInit +DRIGetClientDriverName +DRIGetContext +DRIGetContextStore +DRIGetDeviceInfo +DRIGetDrawableIndex +DRIGetDrawableInfo +DRIGetDrawableStamp +DRIGetSAREAPrivate +DRIGetWrappedFuncs +DRILock +DRIOpenConnection +DRIPaintWindow +DRIPostValidateTree +DRIPrintDrawableLock +DRIQueryDirectRenderingCapable +DRIQueryVersion +DRIReset +DRIScreenInit +DRISwapContext +DRIUnlock +DRIValidateTree +DRIWakeupHandler + +/* $XFree86$ */ diff --git a/nx-X11/programs/Xserver/GL/dri/dri.c b/nx-X11/programs/Xserver/GL/dri/dri.c new file mode 100644 index 000000000..424a21c68 --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/dri.c @@ -0,0 +1,2109 @@ +/* $XFree86: xc/programs/Xserver/GL/dri/dri.c,v 1.39 2003/11/10 18:21:41 tsi Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#ifdef XFree86LOADER +#include "xf86_ansic.h" +#else +#include <sys/time.h> +#include <unistd.h> +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#define _XF86DRI_SERVER_ +#include "xf86dristr.h" +#include "swaprep.h" +#include "xf86str.h" +#include "dri.h" +#include "sarea.h" +#include "dristruct.h" +#include "xf86.h" +#include "xf86drm.h" +#include "glxserver.h" +#include "mi.h" +#include "mipointer.h" + +#if defined(XFree86LOADER) && !defined(PANORAMIX) +extern Bool noPanoramiXExtension; +#endif + +static int DRIScreenPrivIndex = -1; +static int DRIWindowPrivIndex = -1; +static unsigned long DRIGeneration = 0; +static unsigned int DRIDrawableValidationStamp = 0; + +static RESTYPE DRIDrawablePrivResType; +static RESTYPE DRIContextPrivResType; +static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); + + /* Wrapper just like xf86DrvMsg, but + without the verbosity level checking. + This will make it easy to turn off some + messages later, based on verbosity + level. */ + +/* + * Since we're already referencing things from the XFree86 common layer in + * this file, we'd might as well just call xf86VDrvMsgVerb, and have + * consistent message formatting. The verbosity of these messages can be + * easily changed here. + */ +#define DRI_MSG_VERBOSITY 1 +static void +DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); + va_end(ap); +} + +Bool +DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) +{ + DRIScreenPrivPtr pDRIPriv; + drm_context_t * reserved; + int reserved_count; + int i, fd, drmWasAvailable; + Bool xineramaInCore = FALSE; + int err = 0; + char *openbusid; + drmVersionPtr drmlibv; + int drmlibmajor, drmlibminor, drmdimajor, drmdiminor; + + if (DRIGeneration != serverGeneration) { + if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + DRIGeneration = serverGeneration; + } + + /* If the DRI extension is disabled, do not initialize the DRI */ + if (noXFree86DRIExtension) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering has been disabled.\n"); + return FALSE; + } + + /* + * If Xinerama is on, don't allow DRI to initialise. It won't be usable + * anyway. + */ +#if defined(PANORAMIX) && !defined(XFree86LOADER) + xineramaInCore = TRUE; +#elif defined(XFree86LOADER) + if (xf86LoaderCheckSymbol("noPanoramiXExtension")) + xineramaInCore = TRUE; +#endif + +#if defined(PANORAMIX) || defined(XFree86LOADER) + if (xineramaInCore) { + if (!noPanoramiXExtension) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering is not supported when Xinerama is enabled\n"); + return FALSE; + } + } +#endif + + drmWasAvailable = drmAvailable(); + + /* Check the DRM lib version. + * drmGetLibVersion was not supported in version 1.0, so check for + * symbol first to avoid possible crash or hang. + */ + drmlibmajor = 1; + drmlibminor = 0; + if (xf86LoaderCheckSymbol("drmGetLibVersion")) { + drmlibv = drmGetLibVersion(-1); + if (drmlibv != NULL) { + drmlibmajor = drmlibv->version_major; + drmlibminor = drmlibv->version_minor; + drmFreeVersion(drmlibv); + } + } + + /* Check if the libdrm can handle falling back to loading based on name + * if a busid string is passed. + */ + if (drmlibmajor == 1 && drmlibminor >= 2) + openbusid = pDRIInfo->busIdString; + else + openbusid = NULL; + + /* Note that drmOpen will try to load the kernel module, if needed. */ + fd = drmOpen(pDRIInfo->drmDriverName, openbusid); + if (fd < 0) { + /* failed to open DRM */ + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmOpen failed\n"); + return FALSE; + } + + if (!drmWasAvailable) { + /* drmOpen loaded the kernel module, print a message to say so */ + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] loaded kernel module for \"%s\" driver\n", + pDRIInfo->drmDriverName); + } + + pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec)); + if (!pDRIPriv) { + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + return FALSE; + } + + pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv; + pDRIPriv->drmFD = fd; + pDRIPriv->directRenderingSupport = TRUE; + pDRIPriv->pDriverInfo = pDRIInfo; + pDRIPriv->nrWindows = 0; + pDRIPriv->fullscreen = NULL; + + pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; + pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; + + pDRIPriv->grabbedDRILock = FALSE; + pDRIPriv->drmSIGIOHandlerInstalled = FALSE; + + if (drmlibmajor == 1 && drmlibminor >= 2) { + drmSetVersion sv; + + /* Get the interface version, asking for 1.1. */ + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; + err = drmSetInterfaceVersion(pDRIPriv->drmFD, &sv); + if (err == 0) { + drmdimajor = sv.drm_di_major; + drmdiminor = sv.drm_di_minor; + } else { + /* failure, so set it to 1.0.0. */ + drmdimajor = 1; + drmdiminor = 0; + } + } + else { + /* We can't check the DI DRM interface version, so set it to 1.0.0. */ + drmdimajor = 1; + drmdiminor = 0; + } + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] DRM interface version %d.%d\n", drmdimajor, drmdiminor); + + /* If the interface minor number is 1.1, then we've opened a DRM device + * that already had the busid set through drmOpen. + */ + if (drmdimajor == 1 && drmdiminor >= 1) + err = 0; + else + err = drmSetBusid(pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString); + + if (err < 0) { + pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmSetBusid failed (%d, %s), %s\n", + pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString, strerror(-err)); + return FALSE; + } + + *pDRMFD = pDRIPriv->drmFD; + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] created \"%s\" driver at busid \"%s\"\n", + pDRIPriv->pDriverInfo->drmDriverName, + pDRIPriv->pDriverInfo->busIdString); + + if (drmAddMap( pDRIPriv->drmFD, + 0, + pDRIPriv->pDriverInfo->SAREASize, + DRM_SHM, + DRM_CONTAINS_LOCK, + &pDRIPriv->hSAREA) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmAddMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] added %d byte SAREA at %p\n", + pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); + + if (drmMap( pDRIPriv->drmFD, + pDRIPriv->hSAREA, + pDRIPriv->pDriverInfo->SAREASize, + (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmMap failed\n"); + return FALSE; + } + memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", + pDRIPriv->hSAREA, pDRIPriv->pSAREA); + + if (drmAddMap( pDRIPriv->drmFD, + (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, + pDRIPriv->pDriverInfo->frameBufferSize, + DRM_FRAME_BUFFER, + 0, + &pDRIPriv->hFrameBuffer) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmAddMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", + pDRIPriv->hFrameBuffer); + + /* Add tags for reserved contexts */ + if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, + &reserved_count))) { + int i; + void *tag; + + for (i = 0; i < reserved_count; i++) { + tag = DRICreateContextPrivFromHandle(pScreen, + reserved[i], + DRI_CONTEXT_RESERVED); + drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); + } + drmFreeReservedContextList(reserved); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] added %d reserved context%s for kernel\n", + reserved_count, reserved_count > 1 ? "s" : ""); + } + + /* validate max drawable table entry set by driver */ + if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || + (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "Invalid max drawable table size set by driver: %d\n", + pDRIPriv->pDriverInfo->maxDrawableTableEntry); + } + + /* Initialize drawable tables (screen private and SAREA) */ + for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { + pDRIPriv->DRIDrawables[i] = NULL; + pDRIPriv->pSAREA->drawableTable[i].stamp = 0; + pDRIPriv->pSAREA->drawableTable[i].flags = 0; + } + + return TRUE; +} + +Bool +DRIFinishScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + DRIContextFlags flags = 0; + DRIContextPrivPtr pDRIContextPriv; + + /* Set up flags for DRICreateContextPriv */ + switch (pDRIInfo->driverSwapMethod) { + case DRI_KERNEL_SWAP: flags = DRI_CONTEXT_2DONLY; break; + case DRI_HIDE_X_CONTEXT: flags = DRI_CONTEXT_PRESERVED; break; + } + + if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, + &pDRIPriv->myContext, + flags))) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to create server context\n"); + return FALSE; + } + pDRIPriv->myContextPriv = pDRIContextPriv; + + DRIDrvMsg(pScreen->myNum, X_INFO, + "X context handle = %p\n", pDRIPriv->myContext); + + /* Now that we have created the X server's context, we can grab the + * hardware lock for the X server. + */ + DRILock(pScreen, 0); + pDRIPriv->grabbedDRILock = TRUE; + + /* pointers so that we can prevent memory leaks later */ + pDRIPriv->hiddenContextStore = NULL; + pDRIPriv->partial3DContextStore = NULL; + + switch(pDRIInfo->driverSwapMethod) { + case DRI_HIDE_X_CONTEXT: + /* Server will handle 3D swaps, and hide 2D swaps from kernel. + * Register server context as a preserved context. + */ + + /* allocate memory for hidden context store */ + pDRIPriv->hiddenContextStore + = (void *)xcalloc(1, pDRIInfo->contextSize); + if (!pDRIPriv->hiddenContextStore) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to allocate hidden context\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + + /* allocate memory for partial 3D context store */ + pDRIPriv->partial3DContextStore + = (void *)xcalloc(1, pDRIInfo->contextSize); + if (!pDRIPriv->partial3DContextStore) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] failed to allocate partial 3D context\n"); + xfree(pDRIPriv->hiddenContextStore); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + + /* save initial context store */ + if (pDRIInfo->SwapContext) { + (*pDRIInfo->SwapContext)( + pScreen, + DRI_NO_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore, + DRI_NO_CONTEXT, + NULL); + } + /* fall through */ + + case DRI_SERVER_SWAP: + /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT + * setup signal handler for receiving swap requests from kernel + */ + if (!(pDRIPriv->drmSIGIOHandlerInstalled = + drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to setup DRM signal handler\n"); + if (pDRIPriv->hiddenContextStore) + xfree(pDRIPriv->hiddenContextStore); + if (pDRIPriv->partial3DContextStore) + xfree(pDRIPriv->partial3DContextStore); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] installed DRM signal handler\n"); + } + + default: + break; + } + + /* Wrap DRI support */ + if (pDRIInfo->wrap.ValidateTree) { + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; + } + if (pDRIInfo->wrap.PostValidateTree) { + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; + } + if (pDRIInfo->wrap.WindowExposures) { + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; + } + if (pDRIInfo->wrap.CopyWindow) { + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; + } + if (pDRIInfo->wrap.ClipNotify) { + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; + } + if (pDRIInfo->wrap.AdjustFrame) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; + pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; + } + pDRIPriv->wrapped = TRUE; + + DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); + + return TRUE; +} + +void +DRICloseScreen(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo; + drm_context_t * reserved; + int reserved_count; + + if (pDRIPriv && pDRIPriv->directRenderingSupport) { + + pDRIInfo = pDRIPriv->pDriverInfo; + + if (pDRIPriv->wrapped) { + /* Unwrap DRI Functions */ + if (pDRIInfo->wrap.ValidateTree) { + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + pDRIPriv->wrap.ValidateTree = NULL; + } + if (pDRIInfo->wrap.PostValidateTree) { + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + pDRIPriv->wrap.PostValidateTree = NULL; + } + if (pDRIInfo->wrap.WindowExposures) { + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + pDRIPriv->wrap.WindowExposures = NULL; + } + if (pDRIInfo->wrap.CopyWindow) { + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + pDRIPriv->wrap.CopyWindow = NULL; + } + if (pDRIInfo->wrap.ClipNotify) { + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + pDRIPriv->wrap.ClipNotify = NULL; + } + if (pDRIInfo->wrap.AdjustFrame) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; + pDRIPriv->wrap.AdjustFrame = NULL; + } + pDRIPriv->wrapped = FALSE; + } + + if (pDRIPriv->drmSIGIOHandlerInstalled) { + if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to remove DRM signal handler\n"); + } + } + + if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { + DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); + } + + if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to destroy server context\n"); + } + + /* Remove tags for reserved contexts */ + if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, + &reserved_count))) { + int i; + + for (i = 0; i < reserved_count; i++) { + DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, + reserved[i])); + } + drmFreeReservedContextList(reserved); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] removed %d reserved context%s for kernel\n", + reserved_count, reserved_count > 1 ? "s" : ""); + } + + /* Make sure signals get unblocked etc. */ + drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); + pDRIPriv->lockRefCount = 0; + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] unmapping %d bytes of SAREA %p at %p\n", + pDRIInfo->SAREASize, + pDRIPriv->hSAREA, + pDRIPriv->pSAREA); + if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] unable to unmap %d bytes" + " of SAREA %p at %p\n", + pDRIInfo->SAREASize, + pDRIPriv->hSAREA, + pDRIPriv->pSAREA); + } + + drmClose(pDRIPriv->drmFD); + + xfree(pDRIPriv); + pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; + } +} + +Bool +DRIExtensionInit(void) +{ + int i; + ScreenPtr pScreen; + + if (DRIScreenPrivIndex < 0) { + return FALSE; + } + + /* Allocate a window private index with a zero sized private area for + * each window, then should a window become a DRI window, we'll hang + * a DRIWindowPrivateRec off of this private index. + */ + if ((DRIWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) + return FALSE; + + DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete); + DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete); + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + if (!AllocateWindowPrivate(pScreen, DRIWindowPrivIndex, 0)) + return FALSE; + } + + RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); + + return TRUE; +} + +void +DRIReset(void) +{ + /* + * This stub routine is called when the X Server recycles, resources + * allocated by DRIExtensionInit need to be managed here. + * + * Currently this routine is a stub because all the interesting resources + * are managed via the screen init process. + */ +} + +Bool +DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv) + *isCapable = pDRIPriv->directRenderingSupport; + else + *isCapable = FALSE; + + return TRUE; +} + +Bool +DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *hSAREA = pDRIPriv->hSAREA; + *busIdString = pDRIPriv->pDriverInfo->busIdString; + + return TRUE; +} + +Bool +DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; + return TRUE; +} + +Bool +DRICloseConnection(ScreenPtr pScreen) +{ + return TRUE; +} + +Bool +DRIGetClientDriverName(ScreenPtr pScreen, + int *ddxDriverMajorVersion, + int *ddxDriverMinorVersion, + int *ddxDriverPatchVersion, + char **clientDriverName) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; + *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; + *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; + *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; + + return TRUE; +} + +/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper + functions that layer on drmCreateContext and drmAddContextTag. + + DRICreateContextPriv always creates a kernel drm_context_t and then calls + DRICreateContextPrivFromHandle to create a DRIContextPriv structure for + DRI tracking. For the SIGIO handler, the drm_context_t is associated with + DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv + area and are passed to the kernel (if necessary). + + DRICreateContextPriv returns a pointer to newly allocated + DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ + +DRIContextPrivPtr +DRICreateContextPriv(ScreenPtr pScreen, + drm_context_t * pHWContext, + DRIContextFlags flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { + return NULL; + } + + return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); +} + +DRIContextPrivPtr +DRICreateContextPrivFromHandle(ScreenPtr pScreen, + drm_context_t hHWContext, + DRIContextFlags flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + int contextPrivSize; + + contextPrivSize = sizeof(DRIContextPrivRec) + + pDRIPriv->pDriverInfo->contextSize; + if (!(pDRIContextPriv = xcalloc(1, contextPrivSize))) { + return NULL; + } + pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); + + drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); + + pDRIContextPriv->hwContext = hHWContext; + pDRIContextPriv->pScreen = pScreen; + pDRIContextPriv->flags = flags; + pDRIContextPriv->valid3D = FALSE; + + if (flags & DRI_CONTEXT_2DONLY) { + if (drmSetContextFlags(pDRIPriv->drmFD, + hHWContext, + DRM_CONTEXT_2DONLY)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to set 2D context flag\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return NULL; + } + } + if (flags & DRI_CONTEXT_PRESERVED) { + if (drmSetContextFlags(pDRIPriv->drmFD, + hHWContext, + DRM_CONTEXT_PRESERVED)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to set preserved flag\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return NULL; + } + } + return pDRIContextPriv; +} + +Bool +DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) +{ + DRIScreenPrivPtr pDRIPriv; + + if (!pDRIContextPriv) return TRUE; + + pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); + + if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { + /* Don't delete reserved contexts from + kernel area -- the kernel manages its + reserved contexts itself. */ + if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) + return FALSE; + } + + /* Remove the tag last to prevent a race + condition where the context has pending + buffers. The context can't be re-used + while in this thread, but buffers can be + dispatched asynchronously. */ + drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); + xfree(pDRIContextPriv); + return TRUE; +} + +static Bool +DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + __GLXscreenInfo *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); + __GLcontextModes *modes = pGLXScreen->modes; + void **pVisualConfigPriv = pGLXScreen->pVisualPriv; + DRIContextPrivPtr pDRIContextPriv; + void *contextStore; + VisualPtr visual; + int visNum; + + visual = pScreen->visuals; + + /* Find the X visual that corresponds the the first GLX visual */ + for (visNum = 0; + visNum < pScreen->numVisuals; + visNum++, visual++) { + if (modes->visualID == visual->vid) + break; + } + if (visNum == pScreen->numVisuals) return FALSE; + + if (!(pDRIContextPriv = + DRICreateContextPriv(pScreen, + &pDRIPriv->pSAREA->dummy_context, 0))) { + return FALSE; + } + + contextStore = DRIGetContextStore(pDRIContextPriv); + if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { + if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, visual, + pDRIPriv->pSAREA->dummy_context, + *pVisualConfigPriv, + (DRIContextType)(long)contextStore)) { + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + } + + pDRIPriv->dummyCtxPriv = pDRIContextPriv; + return TRUE; +} + +static void +DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; + void *contextStore; + + if (!pDRIContextPriv) return; + if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { + contextStore = DRIGetContextStore(pDRIContextPriv); + pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, + pDRIContextPriv->hwContext, + (DRIContextType)(long)contextStore); + } + + DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); + pDRIPriv->dummyCtxPriv = NULL; +} + +Bool +DRICreateContext(ScreenPtr pScreen, VisualPtr visual, + XID context, drm_context_t * pHWContext) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + __GLXscreenInfo *pGLXScreen = __glXgetActiveScreen(pScreen->myNum); + __GLcontextModes *modes = pGLXScreen->modes; + void **pVisualConfigPriv = pGLXScreen->pVisualPriv; + DRIContextPrivPtr pDRIContextPriv; + void *contextStore; + + if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { + if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] Could not create dummy context\n"); + return FALSE; + } + } + + /* Find the GLX visual associated with the one requested */ + for (modes = pGLXScreen->modes; modes != NULL; modes = modes->next) { + if (modes->visualID == visual->vid) + break; + pVisualConfigPriv++; + } + + if (modes == NULL) { + /* No matching GLX visual found */ + return FALSE; + } + + if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { + return FALSE; + } + + contextStore = DRIGetContextStore(pDRIContextPriv); + if (pDRIPriv->pDriverInfo->CreateContext) { + if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, visual, + *pHWContext, *pVisualConfigPriv, + (DRIContextType)(long)contextStore))) { + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + } + + /* track this in case the client dies before cleanup */ + AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); + + return TRUE; +} + +Bool +DRIDestroyContext(ScreenPtr pScreen, XID context) +{ + FreeResourceByType(context, DRIContextPrivResType, FALSE); + + return TRUE; +} + +/* DRIContextPrivDelete is called by the resource manager. */ +Bool +DRIContextPrivDelete(pointer pResource, XID id) +{ + DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; + DRIScreenPrivPtr pDRIPriv; + void *contextStore; + + pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); + if (pDRIPriv->pDriverInfo->DestroyContext) { + contextStore = DRIGetContextStore(pDRIContextPriv); + pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, + pDRIContextPriv->hwContext, + (DRIContextType)(long)contextStore); + } + return DRIDestroyContextPriv(pDRIContextPriv); +} + + +/* This walks the drawable timestamp array and invalidates all of them + * in the case of transition from private to shared backbuffers. It's + * not necessary for correctness, because DRIClipNotify gets called in + * time to prevent any conflict, but the transition from + * shared->private is sometimes missed if we don't do this. + */ +static void +DRIClipNotifyAllDrawables(ScreenPtr pScreen) +{ + int i; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { + pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; + } +} + + +static void +DRITransitionToSharedBuffers(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionSingleToMulti3D) + pDRIInfo->TransitionSingleToMulti3D( pScreen ); +} + + +static void +DRITransitionToPrivateBuffers(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionMultiToSingle3D) + pDRIInfo->TransitionMultiToSingle3D( pScreen ); +} + + +static void +DRITransitionTo3d(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionTo3d) + pDRIInfo->TransitionTo3d( pScreen ); +} + +static void +DRITransitionTo2d(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionTo2d) + pDRIInfo->TransitionTo2d( pScreen ); +} + + +Bool +DRICreateDrawable(ScreenPtr pScreen, Drawable id, + DrawablePtr pDrawable, drm_drawable_t * hHWDrawable) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + WindowPtr pWin; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + pDRIDrawablePriv->refCount++; + } + else { + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = xalloc(sizeof(DRIDrawablePrivRec)))) { + return FALSE; + } + + /* Only create a drm_drawable_t once */ + if (drmCreateDrawable(pDRIPriv->drmFD, hHWDrawable)) { + xfree(pDRIDrawablePriv); + return FALSE; + } + + /* add it to the list of DRI drawables for this screen */ + pDRIDrawablePriv->hwDrawable = *hHWDrawable; + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 1; + pDRIDrawablePriv->drawableIndex = -1; + + /* save private off of preallocated index */ + pWin->devPrivates[DRIWindowPrivIndex].ptr = + (pointer)pDRIDrawablePriv; + + switch (++pDRIPriv->nrWindows) { + case 1: + DRITransitionTo3d( pScreen ); + break; + case 2: + DRITransitionToSharedBuffers( pScreen ); + break; + default: + break; + } + + /* track this in case this window is destroyed */ + AddResource(id, DRIDrawablePrivResType, (pointer)pWin); + } + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIDestroyDrawable(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable) +{ + DRIDrawablePrivPtr pDRIDrawablePriv; + WindowPtr pWin; + + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + pDRIDrawablePriv->refCount--; + if (pDRIDrawablePriv->refCount <= 0) { + /* This calls back DRIDrawablePrivDelete which frees private area */ + FreeResourceByType(id, DRIDrawablePrivResType, FALSE); + } + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIDrawablePrivDelete(pointer pResource, XID id) +{ + DrawablePtr pDrawable = (DrawablePtr)pResource; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + WindowPtr pWin; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if (pDRIDrawablePriv->drawableIndex != -1) { + /* bump stamp to force outstanding 3D requests to resync */ + pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp + = DRIDrawableValidationStamp++; + + /* release drawable table entry */ + pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; + } + + if (drmDestroyDrawable(pDRIPriv->drmFD, + pDRIDrawablePriv->hwDrawable)) { + return FALSE; + } + xfree(pDRIDrawablePriv); + pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL; + + switch (--pDRIPriv->nrWindows) { + case 0: + DRITransitionTo2d( pDrawable->pScreen ); + break; + case 1: + DRITransitionToPrivateBuffers( pDrawable->pScreen ); + break; + default: + break; + } + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIGetDrawableInfo(ScreenPtr pScreen, + DrawablePtr pDrawable, + unsigned int* index, + unsigned int* stamp, + int* X, + int* Y, + int* W, + int* H, + int* numClipRects, + drm_clip_rect_t ** pClipRects, + int* backX, + int* backY, + int* numBackClipRects, + drm_clip_rect_t ** pBackClipRects) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; + WindowPtr pWin, pOldWin; + int i; + + printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + + /* Manage drawable table */ + if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ + + /* Search table for empty entry */ + i = 0; + while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { + if (!(pDRIPriv->DRIDrawables[i])) { + pDRIPriv->DRIDrawables[i] = pDrawable; + pDRIDrawablePriv->drawableIndex = i; + pDRIPriv->pSAREA->drawableTable[i].stamp = + DRIDrawableValidationStamp++; + break; + } + i++; + } + + /* Search table for oldest entry */ + if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { + unsigned int oldestStamp = ~0; + int oldestIndex = 0; + i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; + while (i--) { + if (pDRIPriv->pSAREA->drawableTable[i].stamp < + oldestStamp) { + oldestIndex = i; + oldestStamp = + pDRIPriv->pSAREA->drawableTable[i].stamp; + } + } + pDRIDrawablePriv->drawableIndex = oldestIndex; + + /* release oldest drawable table entry */ + pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; + pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); + pOldDrawPriv->drawableIndex = -1; + + /* claim drawable table entry */ + pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; + + /* validate SAREA entry */ + pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = + DRIDrawableValidationStamp++; + + /* check for stamp wrap around */ + if (oldestStamp > DRIDrawableValidationStamp) { + + /* walk SAREA table and invalidate all drawables */ + for( i=0; + i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; + i++) { + pDRIPriv->pSAREA->drawableTable[i].stamp = + DRIDrawableValidationStamp++; + } + } + } + + /* If the driver wants to be notified when the index is + * set for a drawable, let it know now. + */ + if (pDRIPriv->pDriverInfo->SetDrawableIndex) + pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, + pDRIDrawablePriv->drawableIndex); + + /* reinit drawable ID if window is visible */ + if ((pWin->viewable) && + (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) + { + (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, + &pWin->clipList, pDRIDrawablePriv->drawableIndex); + } + } + + *index = pDRIDrawablePriv->drawableIndex; + *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; + *X = (int)(pWin->drawable.x); + *Y = (int)(pWin->drawable.y); +#if 0 + *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1); + *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1); +#endif + *W = (int)(pWin->drawable.width); + *H = (int)(pWin->drawable.height); + *numClipRects = REGION_NUM_RECTS(&pWin->clipList); + *pClipRects = (drm_clip_rect_t *)REGION_RECTS(&pWin->clipList); + + if (!*numClipRects && pDRIPriv->fullscreen) { + /* use fake full-screen clip rect */ + pDRIPriv->fullscreen_rect.x1 = *X; + pDRIPriv->fullscreen_rect.y1 = *Y; + pDRIPriv->fullscreen_rect.x2 = *X + *W; + pDRIPriv->fullscreen_rect.y2 = *Y + *H; + + *numClipRects = 1; + *pClipRects = &pDRIPriv->fullscreen_rect; + } + + *backX = *X; + *backY = *Y; + + if (pDRIPriv->nrWindows == 1 && *numClipRects) { + /* Use a single cliprect. */ + + int x0 = *X; + int y0 = *Y; + int x1 = x0 + *W; + int y1 = y0 + *H; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > pScreen->width) x1 = pScreen->width; + if (y1 > pScreen->height) y1 = pScreen->height; + + pDRIPriv->private_buffer_rect.x1 = x0; + pDRIPriv->private_buffer_rect.y1 = y0; + pDRIPriv->private_buffer_rect.x2 = x1; + pDRIPriv->private_buffer_rect.y2 = y1; + + *numBackClipRects = 1; + *pBackClipRects = &(pDRIPriv->private_buffer_rect); + } else { + /* Use the frontbuffer cliprects for back buffers. */ + *numBackClipRects = 0; + *pBackClipRects = 0; + } + } + else { + /* Not a DRIDrawable */ + return FALSE; + } + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIGetDeviceInfo(ScreenPtr pScreen, + drm_handle_t * hFrameBuffer, + int* fbOrigin, + int* fbSize, + int* fbStride, + int* devPrivateSize, + void** pDevPrivate) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *hFrameBuffer = pDRIPriv->hFrameBuffer; + *fbOrigin = 0; + *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; + *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; + *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; + *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; + + return TRUE; +} + +DRIInfoPtr +DRICreateInfoRec(void) +{ + DRIInfoPtr inforec = (DRIInfoPtr)xcalloc(1, sizeof(DRIInfoRec)); + if (!inforec) return NULL; + + /* Initialize defaults */ + inforec->busIdString = NULL; + + /* Wrapped function defaults */ + inforec->wrap.WakeupHandler = DRIDoWakeupHandler; + inforec->wrap.BlockHandler = DRIDoBlockHandler; + inforec->wrap.WindowExposures = DRIWindowExposures; + inforec->wrap.CopyWindow = DRICopyWindow; + inforec->wrap.ValidateTree = DRIValidateTree; + inforec->wrap.PostValidateTree = DRIPostValidateTree; + inforec->wrap.ClipNotify = DRIClipNotify; + inforec->wrap.AdjustFrame = DRIAdjustFrame; + + inforec->TransitionTo2d = 0; + inforec->TransitionTo3d = 0; + inforec->SetDrawableIndex = 0; + + return inforec; +} + +void +DRIDestroyInfoRec(DRIInfoPtr DRIInfo) +{ + if (DRIInfo->busIdString) xfree(DRIInfo->busIdString); + xfree((char*)DRIInfo); +} + + +void +DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && + pDRIPriv->pDriverInfo->wrap.WakeupHandler) + (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, + result, pReadmask); + } +} + +void +DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && + pDRIPriv->pDriverInfo->wrap.BlockHandler) + (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, + pTimeout, pReadmask); + } +} + +void +DRIDoWakeupHandler(int screenNum, pointer wakeupData, + unsigned long result, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + DRILock(pScreen, 0); + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_3D_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore); + } +} + +void +DRIDoBlockHandler(int screenNum, pointer blockData, + pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_NO_CONTEXT, + NULL, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore); + } + DRIUnlock(pScreen); +} + +void +DRISwapContext(int drmFD, void *oldctx, void *newctx) +{ + DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; + DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; + ScreenPtr pScreen = newContext->pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + void* oldContextStore = NULL; + DRIContextType oldContextType; + void* newContextStore = NULL; + DRIContextType newContextType; + DRISyncType syncType; +#ifdef DEBUG + static int count = 0; +#endif + + if (!newContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", + oldContext, newContext); + return; + } + +#ifdef DEBUG + /* usefull for debugging, just print out after n context switches */ + if (!count || !(count % 1)) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[DRI] Context switch %5d from %p/0x%08x (%d)\n", + count, + oldContext, + oldContext ? oldContext->flags : 0, + oldContext ? oldContext->hwContext : -1); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[DRI] Context switch %5d to %p/0x%08x (%d)\n", + count, + newContext, + newContext ? newContext->flags : 0, + newContext ? newContext->hwContext : -1); + } + ++count; +#endif + + if (!pDRIPriv->pDriverInfo->SwapContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] DDX driver missing context swap call back\n"); + return; + } + + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + + /* only 3D contexts are swapped in this case */ + if (oldContext) { + oldContextStore = DRIGetContextStore(oldContext); + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + } else { + oldContextType = DRI_NO_CONTEXT; + } + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_3D_SYNC; + } + else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { + + /* optimize 2D context swaps */ + + if (newContext->flags & DRI_CONTEXT_2DONLY) { + /* go from 3D context to 2D context and only save 2D + * subset of 3D state + */ + oldContextStore = DRIGetContextStore(oldContext); + oldContextType = DRI_2D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + newContextType = DRI_2D_CONTEXT; + syncType = DRI_3D_SYNC; + pDRIPriv->lastPartial3DContext = oldContext; + } + else if (oldContext->flags & DRI_CONTEXT_2DONLY) { + if (pDRIPriv->lastPartial3DContext == newContext) { + /* go from 2D context back to previous 3D context and + * only restore 2D subset of previous 3D state + */ + oldContextStore = DRIGetContextStore(oldContext); + oldContextType = DRI_2D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + newContextType = DRI_2D_CONTEXT; + syncType = DRI_2D_SYNC; + } + else { + /* go from 2D context to a different 3D context */ + + /* call DDX driver to do partial restore */ + oldContextStore = DRIGetContextStore(oldContext); + newContextStore = + DRIGetContextStore(pDRIPriv->lastPartial3DContext); + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_2D_CONTEXT, + oldContextStore, + DRI_2D_CONTEXT, + newContextStore); + + /* now setup for a complete 3D swap */ + oldContextStore = newContextStore; + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_NO_SYNC; + } + } + else { + /* now setup for a complete 3D swap */ + oldContextStore = newContextStore; + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_3D_SYNC; + } + } + + /* call DDX driver to perform the swap */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + syncType, + oldContextType, + oldContextStore, + newContextType, + newContextStore); +} + +void* +DRIGetContextStore(DRIContextPrivPtr context) +{ + return((void *)context->pContextStore); +} + +void +DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if(pDRIDrawablePriv) { + (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, + pDRIDrawablePriv->drawableIndex); + } + + /* call lower wrapped functions */ + if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { + + /* unwrap */ + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + + /* call lower layers */ + (*pScreen->WindowExposures)(pWin, prgn, bsreg); + + /* rewrap */ + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = DRIWindowExposures; + } +} + + +static int +DRITreeTraversal(WindowPtr pWin, pointer data) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if(pDRIDrawablePriv) { + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + RegionPtr reg = (RegionPtr)data; + + REGION_UNION(pScreen, reg, reg, &(pWin->clipList)); + + if(pDRIPriv->nrWindows == 1) + return WT_STOPWALKING; + } + return WT_WALKCHILDREN; +} + +void +DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv) return; + + if(pDRIPriv->nrWindows > 0) { + RegionRec reg; + + REGION_NULL(pScreen, ®); + TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); + + if(REGION_NOTEMPTY(pScreen, ®)) { + REGION_TRANSLATE(pScreen, ®, ptOldOrg.x - pWin->drawable.x, + ptOldOrg.y - pWin->drawable.y); + REGION_INTERSECT(pScreen, ®, ®, prgnSrc); + + /* The MoveBuffers interface is not ideal */ + (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, + pDRIPriv->pDriverInfo->ddxDrawableTableEntry); + } + + REGION_UNINIT(pScreen, ®); + } + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.CopyWindow) { + /* unwrap */ + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + + /* call lower layers */ + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* rewrap */ + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = DRICopyWindow; + } +} + +static void +DRIGetSecs(long *secs, long *usecs) +{ +#ifdef XFree86LOADER + getsecs(secs,usecs); +#else + struct timeval tv; + + gettimeofday(&tv, NULL); + + *secs = tv.tv_sec; + *usecs = tv.tv_usec; +#endif +} + +static unsigned long +DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, + unsigned long f_secs, unsigned long f_usecs) +{ + if (f_usecs < s_usecs) { + --f_secs; + f_usecs += 1000000; + } + return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; +} + +static void +DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) +{ + int count = 10000; +#if !defined(__alpha__) && !defined(__powerpc__) + char ret; +#else + int ret; +#endif + long s_secs, s_usecs; + long f_secs, f_usecs; + long msecs; + long prev = 0; + + DRIGetSecs(&s_secs, &s_usecs); + + do { + DRM_SPINLOCK_COUNT(lock, val, count, ret); + if (!ret) return; /* Got lock */ + DRIGetSecs(&f_secs, &f_usecs); + msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); + if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ + } while (msecs < timeout); + + /* Didn't get lock, so take it. The worst + that can happen is that there is some + garbage written to the wrong part of the + framebuffer that a refresh will repair. + That's undesirable, but better than + locking the server. This should be a + very rare event. */ + DRM_SPINLOCK_TAKE(lock, val); +} + +static void +DRILockTree(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv) return; + + /* Restore the last known 3D context if the X context is hidden */ + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_NO_CONTEXT, + NULL, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore); + } + + /* Call kernel to release lock */ + DRIUnlock(pScreen); + + /* Grab drawable spin lock: a time out between 10 and 30 seconds is + appropriate, since this should never time out except in the case of + client death while the lock is being held. The timeout must be + greater than any reasonable rendering time. */ + DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ + + /* Call kernel flush outstanding buffers and relock */ + DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); + + /* Switch back to our 2D context if the X context is hidden */ + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_3D_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore); + } +} + +/* It appears that somebody is relying on the lock being set even + if we aren't touching 3D windows */ + +#define DRI_BROKEN + +static Bool DRIWindowsTouched = FALSE; + +int +DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + int returnValue = 1; /* always return 1, not checked by dix/window.c */ + + if(!pDRIPriv) return returnValue; + + DRIWindowsTouched = FALSE; + +#ifdef DRI_BROKEN + if(!DRIWindowsTouched) { + DRILockTree(pScreen); + DRIWindowsTouched = TRUE; + } +#endif + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.ValidateTree) { + /* unwrap */ + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + + /* call lower layers */ + returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); + + /* rewrap */ + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = DRIValidateTree; + } + + return returnValue; +} + +void +DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + + if (pParent) { + pScreen = pParent->drawable.pScreen; + } else { + pScreen = pChild->drawable.pScreen; + } + if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; + + if (pDRIPriv->wrap.PostValidateTree) { + /* unwrap */ + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + + /* call lower layers */ + (*pScreen->PostValidateTree)(pParent, pChild, kind); + + /* rewrap */ + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = DRIPostValidateTree; + } + + if (DRIWindowsTouched) { + /* Release spin lock */ + DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); + DRIWindowsTouched = FALSE; + } +} + +void +DRIClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + + if(!pDRIPriv) return; + + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + +#ifndef DRI_BROKEN + if(!DRIWindowsTouched) { + DRILockTree(pScreen); + DRIWindowsTouched = TRUE; + } +#endif + + pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp + = DRIDrawableValidationStamp++; + } + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.ClipNotify) { + + /* unwrap */ + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + + /* call lower layers */ + (*pScreen->ClipNotify)(pWin, dx, dy); + + /* rewrap */ + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = DRIClipNotify; + } +} + +CARD32 +DRIGetDrawableIndex(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + CARD32 index; + + if (pDRIDrawablePriv) { + index = pDRIDrawablePriv->drawableIndex; + } + else { + index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; + } + + return index; +} + +unsigned int +DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; +} + + +void +DRIPrintDrawableLock(ScreenPtr pScreen, char *msg) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); +} + +void +DRILock(ScreenPtr pScreen, int flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if(!pDRIPriv) return; + + if (!pDRIPriv->lockRefCount) + DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pSAREA, pDRIPriv->myContext, flags); + pDRIPriv->lockRefCount++; +} + +void +DRIUnlock(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if(!pDRIPriv) return; + + if (pDRIPriv->lockRefCount > 0) { + pDRIPriv->lockRefCount--; + } + else { + ErrorF("DRIUnlock called when not locked\n"); + return; + } + if (!pDRIPriv->lockRefCount) + DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pSAREA, pDRIPriv->myContext); +} + +void * +DRIGetSAREAPrivate(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if (!pDRIPriv) return 0; + + return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); +} + +drm_context_t +DRIGetContext(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if (!pDRIPriv) return 0; + + return pDRIPriv->myContext; +} + +/* This lets get at the unwrapped functions so that they can correctly + * call the lowerlevel functions, and choose whether they will be + * called at every level of recursion (eg in validatetree). + */ +DRIWrappedFuncsRec * +DRIGetWrappedFuncs(ScreenPtr pScreen) +{ + return &(DRI_SCREEN_PRIV(pScreen)->wrap); +} + +/* note that this returns the library version, not the protocol version */ +void +DRIQueryVersion(int *majorVersion, + int *minorVersion, + int *patchVersion) +{ + *majorVersion = DRIINFO_MAJOR_VERSION; + *minorVersion = DRIINFO_MINOR_VERSION; + *patchVersion = DRIINFO_PATCH_VERSION; +} + +static void +_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) +{ + pDRIPriv->pSAREA->frame.x = x; + pDRIPriv->pSAREA->frame.y = y; + pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; + pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; +} + +void +DRIAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[scrnIndex]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int px, py; + + if (!pDRIPriv || !pDRIPriv->pSAREA) { + DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", + pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); + return; + } + + if (pDRIPriv->fullscreen) { + /* Fix up frame */ + pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; + pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; + pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; + pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; + + /* Fix up cursor */ + miPointerPosition(&px, &py); + if (px < pScrn->frameX0) px = pScrn->frameX0; + if (px > pScrn->frameX1) px = pScrn->frameX1; + if (py < pScrn->frameY0) py = pScrn->frameY0; + if (py > pScrn->frameY1) py = pScrn->frameY1; + pScreen->SetCursorPosition(pScreen, px, py, TRUE); + return; + } + + if (pDRIPriv->wrap.AdjustFrame) { + /* unwrap */ + pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; + /* call lower layers */ + (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); + /* rewrap */ + pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; + pScrn->AdjustFrame = DRIAdjustFrame; + } + + _DRIAdjustFrame(pScrn, pDRIPriv, x, y); +} + +/* + * DRIMoveBuffersHelper swaps the regions rects in place leaving you + * a region with the rects in the order that you need to blit them, + * but it is possibly (likely) an invalid region afterwards. If you + * need to use the region again for anything you have to call + * REGION_VALIDATE on it, or better yet, save a copy first. + */ + +void +DRIMoveBuffersHelper( + ScreenPtr pScreen, + int dx, + int dy, + int *xdir, + int *ydir, + RegionPtr reg +) +{ + BoxPtr extents, pbox, firstBox, lastBox; + BoxRec tmpBox; + int y, nbox; + + extents = REGION_EXTENTS(pScreen, reg); + nbox = REGION_NUM_RECTS(reg); + pbox = REGION_RECTS(reg); + + if((dy > 0) && (dy < (extents->y2 - extents->y1))) { + *ydir = -1; + if(nbox > 1) { + firstBox = pbox; + lastBox = pbox + nbox - 1; + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + } + } else *ydir = 1; + + if((dx > 0) && (dx < (extents->x2 - extents->x1))) { + *xdir = -1; + if(nbox > 1) { + firstBox = lastBox = pbox; + y = pbox->y1; + while(--nbox) { + pbox++; + if(pbox->y1 == y) lastBox++; + else { + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + + firstBox = lastBox = pbox; + y = pbox->y1; + } + } + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + } + } else *xdir = 1; + +} + +char * +DRICreatePCIBusID(pciVideoPtr PciInfo) +{ + char *busID; + int domain; + PCITAG tag; + + busID = xalloc(20); + if (busID == NULL) + return NULL; + + tag = pciTag(PciInfo->bus, PciInfo->device, PciInfo->func); + domain = xf86GetPciDomain(tag); + snprintf(busID, 20, "pci:%04x:%02x:%02x.%d", domain, PciInfo->bus, + PciInfo->device, PciInfo->func); + return busID; +} diff --git a/nx-X11/programs/Xserver/GL/dri/dri.h b/nx-X11/programs/Xserver/GL/dri/dri.h new file mode 100644 index 000000000..312e8a8bb --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/dri.h @@ -0,0 +1,345 @@ +/* $XFree86: xc/programs/Xserver/GL/dri/dri.h,v 1.18 2001/03/21 16:21:40 dawes Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Jens Owen <jens@tungstengraphics.com> + * + */ + +/* Prototypes for DRI functions */ + +#ifndef _DRI_H_ + +#include "scrnintstr.h" +#include "xf86dri.h" + +typedef int DRISyncType; + +#define DRI_NO_SYNC 0 +#define DRI_2D_SYNC 1 +#define DRI_3D_SYNC 2 + +typedef int DRIContextType; + +typedef struct _DRIContextPrivRec DRIContextPrivRec, *DRIContextPrivPtr; + +typedef enum _DRIContextFlags +{ + DRI_CONTEXT_2DONLY = 0x01, + DRI_CONTEXT_PRESERVED = 0x02, + DRI_CONTEXT_RESERVED = 0x04 /* DRI Only -- no kernel equivalent */ +} DRIContextFlags; + +#define DRI_NO_CONTEXT 0 +#define DRI_2D_CONTEXT 1 +#define DRI_3D_CONTEXT 2 + +typedef int DRISwapMethod; + +#define DRI_HIDE_X_CONTEXT 0 +#define DRI_SERVER_SWAP 1 +#define DRI_KERNEL_SWAP 2 + +typedef int DRIWindowRequests; + +#define DRI_NO_WINDOWS 0 +#define DRI_3D_WINDOWS_ONLY 1 +#define DRI_ALL_WINDOWS 2 + + +typedef void (*ClipNotifyPtr)( WindowPtr, int, int ); +typedef void (*AdjustFramePtr)(int scrnIndex, int x, int y, int flags); + + +/* + * These functions can be wrapped by the DRI. Each of these have + * generic default funcs (initialized in DRICreateInfoRec) and can be + * overridden by the driver in its [driver]DRIScreenInit function. + */ +typedef struct { + ScreenWakeupHandlerProcPtr WakeupHandler; + ScreenBlockHandlerProcPtr BlockHandler; + WindowExposuresProcPtr WindowExposures; + CopyWindowProcPtr CopyWindow; + ValidateTreeProcPtr ValidateTree; + PostValidateTreeProcPtr PostValidateTree; + ClipNotifyProcPtr ClipNotify; + AdjustFramePtr AdjustFrame; +} DRIWrappedFuncsRec, *DRIWrappedFuncsPtr; + + +/* + * Prior to Xorg 6.8.99.8, the DRIInfoRec structure was implicitly versioned + * by the XF86DRI_*_VERSION defines in xf86dristr.h. These numbers were also + * being used to version the XFree86-DRI protocol. Bugs #3066 and #3163 + * showed that this was inadequate. The DRIInfoRec structure is now versioned + * by the DRIINFO_*_VERSION defines in this file. - ajax, 2005-05-18. + * + * Revision history: + * 4.1.0 and earlier: DRIQueryVersion returns XF86DRI_*_VERSION. + * 4.2.0: DRIQueryVersion begins returning DRIINFO_*_VERSION. + * 5.0.0: frameBufferPhysicalAddress changed from CARD32 to pointer. + */ + +#define DRIINFO_MAJOR_VERSION 5 +#define DRIINFO_MINOR_VERSION 0 +#define DRIINFO_PATCH_VERSION 0 + +typedef struct { + /* driver call back functions + * + * New fields should be added at the end for backwards compatibility. + * Bump the DRIINFO patch number to indicate bugfixes. + * Bump the DRIINFO minor number to indicate new fields. + * Bump the DRIINFO major number to indicate binary-incompatible changes. + */ + Bool (*CreateContext)(ScreenPtr pScreen, + VisualPtr visual, + drm_context_t hHWContext, + void* pVisualConfigPriv, + DRIContextType context); + void (*DestroyContext)(ScreenPtr pScreen, + drm_context_t hHWContext, + DRIContextType context); + void (*SwapContext)(ScreenPtr pScreen, + DRISyncType syncType, + DRIContextType readContextType, + void* readContextStore, + DRIContextType writeContextType, + void* writeContextStore); + void (*InitBuffers)(WindowPtr pWin, + RegionPtr prgn, + CARD32 indx); + void (*MoveBuffers)(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc, + CARD32 indx); + void (*TransitionTo3d)(ScreenPtr pScreen); + void (*TransitionTo2d)(ScreenPtr pScreen); + + void (*SetDrawableIndex)(WindowPtr pWin, CARD32 indx); + Bool (*OpenFullScreen)(ScreenPtr pScreen); + Bool (*CloseFullScreen)(ScreenPtr pScreen); + + /* wrapped functions */ + DRIWrappedFuncsRec wrap; + + /* device info */ + char* drmDriverName; + char* clientDriverName; + char* busIdString; + int ddxDriverMajorVersion; + int ddxDriverMinorVersion; + int ddxDriverPatchVersion; + pointer frameBufferPhysicalAddress; + long frameBufferSize; + long frameBufferStride; + long SAREASize; + int maxDrawableTableEntry; + int ddxDrawableTableEntry; + long contextSize; + DRISwapMethod driverSwapMethod; + DRIWindowRequests bufferRequests; + int devPrivateSize; + void* devPrivate; + Bool createDummyCtx; + Bool createDummyCtxPriv; + + /* New with DRI version 4.1.0 */ + void (*TransitionSingleToMulti3D)(ScreenPtr pScreen); + void (*TransitionMultiToSingle3D)(ScreenPtr pScreen); +} DRIInfoRec, *DRIInfoPtr; + + +extern Bool DRIScreenInit(ScreenPtr pScreen, + DRIInfoPtr pDRIInfo, + int *pDRMFD); + +extern void DRICloseScreen(ScreenPtr pScreen); + +extern Bool DRIExtensionInit(void); + +extern void DRIReset(void); + +extern Bool DRIQueryDirectRenderingCapable(ScreenPtr pScreen, + Bool *isCapable); + +extern Bool DRIOpenConnection(ScreenPtr pScreen, + drm_handle_t * hSAREA, + char **busIdString); + +extern Bool DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic); + +extern Bool DRICloseConnection(ScreenPtr pScreen); + +extern Bool DRIGetClientDriverName(ScreenPtr pScreen, + int* ddxDriverMajorVersion, + int* ddxDriverMinorVersion, + int* ddxDriverPatchVersion, + char** clientDriverName); + +extern Bool DRICreateContext(ScreenPtr pScreen, + VisualPtr visual, + XID context, + drm_context_t * pHWContext); + +extern Bool DRIDestroyContext(ScreenPtr pScreen, XID context); + +extern Bool DRIContextPrivDelete(pointer pResource, XID id); + +extern Bool DRICreateDrawable(ScreenPtr pScreen, + Drawable id, + DrawablePtr pDrawable, + drm_drawable_t * hHWDrawable); + +extern Bool DRIDestroyDrawable(ScreenPtr pScreen, + Drawable id, + DrawablePtr pDrawable); + +extern Bool DRIDrawablePrivDelete(pointer pResource, + XID id); + +extern Bool DRIGetDrawableInfo(ScreenPtr pScreen, + DrawablePtr pDrawable, + unsigned int* indx, + unsigned int* stamp, + int* X, + int* Y, + int* W, + int* H, + int* numClipRects, + drm_clip_rect_t ** pClipRects, + int* backX, + int* backY, + int* numBackClipRects, + drm_clip_rect_t ** pBackClipRects); + +extern Bool DRIGetDeviceInfo(ScreenPtr pScreen, + drm_handle_t * hFrameBuffer, + int* fbOrigin, + int* fbSize, + int* fbStride, + int* devPrivateSize, + void** pDevPrivate); + +extern DRIInfoPtr DRICreateInfoRec(void); + +extern void DRIDestroyInfoRec(DRIInfoPtr DRIInfo); + +extern Bool DRIFinishScreenInit(ScreenPtr pScreen); + +extern void DRIWakeupHandler(pointer wakeupData, + int result, + pointer pReadmask); + +extern void DRIBlockHandler(pointer blockData, + OSTimePtr pTimeout, + pointer pReadmask); + +extern void DRIDoWakeupHandler(int screenNum, + pointer wakeupData, + unsigned long result, + pointer pReadmask); + +extern void DRIDoBlockHandler(int screenNum, + pointer blockData, + pointer pTimeout, + pointer pReadmask); + +extern void DRISwapContext(int drmFD, + void *oldctx, + void *newctx); + +extern void *DRIGetContextStore(DRIContextPrivPtr context); + +extern void DRIWindowExposures(WindowPtr pWin, + RegionPtr prgn, + RegionPtr bsreg); + +extern void DRICopyWindow(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); + +extern int DRIValidateTree(WindowPtr pParent, + WindowPtr pChild, + VTKind kind); + +extern void DRIPostValidateTree(WindowPtr pParent, + WindowPtr pChild, + VTKind kind); + +extern void DRIClipNotify(WindowPtr pWin, + int dx, + int dy); + +extern CARD32 DRIGetDrawableIndex(WindowPtr pWin); + +extern void DRIPrintDrawableLock(ScreenPtr pScreen, char *msg); + +extern void DRILock(ScreenPtr pScreen, int flags); + +extern void DRIUnlock(ScreenPtr pScreen); + +extern DRIWrappedFuncsRec *DRIGetWrappedFuncs(ScreenPtr pScreen); + +extern void *DRIGetSAREAPrivate(ScreenPtr pScreen); + +extern unsigned int DRIGetDrawableStamp(ScreenPtr pScreen, + CARD32 drawable_index); + +extern DRIContextPrivPtr DRICreateContextPriv(ScreenPtr pScreen, + drm_context_t * pHWContext, + DRIContextFlags flags); + +extern DRIContextPrivPtr DRICreateContextPrivFromHandle(ScreenPtr pScreen, + drm_context_t hHWContext, + DRIContextFlags flags); + +extern Bool DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv); + +extern drm_context_t DRIGetContext(ScreenPtr pScreen); + +extern void DRIQueryVersion(int *majorVersion, + int *minorVersion, + int *patchVersion); + +extern void DRIAdjustFrame(int scrnIndex, int x, int y, int flags); + +extern void DRIMoveBuffersHelper(ScreenPtr pScreen, + int dx, + int dy, + int *xdir, + int *ydir, + RegionPtr reg); + +extern char *DRICreatePCIBusID(pciVideoPtr PciInfo); + +#define _DRI_H_ + +#endif diff --git a/nx-X11/programs/Xserver/GL/dri/drimodule.c b/nx-X11/programs/Xserver/GL/dri/drimodule.c new file mode 100644 index 000000000..922c6f40e --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/drimodule.c @@ -0,0 +1,127 @@ +/* $XdotOrg: xc/programs/Xserver/GL/dri/drimodule.c,v 1.6 2005/11/02 15:53:57 kem Exp $ */ +/************************************************************************** + +Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ +/* $XFree86: xc/programs/Xserver/GL/dri/drimodule.c,v 1.5 2001/06/15 21:22:39 dawes Exp $ */ + +/* + * Authors: + * Kevin E. Martin <kevin@precisioninsight.com> + * Rickard E. Faith <faith@precisioninsight.com> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86Module.h" +#include "globals.h" + +static MODULESETUPPROTO(driSetup); + +static XF86ModuleVersionInfo VersRec = +{ + "dri", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_EXTENSION, + ABI_EXTENSION_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +extern void XFree86DRIExtensionInit(INITARGS); +#define _XF86DRI_SERVER_ +#include "xf86dristr.h" + +ExtensionModule XF86DRIExt = +{ + XFree86DRIExtensionInit, + XF86DRINAME, + &noXFree86DRIExtension, + NULL, + NULL +}; + +static const char *drmSymbols[] = { + "drmAddContextTag", + "drmAddMap", + "drmAuthMagic", + "drmAvailable", + "drmClose", + "drmCreateContext", + "drmCreateDrawable", + "drmDelContextTag", + "drmDestroyContext", + "drmDestroyDrawable", + "drmFreeReservedContextList", + "drmGetContextTag", + "drmGetLock", + "drmGetReservedContextList", + "drmInstallSIGIOHandler", + "drmMap", + "drmOpen", + "drmRemoveSIGIOHandler", + "drmSetBusid", + "drmSetContextFlags", + "drmUnlock", + "drmUnmap", + NULL +}; + +XF86ModuleData driModuleData = { &VersRec, driSetup, NULL }; + +static pointer +driSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + pointer drm = NULL; + + if (!setupDone) { + setupDone = TRUE; + + drm = + LoadSubModule(module, "drm", NULL, NULL, NULL, NULL, errmaj, errmin); + + if (!drm) { + if (errmaj) *errmaj = LDR_NOSUBENT; + } + else { + LoaderReqSymLists(drmSymbols, NULL); + LoaderRefSymbols("noPanoramiXExtension", NULL); + LoadExtension(&XF86DRIExt, FALSE); + } + } else { + if (errmaj) *errmaj = LDR_ONCEONLY; + } + /* Need a non-NULL return value to indicate success */ + return drm; +} + diff --git a/nx-X11/programs/Xserver/GL/dri/dristruct.h b/nx-X11/programs/Xserver/GL/dri/dristruct.h new file mode 100644 index 000000000..b47afba3a --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/dristruct.h @@ -0,0 +1,105 @@ +/* $XFree86: xc/programs/Xserver/GL/dri/dristruct.h,v 1.12 2002/10/30 12:52:03 alanh Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Jens Owen <jens@tungstengraphics.com> + * + */ + +#ifndef DRI_STRUCT_H +#define DRI_STRUCT_H + +#include "xf86drm.h" + + +#define DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin) \ + ((DRIWindowPrivIndex < 0) ? \ + NULL : \ + ((DRIDrawablePrivPtr)((pWin)->devPrivates[DRIWindowPrivIndex].ptr))) + +#define DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix) \ + ((DRIPixmapPrivIndex < 0) ? \ + NULL : \ + ((DRIDrawablePrivPtr)((pPix)->devPrivates[DRIWindowPrivIndex].ptr))) + +typedef struct _DRIDrawablePrivRec +{ + drm_drawable_t hwDrawable; + int drawableIndex; + ScreenPtr pScreen; + int refCount; +} DRIDrawablePrivRec, *DRIDrawablePrivPtr; + +struct _DRIContextPrivRec +{ + drm_context_t hwContext; + ScreenPtr pScreen; + Bool valid3D; + DRIContextFlags flags; + void** pContextStore; +}; + +#define DRI_SCREEN_PRIV(pScreen) \ + ((DRIScreenPrivIndex < 0) ? \ + NULL : \ + ((DRIScreenPrivPtr)((pScreen)->devPrivates[DRIScreenPrivIndex].ptr))) + +#define DRI_SCREEN_PRIV_FROM_INDEX(screenIndex) ((DRIScreenPrivPtr) \ + (screenInfo.screens[screenIndex]->devPrivates[DRIScreenPrivIndex].ptr)) + + +typedef struct _DRIScreenPrivRec +{ + Bool directRenderingSupport; + int drmFD; /* File descriptor for /dev/video/? */ + drm_handle_t hSAREA; /* Handle to SAREA, for mapping */ + XF86DRISAREAPtr pSAREA; /* Mapped pointer to SAREA */ + drm_handle_t hFrameBuffer; /* Handle to framebuffer, for mapping */ + drm_context_t myContext; /* DDX Driver's context */ + DRIContextPrivPtr myContextPriv;/* Pointer to server's private area */ + DRIContextPrivPtr lastPartial3DContext; /* last one partially saved */ + void** hiddenContextStore; /* hidden X context */ + void** partial3DContextStore; /* parital 3D context */ + DRIInfoPtr pDriverInfo; + int nrWindows; + drm_clip_rect_t private_buffer_rect; /* management of private buffers */ + DrawablePtr fullscreen; /* pointer to fullscreen drawable */ + drm_clip_rect_t fullscreen_rect; /* fake rect for fullscreen mode */ + DRIWrappedFuncsRec wrap; + DrawablePtr DRIDrawables[SAREA_MAX_DRAWABLES]; + DRIContextPrivPtr dummyCtxPriv; /* Pointer to dummy context */ + Bool createDummyCtx; + Bool createDummyCtxPriv; + Bool grabbedDRILock; + Bool drmSIGIOHandlerInstalled; + Bool wrapped; + int lockRefCount; +} DRIScreenPrivRec, *DRIScreenPrivPtr; + +#endif /* DRI_STRUCT_H */ diff --git a/nx-X11/programs/Xserver/GL/dri/sarea.h b/nx-X11/programs/Xserver/GL/dri/sarea.h new file mode 100644 index 000000000..77c16e0ef --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/sarea.h @@ -0,0 +1,94 @@ +/* $XFree86: xc/programs/Xserver/GL/dri/sarea.h,v 1.11 2002/10/30 12:52:03 alanh Exp $ */ +/** + * \file sarea.h + * SAREA definitions. + * + * \author Kevin E. Martin <kevin@precisioninsight.com> + * \author Jens Owen <jens@tungstengraphics.com> + * \author Rickard E. (Rik) Faith <faith@valinux.com> + */ + +/* + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* $XFree86: xc/programs/Xserver/GL/dri/sarea.h,v 1.11 2002/10/30 12:52:03 alanh Exp $ */ + +#ifndef _SAREA_H_ +#define _SAREA_H_ + +#include "xf86drm.h" + +/* SAREA area needs to be at least a page */ +#if defined(__alpha__) +#define SAREA_MAX 0x2000 +#elif defined(__ia64__) +#define SAREA_MAX 0x10000 /* 64kB */ +#else +/* Intel 830M driver needs at least 8k SAREA */ +#define SAREA_MAX 0x2000 +#endif + +#define SAREA_MAX_DRAWABLES 256 + +#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000 + +/** + * SAREA per drawable information. + * + * \sa _XF86DRISAREA. + */ +typedef struct _XF86DRISAREADrawable { + unsigned int stamp; + unsigned int flags; +} XF86DRISAREADrawableRec, *XF86DRISAREADrawablePtr; + +/** + * SAREA frame information. + * + * \sa _XF86DRISAREA. + */ +typedef struct _XF86DRISAREAFrame { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} XF86DRISAREAFrameRec, *XF86DRISAREAFramePtr; + +/** + * SAREA definition. + */ +typedef struct _XF86DRISAREA { + /** first thing is always the DRM locking structure */ + drmLock lock; + /** \todo Use readers/writer lock for drawable_lock */ + drmLock drawable_lock; + XF86DRISAREADrawableRec drawableTable[SAREA_MAX_DRAWABLES]; + XF86DRISAREAFrameRec frame; + drm_context_t dummy_context; +} XF86DRISAREARec, *XF86DRISAREAPtr; + +#endif diff --git a/nx-X11/programs/Xserver/GL/dri/xf86dri.c b/nx-X11/programs/Xserver/GL/dri/xf86dri.c new file mode 100644 index 000000000..273ccda1b --- /dev/null +++ b/nx-X11/programs/Xserver/GL/dri/xf86dri.c @@ -0,0 +1,649 @@ +/* $XFree86: xc/programs/Xserver/GL/dri/xf86dri.c,v 1.12 2002/12/14 01:36:08 dawes Exp $ */ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin <martin@valinux.com> + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#ifdef XFree86LOADER +#include "xf86_ansic.h" +#endif + +#define NEED_REPLIES +#define NEED_EVENTS +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86DRI_SERVER_ +#include "xf86dristr.h" +#include "swaprep.h" +#include "xf86str.h" +#include "dri.h" +#include "sarea.h" +#include "dristruct.h" +#include "xf86.h" +#include "xf86drm.h" + +static int DRIErrorBase; + +static DISPATCH_PROC(ProcXF86DRIQueryVersion); +static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(ProcXF86DRIOpenConnection); +static DISPATCH_PROC(ProcXF86DRICloseConnection); +static DISPATCH_PROC(ProcXF86DRIGetClientDriverName); +static DISPATCH_PROC(ProcXF86DRICreateContext); +static DISPATCH_PROC(ProcXF86DRIDestroyContext); +static DISPATCH_PROC(ProcXF86DRICreateDrawable); +static DISPATCH_PROC(ProcXF86DRIDestroyDrawable); +static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo); +static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo); +static DISPATCH_PROC(ProcXF86DRIDispatch); +static DISPATCH_PROC(ProcXF86DRIAuthConnection); + +static DISPATCH_PROC(SProcXF86DRIQueryVersion); +static DISPATCH_PROC(SProcXF86DRIDispatch); + +static void XF86DRIResetProc(ExtensionEntry* extEntry); + +static unsigned char DRIReqCode = 0; + +extern void XFree86DRIExtensionInit(void); + +void +XFree86DRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + +#ifdef XF86DRI_EVENTS + EventType = CreateNewResourceType(XF86DRIFreeEvents); +#endif + + if ( + DRIExtensionInit() && +#ifdef XF86DRI_EVENTS + EventType && ScreenPrivateIndex != -1 && +#endif + (extEntry = AddExtension(XF86DRINAME, + XF86DRINumberEvents, + XF86DRINumberErrors, + ProcXF86DRIDispatch, + SProcXF86DRIDispatch, + XF86DRIResetProc, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + } +} + +/*ARGSUSED*/ +static void +XF86DRIResetProc ( + ExtensionEntry* extEntry +) +{ + DRIReset(); +} + +static int +ProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + xXF86DRIQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XF86DRI_MAJOR_VERSION; + rep.minorVersion = XF86DRI_MINOR_VERSION; + rep.patchVersion = XF86DRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + xXF86DRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], + &isCapable)) { + return BadValue; + } + rep.isCapable = isCapable; + + if (!LocalClient(client)) + rep.isCapable = 0; + + WriteToClient(client, + sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIOpenConnection( + register ClientPtr client +) +{ + xXF86DRIOpenConnectionReply rep; + drm_handle_t hSAREA; + char* busIdString; + + REQUEST(xXF86DRIOpenConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!DRIOpenConnection( screenInfo.screens[stuff->screen], + &hSAREA, + &busIdString)) { + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.busIdStringLength = 0; + if (busIdString) + rep.busIdStringLength = strlen(busIdString); + rep.length = (SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + + ((rep.busIdStringLength + 3) & ~3)) >> 2; + + rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hSAREAHigh = (CARD32)(hSAREA >> 32); +#else + rep.hSAREAHigh = 0; +#endif + + WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); + if (rep.busIdStringLength) + WriteToClient(client, rep.busIdStringLength, busIdString); + return (client->noClientException); +} + +static int +ProcXF86DRIAuthConnection( + register ClientPtr client +) +{ + xXF86DRIAuthConnectionReply rep; + + REQUEST(xXF86DRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.authenticated = 1; + + if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { + ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRICloseConnection( + register ClientPtr client +) +{ + REQUEST(xXF86DRICloseConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + DRICloseConnection( screenInfo.screens[stuff->screen]); + + return (client->noClientException); +} + +static int +ProcXF86DRIGetClientDriverName( + register ClientPtr client +) +{ + xXF86DRIGetClientDriverNameReply rep; + char* clientDriverName; + + REQUEST(xXF86DRIGetClientDriverNameReq); + REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + DRIGetClientDriverName( screenInfo.screens[stuff->screen], + (int *)&rep.ddxDriverMajorVersion, + (int *)&rep.ddxDriverMinorVersion, + (int *)&rep.ddxDriverPatchVersion, + &clientDriverName); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.clientDriverNameLength = 0; + if (clientDriverName) + rep.clientDriverNameLength = strlen(clientDriverName); + rep.length = (SIZEOF(xXF86DRIGetClientDriverNameReply) - + SIZEOF(xGenericReply) + + ((rep.clientDriverNameLength + 3) & ~3)) >> 2; + + WriteToClient(client, + sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); + if (rep.clientDriverNameLength) + WriteToClient(client, + rep.clientDriverNameLength, + clientDriverName); + return (client->noClientException); +} + +static int +ProcXF86DRICreateContext( + register ClientPtr client +) +{ + xXF86DRICreateContextReply rep; + ScreenPtr pScreen; + VisualPtr visual; + int i; + + REQUEST(xXF86DRICreateContextReq); + REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + pScreen = screenInfo.screens[stuff->screen]; + visual = pScreen->visuals; + + /* Find the requested X visual */ + for (i = 0; i < pScreen->numVisuals; i++, visual++) + if (visual->vid == stuff->visual) + break; + if (i == pScreen->numVisuals) { + /* No visual found */ + return BadValue; + } + + if (!DRICreateContext( pScreen, + visual, + stuff->context, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIDestroyContext( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyContextReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!DRIDestroyContext( screenInfo.screens[stuff->screen], + stuff->context)) { + return BadValue; + } + + return (client->noClientException); +} + +static int +ProcXF86DRICreateDrawable( + ClientPtr client +) +{ + xXF86DRICreateDrawableReply rep; + DrawablePtr pDrawable; + + REQUEST(xXF86DRICreateDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!(pDrawable = (DrawablePtr)SecurityLookupDrawable( + (Drawable)stuff->drawable, + client, + SecurityReadAccess))) { + return BadValue; + } + + if (!DRICreateDrawable( screenInfo.screens[stuff->screen], + (Drawable)stuff->drawable, + pDrawable, + (drm_drawable_t *)&rep.hHWDrawable)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + return (client->noClientException); +} + +static int +ProcXF86DRIDestroyDrawable( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyDrawableReq); + DrawablePtr pDrawable; + REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!(pDrawable = (DrawablePtr)SecurityLookupDrawable( + (Drawable)stuff->drawable, + client, + SecurityReadAccess))) { + return BadValue; + } + + if (!DRIDestroyDrawable( screenInfo.screens[stuff->screen], + (Drawable)stuff->drawable, + pDrawable)) { + return BadValue; + } + + return (client->noClientException); +} + +static int +ProcXF86DRIGetDrawableInfo( + register ClientPtr client +) +{ + xXF86DRIGetDrawableInfoReply rep; + DrawablePtr pDrawable; + int X, Y, W, H; + drm_clip_rect_t * pClipRects; + drm_clip_rect_t * pBackClipRects; + int backX, backY; + + REQUEST(xXF86DRIGetDrawableInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!(pDrawable = (DrawablePtr)SecurityLookupDrawable( + (Drawable)stuff->drawable, + client, + SecurityReadAccess))) { + return BadValue; + } + + if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], + pDrawable, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { + return BadValue; + } + + rep.drawableX = X; + rep.drawableY = Y; + rep.drawableWidth = W; + rep.drawableHeight = H; + rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply)); + + rep.backX = backX; + rep.backY = backY; + + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + + if (rep.numClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + + rep.length = ((rep.length + 3) & ~3) >> 2; + + WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); + + if (rep.numClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)pClipRects); + } + + if (rep.numBackClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)pBackClipRects); + } + + return (client->noClientException); +} + +static int +ProcXF86DRIGetDeviceInfo( + register ClientPtr client +) +{ + xXF86DRIGetDeviceInfoReply rep; + drm_handle_t hFrameBuffer; + void *pDevPrivate; + + REQUEST(xXF86DRIGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], + &hFrameBuffer, + (int*)&rep.framebufferOrigin, + (int*)&rep.framebufferSize, + (int*)&rep.framebufferStride, + (int*)&rep.devPrivateSize, + &pDevPrivate)) { + return BadValue; + } + + rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); +#else + rep.hFrameBufferHigh = 0; +#endif + + rep.length = 0; + if (rep.devPrivateSize) { + rep.length = (SIZEOF(xXF86DRIGetDeviceInfoReply) - + SIZEOF(xGenericReply) + + ((rep.devPrivateSize + 3) & ~3)) >> 2; + } + + WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); + if (rep.length) { + WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); + } + return (client->noClientException); +} + +static int +ProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return ProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return ProcXF86DRIQueryDirectRenderingCapable(client); + } + + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + switch (stuff->data) + { + case X_XF86DRIOpenConnection: + return ProcXF86DRIOpenConnection(client); + case X_XF86DRICloseConnection: + return ProcXF86DRICloseConnection(client); + case X_XF86DRIGetClientDriverName: + return ProcXF86DRIGetClientDriverName(client); + case X_XF86DRICreateContext: + return ProcXF86DRICreateContext(client); + case X_XF86DRIDestroyContext: + return ProcXF86DRIDestroyContext(client); + case X_XF86DRICreateDrawable: + return ProcXF86DRICreateDrawable(client); + case X_XF86DRIDestroyDrawable: + return ProcXF86DRIDestroyDrawable(client); + case X_XF86DRIGetDrawableInfo: + return ProcXF86DRIGetDrawableInfo(client); + case X_XF86DRIGetDeviceInfo: + return ProcXF86DRIGetDeviceInfo(client); + case X_XF86DRIAuthConnection: + return ProcXF86DRIAuthConnection(client); + /* {Open,Close}FullScreen are deprecated now */ + default: + return BadRequest; + } +} + +static int +SProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86DRIQueryVersion(client); +} + +static int +SProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* It is bound to be non-local when there is byte swapping */ + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + /* only local clients are allowed DRI access */ + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return SProcXF86DRIQueryVersion(client); + default: + return BadRequest; + } +} |