--- xorg-server-1.2.99.0/exa/exa.c.exa2~ 2006-11-05 14:35:47.000000000 +0100 +++ xorg-server-1.2.99.0/exa/exa.c 2006-11-05 14:37:20.000000000 +0100 @@ -122,13 +122,19 @@ * optimizations in pixmap migration when no changes have occurred. */ void -exaDrawableDirty (DrawablePtr pDrawable) +exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2) { ExaPixmapPrivPtr pExaPixmap; + RegionPtr pDamageReg; + RegionRec region = { { x1, y2, x2, y2 }, NULL }; pExaPixmap = ExaGetPixmapPriv(exaGetDrawablePixmap (pDrawable)); - if (pExaPixmap != NULL) - pExaPixmap->dirty = TRUE; + + if (!pExaPixmap || x1 >= x2 || y1 >= y2) + return; + + pDamageReg = DamageRegion(pExaPixmap->pDamage); + REGION_UNION(pScreen, pDamageReg, pDamageReg, ®ion); } static Bool @@ -149,6 +155,7 @@ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; pPixmap->devKind = pExaPixmap->sys_pitch; } + REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validReg); } return fbDestroyPixmap (pPixmap); } @@ -216,7 +223,20 @@ return NULL; } - pExaPixmap->dirty = FALSE; + /* Set up damage tracking */ + pExaPixmap->pDamage = DamageCreate (NULL, NULL, DamageReportNone, TRUE, + pScreen, pPixmap); + + if (pExaPixmap->pDamage == NULL) { + fbDestroyPixmap (pPixmap); + return NULL; + } + + DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage); + DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE); + + /* None of the pixmap bits are valid initially */ + REGION_NULL(pScreen, &pExaPixmap->validReg); return pPixmap; } @@ -334,8 +354,7 @@ /** * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. * - * It deals with marking drawables as dirty, and calling the driver's - * FinishAccess() only if necessary. + * It deals with calling the driver's FinishAccess() only if necessary. */ void exaFinishAccess(DrawablePtr pDrawable, int index) @@ -345,9 +364,6 @@ PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; - if (index == EXA_PREPARE_DEST) - exaDrawableDirty (pDrawable); - pPixmap = exaGetDrawablePixmap (pDrawable); pExaPixmap = ExaGetPixmapPriv(pPixmap); @@ -373,7 +389,7 @@ * accelerated or may sync the card and fall back to fb. */ static void -exaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) +exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) { /* fbValidateGC will do direct access to pixmaps if the tiling has changed. * Preempt fbValidateGC by doing its work and masking the change out, so @@ -423,6 +439,9 @@ exaMoveOutPixmap(pGC->tile.pixmap); fbPadPixmap (pGC->tile.pixmap); exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_DEST); + exaDrawableDirty(&pGC->tile.pixmap->drawable, 0, 0, + pGC->tile.pixmap->drawable.width, + pGC->tile.pixmap->drawable.height); } /* Mask out the GCTile change notification, now that we've done FB's * job for it. --- xorg-server-1.2.99.0/exa/exa_accel.c.exa2~ 2006-07-20 22:27:47.000000000 +0200 +++ xorg-server-1.2.99.0/exa/exa_accel.c 2006-11-05 14:35:47.000000000 +0100 @@ -20,6 +20,11 @@ * 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. + * + * Authors: + * Eric Anholt + * Michel Dänzer + * */ #ifdef HAVE_DIX_CONFIG_H @@ -104,6 +109,9 @@ (*pExaScr->info->Solid) (pPixmap, fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, fullY1 + 1 + off_y); + exaDrawableDirty (pDrawable, + fullX1 + off_x, fullY1 + off_y, + fullX2 + off_x, fullY1 + 1 + off_y); } else { @@ -118,17 +126,20 @@ partX2 = pbox->x2; if (partX2 > fullX2) partX2 = fullX2; - if (partX2 > partX1) + if (partX2 > partX1) { (*pExaScr->info->Solid) (pPixmap, partX1 + off_x, fullY1 + off_y, partX2 + off_x, fullY1 + 1 + off_y); + exaDrawableDirty (pDrawable, + partX1 + off_x, fullY1 + off_y, + partX2 + off_x, fullY1 + 1 + off_y); + } } pbox++; } } } (*pExaScr->info->DoneSolid) (pPixmap); - exaDrawableDirty (pDrawable); exaMarkSync(pScreen); } @@ -222,8 +233,8 @@ exaFinishAccess(pDrawable, EXA_PREPARE_DEST); } + exaDrawableDirty(pDrawable, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } - exaDrawableDirty(pDrawable); return; @@ -351,11 +362,13 @@ dst_off_y + pbox->y1 + i, pbox->x2 - pbox->x1, 1); } + exaDrawableDirty(pDstDrawable, + dst_off_x + pbox->x1, dst_off_y + pbox->y1, + dst_off_x + pbox->x2, dst_off_y + pbox->y2); } if (dirsetup != 0) pExaScr->info->DoneCopy(pDstPixmap); exaMarkSync(pDstDrawable->pScreen); - exaDrawableDirty(pDstDrawable); return TRUE; } @@ -423,11 +436,13 @@ pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + exaDrawableDirty (pDstDrawable, + pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneCopy) (pDstPixmap); exaMarkSync(pDstDrawable->pScreen); - exaDrawableDirty (pDstDrawable); return; } @@ -442,6 +457,13 @@ bitplane, closure); exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); + while (nbox--) + { + exaDrawableDirty (pDstDrawable, + pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); + pbox++; + } } RegionPtr @@ -706,15 +728,18 @@ pbox++; - if (partX1 < partX2 && partY1 < partY2) + if (partX1 < partX2 && partY1 < partY2) { (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); + exaDrawableDirty (pDrawable, + partX1 + xoff, partY1 + yoff, + partX2 + xoff, partY2 + yoff); + } } } } (*pExaScr->info->DoneSolid) (pPixmap); - exaDrawableDirty (pDrawable); exaMarkSync(pDrawable->pScreen); } @@ -735,11 +760,15 @@ int xoff, yoff; int partX1, partX2, partY1, partY2; ExaMigrationRec pixmaps[1]; + Bool fallback = FALSE; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); - + + /* We need to initialize x/yoff for tracking damage in the fallback case */ + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (pExaScr->swappedOut || pDrawable->width > pExaScr->info->maxX || pDrawable->height > pExaScr->info->maxY) @@ -750,19 +779,19 @@ exaDoMigration (pixmaps, 1, TRUE); } - if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || + if (!pPixmap || !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) { fallback: EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); + fallback = TRUE; exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, fbAnd (GXcopy, fg, pm), fbXor (GXcopy, fg, pm)); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return; } for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); nbox--; @@ -790,12 +819,19 @@ if (partY2 <= partY1) continue; - (*pExaScr->info->Solid) (pPixmap, - partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); + if (!fallback) + (*pExaScr->info->Solid) (pPixmap, + partX1 + xoff, partY1 + yoff, + partX2 + xoff, partY2 + yoff); + exaDrawableDirty (pDrawable, + partX1 + xoff, partY1 + yoff, + partX2 + xoff, partY2 + yoff); } + + if (fallback) + return; + (*pExaScr->info->DoneSolid) (pPixmap); - exaDrawableDirty (pDrawable); exaMarkSync(pDrawable->pScreen); } @@ -928,6 +964,8 @@ gStride, 0); } + exaDrawableDirty(pDrawable, gx + dstXoff, gy + dstYoff, + gx + dstXoff + gWidth, gy + dstYoff + gHeight); } x += pci->metrics.characterWidth; } @@ -994,6 +1032,8 @@ PixmapPtr pPixmap; int xoff, yoff; ExaMigrationRec pixmaps[1]; + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; @@ -1011,19 +1051,18 @@ if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && (*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel)) { - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (pRegion); - while (nbox--) { (*pExaScr->info->Solid) (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, pBox->x2 + xoff, pBox->y2 + yoff); + exaDrawableDirty (pDrawable, + pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); } else { @@ -1034,6 +1073,13 @@ fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + while (nbox--) + { + exaDrawableDirty (pDrawable, + pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); + pBox++; + } } } @@ -1050,6 +1096,8 @@ int xoff, yoff; int tileWidth, tileHeight; ExaMigrationRec pixmaps[2]; + int nbox = REGION_NUM_RECTS (pRegion); + BoxPtr pBox = REGION_RECTS (pRegion); tileWidth = pTile->drawable.width; tileHeight = pTile->drawable.height; @@ -1069,6 +1117,9 @@ pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pTile; + /* We need to initialize x/yoff for tracking damage in the fallback case */ + pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (pDrawable->width > pExaScr->info->maxX || pDrawable->height > pExaScr->info->maxY || tileWidth > pExaScr->info->maxX || @@ -1080,7 +1131,6 @@ exaDoMigration (pixmaps, 2, TRUE); } - pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); if (!pPixmap) goto fallback; @@ -1090,9 +1140,6 @@ if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy, FB_ALLONES)) { - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (pRegion); - while (nbox--) { int height = pBox->y2 - pBox->y1; @@ -1127,11 +1174,12 @@ dstY += h; tileY = 0; } + exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneCopy) (pPixmap); exaMarkSync(pDrawable->pScreen); - exaDrawableDirty (pDrawable); return; } @@ -1144,6 +1192,12 @@ fbFillRegionTiled (pDrawable, pRegion, pTile); exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + while (nbox--) + { + exaDrawableDirty (pDrawable, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); + pBox++; + } } void --- xorg-server-1.2.99.0/exa/exa_migration.c.exa2~ 2006-07-20 22:27:47.000000000 +0200 +++ xorg-server-1.2.99.0/exa/exa_migration.c 2006-11-05 14:42:25.000000000 +0100 @@ -22,6 +22,7 @@ * * Authors: * Eric Anholt + * Michel Dänzer * */ @@ -58,6 +59,27 @@ } /** + * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys + * and exaCopyDirtyToFb both needed to do this loop. + */ +static void +exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch, + CARD8 *dst, int dst_pitch) + { + int i, cpp = pPixmap->drawable.bitsPerPixel / 8; + int 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; + dst += dst_pitch; + } +} + +/** * Returns TRUE if the pixmap is dirty (has been modified in its current * location compared to the other), or lacks a private for tracking * dirtiness. @@ -67,7 +89,8 @@ { ExaPixmapPriv (pPix); - return pExaPixmap == NULL || pExaPixmap->dirty == TRUE; + return pExaPixmap == NULL || + REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)); } /** @@ -98,43 +121,42 @@ { ExaScreenPriv (pPixmap->drawable.pScreen); ExaPixmapPriv (pPixmap); + RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage); CARD8 *save_ptr; int save_pitch; - - if (!pExaPixmap->dirty) - return; + BoxPtr pBox = REGION_RECTS(pRegion); + int nbox = REGION_NUM_RECTS(pRegion); save_ptr = pPixmap->devPrivate.ptr; save_pitch = pPixmap->devKind; pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; pPixmap->devKind = pExaPixmap->fb_pitch; - if (pExaScr->info->DownloadFromScreen == NULL || - !pExaScr->info->DownloadFromScreen (pPixmap, - 0, - 0, - pPixmap->drawable.width, - pPixmap->drawable.height, - pExaPixmap->sys_ptr, - pExaPixmap->sys_pitch)) - { - char *src, *dst; - int src_pitch, dst_pitch, i, bytes; - - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); - - dst = pExaPixmap->sys_ptr; - dst_pitch = pExaPixmap->sys_pitch; - src = pExaPixmap->fb_ptr; - src_pitch = pExaPixmap->fb_pitch; - bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch; - - for (i = 0; i < pPixmap->drawable.height; i++) { - memcpy (dst, src, bytes); - dst += dst_pitch; - src += src_pitch; + while (nbox--) { + pBox->x2 = min(pBox->x2, pPixmap->drawable.width); + pBox->y2 = min(pBox->y2, pPixmap->drawable.height); + + if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) + continue; + + if (pExaScr->info->DownloadFromScreen == NULL || + !pExaScr->info->DownloadFromScreen (pPixmap, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + pExaPixmap->sys_ptr + + pBox->y1 * pExaPixmap->sys_pitch + + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, + pExaPixmap->sys_pitch)) + { + exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); + exaMemcpyBox (pPixmap, pBox, + pExaPixmap->fb_ptr, pExaPixmap->fb_pitch, + pExaPixmap->sys_ptr, pExaPixmap->sys_pitch); + exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); } - exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); + + pBox++; } /* Make sure the bits have actually landed, since we don't necessarily sync @@ -145,7 +167,10 @@ pPixmap->devPrivate.ptr = save_ptr; pPixmap->devKind = save_pitch; - pExaPixmap->dirty = FALSE; + /* The previously damaged bits are now no longer damaged but valid */ + REGION_UNION(pPixmap->drawable.pScreen, + &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion); + DamageEmpty (pExaPixmap->pDamage); } /** @@ -158,49 +183,51 @@ { ExaScreenPriv (pPixmap->drawable.pScreen); ExaPixmapPriv (pPixmap); + RegionPtr pRegion = DamageRegion (pExaPixmap->pDamage); CARD8 *save_ptr; int save_pitch; - - if (!pExaPixmap->dirty) - return; + BoxPtr pBox = REGION_RECTS(pRegion); + int nbox = REGION_NUM_RECTS(pRegion); save_ptr = pPixmap->devPrivate.ptr; save_pitch = pPixmap->devKind; pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; pPixmap->devKind = pExaPixmap->fb_pitch; - if (pExaScr->info->UploadToScreen == NULL || - !pExaScr->info->UploadToScreen (pPixmap, - 0, - 0, - pPixmap->drawable.width, - pPixmap->drawable.height, - pExaPixmap->sys_ptr, - pExaPixmap->sys_pitch)) - { - char *src, *dst; - int src_pitch, dst_pitch, i, bytes; - - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST); - - dst = pExaPixmap->fb_ptr; - dst_pitch = pExaPixmap->fb_pitch; - src = pExaPixmap->sys_ptr; - src_pitch = pExaPixmap->sys_pitch; - bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch; - - for (i = 0; i < pPixmap->drawable.height; i++) { - memcpy (dst, src, bytes); - dst += dst_pitch; - src += src_pitch; + while (nbox--) { + pBox->x2 = min(pBox->x2, pPixmap->drawable.width); + pBox->y2 = min(pBox->y2, pPixmap->drawable.height); + + if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) + continue; + + if (pExaScr->info->UploadToScreen == NULL || + !pExaScr->info->UploadToScreen (pPixmap, + pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1, + pExaPixmap->sys_ptr + + pBox->y1 * pExaPixmap->sys_pitch + + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8, + pExaPixmap->sys_pitch)) + { + exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST); + exaMemcpyBox (pPixmap, pBox, + pExaPixmap->sys_ptr, pExaPixmap->sys_pitch, + pExaPixmap->fb_ptr, pExaPixmap->fb_pitch); + exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST); } - exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST); + + pBox++; } pPixmap->devPrivate.ptr = save_ptr; pPixmap->devKind = save_pitch; - pExaPixmap->dirty = FALSE; + /* The previously damaged bits are now no longer damaged but valid */ + REGION_UNION(pPixmap->drawable.pScreen, + &pExaPixmap->validReg, &pExaPixmap->validReg, pRegion); + DamageEmpty (pExaPixmap->pDamage); } /** @@ -213,6 +240,7 @@ { PixmapPtr pPixmap = area->privData; ExaPixmapPriv(pPixmap); + RegionPtr pDamageReg = DamageRegion(pExaPixmap->pDamage); DBG_MIGRATE (("Save %p (%p) (%dx%d) (%c)\n", pPixmap, (void*)(ExaGetPixmapPriv(pPixmap)->area ? @@ -231,10 +259,9 @@ pExaPixmap->fb_ptr = NULL; pExaPixmap->area = NULL; - /* Mark it dirty now, to say that there is important data in the - * system-memory copy. - */ - pExaPixmap->dirty = TRUE; + /* Mark all valid bits as damaged, so they'll get copied to FB next time */ + REGION_UNION(pPixmap->drawable.pScreen, pDamageReg, pDamageReg, + &pExaPixmap->validReg); } /** @@ -413,32 +440,54 @@ * If the pixmap has both a framebuffer and system memory copy, this function * asserts that both of them are the same. */ -static void +static Bool exaAssertNotDirty (PixmapPtr pPixmap) { ExaPixmapPriv (pPixmap); CARD8 *dst, *src; - int dst_pitch, src_pitch, data_row_bytes, y; + RegionPtr pValidReg = &pExaPixmap->validReg; + int dst_pitch, src_pitch, cpp, y, nbox = REGION_NUM_RECTS(pValidReg); + BoxPtr pBox = REGION_RECTS(pValidReg); + Bool ret = TRUE; if (pExaPixmap == NULL || pExaPixmap->fb_ptr == NULL) - return; + return TRUE; dst = pExaPixmap->sys_ptr; dst_pitch = pExaPixmap->sys_pitch; src = pExaPixmap->fb_ptr; src_pitch = pExaPixmap->fb_pitch; - data_row_bytes = pPixmap->drawable.width * - pPixmap->drawable.bitsPerPixel / 8; + cpp = pPixmap->drawable.bitsPerPixel / 8; exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); - for (y = 0; y < pPixmap->drawable.height; y++) { - if (memcmp(dst, src, data_row_bytes) != 0) { - abort(); - } - dst += dst_pitch; - src += src_pitch; + while (nbox--) { + int rowbytes; + + pBox->x2 = min(pBox->x2, pPixmap->drawable.width); + pBox->y2 = min(pBox->y2, pPixmap->drawable.height); + + if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) + continue; + + rowbytes = (pBox->x2 - pBox->x1) * cpp; + src += pBox->y1 * src_pitch + pBox->x1 * cpp; + dst += pBox->y1 * dst_pitch + pBox->x1 * cpp; + + for (y = pBox->y2 - pBox->y1; y; y--) { + if (memcmp(dst + pBox->y1 * dst_pitch + pBox->x1 * cpp, + src + pBox->y1 * src_pitch + pBox->x1 * cpp, + (pBox->x2 - pBox->x1) * cpp) != 0) { + ret = FALSE; + break; + } + src += src_pitch; + dst += dst_pitch; + } + src -= pBox->y1 * src_pitch + pBox->x1 * cpp; + dst -= pBox->y1 * dst_pitch + pBox->x1 * cpp; } exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); + return ret; } /** @@ -462,8 +511,9 @@ */ if (pExaScr->checkDirtyCorrectness) { for (i = 0; i < npixmaps; i++) { - if (!exaPixmapIsDirty (pixmaps[i].pPix)) - exaAssertNotDirty (pixmaps[i].pPix); + if (!exaPixmapIsDirty (pixmaps[i].pPix) && + !exaAssertNotDirty (pixmaps[i].pPix)) + ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __func__, i); } } /* If anything is pinned in system memory, we won't be able to --- xorg-server-1.2.99.0/exa/exa_offscreen.c.exa2~ 2006-07-20 22:27:47.000000000 +0200 +++ xorg-server-1.2.99.0/exa/exa_offscreen.c 2006-11-05 14:35:47.000000000 +0100 @@ -390,6 +390,7 @@ if (area->state == ExaOffscreenRemovable) area->score = (area->score * 7) / 8; } + iter = 0; } } --- xorg-server-1.2.99.0/exa/exa_priv.h.exa2~ 2006-07-20 22:27:47.000000000 +0200 +++ xorg-server-1.2.99.0/exa/exa_priv.h 2006-11-05 14:35:47.000000000 +0100 @@ -51,6 +51,7 @@ #ifdef RENDER #include "fbpict.h" #endif +#include "damage.h" #define DEBUG_TRACE_FALL 0 #define DEBUG_MIGRATE 0 @@ -160,16 +161,16 @@ unsigned int fb_size; /**< size of pixmap in framebuffer memory */ /** - * If area is NULL, then dirty == TRUE means that the pixmap has been - * modified, so the contents are defined. Used to avoid uploads of - * undefined data. - * - * If area is non-NULL, then dirty == TRUE means that the pixmap data at - * pPixmap->devPrivate.ptr (either fb_ptr or sys_ptr) has been changed - * compared to the copy in the other location. This is used to avoid - * uploads/downloads of unmodified data. + * The damage record contains the areas of the pixmap's current location + * (framebuffer or system) that have been damaged compared to the other + * location. */ - Bool dirty; + DamagePtr pDamage; + /** + * The valid region marks the valid bits of a drawable (at least, as it's + * derived from damage, which may be overreported). + */ + RegionRec validReg; } ExaPixmapPrivRec, *ExaPixmapPrivPtr; typedef struct _ExaMigrationRec { @@ -339,7 +340,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index); void -exaDrawableDirty(DrawablePtr pDrawable); +exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2); Bool exaDrawableIsOffscreen (DrawablePtr pDrawable); --- xorg-server-1.2.99.0/exa/exa_render.c.exa2~ 2006-08-15 14:25:57.000000000 +0200 +++ xorg-server-1.2.99.0/exa/exa_render.c 2006-11-05 14:35:47.000000000 +0100 @@ -302,12 +302,14 @@ (*pExaScr->info->Solid) (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); + exaDrawableDirty (pDst->pDrawable, + pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneSolid) (pDstPix); exaMarkSync(pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 1; @@ -441,12 +443,14 @@ pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + exaDrawableDirty (pDst->pDrawable, + pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneComposite) (pDstPix); exaMarkSync(pDst->pDrawable->pScreen); - exaDrawableDirty (pDst->pDrawable); REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 1; @@ -715,6 +719,8 @@ exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + exaDrawableDirty(pPicture->pDrawable, 0, 0, + pPicture->pDrawable->width, pPicture->pDrawable->height); } /** @@ -735,6 +741,8 @@ exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); fbAddTriangles(pPicture, x_off, y_off, ntri, tris); exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); + exaDrawableDirty(pPicture->pDrawable, 0, 0, + pPicture->pDrawable->width, pPicture->pDrawable->height); } /** @@ -1024,7 +1032,8 @@ exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC, 0, 0, glyph->info.width, glyph->info.height, 0, 0); } else { - exaDrawableDirty (&pPixmap->drawable); + exaDrawableDirty (&pPixmap->drawable, 0, 0, + glyph->info.width, glyph->info.height); } if (maskFormat)