exa: Use damage to optimise away useless copies.

This commit is contained in:
Maarten Maathuis 2009-08-02 02:35:46 +02:00
parent 03ecb164f2
commit 9d2a7128d3
2 changed files with 69 additions and 8 deletions

View File

@ -35,13 +35,29 @@ static void
exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch, exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch,
CARD8 *dst, int dst_pitch) CARD8 *dst, int dst_pitch)
{ {
int i; ExaPixmapPriv(pPixmap);
RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
int bytes, nbox;
BoxPtr pbox;
for (i = pPixmap->drawable.height; i; i--) { pbox = REGION_RECTS(damage);
memcpy (dst, src, min(src_pitch, dst_pitch)); nbox = REGION_NUM_RECTS(damage);
while (nbox--) {
bytes = (pbox->x2 - pbox->x1) * cpp;
src += pbox->y1 * src_pitch + pbox->x1 * cpp;
dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
for (i = pbox->y2 - pbox->y1; i; i--) {
memcpy (dst, src, bytes);
src += src_pitch; src += src_pitch;
dst += dst_pitch; dst += dst_pitch;
} }
pbox++;
}
} }
void void
@ -50,12 +66,15 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
ScreenPtr pScreen = pPixmap->drawable.pScreen; ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv(pScreen); ExaScreenPriv(pScreen);
ExaPixmapPriv(pPixmap); ExaPixmapPriv(pPixmap);
RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
void *sys_buffer = pExaPixmap->sys_ptr; void *sys_buffer = pExaPixmap->sys_ptr;
int w = pPixmap->drawable.width, h = pPixmap->drawable.height; int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel; int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
int usage_hint = pPixmap->usage_hint; int usage_hint = pPixmap->usage_hint;
int sys_pitch = pExaPixmap->sys_pitch; int sys_pitch = pExaPixmap->sys_pitch;
int paddedWidth = sys_pitch; int paddedWidth = sys_pitch;
int nbox;
BoxPtr pbox;
/* Already done. */ /* Already done. */
if (pExaPixmap->driverPriv) if (pExaPixmap->driverPriv)
@ -93,7 +112,17 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
if (!pExaScr->info->UploadToScreen) if (!pExaScr->info->UploadToScreen)
goto fallback; goto fallback;
if (pExaScr->info->UploadToScreen(pPixmap, 0, 0, w, h, sys_buffer, sys_pitch)) pbox = REGION_RECTS(damage);
nbox = REGION_NUM_RECTS(damage);
while (nbox--) {
if (!pExaScr->info->UploadToScreen(pPixmap, pbox->x1, pbox->y1, pbox->x2 - pbox->x1,
pbox->y2 - pbox->y1, (char *) (sys_buffer) + pbox->y1 * sys_pitch + pbox->x1 * (bpp / 8), sys_pitch))
goto fallback;
pbox++;
}
goto finish; goto finish;
fallback: fallback:
@ -104,6 +133,13 @@ fallback:
finish: finish:
free(sys_buffer); free(sys_buffer);
/* We no longer need this. */
if (pExaPixmap->pDamage) {
DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
DamageDestroy(pExaPixmap->pDamage);
pExaPixmap->pDamage = NULL;
}
} }
void void

View File

@ -114,6 +114,23 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
/* We want to be able to copy the pixmap to driver memory later on. */ /* We want to be able to copy the pixmap to driver memory later on. */
pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
/* Set up damage tracking */
pExaPixmap->pDamage = DamageCreate (NULL, NULL,
DamageReportNone, TRUE,
pScreen, pPixmap);
if (pExaPixmap->pDamage == NULL) {
swap(pExaScr, pScreen, DestroyPixmap);
pScreen->DestroyPixmap (pPixmap);
swap(pExaScr, pScreen, DestroyPixmap);
return NULL;
}
DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
/* This ensures that pending damage reflects the current operation. */
/* This is used by exa to optimize migration. */
DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
} }
return pPixmap; return pPixmap;
@ -136,8 +153,16 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
if (pExaPixmap) { if (pExaPixmap) {
if (pPixData) { if (pPixData) {
if (!exaPixmapIsPinned(pPixmap)) if (!exaPixmapIsPinned(pPixmap)) {
free(pExaPixmap->sys_ptr); free(pExaPixmap->sys_ptr);
/* We no longer need this. */
if (pExaPixmap->pDamage) {
DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
DamageDestroy(pExaPixmap->pDamage);
pExaPixmap->pDamage = NULL;
}
}
pExaPixmap->sys_ptr = pPixData; pExaPixmap->sys_ptr = pPixData;
} }