diff options
Diffstat (limited to 'xorg-server/exa/exa_migration_mixed.c')
-rw-r--r-- | xorg-server/exa/exa_migration_mixed.c | 179 |
1 files changed, 97 insertions, 82 deletions
diff --git a/xorg-server/exa/exa_migration_mixed.c b/xorg-server/exa/exa_migration_mixed.c index d1ee9871b..f42c9c233 100644 --- a/xorg-server/exa/exa_migration_mixed.c +++ b/xorg-server/exa/exa_migration_mixed.c @@ -31,55 +31,16 @@ #include "exa_priv.h" #include "exa.h" -static void -exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch) -{ - ExaPixmapPriv(pPixmap); - RegionPtr damage = DamageRegion (pExaPixmap->pDamage); - GCPtr pGC = GetScratchGC (pPixmap->drawable.depth, - pPixmap->drawable.pScreen); - int nbox, cpp = pPixmap->drawable.bitsPerPixel / 8; - DamagePtr backup = pExaPixmap->pDamage; - BoxPtr pbox; - CARD8 *src2; - - /* We don't want damage optimisations. */ - pExaPixmap->pDamage = NULL; - ValidateGC (&pPixmap->drawable, pGC); - - pbox = REGION_RECTS(damage); - nbox = REGION_NUM_RECTS(damage); - - while (nbox--) { - src2 = src + pbox->y1 * src_pitch + pbox->x1 * cpp; - - ExaCheckPutImage(&pPixmap->drawable, pGC, - pPixmap->drawable.depth, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, 0, - ZPixmap, (char*) src2); - - pbox++; - } - - FreeScratchGC (pGC); - pExaPixmap->pDamage = backup; -} - void 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; + int paddedWidth = pExaPixmap->sys_pitch; /* Already done. */ if (pExaPixmap->driverPriv) @@ -105,50 +66,8 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap) if (!pExaPixmap->driverPriv) return; - pExaPixmap->offscreen = TRUE; - pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL; - pExaPixmap->sys_pitch = pPixmap->devKind = 0; - - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, paddedWidth, NULL); - - /* scratch pixmaps */ - if (!w || !h) - goto finish; - - /* we do not malloc memory by default. */ - if (!sys_buffer) - goto finish; - - if (!pExaScr->info->UploadToScreen) - goto fallback; - - 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: - exaUploadFallback(pPixmap, sys_buffer, sys_pitch); - -finish: - free(sys_buffer); - - /* We no longer need this. */ - if (pExaPixmap->pDamage) { - DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); - DamageDestroy(pExaPixmap->pDamage); - pExaPixmap->pDamage = NULL; - } } void @@ -175,8 +94,16 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) for (i = 0; i < npixmaps; i++) { PixmapPtr pPixmap = pixmaps[i].pPix; ExaPixmapPriv(pPixmap); + if (!pExaPixmap->driverPriv) exaCreateDriverPixmap_mixed(pPixmap); + + if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) { + pPixmap->devKind = pExaPixmap->fb_pitch; + exaCopyDirtyToFb(pixmaps + i); + } + + pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap); } } @@ -192,3 +119,91 @@ exaMoveInPixmap_mixed(PixmapPtr pPixmap) exaDoMigration(pixmaps, 1, TRUE); } + +/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we + * use the DownloadFromScreen hook to retrieve contents to a copy in system + * memory, perform software rendering on that and move back the results with the + * UploadToScreen hook (see exaFinishAccess_mixed). + */ +void +exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg) +{ + if (!ExaDoPrepareAccess(pPixmap, index)) { + ExaPixmapPriv(pPixmap); + Bool is_offscreen = exaPixmapIsOffscreen(pPixmap); + ExaMigrationRec pixmaps[1]; + + /* Do we need to allocate our system buffer? */ + if (!pExaPixmap->sys_ptr) { + pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch * + pPixmap->drawable.height); + if (!pExaPixmap->sys_ptr) + FatalError("EXA: malloc failed for size %d bytes\n", + pExaPixmap->sys_pitch * pPixmap->drawable.height); + } + + if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) { + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + } else { + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + } + pixmaps[0].pPix = pPixmap; + pixmaps[0].pReg = pReg; + + if (!pExaPixmap->pDamage && (is_offscreen || !exaPixmapIsPinned(pPixmap))) { + Bool as_dst = pixmaps[0].as_dst; + + /* Set up damage tracking */ + pExaPixmap->pDamage = DamageCreate(NULL, NULL, DamageReportNone, + TRUE, pPixmap->drawable.pScreen, + pPixmap); + + 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); + + if (is_offscreen) { + exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width, + pPixmap->drawable.height); + + /* We don't know which region of the destination will be damaged, + * have to assume all of it + */ + if (as_dst) { + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pReg = NULL; + } + pPixmap->devKind = pExaPixmap->fb_pitch; + exaCopyDirtyToSys(pixmaps); + } + + if (as_dst) + exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width, + pPixmap->drawable.height); + } else if (is_offscreen) { + pPixmap->devKind = pExaPixmap->fb_pitch; + exaCopyDirtyToSys(pixmaps); + } + + pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; + pPixmap->devKind = pExaPixmap->sys_pitch; + pExaPixmap->offscreen = FALSE; + } +} + +/* Move back results of software rendering on system memory copy of mixed driver + * pixmap (see exaPrepareAccessReg_mixed). + */ +void exaFinishAccess_mixed(PixmapPtr pPixmap, int index) +{ + ExaPixmapPriv(pPixmap); + + if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) { + DamageRegionProcessPending(&pPixmap->drawable); + exaMoveInPixmap_mixed(pPixmap); + } +} |