diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2020-11-17 11:59:51 +0100 |
---|---|---|
committer | Olivier Fourdan <ofourdan@redhat.com> | 2022-01-18 12:09:52 +0100 |
commit | cd080f721b0e253bb3cff32e1b206a056b2540e1 (patch) | |
tree | 35526b07c03555fa0d39c38ac30aabcb18696b62 | |
parent | 09ce18292c36fa801424aa1c7cd1545db1d3a869 (diff) |
Drop EXA code
Not used on this branch.
(cherry picked from commit aa49cd5ab72fa9624e1a20750af542b3bbb1e988)
-rw-r--r-- | exa/exa.c | 1144 | ||||
-rw-r--r-- | exa/exa.h | 820 | ||||
-rw-r--r-- | exa/exa_accel.c | 1297 | ||||
-rw-r--r-- | exa/exa_classic.c | 265 | ||||
-rw-r--r-- | exa/exa_driver.c | 230 | ||||
-rw-r--r-- | exa/exa_glyphs.c | 839 | ||||
-rw-r--r-- | exa/exa_migration_classic.c | 761 | ||||
-rw-r--r-- | exa/exa_migration_mixed.c | 270 | ||||
-rw-r--r-- | exa/exa_mixed.c | 330 | ||||
-rw-r--r-- | exa/exa_offscreen.c | 677 | ||||
-rw-r--r-- | exa/exa_priv.h | 735 | ||||
-rw-r--r-- | exa/exa_render.c | 1229 | ||||
-rw-r--r-- | exa/exa_unaccel.c | 733 | ||||
-rw-r--r-- | exa/meson.build | 19 | ||||
-rw-r--r-- | meson.build | 1 |
15 files changed, 0 insertions, 9350 deletions
diff --git a/exa/exa.c b/exa/exa.c deleted file mode 100644 index b16875845..000000000 --- a/exa/exa.c +++ /dev/null @@ -1,1144 +0,0 @@ -/* - * Copyright © 2001 Keith Packard - * - * Partly based on code that is Copyright © The XFree86 Project Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/** @file - * This file covers the initialization and teardown of EXA, and has various - * functions not responsible for performing rendering, pixmap migration, or - * memory management. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <stdlib.h> - -#include "exa_priv.h" -#include "exa.h" - -DevPrivateKeyRec exaScreenPrivateKeyRec; - -#ifdef MITSHM -static ShmFuncs exaShmFuncs = { NULL, NULL }; -#endif - -/** - * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of - * the beginning of the given pixmap. - * - * Note that drivers are free to, and often do, munge this offset as necessary - * for handing to the hardware -- for example, translating it into a different - * aperture. This function may need to be extended in the future if we grow - * support for having multiple card-accessible offscreen, such as an AGP memory - * pool alongside the framebuffer pool. - */ -unsigned long -exaGetPixmapOffset(PixmapPtr pPix) -{ - ExaScreenPriv(pPix->drawable.pScreen); - ExaPixmapPriv(pPix); - - return (CARD8 *) pExaPixmap->fb_ptr - pExaScr->info->memoryBase; -} - -void * -exaGetPixmapDriverPrivate(PixmapPtr pPix) -{ - ExaPixmapPriv(pPix); - - return pExaPixmap->driverPriv; -} - -/** - * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap. - * - * This is a helper to make driver code more obvious, due to the rather obscure - * naming of the pitch field in the pixmap. - */ -unsigned long -exaGetPixmapPitch(PixmapPtr pPix) -{ - return pPix->devKind; -} - -/** - * exaGetPixmapSize() returns the size in bytes of the given pixmap in video - * memory. Only valid when the pixmap is currently in framebuffer. - */ -unsigned long -exaGetPixmapSize(PixmapPtr pPix) -{ - ExaPixmapPrivPtr pExaPixmap; - - pExaPixmap = ExaGetPixmapPriv(pPix); - if (pExaPixmap != NULL) - return pExaPixmap->fb_size; - return 0; -} - -/** - * exaGetDrawablePixmap() returns a backing pixmap for a given drawable. - * - * @param pDrawable the drawable being requested. - * - * This function returns the backing pixmap for a drawable, whether it is a - * redirected window, unredirected window, or already a pixmap. Note that - * coordinate translation is needed when drawing to the backing pixmap of a - * redirected window, and the translation coordinates are provided by calling - * exaGetOffscreenPixmap() on the drawable. - */ -PixmapPtr -exaGetDrawablePixmap(DrawablePtr pDrawable) -{ - if (pDrawable->type == DRAWABLE_WINDOW) - return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); - else - return (PixmapPtr) pDrawable; -} - -/** - * Sets the offsets to add to coordinates to make them address the same bits in - * the backing drawable. These coordinates are nonzero only for redirected - * windows. - */ -void -exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp) -{ -#ifdef COMPOSITE - if (pDrawable->type == DRAWABLE_WINDOW) { - *xp = -pPixmap->screen_x; - *yp = -pPixmap->screen_y; - return; - } -#endif - - *xp = 0; - *yp = 0; -} - -/** - * exaPixmapDirty() marks a pixmap as dirty, allowing for - * optimizations in pixmap migration when no changes have occurred. - */ -void -exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2) -{ - BoxRec box; - RegionRec region; - - box.x1 = max(x1, 0); - box.y1 = max(y1, 0); - box.x2 = min(x2, pPix->drawable.width); - box.y2 = min(y2, pPix->drawable.height); - - if (box.x1 >= box.x2 || box.y1 >= box.y2) - return; - - RegionInit(®ion, &box, 1); - DamageDamageRegion(&pPix->drawable, ®ion); - RegionUninit(®ion); -} - -static int -exaLog2(int val) -{ - int bits; - - if (val <= 0) - return 0; - for (bits = 0; val != 0; bits++) - val >>= 1; - return bits - 1; -} - -void -exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, - int w, int h, int bpp) -{ - pExaPixmap->accel_blocked = 0; - - if (pExaScr->info->maxPitchPixels) { - int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp); - - if (pExaPixmap->fb_pitch > max_pitch) - pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; - } - - if (pExaScr->info->maxPitchBytes && - pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes) - pExaPixmap->accel_blocked |= EXA_RANGE_PITCH; - - if (w > pExaScr->info->maxX) - pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH; - - if (h > pExaScr->info->maxY) - pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT; -} - -void -exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, - int w, int h, int bpp) -{ - if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1) - pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp); - else - pExaPixmap->fb_pitch = bits_to_bytes(w * bpp); - - pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch, - pExaScr->info->pixmapPitchAlign); -} - -/** - * 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; -} - -/** - * exaPixmapHasGpuCopy() 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 - * with the CPU. - * - * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly - * deal with moving pixmaps in and out of system memory), EXA will give drivers - * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE. - * - * @return TRUE if the given drawable is in framebuffer memory. - */ -Bool -exaPixmapHasGpuCopy(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - - if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) - return FALSE; - - return (*pExaScr->pixmap_has_gpu_copy) (pPixmap); -} - -/** - * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy(). - */ -Bool -exaDrawableIsOffscreen(DrawablePtr pDrawable) -{ - return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable)); -} - -/** - * Returns the pixmap which backs a drawable, and the offsets to add to - * coordinates to make them address the same bits in the backing drawable. - */ -PixmapPtr -exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp) -{ - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - exaGetDrawableDeltas(pDrawable, pPixmap, xp, yp); - - if (exaPixmapHasGpuCopy(pPixmap)) - return pPixmap; - else - return NULL; -} - -/** - * Returns TRUE if the pixmap GPU copy is being accessed. - */ -Bool -ExaDoPrepareAccess(PixmapPtr pPixmap, int index) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - ExaPixmapPriv(pPixmap); - Bool has_gpu_copy, ret; - int i; - - if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) - return FALSE; - - if (pExaPixmap == NULL) - EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE); - - /* Handle repeated / nested calls. */ - for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { - if (pExaScr->access[i].pixmap == pPixmap) { - pExaScr->access[i].count++; - return pExaScr->access[i].retval; - } - } - - /* If slot for this index is taken, find an empty slot */ - if (pExaScr->access[index].pixmap) { - for (index = EXA_NUM_PREPARE_INDICES - 1; index >= 0; index--) - if (!pExaScr->access[index].pixmap) - break; - } - - /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */ - if (pPixmap->devPrivate.ptr != NULL) { - EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", pPixmap->devPrivate.ptr)); - } - - has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); - - if (has_gpu_copy && pExaPixmap->fb_ptr) { - pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; - ret = TRUE; - } - else { - pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; - ret = FALSE; - } - - /* Store so we can handle repeated / nested calls. */ - pExaScr->access[index].pixmap = pPixmap; - pExaScr->access[index].count = 1; - - if (!has_gpu_copy) - goto out; - - exaWaitSync(pScreen); - - if (pExaScr->info->PrepareAccess == NULL) - goto out; - - if (index >= EXA_PREPARE_AUX_DEST && - !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { - if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) - FatalError("Unsupported AUX indices used on a pinned pixmap.\n"); - exaMoveOutPixmap(pPixmap); - ret = FALSE; - goto out; - } - - if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { - if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED && - !(pExaScr->info->flags & EXA_MIXED_PIXMAPS)) - FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); - exaMoveOutPixmap(pPixmap); - ret = FALSE; - goto out; - } - - ret = TRUE; - - out: - pExaScr->access[index].retval = ret; - return ret; -} - -/** - * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. - * - * It deals with waiting for synchronization with the card, determining if - * PrepareAccess() is necessary, and working around PrepareAccess() failure. - */ -void -exaPrepareAccess(DrawablePtr pDrawable, int index) -{ - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - ExaScreenPriv(pDrawable->pScreen); - - if (pExaScr->prepare_access_reg) - pExaScr->prepare_access_reg(pPixmap, index, NULL); - else - (void) ExaDoPrepareAccess(pPixmap, index); -} - -/** - * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler. - * - * It deals with calling the driver's FinishAccess() only if necessary. - */ -void -exaFinishAccess(DrawablePtr pDrawable, int index) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - ExaScreenPriv(pScreen); - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPixmap); - int i; - - if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) - return; - - if (pExaPixmap == NULL) - EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),); - - /* Handle repeated / nested calls. */ - for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { - if (pExaScr->access[i].pixmap == pPixmap) { - if (--pExaScr->access[i].count > 0) - return; - break; - } - } - - /* Catch unbalanced Prepare/FinishAccess calls. */ - if (i == EXA_NUM_PREPARE_INDICES) - EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap),); - - pExaScr->access[i].pixmap = NULL; - - /* We always hide the devPrivate.ptr. */ - pPixmap->devPrivate.ptr = NULL; - - /* Only call FinishAccess if PrepareAccess was called and succeeded. */ - if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval) - return; - - 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, i); -} - -/** - * Helper for things common to all schemes when a pixmap is destroyed - */ -void -exaDestroyPixmap(PixmapPtr pPixmap) -{ - ExaScreenPriv(pPixmap->drawable.pScreen); - int i; - - /* Finish access if it was prepared (e.g. pixmap created during - * software fallback) - */ - for (i = 0; i < EXA_NUM_PREPARE_INDICES; i++) { - if (pExaScr->access[i].pixmap == pPixmap) { - exaFinishAccess(&pPixmap->drawable, i); - pExaScr->access[i].pixmap = NULL; - break; - } - } -} - -/** - * Here begins EXA's GC code. - * Do not ever access the fb/mi layer directly. - */ - -static void - exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); - -static void - exaDestroyGC(GCPtr pGC); - -static void - exaChangeGC(GCPtr pGC, unsigned long mask); - -static void - exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); - -static void - exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects); - -static void - exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); - -static void - exaDestroyClip(GCPtr pGC); - -const GCFuncs exaGCFuncs = { - exaValidateGC, - exaChangeGC, - exaCopyGC, - exaDestroyGC, - exaChangeClip, - exaDestroyClip, - exaCopyClip -}; - -static void -exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) -{ - /* fbValidateGC will do direct access to pixmaps if the tiling has changed. - * Do a few smart things so fbValidateGC can do its work. - */ - - ScreenPtr pScreen = pDrawable->pScreen; - - ExaScreenPriv(pScreen); - ExaGCPriv(pGC); - PixmapPtr pTile = NULL; - - /* Either of these conditions is enough to trigger access to a tile pixmap. - * With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid - * tile pixmap pointer. - */ - if (pGC->fillStyle == FillTiled || - ((changes & GCTile) && !pGC->tileIsPixel)) { - pTile = pGC->tile.pixmap; - } - - if (pGC->stipple) - exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); - if (pTile) - exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC); - - /* Calls to Create/DestroyPixmap have to be identified as special. */ - pExaScr->fallback_counter++; - swap(pExaGC, pGC, funcs); - (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); - swap(pExaGC, pGC, funcs); - pExaScr->fallback_counter--; - - if (pTile) - exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC); - if (pGC->stipple) - exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); -} - -/* Is exaPrepareAccessGC() needed? */ -static void -exaDestroyGC(GCPtr pGC) -{ - ExaGCPriv(pGC); - swap(pExaGC, pGC, funcs); - (*pGC->funcs->DestroyGC) (pGC); - swap(pExaGC, pGC, funcs); -} - -static void -exaChangeGC(GCPtr pGC, unsigned long mask) -{ - ExaGCPriv(pGC); - swap(pExaGC, pGC, funcs); - (*pGC->funcs->ChangeGC) (pGC, mask); - swap(pExaGC, pGC, funcs); -} - -static void -exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) -{ - ExaGCPriv(pGCDst); - swap(pExaGC, pGCDst, funcs); - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - swap(pExaGC, pGCDst, funcs); -} - -static void -exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects) -{ - ExaGCPriv(pGC); - swap(pExaGC, pGC, funcs); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - swap(pExaGC, pGC, funcs); -} - -static void -exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc) -{ - ExaGCPriv(pGCDst); - swap(pExaGC, pGCDst, funcs); - (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); - swap(pExaGC, pGCDst, funcs); -} - -static void -exaDestroyClip(GCPtr pGC) -{ - ExaGCPriv(pGC); - swap(pExaGC, pGC, funcs); - (*pGC->funcs->DestroyClip) (pGC); - swap(pExaGC, pGC, funcs); -} - -/** - * exaCreateGC makes a new GC and hooks up its funcs handler, so that - * exaValidateGC() will get called. - */ -static int -exaCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - - ExaScreenPriv(pScreen); - ExaGCPriv(pGC); - Bool ret; - - swap(pExaScr, pScreen, CreateGC); - if ((ret = (*pScreen->CreateGC) (pGC))) { - wrap(pExaGC, pGC, funcs, &exaGCFuncs); - wrap(pExaGC, pGC, ops, &exaOps); - } - swap(pExaScr, pScreen, CreateGC); - - return ret; -} - -static Bool -exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask) -{ - Bool ret; - ScreenPtr pScreen = pWin->drawable.pScreen; - - ExaScreenPriv(pScreen); - - if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) - exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); - - if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) - exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); - - pExaScr->fallback_counter++; - swap(pExaScr, pScreen, ChangeWindowAttributes); - ret = pScreen->ChangeWindowAttributes(pWin, mask); - swap(pExaScr, pScreen, ChangeWindowAttributes); - pExaScr->fallback_counter--; - - if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) - exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC); - if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE) - exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK); - - return ret; -} - -static RegionPtr -exaBitmapToRegion(PixmapPtr pPix) -{ - RegionPtr ret; - ScreenPtr pScreen = pPix->drawable.pScreen; - - ExaScreenPriv(pScreen); - - exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC); - swap(pExaScr, pScreen, BitmapToRegion); - ret = (*pScreen->BitmapToRegion) (pPix); - swap(pExaScr, pScreen, BitmapToRegion); - exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC); - - return ret; -} - -static Bool -exaCreateScreenResources(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - PixmapPtr pScreenPixmap; - Bool b; - - swap(pExaScr, pScreen, CreateScreenResources); - b = pScreen->CreateScreenResources(pScreen); - swap(pExaScr, pScreen, CreateScreenResources); - - if (!b) - return FALSE; - - pScreenPixmap = pScreen->GetScreenPixmap(pScreen); - - if (pScreenPixmap) { - ExaPixmapPriv(pScreenPixmap); - - exaSetAccelBlock(pExaScr, pExaPixmap, - pScreenPixmap->drawable.width, - pScreenPixmap->drawable.height, - pScreenPixmap->drawable.bitsPerPixel); - } - - return TRUE; -} - -static void -ExaBlockHandler(ScreenPtr pScreen, void *pTimeout) -{ - ExaScreenPriv(pScreen); - - /* Move any deferred results from a software fallback to the driver pixmap */ - if (pExaScr->deferred_mixed_pixmap) - exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); - - unwrap(pExaScr, pScreen, BlockHandler); - (*pScreen->BlockHandler) (pScreen, pTimeout); - wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); - - /* The rest only applies to classic EXA */ - if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) - return; - - /* Try and keep the offscreen memory area tidy every now and then (at most - * once per second) when the server has been idle for at least 100ms. - */ - if (pExaScr->numOffscreenAvailable > 1) { - CARD32 now = GetTimeInMillis(); - - pExaScr->nextDefragment = now + - max(100, (INT32) (pExaScr->lastDefragment + 1000 - now)); - AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now); - } -} - -static void -ExaWakeupHandler(ScreenPtr pScreen, int result) -{ - ExaScreenPriv(pScreen); - - unwrap(pExaScr, pScreen, WakeupHandler); - (*pScreen->WakeupHandler) (pScreen, result); - wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); - - if (result == 0 && pExaScr->numOffscreenAvailable > 1) { - CARD32 now = GetTimeInMillis(); - - if ((int) (now - pExaScr->nextDefragment) > 0) { - ExaOffscreenDefragment(pScreen); - pExaScr->lastDefragment = now; - } - } -} - -/** - * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's - * screen private, before calling down to the next CloseSccreen. - */ -static Bool -exaCloseScreen(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - if (ps->Glyphs == exaGlyphs) - exaGlyphsFini(pScreen); - - if (pScreen->BlockHandler == ExaBlockHandler) - unwrap(pExaScr, pScreen, BlockHandler); - if (pScreen->WakeupHandler == ExaWakeupHandler) - unwrap(pExaScr, pScreen, WakeupHandler); - unwrap(pExaScr, pScreen, CreateGC); - unwrap(pExaScr, pScreen, CloseScreen); - unwrap(pExaScr, pScreen, GetImage); - unwrap(pExaScr, pScreen, GetSpans); - if (pExaScr->SavedCreatePixmap) - unwrap(pExaScr, pScreen, CreatePixmap); - if (pExaScr->SavedDestroyPixmap) - unwrap(pExaScr, pScreen, DestroyPixmap); - if (pExaScr->SavedModifyPixmapHeader) - unwrap(pExaScr, pScreen, ModifyPixmapHeader); - unwrap(pExaScr, pScreen, CopyWindow); - unwrap(pExaScr, pScreen, ChangeWindowAttributes); - unwrap(pExaScr, pScreen, BitmapToRegion); - unwrap(pExaScr, pScreen, CreateScreenResources); - if (pExaScr->SavedSharePixmapBacking) - unwrap(pExaScr, pScreen, SharePixmapBacking); - if (pExaScr->SavedSetSharedPixmapBacking) - unwrap(pExaScr, pScreen, SetSharedPixmapBacking); - unwrap(pExaScr, ps, Composite); - if (pExaScr->SavedGlyphs) - unwrap(pExaScr, ps, Glyphs); - unwrap(pExaScr, ps, Trapezoids); - unwrap(pExaScr, ps, Triangles); - unwrap(pExaScr, ps, AddTraps); - - free(pExaScr); - - return (*pScreen->CloseScreen) (pScreen); -} - -/** - * This function allocates a driver structure for EXA drivers to fill in. By - * having EXA allocate the structure, the driver structure can be extended - * without breaking ABI between EXA and the drivers. The driver's - * responsibility is to check beforehand that the EXA module has a matching - * major number and sufficient minor. Drivers are responsible for freeing the - * driver structure using free(). - * - * @return a newly allocated, zero-filled driver structure - */ -ExaDriverPtr -exaDriverAlloc(void) -{ - return calloc(1, sizeof(ExaDriverRec)); -} - -/** - * @param pScreen screen being initialized - * @param pScreenInfo EXA driver record - * - * exaDriverInit sets up EXA given a driver record filled in by the driver. - * pScreenInfo should have been allocated by exaDriverAlloc(). See the - * comments in _ExaDriver for what must be filled in and what is optional. - * - * @return TRUE if EXA was successfully initialized. - */ -Bool -exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo) -{ - ExaScreenPrivPtr pExaScr; - PictureScreenPtr ps; - - if (!pScreenInfo) - return FALSE; - - if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || - pScreenInfo->exa_minor > EXA_VERSION_MINOR) { - LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements " - "(%d.%d) are incompatible with EXA version (%d.%d)\n", - pScreen->myNum, - pScreenInfo->exa_major, pScreenInfo->exa_minor, - EXA_VERSION_MAJOR, EXA_VERSION_MINOR); - return FALSE; - } - - if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) { - if (!pScreenInfo->memoryBase) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase " - "must be non-zero\n", pScreen->myNum); - return FALSE; - } - - if (!pScreenInfo->memorySize) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " - "non-zero\n", pScreen->myNum); - return FALSE; - } - - if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must " - "be <= ExaDriverRec::memorySize\n", pScreen->myNum); - return FALSE; - } - } - - if (!pScreenInfo->PrepareSolid) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " - "non-NULL\n", pScreen->myNum); - return FALSE; - } - - if (!pScreenInfo->PrepareCopy) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " - "non-NULL\n", pScreen->myNum); - return FALSE; - } - - if (!pScreenInfo->WaitMarker) { - LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " - "non-NULL\n", pScreen->myNum); - return FALSE; - } - - /* If the driver doesn't set any max pitch values, we'll just assume - * that there's a limitation by pixels, and that it's the same as - * maxX. - * - * We want maxPitchPixels or maxPitchBytes to be set so we can check - * pixmaps against the max pitch in exaCreatePixmap() -- it matters - * whether a pixmap is rejected because of its pitch or - * because of its width. - */ - if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) { - pScreenInfo->maxPitchPixels = pScreenInfo->maxX; - } - - ps = GetPictureScreenIfSet(pScreen); - - if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) { - LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n", - pScreen->myNum); - return FALSE; - } - - pExaScr = calloc(sizeof(ExaScreenPrivRec), 1); - if (!pExaScr) { - LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n", - pScreen->myNum); - return FALSE; - } - - pExaScr->info = pScreenInfo; - - dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey, pExaScr); - - pExaScr->migration = ExaMigrationAlways; - - exaDDXDriverInit(pScreen); - - if (!dixRegisterScreenSpecificPrivateKey - (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) { - LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n", - pScreen->myNum); - return FALSE; - } - - /* - * Replace various fb screen functions - */ - if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && - (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) || - (pExaScr->info->flags & EXA_MIXED_PIXMAPS))) - wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler); - if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) && - !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) - wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler); - wrap(pExaScr, pScreen, CreateGC, exaCreateGC); - wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen); - wrap(pExaScr, pScreen, GetImage, exaGetImage); - wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans); - wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow); - wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes); - wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion); - wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources); - - if (ps) { - wrap(pExaScr, ps, Composite, exaComposite); - if (pScreenInfo->PrepareComposite) { - wrap(pExaScr, ps, Glyphs, exaGlyphs); - } - else { - wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs); - } - wrap(pExaScr, ps, Trapezoids, exaTrapezoids); - wrap(pExaScr, ps, Triangles, exaTriangles); - wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps); - } - -#ifdef MITSHM - /* - * Don't allow shared pixmaps. - */ - ShmRegisterFuncs(pScreen, &exaShmFuncs); -#endif - /* - * Hookup offscreen pixmaps - */ - if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { - if (!dixRegisterScreenSpecificPrivateKey - (pScreen, &pExaScr->pixmapPrivateKeyRec, PRIVATE_PIXMAP, - sizeof(ExaPixmapPrivRec))) { - LogMessage(X_WARNING, - "EXA(%d): Failed to allocate pixmap private\n", - pScreen->myNum); - return FALSE; - } - if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) { - 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); - wrap(pExaScr, pScreen, SharePixmapBacking, exaSharePixmapBacking_mixed); - wrap(pExaScr, pScreen, SetSharedPixmapBacking, exaSetSharedPixmapBacking_mixed); - - pExaScr->do_migration = exaDoMigration_mixed; - pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed; - pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed; - pExaScr->do_move_out_pixmap = NULL; - pExaScr->prepare_access_reg = exaPrepareAccessReg_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_has_gpu_copy = exaPixmapHasGpuCopy_driver; - pExaScr->do_move_in_pixmap = NULL; - pExaScr->do_move_out_pixmap = NULL; - pExaScr->prepare_access_reg = NULL; - } - } - else { - wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); - wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic); - wrap(pExaScr, pScreen, ModifyPixmapHeader, - exaModifyPixmapHeader_classic); - pExaScr->do_migration = exaDoMigration_classic; - pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic; - pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic; - pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic; - pExaScr->prepare_access_reg = exaPrepareAccessReg_classic; - } - if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { - LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", - pScreen->myNum, - pExaScr->info->memorySize - - pExaScr->info->offScreenBase); - } - else { - LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n", - pScreen->myNum); - - } - } - else - LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum); - - if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { - DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase, - pExaScr->info->memorySize)); - if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) { - if (!exaOffscreenInit(pScreen)) { - LogMessage(X_WARNING, - "EXA(%d): Offscreen pixmap setup failed\n", - pScreen->myNum); - return FALSE; - } - } - } - - if (ps->Glyphs == exaGlyphs) - exaGlyphsInit(pScreen); - - LogMessage(X_INFO, "EXA(%d): Driver registered support for the following" - " operations:\n", pScreen->myNum); - assert(pScreenInfo->PrepareSolid != NULL); - LogMessage(X_INFO, " Solid\n"); - assert(pScreenInfo->PrepareCopy != NULL); - LogMessage(X_INFO, " Copy\n"); - if (pScreenInfo->PrepareComposite != NULL) { - LogMessage(X_INFO, " Composite (RENDER acceleration)\n"); - } - if (pScreenInfo->UploadToScreen != NULL) { - LogMessage(X_INFO, " UploadToScreen\n"); - } - if (pScreenInfo->DownloadFromScreen != NULL) { - LogMessage(X_INFO, " DownloadFromScreen\n"); - } - - return TRUE; -} - -/** - * exaDriverFini tears down EXA on a given screen. - * - * @param pScreen screen being torn down. - */ -void -exaDriverFini(ScreenPtr pScreen) -{ - /*right now does nothing */ -} - -/** - * exaMarkSync() should be called after any asynchronous drawing by the hardware. - * - * @param pScreen screen which drawing occurred on - * - * exaMarkSync() sets a flag to indicate that some asynchronous drawing has - * happened and a WaitSync() will be necessary before relying on the contents of - * offscreen memory from the CPU's perspective. It also calls an optional - * driver MarkSync() callback, the return value of which may be used to do partial - * synchronization with the hardware in the future. - */ -void -exaMarkSync(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - - pExaScr->info->needsSync = TRUE; - if (pExaScr->info->MarkSync != NULL) { - pExaScr->info->lastMarker = (*pExaScr->info->MarkSync) (pScreen); - } -} - -/** - * exaWaitSync() ensures that all drawing has been completed. - * - * @param pScreen screen being synchronized. - * - * Calls down into the driver to ensure that all previous drawing has completed. - * It should always be called before relying on the framebuffer contents - * reflecting previous drawing, from a CPU perspective. - */ -void -exaWaitSync(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - - if (pExaScr->info->needsSync && !pExaScr->swappedOut) { - (*pExaScr->info->WaitMarker) (pScreen, pExaScr->info->lastMarker); - pExaScr->info->needsSync = FALSE; - } -} - -/** - * Performs migration of the pixmaps according to the operation information - * provided in pixmaps and can_accel and the migration scheme chosen in the - * config file. - */ -void -exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) -{ - ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; - - ExaScreenPriv(pScreen); - - if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) - return; - - if (pExaScr->do_migration) - (*pExaScr->do_migration) (pixmaps, npixmaps, can_accel); -} - -void -exaMoveInPixmap(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - - if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) - return; - - if (pExaScr->do_move_in_pixmap) - (*pExaScr->do_move_in_pixmap) (pPixmap); -} - -void -exaMoveOutPixmap(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - - if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS)) - return; - - if (pExaScr->do_move_out_pixmap) - (*pExaScr->do_move_out_pixmap) (pPixmap); -} diff --git a/exa/exa.h b/exa/exa.h deleted file mode 100644 index fba06ca0f..000000000 --- a/exa/exa.h +++ /dev/null @@ -1,820 +0,0 @@ -/* - * - * Copyright (C) 2000 Keith Packard - * 2004 Eric Anholt - * 2005 Zack Rusin - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of copyright holders not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Copyright holders make no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/** @file - * This is the header containing the public API of EXA for exa drivers. - */ - -#ifndef EXA_H -#define EXA_H - -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "picturestr.h" -#include "fb.h" - -#define EXA_VERSION_MAJOR 2 -#define EXA_VERSION_MINOR 6 -#define EXA_VERSION_RELEASE 0 - -typedef struct _ExaOffscreenArea ExaOffscreenArea; - -typedef void (*ExaOffscreenSaveProc) (ScreenPtr pScreen, - ExaOffscreenArea * area); - -typedef enum _ExaOffscreenState { - ExaOffscreenAvail, - ExaOffscreenRemovable, - ExaOffscreenLocked -} ExaOffscreenState; - -struct _ExaOffscreenArea { - int base_offset; /* allocation base */ - int offset; /* aligned offset */ - int size; /* total allocation size */ - unsigned last_use; - void *privData; - - ExaOffscreenSaveProc save; - - ExaOffscreenState state; - - ExaOffscreenArea *next; - - unsigned eviction_cost; - - ExaOffscreenArea *prev; /* Double-linked list for defragmentation */ - int align; /* required alignment */ -}; - -/** - * The ExaDriver structure is allocated through exaDriverAlloc(), and then - * fllled in by drivers. - */ -typedef struct _ExaDriver { - /** - * exa_major and exa_minor should be set by the driver to the version of - * EXA which the driver was compiled for (or configures itself at runtime - * to support). This allows EXA to extend the structure for new features - * without breaking ABI for drivers compiled against older versions. - */ - int exa_major, exa_minor; - - /** - * memoryBase is the address of the beginning of framebuffer memory. - * The visible screen should be within memoryBase to memoryBase + - * memorySize. - */ - CARD8 *memoryBase; - - /** - * offScreenBase is the offset from memoryBase of the beginning of the area - * to be managed by EXA's linear offscreen memory manager. - * - * In XFree86 DDX drivers, this is probably: - * (pScrn->displayWidth * cpp * pScrn->virtualY) - */ - unsigned long offScreenBase; - - /** - * memorySize is the length (in bytes) of framebuffer memory beginning - * from memoryBase. - * - * The offscreen memory manager will manage the area beginning at - * (memoryBase + offScreenBase), with a length of (memorySize - - * offScreenBase) - * - * In XFree86 DDX drivers, this is probably (pScrn->videoRam * 1024) - */ - unsigned long memorySize; - - /** - * pixmapOffsetAlign is the byte alignment necessary for pixmap offsets - * within framebuffer. - * - * Hardware typically has a required alignment of offsets, which may or may - * not be a power of two. EXA will ensure that pixmaps managed by the - * offscreen memory manager meet this alignment requirement. - */ - int pixmapOffsetAlign; - - /** - * pixmapPitchAlign is the byte alignment necessary for pixmap pitches - * within the framebuffer. - * - * Hardware typically has a required alignment of pitches for acceleration. - * For 3D hardware, Composite acceleration often requires that source and - * mask pixmaps (textures) have a power-of-two pitch, which can be demanded - * using EXA_OFFSCREEN_ALIGN_POT. These pitch requirements only apply to - * pixmaps managed by the offscreen memory manager. Thus, it is up to the - * driver to ensure that the visible screen has an appropriate pitch for - * acceleration. - */ - int pixmapPitchAlign; - - /** - * The flags field is bitfield of boolean values controlling EXA's behavior. - * - * The flags include EXA_OFFSCREEN_PIXMAPS, EXA_OFFSCREEN_ALIGN_POT, and - * EXA_TWO_BITBLT_DIRECTIONS. - */ - int flags; - - /** @{ */ - /** - * maxX controls the X coordinate limitation for rendering from the card. - * The driver should never receive a request for rendering beyond maxX - * in the X direction from the origin of a pixmap. - */ - int maxX; - - /** - * maxY controls the Y coordinate limitation for rendering from the card. - * The driver should never receive a request for rendering beyond maxY - * in the Y direction from the origin of a pixmap. - */ - int maxY; - /** @} */ - - /* private */ - ExaOffscreenArea *offScreenAreas; - Bool needsSync; - int lastMarker; - - /** @name Solid - * @{ - */ - /** - * PrepareSolid() sets up the driver for doing a solid fill. - * @param pPixmap Destination pixmap - * @param alu raster operation - * @param planemask write mask for the fill - * @param fg "foreground" color for the fill - * - * This call should set up the driver for doing a series of solid fills - * through the Solid() call. The alu raster op is one of the GX* - * graphics functions listed in X.h, and typically maps to a similar - * single-byte "ROP" setting in all hardware. The planemask controls - * which bits of the destination should be affected, and will only represent - * the bits up to the depth of pPixmap. The fg is the pixel value of the - * foreground color referred to in ROP descriptions. - * - * Note that many drivers will need to store some of the data in the driver - * private record, for sending to the hardware with each drawing command. - * - * The PrepareSolid() call is required of all drivers, but it may fail for any - * reason. Failure results in a fallback to software rendering. - */ - Bool (*PrepareSolid) (PixmapPtr pPixmap, - int alu, Pixel planemask, Pixel fg); - - /** - * Solid() performs a solid fill set up in the last PrepareSolid() call. - * - * @param pPixmap destination pixmap - * @param x1 left coordinate - * @param y1 top coordinate - * @param x2 right coordinate - * @param y2 bottom coordinate - * - * Performs the fill set up by the last PrepareSolid() call, covering the - * area from (x1,y1) to (x2,y2) in pPixmap. Note that the coordinates are - * in the coordinate space of the destination pixmap, so the driver will - * need to set up the hardware's offset and pitch for the destination - * coordinates according to the pixmap's offset and pitch within - * framebuffer. This likely means using exaGetPixmapOffset() and - * exaGetPixmapPitch(). - * - * This call is required if PrepareSolid() ever succeeds. - */ - void (*Solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2); - - /** - * DoneSolid() finishes a set of solid fills. - * - * @param pPixmap destination pixmap. - * - * The DoneSolid() call is called at the end of a series of consecutive - * Solid() calls following a successful PrepareSolid(). This allows drivers - * to finish up emitting drawing commands that were buffered, or clean up - * state from PrepareSolid(). - * - * This call is required if PrepareSolid() ever succeeds. - */ - void (*DoneSolid) (PixmapPtr pPixmap); - /** @} */ - - /** @name Copy - * @{ - */ - /** - * PrepareCopy() sets up the driver for doing a copy within video - * memory. - * - * @param pSrcPixmap source pixmap - * @param pDstPixmap destination pixmap - * @param dx X copy direction - * @param dy Y copy direction - * @param alu raster operation - * @param planemask write mask for the fill - * - * This call should set up the driver for doing a series of copies from the - * the pSrcPixmap to the pDstPixmap. The dx flag will be positive if the - * hardware should do the copy from the left to the right, and dy will be - * positive if the copy should be done from the top to the bottom. This - * is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap. - * If your hardware can only support blits that are (left to right, top to - * bottom) or (right to left, bottom to top), then you should set - * #EXA_TWO_BITBLT_DIRECTIONS, and EXA will break down Copy operations to - * ones that meet those requirements. The alu raster op is one of the GX* - * graphics functions listed in X.h, and typically maps to a similar - * single-byte "ROP" setting in all hardware. The planemask controls which - * bits of the destination should be affected, and will only represent the - * bits up to the depth of pPixmap. - * - * Note that many drivers will need to store some of the data in the driver - * private record, for sending to the hardware with each drawing command. - * - * The PrepareCopy() call is required of all drivers, but it may fail for any - * reason. Failure results in a fallback to software rendering. - */ - Bool (*PrepareCopy) (PixmapPtr pSrcPixmap, - PixmapPtr pDstPixmap, - int dx, int dy, int alu, Pixel planemask); - - /** - * Copy() performs a copy set up in the last PrepareCopy call. - * - * @param pDstPixmap destination pixmap - * @param srcX source X coordinate - * @param srcY source Y coordinate - * @param dstX destination X coordinate - * @param dstY destination Y coordinate - * @param width width of the rectangle to be copied - * @param height height of the rectangle to be copied. - * - * Performs the copy set up by the last PrepareCopy() call, copying the - * rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source - * pixmap to the same-sized rectangle at (dstX, dstY) in the destination - * pixmap. Those rectangles may overlap in memory, if - * pSrcPixmap == pDstPixmap. Note that this call does not receive the - * pSrcPixmap as an argument -- if it's needed in this function, it should - * be stored in the driver private during PrepareCopy(). As with Solid(), - * the coordinates are in the coordinate space of each pixmap, so the driver - * will need to set up source and destination pitches and offsets from those - * pixmaps, probably using exaGetPixmapOffset() and exaGetPixmapPitch(). - * - * This call is required if PrepareCopy ever succeeds. - */ - void (*Copy) (PixmapPtr pDstPixmap, - int srcX, - int srcY, int dstX, int dstY, int width, int height); - - /** - * DoneCopy() finishes a set of copies. - * - * @param pPixmap destination pixmap. - * - * The DoneCopy() call is called at the end of a series of consecutive - * Copy() calls following a successful PrepareCopy(). This allows drivers - * to finish up emitting drawing commands that were buffered, or clean up - * state from PrepareCopy(). - * - * This call is required if PrepareCopy() ever succeeds. - */ - void (*DoneCopy) (PixmapPtr pDstPixmap); - /** @} */ - - /** @name Composite - * @{ - */ - /** - * CheckComposite() checks to see if a composite operation could be - * accelerated. - * - * @param op Render operation - * @param pSrcPicture source Picture - * @param pMaskPicture mask picture - * @param pDstPicture destination Picture - * - * The CheckComposite() call checks if the driver could handle acceleration - * of op with the given source, mask, and destination pictures. This allows - * drivers to check source and destination formats, supported operations, - * transformations, and component alpha state, and send operations it can't - * support to software rendering early on. This avoids costly pixmap - * migration to the wrong places when the driver can't accelerate - * operations. Note that because migration hasn't happened, the driver - * can't know during CheckComposite() what the offsets and pitches of the - * pixmaps are going to be. - * - * See PrepareComposite() for more details on likely issues that drivers - * will have in accelerating Composite operations. - * - * The CheckComposite() call is recommended if PrepareComposite() is - * implemented, but is not required. - */ - Bool (*CheckComposite) (int op, - PicturePtr pSrcPicture, - PicturePtr pMaskPicture, PicturePtr pDstPicture); - - /** - * PrepareComposite() sets up the driver for doing a Composite operation - * described in the Render extension protocol spec. - * - * @param op Render operation - * @param pSrcPicture source Picture - * @param pMaskPicture mask picture - * @param pDstPicture destination Picture - * @param pSrc source pixmap - * @param pMask mask pixmap - * @param pDst destination pixmap - * - * This call should set up the driver for doing a series of Composite - * operations, as described in the Render protocol spec, with the given - * pSrcPicture, pMaskPicture, and pDstPicture. The pSrc, pMask, and - * pDst are the pixmaps containing the pixel data, and should be used for - * setting the offset and pitch used for the coordinate spaces for each of - * the Pictures. - * - * Notes on interpreting Picture structures: - * - The Picture structures will always have a valid pDrawable. - * - The Picture structures will never have alphaMap set. - * - The mask Picture (and therefore pMask) may be NULL, in which case the - * operation is simply src OP dst instead of src IN mask OP dst, and - * mask coordinates should be ignored. - * - pMarkPicture may have componentAlpha set, which greatly changes - * the behavior of the Composite operation. componentAlpha has no effect - * when set on pSrcPicture or pDstPicture. - * - The source and mask Pictures may have a transformation set - * (Picture->transform != NULL), which means that the source coordinates - * should be transformed by that transformation, resulting in scaling, - * rotation, etc. The PictureTransformPoint() call can transform - * coordinates for you. Transforms have no effect on Pictures when used - * as a destination. - * - The source and mask pictures may have a filter set. PictFilterNearest - * and PictFilterBilinear are defined in the Render protocol, but others - * may be encountered, and must be handled correctly (usually by - * PrepareComposite failing, and falling back to software). Filters have - * no effect on Pictures when used as a destination. - * - The source and mask Pictures may have repeating set, which must be - * respected. Many chipsets will be unable to support repeating on - * pixmaps that have a width or height that is not a power of two. - * - * If your hardware can't support source pictures (textures) with - * non-power-of-two pitches, you should set #EXA_OFFSCREEN_ALIGN_POT. - * - * Note that many drivers will need to store some of the data in the driver - * private record, for sending to the hardware with each drawing command. - * - * The PrepareComposite() call is not required. However, it is highly - * recommended for performance of antialiased font rendering and performance - * of cairo applications. Failure results in a fallback to software - * rendering. - */ - Bool (*PrepareComposite) (int op, - PicturePtr pSrcPicture, - PicturePtr pMaskPicture, - PicturePtr pDstPicture, - PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); - - /** - * Composite() performs a Composite operation set up in the last - * PrepareComposite() call. - * - * @param pDstPixmap destination pixmap - * @param srcX source X coordinate - * @param srcY source Y coordinate - * @param maskX source X coordinate - * @param maskY source Y coordinate - * @param dstX destination X coordinate - * @param dstY destination Y coordinate - * @param width destination rectangle width - * @param height destination rectangle height - * - * Performs the Composite operation set up by the last PrepareComposite() - * call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height) - * in the destination Pixmap. Note that if a transformation was set on - * the source or mask Pictures, the source rectangles may not be the same - * size as the destination rectangles and filtering. Getting the coordinate - * transformation right at the subpixel level can be tricky, and rendercheck - * can test this for you. - * - * This call is required if PrepareComposite() ever succeeds. - */ - void (*Composite) (PixmapPtr pDst, - int srcX, - int srcY, - int maskX, - int maskY, int dstX, int dstY, int width, int height); - - /** - * DoneComposite() finishes a set of Composite operations. - * - * @param pPixmap destination pixmap. - * - * The DoneComposite() call is called at the end of a series of consecutive - * Composite() calls following a successful PrepareComposite(). This allows - * drivers to finish up emitting drawing commands that were buffered, or - * clean up state from PrepareComposite(). - * - * This call is required if PrepareComposite() ever succeeds. - */ - void (*DoneComposite) (PixmapPtr pDst); - /** @} */ - - /** - * UploadToScreen() loads a rectangle of data from src into pDst. - * - * @param pDst destination pixmap - * @param x destination X coordinate. - * @param y destination Y coordinate - * @param width width of the rectangle to be copied - * @param height height of the rectangle to be copied - * @param src pointer to the beginning of the source data - * @param src_pitch pitch (in bytes) of the lines of source data. - * - * UploadToScreen() copies data in system memory beginning at src (with - * pitch src_pitch) into the destination pixmap from (x, y) to - * (x + width, y + height). This is typically done with hostdata uploads, - * where the CPU sets up a blit command on the hardware with instructions - * that the blit data will be fed through some sort of aperture on the card. - * - * If UploadToScreen() is performed asynchronously, it is up to the driver - * to call exaMarkSync(). This is in contrast to most other acceleration - * calls in EXA. - * - * UploadToScreen() can aid in pixmap migration, but is most important for - * the performance of exaGlyphs() (antialiased font drawing) by allowing - * pipelining of data uploads, avoiding a sync of the card after each glyph. - * - * @return TRUE if the driver successfully uploaded the data. FALSE - * indicates that EXA should fall back to doing the upload in software. - * - * UploadToScreen() is not required, but is recommended if Composite - * acceleration is supported. - */ - Bool (*UploadToScreen) (PixmapPtr pDst, - int x, - int y, int w, int h, char *src, int src_pitch); - - /** - * UploadToScratch() is no longer used and will be removed next time the EXA - * major version needs to be bumped. - */ - Bool (*UploadToScratch) (PixmapPtr pSrc, PixmapPtr pDst); - - /** - * DownloadFromScreen() loads a rectangle of data from pSrc into dst - * - * @param pSrc source pixmap - * @param x source X coordinate. - * @param y source Y coordinate - * @param width width of the rectangle to be copied - * @param height height of the rectangle to be copied - * @param dst pointer to the beginning of the destination data - * @param dst_pitch pitch (in bytes) of the lines of destination data. - * - * DownloadFromScreen() copies data from offscreen memory in pSrc from - * (x, y) to (x + width, y + height), to system memory starting at - * dst (with pitch dst_pitch). This would usually be done - * using scatter-gather DMA, supported by a DRM call, or by blitting to AGP - * and then synchronously reading from AGP. Because the implementation - * might be synchronous, EXA leaves it up to the driver to call - * exaMarkSync() if DownloadFromScreen() was asynchronous. This is in - * contrast to most other acceleration calls in EXA. - * - * DownloadFromScreen() can aid in the largest bottleneck in pixmap - * migration, which is the read from framebuffer when evicting pixmaps from - * framebuffer memory. Thus, it is highly recommended, even though - * implementations are typically complicated. - * - * @return TRUE if the driver successfully downloaded the data. FALSE - * indicates that EXA should fall back to doing the download in software. - * - * DownloadFromScreen() is not required, but is highly recommended. - */ - Bool (*DownloadFromScreen) (PixmapPtr pSrc, - int x, int y, - int w, int h, char *dst, int dst_pitch); - - /** - * MarkSync() requests that the driver mark a synchronization point, - * returning an driver-defined integer marker which could be requested for - * synchronization to later in WaitMarker(). This might be used in the - * future to avoid waiting for full hardware stalls before accessing pixmap - * data with the CPU, but is not important in the current incarnation of - * EXA. - * - * Note that drivers should call exaMarkSync() when they have done some - * acceleration, rather than their own MarkSync() handler, as otherwise EXA - * will be unaware of the driver's acceleration and not sync to it during - * fallbacks. - * - * MarkSync() is optional. - */ - int (*MarkSync) (ScreenPtr pScreen); - - /** - * WaitMarker() waits for all rendering before the given marker to have - * completed. If the driver does not implement MarkSync(), marker is - * meaningless, and all rendering by the hardware should be completed before - * WaitMarker() returns. - * - * Note that drivers should call exaWaitSync() to wait for all acceleration - * to finish, as otherwise EXA will be unaware of the driver having - * synchronized, resulting in excessive WaitMarker() calls. - * - * WaitMarker() is required of all drivers. - */ - void (*WaitMarker) (ScreenPtr pScreen, int marker); - - /** @{ */ - /** - * PrepareAccess() is called before CPU access to an offscreen pixmap. - * - * @param pPix the pixmap being accessed - * @param index the index of the pixmap being accessed. - * - * PrepareAccess() will be called before CPU access to an offscreen pixmap. - * This can be used to set up hardware surfaces for byteswapping or - * untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of - * making CPU access use a different aperture. - * - * The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC, - * #EXA_PREPARE_MASK, #EXA_PREPARE_AUX_DEST, #EXA_PREPARE_AUX_SRC, or - * #EXA_PREPARE_AUX_MASK. Since only up to #EXA_NUM_PREPARE_INDICES pixmaps - * will have PrepareAccess() called on them per operation, drivers can have - * a small, statically-allocated space to maintain state for PrepareAccess() - * and FinishAccess() in. Note that PrepareAccess() is only called once per - * pixmap and operation, regardless of whether the pixmap is used as a - * destination and/or source, and the index may not reflect the usage. - * - * PrepareAccess() may fail. An example might be the case of hardware that - * can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess() - * fails, EXA will migrate the pixmap to system memory. - * DownloadFromScreen() must be implemented and must not fail if a driver - * wishes to fail in PrepareAccess(). PrepareAccess() must not fail when - * pPix is the visible screen, because the visible screen can not be - * migrated. - * - * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU - * drawing. - * @return FALSE if PrepareAccess() is unsuccessful and EXA should use - * DownloadFromScreen() to migate the pixmap out. - */ - Bool (*PrepareAccess) (PixmapPtr pPix, int index); - - /** - * FinishAccess() is called after CPU access to an offscreen pixmap. - * - * @param pPix the pixmap being accessed - * @param index the index of the pixmap being accessed. - * - * FinishAccess() will be called after finishing CPU access of an offscreen - * pixmap set up by PrepareAccess(). Note that the FinishAccess() will not be - * called if PrepareAccess() failed and the pixmap was migrated out. - */ - void (*FinishAccess) (PixmapPtr pPix, int index); - - /** - * PixmapIsOffscreen() is an optional driver replacement to - * exaPixmapHasGpuCopy(). Set to NULL if you want the standard behaviour - * of exaPixmapHasGpuCopy(). - * - * @param pPix the pixmap - * @return TRUE if the given drawable is in framebuffer memory. - * - * exaPixmapHasGpuCopy() 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 - * with the CPU. - * - * - */ - Bool (*PixmapIsOffscreen) (PixmapPtr pPix); - - /** @name PrepareAccess() and FinishAccess() indices - * @{ - */ - /** - * EXA_PREPARE_DEST is the index for a pixmap that may be drawn to or - * read from. - */ -#define EXA_PREPARE_DEST 0 - /** - * EXA_PREPARE_SRC is the index for a pixmap that may be read from - */ -#define EXA_PREPARE_SRC 1 - /** - * EXA_PREPARE_SRC is the index for a second pixmap that may be read - * from. - */ -#define EXA_PREPARE_MASK 2 - /** - * EXA_PREPARE_AUX* are additional indices for other purposes, e.g. - * separate alpha maps with Composite operations. - */ -#define EXA_PREPARE_AUX_DEST 3 -#define EXA_PREPARE_AUX_SRC 4 -#define EXA_PREPARE_AUX_MASK 5 -#define EXA_NUM_PREPARE_INDICES 6 - /** @} */ - - /** - * maxPitchPixels controls the pitch limitation for rendering from - * the card. - * The driver should never receive a request for rendering a pixmap - * that has a pitch (in pixels) beyond maxPitchPixels. - * - * Setting this field is optional -- if your hardware doesn't have - * a pitch limitation in pixels, don't set this. If neither this value - * nor maxPitchBytes is set, then maxPitchPixels is set to maxX. - * If set, it must not be smaller than maxX. - * - * @sa maxPitchBytes - */ - int maxPitchPixels; - - /** - * maxPitchBytes controls the pitch limitation for rendering from - * the card. - * The driver should never receive a request for rendering a pixmap - * that has a pitch (in bytes) beyond maxPitchBytes. - * - * Setting this field is optional -- if your hardware doesn't have - * a pitch limitation in bytes, don't set this. - * If set, it must not be smaller than maxX * 4. - * There's no default value for maxPitchBytes. - * - * @sa maxPitchPixels - */ - int maxPitchBytes; - - /* Hooks to allow driver to its own pixmap memory management */ - void *(*CreatePixmap) (ScreenPtr pScreen, int size, int align); - void (*DestroyPixmap) (ScreenPtr pScreen, void *driverPriv); - /** - * Returning a pixmap with non-NULL devPrivate.ptr implies a pixmap which is - * not offscreen, which will never be accelerated and Prepare/FinishAccess won't - * be called. - */ - Bool (*ModifyPixmapHeader) (PixmapPtr pPixmap, int width, int height, - int depth, int bitsPerPixel, int devKind, - void *pPixData); - - /* hooks for drivers with tiling support: - * driver MUST fill out new_fb_pitch with valid pitch of pixmap - */ - void *(*CreatePixmap2) (ScreenPtr pScreen, int width, int height, - int depth, int usage_hint, int bitsPerPixel, - int *new_fb_pitch); - /** @} */ - Bool (*SharePixmapBacking)(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p); - - Bool (*SetSharedPixmapBacking)(PixmapPtr pPixmap, void *handle); - -} ExaDriverRec, *ExaDriverPtr; - -/** @name EXA driver flags - * @{ - */ -/** - * EXA_OFFSCREEN_PIXMAPS indicates to EXA that the driver can support - * offscreen pixmaps. - */ -#define EXA_OFFSCREEN_PIXMAPS (1 << 0) - -/** - * EXA_OFFSCREEN_ALIGN_POT indicates to EXA that the driver needs pixmaps - * to have a power-of-two pitch. - */ -#define EXA_OFFSCREEN_ALIGN_POT (1 << 1) - -/** - * EXA_TWO_BITBLT_DIRECTIONS indicates to EXA that the driver can only - * support copies that are (left-to-right, top-to-bottom) or - * (right-to-left, bottom-to-top). - */ -#define EXA_TWO_BITBLT_DIRECTIONS (1 << 2) - -/** - * EXA_HANDLES_PIXMAPS indicates to EXA that the driver can handle - * all pixmap addressing and migration. - */ -#define EXA_HANDLES_PIXMAPS (1 << 3) - -/** - * EXA_SUPPORTS_PREPARE_AUX indicates to EXA that the driver can handle the - * EXA_PREPARE_AUX* indices in the Prepare/FinishAccess hooks. If there are no - * such hooks, this flag has no effect. - */ -#define EXA_SUPPORTS_PREPARE_AUX (1 << 4) - -/** - * EXA_SUPPORTS_OFFSCREEN_OVERLAPS indicates to EXA that the driver Copy hooks - * can handle the source and destination occupying overlapping offscreen memory - * areas. This allows the offscreen memory defragmentation code to defragment - * areas where the defragmented position overlaps the fragmented position. - * - * Typically this is supported by traditional 2D engines but not by 3D engines. - */ -#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 */ -extern _X_EXPORT ExaDriverPtr exaDriverAlloc(void); - -extern _X_EXPORT Bool - exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo); - -extern _X_EXPORT void - exaDriverFini(ScreenPtr pScreen); - -extern _X_EXPORT void - exaMarkSync(ScreenPtr pScreen); -extern _X_EXPORT void - exaWaitSync(ScreenPtr pScreen); - -extern _X_EXPORT unsigned long - exaGetPixmapOffset(PixmapPtr pPix); - -extern _X_EXPORT unsigned long - exaGetPixmapPitch(PixmapPtr pPix); - -extern _X_EXPORT unsigned long - exaGetPixmapSize(PixmapPtr pPix); - -extern _X_EXPORT void *exaGetPixmapDriverPrivate(PixmapPtr p); - -/* in exa_offscreen.c */ -extern _X_EXPORT ExaOffscreenArea *exaOffscreenAlloc(ScreenPtr pScreen, - int size, int align, - Bool locked, - ExaOffscreenSaveProc save, - void *privData); - -extern _X_EXPORT ExaOffscreenArea *exaOffscreenFree(ScreenPtr pScreen, - ExaOffscreenArea * area); - -extern _X_EXPORT void - ExaOffscreenMarkUsed(PixmapPtr pPixmap); - -extern _X_EXPORT void - exaEnableDisableFBAccess(ScreenPtr pScreen, Bool enable); - -extern _X_EXPORT Bool - exaDrawableIsOffscreen(DrawablePtr pDrawable); - -/* in exa.c */ -extern _X_EXPORT void - exaMoveInPixmap(PixmapPtr pPixmap); - -extern _X_EXPORT void - exaMoveOutPixmap(PixmapPtr pPixmap); - -/* in exa_unaccel.c */ -extern _X_EXPORT CARD32 - exaGetPixmapFirstPixel(PixmapPtr pPixmap); - -/** - * Returns TRUE if the given planemask covers all the significant bits in the - * pixel values for pDrawable. - */ -#define EXA_PM_IS_SOLID(_pDrawable, _pm) \ - (((_pm) & FbFullMask((_pDrawable)->depth)) == \ - FbFullMask((_pDrawable)->depth)) - -#endif /* EXA_H */ diff --git a/exa/exa_accel.c b/exa/exa_accel.c deleted file mode 100644 index e632331da..000000000 --- a/exa/exa_accel.c +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * Copyright © 2001 Keith Packard - * - * Partly based on code that is Copyright © The XFree86 Project Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Michel Dänzer <michel@tungstengraphics.com> - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif -#include "exa_priv.h" -#include <X11/fonts/fontstruct.h> -#include "dixfontstr.h" -#include "exa.h" - -static void -exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, - DDXPointPtr ppt, int *pwidth, int fSorted) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - ExaScreenPriv(pScreen); - RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPixmap); - BoxPtr pextent, pbox; - int nbox; - int extentX1, extentX2, extentY1, extentY2; - int fullX1, fullX2, fullY1; - int partX1, partX2; - int off_x, off_y; - - if (pExaScr->fallback_counter || - pExaScr->swappedOut || - pGC->fillStyle != FillSolid || pExaPixmap->accel_blocked) { - ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); - return; - } - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[1]; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPixmap; - pixmaps[0].pReg = NULL; - - exaDoMigration(pixmaps, 1, TRUE); - } - - if (!(pPixmap = exaGetOffscreenPixmap(pDrawable, &off_x, &off_y)) || - !(*pExaScr->info->PrepareSolid) (pPixmap, - pGC->alu, - pGC->planemask, pGC->fgPixel)) { - ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted); - return; - } - - pextent = RegionExtents(pClip); - extentX1 = pextent->x1; - extentY1 = pextent->y1; - extentX2 = pextent->x2; - extentY2 = pextent->y2; - while (n--) { - fullX1 = ppt->x; - fullY1 = ppt->y; - fullX2 = fullX1 + (int) *pwidth; - ppt++; - pwidth++; - - if (fullY1 < extentY1 || extentY2 <= fullY1) - continue; - - if (fullX1 < extentX1) - fullX1 = extentX1; - - if (fullX2 > extentX2) - fullX2 = extentX2; - - if (fullX1 >= fullX2) - continue; - - nbox = RegionNumRects(pClip); - if (nbox == 1) { - (*pExaScr->info->Solid) (pPixmap, - fullX1 + off_x, fullY1 + off_y, - fullX2 + off_x, fullY1 + 1 + off_y); - } - else { - pbox = RegionRects(pClip); - while (nbox--) { - if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) { - partX1 = pbox->x1; - if (partX1 < fullX1) - partX1 = fullX1; - partX2 = pbox->x2; - if (partX2 > fullX2) - partX2 = fullX2; - if (partX2 > partX1) { - (*pExaScr->info->Solid) (pPixmap, - partX1 + off_x, fullY1 + off_y, - partX2 + off_x, - fullY1 + 1 + off_y); - } - } - pbox++; - } - } - } - (*pExaScr->info->DoneSolid) (pPixmap); - exaMarkSync(pScreen); -} - -static Bool -exaDoPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - int w, int h, int format, char *bits, int src_stride) -{ - ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPix); - RegionPtr pClip; - BoxPtr pbox; - int nbox; - int xoff, yoff; - int bpp = pDrawable->bitsPerPixel; - Bool ret = TRUE; - - if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || - !pExaScr->info->UploadToScreen) - return FALSE; - - /* If there's a system copy, we want to save the result there */ - if (pExaPixmap->pDamage) - return FALSE; - - /* Don't bother with under 8bpp, XYPixmaps. */ - if (format != ZPixmap || bpp < 8) - return FALSE; - - /* Only accelerate copies: no rop or planemask. */ - if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) - return FALSE; - - if (pExaScr->swappedOut) - return FALSE; - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[1]; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPix; - pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); - - exaDoMigration(pixmaps, 1, TRUE); - } - - pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff); - - if (!pPix) - return FALSE; - - x += pDrawable->x; - y += pDrawable->y; - - pClip = fbGetCompositeClip(pGC); - for (nbox = RegionNumRects(pClip), - pbox = RegionRects(pClip); nbox--; pbox++) { - int x1 = x; - int y1 = y; - int x2 = x + w; - int y2 = y + h; - char *src; - Bool ok; - - if (x1 < pbox->x1) - x1 = pbox->x1; - if (y1 < pbox->y1) - y1 = pbox->y1; - if (x2 > pbox->x2) - x2 = pbox->x2; - if (y2 > pbox->y2) - y2 = pbox->y2; - if (x1 >= x2 || y1 >= y2) - continue; - - src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); - ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, - x2 - x1, y2 - y1, src, src_stride); - /* We have to fall back completely, and ignore what has already been completed. - * Messing with the fb layer directly like we used to is completely unacceptable. - */ - if (!ok) { - ret = FALSE; - break; - } - } - - if (ret) - exaMarkSync(pDrawable->pScreen); - - return ret; -} - -static void -exaPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char *bits) -{ - if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits, - PixmapBytePad(w, pDrawable->depth))) - ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, - bits); -} - -static Bool inline -exaCopyNtoNTwoDir(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, - GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) -{ - ExaScreenPriv(pDstDrawable->pScreen); - PixmapPtr pSrcPixmap, pDstPixmap; - int src_off_x, src_off_y, dst_off_x, dst_off_y; - int dirsetup; - - /* Need to get both pixmaps to call the driver routines */ - pSrcPixmap = exaGetOffscreenPixmap(pSrcDrawable, &src_off_x, &src_off_y); - pDstPixmap = exaGetOffscreenPixmap(pDstDrawable, &dst_off_x, &dst_off_y); - if (!pSrcPixmap || !pDstPixmap) - return FALSE; - - /* - * Now the case of a chip that only supports xdir = ydir = 1 or - * xdir = ydir = -1, but we have xdir != ydir. - */ - dirsetup = 0; /* No direction set up yet. */ - for (; nbox; pbox++, nbox--) { - if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { - /* Do a xdir = ydir = -1 blit instead. */ - if (dirsetup != -1) { - if (dirsetup != 0) - pExaScr->info->DoneCopy(pDstPixmap); - dirsetup = -1; - if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, - pDstPixmap, - -1, -1, - pGC ? pGC->alu : GXcopy, - pGC ? pGC->planemask : - FB_ALLONES)) - return FALSE; - } - (*pExaScr->info->Copy) (pDstPixmap, - src_off_x + pbox->x1 + dx, - src_off_y + pbox->y1 + dy, - dst_off_x + pbox->x1, - dst_off_y + pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - } - else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { - /* Do a xdir = ydir = 1 blit instead. */ - if (dirsetup != 1) { - if (dirsetup != 0) - pExaScr->info->DoneCopy(pDstPixmap); - dirsetup = 1; - if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, - pDstPixmap, - 1, 1, - pGC ? pGC->alu : GXcopy, - pGC ? pGC->planemask : - FB_ALLONES)) - return FALSE; - } - (*pExaScr->info->Copy) (pDstPixmap, - src_off_x + pbox->x1 + dx, - src_off_y + pbox->y1 + dy, - dst_off_x + pbox->x1, - dst_off_y + pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - } - else if (dx >= 0) { - /* - * xdir = 1, ydir = -1. - * Perform line-by-line xdir = ydir = 1 blits, going up. - */ - int i; - - if (dirsetup != 1) { - if (dirsetup != 0) - pExaScr->info->DoneCopy(pDstPixmap); - dirsetup = 1; - if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, - pDstPixmap, - 1, 1, - pGC ? pGC->alu : GXcopy, - pGC ? pGC->planemask : - FB_ALLONES)) - return FALSE; - } - for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) - (*pExaScr->info->Copy) (pDstPixmap, - src_off_x + pbox->x1 + dx, - src_off_y + pbox->y1 + dy + i, - dst_off_x + pbox->x1, - dst_off_y + pbox->y1 + i, - pbox->x2 - pbox->x1, 1); - } - else { - /* - * xdir = -1, ydir = 1. - * Perform line-by-line xdir = ydir = -1 blits, going down. - */ - int i; - - if (dirsetup != -1) { - if (dirsetup != 0) - pExaScr->info->DoneCopy(pDstPixmap); - dirsetup = -1; - if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, - pDstPixmap, - -1, -1, - pGC ? pGC->alu : GXcopy, - pGC ? pGC->planemask : - FB_ALLONES)) - return FALSE; - } - for (i = 0; i < pbox->y2 - pbox->y1; i++) - (*pExaScr->info->Copy) (pDstPixmap, - src_off_x + pbox->x1 + dx, - src_off_y + pbox->y1 + dy + i, - dst_off_x + pbox->x1, - dst_off_y + pbox->y1 + i, - pbox->x2 - pbox->x1, 1); - } - } - if (dirsetup != 0) - pExaScr->info->DoneCopy(pDstPixmap); - exaMarkSync(pDstDrawable->pScreen); - return TRUE; -} - -Bool -exaHWCopyNtoN(DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - BoxPtr pbox, - int nbox, int dx, int dy, Bool reverse, Bool upsidedown) -{ - ExaScreenPriv(pDstDrawable->pScreen); - PixmapPtr pSrcPixmap, pDstPixmap; - ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; - int src_off_x, src_off_y; - int dst_off_x, dst_off_y; - RegionPtr srcregion = NULL, dstregion = NULL; - xRectangle *rects; - Bool ret = TRUE; - - /* avoid doing copy operations if no boxes */ - if (nbox == 0) - return TRUE; - - pSrcPixmap = exaGetDrawablePixmap(pSrcDrawable); - pDstPixmap = exaGetDrawablePixmap(pDstDrawable); - - exaGetDrawableDeltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); - exaGetDrawableDeltas(pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); - - rects = xallocarray(nbox, sizeof(xRectangle)); - - if (rects) { - int i; - int ordering; - - for (i = 0; i < nbox; i++) { - rects[i].x = pbox[i].x1 + dx + src_off_x; - rects[i].y = pbox[i].y1 + dy + src_off_y; - rects[i].width = pbox[i].x2 - pbox[i].x1; - rects[i].height = pbox[i].y2 - pbox[i].y1; - } - - /* This must match the RegionCopy() logic for reversing rect order */ - if (nbox == 1 || (dx > 0 && dy > 0) || - (pDstDrawable != pSrcDrawable && - (pDstDrawable->type != DRAWABLE_WINDOW || - pSrcDrawable->type != DRAWABLE_WINDOW))) - ordering = CT_YXBANDED; - else - ordering = CT_UNSORTED; - - srcregion = RegionFromRects(nbox, rects, ordering); - free(rects); - - if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, - pGC->fillStyle, pGC->alu, - pGC->clientClip != NULL)) { - dstregion = RegionCreate(NullBox, 0); - RegionCopy(dstregion, srcregion); - RegionTranslate(dstregion, dst_off_x - dx - src_off_x, - dst_off_y - dy - src_off_y); - } - } - - pSrcExaPixmap = ExaGetPixmapPriv(pSrcPixmap); - pDstExaPixmap = ExaGetPixmapPriv(pDstPixmap); - - /* Check whether the accelerator can use this pixmap. - * If the pitch of the pixmaps is out of range, there's nothing - * we can do but fall back to software rendering. - */ - if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || - pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) - goto fallback; - - /* If the width or the height of either of the pixmaps - * is out of range, check whether the boxes are actually out of the - * addressable range as well. If they aren't, we can still do - * the copying in hardware. - */ - if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { - int i; - - for (i = 0; i < nbox; i++) { - /* src */ - if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || - (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) - goto fallback; - - /* dst */ - if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || - (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) - goto fallback; - } - } - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[2]; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pDstPixmap; - pixmaps[0].pReg = dstregion; - pixmaps[1].as_dst = FALSE; - pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = pSrcPixmap; - pixmaps[1].pReg = srcregion; - - exaDoMigration(pixmaps, 2, TRUE); - } - - /* Mixed directions must be handled specially if the card is lame */ - if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && - reverse != upsidedown) { - if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, - dx, dy)) - goto out; - goto fallback; - } - - if (exaPixmapHasGpuCopy(pDstPixmap)) { - /* Normal blitting. */ - if (exaPixmapHasGpuCopy(pSrcPixmap)) { - if (!(*pExaScr->info->PrepareCopy) - (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1, - pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) { - goto fallback; - } - - while (nbox--) { - (*pExaScr->info->Copy) (pDstPixmap, - pbox->x1 + dx + src_off_x, - pbox->y1 + dy + src_off_y, - pbox->x1 + dst_off_x, - pbox->y1 + dst_off_y, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - pbox++; - } - - (*pExaScr->info->DoneCopy) (pDstPixmap); - exaMarkSync(pDstDrawable->pScreen); - /* UTS: mainly for SHM PutImage's secondary path. - * - * Only taking this path for directly accessible pixmaps. - */ - } - else if (!pDstExaPixmap->pDamage && pSrcExaPixmap->sys_ptr) { - int bpp = pSrcDrawable->bitsPerPixel; - int src_stride = exaGetPixmapPitch(pSrcPixmap); - CARD8 *src = NULL; - - if (!pExaScr->info->UploadToScreen) - goto fallback; - - if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) - goto fallback; - - if (pSrcDrawable->bitsPerPixel < 8) - goto fallback; - - if (pGC && - !(pGC->alu == GXcopy && - EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask))) - goto fallback; - - while (nbox--) { - src = - pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + - src_off_y) * src_stride + - (pbox->x1 + dx + src_off_x) * (bpp / 8); - if (!pExaScr->info-> - UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x, - pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1, (char *) src, - src_stride)) - goto fallback; - - pbox++; - } - } - else - goto fallback; - } - else - goto fallback; - - goto out; - - fallback: - ret = FALSE; - - out: - if (dstregion) { - RegionUninit(dstregion); - RegionDestroy(dstregion); - } - if (srcregion) { - RegionUninit(srcregion); - RegionDestroy(srcregion); - } - - return ret; -} - -void -exaCopyNtoN(DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - BoxPtr pbox, - int nbox, - int dx, - int dy, - Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) -{ - ExaScreenPriv(pDstDrawable->pScreen); - - if (pExaScr->fallback_counter || - (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW)) - return; - - if (exaHWCopyNtoN - (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, - upsidedown)) - return; - - /* This is a CopyWindow, it's cleaner to fallback at the original call. */ - if (pExaScr->fallback_flags & EXA_ACCEL_COPYWINDOW) { - pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW; - return; - } - - /* fallback */ - ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, - reverse, upsidedown, bitplane, closure); -} - -RegionPtr -exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, - int srcx, int srcy, int width, int height, int dstx, int dsty) -{ - ExaScreenPriv(pDstDrawable->pScreen); - - if (pExaScr->fallback_counter || pExaScr->swappedOut) { - return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC, - srcx, srcy, width, height, dstx, dsty); - } - - return miDoCopy(pSrcDrawable, pDstDrawable, pGC, - srcx, srcy, width, height, - dstx, dsty, exaCopyNtoN, 0, NULL); -} - -static void -exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr ppt) -{ - ExaScreenPriv(pDrawable->pScreen); - int i; - xRectangle *prect; - - /* If we can't reuse the current GC as is, don't bother accelerating the - * points. - */ - if (pExaScr->fallback_counter || pGC->fillStyle != FillSolid) { - ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); - return; - } - - prect = xallocarray(npt, sizeof(xRectangle)); - for (i = 0; i < npt; i++) { - prect[i].x = ppt[i].x; - prect[i].y = ppt[i].y; - if (i > 0 && mode == CoordModePrevious) { - prect[i].x += prect[i - 1].x; - prect[i].y += prect[i - 1].y; - } - prect[i].width = 1; - prect[i].height = 1; - } - pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); - free(prect); -} - -/** - * exaPolylines() checks if it can accelerate the lines as a group of - * horizontal or vertical lines (rectangles), and uses existing rectangle fill - * acceleration if so. - */ -static void -exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr ppt) -{ - ExaScreenPriv(pDrawable->pScreen); - xRectangle *prect; - int x1, x2, y1, y2; - int i; - - if (pExaScr->fallback_counter) { - ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); - return; - } - - /* Don't try to do wide lines or non-solid fill style. */ - if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || - pGC->fillStyle != FillSolid) { - ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); - return; - } - - prect = xallocarray(npt - 1, sizeof(xRectangle)); - x1 = ppt[0].x; - y1 = ppt[0].y; - /* If we have any non-horizontal/vertical, fall back. */ - for (i = 0; i < npt - 1; i++) { - if (mode == CoordModePrevious) { - x2 = x1 + ppt[i + 1].x; - y2 = y1 + ppt[i + 1].y; - } - else { - x2 = ppt[i + 1].x; - y2 = ppt[i + 1].y; - } - - if (x1 != x2 && y1 != y2) { - free(prect); - ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); - return; - } - - if (x1 < x2) { - prect[i].x = x1; - prect[i].width = x2 - x1 + 1; - } - else { - prect[i].x = x2; - prect[i].width = x1 - x2 + 1; - } - if (y1 < y2) { - prect[i].y = y1; - prect[i].height = y2 - y1 + 1; - } - else { - prect[i].y = y2; - prect[i].height = y1 - y2 + 1; - } - - x1 = x2; - y1 = y2; - } - pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); - free(prect); -} - -/** - * exaPolySegment() checks if it can accelerate the lines as a group of - * horizontal or vertical lines (rectangles), and uses existing rectangle fill - * acceleration if so. - */ -static void -exaPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg) -{ - ExaScreenPriv(pDrawable->pScreen); - xRectangle *prect; - int i; - - /* Don't try to do wide lines or non-solid fill style. */ - if (pExaScr->fallback_counter || pGC->lineWidth != 0 || - pGC->lineStyle != LineSolid || pGC->fillStyle != FillSolid) { - ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); - return; - } - - /* If we have any non-horizontal/vertical, fall back. */ - for (i = 0; i < nseg; i++) { - if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { - ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); - return; - } - } - - prect = xallocarray((unsigned int)nseg, sizeof(xRectangle)); - for (i = 0; i < nseg; i++) { - if (pSeg[i].x1 < pSeg[i].x2) { - prect[i].x = pSeg[i].x1; - prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; - } - else { - prect[i].x = pSeg[i].x2; - prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; - } - if (pSeg[i].y1 < pSeg[i].y2) { - prect[i].y = pSeg[i].y1; - prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; - } - else { - prect[i].y = pSeg[i].y2; - prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; - } - - /* don't paint last pixel */ - if (pGC->capStyle == CapNotLast) { - if (prect[i].width == 1) - prect[i].height--; - else - prect[i].width--; - } - } - pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); - free(prect); -} - -static Bool exaFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, - Pixel pixel, CARD32 planemask, CARD32 alu, - Bool hasClientClip); - -static void -exaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) -{ - ExaScreenPriv(pDrawable->pScreen); - RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPixmap); - register BoxPtr pbox; - BoxPtr pextent; - int extentX1, extentX2, extentY1, extentY2; - int fullX1, fullX2, fullY1, fullY2; - int partX1, partX2, partY1, partY2; - int xoff, yoff; - int xorg, yorg; - int n; - RegionPtr pReg = RegionFromRects(nrect, prect, CT_UNSORTED); - - /* Compute intersection of rects and clip region */ - RegionTranslate(pReg, pDrawable->x, pDrawable->y); - RegionIntersect(pReg, pClip, pReg); - - if (!RegionNumRects(pReg)) { - goto out; - } - - exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); - - if (pExaScr->fallback_counter || pExaScr->swappedOut || - pExaPixmap->accel_blocked) { - goto fallback; - } - - /* For ROPs where overlaps don't matter, convert rectangles to region and - * call exaFillRegion{Solid,Tiled}. - */ - if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && - (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || - pGC->alu == GXnoop || pGC->alu == GXcopyInverted || - pGC->alu == GXset)) { - if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && - exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? - pGC->fgPixel : pGC->tile.pixel, pGC->planemask, - pGC->alu, pGC->clientClip != NULL)) || - (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && - exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, - pGC->planemask, pGC->alu, - pGC->clientClip != NULL))) { - goto out; - } - } - - if (pGC->fillStyle != FillSolid && - !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { - goto fallback; - } - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[1]; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPixmap; - pixmaps[0].pReg = NULL; - - exaDoMigration(pixmaps, 1, TRUE); - } - - if (!exaPixmapHasGpuCopy(pPixmap) || - !(*pExaScr->info->PrepareSolid) (pPixmap, - pGC->alu, - pGC->planemask, pGC->fgPixel)) { - fallback: - ExaCheckPolyFillRect(pDrawable, pGC, nrect, prect); - goto out; - } - - xorg = pDrawable->x; - yorg = pDrawable->y; - - pextent = RegionExtents(pClip); - extentX1 = pextent->x1; - extentY1 = pextent->y1; - extentX2 = pextent->x2; - extentY2 = pextent->y2; - while (nrect--) { - fullX1 = prect->x + xorg; - fullY1 = prect->y + yorg; - fullX2 = fullX1 + (int) prect->width; - fullY2 = fullY1 + (int) prect->height; - prect++; - - if (fullX1 < extentX1) - fullX1 = extentX1; - - if (fullY1 < extentY1) - fullY1 = extentY1; - - if (fullX2 > extentX2) - fullX2 = extentX2; - - if (fullY2 > extentY2) - fullY2 = extentY2; - - if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) - continue; - n = RegionNumRects(pClip); - if (n == 1) { - (*pExaScr->info->Solid) (pPixmap, - fullX1 + xoff, fullY1 + yoff, - fullX2 + xoff, fullY2 + yoff); - } - else { - pbox = RegionRects(pClip); - /* - * clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect(), - * but rectangles may overlap each other here. - */ - while (n--) { - partX1 = pbox->x1; - if (partX1 < fullX1) - partX1 = fullX1; - partY1 = pbox->y1; - if (partY1 < fullY1) - partY1 = fullY1; - partX2 = pbox->x2; - if (partX2 > fullX2) - partX2 = fullX2; - partY2 = pbox->y2; - if (partY2 > fullY2) - partY2 = fullY2; - - pbox++; - - if (partX1 < partX2 && partY1 < partY2) { - (*pExaScr->info->Solid) (pPixmap, - partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); - } - } - } - } - (*pExaScr->info->DoneSolid) (pPixmap); - exaMarkSync(pDrawable->pScreen); - - out: - RegionUninit(pReg); - RegionDestroy(pReg); -} - -const GCOps exaOps = { - exaFillSpans, - ExaCheckSetSpans, - exaPutImage, - exaCopyArea, - ExaCheckCopyPlane, - exaPolyPoint, - exaPolylines, - exaPolySegment, - miPolyRectangle, - ExaCheckPolyArc, - miFillPolygon, - exaPolyFillRect, - miPolyFillArc, - miPolyText8, - miPolyText16, - miImageText8, - miImageText16, - ExaCheckImageGlyphBlt, - ExaCheckPolyGlyphBlt, - ExaCheckPushPixels, -}; - -void -exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - RegionRec rgnDst; - int dx, dy; - PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); - - ExaScreenPriv(pWin->drawable.pScreen); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - RegionTranslate(prgnSrc, -dx, -dy); - - RegionInit(&rgnDst, NullBox, 0); - - RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); -#ifdef COMPOSITE - if (pPixmap->screen_x || pPixmap->screen_y) - RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y); -#endif - - if (pExaScr->fallback_counter) { - pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW; - goto fallback; - } - - pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW; - miCopyRegion(&pPixmap->drawable, &pPixmap->drawable, - NULL, &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); - pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW; - - fallback: - RegionUninit(&rgnDst); - - if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) { - pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW; - RegionTranslate(prgnSrc, dx, dy); - ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc); - } -} - -static Bool -exaFillRegionSolid(DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, - CARD32 planemask, CARD32 alu, Bool hasClientClip) -{ - ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPixmap); - int xoff, yoff; - Bool ret = FALSE; - - exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); - RegionTranslate(pRegion, xoff, yoff); - - if (pExaScr->fallback_counter || pExaPixmap->accel_blocked) - goto out; - - 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, - hasClientClip) ? NULL : pRegion; - - exaDoMigration(pixmaps, 1, TRUE); - } - - if (exaPixmapHasGpuCopy(pPixmap) && - (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) { - int nbox; - BoxPtr pBox; - - nbox = RegionNumRects(pRegion); - pBox = RegionRects(pRegion); - - while (nbox--) { - (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2, - pBox->y2); - pBox++; - } - (*pExaScr->info->DoneSolid) (pPixmap); - exaMarkSync(pDrawable->pScreen); - - if (pExaPixmap->pDamage && - pExaPixmap->sys_ptr && pDrawable->type == DRAWABLE_PIXMAP && - pDrawable->width == 1 && pDrawable->height == 1 && - pDrawable->bitsPerPixel != 24 && alu == GXcopy) { - RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); - - switch (pDrawable->bitsPerPixel) { - case 32: - *(CARD32 *) pExaPixmap->sys_ptr = pixel; - break; - case 16: - *(CARD16 *) pExaPixmap->sys_ptr = pixel; - break; - case 8: - case 4: - case 1: - *(CARD8 *) pExaPixmap->sys_ptr = pixel; - } - - RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, pRegion); - RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, pRegion); - RegionSubtract(pending_damage, pending_damage, pRegion); - } - - ret = TRUE; - } - - out: - RegionTranslate(pRegion, -xoff, -yoff); - - return ret; -} - -/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. - * Based on fbFillRegionTiled(), fbTile(). - */ -Bool -exaFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, - DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu, - Bool hasClientClip) -{ - ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPixmap; - ExaPixmapPrivPtr pExaPixmap; - ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); - int xoff, yoff; - int tileWidth, tileHeight; - int nbox = RegionNumRects(pRegion); - BoxPtr pBox = RegionRects(pRegion); - Bool ret = FALSE; - int i; - - tileWidth = pTile->drawable.width; - tileHeight = pTile->drawable.height; - - /* If we're filling with a solid color, grab it out and go to - * FillRegionSolid, saving numerous copies. - */ - if (tileWidth == 1 && tileHeight == 1) - return exaFillRegionSolid(pDrawable, pRegion, - exaGetPixmapFirstPixel(pTile), planemask, - alu, hasClientClip); - - pPixmap = exaGetDrawablePixmap(pDrawable); - pExaPixmap = ExaGetPixmapPriv(pPixmap); - - if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || - pTileExaPixmap->accel_blocked) - return FALSE; - - 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, - hasClientClip) ? NULL : pRegion; - pixmaps[1].as_dst = FALSE; - pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = pTile; - pixmaps[1].pReg = NULL; - - exaDoMigration(pixmaps, 2, TRUE); - } - - pPixmap = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff); - - if (!pPixmap || !exaPixmapHasGpuCopy(pTile)) - return FALSE; - - if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) { - if (xoff || yoff) - RegionTranslate(pRegion, xoff, yoff); - - for (i = 0; i < nbox; i++) { - int height = pBox[i].y2 - pBox[i].y1; - int dstY = pBox[i].y1; - int tileY; - - if (alu == GXcopy) - height = min(height, tileHeight); - - modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); - - while (height > 0) { - int width = pBox[i].x2 - pBox[i].x1; - int dstX = pBox[i].x1; - int tileX; - int h = tileHeight - tileY; - - if (alu == GXcopy) - width = min(width, tileWidth); - - if (h > height) - h = height; - height -= h; - - modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, - tileX); - - while (width > 0) { - int w = tileWidth - tileX; - - if (w > width) - w = width; - width -= w; - - (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY, - w, h); - dstX += w; - tileX = 0; - } - dstY += h; - tileY = 0; - } - } - (*pExaScr->info->DoneCopy) (pPixmap); - - /* With GXcopy, we only need to do the basic algorithm up to the tile - * size; then, we can just keep doubling the destination in each - * direction until it fills the box. This way, the number of copy - * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where - * rx/ry is the ratio between box and tile width/height. This can make - * a big difference if each driver copy incurs a significant constant - * overhead. - */ - if (alu != GXcopy) - ret = TRUE; - else { - Bool more_copy = FALSE; - - for (i = 0; i < nbox; i++) { - int dstX = pBox[i].x1 + tileWidth; - int dstY = pBox[i].y1 + tileHeight; - - if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) { - more_copy = TRUE; - break; - } - } - - if (more_copy == FALSE) - ret = TRUE; - - if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, - 1, 1, alu, - planemask)) { - for (i = 0; i < nbox; i++) { - int dstX = pBox[i].x1 + tileWidth; - int dstY = pBox[i].y1 + tileHeight; - int width = min(pBox[i].x2 - dstX, tileWidth); - int height = min(pBox[i].y2 - pBox[i].y1, tileHeight); - - while (dstX < pBox[i].x2) { - (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, - dstX, pBox[i].y1, width, - height); - dstX += width; - width = min(pBox[i].x2 - dstX, width * 2); - } - - width = pBox[i].x2 - pBox[i].x1; - height = min(pBox[i].y2 - dstY, tileHeight); - - while (dstY < pBox[i].y2) { - (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, - pBox[i].x1, dstY, width, - height); - dstY += height; - height = min(pBox[i].y2 - dstY, height * 2); - } - } - - (*pExaScr->info->DoneCopy) (pPixmap); - - ret = TRUE; - } - } - - exaMarkSync(pDrawable->pScreen); - - if (xoff || yoff) - RegionTranslate(pRegion, -xoff, -yoff); - } - - return ret; -} - -/** - * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. - * - * This is probably the only case we actually care about. The rest fall through - * to migration and fbGetImage, which hopefully will result in migration pushing - * the pixmap out of framebuffer. - */ -void -exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, - unsigned int format, unsigned long planeMask, char *d) -{ - ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPix); - int xoff, yoff; - Bool ok; - - if (pExaScr->fallback_counter || pExaScr->swappedOut) - goto fallback; - - /* If there's a system copy, we want to save the result there */ - if (pExaPixmap->pDamage) - goto fallback; - - pPix = exaGetOffscreenPixmap(pDrawable, &xoff, &yoff); - - if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL) - goto fallback; - - /* Only cover the ZPixmap, solid copy case. */ - if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) - goto fallback; - - /* Only try to handle the 8bpp and up cases, since we don't want to think - * about <8bpp. - */ - if (pDrawable->bitsPerPixel < 8) - goto fallback; - - ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff, - pDrawable->y + y + yoff, w, h, d, - PixmapBytePad(w, pDrawable->depth)); - if (ok) { - exaWaitSync(pDrawable->pScreen); - return; - } - - fallback: - ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d); -} diff --git a/exa/exa_classic.c b/exa/exa_classic.c deleted file mode 100644 index a6a60e50c..000000000 --- a/exa/exa_classic.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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 classic exa specific implementation. */ - -static _X_INLINE void * -ExaGetPixmapAddress(PixmapPtr p) -{ - ExaPixmapPriv(p); - - if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr) - return pExaPixmap->fb_ptr; - else - return pExaPixmap->sys_ptr; -} - -/** - * exaCreatePixmap() creates a new pixmap. - * - * If width and height are 0, this won't be a full-fledged pixmap and it will - * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because - * ModifyPixmapHeader() would break migration. These types of pixmaps are used - * for scratch pixmaps, or to represent the visible screen. - */ -PixmapPtr -exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth, - unsigned usage_hint) -{ - PixmapPtr pPixmap; - ExaPixmapPrivPtr pExaPixmap; - BoxRec box; - int bpp; - - ExaScreenPriv(pScreen); - - if (w > 32767 || h > 32767) - return NullPixmap; - - swap(pExaScr, pScreen, CreatePixmap); - pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint); - swap(pExaScr, pScreen, CreatePixmap); - - if (!pPixmap) - return NULL; - - pExaPixmap = ExaGetPixmapPriv(pPixmap); - pExaPixmap->driverPriv = NULL; - - bpp = pPixmap->drawable.bitsPerPixel; - - pExaPixmap->driverPriv = NULL; - /* Scratch pixmaps may have w/h equal to zero, and may not be - * migrated. - */ - if (!w || !h) - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; - else - pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; - - pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; - pExaPixmap->sys_pitch = pPixmap->devKind; - - pPixmap->devPrivate.ptr = NULL; - pExaPixmap->use_gpu_copy = FALSE; - - pExaPixmap->fb_ptr = NULL; - exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); - pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; - - if (pExaPixmap->fb_pitch > 131071) { - swap(pExaScr, pScreen, DestroyPixmap); - pScreen->DestroyPixmap(pPixmap); - swap(pExaScr, pScreen, DestroyPixmap); - return NULL; - } - - /* 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->area = NULL; - - /* We set the initial pixmap as completely valid for a simple reason. - * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which - * could form single pixel rects as part of a region. Setting the complete region - * as valid is a natural defragmentation of the region. - */ - box.x1 = 0; - box.y1 = 0; - box.x2 = w; - box.y2 = h; - RegionInit(&pExaPixmap->validSys, &box, 0); - RegionInit(&pExaPixmap->validFB, &box, 0); - - exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); - - /* During a fallback we must prepare access. */ - if (pExaScr->fallback_counter) - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); - - return pPixmap; -} - -Bool -exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, - int depth, int bitsPerPixel, int devKind, - void *pPixData) -{ - ScreenPtr pScreen; - ExaScreenPrivPtr pExaScr; - ExaPixmapPrivPtr pExaPixmap; - Bool ret; - - if (!pPixmap) - return FALSE; - - pScreen = pPixmap->drawable.pScreen; - pExaScr = ExaGetScreenPriv(pScreen); - pExaPixmap = ExaGetPixmapPriv(pPixmap); - - if (pExaPixmap) { - if (pPixData) - pExaPixmap->sys_ptr = pPixData; - - if (devKind > 0) - pExaPixmap->sys_pitch = devKind; - - /* Classic EXA: - * - Framebuffer. - * - Scratch pixmap with gpu memory. - */ - if (pExaScr->info->memoryBase && pPixData) { - if ((CARD8 *) pPixData >= pExaScr->info->memoryBase && - ((CARD8 *) pPixData - pExaScr->info->memoryBase) < - pExaScr->info->memorySize) { - pExaPixmap->fb_ptr = pPixData; - pExaPixmap->fb_pitch = devKind; - pExaPixmap->use_gpu_copy = TRUE; - } - } - - if (width > 0 && height > 0 && bitsPerPixel > 0) { - exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); - - exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); - } - - /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or - * gpu memory, so there's no need to track damage. - */ - if (pExaPixmap->pDamage) { - DamageDestroy(pExaPixmap->pDamage); - pExaPixmap->pDamage = NULL; - } - } - - swap(pExaScr, pScreen, ModifyPixmapHeader); - ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, - bitsPerPixel, devKind, pPixData); - swap(pExaScr, pScreen, ModifyPixmapHeader); - - /* Always NULL this, we don't want lingering pointers. */ - pPixmap->devPrivate.ptr = NULL; - - return ret; -} - -Bool -exaDestroyPixmap_classic(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - Bool ret; - - if (pPixmap->refcnt == 1) { - ExaPixmapPriv(pPixmap); - - exaDestroyPixmap(pPixmap); - - if (pExaPixmap->area) { - DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", - (void *) pPixmap->drawable.id, - ExaGetPixmapPriv(pPixmap)->area->offset, - pPixmap->drawable.width, pPixmap->drawable.height)); - /* Free the offscreen area */ - exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area); - pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; - pPixmap->devKind = pExaPixmap->sys_pitch; - } - RegionUninit(&pExaPixmap->validSys); - RegionUninit(&pExaPixmap->validFB); - } - - swap(pExaScr, pScreen, DestroyPixmap); - ret = pScreen->DestroyPixmap(pPixmap); - swap(pExaScr, pScreen, DestroyPixmap); - - return ret; -} - -Bool -exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - ExaPixmapPriv(pPixmap); - Bool ret; - - if (pExaScr->info->PixmapIsOffscreen) { - void *old_ptr = pPixmap->devPrivate.ptr; - - pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); - ret = pExaScr->info->PixmapIsOffscreen(pPixmap); - pPixmap->devPrivate.ptr = old_ptr; - } - else - ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr); - - return ret; -} diff --git a/exa/exa_driver.c b/exa/exa_driver.c deleted file mode 100644 index 8799a798e..000000000 --- a/exa/exa_driver.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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 specific implementation. */ - -static _X_INLINE void * -ExaGetPixmapAddress(PixmapPtr p) -{ - ExaPixmapPriv(p); - - return pExaPixmap->sys_ptr; -} - -/** - * exaCreatePixmap() creates a new pixmap. - * - * Pixmaps are always marked as pinned, because exa has no control over them. - */ -PixmapPtr -exaCreatePixmap_driver(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; - - /* Set this before driver hooks, to allow for driver pixmaps without gpu - * memory to back it. These pixmaps have a valid pointer at all times. - */ - pPixmap->devPrivate.ptr = NULL; - - if (pExaScr->info->CreatePixmap2) { - int new_pitch = 0; - - pExaPixmap->driverPriv = - pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, - &new_pitch); - paddedWidth = pExaPixmap->fb_pitch = new_pitch; - } - else { - paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); - if (paddedWidth / 4 > 32767 || h > 32767) - return NullPixmap; - - exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); - - if (paddedWidth < pExaPixmap->fb_pitch) - paddedWidth = pExaPixmap->fb_pitch; - datasize = h * paddedWidth; - pExaPixmap->driverPriv = - pExaScr->info->CreatePixmap(pScreen, datasize, 0); - } - - if (!pExaPixmap->driverPriv) { - swap(pExaScr, pScreen, DestroyPixmap); - pScreen->DestroyPixmap(pPixmap); - swap(pExaScr, pScreen, DestroyPixmap); - return NULL; - } - - /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */ - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; - pExaPixmap->fb_ptr = NULL; - pExaPixmap->pDamage = NULL; - pExaPixmap->sys_ptr = NULL; - - (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL); - - pExaPixmap->area = NULL; - - exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); - - pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); - - /* During a fallback we must prepare access. */ - if (pExaScr->fallback_counter) - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); - - return pPixmap; -} - -Bool -exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, - int depth, int bitsPerPixel, int devKind, - void *pPixData) -{ - ScreenPtr pScreen; - ExaScreenPrivPtr pExaScr; - ExaPixmapPrivPtr pExaPixmap; - Bool ret; - - if (!pPixmap) - return FALSE; - - pScreen = pPixmap->drawable.pScreen; - pExaScr = ExaGetScreenPriv(pScreen); - pExaPixmap = ExaGetPixmapPriv(pPixmap); - - if (pExaPixmap) { - if (pPixData) - 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); - } - } - - if (pExaScr->info->ModifyPixmapHeader) { - 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 - * !has_gpu_copy 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_driver(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - Bool ret; - - if (pPixmap->refcnt == 1) { - ExaPixmapPriv(pPixmap); - - exaDestroyPixmap(pPixmap); - - if (pExaPixmap->driverPriv) - pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); - pExaPixmap->driverPriv = NULL; - } - - swap(pExaScr, pScreen, DestroyPixmap); - ret = pScreen->DestroyPixmap(pPixmap); - swap(pExaScr, pScreen, DestroyPixmap); - - return ret; -} - -Bool -exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - void *saved_ptr; - Bool ret; - - saved_ptr = pPixmap->devPrivate.ptr; - pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); - ret = pExaScr->info->PixmapIsOffscreen(pPixmap); - pPixmap->devPrivate.ptr = saved_ptr; - - return ret; -} diff --git a/exa/exa_glyphs.c b/exa/exa_glyphs.c deleted file mode 100644 index 192a643cc..000000000 --- a/exa/exa_glyphs.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * Copyright © 2008 Red Hat, Inc. - * Partly based on code Copyright © 2000 SuSE, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of SuSE not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. SuSE makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Owen Taylor <otaylor@fishsoup.net> - * Based on code by: Keith Packard - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <stdlib.h> - -#include "exa_priv.h" - -#include "mipict.h" - -#if DEBUG_GLYPH_CACHE -#define DBG_GLYPH_CACHE(a) ErrorF a -#else -#define DBG_GLYPH_CACHE(a) -#endif - -/* Width of the pixmaps we use for the caches; this should be less than - * max texture size of the driver; this may need to actually come from - * the driver. - */ -#define CACHE_PICTURE_WIDTH 1024 - -/* Maximum number of glyphs we buffer on the stack before flushing - * rendering to the mask or destination surface. - */ -#define GLYPH_BUFFER_SIZE 256 - -typedef struct { - PicturePtr mask; - ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE]; - int count; -} ExaGlyphBuffer, *ExaGlyphBufferPtr; - -typedef enum { - ExaGlyphSuccess, /* Glyph added to render buffer */ - ExaGlyphFail, /* out of memory, etc */ - ExaGlyphNeedFlush, /* would evict a glyph already in the buffer */ -} ExaGlyphCacheResult; - -void -exaGlyphsInit(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - int i = 0; - - memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches)); - - pExaScr->glyphCaches[i].format = PICT_a8; - pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = - 16; - i++; - pExaScr->glyphCaches[i].format = PICT_a8; - pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = - 32; - i++; - pExaScr->glyphCaches[i].format = PICT_a8r8g8b8; - pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = - 16; - i++; - pExaScr->glyphCaches[i].format = PICT_a8r8g8b8; - pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight = - 32; - i++; - - assert(i == EXA_NUM_GLYPH_CACHES); - - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { - pExaScr->glyphCaches[i].columns = - CACHE_PICTURE_WIDTH / pExaScr->glyphCaches[i].glyphWidth; - pExaScr->glyphCaches[i].size = 256; - pExaScr->glyphCaches[i].hashSize = 557; - } -} - -static void -exaUnrealizeGlyphCaches(ScreenPtr pScreen, unsigned int format) -{ - ExaScreenPriv(pScreen); - int i; - - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { - ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; - - if (cache->format != format) - continue; - - if (cache->picture) { - FreePicture((void *) cache->picture, (XID) 0); - cache->picture = NULL; - } - - free(cache->hashEntries); - cache->hashEntries = NULL; - - free(cache->glyphs); - cache->glyphs = NULL; - cache->glyphCount = 0; - } -} - -#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) - -/* All caches for a single format share a single pixmap for glyph storage, - * allowing mixing glyphs of different sizes without paying a penalty - * for switching between mask pixmaps. (Note that for a size of font - * right at the border between two sizes, we might be switching for almost - * every glyph.) - * - * This function allocates the storage pixmap, and then fills in the - * rest of the allocated structures for all caches with the given format. - */ -static Bool -exaRealizeGlyphCaches(ScreenPtr pScreen, unsigned int format) -{ - ExaScreenPriv(pScreen); - - int depth = PIXMAN_FORMAT_DEPTH(format); - PictFormatPtr pPictFormat; - PixmapPtr pPixmap; - PicturePtr pPicture; - CARD32 component_alpha; - int height; - int i; - int error; - - pPictFormat = PictureMatchFormat(pScreen, depth, format); - if (!pPictFormat) - return FALSE; - - /* Compute the total vertical size needed for the format */ - - height = 0; - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { - ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; - int rows; - - if (cache->format != format) - continue; - - cache->yOffset = height; - - rows = (cache->size + cache->columns - 1) / cache->columns; - height += rows * cache->glyphHeight; - } - - /* Now allocate the pixmap and picture */ - pPixmap = (*pScreen->CreatePixmap) (pScreen, - CACHE_PICTURE_WIDTH, height, depth, 0); - if (!pPixmap) - return FALSE; - - component_alpha = NeedsComponent(pPictFormat->format); - pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, - CPComponentAlpha, &component_alpha, serverClient, - &error); - - (*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */ - - if (!pPicture) - return FALSE; - - /* And store the picture in all the caches for the format */ - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { - ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; - int j; - - if (cache->format != format) - continue; - - cache->picture = pPicture; - cache->picture->refcnt++; - cache->hashEntries = xallocarray(cache->hashSize, sizeof(int)); - cache->glyphs = xallocarray(cache->size, sizeof(ExaCachedGlyphRec)); - cache->glyphCount = 0; - - if (!cache->hashEntries || !cache->glyphs) - goto bail; - - for (j = 0; j < cache->hashSize; j++) - cache->hashEntries[j] = -1; - - cache->evictionPosition = rand() % cache->size; - } - - /* Each cache references the picture individually */ - FreePicture((void *) pPicture, (XID) 0); - return TRUE; - - bail: - exaUnrealizeGlyphCaches(pScreen, format); - return FALSE; -} - -void -exaGlyphsFini(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - int i; - - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { - ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; - - if (cache->picture) - exaUnrealizeGlyphCaches(pScreen, cache->format); - } -} - -static int -exaGlyphCacheHashLookup(ExaGlyphCachePtr cache, GlyphPtr pGlyph) -{ - int slot; - - slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hashEntries[slot]; - - if (entryPos == -1) - return -1; - - if (memcmp - (pGlyph->sha1, cache->glyphs[entryPos].sha1, - sizeof(pGlyph->sha1)) == 0) { - return entryPos; - } - - slot--; - if (slot < 0) - slot = cache->hashSize - 1; - } -} - -static void -exaGlyphCacheHashInsert(ExaGlyphCachePtr cache, GlyphPtr pGlyph, int pos) -{ - int slot; - - memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1)); - - slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize; - - while (TRUE) { /* hash table can never be full */ - if (cache->hashEntries[slot] == -1) { - cache->hashEntries[slot] = pos; - return; - } - - slot--; - if (slot < 0) - slot = cache->hashSize - 1; - } -} - -static void -exaGlyphCacheHashRemove(ExaGlyphCachePtr cache, int pos) -{ - int slot; - int emptiedSlot = -1; - - slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize; - - while (TRUE) { /* hash table can never be full */ - int entryPos = cache->hashEntries[slot]; - - if (entryPos == -1) - return; - - if (entryPos == pos) { - cache->hashEntries[slot] = -1; - emptiedSlot = slot; - } - else if (emptiedSlot != -1) { - /* See if we can move this entry into the emptied slot, we can't - * do that if if entry would have hashed between the current position - * and the emptied slot. (taking wrapping into account). Bad positions - * are: - * - * | XXXXXXXXXX | - * i j - * - * |XXX XXXX| - * j i - * - * i - slot, j - emptiedSlot - * - * (Knuth 6.4R) - */ - - int entrySlot = - (*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize; - - if (!((entrySlot >= slot && entrySlot < emptiedSlot) || - (emptiedSlot < slot && - (entrySlot < emptiedSlot || entrySlot >= slot)))) { - cache->hashEntries[emptiedSlot] = entryPos; - cache->hashEntries[slot] = -1; - emptiedSlot = slot; - } - } - - slot--; - if (slot < 0) - slot = cache->hashSize - 1; - } -} - -#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth) -#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight) - -/* The most efficient thing to way to upload the glyph to the screen - * is to use the UploadToScreen() driver hook; this allows us to - * pipeline glyph uploads and to avoid creating gpu backed pixmaps for - * glyphs that we'll never use again. - * - * If we can't do it with UploadToScreen (because the glyph has a gpu copy, - * etc), we fall back to CompositePicture. - * - * We need to damage the cache pixmap manually in either case because the damage - * layer unwrapped the picture screen before calling exaGlyphs. - */ -static void -exaGlyphCacheUploadGlyph(ScreenPtr pScreen, - ExaGlyphCachePtr cache, int x, int y, GlyphPtr pGlyph) -{ - ExaScreenPriv(pScreen); - PicturePtr pGlyphPicture = GetGlyphPicture(pGlyph, pScreen); - PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable; - - ExaPixmapPriv(pGlyphPixmap); - PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable; - - if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut || - pExaPixmap->accel_blocked) - goto composite; - - /* If the glyph pixmap is already uploaded, no point in doing - * things this way */ - if (exaPixmapHasGpuCopy(pGlyphPixmap)) - goto composite; - - /* UploadToScreen only works if bpp match */ - if (pGlyphPixmap->drawable.bitsPerPixel != - pCachePixmap->drawable.bitsPerPixel) - goto composite; - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[1]; - - /* cache pixmap must have a gpu copy. */ - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pCachePixmap; - pixmaps[0].pReg = NULL; - exaDoMigration(pixmaps, 1, TRUE); - } - - if (!exaPixmapHasGpuCopy(pCachePixmap)) - goto composite; - - /* x,y are in pixmap coordinates, no need for cache{X,Y}off */ - if (pExaScr->info->UploadToScreen(pCachePixmap, - x, - y, - pGlyph->info.width, - pGlyph->info.height, - (char *) pExaPixmap->sys_ptr, - pExaPixmap->sys_pitch)) - goto damage; - - composite: - CompositePicture(PictOpSrc, - pGlyphPicture, - None, - cache->picture, - 0, 0, 0, 0, x, y, pGlyph->info.width, pGlyph->info.height); - - damage: - /* The cache pixmap isn't a window, so no need to offset coordinates. */ - exaPixmapDirty(pCachePixmap, - x, y, x + cache->glyphWidth, y + cache->glyphHeight); -} - -static ExaGlyphCacheResult -exaGlyphCacheBufferGlyph(ScreenPtr pScreen, - ExaGlyphCachePtr cache, - ExaGlyphBufferPtr buffer, - GlyphPtr pGlyph, - PicturePtr pSrc, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst) -{ - ExaCompositeRectPtr rect; - int pos; - int x, y; - - if (buffer->mask && buffer->mask != cache->picture) - return ExaGlyphNeedFlush; - - if (!cache->picture) { - if (!exaRealizeGlyphCaches(pScreen, cache->format)) - return ExaGlyphFail; - } - - DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n", - cache->glyphWidth, cache->glyphHeight, - cache->format == PICT_a8 ? "A" : "ARGB", - (long) *(CARD32 *) pGlyph->sha1)); - - pos = exaGlyphCacheHashLookup(cache, pGlyph); - if (pos != -1) { - DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos)); - x = CACHE_X(pos); - y = CACHE_Y(pos); - } - else { - if (cache->glyphCount < cache->size) { - /* Space remaining; we fill from the start */ - pos = cache->glyphCount; - x = CACHE_X(pos); - y = CACHE_Y(pos); - cache->glyphCount++; - DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos)); - - exaGlyphCacheHashInsert(cache, pGlyph, pos); - - } - else { - /* Need to evict an entry. We have to see if any glyphs - * already in the output buffer were at this position in - * the cache - */ - pos = cache->evictionPosition; - x = CACHE_X(pos); - y = CACHE_Y(pos); - DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos)); - if (buffer->count) { - int i; - - for (i = 0; i < buffer->count; i++) { - if (pSrc ? - (buffer->rects[i].xMask == x && - buffer->rects[i].yMask == - y) : (buffer->rects[i].xSrc == x && - buffer->rects[i].ySrc == y)) { - DBG_GLYPH_CACHE((" must flush buffer\n")); - return ExaGlyphNeedFlush; - } - } - } - - /* OK, we're all set, swap in the new glyph */ - exaGlyphCacheHashRemove(cache, pos); - exaGlyphCacheHashInsert(cache, pGlyph, pos); - - /* And pick a new eviction position */ - cache->evictionPosition = rand() % cache->size; - } - - exaGlyphCacheUploadGlyph(pScreen, cache, x, y, pGlyph); - } - - buffer->mask = cache->picture; - - rect = &buffer->rects[buffer->count]; - - if (pSrc) { - rect->xSrc = xSrc; - rect->ySrc = ySrc; - rect->xMask = x; - rect->yMask = y; - } - else { - rect->xSrc = x; - rect->ySrc = y; - rect->xMask = 0; - rect->yMask = 0; - } - - rect->pDst = pDst; - rect->xDst = xDst; - rect->yDst = yDst; - rect->width = pGlyph->info.width; - rect->height = pGlyph->info.height; - - buffer->count++; - - return ExaGlyphSuccess; -} - -#undef CACHE_X -#undef CACHE_Y - -static ExaGlyphCacheResult -exaBufferGlyph(ScreenPtr pScreen, - ExaGlyphBufferPtr buffer, - GlyphPtr pGlyph, - PicturePtr pSrc, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst) -{ - ExaScreenPriv(pScreen); - unsigned int format = (GetGlyphPicture(pGlyph, pScreen))->format; - int width = pGlyph->info.width; - int height = pGlyph->info.height; - ExaCompositeRectPtr rect; - PicturePtr mask; - int i; - - if (buffer->count == GLYPH_BUFFER_SIZE) - return ExaGlyphNeedFlush; - - if (PICT_FORMAT_BPP(format) == 1) - format = PICT_a8; - - for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) { - ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i]; - - if (format == cache->format && - width <= cache->glyphWidth && height <= cache->glyphHeight) { - ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen, - &pExaScr-> - glyphCaches - [i], - buffer, - pGlyph, - pSrc, - pDst, - xSrc, ySrc, - xMask, yMask, - xDst, yDst); - - switch (result) { - case ExaGlyphFail: - break; - case ExaGlyphSuccess: - case ExaGlyphNeedFlush: - return result; - } - } - } - - /* Couldn't find the glyph in the cache, use the glyph picture directly */ - - mask = GetGlyphPicture(pGlyph, pScreen); - if (buffer->mask && buffer->mask != mask) - return ExaGlyphNeedFlush; - - buffer->mask = mask; - - rect = &buffer->rects[buffer->count]; - rect->xSrc = xSrc; - rect->ySrc = ySrc; - rect->xMask = xMask; - rect->yMask = yMask; - rect->xDst = xDst; - rect->yDst = yDst; - rect->width = width; - rect->height = height; - - buffer->count++; - - return ExaGlyphSuccess; -} - -static void -exaGlyphsToMask(PicturePtr pMask, ExaGlyphBufferPtr buffer) -{ - exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask, - buffer->count, buffer->rects); - - buffer->count = 0; - buffer->mask = NULL; -} - -static void -exaGlyphsToDst(CARD8 op, PicturePtr pSrc, PicturePtr pDst, ExaGlyphBufferPtr buffer) -{ - exaCompositeRects(op, pSrc, buffer->mask, pDst, buffer->count, - buffer->rects); - - buffer->count = 0; - buffer->mask = NULL; -} - -/* Cut and paste from render/glyph.c - probably should export it instead */ -static void -GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents) -{ - int x1, x2, y1, y2; - int n; - GlyphPtr glyph; - int x, y; - - x = 0; - y = 0; - extents->x1 = MAXSHORT; - extents->x2 = MINSHORT; - extents->y1 = MAXSHORT; - extents->y2 = MINSHORT; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - list++; - while (n--) { - glyph = *glyphs++; - x1 = x - glyph->info.x; - if (x1 < MINSHORT) - x1 = MINSHORT; - y1 = y - glyph->info.y; - if (y1 < MINSHORT) - y1 = MINSHORT; - x2 = x1 + glyph->info.width; - if (x2 > MAXSHORT) - x2 = MAXSHORT; - y2 = y1 + glyph->info.height; - if (y2 > MAXSHORT) - y2 = MAXSHORT; - if (x1 < extents->x1) - extents->x1 = x1; - if (x2 > extents->x2) - extents->x2 = x2; - if (y1 < extents->y1) - extents->y1 = y1; - if (y2 > extents->y2) - extents->y2 = y2; - x += glyph->info.xOff; - y += glyph->info.yOff; - } - } -} - -void -exaGlyphs(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) -{ - PixmapPtr pMaskPixmap = 0; - PicturePtr pMask = NULL; - ScreenPtr pScreen = pDst->pDrawable->pScreen; - int width = 0, height = 0; - int x, y; - int first_xOff = list->xOff, first_yOff = list->yOff; - int n; - GlyphPtr glyph; - int error; - BoxRec extents = { 0, 0, 0, 0 }; - CARD32 component_alpha; - ExaGlyphBuffer buffer; - - if (maskFormat) { - ExaScreenPriv(pScreen); - GCPtr pGC; - xRectangle rect; - - GlyphExtents(nlist, list, glyphs, &extents); - - if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) - return; - width = extents.x2 - extents.x1; - height = extents.y2 - extents.y1; - - if (maskFormat->depth == 1) { - PictFormatPtr a8Format = PictureMatchFormat(pScreen, 8, PICT_a8); - - if (a8Format) - maskFormat = a8Format; - } - - pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - maskFormat->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pMaskPixmap) - return; - component_alpha = NeedsComponent(maskFormat->format); - pMask = CreatePicture(0, &pMaskPixmap->drawable, - maskFormat, CPComponentAlpha, &component_alpha, - serverClient, &error); - if (!pMask || - (!component_alpha && pExaScr->info->CheckComposite && - !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask))) - { - PictFormatPtr argbFormat; - - (*pScreen->DestroyPixmap) (pMaskPixmap); - - if (!pMask) - return; - - /* The driver can't seem to composite to a8, let's try argb (but - * without component-alpha) */ - FreePicture((void *) pMask, (XID) 0); - - argbFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8); - - if (argbFormat) - maskFormat = argbFormat; - - pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - maskFormat->depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pMaskPixmap) - return; - - pMask = CreatePicture(0, &pMaskPixmap->drawable, maskFormat, 0, 0, - serverClient, &error); - if (!pMask) { - (*pScreen->DestroyPixmap) (pMaskPixmap); - return; - } - } - pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen); - ValidateGC(&pMaskPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); - FreeScratchGC(pGC); - x = -extents.x1; - y = -extents.y1; - } - else { - x = 0; - y = 0; - } - buffer.count = 0; - buffer.mask = NULL; - while (nlist--) { - x += list->xOff; - y += list->yOff; - n = list->len; - while (n--) { - glyph = *glyphs++; - - if (glyph->info.width > 0 && glyph->info.height > 0) { - /* pGlyph->info.{x,y} compensate for empty space in the glyph. */ - if (maskFormat) { - if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, - 0, 0, 0, 0, x - glyph->info.x, - y - glyph->info.y) == - ExaGlyphNeedFlush) { - exaGlyphsToMask(pMask, &buffer); - exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask, - 0, 0, 0, 0, x - glyph->info.x, - y - glyph->info.y); - } - } - else { - if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, - xSrc + (x - glyph->info.x) - first_xOff, - ySrc + (y - glyph->info.y) - first_yOff, - 0, 0, x - glyph->info.x, - y - glyph->info.y) - == ExaGlyphNeedFlush) { - exaGlyphsToDst(op, pSrc, pDst, &buffer); - exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst, - xSrc + (x - glyph->info.x) - first_xOff, - ySrc + (y - glyph->info.y) - first_yOff, - 0, 0, x - glyph->info.x, - y - glyph->info.y); - } - } - } - - x += glyph->info.xOff; - y += glyph->info.yOff; - } - list++; - } - - if (buffer.count) { - if (maskFormat) - exaGlyphsToMask(pMask, &buffer); - else - exaGlyphsToDst(op, pSrc, pDst, &buffer); - } - - if (maskFormat) { - x = extents.x1; - y = extents.y1; - CompositePicture(op, - pSrc, - pMask, - pDst, - xSrc + x - first_xOff, - ySrc + y - first_yOff, 0, 0, x, y, width, height); - FreePicture((void *) pMask, (XID) 0); - (*pScreen->DestroyPixmap) (pMaskPixmap); - } -} diff --git a/exa/exa_migration_classic.c b/exa/exa_migration_classic.c deleted file mode 100644 index f712e1914..000000000 --- a/exa/exa_migration_classic.c +++ /dev/null @@ -1,761 +0,0 @@ -/* - * Copyright © 2006 Intel Corporation - * - * 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. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Michel Dänzer <michel@tungstengraphics.com> - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <string.h> - -#include "exa_priv.h" -#include "exa.h" - -#if DEBUG_MIGRATE -#define DBG_MIGRATE(a) ErrorF a -#else -#define DBG_MIGRATE(a) -#endif - -/** - * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys - * and exaCopyDirtyToFb both needed to do this loop. - */ -static void -exaMemcpyBox(PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch, - CARD8 *dst, int dst_pitch) -{ - int i, cpp = pPixmap->drawable.bitsPerPixel / 8; - int bytes = (pbox->x2 - pbox->x1) * cpp; - - src += pbox->y1 * src_pitch + pbox->x1 * cpp; - dst += pbox->y1 * dst_pitch + pbox->x1 * cpp; - - for (i = pbox->y2 - pbox->y1; i; i--) { - memcpy(dst, src, bytes); - src += 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 - * dirtiness. - */ -static Bool -exaPixmapIsDirty(PixmapPtr pPix) -{ - ExaPixmapPriv(pPix); - - if (pExaPixmap == NULL) - EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE); - - if (!pExaPixmap->pDamage) - return FALSE; - - return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) || - !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB); -} - -/** - * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score - * to be considered "should be in framebuffer". That's just anything that has - * had more acceleration than fallbacks, or has no score yet. - * - * Only valid if using a migration scheme that tracks score. - */ -static Bool -exaPixmapShouldBeInFB(PixmapPtr pPix) -{ - ExaPixmapPriv(pPix); - - if (exaPixmapIsPinned(pPix)) - return TRUE; - - return pExaPixmap->score >= 0; -} - -/** - * If the pixmap is currently dirty, this copies at least the dirty area from - * FB to system or vice versa. Both areas must be allocated. - */ -static void -exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc, - Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h, - char *sys, int sys_pitch), int fallback_index, - void (*sync) (ScreenPtr pScreen)) -{ - PixmapPtr pPixmap = migrate->pPix; - - ExaPixmapPriv(pPixmap); - RegionPtr damage = DamageRegion(pExaPixmap->pDamage); - RegionRec CopyReg; - Bool save_use_gpu_copy; - int save_pitch; - BoxPtr pBox; - int nbox; - Bool access_prepared = FALSE; - Bool need_sync = FALSE; - - /* Damaged bits are valid in current copy but invalid in other one */ - if (pExaPixmap->use_gpu_copy) { - RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage); - RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage); - } - else { - RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage); - RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage); - } - - RegionEmpty(damage); - - /* Copy bits valid in source but not in destination */ - RegionNull(&CopyReg); - RegionSubtract(&CopyReg, pValidSrc, pValidDst); - - if (migrate->as_dst) { - ExaScreenPriv(pPixmap->drawable.pScreen); - - /* XXX: The pending damage region will be marked as damaged after the - * operation, so it should serve as an upper bound for the region that - * needs to be synchronized for the operation. Unfortunately, this - * causes corruption in some cases, e.g. when starting compiz. See - * https://bugs.freedesktop.org/show_bug.cgi?id=12916 . - */ - if (pExaScr->optimize_migration) { - RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); - -#if DEBUG_MIGRATE - if (RegionNil(pending_damage)) { - static Bool firsttime = TRUE; - - if (firsttime) { - ErrorF("%s: Pending damage region empty!\n", __func__); - firsttime = FALSE; - } - } -#endif - - /* Try to prevent destination valid region from growing too many - * rects by filling it up to the extents of the union of the - * destination valid region and the pending damage region. - */ - if (RegionNumRects(pValidDst) > 10) { - BoxRec box; - BoxPtr pValidExt, pDamageExt; - RegionRec closure; - - pValidExt = RegionExtents(pValidDst); - pDamageExt = RegionExtents(pending_damage); - - box.x1 = min(pValidExt->x1, pDamageExt->x1); - box.y1 = min(pValidExt->y1, pDamageExt->y1); - box.x2 = max(pValidExt->x2, pDamageExt->x2); - box.y2 = max(pValidExt->y2, pDamageExt->y2); - - RegionInit(&closure, &box, 0); - RegionIntersect(&CopyReg, &CopyReg, &closure); - } - else - RegionIntersect(&CopyReg, &CopyReg, pending_damage); - } - - /* The caller may provide a region to be subtracted from the calculated - * dirty region. This is to avoid migration of bits that don't - * contribute to the result of the operation. - */ - if (migrate->pReg) - RegionSubtract(&CopyReg, &CopyReg, migrate->pReg); - } - else { - /* The caller may restrict the region to be migrated for source pixmaps - * to what's relevant for the operation. - */ - if (migrate->pReg) - RegionIntersect(&CopyReg, &CopyReg, migrate->pReg); - } - - pBox = RegionRects(&CopyReg); - nbox = RegionNumRects(&CopyReg); - - save_use_gpu_copy = pExaPixmap->use_gpu_copy; - save_pitch = pPixmap->devKind; - pExaPixmap->use_gpu_copy = TRUE; - pPixmap->devKind = pExaPixmap->fb_pitch; - - while (nbox--) { - pBox->x1 = max(pBox->x1, 0); - pBox->y1 = max(pBox->y1, 0); - pBox->x2 = min(pBox->x2, pPixmap->drawable.width); - pBox->y2 = min(pBox->y2, pPixmap->drawable.height); - - if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) - continue; - - if (!transfer || !transfer(pPixmap, - pBox->x1, pBox->y1, - pBox->x2 - pBox->x1, - pBox->y2 - pBox->y1, - (char *) (pExaPixmap->sys_ptr - + pBox->y1 * pExaPixmap->sys_pitch - + - pBox->x1 * - pPixmap->drawable.bitsPerPixel / - 8), pExaPixmap->sys_pitch)) { - if (!access_prepared) { - ExaDoPrepareAccess(pPixmap, fallback_index); - access_prepared = TRUE; - } - if (fallback_index == EXA_PREPARE_DEST) { - exaMemcpyBox(pPixmap, pBox, - pExaPixmap->sys_ptr, pExaPixmap->sys_pitch, - pPixmap->devPrivate.ptr, pPixmap->devKind); - } - else { - exaMemcpyBox(pPixmap, pBox, - pPixmap->devPrivate.ptr, pPixmap->devKind, - pExaPixmap->sys_ptr, pExaPixmap->sys_pitch); - } - } - else - need_sync = TRUE; - - pBox++; - } - - pExaPixmap->use_gpu_copy = save_use_gpu_copy; - pPixmap->devKind = save_pitch; - - /* Try to prevent source valid region from growing too many rects by - * removing parts of it which are also in the destination valid region. - * Removing anything beyond that would lead to data loss. - */ - if (RegionNumRects(pValidSrc) > 20) - RegionSubtract(pValidSrc, pValidSrc, pValidDst); - - /* The copied bits are now valid in destination */ - RegionUnion(pValidDst, pValidDst, &CopyReg); - - RegionUninit(&CopyReg); - - if (access_prepared) - exaFinishAccess(&pPixmap->drawable, fallback_index); - else if (need_sync && sync) - sync(pPixmap->drawable.pScreen); -} - -/** - * If the pixmap is currently dirty, this copies at least the dirty area from - * the framebuffer memory copy to the system memory copy. Both areas must be - * allocated. - */ -void -exaCopyDirtyToSys(ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - - ExaScreenPriv(pPixmap->drawable.pScreen); - ExaPixmapPriv(pPixmap); - - exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB, - pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC, - exaWaitSync); -} - -/** - * If the pixmap is currently dirty, this copies at least the dirty area from - * the system memory copy to the framebuffer memory copy. Both areas must be - * allocated. - */ -void -exaCopyDirtyToFb(ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - - ExaScreenPriv(pPixmap->drawable.pScreen); - ExaPixmapPriv(pPixmap); - - exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys, - pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL); -} - -/** - * Allocates a framebuffer copy of the pixmap if necessary, and then copies - * any necessary pixmap data into the framebuffer copy and points the pixmap at - * it. - * - * Note that when first allocated, a pixmap will have FALSE dirty flag. - * This is intentional because pixmap data starts out undefined. So if we move - * it in due to the first operation against it being accelerated, it will have - * undefined framebuffer contents that we didn't have to upload. If we do - * moveouts (and moveins) after the first movein, then we will only have to copy - * back and forth if the pixmap was written to after the last synchronization of - * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away) - * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move - * all the data, since it's almost surely all valid now. - */ -static void -exaDoMoveInPixmap(ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - ExaPixmapPriv(pPixmap); - - /* If we're VT-switched away, no touching card memory allowed. */ - if (pExaScr->swappedOut) - return; - - /* If we're not allowed to move, then fail. */ - if (exaPixmapIsPinned(pPixmap)) - return; - - /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of - * fragility in EXA, and <8bpp is probably not used enough any more to care - * (at least, not in acceleratd paths). - */ - if (pPixmap->drawable.bitsPerPixel < 8) - return; - - if (pExaPixmap->accel_blocked) - return; - - if (pExaPixmap->area == NULL) { - pExaPixmap->area = - exaOffscreenAlloc(pScreen, pExaPixmap->fb_size, - pExaScr->info->pixmapOffsetAlign, FALSE, - exaPixmapSave, (void *) pPixmap); - if (pExaPixmap->area == NULL) - return; - - pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase + - pExaPixmap->area->offset; - } - - exaCopyDirtyToFb(migrate); - - if (exaPixmapHasGpuCopy(pPixmap)) - return; - - DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap, - (ExaGetPixmapPriv(pPixmap)->area ? - ExaGetPixmapPriv(pPixmap)->area->offset : 0), - pPixmap->drawable.width, - pPixmap->drawable.height, - exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); - - pExaPixmap->use_gpu_copy = TRUE; - - pPixmap->devKind = pExaPixmap->fb_pitch; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; -} - -void -exaMoveInPixmap_classic(PixmapPtr pPixmap) -{ - static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE, - .pReg = NULL - }; - - migrate.pPix = pPixmap; - exaDoMoveInPixmap(&migrate); -} - -/** - * Switches the current active location of the pixmap to system memory, copying - * updated data out if necessary. - */ -static void -exaDoMoveOutPixmap(ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - - ExaPixmapPriv(pPixmap); - - if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap)) - return; - - exaCopyDirtyToSys(migrate); - - if (exaPixmapHasGpuCopy(pPixmap)) { - - DBG_MIGRATE(("<- %p (%p) (%dx%d) (%c)\n", pPixmap, - (void *) (ExaGetPixmapPriv(pPixmap)->area ? - ExaGetPixmapPriv(pPixmap)->area->offset : 0), - pPixmap->drawable.width, - pPixmap->drawable.height, - exaPixmapIsDirty(pPixmap) ? 'd' : 'c')); - - pExaPixmap->use_gpu_copy = FALSE; - - pPixmap->devKind = pExaPixmap->sys_pitch; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - } -} - -void -exaMoveOutPixmap_classic(PixmapPtr pPixmap) -{ - static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE, - .pReg = NULL - }; - - migrate.pPix = pPixmap; - exaDoMoveOutPixmap(&migrate); -} - -/** - * Copies out important pixmap data and removes references to framebuffer area. - * Called when the memory manager decides it's time to kick the pixmap out of - * framebuffer entirely. - */ -void -exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area) -{ - PixmapPtr pPixmap = area->privData; - - ExaPixmapPriv(pPixmap); - - exaMoveOutPixmap(pPixmap); - - pExaPixmap->fb_ptr = NULL; - pExaPixmap->area = NULL; - - /* Mark all FB bits as invalid, so all valid system bits get copied to FB - * next time */ - RegionEmpty(&pExaPixmap->validFB); -} - -/** - * For the "greedy" migration scheme, pushes the pixmap toward being located in - * framebuffer memory. - */ -static void -exaMigrateTowardFb(ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - - ExaPixmapPriv(pPixmap); - - if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) { - DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n", - (void *) pPixmap)); - return; - } - - DBG_MIGRATE(("UseScreen %p score %d\n", - (void *) pPixmap, pExaPixmap->score)); - - if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) { - exaDoMoveInPixmap(migrate); - pExaPixmap->score = 0; - } - - if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX) - pExaPixmap->score++; - - if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN && - !exaPixmapHasGpuCopy(pPixmap)) { - exaDoMoveInPixmap(migrate); - } - - if (exaPixmapHasGpuCopy(pPixmap)) { - exaCopyDirtyToFb(migrate); - ExaOffscreenMarkUsed(pPixmap); - } - else - exaCopyDirtyToSys(migrate); -} - -/** - * For the "greedy" migration scheme, pushes the pixmap toward being located in - * system memory. - */ -static void -exaMigrateTowardSys(ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - - ExaPixmapPriv(pPixmap); - - DBG_MIGRATE(("UseMem: %p score %d\n", (void *) pPixmap, - pExaPixmap->score)); - - if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) - return; - - if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) - pExaPixmap->score = 0; - - if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN) - pExaPixmap->score--; - - if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area) - exaDoMoveOutPixmap(migrate); - - if (exaPixmapHasGpuCopy(pPixmap)) { - exaCopyDirtyToFb(migrate); - ExaOffscreenMarkUsed(pPixmap); - } - else - exaCopyDirtyToSys(migrate); -} - -/** - * If the pixmap has both a framebuffer and system memory copy, this function - * asserts that both of them are the same. - */ -static Bool -exaAssertNotDirty(PixmapPtr pPixmap) -{ - ExaPixmapPriv(pPixmap); - CARD8 *dst, *src; - RegionRec ValidReg; - int dst_pitch, src_pitch, cpp, y, nbox, save_pitch; - BoxPtr pBox; - Bool ret = TRUE, save_use_gpu_copy; - - if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL) - return ret; - - RegionNull(&ValidReg); - RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys); - nbox = RegionNumRects(&ValidReg); - - if (!nbox) - goto out; - - pBox = RegionRects(&ValidReg); - - dst_pitch = pExaPixmap->sys_pitch; - src_pitch = pExaPixmap->fb_pitch; - cpp = pPixmap->drawable.bitsPerPixel / 8; - - save_use_gpu_copy = pExaPixmap->use_gpu_copy; - save_pitch = pPixmap->devKind; - pExaPixmap->use_gpu_copy = TRUE; - pPixmap->devKind = pExaPixmap->fb_pitch; - - if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC)) - goto skip; - - while (nbox--) { - int rowbytes; - - pBox->x1 = max(pBox->x1, 0); - pBox->y1 = max(pBox->y1, 0); - pBox->x2 = min(pBox->x2, pPixmap->drawable.width); - pBox->y2 = min(pBox->y2, pPixmap->drawable.height); - - if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2) - continue; - - rowbytes = (pBox->x2 - pBox->x1) * cpp; - src = - (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch + - pBox->x1 * cpp; - dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp; - - for (y = pBox->y1; y < pBox->y2; - y++, src += src_pitch, dst += dst_pitch) { - if (memcmp(dst, src, rowbytes) != 0) { - ret = FALSE; - exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2); - break; - } - } - } - - skip: - exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); - - pExaPixmap->use_gpu_copy = save_use_gpu_copy; - pPixmap->devKind = save_pitch; - - out: - RegionUninit(&ValidReg); - return ret; -} - -/** - * Performs migration of the pixmaps according to the operation information - * provided in pixmaps and can_accel and the migration scheme chosen in the - * config file. - */ -void -exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) -{ - ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; - - ExaScreenPriv(pScreen); - int i, j; - - /* If this debugging flag is set, check each pixmap for whether it is marked - * as clean, and if so, actually check if that's the case. This should help - * catch issues with failing to mark a drawable as dirty. While it will - * catch them late (after the operation happened), it at least explains what - * went wrong, and instrumenting the code to find what operation happened - * to the pixmap last shouldn't be hard. - */ - if (pExaScr->checkDirtyCorrectness) { - for (i = 0; i < npixmaps; i++) { - if (!exaPixmapIsDirty(pixmaps[i].pPix) && - !exaAssertNotDirty(pixmaps[i].pPix)) - ErrorF("%s: Pixmap %d dirty but not marked as such!\n", - __func__, 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) && - !exaPixmapHasGpuCopy(pixmaps[i].pPix)) { - EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix, - pixmaps[i].pPix->drawable.width, - pixmaps[i].pPix->drawable.height)); - can_accel = FALSE; - break; - } - } - - if (pExaScr->migration == ExaMigrationSmart) { - /* If we've got something as a destination that we shouldn't cause to - * become newly dirtied, take the unaccelerated route. - */ - for (i = 0; i < npixmaps; i++) { - if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB(pixmaps[i].pPix) && - !exaPixmapIsDirty(pixmaps[i].pPix)) { - for (i = 0; i < npixmaps; i++) { - if (!exaPixmapIsDirty(pixmaps[i].pPix)) - exaDoMoveOutPixmap(pixmaps + i); - } - return; - } - } - - /* If we aren't going to accelerate, then we migrate everybody toward - * system memory, and kick out if it's free. - */ - if (!can_accel) { - for (i = 0; i < npixmaps; i++) { - exaMigrateTowardSys(pixmaps + i); - if (!exaPixmapIsDirty(pixmaps[i].pPix)) - exaDoMoveOutPixmap(pixmaps + i); - } - return; - } - - /* Finally, the acceleration path. Move them all in. */ - for (i = 0; i < npixmaps; i++) { - exaMigrateTowardFb(pixmaps + i); - exaDoMoveInPixmap(pixmaps + i); - } - } - else if (pExaScr->migration == ExaMigrationGreedy) { - /* If we can't accelerate, either because the driver can't or because one of - * the pixmaps is pinned in system memory, then we migrate everybody toward - * system memory. - * - * We also migrate toward system if all pixmaps involved are currently in - * system memory -- this can mitigate thrashing when there are significantly - * more pixmaps active than would fit in memory. - * - * If not, then we migrate toward FB so that hopefully acceleration can - * happen. - */ - if (!can_accel) { - for (i = 0; i < npixmaps; i++) - exaMigrateTowardSys(pixmaps + i); - return; - } - - for (i = 0; i < npixmaps; i++) { - if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) { - /* Found one in FB, so move all to FB. */ - for (j = 0; j < npixmaps; j++) - exaMigrateTowardFb(pixmaps + i); - return; - } - } - - /* Nobody's in FB, so move all away from FB. */ - for (i = 0; i < npixmaps; i++) - exaMigrateTowardSys(pixmaps + i); - } - else if (pExaScr->migration == ExaMigrationAlways) { - /* Always move the pixmaps out if we can't accelerate. If we can - * accelerate, try to move them all in. If that fails, then move them - * back out. - */ - if (!can_accel) { - for (i = 0; i < npixmaps; i++) - exaDoMoveOutPixmap(pixmaps + i); - return; - } - - /* Now, try to move them all into FB */ - for (i = 0; i < npixmaps; i++) { - exaDoMoveInPixmap(pixmaps + i); - } - - /* If we couldn't fit everything in, abort */ - for (i = 0; i < npixmaps; i++) { - if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) { - return; - } - } - - /* Yay, everything has a gpu copy, mark memory as used */ - for (i = 0; i < npixmaps; i++) { - ExaOffscreenMarkUsed(pixmaps[i].pPix); - } - } -} - -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); -} diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c deleted file mode 100644 index 7d3fca7c0..000000000 --- a/exa/exa_migration_mixed.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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" - -void -exaCreateDriverPixmap_mixed(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - ExaPixmapPriv(pPixmap); - 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 paddedWidth = pExaPixmap->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 (pExaScr->info->CreatePixmap2) { - int new_pitch = 0; - - pExaPixmap->driverPriv = - pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, - &new_pitch); - paddedWidth = pExaPixmap->fb_pitch = new_pitch; - } - else { - if (paddedWidth < pExaPixmap->fb_pitch) - paddedWidth = pExaPixmap->fb_pitch; - pExaPixmap->driverPriv = - pExaScr->info->CreatePixmap(pScreen, paddedWidth * h, 0); - } - - if (!pExaPixmap->driverPriv) - return; - - (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL); -} - -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) && - !exaPixmapHasGpuCopy(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); - - if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) { - ExaScreenPriv(pPixmap->drawable.pScreen); - - /* This pitch is needed for proper acceleration. For some reason - * there are pixmaps without pDamage and a bad fb_pitch value. - * So setting devKind when only exaPixmapHasGpuCopy() is true - * causes corruption. Pixmaps without pDamage are not migrated - * and should have a valid devKind at all times, so that's why this - * isn't causing problems. Pixmaps have their gpu pitch set the - * first time in the MPH call from exaCreateDriverPixmap_mixed(). - */ - pPixmap->devKind = pExaPixmap->fb_pitch; - exaCopyDirtyToFb(pixmaps + i); - - if (pExaScr->deferred_mixed_pixmap == pPixmap && - !pixmaps[i].as_dst && !pixmaps[i].pReg) - pExaScr->deferred_mixed_pixmap = NULL; - } - - pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); - } -} - -void -exaMoveInPixmap_mixed(PixmapPtr pPixmap) -{ - ExaMigrationRec pixmaps[1]; - - pixmaps[0].as_dst = FALSE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = pPixmap; - pixmaps[0].pReg = NULL; - - exaDoMigration(pixmaps, 1, TRUE); -} - -void -exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - PixmapPtr pPixmap = closure; - - ExaPixmapPriv(pPixmap); - - /* Move back results of software rendering on system memory copy of mixed driver - * pixmap (see exaPrepareAccessReg_mixed). - * - * Defer moving the destination back into the driver pixmap, to try and save - * overhead on multiple subsequent software fallbacks. - */ - if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) { - ExaScreenPriv(pPixmap->drawable.pScreen); - - if (pExaScr->deferred_mixed_pixmap && - pExaScr->deferred_mixed_pixmap != pPixmap) - exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap); - pExaScr->deferred_mixed_pixmap = pPixmap; - } -} - -/* 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 exaDamageReport_mixed). - */ -void -exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg) -{ - ExaPixmapPriv(pPixmap); - Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); - Bool success; - - success = ExaDoPrepareAccess(pPixmap, index); - - if (success && has_gpu_copy && pExaPixmap->pDamage) { - /* You cannot do accelerated operations while a buffer is mapped. */ - exaFinishAccess(&pPixmap->drawable, index); - /* Update the gpu view of both deferred destination pixmaps and of - * source pixmaps that were migrated with a bounding region. - */ - exaMoveInPixmap_mixed(pPixmap); - success = ExaDoPrepareAccess(pPixmap, index); - - if (success) { - /* We have a gpu pixmap that can be accessed, we don't need the cpu - * copy anymore. Drivers that prefer DFS, should fail prepare - * access. - */ - DamageDestroy(pExaPixmap->pDamage); - pExaPixmap->pDamage = NULL; - - free(pExaPixmap->sys_ptr); - pExaPixmap->sys_ptr = NULL; - - return; - } - } - - if (!success) { - ExaMigrationRec pixmaps[1]; - - /* Do we need to allocate our system buffer? */ - if (!pExaPixmap->sys_ptr) { - pExaPixmap->sys_ptr = xallocarray(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 && - (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) { - Bool as_dst = pixmaps[0].as_dst; - - /* Set up damage tracking */ - pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL, - DamageReportNonEmpty, TRUE, - pPixmap->drawable.pScreen, - pPixmap); - - if (pExaPixmap->pDamage) { - 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 (has_gpu_copy) { - 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; - } - exaCopyDirtyToSys(pixmaps); - } - - if (as_dst) - exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width, - pPixmap->drawable.height); - } - else if (has_gpu_copy) - exaCopyDirtyToSys(pixmaps); - - pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; - pPixmap->devKind = pExaPixmap->sys_pitch; - pExaPixmap->use_gpu_copy = FALSE; - } -} diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c deleted file mode 100644 index 1e67ec23a..000000000 --- a/exa/exa_mixed.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * 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. - */ - -static _X_INLINE void * -ExaGetPixmapAddress(PixmapPtr p) -{ - ExaPixmapPriv(p); - - return pExaPixmap->sys_ptr; -} - -/** - * exaCreatePixmap() creates a new pixmap. - */ -PixmapPtr -exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, - unsigned usage_hint) -{ - PixmapPtr pPixmap; - ExaPixmapPrivPtr pExaPixmap; - int bpp; - size_t paddedWidth; - - 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; - - /* We will allocate the system pixmap later if needed. */ - pPixmap->devPrivate.ptr = NULL; - pExaPixmap->sys_ptr = NULL; - pExaPixmap->sys_pitch = paddedWidth; - - pExaPixmap->area = NULL; - pExaPixmap->fb_ptr = NULL; - pExaPixmap->pDamage = NULL; - - exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); - exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); - - (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL); - - /* A scratch pixmap will become a driver pixmap right away. */ - if (!w || !h) { - exaCreateDriverPixmap_mixed(pPixmap); - pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap); - } - else { - pExaPixmap->use_gpu_copy = FALSE; - - if (w == 1 && h == 1) { - pExaPixmap->sys_ptr = malloc(paddedWidth); - - /* Set up damage tracking */ - pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL, - DamageReportNonEmpty, TRUE, - pPixmap->drawable.pScreen, - pPixmap); - - if (pExaPixmap->pDamage) { - 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); - } - } - } - - /* During a fallback we must prepare access. */ - if (pExaScr->fallback_counter) - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); - - return pPixmap; -} - -Bool -exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth, - int bitsPerPixel, int devKind, void *pPixData) -{ - ScreenPtr pScreen; - ExaScreenPrivPtr pExaScr; - ExaPixmapPrivPtr pExaPixmap; - Bool ret, has_gpu_copy; - - if (!pPixmap) - return FALSE; - - pScreen = pPixmap->drawable.pScreen; - pExaScr = ExaGetScreenPriv(pScreen); - pExaPixmap = ExaGetPixmapPriv(pPixmap); - - if (pPixData) { - if (pExaPixmap->driverPriv) { - if (pExaPixmap->pDamage) { - DamageDestroy(pExaPixmap->pDamage); - pExaPixmap->pDamage = NULL; - } - - pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); - pExaPixmap->driverPriv = NULL; - } - - pExaPixmap->use_gpu_copy = FALSE; - pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; - } - - has_gpu_copy = exaPixmapHasGpuCopy(pPixmap); - - if (width <= 0) - width = pPixmap->drawable.width; - - if (height <= 0) - height = pPixmap->drawable.height; - - if (bitsPerPixel <= 0) { - if (depth <= 0) - bitsPerPixel = pPixmap->drawable.bitsPerPixel; - else - bitsPerPixel = BitsPerPixel(depth); - } - - if (depth <= 0) - depth = pPixmap->drawable.depth; - - if (width != pPixmap->drawable.width || - height != pPixmap->drawable.height || - depth != pPixmap->drawable.depth || - bitsPerPixel != pPixmap->drawable.bitsPerPixel) { - if (pExaPixmap->driverPriv) { - if (devKind > 0) - pExaPixmap->fb_pitch = devKind; - else - exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); - - exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); - RegionEmpty(&pExaPixmap->validFB); - } - - /* Need to re-create system copy if there's also a GPU copy */ - if (has_gpu_copy) { - if (pExaPixmap->sys_ptr) { - free(pExaPixmap->sys_ptr); - pExaPixmap->sys_ptr = NULL; - DamageDestroy(pExaPixmap->pDamage); - pExaPixmap->pDamage = NULL; - RegionEmpty(&pExaPixmap->validSys); - - if (pExaScr->deferred_mixed_pixmap == pPixmap) - pExaScr->deferred_mixed_pixmap = NULL; - } - - pExaPixmap->sys_pitch = PixmapBytePad(width, depth); - } - } - - if (has_gpu_copy) { - 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. */ - if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) { - ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth, - bitsPerPixel, devKind, - pPixData); - if (ret == TRUE) - goto out; - } - - swap(pExaScr, pScreen, ModifyPixmapHeader); - ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, - bitsPerPixel, devKind, pPixData); - swap(pExaScr, pScreen, ModifyPixmapHeader); - - out: - if (has_gpu_copy) { - 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; - - return ret; -} - -Bool -exaDestroyPixmap_mixed(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - Bool ret; - - if (pPixmap->refcnt == 1) { - ExaPixmapPriv(pPixmap); - - exaDestroyPixmap(pPixmap); - - if (pExaScr->deferred_mixed_pixmap == pPixmap) - pExaScr->deferred_mixed_pixmap = NULL; - - if (pExaPixmap->driverPriv) - pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); - pExaPixmap->driverPriv = NULL; - - if (pExaPixmap->pDamage) { - free(pExaPixmap->sys_ptr); - pExaPixmap->sys_ptr = NULL; - pExaPixmap->pDamage = NULL; - } - } - - swap(pExaScr, pScreen, DestroyPixmap); - ret = pScreen->DestroyPixmap(pPixmap); - swap(pExaScr, pScreen, DestroyPixmap); - - return ret; -} - -Bool -exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - - ExaScreenPriv(pScreen); - ExaPixmapPriv(pPixmap); - void *saved_ptr; - Bool ret; - - if (!pExaPixmap->driverPriv) - return FALSE; - - saved_ptr = pPixmap->devPrivate.ptr; - pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); - ret = pExaScr->info->PixmapIsOffscreen(pPixmap); - pPixmap->devPrivate.ptr = saved_ptr; - - return ret; -} - -Bool -exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - ExaScreenPriv(pScreen); - Bool ret = FALSE; - - exaMoveInPixmap(pPixmap); - /* get the driver to give us a handle */ - if (pExaScr->info->SharePixmapBacking) - ret = pExaScr->info->SharePixmapBacking(pPixmap, secondary, handle_p); - - return ret; -} - -Bool -exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - ExaScreenPriv(pScreen); - Bool ret = FALSE; - - if (pExaScr->info->SetSharedPixmapBacking) - ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle); - - if (ret == TRUE) - exaMoveInPixmap(pPixmap); - - return ret; -} - - diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c deleted file mode 100644 index c77e36261..000000000 --- a/exa/exa_offscreen.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright © 2003 Anders Carlsson - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Anders Carlsson not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Anders Carlsson makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/** @file - * This allocator allocates blocks of memory by maintaining a list of areas. - * When allocating, the contiguous block of areas with the minimum eviction - * cost is found and evicted in order to make room for the new allocation. - */ - -#include "exa_priv.h" - -#include <limits.h> -#include <assert.h> -#include <stdlib.h> - -#if DEBUG_OFFSCREEN -#define DBG_OFFSCREEN(a) ErrorF a -#else -#define DBG_OFFSCREEN(a) -#endif - -#if DEBUG_OFFSCREEN -static void -ExaOffscreenValidate(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - ExaOffscreenArea *prev = 0, *area; - - assert(pExaScr->info->offScreenAreas->base_offset == - pExaScr->info->offScreenBase); - for (area = pExaScr->info->offScreenAreas; area; area = area->next) { - assert(area->offset >= area->base_offset); - assert(area->offset < (area->base_offset + area->size)); - if (prev) - assert(prev->base_offset + prev->size == area->base_offset); - prev = area; - } - assert(prev->base_offset + prev->size == pExaScr->info->memorySize); -} -#else -#define ExaOffscreenValidate(s) -#endif - -static ExaOffscreenArea * -ExaOffscreenKickOut(ScreenPtr pScreen, ExaOffscreenArea * area) -{ - if (area->save) - (*area->save) (pScreen, area); - return exaOffscreenFree(pScreen, area); -} - -static void -exaUpdateEvictionCost(ExaOffscreenArea * area, unsigned offScreenCounter) -{ - unsigned age; - - if (area->state == ExaOffscreenAvail) - return; - - age = offScreenCounter - area->last_use; - - /* This is unlikely to happen, but could result in a division by zero... */ - if (age > (UINT_MAX / 2)) { - age = UINT_MAX / 2; - area->last_use = offScreenCounter - age; - } - - area->eviction_cost = area->size / age; -} - -static ExaOffscreenArea * -exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align) -{ - ExaOffscreenArea *begin, *end, *best; - unsigned cost, best_cost; - int avail, real_size; - - best_cost = UINT_MAX; - begin = end = pExaScr->info->offScreenAreas; - avail = 0; - cost = 0; - best = 0; - - while (end != NULL) { - restart: - while (begin != NULL && begin->state == ExaOffscreenLocked) - begin = end = begin->next; - - if (begin == NULL) - break; - - /* adjust size needed to account for alignment loss for this area */ - real_size = size + (begin->base_offset + begin->size - size) % align; - - while (avail < real_size && end != NULL) { - if (end->state == ExaOffscreenLocked) { - /* Can't more room here, restart after this locked area */ - avail = 0; - cost = 0; - begin = end; - goto restart; - } - avail += end->size; - exaUpdateEvictionCost(end, pExaScr->offScreenCounter); - cost += end->eviction_cost; - end = end->next; - } - - /* Check the cost, update best */ - if (avail >= real_size && cost < best_cost) { - best = begin; - best_cost = cost; - } - - avail -= begin->size; - cost -= begin->eviction_cost; - begin = begin->next; - } - - return best; -} - -/** - * exaOffscreenAlloc allocates offscreen memory - * - * @param pScreen current screen - * @param size size in bytes of the allocation - * @param align byte alignment requirement for the offset of the allocated area - * @param locked whether the allocated area is locked and can't be kicked out - * @param save callback for when the area is evicted from memory - * @param privdata private data for the save callback. - * - * Allocates offscreen memory from the device associated with pScreen. size - * and align determine where and how large the allocated area is, and locked - * will mark whether it should be held in card memory. privdata may be any - * pointer for the save callback when the area is removed. - * - * Note that locked areas do get evicted on VT switch unless the driver - * requested version 2.1 or newer behavior. In that case, the save callback is - * still called. - */ -ExaOffscreenArea * -exaOffscreenAlloc(ScreenPtr pScreen, int size, int align, - Bool locked, ExaOffscreenSaveProc save, void *privData) -{ - ExaOffscreenArea *area; - - ExaScreenPriv(pScreen); - int real_size = 0, largest_avail = 0; - -#if DEBUG_OFFSCREEN - static int number = 0; - - ErrorF("================= ============ allocating a new pixmap %d\n", - ++number); -#endif - - ExaOffscreenValidate(pScreen); - if (!align) - align = 1; - - if (!size) { - DBG_OFFSCREEN(("Alloc 0x%x -> EMPTY\n", size)); - return NULL; - } - - /* throw out requests that cannot fit */ - if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase)) { - DBG_OFFSCREEN(("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size, - pExaScr->info->memorySize - - pExaScr->info->offScreenBase)); - return NULL; - } - - /* Try to find a free space that'll fit. */ - for (area = pExaScr->info->offScreenAreas; area; area = area->next) { - /* skip allocated areas */ - if (area->state != ExaOffscreenAvail) - continue; - - /* adjust size to match alignment requirement */ - real_size = size + (area->base_offset + area->size - size) % align; - - /* does it fit? */ - if (real_size <= area->size) - break; - - if (area->size > largest_avail) - largest_avail = area->size; - } - - if (!area) { - area = exaFindAreaToEvict(pExaScr, size, align); - - if (!area) { - DBG_OFFSCREEN(("Alloc 0x%x -> NOSPACE\n", size)); - /* Could not allocate memory */ - ExaOffscreenValidate(pScreen); - return NULL; - } - - /* adjust size needed to account for alignment loss for this area */ - real_size = size + (area->base_offset + area->size - size) % align; - - /* - * Kick out first area if in use - */ - if (area->state != ExaOffscreenAvail) - area = ExaOffscreenKickOut(pScreen, area); - /* - * Now get the system to merge the other needed areas together - */ - while (area->size < real_size) { - assert(area->next); - assert(area->next->state == ExaOffscreenRemovable); - (void) ExaOffscreenKickOut(pScreen, area->next); - } - } - - /* save extra space in new area */ - if (real_size < area->size) { - ExaOffscreenArea *new_area = malloc(sizeof(ExaOffscreenArea)); - - if (!new_area) - return NULL; - new_area->base_offset = area->base_offset; - - new_area->offset = new_area->base_offset; - new_area->align = 0; - new_area->size = area->size - real_size; - new_area->state = ExaOffscreenAvail; - new_area->save = NULL; - new_area->last_use = 0; - new_area->eviction_cost = 0; - new_area->next = area; - new_area->prev = area->prev; - if (area->prev->next) - area->prev->next = new_area; - else - pExaScr->info->offScreenAreas = new_area; - area->prev = new_area; - area->base_offset = new_area->base_offset + new_area->size; - area->size = real_size; - } - else - pExaScr->numOffscreenAvailable--; - - /* - * Mark this area as in use - */ - if (locked) - area->state = ExaOffscreenLocked; - else - area->state = ExaOffscreenRemovable; - area->privData = privData; - area->save = save; - area->last_use = pExaScr->offScreenCounter++; - area->offset = (area->base_offset + align - 1); - area->offset -= area->offset % align; - area->align = align; - - ExaOffscreenValidate(pScreen); - - DBG_OFFSCREEN(("Alloc 0x%x -> 0x%x (0x%x)\n", size, - area->base_offset, area->offset)); - return area; -} - -/** - * Ejects all offscreen areas, and uninitializes the offscreen memory manager. - */ -void -ExaOffscreenSwapOut(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - - ExaOffscreenValidate(pScreen); - /* loop until a single free area spans the space */ - for (;;) { - ExaOffscreenArea *area = pExaScr->info->offScreenAreas; - - if (!area) - break; - if (area->state == ExaOffscreenAvail) { - area = area->next; - if (!area) - break; - } - assert(area->state != ExaOffscreenAvail); - (void) ExaOffscreenKickOut(pScreen, area); - ExaOffscreenValidate(pScreen); - } - ExaOffscreenValidate(pScreen); - ExaOffscreenFini(pScreen); -} - -/** Ejects all pixmaps managed by EXA. */ -static void -ExaOffscreenEjectPixmaps(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - - ExaOffscreenValidate(pScreen); - /* loop until a single free area spans the space */ - for (;;) { - ExaOffscreenArea *area; - - for (area = pExaScr->info->offScreenAreas; area != NULL; - area = area->next) { - if (area->state == ExaOffscreenRemovable && - area->save == exaPixmapSave) { - (void) ExaOffscreenKickOut(pScreen, area); - ExaOffscreenValidate(pScreen); - break; - } - } - if (area == NULL) - break; - } - ExaOffscreenValidate(pScreen); -} - -void -ExaOffscreenSwapIn(ScreenPtr pScreen) -{ - exaOffscreenInit(pScreen); -} - -/** - * Prepares EXA for disabling of FB access, or restoring it. - * - * In version 2.1, the disabling results in pixmaps being ejected, while other - * allocations remain. With this plus the prevention of migration while - * swappedOut is set, EXA by itself should not cause any access of the - * framebuffer to occur while swapped out. Any remaining issues are the - * responsibility of the driver. - * - * Prior to version 2.1, all allocations, including locked ones, are ejected - * when access is disabled, and the allocator is torn down while swappedOut - * is set. This is more drastic, and caused implementation difficulties for - * many drivers that could otherwise handle the lack of FB access while - * swapped out. - */ -void -exaEnableDisableFBAccess(ScreenPtr pScreen, Bool enable) -{ - ExaScreenPriv(pScreen); - - if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) - return; - - if (!enable && pExaScr->disableFbCount++ == 0) { - if (pExaScr->info->exa_minor < 1) - ExaOffscreenSwapOut(pScreen); - else - ExaOffscreenEjectPixmaps(pScreen); - pExaScr->swappedOut = TRUE; - } - - if (enable && --pExaScr->disableFbCount == 0) { - if (pExaScr->info->exa_minor < 1) - ExaOffscreenSwapIn(pScreen); - pExaScr->swappedOut = FALSE; - } -} - -/* merge the next free area into this one */ -static void -ExaOffscreenMerge(ExaScreenPrivPtr pExaScr, ExaOffscreenArea * area) -{ - ExaOffscreenArea *next = area->next; - - /* account for space */ - area->size += next->size; - /* frob pointer */ - area->next = next->next; - if (area->next) - area->next->prev = area; - else - pExaScr->info->offScreenAreas->prev = area; - free(next); - - pExaScr->numOffscreenAvailable--; -} - -/** - * exaOffscreenFree frees an allocation. - * - * @param pScreen current screen - * @param area offscreen area to free - * - * exaOffscreenFree frees an allocation created by exaOffscreenAlloc. Note that - * the save callback of the area is not called, and it is up to the driver to - * do any cleanup necessary as a result. - * - * @return pointer to the newly freed area. This behavior should not be relied - * on. - */ -ExaOffscreenArea * -exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea * area) -{ - ExaScreenPriv(pScreen); - ExaOffscreenArea *next = area->next; - ExaOffscreenArea *prev; - - DBG_OFFSCREEN(("Free 0x%x -> 0x%x (0x%x)\n", area->size, - area->base_offset, area->offset)); - ExaOffscreenValidate(pScreen); - - area->state = ExaOffscreenAvail; - area->save = NULL; - area->last_use = 0; - area->eviction_cost = 0; - /* - * Find previous area - */ - if (area == pExaScr->info->offScreenAreas) - prev = NULL; - else - prev = area->prev; - - pExaScr->numOffscreenAvailable++; - - /* link with next area if free */ - if (next && next->state == ExaOffscreenAvail) - ExaOffscreenMerge(pExaScr, area); - - /* link with prev area if free */ - if (prev && prev->state == ExaOffscreenAvail) { - area = prev; - ExaOffscreenMerge(pExaScr, area); - } - - ExaOffscreenValidate(pScreen); - DBG_OFFSCREEN(("\tdone freeing\n")); - return area; -} - -void -ExaOffscreenMarkUsed(PixmapPtr pPixmap) -{ - ExaPixmapPriv(pPixmap); - ExaScreenPriv(pPixmap->drawable.pScreen); - - if (!pExaPixmap || !pExaPixmap->area) - return; - - pExaPixmap->area->last_use = pExaScr->offScreenCounter++; -} - -/** - * Defragment offscreen memory by compacting allocated areas at the end of it, - * leaving the total amount of memory available as a single area at the - * beginning (when there are no pinned allocations). - */ -_X_HIDDEN ExaOffscreenArea * -ExaOffscreenDefragment(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - ExaOffscreenArea *area, *largest_available = NULL; - int largest_size = 0; - PixmapPtr pDstPix; - ExaPixmapPrivPtr pExaDstPix; - - pDstPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, 0, 0); - - if (!pDstPix) - return NULL; - - pExaDstPix = ExaGetPixmapPriv(pDstPix); - pExaDstPix->use_gpu_copy = TRUE; - - for (area = pExaScr->info->offScreenAreas->prev; - area != pExaScr->info->offScreenAreas;) { - ExaOffscreenArea *prev = area->prev; - PixmapPtr pSrcPix; - ExaPixmapPrivPtr pExaSrcPix; - Bool save_use_gpu_copy; - int save_pitch; - - if (area->state != ExaOffscreenAvail || - prev->state == ExaOffscreenLocked || - (prev->state == ExaOffscreenRemovable && - prev->save != exaPixmapSave)) { - area = prev; - continue; - } - - if (prev->state == ExaOffscreenAvail) { - if (area == largest_available) { - largest_available = prev; - largest_size += prev->size; - } - area = prev; - ExaOffscreenMerge(pExaScr, area); - continue; - } - - if (area->size > largest_size) { - largest_available = area; - largest_size = area->size; - } - - pSrcPix = prev->privData; - pExaSrcPix = ExaGetPixmapPriv(pSrcPix); - - pExaDstPix->fb_ptr = pExaScr->info->memoryBase + - area->base_offset + area->size - prev->size + prev->base_offset - - prev->offset; - pExaDstPix->fb_ptr -= (unsigned long) pExaDstPix->fb_ptr % prev->align; - - if (pExaDstPix->fb_ptr <= pExaSrcPix->fb_ptr) { - area = prev; - continue; - } - - if (!(pExaScr->info->flags & EXA_SUPPORTS_OFFSCREEN_OVERLAPS) && - (pExaSrcPix->fb_ptr + prev->size) > pExaDstPix->fb_ptr) { - area = prev; - continue; - } - - save_use_gpu_copy = pExaSrcPix->use_gpu_copy; - save_pitch = pSrcPix->devKind; - - pExaSrcPix->use_gpu_copy = TRUE; - pSrcPix->devKind = pExaSrcPix->fb_pitch; - - pDstPix->drawable.width = pSrcPix->drawable.width; - pDstPix->devKind = pSrcPix->devKind; - pDstPix->drawable.height = pSrcPix->drawable.height; - pDstPix->drawable.depth = pSrcPix->drawable.depth; - pDstPix->drawable.bitsPerPixel = pSrcPix->drawable.bitsPerPixel; - - if (!pExaScr->info->PrepareCopy(pSrcPix, pDstPix, -1, -1, GXcopy, ~0)) { - pExaSrcPix->use_gpu_copy = save_use_gpu_copy; - pSrcPix->devKind = save_pitch; - area = prev; - continue; - } - - pExaScr->info->Copy(pDstPix, 0, 0, 0, 0, pDstPix->drawable.width, - pDstPix->drawable.height); - pExaScr->info->DoneCopy(pDstPix); - exaMarkSync(pScreen); - - DBG_OFFSCREEN(("Before swap: prev=0x%08x-0x%08x-0x%08x area=0x%08x-0x%08x-0x%08x\n", prev->base_offset, prev->offset, prev->base_offset + prev->size, area->base_offset, area->offset, area->base_offset + area->size)); - - /* Calculate swapped area offsets and sizes */ - area->base_offset = prev->base_offset; - area->offset = area->base_offset; - prev->offset += pExaDstPix->fb_ptr - pExaSrcPix->fb_ptr; - assert(prev->offset >= pExaScr->info->offScreenBase); - assert(prev->offset < pExaScr->info->memorySize); - prev->base_offset = prev->offset; - if (area->next) - prev->size = area->next->base_offset - prev->base_offset; - else - prev->size = pExaScr->info->memorySize - prev->base_offset; - area->size = prev->base_offset - area->base_offset; - - DBG_OFFSCREEN(("After swap: area=0x%08x-0x%08x-0x%08x prev=0x%08x-0x%08x-0x%08x\n", area->base_offset, area->offset, area->base_offset + area->size, prev->base_offset, prev->offset, prev->base_offset + prev->size)); - - /* Swap areas in list */ - if (area->next) - area->next->prev = prev; - else - pExaScr->info->offScreenAreas->prev = prev; - if (prev->prev->next) - prev->prev->next = area; - else - pExaScr->info->offScreenAreas = area; - prev->next = area->next; - area->next = prev; - area->prev = prev->prev; - prev->prev = area; - if (!area->prev->next) - pExaScr->info->offScreenAreas = area; - -#if DEBUG_OFFSCREEN - if (prev->prev == prev || prev->next == prev) - ErrorF("Whoops, prev points to itself!\n"); - - if (area->prev == area || area->next == area) - ErrorF("Whoops, area points to itself!\n"); -#endif - - pExaSrcPix->fb_ptr = pExaDstPix->fb_ptr; - pExaSrcPix->use_gpu_copy = save_use_gpu_copy; - pSrcPix->devKind = save_pitch; - } - - pDstPix->drawable.width = 0; - pDstPix->drawable.height = 0; - pDstPix->drawable.depth = 0; - pDstPix->drawable.bitsPerPixel = 0; - - (*pScreen->DestroyPixmap) (pDstPix); - - if (area->state == ExaOffscreenAvail && area->size > largest_size) - return area; - - return largest_available; -} - -/** - * exaOffscreenInit initializes the offscreen memory manager. - * - * @param pScreen current screen - * - * exaOffscreenInit is called by exaDriverInit to set up the memory manager for - * the screen, if any offscreen memory is available. - */ -Bool -exaOffscreenInit(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - ExaOffscreenArea *area; - - /* Allocate a big free area */ - area = malloc(sizeof(ExaOffscreenArea)); - - if (!area) - return FALSE; - - area->state = ExaOffscreenAvail; - area->base_offset = pExaScr->info->offScreenBase; - area->offset = area->base_offset; - area->align = 0; - area->size = pExaScr->info->memorySize - area->base_offset; - area->save = NULL; - area->next = NULL; - area->prev = area; - area->last_use = 0; - area->eviction_cost = 0; - - /* Add it to the free areas */ - pExaScr->info->offScreenAreas = area; - pExaScr->offScreenCounter = 1; - pExaScr->numOffscreenAvailable = 1; - - ExaOffscreenValidate(pScreen); - - return TRUE; -} - -void -ExaOffscreenFini(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - ExaOffscreenArea *area; - - /* just free all of the area records */ - while ((area = pExaScr->info->offScreenAreas)) { - pExaScr->info->offScreenAreas = area->next; - free(area); - } -} diff --git a/exa/exa_priv.h b/exa/exa_priv.h deleted file mode 100644 index 4468487e6..000000000 --- a/exa/exa_priv.h +++ /dev/null @@ -1,735 +0,0 @@ -/* - * - * Copyright (C) 2000 Keith Packard, member of The XFree86 Project, Inc. - * 2005 Zack Rusin, Trolltech - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef EXAPRIV_H -#define EXAPRIV_H - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "exa.h" - -#include <X11/X.h> -#include <X11/Xproto.h> -#ifdef MITSHM -#include "shmint.h" -#endif -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "servermd.h" -#include "colormapst.h" -#include "gcstruct.h" -#include "input.h" -#include "mipointer.h" -#include "mi.h" -#include "dix.h" -#include "fb.h" -#include "fboverlay.h" -#include "fbpict.h" -#include "glyphstr.h" -#include "damage.h" - -#define DEBUG_TRACE_FALL 0 -#define DEBUG_MIGRATE 0 -#define DEBUG_PIXMAP 0 -#define DEBUG_OFFSCREEN 0 -#define DEBUG_GLYPH_CACHE 0 - -#if DEBUG_TRACE_FALL -#define EXA_FALLBACK(x) \ -do { \ - ErrorF("EXA fallback at %s: ", __FUNCTION__); \ - ErrorF x; \ -} while (0) - -char - exaDrawableLocation(DrawablePtr pDrawable); -#else -#define EXA_FALLBACK(x) -#endif - -#if DEBUG_PIXMAP -#define DBG_PIXMAP(a) ErrorF a -#else -#define DBG_PIXMAP(a) -#endif - -#ifndef EXA_MAX_FB -#define EXA_MAX_FB FB_OVERLAY_MAX -#endif - -#ifdef DEBUG -#define EXA_FatalErrorDebug(x) FatalError x -#define EXA_FatalErrorDebugWithRet(x, ret) FatalError x -#else -#define EXA_FatalErrorDebug(x) ErrorF x -#define EXA_FatalErrorDebugWithRet(x, ret) \ -do { \ - ErrorF x; \ - return ret; \ -} while (0) -#endif - -/** - * This is the list of migration heuristics supported by EXA. See - * exaDoMigration() for what their implementations do. - */ -enum ExaMigrationHeuristic { - ExaMigrationGreedy, - ExaMigrationAlways, - ExaMigrationSmart -}; - -typedef struct { - unsigned char sha1[20]; -} ExaCachedGlyphRec, *ExaCachedGlyphPtr; - -typedef struct { - /* The identity of the cache, statically configured at initialization */ - unsigned int format; - int glyphWidth; - int glyphHeight; - - int size; /* Size of cache; eventually this should be dynamically determined */ - - /* Hash table mapping from glyph sha1 to position in the glyph; we use - * open addressing with a hash table size determined based on size and large - * enough so that we always have a good amount of free space, so we can - * use linear probing. (Linear probing is preferable to double hashing - * here because it allows us to easily remove entries.) - */ - int *hashEntries; - int hashSize; - - ExaCachedGlyphPtr glyphs; - int glyphCount; /* Current number of glyphs */ - - PicturePtr picture; /* Where the glyphs of the cache are stored */ - int yOffset; /* y location within the picture where the cache starts */ - int columns; /* Number of columns the glyphs are laid out in */ - int evictionPosition; /* Next random position to evict a glyph */ -} ExaGlyphCacheRec, *ExaGlyphCachePtr; - -#define EXA_NUM_GLYPH_CACHES 4 - -#define EXA_FALLBACK_COPYWINDOW (1 << 0) -#define EXA_ACCEL_COPYWINDOW (1 << 1) - -typedef struct _ExaMigrationRec { - Bool as_dst; - Bool as_src; - PixmapPtr pPix; - RegionPtr pReg; -} ExaMigrationRec, *ExaMigrationPtr; - -typedef void (*EnableDisableFBAccessProcPtr) (ScreenPtr, Bool); -typedef struct { - ExaDriverPtr info; - ScreenBlockHandlerProcPtr SavedBlockHandler; - ScreenWakeupHandlerProcPtr SavedWakeupHandler; - CreateGCProcPtr SavedCreateGC; - CloseScreenProcPtr SavedCloseScreen; - GetImageProcPtr SavedGetImage; - GetSpansProcPtr SavedGetSpans; - CreatePixmapProcPtr SavedCreatePixmap; - DestroyPixmapProcPtr SavedDestroyPixmap; - CopyWindowProcPtr SavedCopyWindow; - ChangeWindowAttributesProcPtr SavedChangeWindowAttributes; - BitmapToRegionProcPtr SavedBitmapToRegion; - CreateScreenResourcesProcPtr SavedCreateScreenResources; - ModifyPixmapHeaderProcPtr SavedModifyPixmapHeader; - SharePixmapBackingProcPtr SavedSharePixmapBacking; - SetSharedPixmapBackingProcPtr SavedSetSharedPixmapBacking; - SourceValidateProcPtr SavedSourceValidate; - CompositeProcPtr SavedComposite; - TrianglesProcPtr SavedTriangles; - GlyphsProcPtr SavedGlyphs; - TrapezoidsProcPtr SavedTrapezoids; - AddTrapsProcPtr SavedAddTraps; - void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps, - Bool can_accel); - Bool (*pixmap_has_gpu_copy) (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); - - Bool swappedOut; - enum ExaMigrationHeuristic migration; - Bool checkDirtyCorrectness; - unsigned disableFbCount; - Bool optimize_migration; - unsigned offScreenCounter; - unsigned numOffscreenAvailable; - CARD32 lastDefragment; - CARD32 nextDefragment; - PixmapPtr deferred_mixed_pixmap; - - /* Reference counting for accessed pixmaps */ - struct { - PixmapPtr pixmap; - int count; - Bool retval; - } access[EXA_NUM_PREPARE_INDICES]; - - /* Holds information on fallbacks that cannot be relayed otherwise. */ - unsigned int fallback_flags; - unsigned int fallback_counter; - - ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES]; - - /** - * Regions affected by fallback composite source / mask operations. - */ - - RegionRec srcReg; - RegionRec maskReg; - PixmapPtr srcPix; - PixmapPtr maskPix; - - DevPrivateKeyRec pixmapPrivateKeyRec; - DevPrivateKeyRec gcPrivateKeyRec; -} ExaScreenPrivRec, *ExaScreenPrivPtr; - -extern DevPrivateKeyRec exaScreenPrivateKeyRec; - -#define exaScreenPrivateKey (&exaScreenPrivateKeyRec) - -#define ExaGetScreenPriv(s) ((ExaScreenPrivPtr)dixGetPrivate(&(s)->devPrivates, exaScreenPrivateKey)) -#define ExaScreenPriv(s) ExaScreenPrivPtr pExaScr = ExaGetScreenPriv(s) - -#define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixGetPrivateAddr(&(gc)->devPrivates, &ExaGetScreenPriv(gc->pScreen)->gcPrivateKeyRec)) -#define ExaGCPriv(gc) ExaGCPrivPtr pExaGC = ExaGetGCPriv(gc) - -/* - * Some macros to deal with function wrapping. - */ -#define wrap(priv, real, mem, func) {\ - priv->Saved##mem = real->mem; \ - real->mem = func; \ -} - -#define unwrap(priv, real, mem) {\ - real->mem = priv->Saved##mem; \ -} - -#ifdef HAVE_TYPEOF -#define swap(priv, real, mem) {\ - typeof(real->mem) tmp = priv->Saved##mem; \ - priv->Saved##mem = real->mem; \ - real->mem = tmp; \ -} -#else -#define swap(priv, real, mem) {\ - const void *tmp = priv->Saved##mem; \ - priv->Saved##mem = real->mem; \ - real->mem = tmp; \ -} -#endif - -#define EXA_PRE_FALLBACK(_screen_) \ - ExaScreenPriv(_screen_); \ - pExaScr->fallback_counter++; - -#define EXA_POST_FALLBACK(_screen_) \ - pExaScr->fallback_counter--; - -#define EXA_PRE_FALLBACK_GC(_gc_) \ - ExaScreenPriv(_gc_->pScreen); \ - ExaGCPriv(_gc_); \ - pExaScr->fallback_counter++; \ - swap(pExaGC, _gc_, ops); - -#define EXA_POST_FALLBACK_GC(_gc_) \ - pExaScr->fallback_counter--; \ - swap(pExaGC, _gc_, ops); - -/** Align an offset to an arbitrary alignment */ -#define EXA_ALIGN(offset, align) (((offset) + (align) - 1) - \ - (((offset) + (align) - 1) % (align))) -/** Align an offset to a power-of-two alignment */ -#define EXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1)) - -#define EXA_PIXMAP_SCORE_MOVE_IN 10 -#define EXA_PIXMAP_SCORE_MAX 20 -#define EXA_PIXMAP_SCORE_MOVE_OUT -10 -#define EXA_PIXMAP_SCORE_MIN -20 -#define EXA_PIXMAP_SCORE_PINNED 1000 -#define EXA_PIXMAP_SCORE_INIT 1001 - -#define ExaGetPixmapPriv(p) ((ExaPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &ExaGetScreenPriv((p)->drawable.pScreen)->pixmapPrivateKeyRec)) -#define ExaPixmapPriv(p) ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv(p) - -#define EXA_RANGE_PITCH (1 << 0) -#define EXA_RANGE_WIDTH (1 << 1) -#define EXA_RANGE_HEIGHT (1 << 2) - -typedef struct { - ExaOffscreenArea *area; - int score; /**< score for the move-in vs move-out heuristic */ - Bool use_gpu_copy; - - CARD8 *sys_ptr; /**< pointer to pixmap data in system memory */ - int sys_pitch; /**< pitch of pixmap in system memory */ - - CARD8 *fb_ptr; /**< pointer to pixmap data in framebuffer memory */ - int fb_pitch; /**< pitch of pixmap in framebuffer memory */ - unsigned int fb_size; /**< size of pixmap in framebuffer memory */ - - /** - * Holds information about whether this pixmap can be used for - * acceleration (== 0) or not (> 0). - * - * Contains a OR'ed combination of the following values: - * EXA_RANGE_PITCH - set if the pixmap's pitch is out of range - * EXA_RANGE_WIDTH - set if the pixmap's width is out of range - * EXA_RANGE_HEIGHT - set if the pixmap's height is out of range - */ - unsigned int accel_blocked; - - /** - * The damage record contains the areas of the pixmap's current location - * (framebuffer or system) that have been damaged compared to the other - * location. - */ - DamagePtr pDamage; - /** - * The valid regions mark the valid bits (at least, as they're derived from - * damage, which may be overreported) of a pixmap's system and FB copies. - */ - RegionRec validSys, validFB; - /** - * Driver private storage per EXA pixmap - */ - void *driverPriv; -} ExaPixmapPrivRec, *ExaPixmapPrivPtr; - -typedef struct { - /* GC values from the layer below. */ - const GCOps *Savedops; - const GCFuncs *Savedfuncs; -} ExaGCPrivRec, *ExaGCPrivPtr; - -typedef struct { - PicturePtr pDst; - INT16 xSrc; - INT16 ySrc; - INT16 xMask; - INT16 yMask; - INT16 xDst; - INT16 yDst; - INT16 width; - INT16 height; -} ExaCompositeRectRec, *ExaCompositeRectPtr; - -/** - * exaDDXDriverInit must be implemented by the DDX using EXA, and is the place - * to set EXA options or hook in screen functions to handle using EXA as the AA. - */ -void exaDDXDriverInit(ScreenPtr pScreen); - -/* exa_unaccel.c */ -void - exaPrepareAccessGC(GCPtr pGC); - -void - exaFinishAccessGC(GCPtr pGC); - -void - -ExaCheckFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nspans, - DDXPointPtr ppt, int *pwidth, int fSorted); - -void - -ExaCheckSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, - DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); - -void - -ExaCheckPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, - int x, int y, int w, int h, int leftPad, int format, - char *bits); - -void - -ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, void *closure); - -RegionPtr - -ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty); - -RegionPtr - -ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty, - unsigned long bitPlane); - -void - -ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr pptInit); - -void - -ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC, - int mode, int npt, DDXPointPtr ppt); - -void - -ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC, - int nsegInit, xSegment * pSegInit); - -void - ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs); - -void - -ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, - int nrect, xRectangle *prect); - -void - -ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr * ppci, void *pglyphBase); - -void - -ExaCheckPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr * ppci, void *pglyphBase); - -void - -ExaCheckPushPixels(GCPtr pGC, PixmapPtr pBitmap, - DrawablePtr pDrawable, int w, int h, int x, int y); - -void - ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); - -void - -ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, - unsigned int format, unsigned long planeMask, char *d); - -void - -ExaCheckGetSpans(DrawablePtr pDrawable, - int wMax, - DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart); - -void - -ExaCheckAddTraps(PicturePtr pPicture, - INT16 x_off, INT16 y_off, int ntrap, xTrap * traps); - -/* exa_accel.c */ - -static _X_INLINE Bool -exaGCReadsDestination(DrawablePtr pDrawable, unsigned long planemask, - unsigned int fillStyle, unsigned char alu, - Bool clientClip) -{ - return ((alu != GXcopy && alu != GXclear && alu != GXset && - alu != GXcopyInverted) || fillStyle == FillStippled || - clientClip != FALSE || !EXA_PM_IS_SOLID(pDrawable, planemask)); -} - -void - exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); - -Bool - -exaFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, - DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu, - Bool clientClip); - -void - -exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, - unsigned int format, unsigned long planeMask, char *d); - -RegionPtr - -exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, - int srcx, int srcy, int width, int height, int dstx, int dsty); - -Bool - -exaHWCopyNtoN(DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - BoxPtr pbox, - int nbox, int dx, int dy, Bool reverse, Bool upsidedown); - -void - -exaCopyNtoN(DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GCPtr pGC, - BoxPtr pbox, - int nbox, - int dx, - int dy, - Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); - -extern const GCOps exaOps; - -void - -ExaCheckComposite(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); - -void - -ExaCheckGlyphs(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); - -/* exa_offscreen.c */ -void - ExaOffscreenSwapOut(ScreenPtr pScreen); - -void - ExaOffscreenSwapIn(ScreenPtr pScreen); - -ExaOffscreenArea *ExaOffscreenDefragment(ScreenPtr pScreen); - -Bool - exaOffscreenInit(ScreenPtr pScreen); - -void - ExaOffscreenFini(ScreenPtr pScreen); - -/* exa.c */ -Bool - ExaDoPrepareAccess(PixmapPtr pPixmap, int index); - -void - exaPrepareAccess(DrawablePtr pDrawable, int index); - -void - exaFinishAccess(DrawablePtr pDrawable, int index); - -void - exaDestroyPixmap(PixmapPtr pPixmap); - -void - exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2); - -void - -exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, - int *xp, int *yp); - -Bool - exaPixmapHasGpuCopy(PixmapPtr p); - -PixmapPtr - exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp); - -PixmapPtr - exaGetDrawablePixmap(DrawablePtr pDrawable); - -void - -exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, - int w, int h, int bpp); - -void - -exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap, - int w, int h, int bpp); - -void - exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); - -Bool - exaPixmapIsPinned(PixmapPtr pPix); - -extern const GCFuncs exaGCFuncs; - -/* exa_classic.c */ -PixmapPtr - -exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth, - unsigned usage_hint); - -Bool - -exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, - int depth, int bitsPerPixel, int devKind, - void *pPixData); - -Bool - exaDestroyPixmap_classic(PixmapPtr pPixmap); - -Bool - exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap); - -/* exa_driver.c */ -PixmapPtr - -exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth, - unsigned usage_hint); - -Bool - -exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, - int depth, int bitsPerPixel, int devKind, - void *pPixData); - -Bool - exaDestroyPixmap_driver(PixmapPtr pPixmap); - -Bool - exaPixmapHasGpuCopy_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, void *pPixData); - -Bool - exaDestroyPixmap_mixed(PixmapPtr pPixmap); - -Bool - exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap); - -/* exa_migration_mixed.c */ -void - exaCreateDriverPixmap_mixed(PixmapPtr pPixmap); - -void - exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); - -void - exaMoveInPixmap_mixed(PixmapPtr pPixmap); - -void - exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure); - -void - exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg); - -Bool -exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle); -Bool -exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p); - -/* exa_render.c */ -Bool - exaOpReadsDestination(CARD8 op); - -void - -exaComposite(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); - -void - -exaCompositeRects(CARD8 op, - PicturePtr Src, - PicturePtr pMask, - PicturePtr pDst, int nrect, ExaCompositeRectPtr rects); - -void - -exaTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntrap, xTrapezoid * traps); - -void - -exaTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntri, xTriangle * tris); - -/* exa_glyph.c */ -void - exaGlyphsInit(ScreenPtr pScreen); - -void - exaGlyphsFini(ScreenPtr pScreen); - -void - -exaGlyphs(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); - -/* exa_migration_classic.c */ -void - exaCopyDirtyToSys(ExaMigrationPtr migrate); - -void - exaCopyDirtyToFb(ExaMigrationPtr migrate); - -void - exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); - -void - exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area); - -void - exaMoveOutPixmap_classic(PixmapPtr pPixmap); - -void - exaMoveInPixmap_classic(PixmapPtr pPixmap); - -void - exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg); - -#endif /* EXAPRIV_H */ diff --git a/exa/exa_render.c b/exa/exa_render.c deleted file mode 100644 index 9fbfdfca2..000000000 --- a/exa/exa_render.c +++ /dev/null @@ -1,1229 +0,0 @@ -/* - * Copyright © 2001 Keith Packard - * - * Partly based on code that is Copyright © The XFree86 Project Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <stdlib.h> - -#include "exa_priv.h" - -#include "mipict.h" - -#if DEBUG_TRACE_FALL -static void -exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n) -{ - char format[20]; - char size[20]; - char loc; - int temp; - - if (!pict) { - snprintf(string, n, "None"); - return; - } - - switch (pict->format) { - case PICT_a8r8g8b8: - snprintf(format, 20, "ARGB8888"); - break; - case PICT_x8r8g8b8: - snprintf(format, 20, "XRGB8888"); - break; - case PICT_b8g8r8a8: - snprintf(format, 20, "BGRA8888"); - break; - case PICT_b8g8r8x8: - snprintf(format, 20, "BGRX8888"); - break; - case PICT_r5g6b5: - snprintf(format, 20, "RGB565 "); - break; - case PICT_x1r5g5b5: - snprintf(format, 20, "RGB555 "); - break; - case PICT_a8: - snprintf(format, 20, "A8 "); - break; - case PICT_a1: - snprintf(format, 20, "A1 "); - break; - default: - snprintf(format, 20, "0x%x", (int) pict->format); - break; - } - - if (pict->pDrawable) { - loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm'; - - snprintf(size, 20, "%dx%d%s", pict->pDrawable->width, - pict->pDrawable->height, pict->repeat ? " R" : ""); - } - else { - loc = '-'; - - snprintf(size, 20, "%s", pict->repeat ? " R" : ""); - } - - snprintf(string, n, "%p:%c fmt %s (%s)", pict->pDrawable, loc, format, - size); -} - -static void -exaPrintCompositeFallback(CARD8 op, - PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) -{ - char sop[20]; - char srcdesc[40], maskdesc[40], dstdesc[40]; - - switch (op) { - case PictOpSrc: - snprintf(sop, sizeof(sop), "Src"); - break; - case PictOpOver: - snprintf(sop, sizeof(sop), "Over"); - break; - default: - snprintf(sop, sizeof(sop), "0x%x", (int) op); - break; - } - - exaCompositeFallbackPictDesc(pSrc, srcdesc, 40); - exaCompositeFallbackPictDesc(pMask, maskdesc, 40); - exaCompositeFallbackPictDesc(pDst, dstdesc, 40); - - ErrorF("Composite fallback: op %s, \n" - " src %s, \n" - " mask %s, \n" - " dst %s, \n", sop, srcdesc, maskdesc, dstdesc); -} -#endif /* DEBUG_TRACE_FALL */ - -Bool -exaOpReadsDestination(CARD8 op) -{ - /* FALSE (does not read destination) is the list of ops in the protocol - * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. - * That's just Clear and Src. ReduceCompositeOp() will already have - * converted con/disjoint clear/src to Clear or Src. - */ - switch (op) { - case PictOpClear: - case PictOpSrc: - return FALSE; - default: - return TRUE; - } -} - -static Bool -exaGetPixelFromRGBA(CARD32 *pixel, - CARD16 red, - CARD16 green, - CARD16 blue, CARD16 alpha, PictFormatPtr pFormat) -{ - int rbits, bbits, gbits, abits; - int rshift, bshift, gshift, ashift; - - *pixel = 0; - - if (!PICT_FORMAT_COLOR(pFormat->format) && - PICT_FORMAT_TYPE(pFormat->format) != PICT_TYPE_A) - return FALSE; - - rbits = PICT_FORMAT_R(pFormat->format); - gbits = PICT_FORMAT_G(pFormat->format); - bbits = PICT_FORMAT_B(pFormat->format); - abits = PICT_FORMAT_A(pFormat->format); - - rshift = pFormat->direct.red; - gshift = pFormat->direct.green; - bshift = pFormat->direct.blue; - ashift = pFormat->direct.alpha; - - *pixel |= (blue >> (16 - bbits)) << bshift; - *pixel |= (red >> (16 - rbits)) << rshift; - *pixel |= (green >> (16 - gbits)) << gshift; - *pixel |= (alpha >> (16 - abits)) << ashift; - - return TRUE; -} - -static Bool -exaGetRGBAFromPixel(CARD32 pixel, - CARD16 *red, - CARD16 *green, - CARD16 *blue, - CARD16 *alpha, - PictFormatPtr pFormat, PictFormatShort format) -{ - int rbits, bbits, gbits, abits; - int rshift, bshift, gshift, ashift; - - if (!PICT_FORMAT_COLOR(format) && PICT_FORMAT_TYPE(format) != PICT_TYPE_A) - return FALSE; - - rbits = PICT_FORMAT_R(format); - gbits = PICT_FORMAT_G(format); - bbits = PICT_FORMAT_B(format); - abits = PICT_FORMAT_A(format); - - if (pFormat) { - rshift = pFormat->direct.red; - gshift = pFormat->direct.green; - bshift = pFormat->direct.blue; - ashift = pFormat->direct.alpha; - } - else if (format == PICT_a8r8g8b8) { - rshift = 16; - gshift = 8; - bshift = 0; - ashift = 24; - } - else - FatalError("EXA bug: exaGetRGBAFromPixel() doesn't match " - "createSourcePicture()\n"); - - if (rbits) { - *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); - while (rbits < 16) { - *red |= *red >> rbits; - rbits <<= 1; - } - - *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); - while (gbits < 16) { - *green |= *green >> gbits; - gbits <<= 1; - } - - *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); - while (bbits < 16) { - *blue |= *blue >> bbits; - bbits <<= 1; - } - } - else { - *red = 0x0000; - *green = 0x0000; - *blue = 0x0000; - } - - if (abits) { - *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); - while (abits < 16) { - *alpha |= *alpha >> abits; - abits <<= 1; - } - } - else - *alpha = 0xffff; - - return TRUE; -} - -static int -exaTryDriverSolidFill(PicturePtr pSrc, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - ExaScreenPriv(pDst->pDrawable->pScreen); - RegionRec region; - BoxPtr pbox; - int nbox; - int dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pDstPix; - ExaPixmapPrivPtr pDstExaPix; - CARD32 pixel; - CARD16 red, green, blue, alpha; - - pDstPix = exaGetDrawablePixmap(pDst->pDrawable); - pDstExaPix = ExaGetPixmapPriv(pDstPix); - - /* Check whether the accelerator can use the destination pixmap. - */ - if (pDstExaPix->accel_blocked) { - return -1; - } - - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; - if (pSrc->pDrawable) { - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - } - - if (!miComputeCompositeRegion(®ion, pSrc, NULL, pDst, - xSrc, ySrc, 0, 0, xDst, yDst, width, height)) - return 1; - - exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); - - RegionTranslate(®ion, dst_off_x, dst_off_y); - - if (pSrc->pDrawable) { - pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); - pixel = exaGetPixmapFirstPixel(pSrcPix); - } - else - miRenderColorToPixel(PictureMatchFormat(pDst->pDrawable->pScreen, 32, - pSrc->format), - &pSrc->pSourcePict->solidFill.fullcolor, - &pixel); - - if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, - pSrc->pFormat, pSrc->format) || - !exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, pDst->pFormat)) { - RegionUninit(®ion); - return -1; - } - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[1]; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pDstPix; - pixmaps[0].pReg = ®ion; - exaDoMigration(pixmaps, 1, TRUE); - } - - if (!exaPixmapHasGpuCopy(pDstPix)) { - RegionUninit(®ion); - return 0; - } - - if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel)) { - RegionUninit(®ion); - return -1; - } - - nbox = RegionNumRects(®ion); - pbox = RegionRects(®ion); - - while (nbox--) { - (*pExaScr->info->Solid) (pDstPix, pbox->x1, pbox->y1, pbox->x2, - pbox->y2); - pbox++; - } - - (*pExaScr->info->DoneSolid) (pDstPix); - exaMarkSync(pDst->pDrawable->pScreen); - - RegionUninit(®ion); - return 1; -} - -static int -exaTryDriverCompositeRects(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - int nrect, ExaCompositeRectPtr rects) -{ - ExaScreenPriv(pDst->pDrawable->pScreen); - int src_off_x = 0, src_off_y = 0, mask_off_x = 0, mask_off_y = 0; - int dst_off_x, dst_off_y; - PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix; - ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix; - - if (!pExaScr->info->PrepareComposite) - return -1; - - if (pSrc->pDrawable) { - pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); - pSrcExaPix = ExaGetPixmapPriv(pSrcPix); - } - - if (pMask && pMask->pDrawable) { - pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); - pMaskExaPix = ExaGetPixmapPriv(pMaskPix); - } - - pDstPix = exaGetDrawablePixmap(pDst->pDrawable); - pDstExaPix = ExaGetPixmapPriv(pDstPix); - - /* Check whether the accelerator can use these pixmaps. - * FIXME: If it cannot, use temporary pixmaps so that the drawing - * happens within limits. - */ - if (pDstExaPix->accel_blocked || - (pSrcExaPix && pSrcExaPix->accel_blocked) || - (pMaskExaPix && pMaskExaPix->accel_blocked)) { - return -1; - } - - if (pExaScr->info->CheckComposite && - !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) { - return -1; - } - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[3]; - int i = 0; - - pixmaps[i].as_dst = TRUE; - pixmaps[i].as_src = exaOpReadsDestination(op); - pixmaps[i].pPix = pDstPix; - pixmaps[i].pReg = NULL; - i++; - - if (pSrcPix) { - pixmaps[i].as_dst = FALSE; - pixmaps[i].as_src = TRUE; - pixmaps[i].pPix = pSrcPix; - pixmaps[i].pReg = NULL; - i++; - } - - if (pMaskPix) { - pixmaps[i].as_dst = FALSE; - pixmaps[i].as_src = TRUE; - pixmaps[i].pPix = pMaskPix; - pixmaps[i].pReg = NULL; - i++; - } - - exaDoMigration(pixmaps, i, TRUE); - } - - pDstPix = exaGetOffscreenPixmap(pDst->pDrawable, &dst_off_x, &dst_off_y); - if (!pDstPix) - return 0; - - if (pSrcPix) { - pSrcPix = - exaGetOffscreenPixmap(pSrc->pDrawable, &src_off_x, &src_off_y); - if (!pSrcPix) - return 0; - } - - if (pMaskPix) { - pMaskPix = - exaGetOffscreenPixmap(pMask->pDrawable, &mask_off_x, &mask_off_y); - if (!pMaskPix) - return 0; - } - - if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix, - pMaskPix, pDstPix)) - return -1; - - while (nrect--) { - INT16 xDst = rects->xDst + pDst->pDrawable->x; - INT16 yDst = rects->yDst + pDst->pDrawable->y; - INT16 xMask = rects->xMask; - INT16 yMask = rects->yMask; - INT16 xSrc = rects->xSrc; - INT16 ySrc = rects->ySrc; - RegionRec region; - BoxPtr pbox; - int nbox; - - if (pMaskPix) { - xMask += pMask->pDrawable->x; - yMask += pMask->pDrawable->y; - } - - if (pSrcPix) { - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - } - - if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - rects->width, rects->height)) - goto next_rect; - - RegionTranslate(®ion, dst_off_x, dst_off_y); - - nbox = RegionNumRects(®ion); - pbox = RegionRects(®ion); - - xMask = xMask + mask_off_x - xDst - dst_off_x; - yMask = yMask + mask_off_y - yDst - dst_off_y; - xSrc = xSrc + src_off_x - xDst - dst_off_x; - ySrc = ySrc + src_off_y - yDst - dst_off_y; - - while (nbox--) { - (*pExaScr->info->Composite) (pDstPix, - pbox->x1 + xSrc, - pbox->y1 + ySrc, - pbox->x1 + xMask, - pbox->y1 + yMask, - pbox->x1, - pbox->y1, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - pbox++; - } - - next_rect: - RegionUninit(®ion); - - rects++; - } - - (*pExaScr->info->DoneComposite) (pDstPix); - exaMarkSync(pDst->pDrawable->pScreen); - - return 1; -} - -/** - * Copy a number of rectangles from source to destination in a single - * operation. This is specialized for glyph rendering: we don't have the - * special-case fallbacks found in exaComposite() - if the driver can support - * it, we use the driver functionality, otherwise we fall back straight to - * software. - */ -void -exaCompositeRects(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, int nrect, ExaCompositeRectPtr rects) -{ - ExaScreenPriv(pDst->pDrawable->pScreen); - int n; - ExaCompositeRectPtr r; - int ret; - - /* 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) { - RegionRec region; - int x1 = MAXSHORT; - int y1 = MAXSHORT; - int x2 = MINSHORT; - int y2 = MINSHORT; - BoxRec box; - - /* We have to manage the damage ourselves, since CompositeRects isn't - * something in the screen that can be managed by the damage extension, - * and EXA depends on damage to track what needs to be migrated between - * the gpu and the cpu. - */ - - /* Compute the overall extents of the composited region - we're making - * the assumption here that we are compositing a bunch of glyphs that - * cluster closely together and damaging each glyph individually would - * be a loss compared to damaging the bounding box. - */ - n = nrect; - r = rects; - while (n--) { - int rect_x2 = r->xDst + r->width; - int rect_y2 = r->yDst + r->height; - - if (r->xDst < x1) - x1 = r->xDst; - if (r->yDst < y1) - y1 = r->yDst; - if (rect_x2 > x2) - x2 = rect_x2; - if (rect_y2 > y2) - y2 = rect_y2; - - r++; - } - - if (x2 <= x1 || y2 <= y1) - return; - - box.x1 = x1; - box.x2 = x2 < MAXSHORT ? x2 : MAXSHORT; - box.y1 = y1; - box.y2 = y2 < MAXSHORT ? y2 : MAXSHORT; - - /* The pixmap migration code relies on pendingDamage indicating - * the bounds of the current rendering, so we need to force - * the actual damage into that region before we do anything, and - * (see use of DamagePendingRegion in exaCopyDirty) - */ - - RegionInit(®ion, &box, 1); - - DamageRegionAppend(pDst->pDrawable, ®ion); - - RegionUninit(®ion); - } - - /************************************************************/ - - ValidatePicture(pSrc); - if (pMask) - ValidatePicture(pMask); - ValidatePicture(pDst); - - ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, rects); - - if (ret != 1) { - if (ret == -1 && op == PictOpOver && pMask && pMask->componentAlpha && - (!pExaScr->info->CheckComposite || - ((*pExaScr->info->CheckComposite) (PictOpOutReverse, pSrc, pMask, - pDst) && - (*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, pMask, - pDst)))) { - ret = - exaTryDriverCompositeRects(PictOpOutReverse, pSrc, pMask, pDst, - nrect, rects); - if (ret == 1) { - op = PictOpAdd; - ret = exaTryDriverCompositeRects(op, pSrc, pMask, pDst, nrect, - rects); - } - } - - if (ret != 1) { - n = nrect; - r = rects; - while (n--) { - ExaCheckComposite(op, pSrc, pMask, pDst, - r->xSrc, r->ySrc, - r->xMask, r->yMask, - r->xDst, r->yDst, r->width, r->height); - r++; - } - } - } - - /************************************************************/ - - if (!pMask) { - /* Now we have to flush the damage out from pendingDamage => damage - * Calling DamageRegionProcessPending has that effect. - */ - - DamageRegionProcessPending(pDst->pDrawable); - } -} - -static int -exaTryDriverComposite(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - ExaScreenPriv(pDst->pDrawable->pScreen); - RegionRec region; - BoxPtr pbox; - int nbox; - int src_off_x, src_off_y, mask_off_x = 0, mask_off_y = 0, dst_off_x, dst_off_y; - PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix; - ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix; - - if (pSrc->pDrawable) { - pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); - pSrcExaPix = ExaGetPixmapPriv(pSrcPix); - } - - pDstPix = exaGetDrawablePixmap(pDst->pDrawable); - pDstExaPix = ExaGetPixmapPriv(pDstPix); - - if (pMask && pMask->pDrawable) { - pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); - pMaskExaPix = ExaGetPixmapPriv(pMaskPix); - } - - /* Check whether the accelerator can use these pixmaps. - * FIXME: If it cannot, use temporary pixmaps so that the drawing - * happens within limits. - */ - if (pDstExaPix->accel_blocked || - (pSrcExaPix && pSrcExaPix->accel_blocked) || - (pMaskExaPix && (pMaskExaPix->accel_blocked))) { - return -1; - } - - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; - - if (pMaskPix) { - xMask += pMask->pDrawable->x; - yMask += pMask->pDrawable->y; - } - - if (pSrcPix) { - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - } - - if (pExaScr->info->CheckComposite && - !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) { - return -1; - } - - if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height)) - return 1; - - exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &dst_off_x, &dst_off_y); - - RegionTranslate(®ion, dst_off_x, dst_off_y); - - if (pExaScr->do_migration) { - ExaMigrationRec pixmaps[3]; - int i = 0; - - pixmaps[i].as_dst = TRUE; - pixmaps[i].as_src = exaOpReadsDestination(op); - pixmaps[i].pPix = pDstPix; - pixmaps[i].pReg = pixmaps[0].as_src ? NULL : ®ion; - i++; - - if (pSrcPix) { - pixmaps[i].as_dst = FALSE; - pixmaps[i].as_src = TRUE; - pixmaps[i].pPix = pSrcPix; - pixmaps[i].pReg = NULL; - i++; - } - - if (pMaskPix) { - pixmaps[i].as_dst = FALSE; - pixmaps[i].as_src = TRUE; - pixmaps[i].pPix = pMaskPix; - pixmaps[i].pReg = NULL; - i++; - } - - exaDoMigration(pixmaps, i, TRUE); - } - - if (pSrcPix) { - pSrcPix = - exaGetOffscreenPixmap(pSrc->pDrawable, &src_off_x, &src_off_y); - if (!pSrcPix) { - RegionUninit(®ion); - return 0; - } - } - - if (pMaskPix) { - pMaskPix = exaGetOffscreenPixmap(pMask->pDrawable, &mask_off_x, - &mask_off_y); - if (!pMaskPix) { - RegionUninit(®ion); - return 0; - } - } - - if (!exaPixmapHasGpuCopy(pDstPix)) { - RegionUninit(®ion); - return 0; - } - - if (!(*pExaScr->info->PrepareComposite) (op, pSrc, pMask, pDst, pSrcPix, - pMaskPix, pDstPix)) { - RegionUninit(®ion); - return -1; - } - - nbox = RegionNumRects(®ion); - pbox = RegionRects(®ion); - - xMask = xMask + mask_off_x - xDst - dst_off_x; - yMask = yMask + mask_off_y - yDst - dst_off_y; - - xSrc = xSrc + src_off_x - xDst - dst_off_x; - ySrc = ySrc + src_off_y - yDst - dst_off_y; - - while (nbox--) { - (*pExaScr->info->Composite) (pDstPix, - pbox->x1 + xSrc, - pbox->y1 + ySrc, - pbox->x1 + xMask, - pbox->y1 + yMask, - pbox->x1, - pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - pbox++; - } - (*pExaScr->info->DoneComposite) (pDstPix); - exaMarkSync(pDst->pDrawable->pScreen); - - RegionUninit(®ion); - return 1; -} - -/** - * exaTryMagicTwoPassCompositeHelper implements PictOpOver using two passes of - * simpler operations PictOpOutReverse and PictOpAdd. Mainly used for component - * alpha and limited 1-tmu cards. - * - * From http://anholt.livejournal.com/32058.html: - * - * The trouble is that component-alpha rendering requires two different sources - * for blending: one for the source value to the blender, which is the - * per-channel multiplication of source and mask, and one for the source alpha - * for multiplying with the destination channels, which is the multiplication - * of the source channels by the mask alpha. So the equation for Over is: - * - * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A - * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R - * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G - * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B - * - * But we can do some simpler operations, right? How about PictOpOutReverse, - * which has a source factor of 0 and dest factor of (1 - source alpha). We - * can get the source alpha value (srca.X = src.A * mask.X) out of the texture - * blenders pretty easily. So we can do a component-alpha OutReverse, which - * gets us: - * - * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A - * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R - * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G - * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B - * - * OK. And if an op doesn't use the source alpha value for the destination - * factor, then we can do the channel multiplication in the texture blenders - * to get the source value, and ignore the source alpha that we wouldn't use. - * We've supported this in the Radeon driver for a long time. An example would - * be PictOpAdd, which does: - * - * dst.A = src.A * mask.A + dst.A - * dst.R = src.R * mask.R + dst.R - * dst.G = src.G * mask.G + dst.G - * dst.B = src.B * mask.B + dst.B - * - * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right - * after it, we get: - * - * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) - * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) - * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) - * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) - */ - -static int -exaTryMagicTwoPassCompositeHelper(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, CARD16 width, CARD16 height) -{ - ExaScreenPriv(pDst->pDrawable->pScreen); - - assert(op == PictOpOver); - - if (pExaScr->info->CheckComposite && - (!(*pExaScr->info->CheckComposite) (PictOpOutReverse, pSrc, pMask, - pDst) || - !(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, pMask, pDst))) { - return -1; - } - - /* Now, we think we should be able to accelerate this operation. First, - * composite the destination to be the destination times the source alpha - * factors. - */ - exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); - - /* Then, add in the source value times the destination alpha factors (1.0). - */ - exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); - - return 1; -} - -void -exaComposite(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - ExaScreenPriv(pDst->pDrawable->pScreen); - int ret = -1; - Bool saveSrcRepeat = pSrc->repeat; - Bool saveMaskRepeat = pMask ? pMask->repeat : 0; - RegionRec region; - - if (pExaScr->swappedOut) - goto fallback; - - /* Remove repeat in source if useless */ - if (pSrc->pDrawable && pSrc->repeat && !pSrc->transform && xSrc >= 0 && - (xSrc + width) <= pSrc->pDrawable->width && ySrc >= 0 && - (ySrc + height) <= pSrc->pDrawable->height) - pSrc->repeat = 0; - - if (!pMask && !pSrc->alphaMap && !pDst->alphaMap && - (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) - { - if (pSrc->pDrawable ? - (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 && - pSrc->repeat) : - (pSrc->pSourcePict->type == SourcePictTypeSolidFill)) { - ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst, - width, height); - if (ret == 1) - goto done; - } - else if (pSrc->pDrawable && !pSrc->transform && - ((op == PictOpSrc && - (pSrc->format == pDst->format || - (PICT_FORMAT_COLOR(pDst->format) && - PICT_FORMAT_COLOR(pSrc->format) && - pDst->format == PICT_FORMAT(PICT_FORMAT_BPP(pSrc->format), - PICT_FORMAT_TYPE(pSrc->format), - 0, - PICT_FORMAT_R(pSrc->format), - PICT_FORMAT_G(pSrc->format), - PICT_FORMAT_B(pSrc->format))))) - || (op == PictOpOver && pSrc->format == pDst->format && - !PICT_FORMAT_A(pSrc->format)))) { - if (!pSrc->repeat && xSrc >= 0 && ySrc >= 0 && - (xSrc + width <= pSrc->pDrawable->width) && - (ySrc + height <= pSrc->pDrawable->height)) { - Bool suc; - - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - - if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, - yDst, width, height)) - goto done; - - suc = exaHWCopyNtoN(pSrc->pDrawable, pDst->pDrawable, NULL, - RegionRects(®ion), - RegionNumRects(®ion), xSrc - xDst, - ySrc - yDst, FALSE, FALSE); - RegionUninit(®ion); - - /* Reset values to their original values. */ - xDst -= pDst->pDrawable->x; - yDst -= pDst->pDrawable->y; - xSrc -= pSrc->pDrawable->x; - ySrc -= pSrc->pDrawable->y; - - if (!suc) - goto fallback; - - goto done; - } - - if (pSrc->repeat && pSrc->repeatType == RepeatNormal && - pSrc->pDrawable->type == DRAWABLE_PIXMAP) { - DDXPointRec patOrg; - - /* Let's see if the driver can do the repeat in one go */ - if (pExaScr->info->PrepareComposite && !pSrc->alphaMap && - !pDst->alphaMap) { - ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, - ySrc, xMask, yMask, xDst, yDst, - width, height); - if (ret == 1) - goto done; - } - - /* Now see if we can use exaFillRegionTiled() */ - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - - if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, xSrc, - ySrc, xMask, yMask, xDst, yDst, - width, height)) - goto done; - - /* pattern origin is the point in the destination drawable - * corresponding to (0,0) in the source */ - patOrg.x = xDst - xSrc; - patOrg.y = yDst - ySrc; - - ret = exaFillRegionTiled(pDst->pDrawable, ®ion, - (PixmapPtr) pSrc->pDrawable, - &patOrg, FB_ALLONES, GXcopy, CT_NONE); - - RegionUninit(®ion); - - if (ret) - goto done; - - /* Let's be correct and restore the variables to their original state. */ - xDst -= pDst->pDrawable->x; - yDst -= pDst->pDrawable->y; - xSrc -= pSrc->pDrawable->x; - ySrc -= pSrc->pDrawable->y; - } - } - } - - /* Remove repeat in mask if useless */ - if (pMask && pMask->pDrawable && pMask->repeat && !pMask->transform && - xMask >= 0 && (xMask + width) <= pMask->pDrawable->width && - yMask >= 0 && (yMask + height) <= pMask->pDrawable->height) - pMask->repeat = 0; - - if (pExaScr->info->PrepareComposite && - !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) { - Bool isSrcSolid; - - ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, - yMask, xDst, yDst, width, height); - if (ret == 1) - goto done; - - /* For generic masks and solid src pictures, mach64 can do Over in two - * passes, similar to the component-alpha case. - */ - isSrcSolid = pSrc->pDrawable ? - (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 && - pSrc->repeat) : - (pSrc->pSourcePict->type == SourcePictTypeSolidFill); - - /* If we couldn't do the Composite in a single pass, and it was a - * component-alpha Over, see if we can do it in two passes with - * an OutReverse and then an Add. - */ - if (ret == -1 && op == PictOpOver && pMask && - (pMask->componentAlpha || isSrcSolid)) { - ret = exaTryMagicTwoPassCompositeHelper(op, pSrc, pMask, pDst, - xSrc, ySrc, - xMask, yMask, xDst, yDst, - width, height); - if (ret == 1) - goto done; - } - } - - fallback: -#if DEBUG_TRACE_FALL - exaPrintCompositeFallback(op, pSrc, pMask, pDst); -#endif - - ExaCheckComposite(op, pSrc, pMask, pDst, xSrc, ySrc, - xMask, yMask, xDst, yDst, width, height); - - done: - pSrc->repeat = saveSrcRepeat; - if (pMask) - pMask->repeat = saveMaskRepeat; -} - -/** - * Same as miCreateAlphaPicture, except it uses ExaCheckPolyFillRect instead - * of PolyFillRect to initialize the pixmap after creating it, to prevent - * the pixmap from being migrated. - * - * See the comments about exaTrapezoids and exaTriangles. - */ -static PicturePtr -exaCreateAlphaPicture(ScreenPtr pScreen, - PicturePtr pDst, - PictFormatPtr pPictFormat, CARD16 width, CARD16 height) -{ - PixmapPtr pPixmap; - PicturePtr pPicture; - GCPtr pGC; - int error; - xRectangle rect; - - if (width > 32767 || height > 32767) - return 0; - - if (!pPictFormat) { - if (pDst->polyEdge == PolyEdgeSharp) - pPictFormat = PictureMatchFormat(pScreen, 1, PICT_a1); - else - pPictFormat = PictureMatchFormat(pScreen, 8, PICT_a8); - if (!pPictFormat) - return 0; - } - - pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, - pPictFormat->depth, 0); - if (!pPixmap) - return 0; - pGC = GetScratchGC(pPixmap->drawable.depth, pScreen); - if (!pGC) { - (*pScreen->DestroyPixmap) (pPixmap); - return 0; - } - ValidateGC(&pPixmap->drawable, pGC); - rect.x = 0; - rect.y = 0; - rect.width = width; - rect.height = height; - ExaCheckPolyFillRect(&pPixmap->drawable, pGC, 1, &rect); - exaPixmapDirty(pPixmap, 0, 0, width, height); - FreeScratchGC(pGC); - pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat, - 0, 0, serverClient, &error); - (*pScreen->DestroyPixmap) (pPixmap); - return pPicture; -} - -/** - * exaTrapezoids is essentially a copy of miTrapezoids that uses - * exaCreateAlphaPicture instead of miCreateAlphaPicture. - * - * The problem with miCreateAlphaPicture is that it calls PolyFillRect - * to initialize the contents after creating the pixmap, which - * causes the pixmap to be moved in for acceleration. The subsequent - * call to RasterizeTrapezoid won't be accelerated however, which - * forces the pixmap to be moved out again. - * - * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect - * to initialize the contents. - */ -void -exaTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntrap, xTrapezoid * traps) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - BoxRec bounds; - - if (maskFormat) { - PicturePtr pPicture; - INT16 xDst, yDst; - INT16 xRel, yRel; - - miTrapezoidBounds(ntrap, traps, &bounds); - - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; - - xDst = traps[0].left.p1.x >> 16; - yDst = traps[0].left.p1.y >> 16; - - pPicture = exaCreateAlphaPicture(pScreen, pDst, maskFormat, - bounds.x2 - bounds.x1, - bounds.y2 - bounds.y1); - if (!pPicture) - return; - - exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - for (; ntrap; ntrap--, traps++) - if (xTrapezoidValid(traps)) - (*ps->RasterizeTrapezoid) (pPicture, traps, -bounds.x1, -bounds.y1); - exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - - xRel = bounds.x1 + xSrc - xDst; - yRel = bounds.y1 + ySrc - yDst; - CompositePicture(op, pSrc, pPicture, pDst, - xRel, yRel, 0, 0, bounds.x1, bounds.y1, - bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); - FreePicture(pPicture, 0); - } - else { - if (pDst->polyEdge == PolyEdgeSharp) - maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); - else - maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); - for (; ntrap; ntrap--, traps++) - exaTrapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps); - } -} - -/** - * exaTriangles is essentially a copy of miTriangles that uses - * exaCreateAlphaPicture instead of miCreateAlphaPicture. - * - * The problem with miCreateAlphaPicture is that it calls PolyFillRect - * to initialize the contents after creating the pixmap, which - * causes the pixmap to be moved in for acceleration. The subsequent - * call to AddTriangles won't be accelerated however, which forces the pixmap - * to be moved out again. - * - * exaCreateAlphaPicture avoids this roundtrip by using ExaCheckPolyFillRect - * to initialize the contents. - */ -void -exaTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int ntri, xTriangle * tris) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - BoxRec bounds; - - if (maskFormat) { - PicturePtr pPicture; - INT16 xDst, yDst; - INT16 xRel, yRel; - - miTriangleBounds(ntri, tris, &bounds); - - if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2) - return; - - xDst = tris[0].p1.x >> 16; - yDst = tris[0].p1.y >> 16; - - pPicture = exaCreateAlphaPicture(pScreen, pDst, maskFormat, - bounds.x2 - bounds.x1, - bounds.y2 - bounds.y1); - if (!pPicture) - return; - - exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - (*ps->AddTriangles) (pPicture, -bounds.x1, -bounds.y1, ntri, tris); - exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - - xRel = bounds.x1 + xSrc - xDst; - yRel = bounds.y1 + ySrc - yDst; - CompositePicture(op, pSrc, pPicture, pDst, - xRel, yRel, 0, 0, bounds.x1, bounds.y1, - bounds.x2 - bounds.x1, bounds.y2 - bounds.y1); - FreePicture(pPicture, 0); - } - else { - if (pDst->polyEdge == PolyEdgeSharp) - maskFormat = PictureMatchFormat(pScreen, 1, PICT_a1); - else - maskFormat = PictureMatchFormat(pScreen, 8, PICT_a8); - - for (; ntri; ntri--, tris++) - exaTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, tris); - } -} diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c deleted file mode 100644 index ed1401a98..000000000 --- a/exa/exa_unaccel.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * - * Copyright © 1999 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include "exa_priv.h" - -#include "mipict.h" - -/* - * These functions wrap the low-level fb rendering functions and - * synchronize framebuffer/accelerated drawing by stalling until - * the accelerator is idle - */ - -/** - * Calls exaPrepareAccess with EXA_PREPARE_SRC for the tile, if that is the - * current fill style. - * - * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are - * 1bpp and never in fb, so we don't worry about them. - * We should worry about them for completeness sake and going forward. - */ -void -exaPrepareAccessGC(GCPtr pGC) -{ - if (pGC->stipple) - exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); - if (pGC->fillStyle == FillTiled) - exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); -} - -/** - * Finishes access to the tile in the GC, if used. - */ -void -exaFinishAccessGC(GCPtr pGC) -{ - if (pGC->fillStyle == FillTiled) - exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); - if (pGC->stipple) - exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); -} - -#if DEBUG_TRACE_FALL -char -exaDrawableLocation(DrawablePtr pDrawable) -{ - return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm'; -} -#endif /* DEBUG_TRACE_FALL */ - -void -ExaCheckFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nspans, - DDXPointPtr ppt, int *pwidth, int fSorted) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, - DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, - int x, int y, int w, int h, int leftPad, int format, - char *bits) -{ - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - ExaPixmapPriv(pPixmap); - - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage || - exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, - pGC->alu, pGC->clientClip != NULL)) - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - else - 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_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, - Bool upsidedown, Pixel bitplane, void *closure) -{ - RegionRec reg; - int xoff, yoff; - - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, - exaDrawableLocation(pSrc), exaDrawableLocation(pDst))); - - if (pExaScr->prepare_access_reg && RegionInitBoxes(®, pbox, nbox)) { - PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc); - - exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff); - RegionTranslate(®, xoff + dx, yoff + dy); - pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, ®); - RegionUninit(®); - } - else - exaPrepareAccess(pSrc, EXA_PREPARE_SRC); - - if (pExaScr->prepare_access_reg && - !exaGCReadsDestination(pDst, pGC->planemask, pGC->fillStyle, - pGC->alu, pGC->clientClip != NULL) && - RegionInitBoxes(®, pbox, nbox)) { - PixmapPtr pPixmap = exaGetDrawablePixmap(pDst); - - exaGetDrawableDeltas(pDst, pPixmap, &xoff, &yoff); - RegionTranslate(®, xoff, yoff); - pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, ®); - RegionUninit(®); - } - else - exaPrepareAccess(pDst, EXA_PREPARE_DEST); - - /* This will eventually call fbCopyNtoN, with some calculation overhead. */ - while (nbox--) { - pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx, - pbox->y1 - pSrc->y + dy, pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1, pbox->x1 - pDst->x, - pbox->y1 - pDst->y); - pbox++; - } - exaFinishAccess(pSrc, EXA_PREPARE_SRC); - exaFinishAccess(pDst, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -static void -ExaFallbackPrepareReg(DrawablePtr pDrawable, - GCPtr pGC, - int x, int y, int width, int height, - int index, Bool checkReads) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - ExaScreenPriv(pScreen); - - if (pExaScr->prepare_access_reg && - !(checkReads && exaGCReadsDestination(pDrawable, pGC->planemask, - pGC->fillStyle, pGC->alu, - pGC->clientClip != NULL))) { - BoxRec box; - RegionRec reg; - int xoff, yoff; - PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); - - exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); - box.x1 = pDrawable->x + x + xoff; - box.y1 = pDrawable->y + y + yoff; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - - RegionInit(®, &box, 1); - pExaScr->prepare_access_reg(pPixmap, index, ®); - RegionUninit(®); - } - else - exaPrepareAccess(pDrawable, index); -} - -RegionPtr -ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty) -{ - RegionPtr ret; - - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, - exaDrawableLocation(pSrc), exaDrawableLocation(pDst))); - ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE); - ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE); - ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); - exaFinishAccess(pSrc, EXA_PREPARE_SRC); - exaFinishAccess(pDst, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); - - return ret; -} - -RegionPtr -ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int w, int h, int dstx, int dsty, - unsigned long bitPlane) -{ - RegionPtr ret; - - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst, - exaDrawableLocation(pSrc), exaDrawableLocation(pDst))); - ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE); - ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE); - ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, - bitPlane); - exaFinishAccess(pSrc, EXA_PREPARE_SRC); - exaFinishAccess(pDst, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); - - return ret; -} - -void -ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, - DDXPointPtr pptInit) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC, - int mode, int npt, DDXPointPtr ppt) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n", - pDrawable, exaDrawableLocation(pDrawable), - pGC->lineWidth, mode, npt)); - - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC, - int nsegInit, xSegment * pSegInit) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable, - exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit)); - - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, - int nrect, xRectangle *prect) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr * ppci, void *pglyphBase) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr * ppci, void *pglyphBase) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable, - exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu)); - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC(pGC); - pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); - exaFinishAccessGC(pGC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckPushPixels(GCPtr pGC, PixmapPtr pBitmap, - DrawablePtr pDrawable, int w, int h, int x, int y) -{ - EXA_PRE_FALLBACK_GC(pGC); - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable, - exaDrawableLocation(&pBitmap->drawable), - exaDrawableLocation(pDrawable))); - ExaFallbackPrepareReg(pDrawable, pGC, x, y, w, h, EXA_PREPARE_DEST, TRUE); - ExaFallbackPrepareReg(&pBitmap->drawable, pGC, 0, 0, w, h, - EXA_PREPARE_SRC, FALSE); - exaPrepareAccessGC(pGC); - pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y); - exaFinishAccessGC(pGC); - exaFinishAccess(&pBitmap->drawable, EXA_PREPARE_SRC); - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK_GC(pGC); -} - -void -ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - DrawablePtr pDrawable = &pWin->drawable; - ScreenPtr pScreen = pDrawable->pScreen; - - EXA_PRE_FALLBACK(pScreen); - EXA_FALLBACK(("from %p\n", pWin)); - - /* Only need the source bits, the destination region will be overwritten */ - if (pExaScr->prepare_access_reg) { - PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin); - int xoff, yoff; - - exaGetDrawableDeltas(&pWin->drawable, pPixmap, &xoff, &yoff); - RegionTranslate(prgnSrc, xoff, yoff); - pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, prgnSrc); - RegionTranslate(prgnSrc, -xoff, -yoff); - } - else - exaPrepareAccess(pDrawable, EXA_PREPARE_SRC); - - swap(pExaScr, pScreen, CopyWindow); - pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc); - swap(pExaScr, pScreen, CopyWindow); - exaFinishAccess(pDrawable, EXA_PREPARE_SRC); - EXA_POST_FALLBACK(pScreen); -} - -void -ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, - unsigned int format, unsigned long planeMask, char *d) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - EXA_PRE_FALLBACK(pScreen); - EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - - ExaFallbackPrepareReg(pDrawable, NULL, x, y, w, h, EXA_PREPARE_SRC, FALSE); - swap(pExaScr, pScreen, GetImage); - pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d); - swap(pExaScr, pScreen, GetImage); - exaFinishAccess(pDrawable, EXA_PREPARE_SRC); - EXA_POST_FALLBACK(pScreen); -} - -void -ExaCheckGetSpans(DrawablePtr pDrawable, - int wMax, - DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - EXA_PRE_FALLBACK(pScreen); - EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - exaPrepareAccess(pDrawable, EXA_PREPARE_SRC); - swap(pExaScr, pScreen, GetSpans); - pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); - swap(pExaScr, pScreen, GetSpans); - exaFinishAccess(pDrawable, EXA_PREPARE_SRC); - EXA_POST_FALLBACK(pScreen); -} - -static void -ExaSrcValidate(DrawablePtr pDrawable, - int x, int y, int width, int height, unsigned int subWindowMode) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - ExaScreenPriv(pScreen); - PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); - BoxRec box; - RegionRec reg; - RegionPtr dst; - int xoff, yoff; - - if (pExaScr->srcPix == pPix) - dst = &pExaScr->srcReg; - else if (pExaScr->maskPix == pPix) - dst = &pExaScr->maskReg; - else - return; - - exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff); - - box.x1 = x + xoff; - box.y1 = y + yoff; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - - RegionInit(®, &box, 1); - RegionUnion(dst, dst, ®); - RegionUninit(®); - - swap(pExaScr, pScreen, SourceValidate); - pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode); - swap(pExaScr, pScreen, SourceValidate); -} - -static Bool -ExaPrepareCompositeReg(ScreenPtr pScreen, - CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - RegionRec region; - RegionPtr dstReg = NULL; - RegionPtr srcReg = NULL; - RegionPtr maskReg = NULL; - PixmapPtr pSrcPix = NULL; - PixmapPtr pMaskPix = NULL; - PixmapPtr pDstPix; - - ExaScreenPriv(pScreen); - Bool ret; - - RegionNull(®ion); - - if (pSrc->pDrawable) { - pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); - RegionNull(&pExaScr->srcReg); - srcReg = &pExaScr->srcReg; - pExaScr->srcPix = pSrcPix; - if (pSrc != pDst) - RegionTranslate(pSrc->pCompositeClip, - -pSrc->pDrawable->x, -pSrc->pDrawable->y); - } else - pExaScr->srcPix = NULL; - - if (pMask && pMask->pDrawable) { - pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); - RegionNull(&pExaScr->maskReg); - maskReg = &pExaScr->maskReg; - pExaScr->maskPix = pMaskPix; - if (pMask != pDst && pMask != pSrc) - RegionTranslate(pMask->pCompositeClip, - -pMask->pDrawable->x, -pMask->pDrawable->y); - } else - pExaScr->maskPix = NULL; - - RegionTranslate(pDst->pCompositeClip, - -pDst->pDrawable->x, -pDst->pDrawable->y); - - pExaScr->SavedSourceValidate = ExaSrcValidate; - swap(pExaScr, pScreen, SourceValidate); - ret = miComputeCompositeRegion(®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); - swap(pExaScr, pScreen, SourceValidate); - - RegionTranslate(pDst->pCompositeClip, - pDst->pDrawable->x, pDst->pDrawable->y); - if (pSrc->pDrawable && pSrc != pDst) - RegionTranslate(pSrc->pCompositeClip, - pSrc->pDrawable->x, pSrc->pDrawable->y); - if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc) - RegionTranslate(pMask->pCompositeClip, - pMask->pDrawable->x, pMask->pDrawable->y); - - if (!ret) { - if (srcReg) - RegionUninit(srcReg); - if (maskReg) - RegionUninit(maskReg); - - return FALSE; - } - - /** - * Don't limit alphamaps readbacks for now until we've figured out how that - * should be done. - */ - - if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) - pExaScr-> - prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable), - EXA_PREPARE_AUX_SRC, NULL); - if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) - pExaScr-> - prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable), - EXA_PREPARE_AUX_MASK, NULL); - - if (pSrcPix) - pExaScr->prepare_access_reg(pSrcPix, EXA_PREPARE_SRC, srcReg); - - if (pMaskPix) - pExaScr->prepare_access_reg(pMaskPix, EXA_PREPARE_MASK, maskReg); - - if (srcReg) - RegionUninit(srcReg); - if (maskReg) - RegionUninit(maskReg); - - pDstPix = exaGetDrawablePixmap(pDst->pDrawable); - if (!exaOpReadsDestination(op)) { - int xoff; - int yoff; - - exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &xoff, &yoff); - RegionTranslate(®ion, pDst->pDrawable->x + xoff, - pDst->pDrawable->y + yoff); - dstReg = ®ion; - } - - if (pDst->alphaMap && pDst->alphaMap->pDrawable) - pExaScr-> - prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable), - EXA_PREPARE_AUX_DEST, dstReg); - pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg); - - RegionUninit(®ion); - return TRUE; -} - -void -ExaCheckComposite(CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - EXA_PRE_FALLBACK(pScreen); - - if (pExaScr->prepare_access_reg) { - if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc, - ySrc, xMask, yMask, xDst, yDst, width, - height)) - goto out_no_clip; - } - else { - - /* We need to prepare access to any separate alpha maps first, - * in case the driver doesn't support EXA_PREPARE_AUX*, - * in which case EXA_PREPARE_SRC may be used for moving them out. - */ - - if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) - exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC); - if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) - exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK); - if (pDst->alphaMap && pDst->alphaMap->pDrawable) - exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST); - - exaPrepareAccess(pDst->pDrawable, EXA_PREPARE_DEST); - - EXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst)); - - if (pSrc->pDrawable != NULL) - exaPrepareAccess(pSrc->pDrawable, EXA_PREPARE_SRC); - if (pMask && pMask->pDrawable != NULL) - exaPrepareAccess(pMask->pDrawable, EXA_PREPARE_MASK); - } - - swap(pExaScr, ps, Composite); - ps->Composite(op, - pSrc, - pMask, - pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); - swap(pExaScr, ps, Composite); - if (pMask && pMask->pDrawable != NULL) - exaFinishAccess(pMask->pDrawable, EXA_PREPARE_MASK); - if (pSrc->pDrawable != NULL) - exaFinishAccess(pSrc->pDrawable, EXA_PREPARE_SRC); - exaFinishAccess(pDst->pDrawable, EXA_PREPARE_DEST); - if (pDst->alphaMap && pDst->alphaMap->pDrawable) - exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST); - if (pSrc->alphaMap && pSrc->alphaMap->pDrawable) - exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC); - if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) - exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK); - - out_no_clip: - EXA_POST_FALLBACK(pScreen); -} - -/** - * Avoid migration ping-pong when using a mask. - */ -void -ExaCheckGlyphs(CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - - EXA_PRE_FALLBACK(pScreen); - - miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); - - EXA_POST_FALLBACK(pScreen); -} - -void -ExaCheckAddTraps(PicturePtr pPicture, - INT16 x_off, INT16 y_off, int ntrap, xTrap * traps) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - EXA_PRE_FALLBACK(pScreen); - - EXA_FALLBACK(("to pict %p (%c)\n", pPicture, - exaDrawableLocation(pPicture->pDrawable))); - exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - swap(pExaScr, ps, AddTraps); - ps->AddTraps(pPicture, x_off, y_off, ntrap, traps); - swap(pExaScr, ps, AddTraps); - exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST); - EXA_POST_FALLBACK(pScreen); -} - -/** - * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps - * that happen to be 1x1. Pixmap must be at least 8bpp. - */ -CARD32 -exaGetPixmapFirstPixel(PixmapPtr pPixmap) -{ - switch (pPixmap->drawable.bitsPerPixel) { - case 32: - { - CARD32 pixel; - - pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1, - ZPixmap, ~0, (char *) &pixel); - return pixel; - } - case 16: - { - CARD16 pixel; - - pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1, - ZPixmap, ~0, (char *) &pixel); - return pixel; - } - case 8: - case 4: - case 1: - { - CARD8 pixel; - - pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1, - ZPixmap, ~0, (char *) &pixel); - return pixel; - } - default: - FatalError("%s called for invalid bpp %d\n", __func__, - pPixmap->drawable.bitsPerPixel); - } -} diff --git a/exa/meson.build b/exa/meson.build deleted file mode 100644 index a3b7aea8c..000000000 --- a/exa/meson.build +++ /dev/null @@ -1,19 +0,0 @@ -srcs_exa = [ - 'exa.c', - 'exa_classic.c', - 'exa_migration_classic.c', - 'exa_driver.c', - 'exa_mixed.c', - 'exa_migration_mixed.c', - 'exa_accel.c', - 'exa_glyphs.c', - 'exa_offscreen.c', - 'exa_render.c', - 'exa_unaccel.c', -] - -libxserver_exa = static_library('libxserver_exa', - srcs_exa, - include_directories: inc, - dependencies: common_dep, -) diff --git a/meson.build b/meson.build index 16c87a1a8..fab53d947 100644 --- a/meson.build +++ b/meson.build @@ -413,7 +413,6 @@ inc = include_directories( 'Xi', 'composite', 'damageext', - 'exa', 'fb', 'glamor', 'mi', |