📄 damage.c
字号:
/* * $Id: damage.c,v 1.1.2.1 2005/09/09 16:09:44 alanh Exp $ * * 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_CONFIG_H#include <config.h>#endif#include <X11/X.h>#include "scrnintstr.h"#include "windowstr.h"#include "font.h"#include "dixfontstr.h"#include "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_DEBUG_ENABLE 0#if DAMAGE_DEBUG_ENABLE#define DAMAGE_DEBUG(x) ErrorF x#else#define DAMAGE_DEBUG(x)#endifstatic PixmapPtrGetDrawablePixmap (DrawablePtr pDrawable){ ScreenPtr pScreen = pDrawable->pScreen; PixmapPtr pPixmap; if (pDrawable->type == DRAWABLE_WINDOW) { pPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) pDrawable); if (!pPixmap) pPixmap = (*pScreen->GetScreenPixmap) (pDrawable->pScreen); } else pPixmap = (PixmapPtr) pDrawable; return pPixmap;}#define pixmapDamage(pPixmap) damagePixPriv(pPixmap)#define drawableDamage(pDrawable) damagePixPriv(GetDrawablePixmap(pDrawable))#define windowDamage(pWin) drawableDamage(&(pWin)->drawable)#define getDrawableDamage(pDrawable) damageGetPixPriv(GetDrawablePixmap(pDrawable))#define getWindowDamage(pWin) getDrawableDamage(&(pWin)->drawable)#define pixDamageRef(pPixmap) \ DamagePtr *pPrev = (DamagePtr *) \ &(pPixmap->devPrivates[damagePixPrivateIndex].ptr)#define winDamageRef(pWindow) \ DamagePtr *pPrev = (DamagePtr *) \ &(pWindow->devPrivates[damageWinPrivateIndex].ptr)#if DAMAGE_DEBUG_ENABLEstatic void_damageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, char *where)#define damageDamageRegion(d,r,c) _damageDamageRegion(d,r,c,__FUNCTION__)#elsestatic voiddamageDamageRegion (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip)#endif{ damageScrPriv(pDrawable->pScreen); drawableDamage(pDrawable); DamagePtr pNext; RegionPtr pClip; RegionRec clippedRec; RegionPtr pDamageRegion; RegionRec pixClip; Bool was_empty; RegionRec tmpRegion; BoxRec tmpBox; int draw_x, draw_y;#ifdef COMPOSITE int screen_x = 0, screen_y = 0;#endif /* short circuit for empty regions */ if (!REGION_NOTEMPTY(pScreen, 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; screen_y = ((PixmapPtr) pDrawable)->screen_y; } if (screen_x || screen_y) REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y);#endif REGION_INIT (pScreen, &clippedRec, NullBox, 0); 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) { DAMAGE_DEBUG (("damage while window unrealized\n")); 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 (pDamage->pDrawable->type != DRAWABLE_WINDOW) { 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) pClip = &((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; REGION_INIT(pScreen, &pixClip, &box, 1); pClip = &pixClip; } REGION_INTERSECT (pScreen, pDamageRegion, pRegion, pClip); /* * Short circuit empty results */ if (!REGION_NOTEMPTY(pScreen, pDamageRegion)) continue; } DAMAGE_DEBUG (("%s %d x %d +%d +%d\n", where, pDamageRegion->extents.x2 - pDamageRegion->extents.x1, pDamageRegion->extents.y2 - pDamageRegion->extents.y1, pDamageRegion->extents.x1, pDamageRegion->extents.y1)); /* * Move region to target coordinate space */ if (draw_x || draw_y) REGION_TRANSLATE (pScreen, pDamageRegion, -draw_x, -draw_y); switch (pDamage->damageLevel) { case DamageReportRawRegion: (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); break; case DamageReportDeltaRegion: REGION_INIT (pScreen, &tmpRegion, NullBox, 0); REGION_SUBTRACT (pScreen, &tmpRegion, pDamageRegion, &pDamage->damage); if (REGION_NOTEMPTY (pScreen, &tmpRegion)) { REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pDamageRegion); (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); } break; case DamageReportBoundingBox: tmpBox = *REGION_EXTENTS (pScreen, &pDamage->damage); REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pDamageRegion); if (!BOX_SAME (&tmpBox, REGION_EXTENTS (pScreen, &pDamage->damage))) (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); break; case DamageReportNonEmpty: was_empty = !REGION_NOTEMPTY(pScreen, &pDamage->damage); REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pDamageRegion); if (was_empty && REGION_NOTEMPTY(pScreen, &pDamage->damage)) (*pDamage->damageReport) (pDamage, &pDamage->damage, pDamage->closure); break; case DamageReportNone: REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pDamageRegion); break; } /* * translate original region back */ if (pDamageRegion == pRegion && (draw_x || draw_y)) REGION_TRANSLATE (pScreen, pDamageRegion, draw_x, draw_y); }#ifdef COMPOSITE if (screen_x || screen_y) REGION_TRANSLATE (pScreen, pRegion, -screen_x, -screen_y);#endif REGION_UNINIT (pScreen, &clippedRec);}#if DAMAGE_DEBUG_ENABLE#define damageDamageBox(d,b) _damageDamageBox(d,b,__FUNCTION__)static void_damageDamageBox (DrawablePtr pDrawable, BoxPtr pBox, char *where)#elsestatic voiddamageDamageBox (DrawablePtr pDrawable, BoxPtr pBox)#endif{ RegionRec region; REGION_INIT (pDrawable->pScreen, ®ion, pBox, 1);#if DAMAGE_DEBUG_ENABLE _damageDamageRegion (pDrawable, ®ion, TRUE, where);#else damageDamageRegion (pDrawable, ®ion, TRUE);#endif REGION_UNINIT (pDrawable->pScreen, ®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, pointer, int);static void damageDestroyClip(GCPtr);static void damageCopyClip(GCPtr, GCPtr);GCFuncs damageGCFuncs = { damageValidateGC, damageChangeGC, damageCopyGC, damageDestroyGC, damageChangeClip, damageDestroyClip, damageCopyClip};extern GCOps damageGCOps;static BooldamageCreateGC(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;}#if NOTUSEDstatic voiddamageWrapGC (GCPtr pGC){ damageGCPriv(pGC); pGCPriv->ops = NULL; pGCPriv->funcs = pGC->funcs; pGC->funcs = &damageGCFuncs;}static voiddamageUnwrapGC (GCPtr pGC){ damageGCPriv(pGC); pGC->funcs = pGCPriv->funcs; if (pGCPriv->ops) pGC->ops = pGCPriv->ops;}#endif#define DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable) \ damageGCPriv(pGC); \ 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 voiddamageValidateGC(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 voiddamageDestroyGC(GCPtr pGC){ DAMAGE_GC_FUNC_PROLOGUE (pGC); (*pGC->funcs->DestroyGC)(pGC); DAMAGE_GC_FUNC_EPILOGUE (pGC);}static voiddamageChangeGC (GCPtr pGC, unsigned long mask){ DAMAGE_GC_FUNC_PROLOGUE (pGC); (*pGC->funcs->ChangeGC) (pGC, mask); DAMAGE_GC_FUNC_EPILOGUE (pGC);}static voiddamageCopyGC (GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst){ DAMAGE_GC_FUNC_PROLOGUE (pGCDst); (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); DAMAGE_GC_FUNC_EPILOGUE (pGCDst);}static voiddamageChangeClip (GCPtr pGC, int type, pointer pvalue, int nrects){ DAMAGE_GC_FUNC_PROLOGUE (pGC); (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); DAMAGE_GC_FUNC_EPILOGUE (pGC);}static voiddamageCopyClip(GCPtr pgcDst, GCPtr pgcSrc){ DAMAGE_GC_FUNC_PROLOGUE (pgcDst); (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); DAMAGE_GC_FUNC_EPILOGUE (pgcDst);}static voiddamageDestroyClip(GCPtr pGC){ DAMAGE_GC_FUNC_PROLOGUE (pGC); (* pGC->funcs->DestroyClip)(pGC); DAMAGE_GC_FUNC_EPILOGUE (pGC);}#define TRIM_BOX(box, pGC) { \ 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) && \ REGION_NOTEMPTY(pScreen, g->pCompositeClip))#ifdef RENDER#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) && \ REGION_NOTEMPTY(pScreen, p->pCompositeClip))static voiddamageComposite (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); } unwrap (pScrPriv, ps, Composite); (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); wrap (pScrPriv, ps, Composite, damageComposite);}static voiddamageGlyphs (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); } unwrap (pScrPriv, ps, Glyphs); (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); wrap (pScrPriv, ps, Glyphs, damageGlyphs);}#endif/**********************************************************/static voiddamageFillSpans(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->ops->FillSpans)(pDrawable, pGC, npt, ppt, pwidth, fSorted);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -