xserver-multidpi/mi/misprite.c

1191 lines
33 KiB
C
Raw Normal View History

2003-11-14 16:54:54 +01:00
/*
* 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 MPX
/*
* MPX additions:
* Copyright © 2006 Peter Hutterer
* License see above.
* Author: Peter Hutterer <peter@cs.unisa.edu.au>
*
*/
#endif
2003-11-14 16:54:54 +01:00
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# include <X11/X.h>
# include <X11/Xproto.h>
2003-11-14 16:54:54 +01:00
# include "misc.h"
# include "pixmapstr.h"
# include "input.h"
# include "mi.h"
# include "cursorstr.h"
# include <X11/fonts/font.h>
2003-11-14 16:54:54 +01:00
# include "scrnintstr.h"
# include "colormapst.h"
# include "windowstr.h"
# include "gcstruct.h"
# include "mipointer.h"
# include "mispritest.h"
# include "dixfontstr.h"
# include <X11/fonts/fontstruct.h>
2003-11-14 17:49:22 +01:00
#ifdef RENDER
# include "mipict.h"
#endif
# include "damage.h"
#ifdef MPX
# include "inputstr.h" /* for MAX_DEVICES */
static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen);
#endif
#define SPRITE_DEBUG_ENABLE 1
#if SPRITE_DEBUG_ENABLE
#define SPRITE_DEBUG(x) ErrorF x
#else
#define SPRITE_DEBUG(x)
#endif
2003-11-14 16:54:54 +01:00
/*
* screen wrappers
*/
static int miSpriteScreenIndex;
static unsigned long miSpriteGeneration = 0;
2003-11-14 17:49:22 +01:00
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);
static void miSpriteCopyWindow (WindowPtr pWindow,
DDXPointRec ptOldOrg,
RegionPtr prgnSrc);
2003-11-14 17:49:22 +01:00
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 miSpriteSaveDoomedAreas(WindowPtr pWin,
RegionPtr pObscured, int dx,
int dy);
static void miSpriteComputeSaved(miCursorInfoPtr pDevCursor,
ScreenPtr pScreen);
2003-11-14 16:54:54 +01:00
#define SCREEN_PROLOGUE(pScreen, field)\
((pScreen)->field = \
((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
#define SCREEN_EPILOGUE(pScreen, field)\
((pScreen)->field = miSprite##field)
2003-11-14 16:54:54 +01:00
/*
* 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);
2003-11-14 16:54:54 +01:00
_X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
2003-11-14 16:54:54 +01:00
miSpriteRealizeCursor,
miSpriteUnrealizeCursor,
miSpriteSetCursor,
miSpriteMoveCursor,
};
/*
* other misc functions
*/
static void miSpriteRemoveCursor(miCursorInfoPtr pDevCursor,
ScreenPtr pScreen);
static void miSpriteRestoreCursor(miCursorInfoPtr pDevCursor,
ScreenPtr pScreen);
2003-11-14 16:54:54 +01:00
static void
miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
ScreenPtr pScreen = closure;
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
#ifdef MPX
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
if (pMPCursor->isUp &&
RECT_IN_REGION (pScreen, pRegion, &pMPCursor->saved) != rgnOUT)
{
SPRITE_DEBUG(("Damage remove MPX\n"));
miSpriteRemoveCursor(pMPCursor, pScreen);
}
mpCursorIdx++;
}
}
#else
if (pScreenPriv->cp->isUp &&
RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
{
SPRITE_DEBUG(("Damage remove\n"));
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
}
#endif
}
2003-11-14 16:54:54 +01:00
/*
* miSpriteInitialize -- called from device-dependent screen
* initialization proc after all of the function pointers have
* been stored in the screen structure.
*/
Bool
miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
ScreenPtr pScreen;
miSpriteCursorFuncPtr cursorFuncs;
miPointerScreenFuncPtr screenFuncs;
{
#ifdef MPX
int mpCursorIdx = 0;
#endif
miSpriteScreenPtr pScreenPriv;
2003-11-14 16:54:54 +01:00
VisualPtr pVisual;
if (!DamageSetup (pScreen))
return FALSE;
2003-11-14 16:54:54 +01:00
if (miSpriteGeneration != serverGeneration)
{
miSpriteScreenIndex = AllocateScreenPrivateIndex ();
if (miSpriteScreenIndex < 0)
return FALSE;
miSpriteGeneration = serverGeneration;
}
pScreenPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec));
if (!pScreenPriv)
2003-11-14 16:54:54 +01:00
return FALSE;
pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
(DamageDestroyFunc) 0,
DamageReportRawRegion,
TRUE,
pScreen,
(void *) pScreen);
2003-11-14 16:54:54 +01:00
if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
{
xfree ((pointer) pScreenPriv);
2003-11-14 16:54:54 +01:00
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->SaveDoomedAreas = pScreen->SaveDoomedAreas;
pScreenPriv->InstallColormap = pScreen->InstallColormap;
pScreenPriv->StoreColors = pScreen->StoreColors;
pScreenPriv->BlockHandler = pScreen->BlockHandler;
pScreenPriv->cp = (miCursorInfoPtr)xalloc(sizeof(miCursorInfoRec));
pScreenPriv->cp->pCursor = NULL;
pScreenPriv->cp->x = 0;
pScreenPriv->cp->y = 0;
pScreenPriv->cp->isUp = FALSE;
pScreenPriv->cp->shouldBeUp = FALSE;
pScreenPriv->cp->pCacheWin = NullWindow;
pScreenPriv->cp->isInCacheWin = FALSE;
pScreenPriv->cp->checkPixels = TRUE;
pScreenPriv->cp->pInstalledMap = NULL;
pScreenPriv->cp->pColormap = NULL;
pScreenPriv->cp->colors[SOURCE_COLOR].red = 0;
pScreenPriv->cp->colors[SOURCE_COLOR].green = 0;
pScreenPriv->cp->colors[SOURCE_COLOR].blue = 0;
pScreenPriv->cp->colors[MASK_COLOR].red = 0;
pScreenPriv->cp->colors[MASK_COLOR].green = 0;
pScreenPriv->cp->colors[MASK_COLOR].blue = 0;
pScreenPriv->funcs = cursorFuncs;
pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
pScreen->CloseScreen = miSpriteCloseScreen;
pScreen->GetImage = miSpriteGetImage;
pScreen->GetSpans = miSpriteGetSpans;
pScreen->SourceValidate = miSpriteSourceValidate;
2003-11-14 16:54:54 +01:00
pScreen->CopyWindow = miSpriteCopyWindow;
2003-11-14 16:54:54 +01:00
pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
pScreen->InstallColormap = miSpriteInstallColormap;
pScreen->StoreColors = miSpriteStoreColors;
2003-11-14 16:54:54 +01:00
pScreen->BlockHandler = miSpriteBlockHandler;
#ifdef MPX
/* alloc and zero memory for all MPX cursors */
pScreenPriv->mpCursors = (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr cursor = &(pScreenPriv->mpCursors[mpCursorIdx]);
cursor->id = mpCursorIdx;
cursor->pCursor = NULL;
cursor->x = 0;
cursor->y = 0;
cursor->isUp = FALSE;
cursor->shouldBeUp = FALSE;
cursor->pCacheWin = NullWindow;
cursor->isInCacheWin = FALSE;
cursor->checkPixels = TRUE;
cursor->pInstalledMap = NULL;
cursor->pColormap = NULL;
cursor->colors[SOURCE_COLOR].red = 0;
cursor->colors[SOURCE_COLOR].green = 0;
cursor->colors[SOURCE_COLOR].blue = 0;
cursor->colors[MASK_COLOR].red = 0;
cursor->colors[MASK_COLOR].green = 0;
cursor->colors[MASK_COLOR].blue = 0;
mpCursorIdx++;
}
/* virtual core pointer has id 1, we might as well save the memory */
xfree(pScreenPriv->cp);
pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
#endif
damageRegister = 0;
2003-11-14 16:54:54 +01:00
return TRUE;
}
/*
* Screen wrappers
*/
/*
* CloseScreen wrapper -- unwrap everything, free the private data
* and call the wrapped function
*/
static Bool
miSpriteCloseScreen (i, pScreen)
2003-11-14 17:49:22 +01:00
int i;
2003-11-14 16:54:54 +01:00
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
pScreen->GetImage = pScreenPriv->GetImage;
pScreen->GetSpans = pScreenPriv->GetSpans;
pScreen->SourceValidate = pScreenPriv->SourceValidate;
pScreen->BlockHandler = pScreenPriv->BlockHandler;
pScreen->InstallColormap = pScreenPriv->InstallColormap;
pScreen->StoreColors = pScreenPriv->StoreColors;
pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
miSpriteIsUpFALSE (pScreenPriv->cp, pScreen, pScreenPriv);
DamageDestroy (pScreenPriv->pDamage);
#ifdef MPX
xfree((pointer)(pScreenPriv->mpCursors));
#endif
2003-11-14 16:54:54 +01:00
xfree ((pointer) pScreenPriv);
return (*pScreen->CloseScreen) (i, pScreen);
}
static void
miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
DrawablePtr pDrawable;
int sx, sy, w, h;
unsigned int format;
unsigned long planemask;
char *pdstLine;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, GetImage);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW &&
pScreenPriv->cp->isUp &&
ORG_OVERLAP(&pScreenPriv->cp->saved,pDrawable->x,pDrawable->y,
sx, sy, w, h))
2003-11-14 16:54:54 +01:00
{
SPRITE_DEBUG (("GetImage remove\n"));
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
2003-11-14 16:54:54 +01:00
}
#ifdef MPX
/* check for MPX cursors in the target region */
if (pDrawable->type == DRAWABLE_WINDOW)
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
if (pMPCursor->isUp &&
ORG_OVERLAP(&pMPCursor->saved,pDrawable->x,pDrawable->y,
sx, sy, w, h))
{
SPRITE_DEBUG(("GetImage remove MPX\n"));
}
miSpriteRemoveCursor(pMPCursor, pScreen);
mpCursorIdx++;
}
}
#endif
2003-11-14 16:54:54 +01:00
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
format, planemask, pdstLine);
SCREEN_EPILOGUE (pScreen, GetImage);
2003-11-14 16:54:54 +01:00
}
static void
miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
DrawablePtr pDrawable;
int wMax;
DDXPointPtr ppt;
int *pwidth;
int nspans;
char *pdstStart;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, GetSpans);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp)
2003-11-14 16:54:54 +01:00
{
register DDXPointPtr pts;
register int *widths;
register int nPts;
register int xorg,
yorg;
xorg = pDrawable->x;
yorg = pDrawable->y;
for (pts = ppt, widths = pwidth, nPts = nspans;
nPts--;
pts++, widths++)
{
if (SPN_OVERLAP(&pScreenPriv->cp->saved,pts->y+yorg,
2003-11-14 16:54:54 +01:00
pts->x+xorg,*widths))
{
SPRITE_DEBUG (("GetSpans remove\n"));
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
2003-11-14 16:54:54 +01:00
break;
}
}
}
#ifdef MPX
if (pDrawable->type == DRAWABLE_WINDOW)
{
int mpCursorIdx = 0;
while(mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
register DDXPointPtr pts;
register int *widths;
register int nPts;
register int xorg,
yorg;
xorg = pDrawable->x;
yorg = pDrawable->y;
for (pts = ppt, widths = pwidth, nPts = nspans;
nPts--;
pts++, widths++)
{
if (SPN_OVERLAP(&pMPCursor->saved,pts->y+yorg,
pts->x+xorg,*widths))
{
SPRITE_DEBUG (("GetSpans remove\n"));
miSpriteRemoveCursor (pMPCursor, pScreen);
break;
}
}
mpCursorIdx++;
}
}
#endif
2003-11-14 16:54:54 +01:00
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
SCREEN_EPILOGUE (pScreen, GetSpans);
2003-11-14 16:54:54 +01:00
}
static void
miSpriteSourceValidate (pDrawable, x, y, width, height)
DrawablePtr pDrawable;
int x, y, width, height;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, SourceValidate);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp &&
ORG_OVERLAP(&pScreenPriv->cp->saved, pDrawable->x, pDrawable->y,
2003-11-14 16:54:54 +01:00
x, y, width, height))
{
SPRITE_DEBUG (("SourceValidate remove\n"));
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
}
#ifdef MPX
if (pDrawable->type == DRAWABLE_WINDOW)
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
if (pMPCursor->isUp && ORG_OVERLAP(&pMPCursor->saved,
pDrawable->x, pDrawable->y, x, y, width, height))
{
SPRITE_DEBUG(("SourceValidate remove MPX\n"));
miSpriteRemoveCursor(pMPCursor, pScreen);
}
mpCursorIdx++;
}
2003-11-14 16:54:54 +01:00
}
#endif
2003-11-14 16:54:54 +01:00
if (pScreen->SourceValidate)
(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
SCREEN_EPILOGUE (pScreen, SourceValidate);
2003-11-14 16:54:54 +01:00
}
static void
miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
2003-11-14 16:54:54 +01:00
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
miSpriteScreenPtr pScreenPriv;
2003-11-14 16:54:54 +01:00
SCREEN_PROLOGUE (pScreen, CopyWindow);
2003-11-14 16:54:54 +01:00
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
/*
* Damage will take care of destination check
*/
if (pScreenPriv->cp->isUp &&
RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->cp->saved) != rgnOUT)
{
SPRITE_DEBUG (("CopyWindow remove\n"));
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
}
#ifdef MPX
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
if (pMPCursor->isUp && RECT_IN_REGION (pScreen, prgnSrc,
&pMPCursor->saved) != rgnOUT)
{
SPRITE_DEBUG(("CopyWindow remove MPX\n"));
miSpriteRemoveCursor(pMPCursor, pScreen);
}
mpCursorIdx++;
}
}
#endif
2003-11-14 16:54:54 +01:00
(*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
SCREEN_EPILOGUE (pScreen, CopyWindow);
2003-11-14 16:54:54 +01:00
}
static void
miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
int i;
pointer blockData;
2003-11-14 17:49:22 +01:00
pointer pTimeout;
2003-11-14 16:54:54 +01:00
pointer pReadmask;
{
ScreenPtr pScreen = screenInfo.screens[i];
miSpriteScreenPtr pPriv;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, BlockHandler);
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
SCREEN_EPILOGUE(pScreen, BlockHandler);
2003-11-14 16:54:54 +01:00
#ifdef MPX
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
if (!pMPCursor->isUp && pMPCursor->shouldBeUp)
{
SPRITE_DEBUG (("BlockHandler restore MPX\n"));
miSpriteRestoreCursor (pMPCursor, pScreen);
}
mpCursorIdx++;
}
}
#else
if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
{
SPRITE_DEBUG (("BlockHandler restore\n"));
miSpriteRestoreCursor (pPriv->cp, pScreen);
}
#endif
2003-11-14 16:54:54 +01:00
}
static void
miSpriteInstallColormap (pMap)
ColormapPtr pMap;
{
ScreenPtr pScreen = pMap->pScreen;
miSpriteScreenPtr pPriv;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, InstallColormap);
(*pScreen->InstallColormap) (pMap);
SCREEN_EPILOGUE(pScreen, InstallColormap);
2003-11-14 16:54:54 +01:00
#ifdef MPX
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
pMPCursor->pInstalledMap = pMap;
if (pMPCursor->pColormap != pMap)
{
pMPCursor->checkPixels = TRUE;
if (pMPCursor->isUp)
miSpriteRemoveCursor(pMPCursor, pScreen);
}
mpCursorIdx++;
}
}
#else
pPriv->cp->pInstalledMap = pMap;
if (pPriv->cp->pColormap != pMap)
{
pPriv->cp->checkPixels = TRUE;
if (pPriv->cp->isUp)
miSpriteRemoveCursor (pPriv->cp, pScreen);
}
#endif
2003-11-14 16:54:54 +01:00
}
static void
miSpriteStoreColors (pMap, ndef, pdef)
ColormapPtr pMap;
int ndef;
xColorItem *pdef;
{
ScreenPtr pScreen = pMap->pScreen;
miSpriteScreenPtr pPriv;
int i;
int updated;
VisualPtr pVisual;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, StoreColors);
(*pScreen->StoreColors) (pMap, ndef, pdef);
SCREEN_EPILOGUE(pScreen, StoreColors);
2003-11-14 16:54:54 +01:00
2003-11-14 17:49:22 +01:00
#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
2003-11-14 16:54:54 +01:00
#define UpdateDAC(dev, plane,dac,mask) {\
if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
dev->colors[plane].dac = pdef[i].dac; \
2003-11-14 16:54:54 +01:00
updated = 1; \
} \
}
#define CheckDirect(dev, plane) \
UpdateDAC(dev, plane,red,redMask) \
UpdateDAC(dev, plane,green,greenMask) \
UpdateDAC(dev, plane,blue,blueMask)
2003-11-14 16:54:54 +01:00
#ifdef MPX
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
if (pPriv->cp->pColormap == pMap)
{
updated = 0;
pVisual = pMap->pVisual;
if (pVisual->class == DirectColor)
{
for (i = 0; i < ndef; i++)
{
CheckDirect (pMPCursor, SOURCE_COLOR)
CheckDirect (pMPCursor, MASK_COLOR)
}
}
else
{
/* PseudoColor/GrayScale - match on exact pixel */
for (i = 0; i < ndef; i++)
{
if (pdef[i].pixel ==
pMPCursor->colors[SOURCE_COLOR].pixel)
{
pMPCursor->colors[SOURCE_COLOR] = pdef[i];
if (++updated == 2)
break;
}
if (pdef[i].pixel ==
pMPCursor->colors[MASK_COLOR].pixel)
{
pMPCursor->colors[MASK_COLOR] = pdef[i];
if (++updated == 2)
break;
}
}
}
if (updated)
{
pMPCursor->checkPixels = TRUE;
if (pMPCursor->isUp)
miSpriteRemoveCursor (pMPCursor, pScreen);
}
}
mpCursorIdx++;
}
}
#else
if (pPriv->cp->pColormap == pMap)
{
updated = 0;
pVisual = pMap->pVisual;
if (pVisual->class == DirectColor)
{
/* Direct color - match on any of the subfields */
for (i = 0; i < ndef; i++)
{
CheckDirect (pPriv->cp, SOURCE_COLOR)
CheckDirect (pPriv->cp, MASK_COLOR)
}
}
else
{
/* PseudoColor/GrayScale - match on exact pixel */
for (i = 0; i < ndef; i++)
{
if (pdef[i].pixel == pPriv->cp->colors[SOURCE_COLOR].pixel)
{
pPriv->cp->colors[SOURCE_COLOR] = pdef[i];
if (++updated == 2)
break;
}
if (pdef[i].pixel == pPriv->cp->colors[MASK_COLOR].pixel)
{
pPriv->cp->colors[MASK_COLOR] = pdef[i];
if (++updated == 2)
break;
}
}
}
if (updated)
{
pPriv->cp->checkPixels = TRUE;
if (pPriv->cp->isUp)
miSpriteRemoveCursor (pPriv->cp, pScreen);
}
}
#endif
2003-11-14 16:54:54 +01:00
}
static void
miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
2003-11-14 16:54:54 +01:00
{
CursorPtr pCursor;
xColorItem *sourceColor, *maskColor;
pCursor = pDevCursor->pCursor;
sourceColor = &pDevCursor->colors[SOURCE_COLOR];
maskColor = &pDevCursor->colors[MASK_COLOR];
if (pDevCursor->pColormap != pDevCursor->pInstalledMap ||
2003-11-14 16:54:54 +01:00
!(pCursor->foreRed == sourceColor->red &&
pCursor->foreGreen == sourceColor->green &&
pCursor->foreBlue == sourceColor->blue &&
pCursor->backRed == maskColor->red &&
pCursor->backGreen == maskColor->green &&
pCursor->backBlue == maskColor->blue))
{
pDevCursor->pColormap = pDevCursor->pInstalledMap;
2003-11-14 16:54:54 +01:00
sourceColor->red = pCursor->foreRed;
sourceColor->green = pCursor->foreGreen;
sourceColor->blue = pCursor->foreBlue;
FakeAllocColor (pDevCursor->pColormap, sourceColor);
2003-11-14 16:54:54 +01:00
maskColor->red = pCursor->backRed;
maskColor->green = pCursor->backGreen;
maskColor->blue = pCursor->backBlue;
FakeAllocColor (pDevCursor->pColormap, maskColor);
2003-11-14 16:54:54 +01:00
/* "free" the pixels right away, don't let this confuse you */
FakeFreeColor(pDevCursor->pColormap, sourceColor->pixel);
FakeFreeColor(pDevCursor->pColormap, maskColor->pixel);
2003-11-14 16:54:54 +01:00
}
pDevCursor->checkPixels = FALSE;
2003-11-14 16:54:54 +01:00
}
/*
* BackingStore wrappers
*/
static void
miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
WindowPtr pWin;
RegionPtr pObscured;
int dx, dy;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
BoxRec cursorBox;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
#ifdef MPX
{
int mpCursorIdx = 0;
while (mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
if (pMPCursor->isUp)
{
cursorBox = pMPCursor->saved;
if (dx || dy)
{
cursorBox.x1 += dx;
cursorBox.y1 += dy;
cursorBox.x2 += dx;
cursorBox.y2 += dy;
}
if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
miSpriteRemoveCursor (pMPCursor, pScreen);
}
mpCursorIdx++;
}
2003-11-14 16:54:54 +01:00
}
#else
if (pScreenPriv->cp->isUp)
{
cursorBox = pScreenPriv->cp->saved;
if (dx || dy)
{
cursorBox.x1 += dx;
cursorBox.y1 += dy;
cursorBox.x2 += dx;
cursorBox.y2 += dy;
}
if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
}
#endif
2003-11-14 16:54:54 +01:00
(*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
SCREEN_EPILOGUE (pScreen, SaveDoomedAreas);
2003-11-14 16:54:54 +01:00
}
/*
* miPointer interface routines
2003-11-14 16:54:54 +01:00
*/
#define SPRITE_PAD 8
2003-11-14 16:54:54 +01:00
static Bool
miSpriteRealizeCursor (pDev, pScreen, pCursor)
DeviceIntPtr pDev;
ScreenPtr pScreen;
CursorPtr pCursor;
2003-11-14 16:54:54 +01:00
{
miSpriteScreenPtr pScreenPriv;
2003-11-14 16:54:54 +01:00
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
#ifdef MPX
{
miCursorInfoPtr pMPCursor = DevToSprite(pDev, pScreen);
if (pCursor == pMPCursor->pCursor)
pMPCursor->checkPixels = TRUE;
}
#else
if (pCursor == pScreenPriv->cp->pCursor)
pScreenPriv->cp->checkPixels = TRUE;
#endif
return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
2003-11-14 16:54:54 +01:00
}
static Bool
miSpriteUnrealizeCursor (pDev, pScreen, pCursor)
DeviceIntPtr pDev;
ScreenPtr pScreen;
CursorPtr pCursor;
2003-11-14 16:54:54 +01:00
{
miSpriteScreenPtr pScreenPriv;
2003-11-14 16:54:54 +01:00
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
2003-11-14 16:54:54 +01:00
}
static void
miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
DeviceIntPtr pDev;
ScreenPtr pScreen;
CursorPtr pCursor;
int x;
int y;
2003-11-14 16:54:54 +01:00
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
miCursorInfoPtr pPointer = pScreenPriv->cp;
#ifdef MPX
if (IsMPDev(pDev))
pPointer = &pScreenPriv->mpCursors[pDev->id];
#endif
if (!pCursor)
2003-11-14 16:54:54 +01:00
{
pPointer->shouldBeUp = FALSE;
if (pPointer->isUp)
miSpriteRemoveCursor (pPointer, pScreen);
pPointer->pCursor = 0;
return;
2003-11-14 16:54:54 +01:00
}
pPointer->shouldBeUp = TRUE;
if (pPointer->x == x &&
pPointer->y == y &&
pPointer->pCursor == pCursor &&
!pPointer->checkPixels)
2003-11-14 16:54:54 +01:00
{
return;
2003-11-14 16:54:54 +01:00
}
pPointer->x = x;
pPointer->y = y;
pPointer->pCacheWin = NullWindow;
if (pPointer->checkPixels || pPointer->pCursor != pCursor)
{
pPointer->pCursor = pCursor;
miSpriteFindColors (pPointer, pScreen);
}
if (pPointer->isUp) {
#if 0
/* FIXME: Disabled for MPX, should be rewritten */
int sx, sy;
/*
* check to see if the old saved region
* encloses the new sprite, in which case we use
* the flicker-free MoveCursor primitive.
*/
sx = pointer->x - (int)pCursor->bits->xhot;
sy = pointer->y - (int)pCursor->bits->yhot;
if (sx + (int) pCursor->bits->width >= pointer->saved.x1 &&
sx < pointer->saved.x2 &&
sy + (int) pCursor->bits->height >= pointer->saved.y1 &&
sy < pointer->saved.y2 &&
(int) pCursor->bits->width + (2 * SPRITE_PAD) ==
pointer->saved.x2 - pointer->saved.x1 &&
(int) pCursor->bits->height + (2 * SPRITE_PAD) ==
pointer->saved.y2 - pointer->saved.y1
)
{
DamageDrawInternal (pScreen, TRUE);
miSpriteIsUpFALSE (pScreen, pScreenPriv);
if (!(sx >= pointer->saved.x1 &&
sx + (int)pCursor->bits->width < pointer->saved.x2
&& sy >= pointer->saved.y1 &&
sy + (int)pCursor->bits->height <
pointer->saved.y2))
{
int oldx1, oldy1, dx, dy;
2003-11-14 16:54:54 +01:00
oldx1 = pointer->saved.x1;
oldy1 = pointer->saved.y1;
2003-11-14 16:54:54 +01:00
dx = oldx1 - (sx - SPRITE_PAD);
dy = oldy1 - (sy - SPRITE_PAD);
pointer->saved.x1 -= dx;
pointer->saved.y1 -= dy;
pointer->saved.x2 -= dx;
pointer->saved.y2 -= dy;
2003-11-14 16:54:54 +01:00
(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
pointer->saved.x1,
pointer->saved.y1,
pointer->saved.x2 -
pointer->saved.x1,
pointer->saved.y2 -
pointer->saved.y1,
2003-11-14 16:54:54 +01:00
dx, dy);
}
(void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
pointer->saved.x1,
pointer->saved.y1,
pointer->saved.x2 -
pointer->saved.x1,
pointer->saved.y2 -
pointer->saved.y1,
sx - pointer->saved.x1,
sy - pointer->saved.y1,
pointer->colors[SOURCE_COLOR].pixel,
pointer->colors[MASK_COLOR].pixel);
miSpriteIsUpTRUE (pScreen, pScreenPriv);
DamageDrawInternal (pScreen, FALSE);
2003-11-14 16:54:54 +01:00
}
else
#endif
2003-11-14 16:54:54 +01:00
{
SPRITE_DEBUG (("SetCursor remove\n"));
miSpriteRemoveCursor (pPointer, pScreen);
2003-11-14 16:54:54 +01:00
}
}
if (!pPointer->isUp && pPointer->pCursor)
{
SPRITE_DEBUG (("SetCursor restore\n"));
miSpriteRestoreCursor (pPointer, pScreen);
}
2003-11-14 16:54:54 +01:00
}
static void
miSpriteMoveCursor (pDev, pScreen, x, y)
DeviceIntPtr pDev;
2003-11-14 16:54:54 +01:00
ScreenPtr pScreen;
int x, y;
{
miSpriteScreenPtr pScreenPriv;
CursorPtr pCursor;
2003-11-14 16:54:54 +01:00
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pScreenPriv->cp->pCursor;
#ifdef MPX
if (IsMPDev(pDev))
pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
#endif
miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
2003-11-14 16:54:54 +01:00
}
/*
* undraw/draw cursor
*/
static void
miSpriteRemoveCursor (pDevCursor, pScreen)
miCursorInfoPtr pDevCursor;
2003-11-14 16:54:54 +01:00
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
DamageDrawInternal (pScreen, TRUE);
2003-11-14 16:54:54 +01:00
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
miSpriteIsUpFALSE (pDevCursor, pScreen, pScreenPriv);
pDevCursor->pCacheWin = NullWindow;
if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDevCursor->id,
pScreen,
pDevCursor->saved.x1,
pDevCursor->saved.y1,
pDevCursor->saved.x2 -
pDevCursor->saved.x1,
pDevCursor->saved.y2 -
pDevCursor->saved.y1))
2003-11-14 16:54:54 +01:00
{
miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
2003-11-14 16:54:54 +01:00
}
DamageDrawInternal (pScreen, FALSE);
2003-11-14 16:54:54 +01:00
}
/*
* Called from the block handler, restores the cursor
* before waiting for something to do.
*/
static void
miSpriteRestoreCursor (pDevCursor, pScreen)
miCursorInfoPtr pDevCursor;
2003-11-14 16:54:54 +01:00
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
int x, y;
CursorPtr pCursor;
DamageDrawInternal (pScreen, TRUE);
miSpriteComputeSaved (pDevCursor, pScreen);
2003-11-14 16:54:54 +01:00
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pDevCursor->pCursor;
x = pDevCursor->x - (int)pCursor->bits->xhot;
y = pDevCursor->y - (int)pCursor->bits->yhot;
if ((*pScreenPriv->funcs->SaveUnderCursor) (pDevCursor->id,
pScreen,
pDevCursor->saved.x1,
pDevCursor->saved.y1,
pDevCursor->saved.x2 -
pDevCursor->saved.x1,
pDevCursor->saved.y2 -
pDevCursor->saved.y1))
2003-11-14 16:54:54 +01:00
{
if (pDevCursor->checkPixels)
miSpriteFindColors (pDevCursor, pScreen);
if ((*pScreenPriv->funcs->PutUpCursor) (pDevCursor->id, pScreen,
pCursor, x, y,
pDevCursor->colors[SOURCE_COLOR].pixel,
pDevCursor->colors[MASK_COLOR].pixel))
{
miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
}
2003-11-14 16:54:54 +01:00
}
DamageDrawInternal (pScreen, FALSE);
2003-11-14 16:54:54 +01:00
}
/*
* compute the desired area of the screen to save
*/
static void
miSpriteComputeSaved (pDevCursor, pScreen)
miCursorInfoPtr pDevCursor;
2003-11-14 16:54:54 +01:00
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
int x, y, w, h;
int wpad, hpad;
CursorPtr pCursor;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pDevCursor->pCursor;
x = pDevCursor->x - (int)pCursor->bits->xhot;
y = pDevCursor->y - (int)pCursor->bits->yhot;
2003-11-14 16:54:54 +01:00
w = pCursor->bits->width;
h = pCursor->bits->height;
wpad = SPRITE_PAD;
hpad = SPRITE_PAD;
pDevCursor->saved.x1 = x - wpad;
pDevCursor->saved.y1 = y - hpad;
pDevCursor->saved.x2 = pDevCursor->saved.x1 + w + wpad * 2;
pDevCursor->saved.y2 = pDevCursor->saved.y1 + h + hpad * 2;
2003-11-14 16:54:54 +01:00
}
#ifdef MPX
static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen)
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
int mpCursorIdx = 0;
while(mpCursorIdx < MAX_DEVICES)
{
miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
if (pMPCursor->id == pDev->id)
return pMPCursor;
mpCursorIdx++;
}
return pScreenPriv->cp;
}
#endif