summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
Diffstat (limited to 'exa')
-rw-r--r--exa/Makefile.am7
-rw-r--r--exa/exa.c514
-rw-r--r--exa/exa.h32
-rw-r--r--exa/exa_accel.c164
-rw-r--r--exa/exa_classic.c258
-rw-r--r--exa/exa_driver.c214
-rw-r--r--exa/exa_glyphs.c17
-rw-r--r--exa/exa_migration_classic.c (renamed from exa/exa_migration.c)29
-rw-r--r--exa/exa_migration_mixed.c194
-rw-r--r--exa/exa_mixed.c251
-rw-r--r--exa/exa_priv.h154
-rw-r--r--exa/exa_render.c399
-rw-r--r--exa/exa_unaccel.c69
13 files changed, 1573 insertions, 729 deletions
diff --git a/exa/Makefile.am b/exa/Makefile.am
index 2b3f1e416..8b759cd76 100644
--- a/exa/Makefile.am
+++ b/exa/Makefile.am
@@ -17,11 +17,14 @@ AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
libexa_la_SOURCES = \
exa.c \
exa.h \
+ exa_classic.c \
+ exa_migration_classic.c \
+ exa_driver.c \
+ exa_mixed.c \
+ exa_migration_mixed.c \
exa_accel.c \
exa_glyphs.c \
- exa_migration.c \
exa_offscreen.c \
exa_render.c \
exa_priv.h \
exa_unaccel.c
-
diff --git a/exa/exa.c b/exa/exa.c
index d04ea71e0..483e3b4eb 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -48,17 +48,6 @@ DevPrivateKey exaGCPrivateKey = &exaGCPrivateKeyIndex;
static ShmFuncs exaShmFuncs = { NULL, NULL };
#endif
-static _X_INLINE void*
-ExaGetPixmapAddress(PixmapPtr p)
-{
- ExaPixmapPriv(p);
-
- if (pExaPixmap->offscreen && pExaPixmap->fb_ptr)
- return pExaPixmap->fb_ptr;
- else
- return pExaPixmap->sys_ptr;
-}
-
/**
* exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
* the beginning of the given pixmap.
@@ -178,45 +167,6 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2)
REGION_UNINIT(pScreen, &region);
}
-static Bool
-exaDestroyPixmap (PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- Bool ret;
-
- if (pPixmap->refcnt == 1)
- {
- ExaPixmapPriv (pPixmap);
-
- if (pExaPixmap->driverPriv) {
- pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
- pExaPixmap->driverPriv = NULL;
- }
-
- if (pExaPixmap->area)
- {
- DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
- (void*)pPixmap->drawable.id,
- ExaGetPixmapPriv(pPixmap)->area->offset,
- pPixmap->drawable.width,
- pPixmap->drawable.height));
- /* Free the offscreen area */
- exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- }
- REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
- REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
- }
-
- swap(pExaScr, pScreen, DestroyPixmap);
- ret = pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
-
- return ret;
-}
-
static int
exaLog2(int val)
{
@@ -229,14 +179,14 @@ exaLog2(int val)
return bits - 1;
}
-static void
+void
exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
int w, int h, int bpp)
{
pExaPixmap->accel_blocked = 0;
if (pExaScr->info->maxPitchPixels) {
- int max_pitch = pExaScr->info->maxPitchPixels * (bpp + 7) / 8;
+ int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp);
if (pExaPixmap->fb_pitch > max_pitch)
pExaPixmap->accel_blocked |= EXA_RANGE_PITCH;
@@ -253,238 +203,33 @@ exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT;
}
-static void
+void
exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
int w, int h, int bpp)
{
if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
- pExaPixmap->fb_pitch = ((1 << (exaLog2(w - 1) + 1)) * bpp + 7) / 8;
+ pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp);
else
- pExaPixmap->fb_pitch = (w * bpp + 7) / 8;
+ pExaPixmap->fb_pitch = bits_to_bytes(w * bpp);
pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
pExaScr->info->pixmapPitchAlign);
}
/**
- * exaCreatePixmap() creates a new pixmap.
- *
- * If width and height are 0, this won't be a full-fledged pixmap and it will
- * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
- * ModifyPixmapHeader() would break migration. These types of pixmaps are used
- * for scratch pixmaps, or to represent the visible screen.
+ * Returns TRUE if the pixmap is not movable. This is the case where it's a
+ * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
+ * some X Server internal component (the score says it's pinned).
*/
-static PixmapPtr
-exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth,
- unsigned usage_hint)
-{
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- BoxRec box;
- int driver_alloc = 0;
- int bpp;
- ExaScreenPriv(pScreen);
-
- if (w > 32767 || h > 32767)
- return NullPixmap;
-
- swap(pExaScr, pScreen, CreatePixmap);
- if (!pExaScr->info->CreatePixmap && !pExaScr->info->CreatePixmap2) {
- pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
- } else {
- driver_alloc = 1;
- pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
- }
- swap(pExaScr, pScreen, CreatePixmap);
-
- if (!pPixmap)
- return NULL;
-
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
- pExaPixmap->driverPriv = NULL;
-
- bpp = pPixmap->drawable.bitsPerPixel;
-
- if (driver_alloc) {
- size_t paddedWidth, datasize;
-
- paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
- if (paddedWidth / 4 > 32767 || h > 32767)
- return NullPixmap;
-
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
-
- if (paddedWidth < pExaPixmap->fb_pitch)
- paddedWidth = pExaPixmap->fb_pitch;
-
- datasize = h * paddedWidth;
-
- /* Set this before driver hooks, to allow for !offscreen pixmaps.
- * !offscreen pixmaps have a valid pointer at all times.
- */
- pPixmap->devPrivate.ptr = NULL;
-
- if (pExaScr->info->CreatePixmap2)
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp);
- else
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
- if (!pExaPixmap->driverPriv) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->pDamage = NULL;
- pExaPixmap->sys_ptr = NULL;
-
- (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
- paddedWidth, NULL);
-
- } else {
- pExaPixmap->driverPriv = NULL;
- /* Scratch pixmaps may have w/h equal to zero, and may not be
- * migrated.
- */
- if (!w || !h)
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- else
- pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
-
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->sys_pitch = pPixmap->devKind;
-
- pPixmap->devPrivate.ptr = NULL;
- pExaPixmap->offscreen = FALSE;
-
- pExaPixmap->fb_ptr = NULL;
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
- pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
-
- if (pExaPixmap->fb_pitch > 131071) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- /* 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->area = NULL;
-
- /* We set the initial pixmap as completely valid for a simple reason.
- * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
- * could form single pixel rects as part of a region. Setting the complete region
- * as valid is a natural defragmentation of the region.
- */
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = w;
- box.y2 = h;
- REGION_INIT(pScreen, &pExaPixmap->validSys, &box, 0);
- REGION_INIT(pScreen, &pExaPixmap->validFB, &box, 0);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- w, h, bpp);
-
- return pPixmap;
-}
-
-static Bool
-exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
- int bitsPerPixel, int devKind, pointer pPixData)
+Bool
+exaPixmapIsPinned (PixmapPtr pPix)
{
- ExaScreenPrivPtr pExaScr;
- ExaPixmapPrivPtr pExaPixmap;
- Bool ret;
-
- if (!pPixmap)
- return FALSE;
-
- pExaScr = ExaGetScreenPriv(pPixmap->drawable.pScreen);
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
-
- if (pExaPixmap) {
- if (pPixData)
- pExaPixmap->sys_ptr = pPixData;
-
- if (devKind > 0)
- pExaPixmap->sys_pitch = devKind;
-
- /* Classic EXA:
- * - Framebuffer.
- * - Scratch pixmap with offscreen memory.
- */
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
- pExaScr->info->memoryBase && pPixData) {
- if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
- ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
- pExaScr->info->memorySize) {
- pExaPixmap->fb_ptr = pPixData;
- pExaPixmap->fb_pitch = devKind;
- pExaPixmap->offscreen = TRUE;
- }
- }
-
- if (width > 0 && height > 0 && bitsPerPixel > 0) {
- exaSetFbPitch(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
- }
-
- /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
- * offscreen memory, so there's no need to track damage.
- */
- if (pExaPixmap->pDamage) {
- DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
- DamageDestroy(pExaPixmap->pDamage);
- pExaPixmap->pDamage = NULL;
- }
- }
-
- if (pExaScr->info->ModifyPixmapHeader) {
- ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
- * 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;
- }
- ret = pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
+ ExaPixmapPriv (pPix);
-out:
- /* Always NULL this, we don't want lingering pointers. */
- pPixmap->devPrivate.ptr = NULL;
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
- return ret;
+ return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
}
/**
@@ -500,21 +245,15 @@ out:
* @return TRUE if the given drawable is in framebuffer memory.
*/
Bool
-exaPixmapIsOffscreen(PixmapPtr p)
+exaPixmapIsOffscreen(PixmapPtr pPixmap)
{
- ScreenPtr pScreen = p->drawable.pScreen;
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv(pScreen);
- ExaPixmapPriv(p);
- Bool ret;
- if (pExaScr->info->PixmapIsOffscreen) {
- p->devPrivate.ptr = ExaGetPixmapAddress(p);
- ret = pExaScr->info->PixmapIsOffscreen(p);
- p->devPrivate.ptr = NULL;
- } else
- ret = (pExaPixmap->offscreen && pExaPixmap->fb_ptr);
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return FALSE;
- return ret;
+ return (*pExaScr->pixmap_is_offscreen)(pPixmap);
}
/**
@@ -554,6 +293,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv(pPixmap);
Bool offscreen;
+ int i;
if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
return FALSE;
@@ -561,19 +301,25 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
if (pExaPixmap == NULL)
EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
- /* Check if we're dealing SRC == DST or similar.
- * In that case the first PrepareAccess has already set pPixmap->devPrivate.ptr.
- */
- if (pPixmap->devPrivate.ptr != NULL) {
- int i;
- for (i = 0; i < 6; i++)
- if (pExaScr->prepare_access[i] == pPixmap)
+ /* Handle repeated / nested calls. */
+ for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
+ if (pExaScr->access[i].pixmap == pPixmap) {
+ pExaScr->access[i].count++;
+ return TRUE;
+ }
+ }
+
+ /* If slot for this index is taken, find an empty slot */
+ if (pExaScr->access[index].pixmap) {
+ for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--)
+ if (!pExaScr->access[index].pixmap)
break;
+ }
- /* No known PrepareAccess or double prepare on the same index. */
- if (i == 6 || i == index)
- EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n",
- pPixmap->devPrivate.ptr));
+ /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */
+ if (pPixmap->devPrivate.ptr != NULL) {
+ EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n",
+ pPixmap->devPrivate.ptr));
}
offscreen = exaPixmapIsOffscreen(pPixmap);
@@ -583,11 +329,22 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
else
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- /* Store so we can check SRC and DEST being the same. */
- pExaScr->prepare_access[index] = pPixmap;
-
- if (!offscreen)
+ /* Store so we can handle repeated / nested calls. */
+ 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;
+ }
+ }
return FALSE;
+ }
exaWaitSync (pDrawable->pScreen);
@@ -616,19 +373,24 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
void
exaPrepareAccessReg(DrawablePtr pDrawable, 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 = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = pReg;
+ PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
+ ExaScreenPriv(pPixmap->drawable.pScreen);
- exaDoMigration(pixmaps, 1, FALSE);
+ 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);
}
@@ -657,6 +419,7 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
ExaScreenPriv (pScreen);
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
+ int i;
if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
return;
@@ -664,11 +427,22 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
if (pExaPixmap == NULL)
EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
- /* Avoid mismatching indices. */
- if (pExaScr->prepare_access[index] != pPixmap)
- EXA_FatalErrorDebug(("EXA bug: Calling FinishAccess on pixmap %p with index %d while "
- "it should have been %p.\n", pPixmap, index, pExaScr->prepare_access[index]));
- pExaScr->prepare_access[index] = NULL;
+ /* Handle repeated / nested calls. */
+ for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) {
+ if (pExaScr->access[i].pixmap == pPixmap) {
+ if (--pExaScr->access[i].count > 0)
+ return;
+ index = i;
+ break;
+ }
+ }
+
+ /* Catch unbalanced Prepare/FinishAccess calls. */
+ if (i == EXA_NUM_PREPARE_INDICES)
+ EXA_FatalErrorDebug(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n",
+ pPixmap));
+
+ pExaScr->access[index].pixmap = NULL;
/* We always hide the devPrivate.ptr. */
pPixmap->devPrivate.ptr = NULL;
@@ -763,15 +537,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.
*/
- if (pExaScr->prepare_access[EXA_PREPARE_DEST] == NULL) {
- ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
- pExaScr->prepare_access[EXA_PREPARE_DEST] = pPixmap;
- } else if (pExaScr->prepare_access[EXA_PREPARE_AUX_DEST] == NULL) {
- ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
- pExaScr->prepare_access[EXA_PREPARE_AUX_DEST] = pPixmap;
- } else {
- FatalError("exaCreatePixmapWithPrepare can only accomodate two pixmaps, we're at three.\n");
- }
+ ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
return pPixmap;
}
@@ -781,12 +547,9 @@ exaDestroyPixmapWithFinish(PixmapPtr pPixmap)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
ExaScreenPriv(pScreen);
- int i;
Bool ret;
- for (i = 0; i < 6; i++)
- if (pExaScr->prepare_access[i] == pPixmap)
- exaFinishAccess(&pPixmap->drawable, i);
+ exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
/* This swaps between this function and the real upper layer function.
* Normally this would swap to the fb layer pointer, this is a very special case.
@@ -848,8 +611,8 @@ exaValidateGC(GCPtr pGC,
(*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
- if (pExaScr->prepare_access[EXA_PREPARE_SRC]) /* tile */
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_SRC]->drawable, EXA_PREPARE_SRC);
+ if (pTile)
+ exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
if (pGC->stipple)
exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
@@ -863,13 +626,6 @@ exaValidateGC(GCPtr pGC,
/* restore copy of fb layer pointer. */
pExaScr->SavedDestroyPixmap = old_ptr2;
- if (pExaScr->prepare_access[EXA_PREPARE_DEST])
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_DEST]->drawable,
- EXA_PREPARE_DEST);
- if (pExaScr->prepare_access[EXA_PREPARE_AUX_DEST])
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_AUX_DEST]->drawable,
- EXA_PREPARE_AUX_DEST);
-
EXA_GC_EPILOGUE(pGC);
}
@@ -979,10 +735,10 @@ exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
ret = pScreen->ChangeWindowAttributes(pWin, mask);
swap(pExaScr, pScreen, ChangeWindowAttributes);
- if (pExaScr->prepare_access[EXA_PREPARE_SRC]) /* background */
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_SRC]->drawable, EXA_PREPARE_SRC);
- if (pExaScr->prepare_access[EXA_PREPARE_MASK]) /* border */
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_MASK]->drawable, EXA_PREPARE_MASK);
+ if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap)
+ exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
+ if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
+ exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
/* switch back to the normal upper layer. */
unwrap(pExaScr, pScreen, CreatePixmap);
@@ -994,13 +750,6 @@ exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
/* restore copy of fb layer pointer. */
pExaScr->SavedDestroyPixmap = old_ptr2;
- if (pExaScr->prepare_access[EXA_PREPARE_DEST])
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_DEST]->drawable,
- EXA_PREPARE_DEST);
- if (pExaScr->prepare_access[EXA_PREPARE_AUX_DEST])
- exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_AUX_DEST]->drawable,
- EXA_PREPARE_AUX_DEST);
-
return ret;
}
@@ -1313,10 +1062,33 @@ exaDriverInit (ScreenPtr pScreen,
pScreen->myNum);
return FALSE;
}
- wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap);
- wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap);
-
- wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader);
+ if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) {
+ if (pExaScr->info->flags & EXA_MIXED_PIXMAPS) {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_mixed);
+ pExaScr->do_migration = exaDoMigration_mixed;
+ pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_mixed;
+ pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
+ pExaScr->do_move_out_pixmap = NULL;
+ } else {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_driver);
+ pExaScr->do_migration = NULL;
+ pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver;
+ pExaScr->do_move_in_pixmap = NULL;
+ pExaScr->do_move_out_pixmap = NULL;
+ }
+ } else {
+ wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
+ wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic);
+ wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader_classic);
+ pExaScr->do_migration = exaDoMigration_classic;
+ pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_classic;
+ pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
+ pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
+ }
if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
pScreen->myNum,
@@ -1414,3 +1186,47 @@ void exaWaitSync(ScreenPtr pScreen)
pExaScr->info->needsSync = FALSE;
}
}
+
+/**
+ * Performs migration of the pixmaps according to the operation information
+ * provided in pixmaps and can_accel and the migration scheme chosen in the
+ * config file.
+ */
+void
+exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_migration)
+ (*pExaScr->do_migration)(pixmaps, npixmaps, can_accel);
+}
+
+void
+exaMoveInPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_move_in_pixmap)
+ (*pExaScr->do_move_in_pixmap)(pPixmap);
+}
+
+void
+exaMoveOutPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+
+ if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+ return;
+
+ if (pExaScr->do_move_out_pixmap)
+ (*pExaScr->do_move_out_pixmap)(pPixmap);
+}
diff --git a/exa/exa.h b/exa/exa.h
index 0701ec98f..4b3947327 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -586,14 +586,14 @@ typedef struct _ExaDriver {
* untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
* making CPU access use a different aperture.
*
- * The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC, or
- * #EXA_PREPARE_MASK, indicating which pixmap is in question. Since only up
- * to three pixmaps will have PrepareAccess() called on them per operation,
- * drivers can have a small, statically-allocated space to maintain state
- * for PrepareAccess() and FinishAccess() in. Note that the same pixmap may
- * have PrepareAccess() called on it more than once, for example when doing
- * a copy within the same pixmap (so it gets PrepareAccess as()
- * #EXA_PREPARE_DEST and then as #EXA_PREPARE_SRC).
+ * The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC,
+ * #EXA_PREPARE_MASK, #EXA_PREPARE_AUX_DEST, #EXA_PREPARE_AUX_SRC, or
+ * #EXA_PREPARE_AUX_MASK. Since only up to #EXA_NUM_PREPARE_INDICES pixmaps
+ * will have PrepareAccess() called on them per operation, drivers can have
+ * a small, statically-allocated space to maintain state for PrepareAccess()
+ * and FinishAccess() in. Note that PrepareAccess() is only called once per
+ * pixmap and operation, regardless of whether the pixmap is used as a
+ * destination and/or source, and the index may not reflect the usage.
*
* PrepareAccess() may fail. An example might be the case of hardware that
* can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
@@ -663,6 +663,7 @@ typedef struct _ExaDriver {
#define EXA_PREPARE_AUX_DEST 3
#define EXA_PREPARE_AUX_SRC 4
#define EXA_PREPARE_AUX_MASK 5
+ #define EXA_NUM_PREPARE_INDICES 6
/** @} */
/**
@@ -707,8 +708,12 @@ typedef struct _ExaDriver {
int depth, int bitsPerPixel, int devKind,
pointer pPixData);
+ /* hooks for drivers with tiling support:
+ * driver MUST fill out new_fb_pitch with valid pitch of pixmap
+ */
void *(*CreatePixmap2)(ScreenPtr pScreen, int width, int height,
- int depth, int usage_hint, int bitsPerPixel);
+ int depth, int usage_hint, int bitsPerPixel,
+ int *new_fb_pitch);
/** @} */
} ExaDriverRec, *ExaDriverPtr;
@@ -757,6 +762,13 @@ typedef struct _ExaDriver {
*/
#define EXA_SUPPORTS_OFFSCREEN_OVERLAPS (1 << 5)
+/**
+ * EXA_MIXED_PIXMAPS will hide unacceleratable pixmaps from drivers and manage the
+ * problem known software fallbacks like trapezoids. This only migrates pixmaps one way
+ * into a driver pixmap and then pins it.
+ */
+#define EXA_MIXED_PIXMAPS (1 << 6)
+
/** @} */
/* in exa.c */
@@ -807,7 +819,7 @@ exaEnableDisableFBAccess (int index, Bool enable);
extern _X_EXPORT Bool
exaDrawableIsOffscreen (DrawablePtr pDrawable);
-/* in exa_migration.c */
+/* in exa.c */
extern _X_EXPORT void
exaMoveInPixmap (PixmapPtr pPixmap);
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index 001a4f0e2..33fbb9843 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -50,12 +50,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
int fullX1, fullX2, fullY1;
int partX1, partX2;
int off_x, off_y;
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
@@ -63,7 +57,16 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
{
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
- } else {
+ }
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
exaDoMigration (pixmaps, 1, TRUE);
}
@@ -148,10 +151,9 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int nbox;
int xoff, yoff;
int bpp = pDrawable->bitsPerPixel;
- Bool access_prepared = FALSE;
Bool ret = TRUE;
- if (pExaPixmap->accel_blocked)
+ if (pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen)
return FALSE;
/* Don't bother with under 8bpp, XYPixmaps. */
@@ -165,10 +167,10 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (pExaScr->swappedOut)
return FALSE;
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
- pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPix;
pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
@@ -178,7 +180,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
- if (!pPix || !pExaScr->info->UploadToScreen)
+ if (!pPix)
return FALSE;
x += pDrawable->x;
@@ -220,9 +222,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
}
}
- if (access_prepared)
- exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
- else
+ if (ret)
exaMarkSync(pDrawable->pScreen);
return ret;
@@ -375,7 +375,6 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable,
ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
int src_off_x, src_off_y;
int dst_off_x, dst_off_y;
- ExaMigrationRec pixmaps[2];
RegionPtr srcregion = NULL, dstregion = NULL;
xRectangle *rects;
Bool ret = TRUE;
@@ -425,14 +424,6 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPixmap;
- pixmaps[0].pReg = dstregion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPixmap;
- pixmaps[1].pReg = srcregion;
pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap);
pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
@@ -466,7 +457,20 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- exaDoMigration (pixmaps, 2, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pDstPixmap;
+ pixmaps[0].pReg = dstregion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pSrcPixmap;
+ pixmaps[1].pReg = srcregion;
+
+ exaDoMigration (pixmaps, 2, TRUE);
+ }
/* Mixed directions must be handled specially if the card is lame */
if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
@@ -766,7 +770,6 @@ exaPolyFillRect(DrawablePtr pDrawable,
int xoff, yoff;
int xorg, yorg;
int n;
- ExaMigrationRec pixmaps[2];
RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
/* Compute intersection of rects and clip region */
@@ -777,11 +780,6 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto out;
}
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
-
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
if (pExaScr->swappedOut || pExaPixmap->accel_blocked)
@@ -814,7 +812,16 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto fallback;
}
- exaDoMigration (pixmaps, 1, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
if (!exaPixmapIsOffscreen (pPixmap) ||
!(*pExaScr->info->PrepareSolid) (pPixmap,
@@ -972,23 +979,23 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
int xoff, yoff;
- ExaMigrationRec pixmaps[1];
Bool ret = FALSE;
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
- alu, clientClipType)
- ? NULL : pRegion;
-
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (pExaPixmap->accel_blocked)
- {
goto out;
- } else {
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
+ alu, clientClipType) ? NULL : pRegion;
+
exaDoMigration (pixmaps, 1, TRUE);
}
@@ -1010,7 +1017,7 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
(*pExaScr->info->DoneSolid) (pPixmap);
exaMarkSync(pDrawable->pScreen);
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+ if (pExaPixmap->pDamage &&
pDrawable->width == 1 && pDrawable->height == 1 &&
pDrawable->bitsPerPixel != 24) {
ExaPixmapPriv(pPixmap);
@@ -1053,7 +1060,6 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
int xoff, yoff;
int tileWidth, tileHeight;
- ExaMigrationRec pixmaps[2];
int nbox = REGION_NUM_RECTS (pRegion);
BoxPtr pBox = REGION_RECTS (pRegion);
Bool ret = FALSE;
@@ -1070,23 +1076,25 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
exaGetPixmapFirstPixel (pTile), planemask,
alu, clientClipType);
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
- alu, clientClipType)
- ? NULL : pRegion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pTile;
- pixmaps[1].pReg = NULL;
-
+ pPixmap = exaGetDrawablePixmap (pDrawable);
pExaPixmap = ExaGetPixmapPriv (pPixmap);
if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
- {
return FALSE;
- } else {
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
+ alu, clientClipType) ? NULL : pRegion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pTile;
+ pixmaps[1].pReg = NULL;
+
exaDoMigration (pixmaps, 2, TRUE);
}
@@ -1225,31 +1233,36 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d)
{
ExaScreenPriv (pDrawable->pScreen);
- ExaMigrationRec pixmaps[1];
- BoxRec Box;
- RegionRec Reg;
- PixmapPtr pPix;
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
int xoff, yoff;
Bool ok;
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = &Reg;
+ if (pExaScr->swappedOut)
+ goto fallback;
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;
+ if (pExaScr->do_migration) {
+ BoxRec Box;
+ RegionRec Reg;
+ ExaMigrationRec pixmaps[1];
- REGION_INIT(pScreen, &Reg, &Box, 1);
+ Box.x1 = pDrawable->y + x + xoff;
+ Box.y1 = pDrawable->y + y + yoff;
+ Box.x2 = Box.x1 + w;
+ Box.y2 = Box.y1 + h;
- if (pExaScr->swappedOut)
- goto fallback;
+ REGION_INIT(pScreen, &Reg, &Box, 1);
- exaDoMigration(pixmaps, 1, FALSE);
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPix;
+ pixmaps[0].pReg = &Reg;
+
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ REGION_UNINIT(pScreen, &Reg);
+ }
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
@@ -1271,12 +1284,9 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
PixmapBytePad(w, pDrawable->depth));
if (ok) {
exaWaitSync(pDrawable->pScreen);
- goto out;
+ return;
}
fallback:
ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
-
-out:
- REGION_UNINIT(pScreen, &Reg);
}
diff --git a/exa/exa_classic.c b/exa/exa_classic.c
new file mode 100644
index 000000000..1eff57091
--- /dev/null
+++ b/exa/exa_classic.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the classic exa specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ if (pExaPixmap->offscreen && pExaPixmap->fb_ptr)
+ return pExaPixmap->fb_ptr;
+ else
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * If width and height are 0, this won't be a full-fledged pixmap and it will
+ * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
+ * ModifyPixmapHeader() would break migration. These types of pixmaps are used
+ * for scratch pixmaps, or to represent the visible screen.
+ */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ BoxRec box;
+ int bpp;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ pExaPixmap->driverPriv = NULL;
+ /* Scratch pixmaps may have w/h equal to zero, and may not be
+ * migrated.
+ */
+ if (!w || !h)
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ else
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+
+ pPixmap->devPrivate.ptr = NULL;
+ pExaPixmap->offscreen = FALSE;
+
+ pExaPixmap->fb_ptr = NULL;
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
+
+ if (pExaPixmap->fb_pitch > 131071) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* 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->area = NULL;
+
+ /* We set the initial pixmap as completely valid for a simple reason.
+ * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
+ * could form single pixel rects as part of a region. Setting the complete region
+ * as valid is a natural defragmentation of the region.
+ */
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+ REGION_INIT(pScreen, &pExaPixmap->validSys, &box, 0);
+ REGION_INIT(pScreen, &pExaPixmap->validFB, &box, 0);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ /* Classic EXA:
+ * - Framebuffer.
+ * - Scratch pixmap with offscreen memory.
+ */
+ if (pExaScr->info->memoryBase && pPixData) {
+ if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
+ ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
+ pExaScr->info->memorySize) {
+ pExaPixmap->fb_ptr = pPixData;
+ pExaPixmap->fb_pitch = devKind;
+ pExaPixmap->offscreen = TRUE;
+ }
+ }
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+
+ /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
+ * offscreen memory, so there's no need to track damage.
+ */
+ if (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ if (pExaPixmap->area)
+ {
+ DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ ExaGetPixmapPriv(pPixmap)->area->offset,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ /* Free the offscreen area */
+ exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ }
+ REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validSys);
+ REGION_UNINIT(pPixmap->drawable.pScreen, &pExaPixmap->validFB);
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapIsOffscreen_classic(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ Bool ret;
+
+ if (pExaScr->info->PixmapIsOffscreen) {
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = NULL;
+ } else
+ ret = (pExaPixmap->offscreen && pExaPixmap->fb_ptr);
+
+ return ret;
+}
diff --git a/exa/exa_driver.c b/exa/exa_driver.c
new file mode 100644
index 000000000..97036955b
--- /dev/null
+++ b/exa/exa_driver.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the driver allocated pixmaps specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * Pixmaps are always marked as pinned, because exa has no control over them.
+ */
+PixmapPtr
+exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth, datasize;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ /* Set this before driver hooks, to allow for !offscreen pixmaps.
+ * !offscreen pixmaps have a valid pointer at all times.
+ */
+ pPixmap->devPrivate.ptr = NULL;
+
+ if (pExaScr->info->CreatePixmap2) {
+ int new_pitch = 0;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
+ paddedWidth = pExaPixmap->fb_pitch = new_pitch;
+ }
+ else {
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (paddedWidth / 4 > 32767 || h > 32767)
+ return NullPixmap;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+ datasize = h * paddedWidth;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
+ }
+
+ if (!pExaPixmap->driverPriv) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+ pExaPixmap->sys_ptr = NULL;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ pExaPixmap->area = NULL;
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+ }
+
+ if (pExaScr->info->ModifyPixmapHeader) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
+ * 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;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_driver (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ if (pExaPixmap->driverPriv)
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapIsOffscreen_driver(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c
index b8d2e52bf..d621ccf76 100644
--- a/exa/exa_glyphs.c
+++ b/exa/exa_glyphs.c
@@ -372,7 +372,6 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
PixmapPtr pGlyphPixmap = (PixmapPtr)pGlyphPicture->pDrawable;
ExaPixmapPriv(pGlyphPixmap);
PixmapPtr pCachePixmap = (PixmapPtr)cache->picture->pDrawable;
- ExaMigrationRec pixmaps[1];
if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || pExaPixmap->accel_blocked)
goto composite;
@@ -386,12 +385,16 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel)
goto composite;
- /* cache pixmap must be offscreen. */
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pCachePixmap;
- pixmaps[0].pReg = NULL;
- exaDoMigration (pixmaps, 1, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ /* cache pixmap must be offscreen. */
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pCachePixmap;
+ pixmaps[0].pReg = NULL;
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
if (!exaPixmapIsOffscreen(pCachePixmap))
goto composite;
diff --git a/exa/exa_migration.c b/exa/exa_migration_classic.c
index f6805cb6e..d8e1e86da 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration_classic.c
@@ -42,22 +42,6 @@
#endif
/**
- * Returns TRUE if the pixmap is not movable. This is the case where it's a
- * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
- * some X Server internal component (the score says it's pinned).
- */
-static Bool
-exaPixmapIsPinned (PixmapPtr pPix)
-{
- ExaPixmapPriv (pPix);
-
- if (pExaPixmap == NULL)
- EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
-
- return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
-}
-
-/**
* The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
* and exaCopyDirtyToFb both needed to do this loop.
*/
@@ -77,7 +61,7 @@ exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int 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
@@ -382,7 +366,7 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate)
}
void
-exaMoveInPixmap (PixmapPtr pPixmap)
+exaMoveInPixmap_classic (PixmapPtr pPixmap)
{
static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
.pReg = NULL };
@@ -423,7 +407,7 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate)
}
void
-exaMoveOutPixmap (PixmapPtr pPixmap)
+exaMoveOutPixmap_classic (PixmapPtr pPixmap)
{
static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
.pReg = NULL };
@@ -607,17 +591,12 @@ out:
* config file.
*/
void
-exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
{
ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
ExaScreenPriv(pScreen);
int i, j;
- if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
- return;
- if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
- return;
-
/* If this debugging flag is set, check each pixmap for whether it is marked
* as clean, and if so, actually check if that's the case. This should help
* catch issues with failing to mark a drawable as dirty. While it will
diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c
new file mode 100644
index 000000000..d1ee9871b
--- /dev/null
+++ b/exa/exa_migration_mixed.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#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;
+
+ /* Already done. */
+ if (pExaPixmap->driverPriv)
+ return;
+
+ if (exaPixmapIsPinned(pPixmap))
+ return;
+
+ /* Can't accel 1/4 bpp. */
+ if (pExaPixmap->accel_blocked || bpp < 8)
+ return;
+
+ if (pExaScr->info->CreatePixmap2) {
+ int new_pitch = 0;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
+ paddedWidth = pExaPixmap->fb_pitch = new_pitch;
+ } else {
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, paddedWidth*h, 0);
+ }
+
+ 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
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ int i;
+
+ /* If anything is pinned in system memory, we won't be able to
+ * accelerate.
+ */
+ for (i = 0; i < npixmaps; i++) {
+ if (exaPixmapIsPinned (pixmaps[i].pPix) &&
+ !exaPixmapIsOffscreen (pixmaps[i].pPix))
+ {
+ can_accel = FALSE;
+ break;
+ }
+ }
+
+ /* We can do nothing. */
+ if (!can_accel)
+ return;
+
+ for (i = 0; i < npixmaps; i++) {
+ PixmapPtr pPixmap = pixmaps[i].pPix;
+ ExaPixmapPriv(pPixmap);
+ if (!pExaPixmap->driverPriv)
+ exaCreateDriverPixmap_mixed(pPixmap);
+ }
+}
+
+void
+exaMoveInPixmap_mixed(PixmapPtr pPixmap)
+{
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration(pixmaps, 1, TRUE);
+}
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
new file mode 100644
index 000000000..01f87ba87
--- /dev/null
+++ b/exa/exa_mixed.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#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*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * 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,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth, datasize;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ 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;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ 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);
+ }
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ 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 (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+
+ /* Anything can happen, don't try to predict it all. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ }
+
+ /* Only pass driver pixmaps to the driver. */
+ if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
+ * 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;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (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;
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapIsOffscreen_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ pointer saved_ptr;
+ Bool ret;
+
+ if (!pExaPixmap->driverPriv)
+ return FALSE;
+
+ saved_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = saved_ptr;
+
+ return ret;
+}
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index b3df1a586..869cf1772 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -142,6 +142,13 @@ typedef struct {
#define EXA_FALLBACK_COPYWINDOW (1 << 0)
#define EXA_ACCEL_COPYWINDOW (1 << 1)
+typedef struct _ExaMigrationRec {
+ Bool as_dst;
+ Bool as_src;
+ PixmapPtr pPix;
+ RegionPtr pReg;
+} ExaMigrationRec, *ExaMigrationPtr;
+
typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
typedef struct {
ExaDriverPtr info;
@@ -165,7 +172,11 @@ typedef struct {
TrapezoidsProcPtr SavedTrapezoids;
AddTrapsProcPtr SavedAddTraps;
#endif
-
+ void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+ Bool (*pixmap_is_offscreen) (PixmapPtr pPixmap);
+ void (*do_move_in_pixmap) (PixmapPtr pPixmap);
+ void (*do_move_out_pixmap) (PixmapPtr pPixmap);
+
Bool swappedOut;
enum ExaMigrationHeuristic migration;
Bool checkDirtyCorrectness;
@@ -176,8 +187,11 @@ typedef struct {
CARD32 lastDefragment;
CARD32 nextDefragment;
- /* Store all accessed pixmaps, so we can check for duplicates. */
- PixmapPtr prepare_access[6];
+ /* Reference counting for accessed pixmaps */
+ struct {
+ PixmapPtr pixmap;
+ int count;
+ } access[EXA_NUM_PREPARE_INDICES];
/* Holds information on fallbacks that cannot be relayed otherwise. */
unsigned int fallback_flags;
@@ -300,13 +314,6 @@ typedef struct {
GCFuncs *Savedfuncs;
} ExaGCPrivRec, *ExaGCPrivPtr;
-typedef struct _ExaMigrationRec {
- Bool as_dst;
- Bool as_src;
- PixmapPtr pPix;
- RegionPtr pReg;
-} ExaMigrationRec, *ExaMigrationPtr;
-
typedef struct {
PicturePtr pDst;
INT16 xSrc;
@@ -440,6 +447,34 @@ void
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d);
+RegionPtr
+exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty);
+
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown);
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure);
+
extern const GCOps exaOps;
#ifdef RENDER
@@ -503,36 +538,77 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp);
PixmapPtr
exaGetDrawablePixmap(DrawablePtr pDrawable);
-RegionPtr
-exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
- int srcx, int srcy, int width, int height, int dstx, int dsty);
+void
+exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
+ int w, int h, int bpp);
-Bool
-exaHWCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown);
+void
+exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
+ int w, int h, int bpp);
void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure);
+exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+
+Bool
+exaPixmapIsPinned (PixmapPtr pPix);
extern const GCFuncs exaGCFuncs;
+/* exa_classic.c */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap);
+
+Bool
+exaPixmapIsOffscreen_classic(PixmapPtr pPixmap);
+
+/* exa_driver.c */
+PixmapPtr
+exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_driver (PixmapPtr pPixmap);
+
+Bool
+exaPixmapIsOffscreen_driver(PixmapPtr pPixmap);
+
+/* exa_mixed.c */
+PixmapPtr
+exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint);
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData);
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap);
+
+Bool
+exaPixmapIsOffscreen_mixed(PixmapPtr pPixmap);
+
+/* exa_migration_mixed.c */
+void
+exaCreateDriverPixmap_mixed(PixmapPtr pPixmap);
+
+void
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+
+void
+exaMoveInPixmap_mixed(PixmapPtr pPixmap);
+
/* exa_render.c */
Bool
exaOpReadsDestination (CARD8 op);
@@ -587,11 +663,17 @@ exaGlyphs (CARD8 op,
GlyphListPtr list,
GlyphPtr *glyphs);
-/* exa_migration.c */
+/* exa_migration_classic.c */
void
-exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
void
exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area);
+void
+exaMoveOutPixmap_classic (PixmapPtr pPixmap);
+
+void
+exaMoveInPixmap_classic (PixmapPtr pPixmap);
+
#endif /* EXAPRIV_H */
diff --git a/exa/exa_render.c b/exa/exa_render.c
index 14d710b57..d46930130 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -54,6 +54,12 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
case PICT_x8r8g8b8:
snprintf(format, 20, "XRGB8888");
break;
+ case PICT_b8g8r8a8:
+ snprintf(format, 20, "BGRA8888");
+ break;
+ case PICT_b8g8r8x8:
+ snprintf(format, 20, "BGRX8888");
+ break;
case PICT_r5g6b5:
snprintf(format, 20, "RGB565 ");
break;
@@ -71,11 +77,17 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n)
break;
}
- loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
+ if (pict->pDrawable) {
+ loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm';
- snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
- pict->pDrawable->height, pict->repeat ?
- " R" : "");
+ snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
+ pict->pDrawable->height, pict->repeat ?
+ " R" : "");
+ } else {
+ loc = '-';
+
+ snprintf(size, 20, "%s", pict->repeat ? " R" : "");
+ }
snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, size);
}
@@ -138,32 +150,26 @@ exaGetPixelFromRGBA(CARD32 *pixel,
CARD16 green,
CARD16 blue,
CARD16 alpha,
- CARD32 format)
+ PictFormatPtr pFormat)
{
int rbits, bbits, gbits, abits;
int rshift, bshift, gshift, ashift;
*pixel = 0;
- if (!PICT_FORMAT_COLOR(format))
+ if (!PICT_FORMAT_COLOR(pFormat->format) &&
+ PICT_FORMAT_TYPE(pFormat->format) != PICT_TYPE_A)
return FALSE;
- rbits = PICT_FORMAT_R(format);
- gbits = PICT_FORMAT_G(format);
- bbits = PICT_FORMAT_B(format);
- abits = PICT_FORMAT_A(format);
-
- if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
- bshift = 0;
- gshift = bbits;
- rshift = gshift + gbits;
- ashift = rshift + rbits;
- } else { /* PICT_TYPE_ABGR */
- rshift = 0;
- gshift = rbits;
- bshift = gshift + gbits;
- ashift = bshift + bbits;
- }
+ rbits = PICT_FORMAT_R(pFormat->format);
+ gbits = PICT_FORMAT_G(pFormat->format);
+ bbits = PICT_FORMAT_B(pFormat->format);
+ abits = PICT_FORMAT_A(pFormat->format);
+
+ rshift = pFormat->direct.red;
+ gshift = pFormat->direct.green;
+ bshift = pFormat->direct.blue;
+ ashift = pFormat->direct.alpha;
*pixel |= ( blue >> (16 - bbits)) << bshift;
*pixel |= ( red >> (16 - rbits)) << rshift;
@@ -179,30 +185,24 @@ exaGetRGBAFromPixel(CARD32 pixel,
CARD16 *green,
CARD16 *blue,
CARD16 *alpha,
- CARD32 format)
+ PictFormatPtr pFormat)
{
int rbits, bbits, gbits, abits;
int rshift, bshift, gshift, ashift;
- if (!PICT_FORMAT_COLOR(format))
+ if (!PICT_FORMAT_COLOR(pFormat->format) &&
+ PICT_FORMAT_TYPE(pFormat->format) != PICT_TYPE_A)
return FALSE;
- rbits = PICT_FORMAT_R(format);
- gbits = PICT_FORMAT_G(format);
- bbits = PICT_FORMAT_B(format);
- abits = PICT_FORMAT_A(format);
-
- if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
- bshift = 0;
- gshift = bbits;
- rshift = gshift + gbits;
- ashift = rshift + rbits;
- } else { /* PICT_TYPE_ABGR */
- rshift = 0;
- gshift = rbits;
- bshift = gshift + gbits;
- ashift = bshift + bbits;
- }
+ rbits = PICT_FORMAT_R(pFormat->format);
+ gbits = PICT_FORMAT_G(pFormat->format);
+ bbits = PICT_FORMAT_B(pFormat->format);
+ abits = PICT_FORMAT_A(pFormat->format);
+
+ rshift = pFormat->direct.red;
+ gshift = pFormat->direct.green;
+ bshift = pFormat->direct.blue;
+ ashift = pFormat->direct.alpha;
*red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
while (rbits < 16) {
@@ -250,28 +250,22 @@ exaTryDriverSolidFill(PicturePtr pSrc,
int nbox;
int dst_off_x, dst_off_y;
PixmapPtr pSrcPix, pDstPix;
- ExaPixmapPrivPtr pSrcExaPix, pDstExaPix;
+ ExaPixmapPrivPtr pDstExaPix;
CARD32 pixel;
CARD16 red, green, blue, alpha;
- ExaMigrationRec pixmaps[1];
pDstPix = exaGetDrawablePixmap (pDst->pDrawable);
- pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
-
- pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
pDstExaPix = ExaGetPixmapPriv(pDstPix);
- /* Check whether the accelerator can use these pixmaps.
+ /* Check whether the accelerator can use the destination pixmap.
*/
- if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked)
+ if (pDstExaPix->accel_blocked)
{
return -1;
}
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
xSrc, ySrc, 0, 0, xDst, yDst,
@@ -282,31 +276,37 @@ exaTryDriverSolidFill(PicturePtr pSrc,
REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
- pixel = exaGetPixmapFirstPixel (pSrcPix);
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPix;
- pixmaps[0].pReg = &region;
- exaDoMigration(pixmaps, 1, TRUE);
+ if (pSrc->pDrawable) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
- if (!exaPixmapIsOffscreen(pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return 0;
- }
+ pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable);
+ pixel = exaGetPixmapFirstPixel (pSrcPix);
+ } else
+ pixel = pSrc->pSourcePict->solidFill.color;
if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha,
- pSrc->format))
+ pSrc->pFormat) ||
+ !exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
+ pDst->pFormat))
{
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return -1;
}
- if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha,
- pDst->format))
- {
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pDstPix;
+ pixmaps[0].pReg = &region;
+ exaDoMigration(pixmaps, 1, TRUE);
+ }
+
+ if (!exaPixmapIsOffscreen(pDstPix)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return -1;
+ return 0;
}
if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel))
@@ -341,17 +341,18 @@ exaTryDriverCompositeRects(CARD8 op,
{
ExaScreenPriv (pDst->pDrawable->pScreen);
int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
- PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
- ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
- ExaMigrationRec pixmaps[3];
+ PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
+ ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
if (!pExaScr->info->PrepareComposite)
return -1;
- pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
- pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ if (pSrc->pDrawable) {
+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+ pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ }
- if (pMask) {
+ if (pMask && pMask->pDrawable) {
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
}
@@ -363,8 +364,9 @@ exaTryDriverCompositeRects(CARD8 op,
* FIXME: If it cannot, use temporary pixmaps so that the drawing
* happens within limits.
*/
- if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked ||
- (pMask && pMaskExaPix->accel_blocked))
+ if (pDstExaPix->accel_blocked ||
+ (pSrcExaPix && pSrcExaPix->accel_blocked) ||
+ (pMaskExaPix && pMaskExaPix->accel_blocked))
{
return -1;
}
@@ -374,36 +376,48 @@ exaTryDriverCompositeRects(CARD8 op,
{
return -1;
}
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = exaOpReadsDestination(op);
- pixmaps[0].pPix = pDstPix;
- pixmaps[0].pReg = NULL;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPix;
- pixmaps[1].pReg = NULL;
- if (pMask) {
- pixmaps[2].as_dst = FALSE;
- pixmaps[2].as_src = TRUE;
- pixmaps[2].pPix = pMaskPix;
- pixmaps[2].pReg = NULL;
- exaDoMigration(pixmaps, 3, TRUE);
- } else
- exaDoMigration(pixmaps, 2, TRUE);
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[3];
+ int i = 0;
+
+ pixmaps[i].as_dst = TRUE;
+ pixmaps[i].as_src = exaOpReadsDestination(op);
+ pixmaps[i].pPix = pDstPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+
+ if (pSrcPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pSrcPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
+
+ if (pMaskPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pMaskPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
+
+ exaDoMigration(pixmaps, i, TRUE);
+ }
pDstPix = exaGetOffscreenPixmap (pDst->pDrawable, &dst_off_x, &dst_off_y);
if (!pDstPix)
return 0;
-
- pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
- if (!pSrcPix)
- return 0;
+ if (pSrcPix) {
+ pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (!pSrcPix)
+ return 0;
+ }
- if (pMask) {
+ if (pMaskPix) {
pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y);
-
if (!pMaskPix)
return 0;
}
@@ -416,15 +430,24 @@ exaTryDriverCompositeRects(CARD8 op,
{
INT16 xDst = rects->xDst + pDst->pDrawable->x;
INT16 yDst = rects->yDst + pDst->pDrawable->y;
- INT16 xMask = pMask ? rects->xMask + pMask->pDrawable->x : 0;
- INT16 yMask = pMask ? rects->yMask + pMask->pDrawable->y : 0;
- INT16 xSrc = rects->xSrc + pSrc->pDrawable->x;
- INT16 ySrc = rects->ySrc + pSrc->pDrawable->y;
-
+ INT16 xMask = rects->xMask;
+ INT16 yMask = rects->yMask;
+ INT16 xSrc = rects->xSrc;
+ INT16 ySrc = rects->ySrc;
RegionRec region;
BoxPtr pbox;
int nbox;
-
+
+ if (pMaskPix) {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ }
+
+ if (pSrcPix) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ }
+
if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
xSrc, ySrc, xMask, yMask, xDst, yDst,
rects->width, rects->height))
@@ -482,8 +505,6 @@ exaCompositeRects(CARD8 op,
ExaCompositeRectPtr rects)
{
ExaScreenPriv (pDst->pDrawable->pScreen);
- PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable);
- ExaPixmapPriv(pPixmap);
int n;
ExaCompositeRectPtr r;
int ret;
@@ -491,7 +512,7 @@ exaCompositeRects(CARD8 op,
/* If we get a mask, that means we're rendering to the exaGlyphs
* destination directly, so the damage layer takes care of this.
*/
- if (!pMask && pExaPixmap->pDamage) {
+ if (!pMask) {
RegionRec region;
int x1 = MAXSHORT;
int y1 = MAXSHORT;
@@ -585,7 +606,7 @@ exaCompositeRects(CARD8 op,
/************************************************************/
- if (!pMask && pExaPixmap->pDamage) {
+ if (!pMask) {
/* Now we have to flush the damage out from pendingDamage => damage
* Calling DamageRegionProcessPending has that effect.
*/
@@ -613,17 +634,18 @@ exaTryDriverComposite(CARD8 op,
BoxPtr pbox;
int nbox;
int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y;
- PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix;
- ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix;
- ExaMigrationRec pixmaps[3];
+ PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix;
+ ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix;
- pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
- pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ if (pSrc->pDrawable) {
+ pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
+ pSrcExaPix = ExaGetPixmapPriv(pSrcPix);
+ }
pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
pDstExaPix = ExaGetPixmapPriv(pDstPix);
- if (pMask) {
+ if (pMask && pMask->pDrawable) {
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
pMaskExaPix = ExaGetPixmapPriv(pMaskPix);
}
@@ -632,8 +654,8 @@ exaTryDriverComposite(CARD8 op,
* FIXME: If it cannot, use temporary pixmaps so that the drawing
* happens within limits.
*/
- if (pSrcExaPix->accel_blocked ||
- pDstExaPix->accel_blocked ||
+ if (pDstExaPix->accel_blocked ||
+ (pSrcExaPix && pSrcExaPix->accel_blocked) ||
(pMask && (pMaskExaPix->accel_blocked)))
{
return -1;
@@ -642,13 +664,15 @@ exaTryDriverComposite(CARD8 op,
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
- if (pMask) {
+ if (pMaskPix) {
xMask += pMask->pDrawable->x;
yMask += pMask->pDrawable->y;
}
- xSrc += pSrc->pDrawable->x;
- ySrc += pSrc->pDrawable->y;
+ if (pSrcPix) {
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ }
if (pExaScr->info->CheckComposite &&
!(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst))
@@ -665,35 +689,53 @@ exaTryDriverComposite(CARD8 op,
REGION_TRANSLATE(pScreen, &region, dst_off_x, dst_off_y);
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = exaOpReadsDestination(op);
- pixmaps[0].pPix = pDstPix;
- pixmaps[0].pReg = pixmaps[0].as_src ? NULL : &region;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPix;
- pixmaps[1].pReg = NULL;
- if (pMask) {
- pixmaps[2].as_dst = FALSE;
- pixmaps[2].as_src = TRUE;
- pixmaps[2].pPix = pMaskPix;
- pixmaps[2].pReg = NULL;
- exaDoMigration(pixmaps, 3, TRUE);
- } else {
- exaDoMigration(pixmaps, 2, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[3];
+ int i = 0;
+
+ pixmaps[i].as_dst = TRUE;
+ pixmaps[i].as_src = exaOpReadsDestination(op);
+ pixmaps[i].pPix = pDstPix;
+ pixmaps[i].pReg = pixmaps[0].as_src ? NULL : &region;
+ i++;
+
+ if (pSrcPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pSrcPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
+
+ if (pMaskPix) {
+ pixmaps[i].as_dst = FALSE;
+ pixmaps[i].as_src = TRUE;
+ pixmaps[i].pPix = pMaskPix;
+ pixmaps[i].pReg = NULL;
+ i++;
+ }
+
+ exaDoMigration(pixmaps, i, TRUE);
}
- pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
- if (pMask)
+ if (pSrcPix) {
+ pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y);
+ if (!pSrcPix) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ return 0;
+ }
+ }
+
+ if (pMaskPix) {
pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x,
&mask_off_y);
-
- if (!exaPixmapIsOffscreen(pDstPix)) {
- REGION_UNINIT(pDst->pDrawable->pScreen, &region);
- return 0;
+ if (!pMaskPix) {
+ REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+ return 0;
+ }
}
- if (!pSrcPix || (pMask && !pMaskPix)) {
+ if (!exaPixmapIsOffscreen(pDstPix)) {
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
return 0;
}
@@ -844,43 +886,44 @@ exaComposite(CARD8 op,
Bool saveMaskRepeat = pMask ? pMask->repeat : 0;
RegionRec region;
- /* We currently don't support acceleration of gradients, or other pictures
- * with a NULL pDrawable.
- */
- if (pExaScr->swappedOut ||
- pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL))
- {
+ if (pExaScr->swappedOut)
goto fallback;
- }
/* Remove repeat in source if useless */
- if (pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
+ if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform && xSrc >= 0 &&
(xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 &&
(ySrc + height) <= pSrc->pDrawable->height)
pSrc->repeat = 0;
- if (!pMask)
+ if (!pMask && !pSrc->alphaMap && !pDst->alphaMap &&
+ (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format))))
{
- if ((op == PictOpSrc &&
- ((pSrc->format == pDst->format) ||
- (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
- (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
- (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
- pSrc->format == pDst->format &&
- (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))
+ if (pSrc->pDrawable ?
+ (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
+ pSrc->repeat) :
+ (pSrc->pSourcePict->type == SourcePictTypeSolidFill))
{
- if (pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 &&
- pSrc->repeat)
- {
- ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
- width, height);
- if (ret == 1)
- goto done;
- }
- else if (pSrc->pDrawable != NULL &&
- !pSrc->repeat &&
- !pSrc->transform)
+ ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst,
+ width, height);
+ if (ret == 1)
+ goto done;
+ } else if (pSrc->pDrawable && !pSrc->transform &&
+ ((op == PictOpSrc &&
+ (pSrc->format == pDst->format ||
+ (PICT_FORMAT_COLOR(pDst->format) &&
+ PICT_FORMAT_COLOR(pSrc->format) &&
+ pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format),
+ PICT_FORMAT_TYPE(pSrc->format),
+ 0,
+ PICT_FORMAT_R(pSrc->format),
+ PICT_FORMAT_G(pSrc->format),
+ PICT_FORMAT_B(pSrc->format))))) ||
+ (op == PictOpOver && pSrc->format == pDst->format &&
+ !PICT_FORMAT_A(pSrc->format))))
+ {
+ if (!pSrc->repeat && xSrc >= 0 && ySrc >= 0 &&
+ (xSrc + width <= pSrc->pDrawable->width) &&
+ (ySrc + height <= pSrc->pDrawable->height))
{
Bool ret;
xDst += pDst->pDrawable->x;
@@ -909,10 +952,9 @@ exaComposite(CARD8 op,
goto done;
}
- else if (pSrc->pDrawable != NULL &&
- pSrc->pDrawable->type == DRAWABLE_PIXMAP &&
- !pSrc->transform &&
- pSrc->repeatType == RepeatNormal)
+
+ if (pSrc->repeat && pSrc->repeatType == RepeatNormal &&
+ pSrc->pDrawable->type == DRAWABLE_PIXMAP)
{
DDXPointRec patOrg;
@@ -962,9 +1004,9 @@ exaComposite(CARD8 op,
}
/* Remove repeat in mask if useless */
- if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 &&
- (xMask + width) <= pMask->pDrawable->width && yMask >= 0 &&
- (yMask + height) <= pMask->pDrawable->height)
+ if (pMask && pMask->pDrawable && pMask->repeat && !pMask->transform &&
+ xMask >= 0 && (xMask + width) <= pMask->pDrawable->width &&
+ yMask >= 0 && (yMask + height) <= pMask->pDrawable->height)
pMask->repeat = 0;
if (pExaScr->info->PrepareComposite &&
@@ -980,9 +1022,10 @@ exaComposite(CARD8 op,
/* For generic masks and solid src pictures, mach64 can do Over in two
* passes, similar to the component-alpha case.
*/
- isSrcSolid = pSrc->pDrawable->width == 1 &&
- pSrc->pDrawable->height == 1 &&
- pSrc->repeat;
+ isSrcSolid = pSrc->pDrawable ?
+ (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 &&
+ pSrc->repeat) :
+ (pSrc->pSourcePict->type == SourcePictTypeSolidFill);
/* If we couldn't do the Composite in a single pass, and it was a
* component-alpha Over, see if we can do it in two passes with
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index 0d53b67d8..f4700adac 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -492,58 +492,37 @@ ExaCheckAddTraps (PicturePtr pPicture,
/**
* Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
* that happen to be 1x1. Pixmap must be at least 8bpp.
- *
- * XXX This really belongs in fb, so it can be aware of tiling and etc.
*/
CARD32
exaGetPixmapFirstPixel (PixmapPtr pPixmap)
{
- CARD32 pixel;
- void *fb;
- Bool need_finish = FALSE;
- BoxRec box;
- RegionRec migration;
- ExaPixmapPriv (pPixmap);
- Bool sys_valid = pExaPixmap->pDamage &&
- !miPointInRegion(&pExaPixmap->validSys, 0, 0, &box);
- Bool damaged = pExaPixmap->pDamage &&
- miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box);
- Bool offscreen = exaPixmapIsOffscreen(pPixmap);
-
- fb = pExaPixmap->sys_ptr;
-
- /* Try to avoid framebuffer readbacks */
- if ((!offscreen && !sys_valid && !damaged) ||
- (offscreen && (!sys_valid || damaged)))
- {
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = 1;
- box.y2 = 1;
- REGION_INIT(pScreen, &migration, &box, 1);
-
- need_finish = TRUE;
-
- exaPrepareAccessReg(&pPixmap->drawable, EXA_PREPARE_SRC, &migration);
- fb = pPixmap->devPrivate.ptr;
- }
-
switch (pPixmap->drawable.bitsPerPixel) {
case 32:
- pixel = *(CARD32 *)fb;
- break;
+ {
+ CARD32 pixel;
+
+ pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
+ ZPixmap, ~0, (char*)&pixel);
+ return pixel;
+ }
case 16:
- pixel = *(CARD16 *)fb;
- break;
+ {
+ CARD16 pixel;
+
+ pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
+ ZPixmap, ~0, (char*)&pixel);
+ return pixel;
+ }
+ case 8:
+ {
+ CARD8 pixel;
+
+ pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
+ ZPixmap, ~0, (char*)&pixel);
+ return pixel;
+ }
default:
- pixel = *(CARD8 *)fb;
- break;
+ FatalError("%s called for invalid bpp %d\n", __func__,
+ pPixmap->drawable.bitsPerPixel);
}
-
- if (need_finish) {
- exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
- REGION_UNINIT(pScreen, &migration);
- }
-
- return pixel;
}