- This is most useful for cases where the first operation is a hardware 
rendered one.
---
 exa/exa_migration_mixed.c |   50 ++++++++++++++++++++++++++++++++++++++------
 exa/exa_mixed.c           |   27 +++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c
index bed7141..88077a3 100644
--- a/exa/exa_migration_mixed.c
+++ b/exa/exa_migration_mixed.c
@@ -35,12 +35,28 @@ static void
 exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_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;
+
+    pbox = REGION_RECTS(damage);
+    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;
+           dst += dst_pitch;
+       }
 
-    for (i = pPixmap->drawable.height; i; i--) {
-       memcpy (dst, src, min(src_pitch, dst_pitch));
-       src += src_pitch;
-       dst += dst_pitch;
+       pbox++;
     }
 }
 
@@ -50,12 +66,15 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
     ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ExaScreenPriv(pScreen);
     ExaPixmapPriv(pPixmap);
+    RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
     void *sys_buffer = pExaPixmap->sys_ptr;
     int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
     int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
     int usage_hint = pPixmap->usage_hint;
     int sys_pitch = pExaPixmap->sys_pitch;
     int paddedWidth = sys_pitch;
+    int nbox;
+    BoxPtr pbox;
 
     /* Already done. */
     if (pExaPixmap->driverPriv)
@@ -91,8 +110,18 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
     if (!pExaScr->info->UploadToScreen)
        goto fallback;
 
-    if (pExaScr->info->UploadToScreen(pPixmap, 0, 0, w, h, sys_buffer, 
sys_pitch))
-       goto finish;
+    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;
 
 fallback:
     ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
@@ -105,6 +134,13 @@ finish:
     pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
 
     exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
+
+    /* We no longer need this. */
+    if (pExaPixmap->pDamage) {
+       DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+       DamageDestroy(pExaPixmap->pDamage);
+       pExaPixmap->pDamage = NULL;
+    }
 }
 
 void
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
index 80af521..9090078 100644
--- a/exa/exa_mixed.c
+++ b/exa/exa_mixed.c
@@ -108,6 +108,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. */
        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;
@@ -130,8 +147,16 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, 
int height, int depth,
 
     if (pExaPixmap) {
         if (pPixData) {
-           if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap))
+           if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap)) {
                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;
        }
 
-- 
1.6.4

_______________________________________________
xorg-devel mailing list
xorg-devel@lists.x.org
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to