1944 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1944 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Copyright © 2003 Keith Packard
 | 
						|
 *
 | 
						|
 * 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, and that the name of Keith Packard not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission.  Keith Packard makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | 
						|
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
						|
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
 * PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
#include    <X11/X.h>
 | 
						|
#include    "scrnintstr.h"
 | 
						|
#include    "windowstr.h"
 | 
						|
#include    <X11/fonts/font.h>
 | 
						|
#include    "dixfontstr.h"
 | 
						|
#include    <X11/fonts/fontstruct.h>
 | 
						|
#include    "mi.h"
 | 
						|
#include    "regionstr.h"
 | 
						|
#include    "globals.h"
 | 
						|
#include    "gcstruct.h"
 | 
						|
#include    "damage.h"
 | 
						|
#include    "damagestr.h"
 | 
						|
 | 
						|
#define wrap(priv, real, mem, func) {\
 | 
						|
    priv->mem = real->mem; \
 | 
						|
    real->mem = func; \
 | 
						|
}
 | 
						|
 | 
						|
#define unwrap(priv, real, mem) {\
 | 
						|
    real->mem = priv->mem; \
 | 
						|
}
 | 
						|
 | 
						|
#define BOX_SAME(a,b) \
 | 
						|
    ((a)->x1 == (b)->x1 && \
 | 
						|
     (a)->y1 == (b)->y1 && \
 | 
						|
     (a)->x2 == (b)->x2 && \
 | 
						|
     (a)->y2 == (b)->y2)
 | 
						|
 | 
						|
#define DAMAGE_VALIDATE_ENABLE 0
 | 
						|
#define DAMAGE_DEBUG_ENABLE 0
 | 
						|
#if DAMAGE_DEBUG_ENABLE
 | 
						|
#define DAMAGE_DEBUG(x)	ErrorF x
 | 
						|
#else
 | 
						|
#define DAMAGE_DEBUG(x)
 | 
						|
#endif
 | 
						|
 | 
						|
#define getPixmapDamageRef(pPixmap) ((DamagePtr *) \
 | 
						|
    dixLookupPrivateAddr(&(pPixmap)->devPrivates, damagePixPrivateKey))
 | 
						|
 | 
						|
#define pixmapDamage(pPixmap)		damagePixPriv(pPixmap)
 | 
						|
 | 
						|
static DevPrivateKeyRec damageScrPrivateKeyRec;
 | 
						|
 | 
						|
#define damageScrPrivateKey (&damageScrPrivateKeyRec)
 | 
						|
static DevPrivateKeyRec damagePixPrivateKeyRec;
 | 
						|
 | 
						|
#define damagePixPrivateKey (&damagePixPrivateKeyRec)
 | 
						|
static DevPrivateKeyRec damageGCPrivateKeyRec;
 | 
						|
 | 
						|
#define damageGCPrivateKey (&damageGCPrivateKeyRec)
 | 
						|
static DevPrivateKeyRec damageWinPrivateKeyRec;
 | 
						|
 | 
						|
#define damageWinPrivateKey (&damageWinPrivateKeyRec)
 | 
						|
 | 
						|
static DamagePtr *
 | 
						|
getDrawableDamageRef(DrawablePtr pDrawable)
 | 
						|
{
 | 
						|
    PixmapPtr pPixmap;
 | 
						|
 | 
						|
    if (WindowDrawable(pDrawable->type)) {
 | 
						|
        ScreenPtr pScreen = pDrawable->pScreen;
 | 
						|
 | 
						|
        pPixmap = 0;
 | 
						|
        if (pScreen->GetWindowPixmap
 | 
						|
#ifdef ROOTLESS_WORKAROUND
 | 
						|
            && ((WindowPtr) pDrawable)->viewable
 | 
						|
#endif
 | 
						|
            )
 | 
						|
            pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
 | 
						|
 | 
						|
        if (!pPixmap) {
 | 
						|
            damageScrPriv(pScreen);
 | 
						|
 | 
						|
            return &pScrPriv->pScreenDamage;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
        pPixmap = (PixmapPtr) pDrawable;
 | 
						|
    return getPixmapDamageRef(pPixmap);
 | 
						|
}
 | 
						|
 | 
						|
#define getDrawableDamage(pDrawable)	(*getDrawableDamageRef (pDrawable))
 | 
						|
#define getWindowDamage(pWin)		getDrawableDamage(&(pWin)->drawable)
 | 
						|
 | 
						|
#define drawableDamage(pDrawable)	\
 | 
						|
    DamagePtr	pDamage = getDrawableDamage(pDrawable)
 | 
						|
 | 
						|
#define windowDamage(pWin)		drawableDamage(&(pWin)->drawable)
 | 
						|
 | 
						|
#define winDamageRef(pWindow) \
 | 
						|
    DamagePtr	*pPrev = (DamagePtr *) \
 | 
						|
	dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey)
 | 
						|
 | 
						|
#if DAMAGE_DEBUG_ENABLE
 | 
						|
static void
 | 
						|
_damageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
 | 
						|
                    int subWindowMode, const char *where)
 | 
						|
#define damageRegionAppend(d,r,c,m) _damageRegionAppend(d,r,c,m,__FUNCTION__)
 | 
						|
#else
 | 
						|
static void
 | 
						|
damageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion, Bool clip,
 | 
						|
                   int subWindowMode)
 | 
						|
#endif
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDrawable->pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
    drawableDamage(pDrawable);
 | 
						|
    DamagePtr pNext;
 | 
						|
    RegionRec clippedRec;
 | 
						|
    RegionPtr pDamageRegion;
 | 
						|
    RegionRec pixClip;
 | 
						|
    int draw_x, draw_y;
 | 
						|
 | 
						|
#ifdef COMPOSITE
 | 
						|
    int screen_x = 0, screen_y = 0;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* short circuit for empty regions */
 | 
						|
    if (!RegionNotEmpty(pRegion))
 | 
						|
        return;
 | 
						|
 | 
						|
