2078 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			2078 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
/**************************************************************************
 | 
						|
 | 
						|
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"
 | 
						|
#include <sys/time.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#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(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 (xf86LoaderCheckSymbol("noPanoramiXExtension"))
 | 
						|
	xineramaInCore = TRUE;
 | 
						|
 | 
						|
    if (xineramaInCore) {
 | 
						|
	if (!noPanoramiXExtension) {
 | 
						|
	    DRIDrvMsg(pScreen->myNum, X_WARNING,
 | 
						|
		"Direct rendering is not supported when Xinerama is enabled\n");
 | 
						|
	    return FALSE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    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 || DRIGeneration != serverGeneration) {
 | 
						|
	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);
 | 
						|
    __GLXscreen *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);
 | 
						|
    __GLXscreen *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;
 | 
						|
 | 
						|
#if 0
 | 
						|
    printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry);
 | 
						|
#endif
 | 
						|
 | 
						|
    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);
 | 
						|
    }
 | 
						|
 | 
						|
    if (pDRIPriv->windowsTouched)
 | 
						|
        DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1);
 | 
						|
    pDRIPriv->windowsTouched = FALSE;
 | 
						|
 | 
						|
    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;
 | 
						|
 | 
						|
    if (!newContext) {
 | 
						|
	DRIDrvMsg(pScreen->myNum, X_ERROR,
 | 
						|
		  "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n",
 | 
						|
		  oldContext, newContext);
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* 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)
 | 
						|
{
 | 
						|
    struct timeval tv;
 | 
						|
 | 
						|
    gettimeofday(&tv, NULL);
 | 
						|
 | 
						|
    *secs  = tv.tv_sec;
 | 
						|
    *usecs = tv.tv_usec;
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
 | 
						|
    /* 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;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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))) {
 | 
						|
 | 
						|
        if(!pDRIPriv->windowsTouched) {
 | 
						|
            DRILockTree(pScreen);
 | 
						|
            pDRIPriv->windowsTouched = TRUE;
 | 
						|
        }
 | 
						|
 | 
						|
	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;
 | 
						|
}
 |