summaryrefslogtreecommitdiff
path: root/exa/exa_mixed.c
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-09-26 01:59:39 +0200
committerMichel Dänzer <daenzer@vmware.com>2009-09-26 01:59:39 +0200
commit1818cbd70fc1f2e1487b4c678e67e28f1265c0ef (patch)
treec19cc48b73ed6885079f48a321aa775068fae57e /exa/exa_mixed.c
parente23bffc41b007f1bc2b8f5cd4ac54213062c95cc (diff)
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.
Diffstat (limited to 'exa/exa_mixed.c')
-rw-r--r--exa/exa_mixed.c87
1 files changed, 35 insertions, 52 deletions
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
index 6aa73f2b6..167ffa9d5 100644
--- a/exa/exa_mixed.c
+++ b/exa/exa_mixed.c
@@ -32,8 +32,6 @@
#include "exa.h"
/* This file holds the driver allocated pixmaps + better initial placement code.
- * A pinned pixmap implies one that is either driver based already or otherwise altered.
- * Proper care is taken to free the initially allocated buffer.
*/
static _X_INLINE void*
@@ -46,9 +44,6 @@ ExaGetPixmapAddress(PixmapPtr p)
/**
* exaCreatePixmap() creates a new pixmap.
- *
- * Pixmaps are always marked as pinned, unless the pixmap can still be transfered to a
- * driver pixmaps.
*/
PixmapPtr
exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
@@ -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;
}
- }
- if (pPixData)
- pExaPixmap->sys_ptr = pPixData;
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+ }
- if (devKind > 0)
- pExaPixmap->sys_pitch = devKind;
+ pExaPixmap->offscreen = FALSE;
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ }
+ if (pExaPixmap->driverPriv) {
if (width > 0 && height > 0 && bitsPerPixel > 0) {
exaSetFbPitch(pExaScr, pExaPixmap,
width, height, bitsPerPixel);
@@ -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);