diff options
Diffstat (limited to 'xorg-server/exa')
-rw-r--r-- | xorg-server/exa/exa.c | 78 | ||||
-rw-r--r-- | xorg-server/exa/exa_glyphs.c | 2 | ||||
-rw-r--r-- | xorg-server/exa/exa_migration_classic.c | 66 | ||||
-rw-r--r-- | xorg-server/exa/exa_migration_mixed.c | 179 | ||||
-rw-r--r-- | xorg-server/exa/exa_mixed.c | 91 | ||||
-rw-r--r-- | xorg-server/exa/exa_priv.h | 22 | ||||
-rw-r--r-- | xorg-server/exa/exa_render.c | 12 | ||||
-rw-r--r-- | xorg-server/exa/exa_unaccel.c | 52 |
8 files changed, 259 insertions, 243 deletions
diff --git a/xorg-server/exa/exa.c b/xorg-server/exa/exa.c index 483e3b4eb..e264d440c 100644 --- a/xorg-server/exa/exa.c +++ b/xorg-server/exa/exa.c @@ -286,11 +286,10 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp) * Returns TRUE if pixmap can be accessed offscreen. */ Bool -ExaDoPrepareAccess(DrawablePtr pDrawable, int index) +ExaDoPrepareAccess(PixmapPtr pPixmap, int index) { - ScreenPtr pScreen = pDrawable->pScreen; + ScreenPtr pScreen = pPixmap->drawable.pScreen; ExaScreenPriv (pScreen); - PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); ExaPixmapPriv(pPixmap); Bool offscreen; int i; @@ -324,7 +323,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index) offscreen = exaPixmapIsOffscreen(pPixmap); - if (offscreen) + if (offscreen && pExaPixmap->fb_ptr) pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; else pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; @@ -333,20 +332,10 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index) pExaScr->access[index].pixmap = pPixmap; pExaScr->access[index].count = 1; - if (!offscreen) { - /* Do we need to allocate our system buffer? */ - if ((pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && (pExaScr->info->flags & EXA_MIXED_PIXMAPS)) { - if (!pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap)) { - pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch * pDrawable->height); - if (!pExaPixmap->sys_ptr) - FatalError("EXA: malloc failed for size %d bytes\n", pExaPixmap->sys_pitch * pDrawable->height); - pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; - } - } + if (!offscreen) return FALSE; - } - exaWaitSync (pDrawable->pScreen); + exaWaitSync (pScreen); if (pExaScr->info->PrepareAccess == NULL) return TRUE; @@ -360,7 +349,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index) } if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { - if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) + if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED && + !(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); exaMoveOutPixmap (pPixmap); @@ -370,31 +360,6 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index) return TRUE; } -void -exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg) -{ - PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); - ExaScreenPriv(pPixmap->drawable.pScreen); - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[1]; - - 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; - - exaDoMigration(pixmaps, 1, FALSE); - } - - ExaDoPrepareAccess(pDrawable, index); -} - /** * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. * @@ -404,7 +369,13 @@ exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg) void exaPrepareAccess(DrawablePtr pDrawable, int index) { - exaPrepareAccessReg(pDrawable, index, NULL); + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaScreenPriv(pDrawable->pScreen); + + if (pExaScr->prepare_access_reg) + pExaScr->prepare_access_reg(pPixmap, index, NULL); + else + (void)ExaDoPrepareAccess(pPixmap, index); } /** @@ -432,7 +403,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index) if (pExaScr->access[i].pixmap == pPixmap) { if (--pExaScr->access[i].count > 0) return; - index = i; break; } } @@ -442,25 +412,25 @@ exaFinishAccess(DrawablePtr pDrawable, int index) EXA_FatalErrorDebug(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap)); - pExaScr->access[index].pixmap = NULL; + pExaScr->access[i].pixmap = NULL; /* We always hide the devPrivate.ptr. */ pPixmap->devPrivate.ptr = NULL; - if (pExaScr->info->FinishAccess == NULL) - return; + if (pExaScr->finish_access) + pExaScr->finish_access(pPixmap, index); - if (!exaPixmapIsOffscreen (pPixmap)) + if (!pExaScr->info->FinishAccess || !exaPixmapIsOffscreen(pPixmap)) return; - if (index >= EXA_PREPARE_AUX_DEST && + if (i >= EXA_PREPARE_AUX_DEST && !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { ErrorF("EXA bug: Trying to call driver FinishAccess hook with " "unsupported index EXA_PREPARE_AUX*\n"); return; } - (*pExaScr->info->FinishAccess) (pPixmap, index); + (*pExaScr->info->FinishAccess) (pPixmap, i); } /** @@ -537,7 +507,7 @@ exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth, * For EXA_HANDLES_PIXMAPS the driver will handle whatever is needed. * We want to signal that the pixmaps will be used as destination. */ - ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); + ExaDoPrepareAccess(pPixmap, EXA_PREPARE_AUX_DEST); return pPixmap; } @@ -1071,6 +1041,8 @@ exaDriverInit (ScreenPtr pScreen, pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_mixed; pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed; pExaScr->do_move_out_pixmap = NULL; + pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed; + pExaScr->finish_access = exaFinishAccess_mixed; } else { wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver); wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver); @@ -1079,6 +1051,8 @@ exaDriverInit (ScreenPtr pScreen, pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver; pExaScr->do_move_in_pixmap = NULL; pExaScr->do_move_out_pixmap = NULL; + pExaScr->prepare_access_reg = NULL; + pExaScr->finish_access = NULL; } } else { wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); @@ -1088,6 +1062,8 @@ exaDriverInit (ScreenPtr pScreen, pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_classic; pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic; pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic; + pExaScr->prepare_access_reg = exaPrepareAccessReg_classic; + pExaScr->finish_access = NULL; } if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", diff --git a/xorg-server/exa/exa_glyphs.c b/xorg-server/exa/exa_glyphs.c index d621ccf76..bf097c32f 100644 --- a/xorg-server/exa/exa_glyphs.c +++ b/xorg-server/exa/exa_glyphs.c @@ -701,7 +701,6 @@ exaGlyphs (CARD8 op, GlyphListPtr list, GlyphPtr *glyphs) { - PicturePtr pPicture; PixmapPtr pMaskPixmap = 0; PicturePtr pMask = NULL; ScreenPtr pScreen = pDst->pDrawable->pScreen; @@ -803,7 +802,6 @@ exaGlyphs (CARD8 op, while (n--) { glyph = *glyphs++; - pPicture = GlyphPicture (glyph)[pScreen->myNum]; if (glyph->info.width > 0 && glyph->info.height > 0) { diff --git a/xorg-server/exa/exa_migration_classic.c b/xorg-server/exa/exa_migration_classic.c index d8e1e86da..6d7b9f5b6 100644 --- a/xorg-server/exa/exa_migration_classic.c +++ b/xorg-server/exa/exa_migration_classic.c @@ -104,9 +104,8 @@ exaPixmapShouldBeInFB (PixmapPtr pPix) static void exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h, - char *sys, int sys_pitch), CARD8 *fallback_src, - CARD8 *fallback_dst, int fallback_srcpitch, int fallback_dstpitch, - int fallback_index, void (*sync) (ScreenPtr pScreen)) + char *sys, int sys_pitch), int fallback_index, + void (*sync) (ScreenPtr pScreen)) { PixmapPtr pPixmap = migrate->pPix; ExaPixmapPriv (pPixmap); @@ -120,7 +119,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, Bool need_sync = FALSE; /* Damaged bits are valid in current copy but invalid in other one */ - if (exaPixmapIsOffscreen(pPixmap)) { + if (pExaPixmap->offscreen) { REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB, damage); REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, @@ -225,23 +224,24 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, pExaPixmap->sys_pitch)) { if (!access_prepared) { - ExaDoPrepareAccess(&pPixmap->drawable, fallback_index); + ExaDoPrepareAccess(pPixmap, fallback_index); access_prepared = TRUE; } - exaMemcpyBox (pPixmap, pBox, - fallback_src, fallback_srcpitch, - fallback_dst, fallback_dstpitch); + if (fallback_index == EXA_PREPARE_DEST) { + exaMemcpyBox (pPixmap, pBox, + pExaPixmap->sys_ptr, pExaPixmap->sys_pitch, + pPixmap->devPrivate.ptr, pPixmap->devKind); + } else { + exaMemcpyBox (pPixmap, pBox, + pPixmap->devPrivate.ptr, pPixmap->devKind, + pExaPixmap->sys_ptr, pExaPixmap->sys_pitch); + } } else need_sync = TRUE; pBox++; } - if (access_prepared) - exaFinishAccess(&pPixmap->drawable, fallback_index); - else if (need_sync && sync) - sync (pPixmap->drawable.pScreen); - pExaPixmap->offscreen = save_offscreen; pPixmap->devKind = save_pitch; @@ -256,6 +256,11 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, REGION_UNION(pScreen, pValidDst, pValidDst, &CopyReg); REGION_UNINIT(pScreen, &CopyReg); + + if (access_prepared) + exaFinishAccess(&pPixmap->drawable, fallback_index); + else if (need_sync && sync) + sync (pPixmap->drawable.pScreen); } /** @@ -263,7 +268,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, * the framebuffer memory copy to the system memory copy. Both areas must be * allocated. */ -static void +void exaCopyDirtyToSys (ExaMigrationPtr migrate) { PixmapPtr pPixmap = migrate->pPix; @@ -271,9 +276,8 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate) ExaPixmapPriv (pPixmap); exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB, - pExaScr->info->DownloadFromScreen, pExaPixmap->fb_ptr, - pExaPixmap->sys_ptr, pExaPixmap->fb_pitch, - pExaPixmap->sys_pitch, EXA_PREPARE_SRC, exaWaitSync); + pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC, + exaWaitSync); } /** @@ -281,7 +285,7 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate) * the system memory copy to the framebuffer memory copy. Both areas must be * allocated. */ -static void +void exaCopyDirtyToFb (ExaMigrationPtr migrate) { PixmapPtr pPixmap = migrate->pPix; @@ -289,9 +293,7 @@ exaCopyDirtyToFb (ExaMigrationPtr migrate) ExaPixmapPriv (pPixmap); exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys, - pExaScr->info->UploadToScreen, pExaPixmap->sys_ptr, - pExaPixmap->fb_ptr, pExaPixmap->sys_pitch, - pExaPixmap->fb_pitch, EXA_PREPARE_DEST, NULL); + pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL); } /** @@ -545,7 +547,7 @@ exaAssertNotDirty (PixmapPtr pPixmap) pExaPixmap->offscreen = TRUE; pPixmap->devKind = pExaPixmap->fb_pitch; - if (!ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC)) + if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC)) goto skip; while (nbox--) { @@ -718,3 +720,23 @@ exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) } } } + +void +exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg) +{ + ExaMigrationRec pixmaps[1]; + + 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; + + exaDoMigration(pixmaps, 1, FALSE); + + (void)ExaDoPrepareAccess(pPixmap, index); +} 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); + } +} diff --git a/xorg-server/exa/exa_mixed.c b/xorg-server/exa/exa_mixed.c index 01f87ba87..167ffa9d5 100644 --- a/xorg-server/exa/exa_mixed.c +++ b/xorg-server/exa/exa_mixed.c @@ -32,8 +32,6 @@ #include "exa.h" /* This file holds the driver allocated pixmaps + better initial placement code. - * A pinned pixmap implies one that is either driver based already or otherwise altered. - * Proper care is taken to free the initially allocated buffer. */ static _X_INLINE void* @@ -46,9 +44,6 @@ ExaGetPixmapAddress(PixmapPtr p) /** * exaCreatePixmap() creates a new pixmap. - * - * Pixmaps are always marked as pinned, unless the pixmap can still be transfered to a - * driver pixmaps. */ PixmapPtr exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, @@ -57,7 +52,7 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, PixmapPtr pPixmap; ExaPixmapPrivPtr pExaPixmap; int bpp; - size_t paddedWidth, datasize; + size_t paddedWidth; ExaScreenPriv(pScreen); if (w > 32767 || h > 32767) @@ -79,15 +74,12 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, if (paddedWidth / 4 > 32767 || h > 32767) return NullPixmap; - datasize = h * paddedWidth; - /* We will allocate the system pixmap later if needed. */ pPixmap->devPrivate.ptr = NULL; pExaPixmap->sys_ptr = NULL; pExaPixmap->sys_pitch = paddedWidth; pExaPixmap->area = NULL; - pExaPixmap->offscreen = FALSE; pExaPixmap->fb_ptr = NULL; pExaPixmap->pDamage = NULL; @@ -95,36 +87,15 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); - /* Avoid freeing sys_ptr. */ - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; - (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, paddedWidth, NULL); - /* We want to be able to transfer the pixmap to driver memory later on. */ - pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; - /* A scratch pixmap will become a driver pixmap right away. */ if (!w || !h) { exaCreateDriverPixmap_mixed(pPixmap); - } else { - /* 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); - } + pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap); + } else + pExaPixmap->offscreen = FALSE; return pPixmap; } @@ -136,7 +107,7 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, ScreenPtr pScreen = pPixmap->drawable.pScreen; ExaScreenPrivPtr pExaScr; ExaPixmapPrivPtr pExaPixmap; - Bool ret; + Bool ret, is_offscreen; if (!pPixmap) return FALSE; @@ -144,26 +115,23 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, pExaScr = ExaGetScreenPriv(pScreen); pExaPixmap = ExaGetPixmapPriv(pPixmap); - if (pExaPixmap) { - if (!exaPixmapIsPinned(pPixmap)) { - free(pExaPixmap->sys_ptr); - pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL; - pExaPixmap->sys_pitch = pPixmap->devKind = 0; - - /* We no longer need this. */ + if (pPixData) { + if (pExaPixmap->driverPriv) { if (pExaPixmap->pDamage) { DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); DamageDestroy(pExaPixmap->pDamage); pExaPixmap->pDamage = NULL; } - } - if (pPixData) - pExaPixmap->sys_ptr = pPixData; + pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); + pExaPixmap->driverPriv = NULL; + } - if (devKind > 0) - pExaPixmap->sys_pitch = devKind; + pExaPixmap->offscreen = FALSE; + pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; + } + if (pExaPixmap->driverPriv) { if (width > 0 && height > 0 && bitsPerPixel > 0) { exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); @@ -171,9 +139,15 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); } + } - /* Anything can happen, don't try to predict it all. */ - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; + is_offscreen = exaPixmapIsOffscreen(pPixmap); + if (is_offscreen) { + pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; + pPixmap->devKind = pExaPixmap->fb_pitch; + } else { + pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; + pPixmap->devKind = pExaPixmap->sys_pitch; } /* Only pass driver pixmaps to the driver. */ @@ -184,10 +158,6 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, * If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap. * We need to store the pointer, because PrepareAccess won't be called. */ - if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) { - pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; - pExaPixmap->sys_pitch = pPixmap->devKind; - } if (ret == TRUE) goto out; } @@ -198,6 +168,13 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, swap(pExaScr, pScreen, ModifyPixmapHeader); out: + if (is_offscreen) { + pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr; + pExaPixmap->fb_pitch = pPixmap->devKind; + } else { + pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; + pExaPixmap->sys_pitch = pPixmap->devKind; + } /* Always NULL this, we don't want lingering pointers. */ pPixmap->devPrivate.ptr = NULL; @@ -217,10 +194,14 @@ exaDestroyPixmap_mixed(PixmapPtr pPixmap) if (pExaPixmap->driverPriv) pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); - else if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap)) - free(pExaPixmap->sys_ptr); pExaPixmap->driverPriv = NULL; - pExaPixmap->sys_ptr = NULL; + + if (pExaPixmap->pDamage) { + if (pExaPixmap->sys_ptr) + free(pExaPixmap->sys_ptr); + pExaPixmap->sys_ptr = NULL; + pExaPixmap->pDamage = NULL; + } } swap(pExaScr, pScreen, DestroyPixmap); diff --git a/xorg-server/exa/exa_priv.h b/xorg-server/exa/exa_priv.h index 869cf1772..1aec8e966 100644 --- a/xorg-server/exa/exa_priv.h +++ b/xorg-server/exa/exa_priv.h @@ -176,6 +176,8 @@ typedef struct { Bool (*pixmap_is_offscreen) (PixmapPtr pPixmap); void (*do_move_in_pixmap) (PixmapPtr pPixmap); void (*do_move_out_pixmap) (PixmapPtr pPixmap); + void (*prepare_access_reg)(PixmapPtr pPixmap, int index, RegionPtr pReg); + void (*finish_access)(PixmapPtr pPixmap, int index); Bool swappedOut; enum ExaMigrationHeuristic migration; @@ -511,10 +513,7 @@ ExaOffscreenFini (ScreenPtr pScreen); /* exa.c */ Bool -ExaDoPrepareAccess(DrawablePtr pDrawable, int index); - -void -exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg); +ExaDoPrepareAccess(PixmapPtr pPixmap, int index); void exaPrepareAccess(DrawablePtr pDrawable, int index); @@ -609,6 +608,12 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); void exaMoveInPixmap_mixed(PixmapPtr pPixmap); +void +exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg); + +void +exaFinishAccess_mixed(PixmapPtr pPixmap, int index); + /* exa_render.c */ Bool exaOpReadsDestination (CARD8 op); @@ -665,6 +670,12 @@ exaGlyphs (CARD8 op, /* exa_migration_classic.c */ void +exaCopyDirtyToSys (ExaMigrationPtr migrate); + +void +exaCopyDirtyToFb (ExaMigrationPtr migrate); + +void exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); void @@ -676,4 +687,7 @@ exaMoveOutPixmap_classic (PixmapPtr pPixmap); void exaMoveInPixmap_classic (PixmapPtr pPixmap); +void +exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg); + #endif /* EXAPRIV_H */ diff --git a/xorg-server/exa/exa_render.c b/xorg-server/exa/exa_render.c index d46930130..1c1856610 100644 --- a/xorg-server/exa/exa_render.c +++ b/xorg-server/exa/exa_render.c @@ -266,6 +266,10 @@ exaTryDriverSolidFill(PicturePtr pSrc, xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; + if (pSrc->pDrawable) { + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + } if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, xSrc, ySrc, 0, 0, xDst, yDst, @@ -277,9 +281,6 @@ exaTryDriverSolidFill(PicturePtr pSrc, REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); if (pSrc->pDrawable) { - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); pixel = exaGetPixmapFirstPixel (pSrcPix); } else @@ -340,7 +341,8 @@ exaTryDriverCompositeRects(CARD8 op, ExaCompositeRectPtr rects) { ExaScreenPriv (pDst->pDrawable->pScreen); - int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; + int src_off_x = 0, src_off_y = 0, mask_off_x = 0, mask_off_y = 0; + int dst_off_x, dst_off_y; PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix; ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix; @@ -656,7 +658,7 @@ exaTryDriverComposite(CARD8 op, */ if (pDstExaPix->accel_blocked || (pSrcExaPix && pSrcExaPix->accel_blocked) || - (pMask && (pMaskExaPix->accel_blocked))) + (pMaskExaPix && (pMaskExaPix->accel_blocked))) { return -1; } diff --git a/xorg-server/exa/exa_unaccel.c b/xorg-server/exa/exa_unaccel.c index f4700adac..c8f017243 100644 --- a/xorg-server/exa/exa_unaccel.c +++ b/xorg-server/exa/exa_unaccel.c @@ -101,16 +101,19 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { - ExaPixmapPriv(exaGetDrawablePixmap(pDrawable)); + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaPixmapPriv(pPixmap); + ExaScreenPriv(pDrawable->pScreen); EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, + if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage || + exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, pGC->alu, pGC->clientClipType)) exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); else - exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ? - DamagePendingRegion(pExaPixmap->pDamage) : NULL); + pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, + DamagePendingRegion(pExaPixmap->pDamage)); pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); EXA_GC_EPILOGUE(pGC); @@ -323,9 +326,6 @@ void ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d) { - BoxRec Box; - RegionRec Reg; - int xoff, yoff; ScreenPtr pScreen = pDrawable->pScreen; PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); ExaScreenPriv(pScreen); @@ -333,16 +333,24 @@ ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff); + if (pExaScr->prepare_access_reg) { + int xoff, yoff; + BoxRec Box; + RegionRec Reg; + + exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff); + + Box.x1 = pDrawable->y + x + xoff; + Box.y1 = pDrawable->y + y + yoff; + Box.x2 = Box.x1 + w; + Box.y2 = Box.y1 + h; - Box.x1 = pDrawable->y + x + xoff; - Box.y1 = pDrawable->y + y + yoff; - Box.x2 = Box.x1 + w; - Box.y2 = Box.y1 + h; + REGION_INIT(pScreen, &Reg, &Box, 1); - REGION_INIT(pScreen, &Reg, &Box, 1); + pExaScr->prepare_access_reg(pPix, EXA_PREPARE_SRC, &Reg); + } else + exaPrepareAccess(pDrawable, EXA_PREPARE_SRC); - exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg); swap(pExaScr, pScreen, GetImage); pScreen->GetImage (pDrawable, x, y, w, h, format, planeMask, d); swap(pExaScr, pScreen, GetImage); @@ -401,23 +409,23 @@ ExaCheckComposite (CARD8 op, if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK); - if (!exaOpReadsDestination(op)) { + if (!exaOpReadsDestination(op) && pExaScr->prepare_access_reg) { + PixmapPtr pDstPix; + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) goto skip; - exaGetDrawableDeltas (pDst->pDrawable, - exaGetDrawablePixmap(pDst->pDrawable), - &xoff, &yoff); - + pDstPix = exaGetDrawablePixmap(pDst->pDrawable); + exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &xoff, &yoff); REGION_TRANSLATE(pScreen, ®ion, xoff, yoff); if (pDst->alphaMap && pDst->alphaMap->pDrawable) - exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST, - ®ion); + pExaScr->prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable), + EXA_PREPARE_AUX_DEST, ®ion); - exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, ®ion); + pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, ®ion); } else { if (pDst->alphaMap && pDst->alphaMap->pDrawable) exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST); |