From 5e633abcca598289d0423d89bb400b41e6417259 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 15 Mar 2011 21:35:41 +0000 Subject: xserver libX11 libxcb mesa git update 15 Mar 2011 --- xorg-server/mi/misprite.c | 2087 ++++++++++++++++++++++----------------------- 1 file changed, 1042 insertions(+), 1045 deletions(-) (limited to 'xorg-server/mi/misprite.c') diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c index b0290af29..0b47592f0 100644 --- a/xorg-server/mi/misprite.c +++ b/xorg-server/mi/misprite.c @@ -1,1045 +1,1042 @@ -/* - * misprite.c - * - * machine independent software sprite routines - */ - -/* - -Copyright 1989, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice 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 NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP 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. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "pixmapstr.h" -#include "input.h" -#include "mi.h" -#include "cursorstr.h" -#include -#include "scrnintstr.h" -#include "colormapst.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "mipointer.h" -#include "misprite.h" -#include "dixfontstr.h" -#include -#include "inputstr.h" -#include "damage.h" - -typedef struct { - CursorPtr pCursor; - int x; /* cursor hotspot */ - int y; - BoxRec saved; /* saved area from the screen */ - Bool isUp; /* cursor in frame buffer */ - Bool shouldBeUp; /* cursor should be displayed */ - WindowPtr pCacheWin; /* window the cursor last seen in */ - Bool isInCacheWin; - Bool checkPixels; /* check colormap collision */ - ScreenPtr pScreen; -} miCursorInfoRec, *miCursorInfoPtr; - -/* - * per screen information - */ - -typedef struct { - /* screen procedures */ - CloseScreenProcPtr CloseScreen; - GetImageProcPtr GetImage; - GetSpansProcPtr GetSpans; - SourceValidateProcPtr SourceValidate; - - /* window procedures */ - CopyWindowProcPtr CopyWindow; - - /* colormap procedures */ - InstallColormapProcPtr InstallColormap; - StoreColorsProcPtr StoreColors; - - /* os layer procedures */ - ScreenBlockHandlerProcPtr BlockHandler; - - /* device cursor procedures */ - DeviceCursorInitializeProcPtr DeviceCursorInitialize; - DeviceCursorCleanupProcPtr DeviceCursorCleanup; - - xColorItem colors[2]; - ColormapPtr pInstalledMap; - ColormapPtr pColormap; - VisualPtr pVisual; - DamagePtr pDamage; /* damage tracking structure */ - Bool damageRegistered; - int numberOfCursors; -} miSpriteScreenRec, *miSpriteScreenPtr; - -#define SOURCE_COLOR 0 -#define MASK_COLOR 1 - -/* - * Overlap BoxPtr and Box elements - */ -#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ - (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ - ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) - -/* - * Overlap BoxPtr, origins, and rectangle - */ -#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ - BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) - -/* - * Overlap BoxPtr, origins and RectPtr - */ -#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ - ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ - (int)((pRect)->width), (int)((pRect)->height)) -/* - * Overlap BoxPtr and horizontal span - */ -#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) - -#define LINE_SORT(x1,y1,x2,y2) \ -{ int _t; \ - if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ - if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } - -#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ - BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) - - -#define SPRITE_DEBUG_ENABLE 0 -#if SPRITE_DEBUG_ENABLE -#define SPRITE_DEBUG(x) ErrorF x -#else -#define SPRITE_DEBUG(x) -#endif - -#define MISPRITE(dev) \ - (IsFloating(dev) ? \ - (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ - (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) - -static void -miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (pScreenPriv->damageRegistered) { - DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), - pScreenPriv->pDamage); - pScreenPriv->damageRegistered = 0; - } -} - -static void -miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (!pScreenPriv->damageRegistered) { - pScreenPriv->damageRegistered = 1; - DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), - pScreenPriv->pDamage); - } -} - -static void -miSpriteIsUp(miCursorInfoPtr pDevCursor) -{ - pDevCursor->isUp = TRUE; -} - -static void -miSpriteIsDown(miCursorInfoPtr pDevCursor) -{ - pDevCursor->isUp = FALSE; -} - -/* - * screen wrappers - */ - -static DevPrivateKeyRec miSpriteScreenKeyRec; -#define miSpriteScreenKey (&miSpriteScreenKeyRec) -#define GetSpriteScreen(pScreen) \ - (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey)) -static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; -#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec) - -static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); -static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, - int w, int h, unsigned int format, - unsigned long planemask, char *pdstLine); -static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, - DDXPointPtr ppt, int *pwidth, int nspans, - char *pdstStart); -static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, - int width, int height, - unsigned int subWindowMode); -static void miSpriteCopyWindow (WindowPtr pWindow, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc); -static void miSpriteBlockHandler(int i, pointer blockData, - pointer pTimeout, - pointer pReadMask); -static void miSpriteInstallColormap(ColormapPtr pMap); -static void miSpriteStoreColors(ColormapPtr pMap, int ndef, - xColorItem *pdef); - -static void miSpriteComputeSaved(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, - ScreenPtr pScreen); - -#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ - (pPriv)->field) -#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ - ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) - -/* - * pointer-sprite method table - */ - -static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y); -static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y); - -miPointerSpriteFuncRec miSpritePointerFuncs = { - miSpriteRealizeCursor, - miSpriteUnrealizeCursor, - miSpriteSetCursor, - miSpriteMoveCursor, - miSpriteDeviceCursorInitialize, - miSpriteDeviceCursorCleanup, -}; - -/* - * other misc functions - */ - -static void miSpriteRemoveCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miSpriteRestoreCursor(DeviceIntPtr pDev, - ScreenPtr pScreen); - -static void -miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) -{ - if (!pScreenPriv->BlockHandler) { - pScreenPriv->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = miSpriteBlockHandler; - } -} - -static void -miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - ScreenPtr pScreen = closure; - miCursorInfoPtr pCursorInfo; - DeviceIntPtr pDev; - - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - - if (pCursorInfo->isUp && - pCursorInfo->pScreen == pScreen && - RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) - { - SPRITE_DEBUG(("Damage remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } -} - -/* - * miSpriteInitialize -- called from device-dependent screen - * initialization proc after all of the function pointers have - * been stored in the screen structure. - */ - -Bool -miSpriteInitialize (ScreenPtr pScreen, - miPointerScreenFuncPtr screenFuncs) -{ - miSpriteScreenPtr pScreenPriv; - VisualPtr pVisual; - - if (!DamageSetup (pScreen)) - return FALSE; - - if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0)) - return FALSE; - - pScreenPriv = malloc(sizeof (miSpriteScreenRec)); - if (!pScreenPriv) - return FALSE; - - pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, - NULL, - DamageReportRawRegion, - TRUE, - pScreen, - pScreen); - - if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) - { - free(pScreenPriv); - return FALSE; - } - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++) - ; - pScreenPriv->pVisual = pVisual; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreenPriv->GetImage = pScreen->GetImage; - pScreenPriv->GetSpans = pScreen->GetSpans; - pScreenPriv->SourceValidate = pScreen->SourceValidate; - - pScreenPriv->CopyWindow = pScreen->CopyWindow; - - pScreenPriv->InstallColormap = pScreen->InstallColormap; - pScreenPriv->StoreColors = pScreen->StoreColors; - - pScreenPriv->BlockHandler = NULL; - - pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; - pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; - - pScreenPriv->pInstalledMap = NULL; - pScreenPriv->pColormap = NULL; - pScreenPriv->colors[SOURCE_COLOR].red = 0; - pScreenPriv->colors[SOURCE_COLOR].green = 0; - pScreenPriv->colors[SOURCE_COLOR].blue = 0; - pScreenPriv->colors[MASK_COLOR].red = 0; - pScreenPriv->colors[MASK_COLOR].green = 0; - pScreenPriv->colors[MASK_COLOR].blue = 0; - pScreenPriv->damageRegistered = 0; - pScreenPriv->numberOfCursors = 0; - - dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); - - pScreen->CloseScreen = miSpriteCloseScreen; - pScreen->GetImage = miSpriteGetImage; - pScreen->GetSpans = miSpriteGetSpans; - pScreen->SourceValidate = miSpriteSourceValidate; - - pScreen->CopyWindow = miSpriteCopyWindow; - pScreen->InstallColormap = miSpriteInstallColormap; - pScreen->StoreColors = miSpriteStoreColors; - - return TRUE; -} - -/* - * Screen wrappers - */ - -/* - * CloseScreen wrapper -- unwrap everything, free the private data - * and call the wrapped function - */ - -static Bool -miSpriteCloseScreen (int i, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->GetImage = pScreenPriv->GetImage; - pScreen->GetSpans = pScreenPriv->GetSpans; - pScreen->SourceValidate = pScreenPriv->SourceValidate; - pScreen->InstallColormap = pScreenPriv->InstallColormap; - pScreen->StoreColors = pScreenPriv->StoreColors; - - DamageDestroy (pScreenPriv->pDamage); - - free(pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format, unsigned long planemask, - char *pdstLine) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, GetImage); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, - sx, sy, w, h)) - { - SPRITE_DEBUG (("GetImage remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } - - (*pScreen->GetImage) (pDrawable, sx, sy, w, h, - format, planemask, pdstLine); - - SCREEN_EPILOGUE (pPriv, pScreen, GetImage); -} - -static void -miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, - int *pwidth, int nspans, char *pdstStart) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, GetSpans); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - { - DDXPointPtr pts; - int *widths; - int nPts; - int xorg, - yorg; - - xorg = pDrawable->x; - yorg = pDrawable->y; - - for (pts = ppt, widths = pwidth, nPts = nspans; - nPts--; - pts++, widths++) - { - if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, - pts->x+xorg,*widths)) - { - SPRITE_DEBUG (("GetSpans remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - break; - } - } - } - } - } - } - - (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); - - SCREEN_EPILOGUE (pPriv, pScreen, GetSpans); -} - -static void -miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, - int height, unsigned int subWindowMode) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate); - - if (pDrawable->type == DRAWABLE_WINDOW) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, - x, y, width, height)) - { - SPRITE_DEBUG (("SourceValidate remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } - - if (pScreen->SourceValidate) - (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); - - SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate); -} - -static void -miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow); - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - /* - * Damage will take care of destination check - */ - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && - RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) - { - SPRITE_DEBUG (("CopyWindow remove\n")); - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - - (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); - SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow); -} - -static void -miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, - pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[i]; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - Bool WorkToDo = FALSE; - - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo && !pCursorInfo->isUp - && pCursorInfo->pScreen == pScreen - && pCursorInfo->shouldBeUp) - { - SPRITE_DEBUG (("BlockHandler save")); - miSpriteSaveUnderCursor (pDev, pScreen); - } - } - } - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - if (pCursorInfo && !pCursorInfo->isUp && - pCursorInfo->pScreen == pScreen && - pCursorInfo->shouldBeUp) - { - SPRITE_DEBUG (("BlockHandler restore\n")); - miSpriteRestoreCursor (pDev, pScreen); - if (!pCursorInfo->isUp) - WorkToDo = TRUE; - } - } - } - - SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); - - (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); - - if (WorkToDo) - SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); - else - pPriv->BlockHandler = NULL; -} - -static void -miSpriteInstallColormap (ColormapPtr pMap) -{ - ScreenPtr pScreen = pMap->pScreen; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - - SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); - - (*pScreen->InstallColormap) (pMap); - - SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); - - /* InstallColormap can be called before devices are initialized. */ - pPriv->pInstalledMap = pMap; - if (pPriv->pColormap != pMap) - { - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - pCursorInfo->checkPixels = TRUE; - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - miSpriteRemoveCursor(pDev, pScreen); - } - } - - } -} - -static void -miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) -{ - ScreenPtr pScreen = pMap->pScreen; - miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); - int i; - int updated; - VisualPtr pVisual; - DeviceIntPtr pDev; - miCursorInfoPtr pCursorInfo; - - SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); - - (*pScreen->StoreColors) (pMap, ndef, pdef); - - SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); - - if (pPriv->pColormap == pMap) - { - updated = 0; - pVisual = pMap->pVisual; - if (pVisual->class == DirectColor) - { - /* Direct color - match on any of the subfields */ - -#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) - -#define UpdateDAC(dev, plane,dac,mask) {\ - if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ - dev->colors[plane].dac = pdef[i].dac; \ - updated = 1; \ - } \ -} - -#define CheckDirect(dev, plane) \ - UpdateDAC(dev, plane,red,redMask) \ - UpdateDAC(dev, plane,green,greenMask) \ - UpdateDAC(dev, plane,blue,blueMask) - - for (i = 0; i < ndef; i++) - { - CheckDirect (pPriv, SOURCE_COLOR) - CheckDirect (pPriv, MASK_COLOR) - } - } - else - { - /* PseudoColor/GrayScale - match on exact pixel */ - for (i = 0; i < ndef; i++) - { - if (pdef[i].pixel == - pPriv->colors[SOURCE_COLOR].pixel) - { - pPriv->colors[SOURCE_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - if (pdef[i].pixel == - pPriv->colors[MASK_COLOR].pixel) - { - pPriv->colors[MASK_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - } - } - if (updated) - { - for(pDev = inputInfo.devices; pDev; pDev = pDev->next) - { - if (DevHasCursor(pDev)) - { - pCursorInfo = MISPRITE(pDev); - pCursorInfo->checkPixels = TRUE; - if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) - miSpriteRemoveCursor (pDev, pScreen); - } - } - } - } -} - -static void -miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); - CursorPtr pCursor; - xColorItem *sourceColor, *maskColor; - - pCursor = pDevCursor->pCursor; - sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; - maskColor = &pScreenPriv->colors[MASK_COLOR]; - if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || - !(pCursor->foreRed == sourceColor->red && - pCursor->foreGreen == sourceColor->green && - pCursor->foreBlue == sourceColor->blue && - pCursor->backRed == maskColor->red && - pCursor->backGreen == maskColor->green && - pCursor->backBlue == maskColor->blue)) - { - pScreenPriv->pColormap = pScreenPriv->pInstalledMap; - sourceColor->red = pCursor->foreRed; - sourceColor->green = pCursor->foreGreen; - sourceColor->blue = pCursor->foreBlue; - FakeAllocColor (pScreenPriv->pColormap, sourceColor); - maskColor->red = pCursor->backRed; - maskColor->green = pCursor->backGreen; - maskColor->blue = pCursor->backBlue; - FakeAllocColor (pScreenPriv->pColormap, maskColor); - /* "free" the pixels right away, don't let this confuse you */ - FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); - FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); - } - - pDevCursor->checkPixels = FALSE; - -} - -/* - * miPointer interface routines - */ - -#define SPRITE_PAD 8 - -static Bool -miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return FALSE; - - pCursorInfo = MISPRITE(pDev); - - if (pCursor == pCursorInfo->pCursor) - pCursorInfo->checkPixels = TRUE; - - return miDCRealizeCursor(pScreen, pCursor); -} - -static Bool -miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - return miDCUnrealizeCursor(pScreen, pCursor); -} - -static void -miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, int x, int y) -{ - miCursorInfoPtr pPointer; - miSpriteScreenPtr pScreenPriv; - - if (IsFloating(pDev)) - return; - - pPointer = MISPRITE(pDev); - pScreenPriv = GetSpriteScreen(pScreen); - - if (!pCursor) - { - if (pPointer->shouldBeUp) - --pScreenPriv->numberOfCursors; - pPointer->shouldBeUp = FALSE; - if (pPointer->isUp) - miSpriteRemoveCursor (pDev, pScreen); - if (pScreenPriv->numberOfCursors == 0) - miSpriteDisableDamage(pScreen, pScreenPriv); - pPointer->pCursor = 0; - return; - } - if (!pPointer->shouldBeUp) - pScreenPriv->numberOfCursors++; - pPointer->shouldBeUp = TRUE; - if (!pPointer->isUp) - miSpriteRegisterBlockHandler(pScreen, pScreenPriv); - if (pPointer->x == x && - pPointer->y == y && - pPointer->pCursor == pCursor && - !pPointer->checkPixels) - { - return; - } - pPointer->x = x; - pPointer->y = y; - pPointer->pCacheWin = NullWindow; - if (pPointer->checkPixels || pPointer->pCursor != pCursor) - { - pPointer->pCursor = pCursor; - miSpriteFindColors (pPointer, pScreen); - } - if (pPointer->isUp) { - /* TODO: reimplement flicker-free MoveCursor */ - SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); - miSpriteRemoveCursor (pDev, pScreen); - } - - if (!pPointer->isUp && pPointer->pCursor) - { - SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); - miSpriteSaveUnderCursor(pDev, pScreen); - miSpriteRestoreCursor (pDev, pScreen); - } - -} - -static void -miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - CursorPtr pCursor; - - if (IsFloating(pDev)) - return; - - pCursor = MISPRITE(pDev)->pCursor; - - miSpriteSetCursor (pDev, pScreen, pCursor, x, y); -} - - -static Bool -miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miCursorInfoPtr pCursorInfo; - int ret = FALSE; - - pCursorInfo = malloc(sizeof(miCursorInfoRec)); - if (!pCursorInfo) - return FALSE; - - pCursorInfo->pCursor = NULL; - pCursorInfo->x = 0; - pCursorInfo->y = 0; - pCursorInfo->isUp = FALSE; - pCursorInfo->shouldBeUp = FALSE; - pCursorInfo->pCacheWin = NullWindow; - pCursorInfo->isInCacheWin = FALSE; - pCursorInfo->checkPixels = TRUE; - pCursorInfo->pScreen = FALSE; - - ret = miDCDeviceInitialize(pDev, pScreen); - if (!ret) - { - free(pCursorInfo); - pCursorInfo = NULL; - } - dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo); - return ret; -} - -static void -miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - if (DevHasCursor(pDev)) - miDCDeviceCleanup(pDev, pScreen); -} - -/* - * undraw/draw cursor - */ - -static void -miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - miCursorInfoPtr pCursorInfo; - - - if (IsFloating(pDev)) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = GetSpriteScreen(pScreen); - pCursorInfo = MISPRITE(pDev); - - miSpriteIsDown(pCursorInfo); - miSpriteRegisterBlockHandler(pScreen, pScreenPriv); - pCursorInfo->pCacheWin = NullWindow; - miSpriteDisableDamage(pScreen, pScreenPriv); - if (!miDCRestoreUnderCursor(pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1)) - { - miSpriteIsUp(pCursorInfo); - } - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - -/* - * Called from the block handler, saves area under cursor - * before waiting for something to do. - */ - -static void -miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = GetSpriteScreen(pScreen); - pCursorInfo = MISPRITE(pDev); - - miSpriteComputeSaved (pDev, pScreen); - pCursor = pCursorInfo->pCursor; - - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - miSpriteDisableDamage(pScreen, pScreenPriv); - - miDCSaveUnderCursor(pDev, - pScreen, - pCursorInfo->saved.x1, - pCursorInfo->saved.y1, - pCursorInfo->saved.x2 - - pCursorInfo->saved.x1, - pCursorInfo->saved.y2 - - pCursorInfo->saved.y1); - SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - - -/* - * Called from the block handler, restores the cursor - * before waiting for something to do. - */ - -static void -miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miSpriteScreenPtr pScreenPriv; - int x, y; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return; - - DamageDrawInternal (pScreen, TRUE); - pScreenPriv = GetSpriteScreen(pScreen); - pCursorInfo = MISPRITE(pDev); - - miSpriteComputeSaved (pDev, pScreen); - pCursor = pCursorInfo->pCursor; - - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - miSpriteDisableDamage(pScreen, pScreenPriv); - SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); - if (pCursorInfo->checkPixels) - miSpriteFindColors (pCursorInfo, pScreen); - if (miDCPutUpCursor(pDev, pScreen, - pCursor, x, y, - pScreenPriv->colors[SOURCE_COLOR].pixel, - pScreenPriv->colors[MASK_COLOR].pixel)) - { - miSpriteIsUp(pCursorInfo); - pCursorInfo->pScreen = pScreen; - } - miSpriteEnableDamage(pScreen, pScreenPriv); - DamageDrawInternal (pScreen, FALSE); -} - -/* - * compute the desired area of the screen to save - */ - -static void -miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) -{ - int x, y, w, h; - int wpad, hpad; - CursorPtr pCursor; - miCursorInfoPtr pCursorInfo; - - if (IsFloating(pDev)) - return; - - pCursorInfo = MISPRITE(pDev); - - pCursor = pCursorInfo->pCursor; - x = pCursorInfo->x - (int)pCursor->bits->xhot; - y = pCursorInfo->y - (int)pCursor->bits->yhot; - w = pCursor->bits->width; - h = pCursor->bits->height; - wpad = SPRITE_PAD; - hpad = SPRITE_PAD; - pCursorInfo->saved.x1 = x - wpad; - pCursorInfo->saved.y1 = y - hpad; - pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; - pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; -} - +/* + * misprite.c + * + * machine independent software sprite routines + */ + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice 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 NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "pixmapstr.h" +#include "input.h" +#include "mi.h" +#include "cursorstr.h" +#include +#include "scrnintstr.h" +#include "colormapst.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "mipointer.h" +#include "misprite.h" +#include "dixfontstr.h" +#include +#include "inputstr.h" +#include "damage.h" + +typedef struct { + CursorPtr pCursor; + int x; /* cursor hotspot */ + int y; + BoxRec saved; /* saved area from the screen */ + Bool isUp; /* cursor in frame buffer */ + Bool shouldBeUp; /* cursor should be displayed */ + WindowPtr pCacheWin; /* window the cursor last seen in */ + Bool isInCacheWin; + Bool checkPixels; /* check colormap collision */ + ScreenPtr pScreen; +} miCursorInfoRec, *miCursorInfoPtr; + +/* + * per screen information + */ + +typedef struct { + /* screen procedures */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; + + /* window procedures */ + CopyWindowProcPtr CopyWindow; + + /* colormap procedures */ + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + + /* os layer procedures */ + ScreenBlockHandlerProcPtr BlockHandler; + + /* device cursor procedures */ + DeviceCursorInitializeProcPtr DeviceCursorInitialize; + DeviceCursorCleanupProcPtr DeviceCursorCleanup; + + xColorItem colors[2]; + ColormapPtr pInstalledMap; + ColormapPtr pColormap; + VisualPtr pVisual; + DamagePtr pDamage; /* damage tracking structure */ + Bool damageRegistered; + int numberOfCursors; +} miSpriteScreenRec, *miSpriteScreenPtr; + +#define SOURCE_COLOR 0 +#define MASK_COLOR 1 + +/* + * Overlap BoxPtr and Box elements + */ +#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ + (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ + ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) + +/* + * Overlap BoxPtr, origins, and rectangle + */ +#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ + BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) + +/* + * Overlap BoxPtr, origins and RectPtr + */ +#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ + ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ + (int)((pRect)->width), (int)((pRect)->height)) +/* + * Overlap BoxPtr and horizontal span + */ +#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) + +#define LINE_SORT(x1,y1,x2,y2) \ +{ int _t; \ + if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ + if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } + +#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ + BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) + + +#define SPRITE_DEBUG_ENABLE 0 +#if SPRITE_DEBUG_ENABLE +#define SPRITE_DEBUG(x) ErrorF x +#else +#define SPRITE_DEBUG(x) +#endif + +#define MISPRITE(dev) \ + (IsFloating(dev) ? \ + (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ + (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) + +static void +miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (pScreenPriv->damageRegistered) { + DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + pScreenPriv->damageRegistered = 0; + } +} + +static void +miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->damageRegistered) { + pScreenPriv->damageRegistered = 1; + DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + } +} + +static void +miSpriteIsUp(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = TRUE; +} + +static void +miSpriteIsDown(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = FALSE; +} + +/* + * screen wrappers + */ + +static DevPrivateKeyRec miSpriteScreenKeyRec; +#define miSpriteScreenKey (&miSpriteScreenKeyRec) +#define GetSpriteScreen(pScreen) \ + (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey)) +static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; +#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec) + +static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); +static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, + int w, int h, unsigned int format, + unsigned long planemask, char *pdstLine); +static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, + char *pdstStart); +static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, + int width, int height, + unsigned int subWindowMode); +static void miSpriteCopyWindow (WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +static void miSpriteBlockHandler(int i, pointer blockData, + pointer pTimeout, + pointer pReadMask); +static void miSpriteInstallColormap(ColormapPtr pMap); +static void miSpriteStoreColors(ColormapPtr pMap, int ndef, + xColorItem *pdef); + +static void miSpriteComputeSaved(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); + +#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ + (pPriv)->field) +#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ + ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) + +/* + * pointer-sprite method table + */ + +static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y); +static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); + +miPointerSpriteFuncRec miSpritePointerFuncs = { + miSpriteRealizeCursor, + miSpriteUnrealizeCursor, + miSpriteSetCursor, + miSpriteMoveCursor, + miSpriteDeviceCursorInitialize, + miSpriteDeviceCursorCleanup, +}; + +/* + * other misc functions + */ + +static void miSpriteRemoveCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteRestoreCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static void +miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->BlockHandler) { + pScreenPriv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = miSpriteBlockHandler; + } +} + +static void +miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + ScreenPtr pScreen = closure; + miCursorInfoPtr pCursorInfo; + DeviceIntPtr pDev; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG(("Damage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } +} + +/* + * miSpriteInitialize -- called from device-dependent screen + * initialization proc after all of the function pointers have + * been stored in the screen structure. + */ + +Bool +miSpriteInitialize (ScreenPtr pScreen, + miPointerScreenFuncPtr screenFuncs) +{ + miSpriteScreenPtr pScreenPriv; + VisualPtr pVisual; + + if (!DamageSetup (pScreen)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec))) + return FALSE; + + pScreenPriv = malloc(sizeof (miSpriteScreenRec)); + if (!pScreenPriv) + return FALSE; + + pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, + NULL, + DamageReportRawRegion, + TRUE, + pScreen, + pScreen); + + if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) + { + free(pScreenPriv); + return FALSE; + } + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + pScreenPriv->pVisual = pVisual; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreenPriv->SourceValidate = pScreen->SourceValidate; + + pScreenPriv->CopyWindow = pScreen->CopyWindow; + + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreenPriv->StoreColors = pScreen->StoreColors; + + pScreenPriv->BlockHandler = NULL; + + pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; + pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; + + pScreenPriv->pInstalledMap = NULL; + pScreenPriv->pColormap = NULL; + pScreenPriv->colors[SOURCE_COLOR].red = 0; + pScreenPriv->colors[SOURCE_COLOR].green = 0; + pScreenPriv->colors[SOURCE_COLOR].blue = 0; + pScreenPriv->colors[MASK_COLOR].red = 0; + pScreenPriv->colors[MASK_COLOR].green = 0; + pScreenPriv->colors[MASK_COLOR].blue = 0; + pScreenPriv->damageRegistered = 0; + pScreenPriv->numberOfCursors = 0; + + dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); + + pScreen->CloseScreen = miSpriteCloseScreen; + pScreen->GetImage = miSpriteGetImage; + pScreen->GetSpans = miSpriteGetSpans; + pScreen->SourceValidate = miSpriteSourceValidate; + + pScreen->CopyWindow = miSpriteCopyWindow; + pScreen->InstallColormap = miSpriteInstallColormap; + pScreen->StoreColors = miSpriteStoreColors; + + return TRUE; +} + +/* + * Screen wrappers + */ + +/* + * CloseScreen wrapper -- unwrap everything, free the private data + * and call the wrapped function + */ + +static Bool +miSpriteCloseScreen (int i, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->SourceValidate = pScreenPriv->SourceValidate; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + DamageDestroy (pScreenPriv->pDamage); + + free(pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, + char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, + sx, sy, w, h)) + { + SPRITE_DEBUG (("GetImage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + + SCREEN_EPILOGUE (pPriv, pScreen, GetImage); +} + +static void +miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetSpans); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + { + DDXPointPtr pts; + int *widths; + int nPts; + int xorg, + yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, + pts->x+xorg,*widths)) + { + SPRITE_DEBUG (("GetSpans remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + break; + } + } + } + } + } + } + + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + + SCREEN_EPILOGUE (pPriv, pScreen, GetSpans); +} + +static void +miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, + int height, unsigned int subWindowMode) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, + x, y, width, height)) + { + SPRITE_DEBUG (("SourceValidate remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); + + SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate); +} + +static void +miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow); + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + /* + * Damage will take care of destination check + */ + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG (("CopyWindow remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow); +} + +static void +miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + Bool WorkToDo = FALSE; + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp + && pCursorInfo->pScreen == pScreen + && pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler save")); + miSpriteSaveUnderCursor (pDev, pScreen); + } + } + } + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler restore\n")); + miSpriteRestoreCursor (pDev, pScreen); + if (!pCursorInfo->isUp) + WorkToDo = TRUE; + } + } + } + + SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + if (WorkToDo) + SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); + else + pPriv->BlockHandler = NULL; +} + +static void +miSpriteInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); + + (*pScreen->InstallColormap) (pMap); + + SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); + + /* InstallColormap can be called before devices are initialized. */ + pPriv->pInstalledMap = pMap; + if (pPriv->pColormap != pMap) + { + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor(pDev, pScreen); + } + } + + } +} + +static void +miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + int i; + int updated; + VisualPtr pVisual; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + + SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); + + (*pScreen->StoreColors) (pMap, ndef, pdef); + + SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); + + if (pPriv->pColormap == pMap) + { + updated = 0; + pVisual = pMap->pVisual; + if (pVisual->class == DirectColor) + { + /* Direct color - match on any of the subfields */ + +#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) + +#define UpdateDAC(dev, plane,dac,mask) {\ + if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ + dev->colors[plane].dac = pdef[i].dac; \ + updated = 1; \ + } \ +} + +#define CheckDirect(dev, plane) \ + UpdateDAC(dev, plane,red,redMask) \ + UpdateDAC(dev, plane,green,greenMask) \ + UpdateDAC(dev, plane,blue,blueMask) + + for (i = 0; i < ndef; i++) + { + CheckDirect (pPriv, SOURCE_COLOR) + CheckDirect (pPriv, MASK_COLOR) + } + } + else + { + /* PseudoColor/GrayScale - match on exact pixel */ + for (i = 0; i < ndef; i++) + { + if (pdef[i].pixel == + pPriv->colors[SOURCE_COLOR].pixel) + { + pPriv->colors[SOURCE_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + if (pdef[i].pixel == + pPriv->colors[MASK_COLOR].pixel) + { + pPriv->colors[MASK_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + } + } + if (updated) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } +} + +static void +miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + CursorPtr pCursor; + xColorItem *sourceColor, *maskColor; + + pCursor = pDevCursor->pCursor; + sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; + maskColor = &pScreenPriv->colors[MASK_COLOR]; + if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || + !(pCursor->foreRed == sourceColor->red && + pCursor->foreGreen == sourceColor->green && + pCursor->foreBlue == sourceColor->blue && + pCursor->backRed == maskColor->red && + pCursor->backGreen == maskColor->green && + pCursor->backBlue == maskColor->blue)) + { + pScreenPriv->pColormap = pScreenPriv->pInstalledMap; + sourceColor->red = pCursor->foreRed; + sourceColor->green = pCursor->foreGreen; + sourceColor->blue = pCursor->foreBlue; + FakeAllocColor (pScreenPriv->pColormap, sourceColor); + maskColor->red = pCursor->backRed; + maskColor->green = pCursor->backGreen; + maskColor->blue = pCursor->backBlue; + FakeAllocColor (pScreenPriv->pColormap, maskColor); + /* "free" the pixels right away, don't let this confuse you */ + FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); + FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); + } + + pDevCursor->checkPixels = FALSE; + +} + +/* + * miPointer interface routines + */ + +#define SPRITE_PAD 8 + +static Bool +miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return FALSE; + + pCursorInfo = MISPRITE(pDev); + + if (pCursor == pCursorInfo->pCursor) + pCursorInfo->checkPixels = TRUE; + + return miDCRealizeCursor(pScreen, pCursor); +} + +static Bool +miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + return miDCUnrealizeCursor(pScreen, pCursor); +} + +static void +miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y) +{ + miCursorInfoPtr pPointer; + miSpriteScreenPtr pScreenPriv; + + if (IsFloating(pDev)) + return; + + pPointer = MISPRITE(pDev); + pScreenPriv = GetSpriteScreen(pScreen); + + if (!pCursor) + { + if (pPointer->shouldBeUp) + --pScreenPriv->numberOfCursors; + pPointer->shouldBeUp = FALSE; + if (pPointer->isUp) + miSpriteRemoveCursor (pDev, pScreen); + if (pScreenPriv->numberOfCursors == 0) + miSpriteDisableDamage(pScreen, pScreenPriv); + pPointer->pCursor = 0; + return; + } + if (!pPointer->shouldBeUp) + pScreenPriv->numberOfCursors++; + pPointer->shouldBeUp = TRUE; + if (!pPointer->isUp) + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + if (pPointer->x == x && + pPointer->y == y && + pPointer->pCursor == pCursor && + !pPointer->checkPixels) + { + return; + } + pPointer->x = x; + pPointer->y = y; + pPointer->pCacheWin = NullWindow; + if (pPointer->checkPixels || pPointer->pCursor != pCursor) + { + pPointer->pCursor = pCursor; + miSpriteFindColors (pPointer, pScreen); + } + if (pPointer->isUp) { + /* TODO: reimplement flicker-free MoveCursor */ + SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); + miSpriteRemoveCursor (pDev, pScreen); + } + + if (!pPointer->isUp && pPointer->pCursor) + { + SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); + miSpriteSaveUnderCursor(pDev, pScreen); + miSpriteRestoreCursor (pDev, pScreen); + } + +} + +static void +miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + CursorPtr pCursor; + + if (IsFloating(pDev)) + return; + + pCursor = MISPRITE(pDev)->pCursor; + + miSpriteSetCursor (pDev, pScreen, pCursor, x, y); +} + + +static Bool +miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int ret = miDCDeviceInitialize(pDev, pScreen); + + if (ret) + { + miCursorInfoPtr pCursorInfo; + pCursorInfo = dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey); + pCursorInfo->pCursor = NULL; + pCursorInfo->x = 0; + pCursorInfo->y = 0; + pCursorInfo->isUp = FALSE; + pCursorInfo->shouldBeUp = FALSE; + pCursorInfo->pCacheWin = NullWindow; + pCursorInfo->isInCacheWin = FALSE; + pCursorInfo->checkPixels = TRUE; + pCursorInfo->pScreen = FALSE; + } + + return ret; +} + +static void +miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miCursorInfoPtr pCursorInfo = dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey); + + if (DevHasCursor(pDev)) + miDCDeviceCleanup(pDev, pScreen); + + memset(pCursorInfo, 0, sizeof(miCursorInfoRec)); +} + +/* + * undraw/draw cursor + */ + +static void +miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteIsDown(pCursorInfo); + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + pCursorInfo->pCacheWin = NullWindow; + miSpriteDisableDamage(pScreen, pScreenPriv); + if (!miDCRestoreUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1)) + { + miSpriteIsUp(pCursorInfo); + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * Called from the block handler, saves area under cursor + * before waiting for something to do. + */ + +static void +miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + + miDCSaveUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1); + SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + + +/* + * Called from the block handler, restores the cursor + * before waiting for something to do. + */ + +static void +miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); + if (pCursorInfo->checkPixels) + miSpriteFindColors (pCursorInfo, pScreen); + if (miDCPutUpCursor(pDev, pScreen, + pCursor, x, y, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel)) + { + miSpriteIsUp(pCursorInfo); + pCursorInfo->pScreen = pScreen; + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * compute the desired area of the screen to save + */ + +static void +miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int x, y, w, h; + int wpad, hpad; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + pCursorInfo = MISPRITE(pDev); + + pCursor = pCursorInfo->pCursor; + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + w = pCursor->bits->width; + h = pCursor->bits->height; + wpad = SPRITE_PAD; + hpad = SPRITE_PAD; + pCursorInfo->saved.x1 = x - wpad; + pCursorInfo->saved.y1 = y - hpad; + pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; + pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; +} + -- cgit v1.2.3