#ifdef COMPOSITE
 | 
						|
    /*
 | 
						|
     * When drawing to a pixmap which is storing window contents,
 | 
						|
     * the region presented is in pixmap relative coordinates which
 | 
						|
     * need to be converted to screen relative coordinates
 | 
						|
     */
 | 
						|
    if (pDrawable->type != DRAWABLE_WINDOW) {
 | 
						|
        screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x;
 | 
						|
        screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y;
 | 
						|
    }
 | 
						|
    if (screen_x || screen_y)
 | 
						|
        RegionTranslate(pRegion, screen_x, screen_y);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (pDrawable->type == DRAWABLE_WINDOW &&
 | 
						|
        ((WindowPtr) (pDrawable))->backingStore == NotUseful) {
 | 
						|
        if (subWindowMode == ClipByChildren) {
 | 
						|
            RegionIntersect(pRegion, pRegion,
 | 
						|
                            &((WindowPtr) (pDrawable))->clipList);
 | 
						|
        }
 | 
						|
        else if (subWindowMode == IncludeInferiors) {
 | 
						|
            RegionPtr pTempRegion =
 | 
						|
                NotClippedByChildren((WindowPtr) (pDrawable));
 | 
						|
            RegionIntersect(pRegion, pRegion, pTempRegion);
 | 
						|
            RegionDestroy(pTempRegion);
 | 
						|
        }
 | 
						|
        /* If subWindowMode is set to an invalid value, don't perform
 | 
						|
         * any drawable-based clipping. */
 | 
						|
    }
 | 
						|
 | 
						|
    RegionNull(&clippedRec);
 | 
						|
    for (; pDamage; pDamage = pNext) {
 | 
						|
        pNext = pDamage->pNext;
 | 
						|
        /*
 | 
						|
         * Check for internal damage and don't send events
 | 
						|
         */
 | 
						|
        if (pScrPriv->internalLevel > 0 && !pDamage->isInternal) {
 | 
						|
            DAMAGE_DEBUG(("non internal damage, skipping at %d\n",
 | 
						|
                          pScrPriv->internalLevel));
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        /*
 | 
						|
         * Check for unrealized windows
 | 
						|
         */
 | 
						|
        if (pDamage->pDrawable->type == DRAWABLE_WINDOW &&
 | 
						|
            !((WindowPtr) (pDamage->pDrawable))->realized) {
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
 | 
						|
        draw_x = pDamage->pDrawable->x;
 | 
						|
        draw_y = pDamage->pDrawable->y;
 | 
						|
#ifdef COMPOSITE
 | 
						|
        /*
 | 
						|
         * Need to move everyone to screen coordinates
 | 
						|
         * XXX what about off-screen pixmaps with non-zero x/y?
 | 
						|
         */
 | 
						|
        if (!WindowDrawable(pDamage->pDrawable->type)) {
 | 
						|
            draw_x += ((PixmapPtr) pDamage->pDrawable)->screen_x;
 | 
						|
            draw_y += ((PixmapPtr) pDamage->pDrawable)->screen_y;
 | 
						|
        }
 | 
						|
#endif
 | 
						|
 | 
						|
        /*
 | 
						|
         * Clip against border or pixmap bounds
 | 
						|
         */
 | 
						|
 | 
						|
        pDamageRegion = pRegion;
 | 
						|
        if (clip || pDamage->pDrawable != pDrawable) {
 | 
						|
            pDamageRegion = &clippedRec;
 | 
						|
            if (pDamage->pDrawable->type == DRAWABLE_WINDOW) {
 | 
						|
                RegionIntersect(pDamageRegion, pRegion,
 | 
						|
                                &((WindowPtr) (pDamage->pDrawable))->
 | 
						|
                                borderClip);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                BoxRec box;
 | 
						|
 | 
						|
                box.x1 = draw_x;
 | 
						|
                box.y1 = draw_y;
 | 
						|
                box.x2 = draw_x + pDamage->pDrawable->width;
 | 
						|
                box.y2 = draw_y + pDamage->pDrawable->height;
 | 
						|
                RegionInit(&pixClip, &box, 1);
 | 
						|
                RegionIntersect(pDamageRegion, pRegion, &pixClip);
 | 
						|
                RegionUninit(&pixClip);
 | 
						|
            }
 | 
						|
            /*
 | 
						|
             * Short circuit empty results
 | 
						|
             */
 | 
						|
            if (!RegionNotEmpty(pDamageRegion))
 | 
						|
                continue;
 | 
						|
        }
 | 
						|
 | 
						|
        DAMAGE_DEBUG(("%s %d x %d +%d +%d (target 0x%lx monitor 0x%lx)\n",
 | 
						|
                      where,
 | 
						|
                      pDamageRegion->extents.x2 - pDamageRegion->extents.x1,
 | 
						|
                      pDamageRegion->extents.y2 - pDamageRegion->extents.y1,
 | 
						|
                      pDamageRegion->extents.x1, pDamageRegion->extents.y1,
 | 
						|
                      pDrawable->id, pDamage->pDrawable->id));
 | 
						|
 | 
						|
        /*
 | 
						|
         * Move region to target coordinate space
 | 
						|
         */
 | 
						|
        if (draw_x || draw_y)
 | 
						|
            RegionTranslate(pDamageRegion, -draw_x, -draw_y);
 | 
						|
 | 
						|
        /* Store damage region if needed after submission. */
 | 
						|
        if (pDamage->reportAfter)
 | 
						|
            RegionUnion(&pDamage->pendingDamage,
 | 
						|
                        &pDamage->pendingDamage, pDamageRegion);
 | 
						|
 | 
						|
        /* Report damage now, if desired. */
 | 
						|
        if (!pDamage->reportAfter) {
 | 
						|
            if (pDamage->damageReport)
 | 
						|
                DamageReportDamage(pDamage, pDamageRegion);
 | 
						|
            else
 | 
						|
                RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
 | 
						|
        }
 | 
						|
 | 
						|
        /*
 | 
						|
         * translate original region back
 | 
						|
         */
 | 
						|
        if (pDamageRegion == pRegion && (draw_x || draw_y))
 | 
						|
            RegionTranslate(pDamageRegion, draw_x, draw_y);
 | 
						|
    }
 | 
						|
#ifdef COMPOSITE
 | 
						|
    if (screen_x || screen_y)
 | 
						|
        RegionTranslate(pRegion, -screen_x, -screen_y);
 | 
						|
#endif
 | 
						|
 | 
						|
    RegionUninit(&clippedRec);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageRegionProcessPending(DrawablePtr pDrawable)
 | 
						|
{
 | 
						|
    drawableDamage(pDrawable);
 | 
						|
 | 
						|
    for (; pDamage != NULL; pDamage = pDamage->pNext) {
 | 
						|
        if (pDamage->reportAfter) {
 | 
						|
            /* It's possible that there is only interest in postRendering reporting. */
 | 
						|
            if (pDamage->damageReport)
 | 
						|
                DamageReportDamage(pDamage, &pDamage->pendingDamage);
 | 
						|
            else
 | 
						|
                RegionUnion(&pDamage->damage, &pDamage->damage,
 | 
						|
                            &pDamage->pendingDamage);
 | 
						|
        }
 | 
						|
 | 
						|
        if (pDamage->reportAfter)
 | 
						|
            RegionEmpty(&pDamage->pendingDamage);
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#if DAMAGE_DEBUG_ENABLE
 | 
						|
#define damageDamageBox(d,b,m) _damageDamageBox(d,b,m,__FUNCTION__)
 | 
						|
static void
 | 
						|
_damageDamageBox(DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode,
 | 
						|
                 const char *where)
 | 
						|
#else
 | 
						|
static void
 | 
						|
damageDamageBox(DrawablePtr pDrawable, BoxPtr pBox, int subWindowMode)
 | 
						|
#endif
 | 
						|
{
 | 
						|
    RegionRec region;
 | 
						|
 | 
						|
    RegionInit(®ion, pBox, 1);
 | 
						|
#if DAMAGE_DEBUG_ENABLE
 | 
						|
    _damageRegionAppend(pDrawable, ®ion, TRUE, subWindowMode, where);
 | 
						|
#else
 | 
						|
    damageRegionAppend(pDrawable, ®ion, TRUE, subWindowMode);
 | 
						|
#endif
 | 
						|
    RegionUninit(®ion);
 | 
						|
}
 | 
						|
 | 
						|
static void damageValidateGC(GCPtr, unsigned long, DrawablePtr);
 | 
						|
static void damageChangeGC(GCPtr, unsigned long);
 | 
						|
static void damageCopyGC(GCPtr, unsigned long, GCPtr);
 | 
						|
static void damageDestroyGC(GCPtr);
 | 
						|
static void damageChangeClip(GCPtr, int, void *, int);
 | 
						|
static void damageDestroyClip(GCPtr);
 | 
						|
static void damageCopyClip(GCPtr, GCPtr);
 | 
						|
 | 
						|
static GCFuncs damageGCFuncs = {
 | 
						|
    damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC,
 | 
						|
    damageChangeClip, damageDestroyClip, damageCopyClip
 | 
						|
};
 | 
						|
 | 
						|
static GCOps damageGCOps;
 | 
						|
 | 
						|
static Bool
 | 
						|
damageCreateGC(GCPtr pGC)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pGC->pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
    damageGCPriv(pGC);
 | 
						|
    Bool ret;
 | 
						|
 | 
						|
    unwrap(pScrPriv, pScreen, CreateGC);
 | 
						|
    if ((ret = (*pScreen->CreateGC) (pGC))) {
 | 
						|
        pGCPriv->ops = NULL;
 | 
						|
        pGCPriv->funcs = pGC->funcs;
 | 
						|
        pGC->funcs = &damageGCFuncs;
 | 
						|
    }
 | 
						|
    wrap(pScrPriv, pScreen, CreateGC, damageCreateGC);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \
 | 
						|
    damageGCPriv(pGC);  \
 | 
						|
    const GCFuncs *oldFuncs = pGC->funcs; \
 | 
						|
    unwrap(pGCPriv, pGC, funcs);  \
 | 
						|
    unwrap(pGCPriv, pGC, ops); \
 | 
						|
 | 
						|
#define DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable) \
 | 
						|
    wrap(pGCPriv, pGC, funcs, oldFuncs); \
 | 
						|
    wrap(pGCPriv, pGC, ops, &damageGCOps)
 | 
						|
 | 
						|
#define DAMAGE_GC_FUNC_PROLOGUE(pGC) \
 | 
						|
    damageGCPriv(pGC); \
 | 
						|
    unwrap(pGCPriv, pGC, funcs); \
 | 
						|
    if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
 | 
						|
 | 
						|
#define DAMAGE_GC_FUNC_EPILOGUE(pGC) \
 | 
						|
    wrap(pGCPriv, pGC, funcs, &damageGCFuncs);  \
 | 
						|
    if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &damageGCOps)
 | 
						|
 | 
						|
static void
 | 
						|
damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pGC);
 | 
						|
    (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
 | 
						|
    pGCPriv->ops = pGC->ops; /* just so it's not NULL */
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pGC);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageDestroyGC(GCPtr pGC)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pGC);
 | 
						|
    (*pGC->funcs->DestroyGC) (pGC);
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pGC);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageChangeGC(GCPtr pGC, unsigned long mask)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pGC);
 | 
						|
    (*pGC->funcs->ChangeGC) (pGC, mask);
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pGC);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pGCDst);
 | 
						|
    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pGCDst);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pGC);
 | 
						|
    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pGC);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pgcDst);
 | 
						|
    (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pgcDst);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageDestroyClip(GCPtr pGC)
 | 
						|
{
 | 
						|
    DAMAGE_GC_FUNC_PROLOGUE(pGC);
 | 
						|
    (*pGC->funcs->DestroyClip) (pGC);
 | 
						|
    DAMAGE_GC_FUNC_EPILOGUE(pGC);
 | 
						|
}
 | 
						|
 | 
						|
