EXA: Extend mixed pixmaps scheme to allow driver PrepareAccess hook to fail.
If the PrepareAccess hook fails, use the DownloadFromScreen hook to retrieve
driver pixmap contents to a system RAM copy, perform software rendering on that
and copy the results back using the UploadToScreen hook. Use the classic
migration logic to minimize transfers (which as a bonus allows slightly
cleaning up some of the existing mixed pixmap code).
This enables things that weren't possible before with driver-allocated pixmap
storage: If some (or all) GPU pixmap storage can't be mapped directly by the
CPU, this can be handled between the PrepareAccess and
DownloadFrom/UploadToScreen hooks, e.g.:
* Radeon KMS on big endian machines can fail PrepareAccess if the pixmap
requires byte-swapping and swap bytes in DownloadFrom/UploadToScreen.
* Environments where GPU and CPU don't have a shared address space at all.
Here the driver PrepareAccess hook will always fail and leave all transfers
between GPU / CPU storage to the Download/From/UploadToScreen hooks.
Drivers which can handle all pixmaps in the PrepareAccess hook should notice
little if any difference.
(cherry picked from commit 1818cbd70f
)
This commit is contained in:
parent
cecd484fbb
commit
e5371c7fc8
80
exa/exa.c
80
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)
|
||||
if (pExaScr->finish_access)
|
||||
pExaScr->finish_access(pPixmap, index);
|
||||
|
||||
if (!pExaScr->info->FinishAccess || !exaPixmapIsOffscreen(pPixmap))
|
||||
return;
|
||||
|
||||
if (!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",
|
||||
|
|
|
@ -120,7 +120,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,7 +225,7 @@ 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,
|
||||
|
@ -263,7 +263,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;
|
||||
|
@ -281,7 +281,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;
|
||||
|
@ -545,7 +545,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 +718,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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
@ -85,7 +80,6 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
|
|||
pExaPixmap->sys_pitch = paddedWidth;
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
pExaPixmap->offscreen = FALSE;
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
|
||||
|
@ -93,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;
|
||||
}
|
||||
|
@ -134,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;
|
||||
|
@ -142,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;
|
||||
}
|
||||
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
}
|
||||
|
||||
if (pPixData)
|
||||
pExaPixmap->sys_ptr = pPixData;
|
||||
|
||||
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);
|
||||
|
@ -169,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. */
|
||||
|
@ -182,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;
|
||||
}
|
||||
|
@ -196,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;
|
||||
|
||||
|
@ -215,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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -664,6 +669,12 @@ exaGlyphs (CARD8 op,
|
|||
GlyphPtr *glyphs);
|
||||
|
||||
/* exa_migration_classic.c */
|
||||
void
|
||||
exaCopyDirtyToSys (ExaMigrationPtr migrate);
|
||||
|
||||
void
|
||||
exaCopyDirtyToFb (ExaMigrationPtr migrate);
|
||||
|
||||
void
|
||||
exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
Box.x1 = pDrawable->y + x + xoff;
|
||||
Box.y1 = pDrawable->y + y + yoff;
|
||||
Box.x2 = Box.x1 + w;
|
||||
Box.y2 = Box.y1 + h;
|
||||
exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue