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.
This commit is contained in:
Michel Dänzer 2009-09-26 01:59:39 +02:00
commit 1818cbd70f
6 changed files with 232 additions and 216 deletions

View file

@ -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);
}