mi: Don't save midispcur rendering resources for each cursor

Instead, only save them for the most recently drawn cursor. This saves
a bunch of storage for idle cursors.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Keith Packard 2012-07-05 11:15:18 -07:00
parent 7651176b00
commit f38b2b6283

View File

@ -56,9 +56,7 @@ in this Software without prior written authorization from The Open Group.
static DevPrivateKeyRec miDCScreenKeyRec; static DevPrivateKeyRec miDCScreenKeyRec;
#define miDCScreenKey (&miDCScreenKeyRec) #define miDCScreenKey (&miDCScreenKeyRec)
static DevScreenPrivateKeyRec miDCCursorBitsKeyRec;
#define miDCCursorBitsKey (&miDCCursorBitsKeyRec)
static DevScreenPrivateKeyRec miDCDeviceKeyRec; static DevScreenPrivateKeyRec miDCDeviceKeyRec;
#define miDCDeviceKey (&miDCDeviceKeyRec) #define miDCDeviceKey (&miDCDeviceKeyRec)
@ -86,18 +84,15 @@ typedef struct {
*/ */
typedef struct { typedef struct {
CloseScreenProcPtr CloseScreen; CloseScreenProcPtr CloseScreen;
} miDCScreenRec, *miDCScreenPtr;
#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
/* per-cursor per-screen private data */
typedef struct {
PixmapPtr sourceBits; /* source bits */ PixmapPtr sourceBits; /* source bits */
PixmapPtr maskBits; /* mask bits */ PixmapPtr maskBits; /* mask bits */
#ifdef ARGB_CURSOR #ifdef ARGB_CURSOR
PicturePtr pPicture; PicturePtr pPicture;
#endif #endif
} miDCCursorRec, *miDCCursorPtr; CursorPtr pCursor;
} miDCScreenRec, *miDCScreenPtr;
#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
Bool Bool
miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
@ -105,13 +100,11 @@ miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
miDCScreenPtr pScreenPriv; miDCScreenPtr pScreenPriv;
if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) || if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) ||
!dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen,
PRIVATE_CURSOR_BITS, 0) ||
!dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE,
0)) 0))
return FALSE; return FALSE;
pScreenPriv = malloc(sizeof(miDCScreenRec)); pScreenPriv = calloc(1, sizeof(miDCScreenRec));
if (!pScreenPriv) if (!pScreenPriv)
return FALSE; return FALSE;
@ -127,6 +120,28 @@ miDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
return TRUE; return TRUE;
} }
static void
miDCSwitchScreenCursor(ScreenPtr pScreen, CursorPtr pCursor, PixmapPtr sourceBits, PixmapPtr maskBits, PicturePtr pPicture)
{
miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
if (pScreenPriv->sourceBits)
(*pScreen->DestroyPixmap)(pScreenPriv->sourceBits);
pScreenPriv->sourceBits = sourceBits;
if (pScreenPriv->maskBits)
(*pScreen->DestroyPixmap)(pScreenPriv->maskBits);
pScreenPriv->maskBits = maskBits;
#ifdef ARGB_CURSOR
if (pScreenPriv->pPicture)
FreePicture(pScreenPriv->pPicture, 0);
pScreenPriv->pPicture = pPicture;
#endif
pScreenPriv->pCursor = pCursor;
}
static Bool static Bool
miDCCloseScreen(ScreenPtr pScreen) miDCCloseScreen(ScreenPtr pScreen)
{ {
@ -135,6 +150,8 @@ miDCCloseScreen(ScreenPtr pScreen)
pScreenPriv = (miDCScreenPtr) dixLookupPrivate(&pScreen->devPrivates, pScreenPriv = (miDCScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
miDCScreenKey); miDCScreenKey);
pScreen->CloseScreen = pScreenPriv->CloseScreen; pScreen->CloseScreen = pScreenPriv->CloseScreen;
miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL);
free((pointer) pScreenPriv); free((pointer) pScreenPriv);
return (*pScreen->CloseScreen) (pScreen); return (*pScreen->CloseScreen) (pScreen);
} }
@ -142,9 +159,6 @@ miDCCloseScreen(ScreenPtr pScreen)
Bool Bool
miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
{ {
if (pCursor->bits->refcnt <= 1)
dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey,
pScreen, NULL);
return TRUE; return TRUE;
} }
@ -154,8 +168,6 @@ miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
static PicturePtr static PicturePtr
miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin) miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin)
{ {
ScreenPtr pScreen = pDraw->pScreen;
VisualPtr pVisual;
PictFormatPtr pFormat; PictFormatPtr pFormat;
XID subwindow_mode = IncludeInferiors; XID subwindow_mode = IncludeInferiors;
PicturePtr pPicture; PicturePtr pPicture;
@ -172,42 +184,39 @@ miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin)
} }
#endif #endif
static miDCCursorPtr static Bool
miDCRealize(ScreenPtr pScreen, CursorPtr pCursor) miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
{ {
miDCCursorPtr pPriv; miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
GCPtr pGC; GCPtr pGC;
ChangeGCVal gcvals; ChangeGCVal gcvals;
PixmapPtr sourceBits, maskBits;
if (pScreenPriv->pCursor == pCursor)
return TRUE;
pPriv = malloc(sizeof(miDCCursorRec));
if (!pPriv)
return NULL;
#ifdef ARGB_CURSOR #ifdef ARGB_CURSOR
if (pCursor->bits->argb) { if (pCursor->bits->argb) {
PixmapPtr pPixmap; PixmapPtr pPixmap;
PictFormatPtr pFormat; PictFormatPtr pFormat;
int error; int error;
PicturePtr pPicture;
pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8); pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
if (!pFormat) { if (!pFormat)
free((pointer) pPriv); return FALSE;
return NULL;
}
pPriv->sourceBits = 0;
pPriv->maskBits = 0;
pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
pCursor->bits->height, 32, pCursor->bits->height, 32,
CREATE_PIXMAP_USAGE_SCRATCH); CREATE_PIXMAP_USAGE_SCRATCH);
if (!pPixmap) { if (!pPixmap)
free((pointer) pPriv); return FALSE;
return NULL;
}
pGC = GetScratchGC(32, pScreen); pGC = GetScratchGC(32, pScreen);
if (!pGC) { if (!pGC) {
(*pScreen->DestroyPixmap) (pPixmap); (*pScreen->DestroyPixmap) (pPixmap);
free((pointer) pPriv); return FALSE;
return NULL;
} }
ValidateGC(&pPixmap->drawable, pGC); ValidateGC(&pPixmap->drawable, pGC);
(*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
@ -215,105 +224,86 @@ miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
pCursor->bits->height, pCursor->bits->height,
0, ZPixmap, (char *) pCursor->bits->argb); 0, ZPixmap, (char *) pCursor->bits->argb);
FreeScratchGC(pGC); FreeScratchGC(pGC);
pPriv->pPicture = CreatePicture(0, &pPixmap->drawable, pPicture = CreatePicture(0, &pPixmap->drawable,
pFormat, 0, 0, serverClient, &error); pFormat, 0, 0, serverClient, &error);
(*pScreen->DestroyPixmap) (pPixmap); (*pScreen->DestroyPixmap) (pPixmap);
if (!pPriv->pPicture) { if (!pPicture)
free((pointer) pPriv); return FALSE;
return NULL;
} miDCSwitchScreenCursor(pScreen, pCursor, NULL, NULL, pPicture);
dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, return TRUE;
pScreen, pPriv);
return pPriv;
} }
pPriv->pPicture = 0;
#endif #endif
pPriv->sourceBits = sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
(*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
pCursor->bits->height, 1, 0); if (!sourceBits)
if (!pPriv->sourceBits) { return FALSE;
free((pointer) pPriv);
return NULL; maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
pCursor->bits->height, 1, 0);
if (!maskBits) {
(*pScreen->DestroyPixmap) (sourceBits);
return FALSE;
} }
pPriv->maskBits =
(*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
pCursor->bits->height, 1, 0);
if (!pPriv->maskBits) {
(*pScreen->DestroyPixmap) (pPriv->sourceBits);
free((pointer) pPriv);
return NULL;
}
dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen,
pPriv);
/* create the two sets of bits, clipping as appropriate */ /* create the two sets of bits, clipping as appropriate */
pGC = GetScratchGC(1, pScreen); pGC = GetScratchGC(1, pScreen);
if (!pGC) { if (!pGC) {
(void) miDCUnrealizeCursor(pScreen, pCursor); (*pScreen->DestroyPixmap) (sourceBits);
return NULL; (*pScreen->DestroyPixmap) (maskBits);
return FALSE;
} }
ValidateGC((DrawablePtr) pPriv->sourceBits, pGC); ValidateGC((DrawablePtr) sourceBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr) pPriv->sourceBits, pGC, 1, (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height, 0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *) pCursor->bits->source); 0, XYPixmap, (char *) pCursor->bits->source);
gcvals.val = GXand; gcvals.val = GXand;
ChangeGC(NullClient, pGC, GCFunction, &gcvals); ChangeGC(NullClient, pGC, GCFunction, &gcvals);
ValidateGC((DrawablePtr) pPriv->sourceBits, pGC); ValidateGC((DrawablePtr) sourceBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr) pPriv->sourceBits, pGC, 1, (*pGC->ops->PutImage) ((DrawablePtr) sourceBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height, 0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *) pCursor->bits->mask); 0, XYPixmap, (char *) pCursor->bits->mask);
/* mask bits -- pCursor->mask & ~pCursor->source */ /* mask bits -- pCursor->mask & ~pCursor->source */
gcvals.val = GXcopy; gcvals.val = GXcopy;
ChangeGC(NullClient, pGC, GCFunction, &gcvals); ChangeGC(NullClient, pGC, GCFunction, &gcvals);
ValidateGC((DrawablePtr) pPriv->maskBits, pGC); ValidateGC((DrawablePtr) maskBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr) pPriv->maskBits, pGC, 1, (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height, 0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *) pCursor->bits->mask); 0, XYPixmap, (char *) pCursor->bits->mask);
gcvals.val = GXandInverted; gcvals.val = GXandInverted;
ChangeGC(NullClient, pGC, GCFunction, &gcvals); ChangeGC(NullClient, pGC, GCFunction, &gcvals);
ValidateGC((DrawablePtr) pPriv->maskBits, pGC); ValidateGC((DrawablePtr) maskBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr) pPriv->maskBits, pGC, 1, (*pGC->ops->PutImage) ((DrawablePtr) maskBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height, 0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *) pCursor->bits->source); 0, XYPixmap, (char *) pCursor->bits->source);
FreeScratchGC(pGC); FreeScratchGC(pGC);
return pPriv;
miDCSwitchScreenCursor(pScreen, pCursor, sourceBits, maskBits, NULL);
return TRUE;
} }
Bool Bool
miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
{ {
miDCCursorPtr pPriv; miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
pPriv = (miDCCursorPtr) dixLookupScreenPrivate(&pCursor->bits->devPrivates, if (pCursor == pScreenPriv->pCursor)
miDCCursorBitsKey, pScreen); miDCSwitchScreenCursor(pScreen, NULL, NULL, NULL, NULL);
if (pPriv && (pCursor->bits->refcnt <= 1)) {
if (pPriv->sourceBits)
(*pScreen->DestroyPixmap) (pPriv->sourceBits);
if (pPriv->maskBits)
(*pScreen->DestroyPixmap) (pPriv->maskBits);
#ifdef ARGB_CURSOR
if (pPriv->pPicture)
FreePicture(pPriv->pPicture, 0);
#endif
free((pointer) pPriv);
dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey,
pScreen, NULL);
}
return TRUE; return TRUE;
} }
static void static void
miDCPutBits(DrawablePtr pDrawable, miDCPutBits(DrawablePtr pDrawable,
miDCCursorPtr pPriv,
GCPtr sourceGC, GCPtr sourceGC,
GCPtr maskGC, GCPtr maskGC,
int x_org, int x_org,
int y_org, int y_org,
unsigned w, unsigned h, unsigned long source, unsigned long mask) unsigned w, unsigned h, unsigned long source, unsigned long mask)
{ {
miDCScreenPtr pScreenPriv = dixLookupPrivate(&pDrawable->pScreen->devPrivates, miDCScreenKey);
ChangeGCVal gcval; ChangeGCVal gcval;
int x, y; int x, y;
@ -333,7 +323,7 @@ miDCPutBits(DrawablePtr pDrawable,
y = y_org; y = y_org;
} }
(*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, (*sourceGC->ops->PushPixels) (sourceGC, pScreenPriv->sourceBits, pDrawable, w, h,
x, y); x, y);
if (maskGC->fgPixel != mask) { if (maskGC->fgPixel != mask) {
gcval.val = mask; gcval.val = mask;
@ -351,7 +341,7 @@ miDCPutBits(DrawablePtr pDrawable,
y = y_org; y = y_org;
} }
(*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); (*maskGC->ops->PushPixels) (maskGC, pScreenPriv->maskBits, pDrawable, w, h, x, y);
} }
static GCPtr static GCPtr
@ -373,27 +363,22 @@ Bool
miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
int x, int y, unsigned long source, unsigned long mask) int x, int y, unsigned long source, unsigned long mask)
{ {
miDCCursorPtr pPriv; miDCScreenPtr pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey);
miDCBufferPtr pBuffer; miDCBufferPtr pBuffer;
WindowPtr pWin; WindowPtr pWin;
pPriv = (miDCCursorPtr) dixLookupScreenPrivate(&pCursor->bits->devPrivates, if (!miDCRealize(pScreen, pCursor))
miDCCursorBitsKey, pScreen); return FALSE;
if (!pPriv) {
pPriv = miDCRealize(pScreen, pCursor);
if (!pPriv)
return FALSE;
}
pWin = pScreen->root; pWin = pScreen->root;
pBuffer = miGetDCDevice(pDev, pScreen); pBuffer = miGetDCDevice(pDev, pScreen);
#ifdef ARGB_CURSOR #ifdef ARGB_CURSOR
if (pPriv->pPicture) { if (pScreenPriv->pPicture) {
if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
return FALSE; return FALSE;
CompositePicture(PictOpOver, CompositePicture(PictOpOver,
pPriv->pPicture, pScreenPriv->pPicture,
NULL, NULL,
pBuffer->pRootPicture, pBuffer->pRootPicture,
0, 0, 0, 0, 0, 0, 0, 0,
@ -402,7 +387,7 @@ miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
else else
#endif #endif
{ {
miDCPutBits((DrawablePtr) pWin, pPriv, miDCPutBits((DrawablePtr) pWin,
pBuffer->pSourceGC, pBuffer->pMaskGC, pBuffer->pSourceGC, pBuffer->pMaskGC,
x, y, pCursor->bits->width, pCursor->bits->height, x, y, pCursor->bits->width, pCursor->bits->height,
source, mask); source, mask);