diff options
Diffstat (limited to 'xorg-server/exa')
-rw-r--r-- | xorg-server/exa/Makefile.in | 41 | ||||
-rw-r--r-- | xorg-server/exa/exa_accel.c | 2585 | ||||
-rw-r--r-- | xorg-server/exa/exa_migration.c | 700 | ||||
-rw-r--r-- | xorg-server/exa/exa_migration_classic.c | 10 | ||||
-rw-r--r-- | xorg-server/exa/exa_render.c | 383 | ||||
-rw-r--r-- | xorg-server/exa/makefile | 14 |
6 files changed, 1540 insertions, 2193 deletions
diff --git a/xorg-server/exa/Makefile.in b/xorg-server/exa/Makefile.in index 5826ae817..458351a74 100644 --- a/xorg-server/exa/Makefile.in +++ b/xorg-server/exa/Makefile.in @@ -63,16 +63,31 @@ am_libexa_la_OBJECTS = exa.lo exa_classic.lo exa_migration_classic.lo \ exa_driver.lo exa_mixed.lo exa_migration_mixed.lo exa_accel.lo \ exa_glyphs.lo exa_offscreen.lo exa_render.lo exa_unaccel.lo libexa_la_OBJECTS = $(am_libexa_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libexa_la_SOURCES) DIST_SOURCES = $(libexa_la_SOURCES) am__sdk_HEADERS_DIST = exa.h @@ -107,9 +122,9 @@ ADMIN_MAN_DIR = @ADMIN_MAN_DIR@ ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_MAKEFLAGS = @AM_MAKEFLAGS@ APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ -APPLE_APPLICATION_ID = @APPLE_APPLICATION_ID@ APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ APP_MAN_DIR = @APP_MAN_DIR@ APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ @@ -198,6 +213,7 @@ KDRIVE_LIBS = @KDRIVE_LIBS@ KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@ KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@ KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@ +LAUNCHD_ID_PREFIX = @LAUNCHD_ID_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@ @@ -462,7 +478,7 @@ clean-noinstLTLIBRARIES: rm -f "$${dir}/so_locations"; \ done libexa.la: $(libexa_la_OBJECTS) $(libexa_la_DEPENDENCIES) - $(LINK) $(libexa_la_OBJECTS) $(libexa_la_LIBADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(libexa_la_OBJECTS) $(libexa_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -483,22 +499,25 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exa_unaccel.Plo@am__quote@ .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< diff --git a/xorg-server/exa/exa_accel.c b/xorg-server/exa/exa_accel.c index f83a69b35..8f136218f 100644 --- a/xorg-server/exa/exa_accel.c +++ b/xorg-server/exa/exa_accel.c @@ -1,1292 +1,1293 @@ -/* - * 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->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 = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (pClip); - if (nbox == 1) - { - (*pExaScr->info->Solid) (pPixmap, - fullX1 + off_x, fullY1 + off_y, - fullX2 + off_x, fullY1 + 1 + off_y); - } - else - { - pbox = REGION_RECTS(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 (pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen) - 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 = REGION_NUM_RECTS(pClip), - pbox = REGION_RECTS(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 = xalloc(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 miRegionCopy() 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 = RECTS_TO_REGION(pScreen, nbox, rects, ordering); - xfree(rects); - - if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, - pGC->fillStyle, pGC->alu, - pGC->clientClipType)) { - dstregion = REGION_CREATE(pScreen, NullBox, 0); - REGION_COPY(pScreen, dstregion, srcregion); - REGION_TRANSLATE(pScreen, 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 (exaPixmapIsOffscreen(pDstPixmap)) { - /* Normal blitting. */ - if (exaPixmapIsOffscreen(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. */ - } else { - 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; - - goto out; - -fallback: - ret = FALSE; - -out: - if (dstregion) { - REGION_UNINIT(pScreen, dstregion); - REGION_DESTROY(pScreen, dstregion); - } - if (srcregion) { - REGION_UNINIT(pScreen, srcregion); - REGION_DESTROY(pScreen, 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_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->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) -{ - int i; - xRectangle *prect; - - /* If we can't reuse the current GC as is, don't bother accelerating the - * points. - */ - if (pGC->fillStyle != FillSolid) { - ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); - return; - } - - prect = xalloc(sizeof(xRectangle) * npt); - 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); - xfree(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) -{ - xRectangle *prect; - int x1, x2, y1, y2; - int i; - - /* 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 = xalloc(sizeof(xRectangle) * (npt - 1)); - 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) { - xfree(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); - xfree(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) -{ - xRectangle *prect; - int i; - - /* Don't try to do wide lines or non-solid fill style. */ - if (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 = xalloc(sizeof(xRectangle) * nseg); - 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); - xfree(prect); -} - -static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, - Pixel pixel, CARD32 planemask, CARD32 alu, - unsigned int clientClipType); - -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 = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); - - /* Compute intersection of rects and clip region */ - REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); - REGION_INTERSECT(pScreen, pReg, pClip, pReg); - - if (!REGION_NUM_RECTS(pReg)) { - goto out; - } - - exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); - - if (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->clientClipType)) || - (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && - exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, - pGC->planemask, pGC->alu, - pGC->clientClipType))) { - 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 (!exaPixmapIsOffscreen (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 = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (pClip); - if (n == 1) - { - (*pExaScr->info->Solid) (pPixmap, - fullX1 + xoff, fullY1 + yoff, - fullX2 + xoff, fullY2 + yoff); - } - else - { - pbox = REGION_RECTS(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: - REGION_UNINIT(pScreen, pReg); - REGION_DESTROY(pScreen, 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; - REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); - - REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); - - REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); -#ifdef COMPOSITE - if (pPixmap->screen_x || pPixmap->screen_y) - REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, - -pPixmap->screen_x, -pPixmap->screen_y); -#endif - - pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW; - miCopyRegion (&pPixmap->drawable, &pPixmap->drawable, - NULL, - &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); - pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW; - - REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); - - if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) { - pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW; - REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy); - ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc); - } -} - -static Bool -exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, - CARD32 planemask, CARD32 alu, unsigned int clientClipType) -{ - ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); - ExaPixmapPriv (pPixmap); - int xoff, yoff; - Bool ret = FALSE; - - exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); - REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); - - if (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, clientClipType) ? NULL : pRegion; - - exaDoMigration (pixmaps, 1, TRUE); - } - - if (exaPixmapIsOffscreen (pPixmap) && - (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) - { - int nbox; - BoxPtr pBox; - - nbox = REGION_NUM_RECTS (pRegion); - pBox = REGION_RECTS (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 && - pDrawable->width == 1 && pDrawable->height == 1 && - pDrawable->bitsPerPixel != 24) { - ExaPixmapPriv(pPixmap); - - switch (pDrawable->bitsPerPixel) { - case 32: - *(CARD32*)pExaPixmap->sys_ptr = pixel; - break; - case 16: - *(CARD16*)pExaPixmap->sys_ptr = pixel; - break; - case 8: - *(CARD8*)pExaPixmap->sys_ptr = pixel; - } - - REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, - pRegion); - } - - ret = TRUE; - } - -out: - REGION_TRANSLATE(pScreen, 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, - unsigned int clientClipType) -{ - ExaScreenPriv(pDrawable->pScreen); - PixmapPtr pPixmap; - ExaPixmapPrivPtr pExaPixmap; - ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); - int xoff, yoff; - int tileWidth, tileHeight; - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (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, clientClipType); - - pPixmap = exaGetDrawablePixmap (pDrawable); - pExaPixmap = ExaGetPixmapPriv (pPixmap); - - if (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, clientClipType) ? 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 || !exaPixmapIsOffscreen(pTile)) - return FALSE; - - if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) - { - if (xoff || yoff) - REGION_TRANSLATE(pScreen, 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) - REGION_TRANSLATE(pScreen, 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); - int xoff, yoff; - Bool ok; - - if (pExaScr->swappedOut) - goto fallback; - - exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff); - - if (pExaScr->do_migration) { - BoxRec Box; - RegionRec Reg; - ExaMigrationRec pixmaps[1]; - - Box.x1 = pDrawable->y + x + xoff; - Box.y1 = pDrawable->y + y + yoff; - Box.x2 = Box.x1 + w; - Box.y2 = Box.y1 + h; - - REGION_INIT(pScreen, &Reg, &Box, 1); - - pixmaps[0].as_dst = FALSE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = pPix; - pixmaps[0].pReg = &Reg; - - exaDoMigration(pixmaps, 1, FALSE); - - REGION_UNINIT(pScreen, &Reg); - } - - 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); -} +/*
+ * 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->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 = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (pClip);
+ if (nbox == 1)
+ {
+ (*pExaScr->info->Solid) (pPixmap,
+ fullX1 + off_x, fullY1 + off_y,
+ fullX2 + off_x, fullY1 + 1 + off_y);
+ }
+ else
+ {
+ pbox = REGION_RECTS(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 (pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen)
+ 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 = REGION_NUM_RECTS(pClip),
+ pbox = REGION_RECTS(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 = xalloc(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 miRegionCopy() 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 = RECTS_TO_REGION(pScreen, nbox, rects, ordering);
+ xfree(rects);
+
+ if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask,
+ pGC->fillStyle, pGC->alu,
+ pGC->clientClipType)) {
+ dstregion = REGION_CREATE(pScreen, NullBox, 0);
+ REGION_COPY(pScreen, dstregion, srcregion);
+ REGION_TRANSLATE(pScreen, 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 (exaPixmapIsOffscreen(pDstPixmap)) {
+ /* Normal blitting. */
+ if (exaPixmapIsOffscreen(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. */
+ } else {
+ 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;
+
+ goto out;
+
+fallback:
+ ret = FALSE;
+
+out:
+ if (dstregion) {
+ REGION_UNINIT(pScreen, dstregion);
+ REGION_DESTROY(pScreen, dstregion);
+ }
+ if (srcregion) {
+ REGION_UNINIT(pScreen, srcregion);
+ REGION_DESTROY(pScreen, 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_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->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)
+{
+ int i;
+ xRectangle *prect;
+
+ /* If we can't reuse the current GC as is, don't bother accelerating the
+ * points.
+ */
+ if (pGC->fillStyle != FillSolid) {
+ ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = xalloc(sizeof(xRectangle) * npt);
+ 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);
+ xfree(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)
+{
+ xRectangle *prect;
+ int x1, x2, y1, y2;
+ int i;
+
+ /* 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 = xalloc(sizeof(xRectangle) * (npt - 1));
+ 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) {
+ xfree(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);
+ xfree(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)
+{
+ xRectangle *prect;
+ int i;
+
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (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 = xalloc(sizeof(xRectangle) * nseg);
+ 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);
+ xfree(prect);
+}
+
+static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion,
+ Pixel pixel, CARD32 planemask, CARD32 alu,
+ unsigned int clientClipType);
+
+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 = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
+
+ /* Compute intersection of rects and clip region */
+ REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y);
+ REGION_INTERSECT(pScreen, pReg, pClip, pReg);
+
+ if (!REGION_NUM_RECTS(pReg)) {
+ goto out;
+ }
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+
+ if (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->clientClipType)) ||
+ (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
+ exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
+ pGC->planemask, pGC->alu,
+ pGC->clientClipType))) {
+ 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 (!exaPixmapIsOffscreen (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 = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (pClip);
+ if (n == 1)
+ {
+ (*pExaScr->info->Solid) (pPixmap,
+ fullX1 + xoff, fullY1 + yoff,
+ fullX2 + xoff, fullY2 + yoff);
+ }
+ else
+ {
+ pbox = REGION_RECTS(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:
+ REGION_UNINIT(pScreen, pReg);
+ REGION_DESTROY(pScreen, 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;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+#ifdef COMPOSITE
+ if (pPixmap->screen_x || pPixmap->screen_y)
+ REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+#endif
+
+ pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW;
+ miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+ NULL,
+ &rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
+ pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW;
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) {
+ pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy);
+ ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc);
+ }
+}
+
+static Bool
+exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
+ CARD32 planemask, CARD32 alu, unsigned int clientClipType)
+{
+ ExaScreenPriv(pDrawable->pScreen);
+ PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv (pPixmap);
+ int xoff, yoff;
+ Bool ret = FALSE;
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
+
+ if (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, clientClipType) ? NULL : pRegion;
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
+
+ if (exaPixmapIsOffscreen (pPixmap) &&
+ (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
+ {
+ int nbox;
+ BoxPtr pBox;
+
+ nbox = REGION_NUM_RECTS (pRegion);
+ pBox = REGION_RECTS (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) {
+ ExaPixmapPriv(pPixmap);
+
+ switch (pDrawable->bitsPerPixel) {
+ case 32:
+ *(CARD32*)pExaPixmap->sys_ptr = pixel;
+ break;
+ case 16:
+ *(CARD16*)pExaPixmap->sys_ptr = pixel;
+ break;
+ case 8:
+ *(CARD8*)pExaPixmap->sys_ptr = pixel;
+ }
+
+ REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
+ pRegion);
+ }
+
+ ret = TRUE;
+ }
+
+out:
+ REGION_TRANSLATE(pScreen, 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,
+ unsigned int clientClipType)
+{
+ ExaScreenPriv(pDrawable->pScreen);
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
+ int xoff, yoff;
+ int tileWidth, tileHeight;
+ int nbox = REGION_NUM_RECTS (pRegion);
+ BoxPtr pBox = REGION_RECTS (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, clientClipType);
+
+ pPixmap = exaGetDrawablePixmap (pDrawable);
+ pExaPixmap = ExaGetPixmapPriv (pPixmap);
+
+ if (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, clientClipType) ? 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 || !exaPixmapIsOffscreen(pTile))
+ return FALSE;
+
+ if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
+ {
+ if (xoff || yoff)
+ REGION_TRANSLATE(pScreen, 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)
+ REGION_TRANSLATE(pScreen, 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);
+ int xoff, yoff;
+ Bool ok;
+
+ if (pExaScr->swappedOut)
+ goto fallback;
+
+ exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff);
+
+ if (pExaScr->do_migration) {
+ BoxRec Box;
+ RegionRec Reg;
+ ExaMigrationRec pixmaps[1];
+
+ Box.x1 = pDrawable->y + x + xoff;
+ Box.y1 = pDrawable->y + y + yoff;
+ Box.x2 = Box.x1 + w;
+ Box.y2 = Box.y1 + h;
+
+ REGION_INIT(pScreen, &Reg, &Box, 1);
+
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPix;
+ pixmaps[0].pReg = &Reg;
+
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ REGION_UNINIT(pScreen, &Reg);
+ }
+
+ 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/xorg-server/exa/exa_migration.c b/xorg-server/exa/exa_migration.c deleted file mode 100644 index 17dd87e4c..000000000 --- a/xorg-server/exa/exa_migration.c +++ /dev/null @@ -1,700 +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 - -/** - * Returns TRUE if the pixmap is not movable. This is the case where it's a - * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch - * pixmap created by some other X Server internals (the score says it's - * pinned). - */ -static Bool -exaPixmapIsPinned (PixmapPtr pPix) -{ - ExaPixmapPriv (pPix); - - return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED; -} - -/** - * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys - * and exaCopyDirtyToFb both needed to do this loop. - */ -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); - - return pExaPixmap == NULL || - REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)) || - !REGION_EQUAL(pScreen, &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), CARD8 *fallback_src, - CARD8 *fallback_dst, int fallback_srcpitch, int fallback_dstpitch, - int fallback_index, void (*sync) (ScreenPtr pScreen)) -{ - PixmapPtr pPixmap = migrate->pPix; - ExaPixmapPriv (pPixmap); - RegionPtr damage = DamageRegion (pExaPixmap->pDamage); - RegionRec CopyReg; - Bool save_offscreen; - 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 (exaPixmapIsOffscreen(pPixmap)) { - REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB, - damage); - REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, - damage); - } else { - REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, - damage); - REGION_SUBTRACT(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB, - damage); - } - - REGION_EMPTY(pScreen, damage); - - /* Copy bits valid in source but not in destination */ - REGION_NULL(pScreen, &CopyReg); - REGION_SUBTRACT(pScreen, &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 (REGION_NIL(pending_damage)) { - static Bool firsttime = TRUE; - - if (firsttime) { - ErrorF("%s: Pending damage region empty!\n", __FUNCTION__ ); - firsttime = FALSE; - } - } -#endif - - REGION_INTERSECT(pScreen, &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) - REGION_SUBTRACT(pScreen, &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) - REGION_INTERSECT(pScreen, &CopyReg, &CopyReg, migrate->pReg); - } - - pBox = REGION_RECTS(&CopyReg); - nbox = REGION_NUM_RECTS(&CopyReg); - - save_offscreen = pExaPixmap->offscreen; - save_pitch = pPixmap->devKind; - pExaPixmap->offscreen = 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->drawable, fallback_index); - access_prepared = TRUE; - } - exaMemcpyBox (pPixmap, pBox, - fallback_src, fallback_srcpitch, - fallback_dst, fallback_dstpitch); - } else - need_sync = TRUE; - - pBox++; - } - - if (access_prepared) - exaFinishAccess(&pPixmap->drawable, fallback_index); - else if (need_sync) - sync (pPixmap->drawable.pScreen); - - pExaPixmap->offscreen = save_offscreen; - pPixmap->devKind = save_pitch; - - /* The copied bits are now valid in destination */ - REGION_UNION(pScreen, pValidDst, pValidDst, &CopyReg); - - REGION_UNINIT(pScreen, &CopyReg); -} - -/** - * 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. - */ -static void -exaCopyDirtyToSys (ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - ExaScreenPriv (pPixmap->drawable.pScreen); - ExaPixmapPriv (pPixmap); - - exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB, - pExaScr->info->DownloadFromScreen, pExaPixmap->fb_ptr, - pExaPixmap->sys_ptr, pExaPixmap->fb_pitch, - pExaPixmap->sys_pitch, 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. - */ -static void -exaCopyDirtyToFb (ExaMigrationPtr migrate) -{ - PixmapPtr pPixmap = migrate->pPix; - ExaScreenPriv (pPixmap->drawable.pScreen); - ExaPixmapPriv (pPixmap); - - exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys, - pExaScr->info->UploadToScreen, pExaPixmap->sys_ptr, - pExaPixmap->fb_ptr, pExaPixmap->sys_pitch, - pExaPixmap->fb_pitch, EXA_PREPARE_DEST, exaMarkSync); -} - -/** - * 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, (pointer) pPixmap); - if (pExaPixmap->area == NULL) - return; - - pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase + - pExaPixmap->area->offset; - } - - exaCopyDirtyToFb (migrate); - - if (exaPixmapIsOffscreen(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->offscreen = TRUE; - - pPixmap->devKind = pExaPixmap->fb_pitch; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; -} - -void -exaMoveInPixmap (PixmapPtr pPixmap) -{ - static ExaMigrationRec migrate = { FALSE, TRUE, NULL, - 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 (exaPixmapIsOffscreen(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->offscreen = FALSE; - - pPixmap->devKind = pExaPixmap->sys_pitch; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - } -} - -void -exaMoveOutPixmap (PixmapPtr pPixmap) -{ - static ExaMigrationRec migrate = { FALSE, TRUE, NULL, - 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 */ - REGION_EMPTY(pPixmap->drawable.pScreen, &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 == NULL) { - DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n", - (pointer)pPixmap, - exaPixmapIsOffscreen(pPixmap) ? "s" : "m")); - return; - } - - if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) { - DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n", - (pointer)pPixmap)); - return; - } - - DBG_MIGRATE(("UseScreen %p score %d\n", - (pointer)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 && - !exaPixmapIsOffscreen(pPixmap)) - { - exaDoMoveInPixmap(migrate); - } - - ExaOffscreenMarkUsed (pPixmap); -} - -/** - * 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); - - if (pExaPixmap == NULL) { - DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n", - (pointer)pPixmap, - exaPixmapIsOffscreen(pPixmap) ? "s" : "m")); - return; - } - - DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)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 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; - BoxPtr pBox; - Bool ret = TRUE; - - if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL) - return ret; - - REGION_NULL(pScreen, &ValidReg); - REGION_INTERSECT(pScreen, &ValidReg, &pExaPixmap->validFB, - &pExaPixmap->validSys); - nbox = REGION_NUM_RECTS(&ValidReg); - - if (!nbox) - goto out; - - pBox = REGION_RECTS(&ValidReg); - - dst_pitch = pExaPixmap->sys_pitch; - src_pitch = pExaPixmap->fb_pitch; - cpp = pPixmap->drawable.bitsPerPixel / 8; - - ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); - 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 = pExaPixmap->fb_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; - } - } - } - exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); - -out: - REGION_UNINIT(pScreen, &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 (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) -{ - ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen; - ExaScreenPriv(pScreen); - int i, j; - - if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS) - return; - - /* 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", __FUNCTION__ , i); - } - } - /* If anything is pinned in system memory, we won't be able to - * accelerate. - */ - for (i = 0; i < npixmaps; i++) { - if (exaPixmapIsPinned (pixmaps[i].pPix) && - !exaPixmapIsOffscreen (pixmaps[i].pPix)) - { - 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 (exaPixmapIsOffscreen(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 (!exaPixmapIsOffscreen(pixmaps[i].pPix)) { - return; - } - } - - /* Yay, everything's offscreen, mark memory as used */ - for (i = 0; i < npixmaps; i++) { - ExaOffscreenMarkUsed (pixmaps[i].pPix); - } - } -} diff --git a/xorg-server/exa/exa_migration_classic.c b/xorg-server/exa/exa_migration_classic.c index d8e1e86da..e096c1eac 100644 --- a/xorg-server/exa/exa_migration_classic.c +++ b/xorg-server/exa/exa_migration_classic.c @@ -368,8 +368,8 @@ exaDoMoveInPixmap (ExaMigrationPtr migrate) void exaMoveInPixmap_classic (PixmapPtr pPixmap) { - static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE, - .pReg = NULL }; + static ExaMigrationRec migrate = { FALSE, TRUE, + NULL, NULL }; migrate.pPix = pPixmap; exaDoMoveInPixmap (&migrate); @@ -409,8 +409,8 @@ exaDoMoveOutPixmap (ExaMigrationPtr migrate) void exaMoveOutPixmap_classic (PixmapPtr pPixmap) { - static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE, - .pReg = NULL }; + static ExaMigrationRec migrate = { FALSE, TRUE, + NULL, NULL }; migrate.pPix = pPixmap; exaDoMoveOutPixmap (&migrate); @@ -608,7 +608,7 @@ exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel) 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); + ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __FUNCTION__, i); } } /* If anything is pinned in system memory, we won't be able to diff --git a/xorg-server/exa/exa_render.c b/xorg-server/exa/exa_render.c index 1ac29f233..d46930130 100644 --- a/xorg-server/exa/exa_render.c +++ b/xorg-server/exa/exa_render.c @@ -77,11 +77,17 @@ static void exaCompositeFallbackPictDesc(PicturePtr pict, char *string, int n) break; } - loc = exaGetOffscreenPixmap(pict->pDrawable, &temp, &temp) ? 's' : 'm'; + 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" : ""); + 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); } @@ -144,38 +150,26 @@ exaGetPixelFromRGBA(CARD32 *pixel, CARD16 green, CARD16 blue, CARD16 alpha, - CARD32 format) + PictFormatPtr pFormat) { int rbits, bbits, gbits, abits; int rshift, bshift, gshift, ashift; *pixel = 0; - if (!PICT_FORMAT_COLOR(format)) + if (!PICT_FORMAT_COLOR(pFormat->format) && + PICT_FORMAT_TYPE(pFormat->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 (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { - bshift = 0; - gshift = bbits; - rshift = gshift + gbits; - ashift = rshift + rbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { - rshift = 0; - gshift = rbits; - bshift = gshift + gbits; - ashift = bshift + bbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { - bshift = PICT_FORMAT_BPP(format) - bbits; - gshift = bshift - gbits; - rshift = gshift - rbits; - ashift = 0; - } else - 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; @@ -191,36 +185,24 @@ exaGetRGBAFromPixel(CARD32 pixel, CARD16 *green, CARD16 *blue, CARD16 *alpha, - CARD32 format) + PictFormatPtr pFormat) { int rbits, bbits, gbits, abits; int rshift, bshift, gshift, ashift; - if (!PICT_FORMAT_COLOR(format)) + if (!PICT_FORMAT_COLOR(pFormat->format) && + PICT_FORMAT_TYPE(pFormat->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 (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { - bshift = 0; - gshift = bbits; - rshift = gshift + gbits; - ashift = rshift + rbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { - rshift = 0; - gshift = rbits; - bshift = gshift + gbits; - ashift = bshift + bbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { - bshift = PICT_FORMAT_BPP(format) - bbits; - gshift = bshift - gbits; - rshift = gshift - rbits; - ashift = 0; - } else - 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; *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits); while (rbits < 16) { @@ -268,27 +250,22 @@ exaTryDriverSolidFill(PicturePtr pSrc, int nbox; int dst_off_x, dst_off_y; PixmapPtr pSrcPix, pDstPix; - ExaPixmapPrivPtr pSrcExaPix, pDstExaPix; + ExaPixmapPrivPtr pDstExaPix; CARD32 pixel; CARD16 red, green, blue, alpha; pDstPix = exaGetDrawablePixmap (pDst->pDrawable); - pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); - - pSrcExaPix = ExaGetPixmapPriv(pSrcPix); pDstExaPix = ExaGetPixmapPriv(pDstPix); - /* Check whether the accelerator can use these pixmaps. + /* Check whether the accelerator can use the destination pixmap. */ - if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked) + if (pDstExaPix->accel_blocked) { return -1; } xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, xSrc, ySrc, 0, 0, xDst, yDst, @@ -299,7 +276,23 @@ exaTryDriverSolidFill(PicturePtr pSrc, REGION_TRANSLATE(pScreen, ®ion, dst_off_x, dst_off_y); - pixel = exaGetPixmapFirstPixel (pSrcPix); + if (pSrc->pDrawable) { + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + pSrcPix = exaGetDrawablePixmap (pSrc->pDrawable); + pixel = exaGetPixmapFirstPixel (pSrcPix); + } else + pixel = pSrc->pSourcePict->solidFill.color; + + if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, + pSrc->pFormat) || + !exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, + pDst->pFormat)) + { + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + return -1; + } if (pExaScr->do_migration) { ExaMigrationRec pixmaps[1]; @@ -316,20 +309,6 @@ exaTryDriverSolidFill(PicturePtr pSrc, return 0; } - if (!exaGetRGBAFromPixel(pixel, &red, &green, &blue, &alpha, - pSrc->format)) - { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - return -1; - } - - if (!exaGetPixelFromRGBA(&pixel, red, green, blue, alpha, - pDst->format)) - { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - return -1; - } - if (!(*pExaScr->info->PrepareSolid) (pDstPix, GXcopy, 0xffffffff, pixel)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); @@ -362,16 +341,18 @@ exaTryDriverCompositeRects(CARD8 op, { ExaScreenPriv (pDst->pDrawable->pScreen); int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; - ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; + PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix; + ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix; if (!pExaScr->info->PrepareComposite) return -1; - pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); - pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + if (pSrc->pDrawable) { + pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); + pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + } - if (pMask) { + if (pMask && pMask->pDrawable) { pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); pMaskExaPix = ExaGetPixmapPriv(pMaskPix); } @@ -383,8 +364,9 @@ exaTryDriverCompositeRects(CARD8 op, * FIXME: If it cannot, use temporary pixmaps so that the drawing * happens within limits. */ - if (pSrcExaPix->accel_blocked || pDstExaPix->accel_blocked || - (pMask && pMaskExaPix->accel_blocked)) + if (pDstExaPix->accel_blocked || + (pSrcExaPix && pSrcExaPix->accel_blocked) || + (pMaskExaPix && pMaskExaPix->accel_blocked)) { return -1; } @@ -397,37 +379,45 @@ exaTryDriverCompositeRects(CARD8 op, 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++; + } - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = exaOpReadsDestination(op); - pixmaps[0].pPix = pDstPix; - pixmaps[0].pReg = NULL; - pixmaps[1].as_dst = FALSE; - pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = pSrcPix; - pixmaps[1].pReg = NULL; - if (pMask) { - pixmaps[2].as_dst = FALSE; - pixmaps[2].as_src = TRUE; - pixmaps[2].pPix = pMaskPix; - pixmaps[2].pReg = NULL; - exaDoMigration(pixmaps, 3, TRUE); - } else - exaDoMigration(pixmaps, 2, TRUE); + 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; - - pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); - if (!pSrcPix) - return 0; + if (pSrcPix) { + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); + if (!pSrcPix) + return 0; + } - if (pMask) { + if (pMaskPix) { pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y); - if (!pMaskPix) return 0; } @@ -440,15 +430,24 @@ exaTryDriverCompositeRects(CARD8 op, { INT16 xDst = rects->xDst + pDst->pDrawable->x; INT16 yDst = rects->yDst + pDst->pDrawable->y; - INT16 xMask = pMask ? rects->xMask + pMask->pDrawable->x : 0; - INT16 yMask = pMask ? rects->yMask + pMask->pDrawable->y : 0; - INT16 xSrc = rects->xSrc + pSrc->pDrawable->x; - INT16 ySrc = rects->ySrc + pSrc->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)) @@ -635,16 +634,18 @@ exaTryDriverComposite(CARD8 op, BoxPtr pbox; int nbox; int src_off_x, src_off_y, mask_off_x, mask_off_y, dst_off_x, dst_off_y; - PixmapPtr pSrcPix, pMaskPix = NULL, pDstPix; - ExaPixmapPrivPtr pSrcExaPix, pMaskExaPix = NULL, pDstExaPix; + PixmapPtr pSrcPix = NULL, pMaskPix = NULL, pDstPix; + ExaPixmapPrivPtr pSrcExaPix = NULL, pMaskExaPix = NULL, pDstExaPix; - pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); - pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + if (pSrc->pDrawable) { + pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable); + pSrcExaPix = ExaGetPixmapPriv(pSrcPix); + } pDstPix = exaGetDrawablePixmap(pDst->pDrawable); pDstExaPix = ExaGetPixmapPriv(pDstPix); - if (pMask) { + if (pMask && pMask->pDrawable) { pMaskPix = exaGetDrawablePixmap(pMask->pDrawable); pMaskExaPix = ExaGetPixmapPriv(pMaskPix); } @@ -653,8 +654,8 @@ exaTryDriverComposite(CARD8 op, * FIXME: If it cannot, use temporary pixmaps so that the drawing * happens within limits. */ - if (pSrcExaPix->accel_blocked || - pDstExaPix->accel_blocked || + if (pDstExaPix->accel_blocked || + (pSrcExaPix && pSrcExaPix->accel_blocked) || (pMask && (pMaskExaPix->accel_blocked))) { return -1; @@ -663,13 +664,15 @@ exaTryDriverComposite(CARD8 op, xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; - if (pMask) { + if (pMaskPix) { xMask += pMask->pDrawable->x; yMask += pMask->pDrawable->y; } - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; + if (pSrcPix) { + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + } if (pExaScr->info->CheckComposite && !(*pExaScr->info->CheckComposite) (op, pSrc, pMask, pDst)) @@ -688,36 +691,51 @@ exaTryDriverComposite(CARD8 op, 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++; + } - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = exaOpReadsDestination(op); - pixmaps[0].pPix = pDstPix; - pixmaps[0].pReg = pixmaps[0].as_src ? NULL : ®ion; - pixmaps[1].as_dst = FALSE; - pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = pSrcPix; - pixmaps[1].pReg = NULL; - if (pMask) { - pixmaps[2].as_dst = FALSE; - pixmaps[2].as_src = TRUE; - pixmaps[2].pPix = pMaskPix; - pixmaps[2].pReg = NULL; - exaDoMigration(pixmaps, 3, TRUE); - } else - exaDoMigration(pixmaps, 2, TRUE); + 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); } - pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); - if (pMask) + if (pSrcPix) { + pSrcPix = exaGetOffscreenPixmap (pSrc->pDrawable, &src_off_x, &src_off_y); + if (!pSrcPix) { + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + return 0; + } + } + + if (pMaskPix) { pMaskPix = exaGetOffscreenPixmap (pMask->pDrawable, &mask_off_x, &mask_off_y); - - if (!exaPixmapIsOffscreen(pDstPix)) { - REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); - return 0; + if (!pMaskPix) { + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + return 0; + } } - if (!pSrcPix || (pMask && !pMaskPix)) { + if (!exaPixmapIsOffscreen(pDstPix)) { REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); return 0; } @@ -868,45 +886,44 @@ exaComposite(CARD8 op, Bool saveMaskRepeat = pMask ? pMask->repeat : 0; RegionRec region; - /* We currently don't support acceleration of gradients, or other pictures - * with a NULL pDrawable. - */ - if (pExaScr->swappedOut || - pSrc->pDrawable == NULL || (pMask != NULL && pMask->pDrawable == NULL)) - { + if (pExaScr->swappedOut) goto fallback; - } /* Remove repeat in source if useless */ - if (pSrc->repeat && !pSrc->transform && xSrc >= 0 && + 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) + if (!pMask && !pSrc->alphaMap && !pDst->alphaMap && + (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(pSrc->format)))) { - if ((op == PictOpSrc && - ((pSrc->format == pDst->format) || - (pSrc->format==PICT_b8g8r8a8 && pDst->format==PICT_b8g8r8x8) || - (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || - (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || - (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && - pSrc->format == pDst->format && - (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8 || - pSrc->format==PICT_b8g8r8x8))) + if (pSrc->pDrawable ? + (pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 && + pSrc->repeat) : + (pSrc->pSourcePict->type == SourcePictTypeSolidFill)) { - if (pSrc->pDrawable->width == 1 && - pSrc->pDrawable->height == 1 && - pSrc->repeat) - { - ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst, - width, height); - if (ret == 1) - goto done; - } - else if (pSrc->pDrawable != NULL && - !pSrc->repeat && - !pSrc->transform) + 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 ret; xDst += pDst->pDrawable->x; @@ -935,10 +952,9 @@ exaComposite(CARD8 op, goto done; } - else if (pSrc->pDrawable != NULL && - pSrc->pDrawable->type == DRAWABLE_PIXMAP && - !pSrc->transform && - pSrc->repeatType == RepeatNormal) + + if (pSrc->repeat && pSrc->repeatType == RepeatNormal && + pSrc->pDrawable->type == DRAWABLE_PIXMAP) { DDXPointRec patOrg; @@ -988,9 +1004,9 @@ exaComposite(CARD8 op, } /* Remove repeat in mask if useless */ - if (pMask && pMask->repeat && !pMask->transform && xMask >= 0 && - (xMask + width) <= pMask->pDrawable->width && yMask >= 0 && - (yMask + height) <= pMask->pDrawable->height) + 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 && @@ -1006,9 +1022,10 @@ exaComposite(CARD8 op, /* For generic masks and solid src pictures, mach64 can do Over in two * passes, similar to the component-alpha case. */ - isSrcSolid = pSrc->pDrawable->width == 1 && - pSrc->pDrawable->height == 1 && - pSrc->repeat; + 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 diff --git a/xorg-server/exa/makefile b/xorg-server/exa/makefile index 0373a4be3..5ad11a1ed 100644 --- a/xorg-server/exa/makefile +++ b/xorg-server/exa/makefile @@ -1,4 +1,14 @@ -CSRCS=exa.c exa_accel.c exa_migration.c exa_offscreen.c exa_render.c exa_unaccel.c
-
LIBRARY=libexa
+CSRCS = \
+ 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
|