diff options
author | Maarten Maathuis <madman2003@gmail.com> | 2009-08-01 19:19:19 +0200 |
---|---|---|
committer | Maarten Maathuis <madman2003@gmail.com> | 2009-08-06 23:48:14 +0200 |
commit | 03ecb164f2592c954aa408bf121e0c67b604d854 (patch) | |
tree | 98acdd425239b9c8723cea9c537eebca70af8cba /exa | |
parent | ac7ac913fd98ea359c05c89968ab53a3223615b4 (diff) |
exa: A simple 3rd backend implementation.
- Based on driver pixmaps with some changes (completely transparent to driver).
- It helps with the problem of known software fallbacks, such as trapezoids.
- exaDoMigration is now called for all cases that provide a do_migration hook.
- exa_migration.c is renamed to exa_migration_classic.c
Diffstat (limited to 'exa')
-rw-r--r-- | exa/Makefile.am | 4 | ||||
-rw-r--r-- | exa/exa.c | 42 | ||||
-rw-r--r-- | exa/exa.h | 7 | ||||
-rw-r--r-- | exa/exa_accel.c | 34 | ||||
-rw-r--r-- | exa/exa_glyphs.c | 4 | ||||
-rw-r--r-- | exa/exa_migration_classic.c (renamed from exa/exa_migration.c) | 18 | ||||
-rw-r--r-- | exa/exa_migration_mixed.c | 136 | ||||
-rw-r--r-- | exa/exa_mixed.c | 229 | ||||
-rw-r--r-- | exa/exa_priv.h | 27 | ||||
-rw-r--r-- | exa/exa_render.c | 17 |
10 files changed, 460 insertions, 58 deletions
diff --git a/exa/Makefile.am b/exa/Makefile.am index bf2c138d8..8b759cd76 100644 --- a/exa/Makefile.am +++ b/exa/Makefile.am @@ -18,8 +18,10 @@ libexa_la_SOURCES = \ exa.c \ exa.h \ exa_classic.c \ - exa_migration.c \ + exa_migration_classic.c \ exa_driver.c \ + exa_mixed.c \ + exa_migration_mixed.c \ exa_accel.c \ exa_glyphs.c \ exa_offscreen.c \ @@ -217,6 +217,22 @@ exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, } /** + * 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). + */ +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; +} + +/** * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen * memory, meaning that acceleration could probably be done to it, and that it * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it @@ -237,7 +253,7 @@ exaPixmapIsOffscreen(PixmapPtr pPixmap) if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) return FALSE; - return pExaScr->pixmap_is_offscreen(pPixmap); + return (*pExaScr->pixmap_is_offscreen)(pPixmap); } /** @@ -348,9 +364,9 @@ void exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg) { PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); - ExaPixmapPriv(pPixmap); + ExaScreenPriv(pPixmap->drawable.pScreen); - if (pExaPixmap->pDamage) { + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) { @@ -1037,11 +1053,19 @@ exaDriverInit (ScreenPtr pScreen, return FALSE; } if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) { - 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; + 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; + } 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; + } } else { wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic); @@ -1162,5 +1186,5 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) return; if (pExaScr->do_migration) - pExaScr->do_migration(pixmaps, npixmaps, can_accel); + (*pExaScr->do_migration)(pixmaps, npixmaps, can_accel); } @@ -758,6 +758,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 */ diff --git a/exa/exa_accel.c b/exa/exa_accel.c index bc970bbe1..33fbb9843 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -57,7 +57,9 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, { ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; - } else if (pExaPixmap->pDamage) { + } + + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; @@ -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); @@ -455,7 +457,7 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable, } } - if (pDstExaPixmap->pDamage || pSrcExaPixmap->pDamage) { + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[2]; pixmaps[0].as_dst = TRUE; @@ -466,6 +468,7 @@ exaHWCopyNtoN (DrawablePtr pSrcDrawable, pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pSrcPixmap; pixmaps[1].pReg = srcregion; + exaDoMigration (pixmaps, 2, TRUE); } @@ -809,7 +812,7 @@ exaPolyFillRect(DrawablePtr pDrawable, goto fallback; } - if (pExaPixmap->pDamage) { + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; @@ -982,17 +985,16 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); if (pExaPixmap->accel_blocked) - { goto out; - } else if (pExaPixmap->pDamage) { + + 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; + alu, clientClipType) ? NULL : pRegion; exaDoMigration (pixmaps, 1, TRUE); } @@ -1078,17 +1080,16 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, pExaPixmap = ExaGetPixmapPriv (pPixmap); if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked) - { return FALSE; - } else if (pExaPixmap->pDamage || pTileExaPixmap->pDamage) { + + 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; + alu, clientClipType) ? NULL : pRegion; pixmaps[1].as_dst = FALSE; pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pTile; @@ -1233,20 +1234,19 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, { ExaScreenPriv (pDrawable->pScreen); PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); - ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv (pPix); int xoff, yoff; Bool ok; if (pExaScr->swappedOut) goto fallback; - if (pExaPixmap->pDamage) { + exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff); + + if (pExaScr->do_migration) { BoxRec Box; RegionRec Reg; ExaMigrationRec pixmaps[1]; - exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff); - Box.x1 = pDrawable->y + x + xoff; Box.y1 = pDrawable->y + y + yoff; Box.x2 = Box.x1 + w; diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c index 1855de1b1..d621ccf76 100644 --- a/exa/exa_glyphs.c +++ b/exa/exa_glyphs.c @@ -385,10 +385,10 @@ exaGlyphCacheUploadGlyph(ScreenPtr pScreen, if (pGlyphPixmap->drawable.bitsPerPixel != pCachePixmap->drawable.bitsPerPixel) goto composite; - /* cache pixmap must be offscreen. */ - if (pExaPixmap->pDamage) { + 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; diff --git a/exa/exa_migration.c b/exa/exa_migration_classic.c index afab9d2f4..83559593f 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 diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c new file mode 100644 index 000000000..475b76a63 --- /dev/null +++ b/exa/exa_migration_mixed.c @@ -0,0 +1,136 @@ +/* + * 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, + CARD8 *dst, int dst_pitch) + { + int i; + + for (i = pPixmap->drawable.height; i; i--) { + memcpy (dst, src, min(src_pitch, dst_pitch)); + src += src_pitch; + dst += dst_pitch; + } +} + +void +exaCreateDriverPixmap_mixed(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ExaScreenPriv(pScreen); + ExaPixmapPriv(pPixmap); + 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; + + /* Already done. */ + if (pExaPixmap->driverPriv) + return; + + if (exaPixmapIsPinned(pPixmap)) + return; + + /* Can't accel 1/4 bpp. */ + if (pExaPixmap->accel_blocked || bpp < 8) + return; + + if (paddedWidth < pExaPixmap->fb_pitch) + paddedWidth = pExaPixmap->fb_pitch; + + if (pExaScr->info->CreatePixmap2) + pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp); + else + pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, paddedWidth*h, 0); + + if (!pExaPixmap->driverPriv) + return; + + pExaPixmap->offscreen = TRUE; + pExaPixmap->sys_ptr = NULL; + + pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; + (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, + paddedWidth, NULL); + + /* scratch pixmaps */ + if (!w || !h) + goto finish; + + if (!pExaScr->info->UploadToScreen) + goto fallback; + + if (pExaScr->info->UploadToScreen(pPixmap, 0, 0, w, h, sys_buffer, sys_pitch)) + goto finish; + +fallback: + ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST); + exaUploadFallback(pPixmap, sys_buffer, sys_pitch, pPixmap->devPrivate.ptr, + exaGetPixmapPitch(pPixmap)); + exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST); + +finish: + free(sys_buffer); +} + +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); + } +} diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c new file mode 100644 index 000000000..26406c42f --- /dev/null +++ b/exa/exa_mixed.c @@ -0,0 +1,229 @@ +/* + * 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; + + /* Allocate temporary pixmap. */ + pExaPixmap->sys_ptr = malloc(datasize); + pExaPixmap->sys_pitch = paddedWidth; + + if (!pExaPixmap->sys_ptr) { + swap(pExaScr, pScreen, DestroyPixmap); + pScreen->DestroyPixmap (pPixmap); + swap(pExaScr, pScreen, DestroyPixmap); + return NULL; + } + + pExaPixmap->area = NULL; + pExaPixmap->offscreen = FALSE; + pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; + pExaPixmap->fb_ptr = NULL; + pExaPixmap->pDamage = NULL; + + exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); + exaSetAccelBlock(pExaScr, pExaPixmap, + w, h, bpp); + + /* A scratch pixmap will become a driver pixmap right away. */ + if (!w || !h) { + exaCreateDriverPixmap_mixed(pPixmap); + } else { + /* 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 copy the pixmap to driver memory later on. */ + pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; + } + + 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 (pPixData) { + if (!exaPixmapIsPinned(pPixmap)) + free(pExaPixmap->sys_ptr); + 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); + Bool ret; + + if (!pExaPixmap->driverPriv) + return FALSE; + + pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); + ret = pExaScr->info->PixmapIsOffscreen(pPixmap); + pPixmap->devPrivate.ptr = NULL; + + return ret; +} diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 3c3451377..620bc67a4 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -547,6 +547,9 @@ exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, void exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); +Bool +exaPixmapIsPinned (PixmapPtr pPix); + extern const GCFuncs exaGCFuncs; /* exa_classic.c */ @@ -579,6 +582,28 @@ 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); + /* exa_render.c */ Bool exaOpReadsDestination (CARD8 op); @@ -633,7 +658,7 @@ exaGlyphs (CARD8 op, GlyphListPtr list, GlyphPtr *glyphs); -/* exa_migration.c */ +/* exa_migration_classic.c */ void exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); diff --git a/exa/exa_render.c b/exa/exa_render.c index 3c822d16b..1ac29f233 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -301,7 +301,7 @@ exaTryDriverSolidFill(PicturePtr pSrc, pixel = exaGetPixmapFirstPixel (pSrcPix); - if (pDstExaPix->pDamage) { + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; pixmaps[0].as_dst = TRUE; @@ -395,8 +395,7 @@ exaTryDriverCompositeRects(CARD8 op, return -1; } - if (pSrcExaPix->pDamage || pDstExaPix->pDamage || - (pMask && pMaskExaPix->pDamage)) { + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[3]; pixmaps[0].as_dst = TRUE; @@ -507,8 +506,6 @@ exaCompositeRects(CARD8 op, ExaCompositeRectPtr rects) { ExaScreenPriv (pDst->pDrawable->pScreen); - PixmapPtr pPixmap = exaGetDrawablePixmap(pDst->pDrawable); - ExaPixmapPriv(pPixmap); int n; ExaCompositeRectPtr r; int ret; @@ -516,7 +513,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; @@ -610,7 +607,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. */ @@ -689,8 +686,7 @@ exaTryDriverComposite(CARD8 op, REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - if (pSrcExaPix->pDamage || pDstExaPix->pDamage || - (pMask && pMaskExaPix->pDamage)) { + if (pExaScr->do_migration) { ExaMigrationRec pixmaps[3]; pixmaps[0].as_dst = TRUE; @@ -707,9 +703,8 @@ exaTryDriverComposite(CARD8 op, pixmaps[2].pPix = pMaskPix; pixmaps[2].pReg = NULL; exaDoMigration(pixmaps, 3, TRUE); - } else { + } else exaDoMigration(pixmaps, 2, TRUE); - } } pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); |