#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \
 | 
						|
    BoxPtr extents = &pGC->pCompositeClip->extents;\
 | 
						|
    if(box.x1 < extents->x1) box.x1 = extents->x1; \
 | 
						|
    if(box.x2 > extents->x2) box.x2 = extents->x2; \
 | 
						|
    if(box.y1 < extents->y1) box.y1 = extents->y1; \
 | 
						|
    if(box.y2 > extents->y2) box.y2 = extents->y2; \
 | 
						|
    }
 | 
						|
 | 
						|
#define TRANSLATE_BOX(box, pDrawable) { \
 | 
						|
    box.x1 += pDrawable->x; \
 | 
						|
    box.x2 += pDrawable->x; \
 | 
						|
    box.y1 += pDrawable->y; \
 | 
						|
    box.y2 += pDrawable->y; \
 | 
						|
    }
 | 
						|
 | 
						|
#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \
 | 
						|
    TRANSLATE_BOX(box, pDrawable); \
 | 
						|
    TRIM_BOX(box, pGC); \
 | 
						|
    }
 | 
						|
 | 
						|
#define BOX_NOT_EMPTY(box) \
 | 
						|
    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
 | 
						|
 | 
						|
#define checkGCDamage(d,g)	(getDrawableDamage(d) && \
 | 
						|
				 (!g->pCompositeClip ||\
 | 
						|
				  RegionNotEmpty(g->pCompositeClip)))
 | 
						|
 | 
						|
#define TRIM_PICTURE_BOX(box, pDst) { \
 | 
						|
    BoxPtr extents = &pDst->pCompositeClip->extents;\
 | 
						|
    if(box.x1 < extents->x1) box.x1 = extents->x1; \
 | 
						|
    if(box.x2 > extents->x2) box.x2 = extents->x2; \
 | 
						|
    if(box.y1 < extents->y1) box.y1 = extents->y1; \
 | 
						|
    if(box.y2 > extents->y2) box.y2 = extents->y2; \
 | 
						|
    }
 | 
						|
 | 
						|
#define checkPictureDamage(p)	(getDrawableDamage(p->pDrawable) && \
 | 
						|
				 RegionNotEmpty(p->pCompositeClip))
 | 
						|
 | 
						|
static void
 | 
						|
