diff options
author | Michel Dänzer <daenzer@vmware.com> | 2009-09-26 01:59:39 +0200 |
---|---|---|
committer | Michel Dänzer <daenzer@vmware.com> | 2009-09-26 01:59:39 +0200 |
commit | 1818cbd70fc1f2e1487b4c678e67e28f1265c0ef (patch) | |
tree | c19cc48b73ed6885079f48a321aa775068fae57e /exa/exa_mixed.c | |
parent | e23bffc41b007f1bc2b8f5cd4ac54213062c95cc (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.c | 87 |
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); |