miext/damage: Only wrap into the GC ops chain if there's a listener (v3)

before           after          Operation
--------    -----------------    -----------------
1148346.9   1191807.5 (  1.04)   PutImage 10x10 square
2091666.1   2180983.0 (  1.04)   ShmPutImage 10x10 square

v3: In miDamage{R,Unr}egister, bump the serial number of the affected
drawable (and all children if it's a window) so subsequent drawing
against the damage will trigger another ValidateGC pass and we wrap
in/out correctly.  Spotted by Aaron Plattner.

Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Aaron Plattner <aplattner@nvidia.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
Adam Jackson 2012-09-20 17:57:00 -04:00 committed by Keith Packard
parent ad0156c369
commit 4dc2a76740

View File

@ -436,9 +436,13 @@ damageCreateGC(GCPtr pGC)
static void
damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
drawableDamage(pDrawable);
DAMAGE_GC_FUNC_PROLOGUE(pGC);
(*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
pGCPriv->ops = pGC->ops; /* just so it's not NULL */
if (pDamage)
pGCPriv->ops = pGC->ops; /* so it's not NULL, so FUNC_EPILOGUE does work */
else
pGCPriv->ops = NULL;
DAMAGE_GC_FUNC_EPILOGUE(pGC);
}
@ -1663,14 +1667,38 @@ miDamageCreate(DamagePtr pDamage)
{
}
/*
* We only wrap into the GC when there's a registered listener. For windows,
* damage includes damage to children. So if there's a GC validated against
* a subwindow and we then register a damage on the parent, we need to bump
* the serial numbers of the children to re-trigger validation.
*
* Since we can't know if a GC has been validated against one of the affected
* children, just bump them all to be safe.
*/
static int
damageRegisterVisit(WindowPtr pWin, void *data)
{
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
return WT_WALKCHILDREN;
}
void
miDamageRegister(DrawablePtr pDrawable, DamagePtr pDamage)
{
if (pDrawable->type == DRAWABLE_WINDOW)
TraverseTree((WindowPtr)pDrawable, damageRegisterVisit, NULL);
else
pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
}
void
miDamageUnregister(DrawablePtr pDrawable, DamagePtr pDamage)
{
if (pDrawable->type == DRAWABLE_WINDOW)
TraverseTree((WindowPtr)pDrawable, damageRegisterVisit, NULL);
else
pDrawable->serialNumber = NEXT_SERIAL_NUMBER;
}
void