damageComposite(CARD8 op,
 | 
						|
                PicturePtr pSrc,
 | 
						|
                PicturePtr pMask,
 | 
						|
                PicturePtr pDst,
 | 
						|
                INT16 xSrc,
 | 
						|
                INT16 ySrc,
 | 
						|
                INT16 xMask,
 | 
						|
                INT16 yMask,
 | 
						|
                INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if (checkPictureDamage(pDst)) {
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = xDst + pDst->pDrawable->x;
 | 
						|
        box.y1 = yDst + pDst->pDrawable->y;
 | 
						|
        box.x2 = box.x1 + width;
 | 
						|
        box.y2 = box.y1 + height;
 | 
						|
        TRIM_PICTURE_BOX(box, pDst);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDst->pDrawable, &box, pDst->subWindowMode);
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, ps, Composite);
 | 
						|
    (*ps->Composite) (op,
 | 
						|
                      pSrc,
 | 
						|
                      pMask,
 | 
						|
                      pDst,
 | 
						|
                      xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
 | 
						|
    damageRegionProcessPending(pDst->pDrawable);
 | 
						|
    wrap(pScrPriv, ps, Composite, damageComposite);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageGlyphs(CARD8 op,
 | 
						|
             PicturePtr pSrc,
 | 
						|
             PicturePtr pDst,
 | 
						|
             PictFormatPtr maskFormat,
 | 
						|
             INT16 xSrc,
 | 
						|
             INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if (checkPictureDamage(pDst)) {
 | 
						|
        int nlistTmp = nlist;
 | 
						|
        GlyphListPtr listTmp = list;
 | 
						|
        GlyphPtr *glyphsTmp = glyphs;
 | 
						|
        int x, y;
 | 
						|
        int n;
 | 
						|
        GlyphPtr glyph;
 | 
						|
        BoxRec box;
 | 
						|
        int x1, y1, x2, y2;
 | 
						|
 | 
						|
        box.x1 = 32767;
 | 
						|
        box.y1 = 32767;
 | 
						|
        box.x2 = -32767;
 | 
						|
        box.y2 = -32767;
 | 
						|
        x = pDst->pDrawable->x;
 | 
						|
        y = pDst->pDrawable->y;
 | 
						|
        while (nlistTmp--) {
 | 
						|
            x += listTmp->xOff;
 | 
						|
            y += listTmp->yOff;
 | 
						|
            n = listTmp->len;
 | 
						|
            while (n--) {
 | 
						|
                glyph = *glyphsTmp++;
 | 
						|
                x1 = x - glyph->info.x;
 | 
						|
                y1 = y - glyph->info.y;
 | 
						|
                x2 = x1 + glyph->info.width;
 | 
						|
                y2 = y1 + glyph->info.height;
 | 
						|
                if (x1 < box.x1)
 | 
						|
                    box.x1 = x1;
 | 
						|
                if (y1 < box.y1)
 | 
						|
                    box.y1 = y1;
 | 
						|
                if (x2 > box.x2)
 | 
						|
                    box.x2 = x2;
 | 
						|
                if (y2 > box.y2)
 | 
						|
                    box.y2 = y2;
 | 
						|
                x += glyph->info.xOff;
 | 
						|
                y += glyph->info.yOff;
 | 
						|
            }
 | 
						|
            listTmp++;
 | 
						|
        }
 | 
						|
        TRIM_PICTURE_BOX(box, pDst);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDst->pDrawable, &box, pDst->subWindowMode);
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, ps, Glyphs);
 | 
						|
    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
 | 
						|
    damageRegionProcessPending(pDst->pDrawable);
 | 
						|
    wrap(pScrPriv, ps, Glyphs, damageGlyphs);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageAddTraps(PicturePtr pPicture,
 | 
						|
               INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if (checkPictureDamage(pPicture)) {
 | 
						|
        BoxRec box;
 | 
						|
        int i;
 | 
						|
        int x, y;
 | 
						|
        xTrap *t = traps;
 | 
						|
 | 
						|
        box.x1 = 32767;
 | 
						|
        box.y1 = 32767;
 | 
						|
        box.x2 = -32767;
 | 
						|
        box.y2 = -32767;
 | 
						|
        x = pPicture->pDrawable->x + x_off;
 | 
						|
        y = pPicture->pDrawable->y + y_off;
 | 
						|
        for (i = 0; i < ntrap; i++) {
 | 
						|
            pixman_fixed_t l = min(t->top.l, t->bot.l);
 | 
						|
            pixman_fixed_t r = max(t->top.r, t->bot.r);
 | 
						|
            int x1 = x + pixman_fixed_to_int(l);
 | 
						|
            int x2 = x + pixman_fixed_to_int(pixman_fixed_ceil(r));
 | 
						|
            int y1 = y + pixman_fixed_to_int(t->top.y);
 | 
						|
            int y2 = y + pixman_fixed_to_int(pixman_fixed_ceil(t->bot.y));
 | 
						|
 | 
						|
            if (x1 < box.x1)
 | 
						|
                box.x1 = x1;
 | 
						|
            if (x2 > box.x2)
 | 
						|
                box.x2 = x2;
 | 
						|
            if (y1 < box.y1)
 | 
						|
                box.y1 = y1;
 | 
						|
            if (y2 > box.y2)
 | 
						|
                box.y2 = y2;
 | 
						|
        }
 | 
						|
        TRIM_PICTURE_BOX(box, pPicture);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pPicture->pDrawable, &box, pPicture->subWindowMode);
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, ps, AddTraps);
 | 
						|
    (*ps->AddTraps) (pPicture, x_off, y_off, ntrap, traps);
 | 
						|
    damageRegionProcessPending(pPicture->pDrawable);
 | 
						|
    wrap(pScrPriv, ps, AddTraps, damageAddTraps);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************/
 | 
						|
 | 
						|
static void
 | 
						|
damageFillSpans(DrawablePtr pDrawable,
 | 
						|
                GC * pGC, int npt, DDXPointPtr ppt, int *pwidth, int fSorted)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (npt && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        int nptTmp = npt;
 | 
						|
        DDXPointPtr pptTmp = ppt;
 | 
						|
        int *pwidthTmp = pwidth;
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = pptTmp->x;
 | 
						|
        box.x2 = box.x1 + *pwidthTmp;
 | 
						|
        box.y2 = box.y1 = pptTmp->y;
 | 
						|
 | 
						|
        while (--nptTmp) {
 | 
						|
            pptTmp++;
 | 
						|
            pwidthTmp++;
 | 
						|
            if (box.x1 > pptTmp->x)
 | 
						|
                box.x1 = pptTmp->x;
 | 
						|
            if (box.x2 < (pptTmp->x + *pwidthTmp))
 | 
						|
                box.x2 = pptTmp->x + *pwidthTmp;
 | 
						|
            if (box.y1 > pptTmp->y)
 | 
						|
                box.y1 = pptTmp->y;
 | 
						|
            else if (box.y2 < pptTmp->y)
 | 
						|
                box.y2 = pptTmp->y;
 | 
						|
        }
 | 
						|
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        if (!pGC->miTranslate) {
 | 
						|
            TRANSLATE_BOX(box, pDrawable);
 | 
						|
        }
 | 
						|
        TRIM_BOX(box, pGC);
 | 
						|
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
 | 
						|
    (*pGC->ops->FillSpans) (pDrawable, pGC, npt, ppt, pwidth, fSorted);
 | 
						|
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageSetSpans(DrawablePtr pDrawable,
 | 
						|
               GCPtr pGC,
 | 
						|
               char *pcharsrc,
 | 
						|
               DDXPointPtr ppt, int *pwidth, int npt, int fSorted)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (npt && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        DDXPointPtr pptTmp = ppt;
 | 
						|
        int *pwidthTmp = pwidth;
 | 
						|
        int nptTmp = npt;
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = pptTmp->x;
 | 
						|
        box.x2 = box.x1 + *pwidthTmp;
 | 
						|
        box.y2 = box.y1 = pptTmp->y;
 | 
						|
 | 
						|
        while (--nptTmp) {
 | 
						|
            pptTmp++;
 | 
						|
            pwidthTmp++;
 | 
						|
            if (box.x1 > pptTmp->x)
 | 
						|
                box.x1 = pptTmp->x;
 | 
						|
            if (box.x2 < (pptTmp->x + *pwidthTmp))
 | 
						|
                box.x2 = pptTmp->x + *pwidthTmp;
 | 
						|
            if (box.y1 > pptTmp->y)
 | 
						|
                box.y1 = pptTmp->y;
 | 
						|
            else if (box.y2 < pptTmp->y)
 | 
						|
                box.y2 = pptTmp->y;
 | 
						|
        }
 | 
						|
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        if (!pGC->miTranslate) {
 | 
						|
            TRANSLATE_BOX(box, pDrawable);
 | 
						|
        }
 | 
						|
        TRIM_BOX(box, pGC);
 | 
						|
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->SetSpans) (pDrawable, pGC, pcharsrc, ppt, pwidth, npt, fSorted);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePutImage(DrawablePtr pDrawable,
 | 
						|
               GCPtr pGC,
 | 
						|
               int depth,
 | 
						|
               int x,
 | 
						|
               int y, int w, int h, int leftPad, int format, char *pImage)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    if (checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = x + pDrawable->x;
 | 
						|
        box.x2 = box.x1 + w;
 | 
						|
        box.y1 = y + pDrawable->y;
 | 
						|
        box.y2 = box.y1 + h;
 | 
						|
 | 
						|
        TRIM_BOX(box, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h,
 | 
						|
                           leftPad, format, pImage);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static RegionPtr
 | 
						|
damageCopyArea(DrawablePtr pSrc,
 | 
						|
               DrawablePtr pDst,
 | 
						|
               GC * pGC,
 | 
						|
               int srcx, int srcy, int width, int height, int dstx, int dsty)
 | 
						|
{
 | 
						|
    RegionPtr ret;
 | 
						|
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
 | 
						|
 | 
						|
    if (checkGCDamage(pDst, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = dstx + pDst->x;
 | 
						|
        box.x2 = box.x1 + width;
 | 
						|
        box.y1 = dsty + pDst->y;
 | 
						|
        box.y2 = box.y1 + height;
 | 
						|
 | 
						|
        TRIM_BOX(box, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDst, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*pGC->ops->CopyArea) (pSrc, pDst,
 | 
						|
                                 pGC, srcx, srcy, width, height, dstx, dsty);
 | 
						|
    damageRegionProcessPending(pDst);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static RegionPtr
 | 
						|
damageCopyPlane(DrawablePtr pSrc,
 | 
						|
                DrawablePtr pDst,
 | 
						|
                GCPtr pGC,
 | 
						|
                int srcx,
 | 
						|
                int srcy,
 | 
						|
                int width,
 | 
						|
                int height, int dstx, int dsty, unsigned long bitPlane)
 | 
						|
{
 | 
						|
    RegionPtr ret;
 | 
						|
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
 | 
						|
 | 
						|
    if (checkGCDamage(pDst, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = dstx + pDst->x;
 | 
						|
        box.x2 = box.x1 + width;
 | 
						|
        box.y1 = dsty + pDst->y;
 | 
						|
        box.y2 = box.y1 + height;
 | 
						|
 | 
						|
        TRIM_BOX(box, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDst, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = (*pGC->ops->CopyPlane) (pSrc, pDst,
 | 
						|
                                  pGC, srcx, srcy, width, height, dstx, dsty,
 | 
						|
                                  bitPlane);
 | 
						|
    damageRegionProcessPending(pDst);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDst);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolyPoint(DrawablePtr pDrawable,
 | 
						|
                GCPtr pGC, int mode, int npt, xPoint * ppt)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (npt && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
        int nptTmp = npt;
 | 
						|
        xPoint *pptTmp = ppt;
 | 
						|
 | 
						|
        box.x2 = box.x1 = pptTmp->x;
 | 
						|
        box.y2 = box.y1 = pptTmp->y;
 | 
						|
 | 
						|
        /* this could be slow if the points were spread out */
 | 
						|
 | 
						|
        while (--nptTmp) {
 | 
						|
            pptTmp++;
 | 
						|
            if (box.x1 > pptTmp->x)
 | 
						|
                box.x1 = pptTmp->x;
 | 
						|
            else if (box.x2 < pptTmp->x)
 | 
						|
                box.x2 = pptTmp->x;
 | 
						|
            if (box.y1 > pptTmp->y)
 | 
						|
                box.y1 = pptTmp->y;
 | 
						|
            else if (box.y2 < pptTmp->y)
 | 
						|
                box.y2 = pptTmp->y;
 | 
						|
        }
 | 
						|
 | 
						|
        box.x2++;
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, ppt);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolylines(DrawablePtr pDrawable,
 | 
						|
                GCPtr pGC, int mode, int npt, DDXPointPtr ppt)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (npt && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        int nptTmp = npt;
 | 
						|
        DDXPointPtr pptTmp = ppt;
 | 
						|
        BoxRec box;
 | 
						|
        int extra = pGC->lineWidth >> 1;
 | 
						|
 | 
						|
        box.x2 = box.x1 = pptTmp->x;
 | 
						|
        box.y2 = box.y1 = pptTmp->y;
 | 
						|
 | 
						|
        if (nptTmp > 1) {
 | 
						|
            if (pGC->joinStyle == JoinMiter)
 | 
						|
                extra = 6 * pGC->lineWidth;
 | 
						|
            else if (pGC->capStyle == CapProjecting)
 | 
						|
                extra = pGC->lineWidth;
 | 
						|
        }
 | 
						|
 | 
						|
        if (mode == CoordModePrevious) {
 | 
						|
            int x = box.x1;
 | 
						|
            int y = box.y1;
 | 
						|
 | 
						|
            while (--nptTmp) {
 | 
						|
                pptTmp++;
 | 
						|
                x += pptTmp->x;
 | 
						|
                y += pptTmp->y;
 | 
						|
                if (box.x1 > x)
 | 
						|
                    box.x1 = x;
 | 
						|
                else if (box.x2 < x)
 | 
						|
                    box.x2 = x;
 | 
						|
                if (box.y1 > y)
 | 
						|
                    box.y1 = y;
 | 
						|
                else if (box.y2 < y)
 | 
						|
                    box.y2 = y;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            while (--nptTmp) {
 | 
						|
                pptTmp++;
 | 
						|
                if (box.x1 > pptTmp->x)
 | 
						|
                    box.x1 = pptTmp->x;
 | 
						|
                else if (box.x2 < pptTmp->x)
 | 
						|
                    box.x2 = pptTmp->x;
 | 
						|
                if (box.y1 > pptTmp->y)
 | 
						|
                    box.y1 = pptTmp->y;
 | 
						|
                else if (box.y2 < pptTmp->y)
 | 
						|
                    box.y2 = pptTmp->y;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        box.x2++;
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        if (extra) {
 | 
						|
            box.x1 -= extra;
 | 
						|
            box.x2 += extra;
 | 
						|
            box.y1 -= extra;
 | 
						|
            box.y2 += extra;
 | 
						|
        }
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppt);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolySegment(DrawablePtr pDrawable, GCPtr pGC, int nSeg, xSegment * pSeg)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (nSeg && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
        int extra = pGC->lineWidth;
 | 
						|
        int nsegTmp = nSeg;
 | 
						|
        xSegment *pSegTmp = pSeg;
 | 
						|
 | 
						|
        if (pGC->capStyle != CapProjecting)
 | 
						|
            extra >>= 1;
 | 
						|
 | 
						|
        if (pSegTmp->x2 > pSegTmp->x1) {
 | 
						|
            box.x1 = pSegTmp->x1;
 | 
						|
            box.x2 = pSegTmp->x2;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            box.x2 = pSegTmp->x1;
 | 
						|
            box.x1 = pSegTmp->x2;
 | 
						|
        }
 | 
						|
 | 
						|
        if (pSegTmp->y2 > pSegTmp->y1) {
 | 
						|
            box.y1 = pSegTmp->y1;
 | 
						|
            box.y2 = pSegTmp->y2;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            box.y2 = pSegTmp->y1;
 | 
						|
            box.y1 = pSegTmp->y2;
 | 
						|
        }
 | 
						|
 | 
						|
        while (--nsegTmp) {
 | 
						|
            pSegTmp++;
 | 
						|
            if (pSegTmp->x2 > pSegTmp->x1) {
 | 
						|
                if (pSegTmp->x1 < box.x1)
 | 
						|
                    box.x1 = pSegTmp->x1;
 | 
						|
                if (pSegTmp->x2 > box.x2)
 | 
						|
                    box.x2 = pSegTmp->x2;
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                if (pSegTmp->x2 < box.x1)
 | 
						|
                    box.x1 = pSegTmp->x2;
 | 
						|
                if (pSegTmp->x1 > box.x2)
 | 
						|
                    box.x2 = pSegTmp->x1;
 | 
						|
            }
 | 
						|
            if (pSegTmp->y2 > pSegTmp->y1) {
 | 
						|
                if (pSegTmp->y1 < box.y1)
 | 
						|
                    box.y1 = pSegTmp->y1;
 | 
						|
                if (pSegTmp->y2 > box.y2)
 | 
						|
                    box.y2 = pSegTmp->y2;
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                if (pSegTmp->y2 < box.y1)
 | 
						|
                    box.y1 = pSegTmp->y2;
 | 
						|
                if (pSegTmp->y1 > box.y2)
 | 
						|
                    box.y2 = pSegTmp->y1;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        box.x2++;
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        if (extra) {
 | 
						|
            box.x1 -= extra;
 | 
						|
            box.x2 += extra;
 | 
						|
            box.y1 -= extra;
 | 
						|
            box.y2 += extra;
 | 
						|
        }
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PolySegment) (pDrawable, pGC, nSeg, pSeg);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolyRectangle(DrawablePtr pDrawable,
 | 
						|
                    GCPtr pGC, int nRects, xRectangle *pRects)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (nRects && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
        int offset1, offset2, offset3;
 | 
						|
        int nRectsTmp = nRects;
 | 
						|
        xRectangle *pRectsTmp = pRects;
 | 
						|
 | 
						|
        offset2 = pGC->lineWidth;
 | 
						|
        if (!offset2)
 | 
						|
            offset2 = 1;
 | 
						|
        offset1 = offset2 >> 1;
 | 
						|
        offset3 = offset2 - offset1;
 | 
						|
 | 
						|
        while (nRectsTmp--) {
 | 
						|
            box.x1 = pRectsTmp->x - offset1;
 | 
						|
            box.y1 = pRectsTmp->y - offset1;
 | 
						|
            box.x2 = box.x1 + pRectsTmp->width + offset2;
 | 
						|
            box.y2 = box.y1 + offset2;
 | 
						|
            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
            if (BOX_NOT_EMPTY(box))
 | 
						|
                damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
 | 
						|
            box.x1 = pRectsTmp->x - offset1;
 | 
						|
            box.y1 = pRectsTmp->y + offset3;
 | 
						|
            box.x2 = box.x1 + offset2;
 | 
						|
            box.y2 = box.y1 + pRectsTmp->height - offset2;
 | 
						|
            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
            if (BOX_NOT_EMPTY(box))
 | 
						|
                damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
 | 
						|
            box.x1 = pRectsTmp->x + pRectsTmp->width - offset1;
 | 
						|
            box.y1 = pRectsTmp->y + offset3;
 | 
						|
            box.x2 = box.x1 + offset2;
 | 
						|
            box.y2 = box.y1 + pRectsTmp->height - offset2;
 | 
						|
            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
            if (BOX_NOT_EMPTY(box))
 | 
						|
                damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
 | 
						|
            box.x1 = pRectsTmp->x - offset1;
 | 
						|
            box.y1 = pRectsTmp->y + pRectsTmp->height - offset1;
 | 
						|
            box.x2 = box.x1 + pRectsTmp->width + offset2;
 | 
						|
            box.y2 = box.y1 + offset2;
 | 
						|
            TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
            if (BOX_NOT_EMPTY(box))
 | 
						|
                damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
 | 
						|
            pRectsTmp++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    (*pGC->ops->PolyRectangle) (pDrawable, pGC, nRects, pRects);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolyArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (nArcs && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        int extra = pGC->lineWidth >> 1;
 | 
						|
        BoxRec box;
 | 
						|
        int nArcsTmp = nArcs;
 | 
						|
        xArc *pArcsTmp = pArcs;
 | 
						|
 | 
						|
        box.x1 = pArcsTmp->x;
 | 
						|
        box.x2 = box.x1 + pArcsTmp->width;
 | 
						|
        box.y1 = pArcsTmp->y;
 | 
						|
        box.y2 = box.y1 + pArcsTmp->height;
 | 
						|
 | 
						|
        while (--nArcsTmp) {
 | 
						|
            pArcsTmp++;
 | 
						|
            if (box.x1 > pArcsTmp->x)
 | 
						|
                box.x1 = pArcsTmp->x;
 | 
						|
            if (box.x2 < (pArcsTmp->x + pArcsTmp->width))
 | 
						|
                box.x2 = pArcsTmp->x + pArcsTmp->width;
 | 
						|
            if (box.y1 > pArcsTmp->y)
 | 
						|
                box.y1 = pArcsTmp->y;
 | 
						|
            if (box.y2 < (pArcsTmp->y + pArcsTmp->height))
 | 
						|
                box.y2 = pArcsTmp->y + pArcsTmp->height;
 | 
						|
        }
 | 
						|
 | 
						|
        if (extra) {
 | 
						|
            box.x1 -= extra;
 | 
						|
            box.x2 += extra;
 | 
						|
            box.y1 -= extra;
 | 
						|
            box.y2 += extra;
 | 
						|
        }
 | 
						|
 | 
						|
        box.x2++;
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PolyArc) (pDrawable, pGC, nArcs, pArcs);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageFillPolygon(DrawablePtr pDrawable,
 | 
						|
                  GCPtr pGC, int shape, int mode, int npt, DDXPointPtr ppt)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (npt > 2 && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        DDXPointPtr pptTmp = ppt;
 | 
						|
        int nptTmp = npt;
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x2 = box.x1 = pptTmp->x;
 | 
						|
        box.y2 = box.y1 = pptTmp->y;
 | 
						|
 | 
						|
        if (mode != CoordModeOrigin) {
 | 
						|
            int x = box.x1;
 | 
						|
            int y = box.y1;
 | 
						|
 | 
						|
            while (--nptTmp) {
 | 
						|
                pptTmp++;
 | 
						|
                x += pptTmp->x;
 | 
						|
                y += pptTmp->y;
 | 
						|
                if (box.x1 > x)
 | 
						|
                    box.x1 = x;
 | 
						|
                else if (box.x2 < x)
 | 
						|
                    box.x2 = x;
 | 
						|
                if (box.y1 > y)
 | 
						|
                    box.y1 = y;
 | 
						|
                else if (box.y2 < y)
 | 
						|
                    box.y2 = y;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            while (--nptTmp) {
 | 
						|
                pptTmp++;
 | 
						|
                if (box.x1 > pptTmp->x)
 | 
						|
                    box.x1 = pptTmp->x;
 | 
						|
                else if (box.x2 < pptTmp->x)
 | 
						|
                    box.x2 = pptTmp->x;
 | 
						|
                if (box.y1 > pptTmp->y)
 | 
						|
                    box.y1 = pptTmp->y;
 | 
						|
                else if (box.y2 < pptTmp->y)
 | 
						|
                    box.y2 = pptTmp->y;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        box.x2++;
 | 
						|
        box.y2++;
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
 | 
						|
    (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, npt, ppt);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolyFillRect(DrawablePtr pDrawable,
 | 
						|
                   GCPtr pGC, int nRects, xRectangle *pRects)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    if (nRects && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
        xRectangle *pRectsTmp = pRects;
 | 
						|
        int nRectsTmp = nRects;
 | 
						|
 | 
						|
        box.x1 = pRectsTmp->x;
 | 
						|
        box.x2 = box.x1 + pRectsTmp->width;
 | 
						|
        box.y1 = pRectsTmp->y;
 | 
						|
        box.y2 = box.y1 + pRectsTmp->height;
 | 
						|
 | 
						|
        while (--nRectsTmp) {
 | 
						|
            pRectsTmp++;
 | 
						|
            if (box.x1 > pRectsTmp->x)
 | 
						|
                box.x1 = pRectsTmp->x;
 | 
						|
            if (box.x2 < (pRectsTmp->x + pRectsTmp->width))
 | 
						|
                box.x2 = pRectsTmp->x + pRectsTmp->width;
 | 
						|
            if (box.y1 > pRectsTmp->y)
 | 
						|
                box.y1 = pRectsTmp->y;
 | 
						|
            if (box.y2 < (pRectsTmp->y + pRectsTmp->height))
 | 
						|
                box.y2 = pRectsTmp->y + pRectsTmp->height;
 | 
						|
        }
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PolyFillRect) (pDrawable, pGC, nRects, pRects);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int nArcs, xArc * pArcs)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
 | 
						|
    if (nArcs && checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
        int nArcsTmp = nArcs;
 | 
						|
        xArc *pArcsTmp = pArcs;
 | 
						|
 | 
						|
        box.x1 = pArcsTmp->x;
 | 
						|
        box.x2 = box.x1 + pArcsTmp->width;
 | 
						|
        box.y1 = pArcsTmp->y;
 | 
						|
        box.y2 = box.y1 + pArcsTmp->height;
 | 
						|
 | 
						|
        while (--nArcsTmp) {
 | 
						|
            pArcsTmp++;
 | 
						|
            if (box.x1 > pArcsTmp->x)
 | 
						|
                box.x1 = pArcsTmp->x;
 | 
						|
            if (box.x2 < (pArcsTmp->x + pArcsTmp->width))
 | 
						|
                box.x2 = pArcsTmp->x + pArcsTmp->width;
 | 
						|
            if (box.y1 > pArcsTmp->y)
 | 
						|
                box.y1 = pArcsTmp->y;
 | 
						|
            if (box.y2 < (pArcsTmp->y + pArcsTmp->height))
 | 
						|
                box.y2 = pArcsTmp->y + pArcsTmp->height;
 | 
						|
        }
 | 
						|
 | 
						|
        TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PolyFillArc) (pDrawable, pGC, nArcs, pArcs);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * general Poly/Image text function.  Extract glyph information,
 | 
						|
 * compute bounding box and remove cursor if it is overlapped.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
damageDamageChars(DrawablePtr pDrawable,
 | 
						|
                  FontPtr font,
 | 
						|
                  int x,
 | 
						|
                  int y,
 | 
						|
                  unsigned int n,
 | 
						|
                  CharInfoPtr * charinfo, Bool imageblt, int subWindowMode)
 | 
						|
{
 | 
						|
    ExtentInfoRec extents;
 | 
						|
    BoxRec box;
 | 
						|
 | 
						|
    QueryGlyphExtents(font, charinfo, n, &extents);
 | 
						|
    if (imageblt) {
 | 
						|
        if (extents.overallWidth > extents.overallRight)
 | 
						|
            extents.overallRight = extents.overallWidth;
 | 
						|
        if (extents.overallWidth < extents.overallLeft)
 | 
						|
            extents.overallLeft = extents.overallWidth;
 | 
						|
        if (extents.overallLeft > 0)
 | 
						|
            extents.overallLeft = 0;
 | 
						|
        if (extents.fontAscent > extents.overallAscent)
 | 
						|
            extents.overallAscent = extents.fontAscent;
 | 
						|
        if (extents.fontDescent > extents.overallDescent)
 | 
						|
            extents.overallDescent = extents.fontDescent;
 | 
						|
    }
 | 
						|
    box.x1 = x + extents.overallLeft;
 | 
						|
    box.y1 = y - extents.overallAscent;
 | 
						|
    box.x2 = x + extents.overallRight;
 | 
						|
    box.y2 = y + extents.overallDescent;
 | 
						|
    damageDamageBox(pDrawable, &box, subWindowMode);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * values for textType:
 | 
						|
 */
 | 
						|
#define TT_POLY8   0
 | 
						|
#define TT_IMAGE8  1
 | 
						|
#define TT_POLY16  2
 | 
						|
#define TT_IMAGE16 3
 | 
						|
 | 
						|
static void
 | 
						|
damageText(DrawablePtr pDrawable,
 | 
						|
           GCPtr pGC,
 | 
						|
           int x,
 | 
						|
           int y,
 | 
						|
           unsigned long count,
 | 
						|
           char *chars, FontEncoding fontEncoding, Bool textType)
 | 
						|
{
 | 
						|
    CharInfoPtr *charinfo;
 | 
						|
    unsigned long i;
 | 
						|
    unsigned int n;
 | 
						|
    Bool imageblt;
 | 
						|
 | 
						|
    imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
 | 
						|
 | 
						|
    if (!checkGCDamage(pDrawable, pGC))
 | 
						|
        return;
 | 
						|
 | 
						|
    charinfo = malloc(count * sizeof(CharInfoPtr));
 | 
						|
    if (!charinfo)
 | 
						|
        return;
 | 
						|
 | 
						|
    GetGlyphs(pGC->font, count, (unsigned char *) chars,
 | 
						|
              fontEncoding, &i, charinfo);
 | 
						|
    n = (unsigned int) i;
 | 
						|
 | 
						|
    if (n != 0) {
 | 
						|
        damageDamageChars(pDrawable, pGC->font, x + pDrawable->x,
 | 
						|
                          y + pDrawable->y, n, charinfo, imageblt,
 | 
						|
                          pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    free(charinfo);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
damagePolyText8(DrawablePtr pDrawable,
 | 
						|
                GCPtr pGC, int x, int y, int count, char *chars)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    damageText(pDrawable, pGC, x, y, (unsigned long) count, chars, Linear8Bit,
 | 
						|
               TT_POLY8);
 | 
						|
    x = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
damagePolyText16(DrawablePtr pDrawable,
 | 
						|
                 GCPtr pGC, int x, int y, int count, unsigned short *chars)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    damageText(pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
 | 
						|
               FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
 | 
						|
               TT_POLY16);
 | 
						|
    x = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
    return x;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageImageText8(DrawablePtr pDrawable,
 | 
						|
                 GCPtr pGC, int x, int y, int count, char *chars)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    damageText(pDrawable, pGC, x, y, (unsigned long) count, chars, Linear8Bit,
 | 
						|
               TT_IMAGE8);
 | 
						|
    (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageImageText16(DrawablePtr pDrawable,
 | 
						|
                  GCPtr pGC, int x, int y, int count, unsigned short *chars)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    damageText(pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
 | 
						|
               FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
 | 
						|
               TT_IMAGE16);
 | 
						|
    (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageImageGlyphBlt(DrawablePtr pDrawable,
 | 
						|
                    GCPtr pGC,
 | 
						|
                    int x,
 | 
						|
                    int y,
 | 
						|
                    unsigned int nglyph, CharInfoPtr * ppci, void *pglyphBase)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    damageDamageChars(pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
 | 
						|
                      nglyph, ppci, TRUE, pGC->subWindowMode);
 | 
						|
    (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePolyGlyphBlt(DrawablePtr pDrawable,
 | 
						|
                   GCPtr pGC,
 | 
						|
                   int x,
 | 
						|
                   int y,
 | 
						|
                   unsigned int nglyph, CharInfoPtr * ppci, void *pglyphBase)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    damageDamageChars(pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y,
 | 
						|
                      nglyph, ppci, FALSE, pGC->subWindowMode);
 | 
						|
    (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damagePushPixels(GCPtr pGC,
 | 
						|
                 PixmapPtr pBitMap,
 | 
						|
                 DrawablePtr pDrawable, int dx, int dy, int xOrg, int yOrg)
 | 
						|
{
 | 
						|
    DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 | 
						|
    if (checkGCDamage(pDrawable, pGC)) {
 | 
						|
        BoxRec box;
 | 
						|
 | 
						|
        box.x1 = xOrg;
 | 
						|
        box.y1 = yOrg;
 | 
						|
 | 
						|
        if (!pGC->miTranslate) {
 | 
						|
            box.x1 += pDrawable->x;
 | 
						|
            box.y1 += pDrawable->y;
 | 
						|
        }
 | 
						|
 | 
						|
        box.x2 = box.x1 + dx;
 | 
						|
        box.y2 = box.y1 + dy;
 | 
						|
 | 
						|
        TRIM_BOX(box, pGC);
 | 
						|
        if (BOX_NOT_EMPTY(box))
 | 
						|
            damageDamageBox(pDrawable, &box, pGC->subWindowMode);
 | 
						|
    }
 | 
						|
    (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg);
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
    DAMAGE_GC_OP_EPILOGUE(pGC, pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageRemoveDamage(DamagePtr * pPrev, DamagePtr pDamage)
 | 
						|
{
 | 
						|
    while (*pPrev) {
 | 
						|
        if (*pPrev == pDamage) {
 | 
						|
            *pPrev = pDamage->pNext;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        pPrev = &(*pPrev)->pNext;
 | 
						|
    }
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
    ErrorF("Damage not on list\n");
 | 
						|
    OsAbort();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageInsertDamage(DamagePtr * pPrev, DamagePtr pDamage)
 | 
						|
{
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
    DamagePtr pOld;
 | 
						|
 | 
						|
    for (pOld = *pPrev; pOld; pOld = pOld->pNext)
 | 
						|
        if (pOld == pDamage) {
 | 
						|
            ErrorF("Damage already on list\n");
 | 
						|
            OsAbort();
 | 
						|
        }
 | 
						|
#endif
 | 
						|
    pDamage->pNext = *pPrev;
 | 
						|
    *pPrev = pDamage;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
damageDestroyPixmap(PixmapPtr pPixmap)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pPixmap->drawable.pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if (pPixmap->refcnt == 1) {
 | 
						|
        DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
 | 
						|
        DamagePtr pDamage;
 | 
						|
 | 
						|
        while ((pDamage = *pPrev)) {
 | 
						|
            damageRemoveDamage(pPrev, pDamage);
 | 
						|
            if (!pDamage->isWindow)
 | 
						|
                DamageDestroy(pDamage);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, pScreen, DestroyPixmap);
 | 
						|
    (*pScreen->DestroyPixmap) (pPixmap);
 | 
						|
    wrap(pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
damageCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWindow->drawable.pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if (getWindowDamage(pWindow)) {
 | 
						|
        int dx = pWindow->drawable.x - ptOldOrg.x;
 | 
						|
        int dy = pWindow->drawable.y - ptOldOrg.y;
 | 
						|
 | 
						|
        /*
 | 
						|
         * The region comes in source relative, but the damage occurs
 | 
						|
         * at the destination location.  Translate back and forth.
 | 
						|
         */
 | 
						|
        RegionTranslate(prgnSrc, dx, dy);
 | 
						|
        damageRegionAppend(&pWindow->drawable, prgnSrc, FALSE, -1);
 | 
						|
        RegionTranslate(prgnSrc, -dx, -dy);
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, pScreen, CopyWindow);
 | 
						|
    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
 | 
						|
    damageRegionProcessPending(&pWindow->drawable);
 | 
						|
    wrap(pScrPriv, pScreen, CopyWindow, damageCopyWindow);
 | 
						|
}
 | 
						|
 | 
						|
static GCOps damageGCOps = {
 | 
						|
    damageFillSpans, damageSetSpans,
 | 
						|
    damagePutImage, damageCopyArea,
 | 
						|
    damageCopyPlane, damagePolyPoint,
 | 
						|
    damagePolylines, damagePolySegment,
 | 
						|
    damagePolyRectangle, damagePolyArc,
 | 
						|
    damageFillPolygon, damagePolyFillRect,
 | 
						|
    damagePolyFillArc, damagePolyText8,
 | 
						|
    damagePolyText16, damageImageText8,
 | 
						|
    damageImageText16, damageImageGlyphBlt,
 | 
						|
    damagePolyGlyphBlt, damagePushPixels,
 | 
						|
};
 | 
						|
 | 
						|
static void
 | 
						|
damageSetWindowPixmap(WindowPtr pWindow, PixmapPtr pPixmap)
 | 
						|
{
 | 
						|
    DamagePtr pDamage;
 | 
						|
    ScreenPtr pScreen = pWindow->drawable.pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if ((pDamage = damageGetWinPriv(pWindow))) {
 | 
						|
        PixmapPtr pOldPixmap = (*pScreen->GetWindowPixmap) (pWindow);
 | 
						|
        DamagePtr *pPrev = getPixmapDamageRef(pOldPixmap);
 | 
						|
 | 
						|
        while (pDamage) {
 | 
						|
            damageRemoveDamage(pPrev, pDamage);
 | 
						|
            pDamage = pDamage->pNextWin;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, pScreen, SetWindowPixmap);
 | 
						|
    (*pScreen->SetWindowPixmap) (pWindow, pPixmap);
 | 
						|
    wrap(pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
 | 
						|
    if ((pDamage = damageGetWinPriv(pWindow))) {
 | 
						|
        DamagePtr *pPrev = getPixmapDamageRef(pPixmap);
 | 
						|
 | 
						|
        while (pDamage) {
 | 
						|
            damageInsertDamage(pPrev, pDamage);
 | 
						|
            pDamage = pDamage->pNextWin;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
damageDestroyWindow(WindowPtr pWindow)
 | 
						|
{
 | 
						|
    DamagePtr pDamage;
 | 
						|
    ScreenPtr pScreen = pWindow->drawable.pScreen;
 | 
						|
    Bool ret;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    while ((pDamage = damageGetWinPriv(pWindow))) {
 | 
						|
        DamageDestroy(pDamage);
 | 
						|
    }
 | 
						|
    unwrap(pScrPriv, pScreen, DestroyWindow);
 | 
						|
    ret = (*pScreen->DestroyWindow) (pWindow);
 | 
						|
    wrap(pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
damageCloseScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    unwrap(pScrPriv, pScreen, DestroyPixmap);
 | 
						|
    unwrap(pScrPriv, pScreen, CreateGC);
 | 
						|
    unwrap(pScrPriv, pScreen, CopyWindow);
 | 
						|
    unwrap(pScrPriv, pScreen, CloseScreen);
 | 
						|
    free(pScrPriv);
 | 
						|
    return (*pScreen->CloseScreen) (pScreen);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Default implementations of the damage management functions.
 | 
						|
 */
 | 
						|
void
 | 
						|
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
 | 
						|
miDamageDestroy(DamagePtr pDamage)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Public functions for consumption outside this file.
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
DamageSetup(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    DamageScrPrivPtr pScrPriv;
 | 
						|
    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
 | 
						|
 | 
						|
    const DamageScreenFuncsRec miFuncs = {
 | 
						|
        miDamageCreate, miDamageRegister, miDamageUnregister, miDamageDestroy
 | 
						|
    };
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&damageScrPrivateKeyRec, PRIVATE_SCREEN, 0))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (dixLookupPrivate(&pScreen->devPrivates, damageScrPrivateKey))
 | 
						|
        return TRUE;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey
 | 
						|
        (&damageGCPrivateKeyRec, PRIVATE_GC, sizeof(DamageGCPrivRec)))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&damagePixPrivateKeyRec, PRIVATE_PIXMAP, 0))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&damageWinPrivateKeyRec, PRIVATE_WINDOW, 0))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    pScrPriv = malloc(sizeof(DamageScrPrivRec));
 | 
						|
    if (!pScrPriv)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    pScrPriv->internalLevel = 0;
 | 
						|
    pScrPriv->pScreenDamage = 0;
 | 
						|
 | 
						|
    wrap(pScrPriv, pScreen, DestroyPixmap, damageDestroyPixmap);
 | 
						|
    wrap(pScrPriv, pScreen, CreateGC, damageCreateGC);
 | 
						|
    wrap(pScrPriv, pScreen, DestroyWindow, damageDestroyWindow);
 | 
						|
    wrap(pScrPriv, pScreen, SetWindowPixmap, damageSetWindowPixmap);
 | 
						|
    wrap(pScrPriv, pScreen, CopyWindow, damageCopyWindow);
 | 
						|
    wrap(pScrPriv, pScreen, CloseScreen, damageCloseScreen);
 | 
						|
    if (ps) {
 | 
						|
        wrap(pScrPriv, ps, Glyphs, damageGlyphs);
 | 
						|
        wrap(pScrPriv, ps, Composite, damageComposite);
 | 
						|
        wrap(pScrPriv, ps, AddTraps, damageAddTraps);
 | 
						|
    }
 | 
						|
 | 
						|
    pScrPriv->funcs = miFuncs;
 | 
						|
 | 
						|
    dixSetPrivate(&pScreen->devPrivates, damageScrPrivateKey, pScrPriv);
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
DamagePtr
 | 
						|
DamageCreate(DamageReportFunc damageReport,
 | 
						|
             DamageDestroyFunc damageDestroy,
 | 
						|
             DamageReportLevel damageLevel,
 | 
						|
             Bool isInternal, ScreenPtr pScreen, void *closure)
 | 
						|
{
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
    DamagePtr pDamage;
 | 
						|
 | 
						|
    pDamage = dixAllocateObjectWithPrivates(DamageRec, PRIVATE_DAMAGE);
 | 
						|
    if (!pDamage)
 | 
						|
        return 0;
 | 
						|
    pDamage->pNext = 0;
 | 
						|
    pDamage->pNextWin = 0;
 | 
						|
    RegionNull(&pDamage->damage);
 | 
						|
    RegionNull(&pDamage->pendingDamage);
 | 
						|
 | 
						|
    pDamage->damageLevel = damageLevel;
 | 
						|
    pDamage->isInternal = isInternal;
 | 
						|
    pDamage->closure = closure;
 | 
						|
    pDamage->isWindow = FALSE;
 | 
						|
    pDamage->pDrawable = 0;
 | 
						|
    pDamage->reportAfter = FALSE;
 | 
						|
 | 
						|
    pDamage->damageReport = damageReport;
 | 
						|
    pDamage->damageDestroy = damageDestroy;
 | 
						|
    pDamage->pScreen = pScreen;
 | 
						|
 | 
						|
    (*pScrPriv->funcs.Create) (pDamage);
 | 
						|
 | 
						|
    return pDamage;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageRegister(DrawablePtr pDrawable, DamagePtr pDamage)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDrawable->pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
    if (pDrawable->pScreen != pDamage->pScreen) {
 | 
						|
        ErrorF("DamageRegister called with mismatched screens\n");
 | 
						|
        OsAbort();
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    if (pDrawable->type == DRAWABLE_WINDOW) {
 | 
						|
        WindowPtr pWindow = (WindowPtr) pDrawable;
 | 
						|
 | 
						|
        winDamageRef(pWindow);
 | 
						|
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
        DamagePtr pOld;
 | 
						|
 | 
						|
        for (pOld = *pPrev; pOld; pOld = pOld->pNextWin)
 | 
						|
            if (pOld == pDamage) {
 | 
						|
                ErrorF("Damage already on window list\n");
 | 
						|
                OsAbort();
 | 
						|
            }
 | 
						|
#endif
 | 
						|
        pDamage->pNextWin = *pPrev;
 | 
						|
        *pPrev = pDamage;
 | 
						|
        pDamage->isWindow = TRUE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
        pDamage->isWindow = FALSE;
 | 
						|
    pDamage->pDrawable = pDrawable;
 | 
						|
    damageInsertDamage(getDrawableDamageRef(pDrawable), pDamage);
 | 
						|
    (*pScrPriv->funcs.Register) (pDrawable, pDamage);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageDrawInternal(ScreenPtr pScreen, Bool enable)
 | 
						|
{
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    pScrPriv->internalLevel += enable ? 1 : -1;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageUnregister(DamagePtr pDamage)
 | 
						|
{
 | 
						|
    DrawablePtr pDrawable = pDamage->pDrawable;
 | 
						|
    ScreenPtr pScreen = pDrawable->pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    (*pScrPriv->funcs.Unregister) (pDrawable, pDamage);
 | 
						|
 | 
						|
    if (pDrawable->type == DRAWABLE_WINDOW) {
 | 
						|
        WindowPtr pWindow = (WindowPtr) pDrawable;
 | 
						|
 | 
						|
        winDamageRef(pWindow);
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
        int found = 0;
 | 
						|
#endif
 | 
						|
 | 
						|
        while (*pPrev) {
 | 
						|
            if (*pPrev == pDamage) {
 | 
						|
                *pPrev = pDamage->pNextWin;
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
                found = 1;
 | 
						|
#endif
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            pPrev = &(*pPrev)->pNextWin;
 | 
						|
        }
 | 
						|
#if DAMAGE_VALIDATE_ENABLE
 | 
						|
        if (!found) {
 | 
						|
            ErrorF("Damage not on window list\n");
 | 
						|
            OsAbort();
 | 
						|
        }
 | 
						|
#endif
 | 
						|
    }
 | 
						|
    pDamage->pDrawable = 0;
 | 
						|
    damageRemoveDamage(getDrawableDamageRef(pDrawable), pDamage);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageDestroy(DamagePtr pDamage)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pDamage->pScreen;
 | 
						|
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
 | 
						|
    if (pDamage->pDrawable)
 | 
						|
        DamageUnregister(pDamage);
 | 
						|
 | 
						|
    if (pDamage->damageDestroy)
 | 
						|
        (*pDamage->damageDestroy) (pDamage, pDamage->closure);
 | 
						|
    (*pScrPriv->funcs.Destroy) (pDamage);
 | 
						|
    RegionUninit(&pDamage->damage);
 | 
						|
    RegionUninit(&pDamage->pendingDamage);
 | 
						|
    dixFreeObjectWithPrivates(pDamage, PRIVATE_DAMAGE);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
DamageSubtract(DamagePtr pDamage, const RegionPtr pRegion)
 | 
						|
{
 | 
						|
    RegionPtr pClip;
 | 
						|
    RegionRec pixmapClip;
 | 
						|
    DrawablePtr pDrawable = pDamage->pDrawable;
 | 
						|
 | 
						|
    RegionSubtract(&pDamage->damage, &pDamage->damage, pRegion);
 | 
						|
    if (pDrawable) {
 | 
						|
        if (pDrawable->type == DRAWABLE_WINDOW)
 | 
						|
            pClip = &((WindowPtr) pDrawable)->borderClip;
 | 
						|
        else {
 | 
						|
            BoxRec box;
 | 
						|
 | 
						|
            box.x1 = pDrawable->x;
 | 
						|
            box.y1 = pDrawable->y;
 | 
						|
            box.x2 = pDrawable->x + pDrawable->width;
 | 
						|
            box.y2 = pDrawable->y + pDrawable->height;
 | 
						|
            RegionInit(&pixmapClip, &box, 1);
 | 
						|
            pClip = &pixmapClip;
 | 
						|
        }
 | 
						|
        RegionTranslate(&pDamage->damage, pDrawable->x, pDrawable->y);
 | 
						|
        RegionIntersect(&pDamage->damage, &pDamage->damage, pClip);
 | 
						|
        RegionTranslate(&pDamage->damage, -pDrawable->x, -pDrawable->y);
 | 
						|
        if (pDrawable->type != DRAWABLE_WINDOW)
 | 
						|
            RegionUninit(&pixmapClip);
 | 
						|
    }
 | 
						|
    return RegionNotEmpty(&pDamage->damage);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageEmpty(DamagePtr pDamage)
 | 
						|
{
 | 
						|
    RegionEmpty(&pDamage->damage);
 | 
						|
}
 | 
						|
 | 
						|
RegionPtr
 | 
						|
DamageRegion(DamagePtr pDamage)
 | 
						|
{
 | 
						|
    return &pDamage->damage;
 | 
						|
}
 | 
						|
 | 
						|
RegionPtr
 | 
						|
DamagePendingRegion(DamagePtr pDamage)
 | 
						|
{
 | 
						|
    return &pDamage->pendingDamage;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageRegionAppend(DrawablePtr pDrawable, RegionPtr pRegion)
 | 
						|
{
 | 
						|
    damageRegionAppend(pDrawable, pRegion, FALSE, -1);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageRegionProcessPending(DrawablePtr pDrawable)
 | 
						|
{
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
/* This call is very odd, i'm leaving it intact for API sake, but please don't use it. */
 | 
						|
void
 | 
						|
DamageDamageRegion(DrawablePtr pDrawable, RegionPtr pRegion)
 | 
						|
{
 | 
						|
    damageRegionAppend(pDrawable, pRegion, FALSE, -1);
 | 
						|
 | 
						|
    /* Go back and report this damage for DamagePtrs with reportAfter set, since
 | 
						|
     * this call isn't part of an in-progress drawing op in the call chain and
 | 
						|
     * the DDX probably just wants to know about it right away.
 | 
						|
     */
 | 
						|
    damageRegionProcessPending(pDrawable);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageSetReportAfterOp(DamagePtr pDamage, Bool reportAfter)
 | 
						|
{
 | 
						|
    pDamage->reportAfter = reportAfter;
 | 
						|
}
 | 
						|
 | 
						|
DamageScreenFuncsPtr
 | 
						|
DamageGetScreenFuncs(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    damageScrPriv(pScreen);
 | 
						|
    return &pScrPriv->funcs;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DamageReportDamage(DamagePtr pDamage, RegionPtr pDamageRegion)
 | 
						|
{
 | 
						|
    BoxRec tmpBox;
 | 
						|
    RegionRec tmpRegion;
 | 
						|
    Bool was_empty;
 | 
						|
 | 
						|
    switch (pDamage->damageLevel) {
 | 
						|
    case DamageReportRawRegion:
 | 
						|
        RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
 | 
						|
        (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure);
 | 
						|
        break;
 | 
						|
    case DamageReportDeltaRegion:
 | 
						|
        RegionNull(&tmpRegion);
 | 
						|
        RegionSubtract(&tmpRegion, pDamageRegion, &pDamage->damage);
 | 
						|
        if (RegionNotEmpty(&tmpRegion)) {
 | 
						|
            RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
 | 
						|
            (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure);
 | 
						|
        }
 | 
						|
        RegionUninit(&tmpRegion);
 | 
						|
        break;
 | 
						|
    case DamageReportBoundingBox:
 | 
						|
        tmpBox = *RegionExtents(&pDamage->damage);
 | 
						|
        RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
 | 
						|
        if (!BOX_SAME(&tmpBox, RegionExtents(&pDamage->damage))) {
 | 
						|
            (*pDamage->damageReport) (pDamage, &pDamage->damage,
 | 
						|
                                      pDamage->closure);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    case DamageReportNonEmpty:
 | 
						|
        was_empty = !RegionNotEmpty(&pDamage->damage);
 | 
						|
        RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
 | 
						|
        if (was_empty && RegionNotEmpty(&pDamage->damage)) {
 | 
						|
            (*pDamage->damageReport) (pDamage, &pDamage->damage,
 | 
						|
                                      pDamage->closure);
 | 
						|
        }
 | 
						|
        break;
 | 
						|
    case DamageReportNone:
 | 
						|
        RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion);
 | 
						|
        break;
 | 
						|
    }
 | 
						|
}
 |