diff --git a/Makefile.am b/Makefile.am index e00379078..93aeea35e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,7 +72,7 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = xorg-server.pc endif -EXTRA_DIST = xorg-server.pc.in xorg-server.m4 autogen.sh README.md +EXTRA_DIST = xorg-server.pc.in xorg-server.m4 autogen.sh README.md SECURITY.md DISTCHECK_CONFIGURE_FLAGS=\ --with-xkb-path=$(XKB_BASE_DIRECTORY) \ diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..f36abe23c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,50 @@ +# Reporting Security Issues + +Please notify us of any security issues by sending mail to +. + +See https://www.x.org/wiki/Development/Security/Organization/ +for more information about the X.Org security team. + +# Learning about Security Fixes + +X.Org announces security bugs and bug fix releases on the xorg-announce +mailing list. See the archives at https://lists.x.org/archives/xorg-announce/ +and see https://lists.x.org/mailman/listinfo/xorg-announce to subscribe. + +Security advisories are also listed on our wiki at +https://www.x.org/wiki/Development/Security/ and mailed to the +https://oss-security.openwall.org/wiki/mailing-lists/oss-security mailing list. + +# Security model and trust boundaries + +Only the Xorg server is expected to run with elevated privileges. +(Some distros may run Xorg with a wrapper to only grant these privileges when +necessary.) The Xorg server usually requires root access to hardware devices +and I/O registers when using a UMS (Userspace Mode Setting) driver, and not +when using a KMS (Kernel Mode Setting) driver, or drivers which do not require +actual hardware access (such as xf86-video-dummy). + +All other X servers (Xephyr, Xnest, Xvfb, etc.) are expected to run with only +the privileges of the user who started the server. They should not require +direct access to any devices. + +The Xorg server uses configuration files to control various aspects of its +operation (see the xorg.conf(5) man page), including specifying loadable +object modules to run code from with the full privileges of the X server. +There is no attempt to sandbox these modules - they are considered to be fully +trusted, and thus anyone who can edit a config file is considered to be fully +trusted - a module being able to control or crash the X server is not considered +a security vulnerability (though a crash would be a non-security bug in the +module). The configuration file loading mechanism takes steps to verify that +config files are owned by trusted users before reading them, and failure to do +so would be considered a security vulnerability. + +Access control for which clients can connect to the X server is provided by +a number of mechanisms, see the Xsecurity(7) man page for details. Once a +client is authenticated via those mechanisms and has an active connection, +we do not consider it a security vulnerability for them to be able to take +any actions described in the X11 protocol or extension specifications, such +as changing monitor configurations or killing other clients, though we will +accept non-security bug reports for clients doing so in a manner or via +requests not documented in the protocol specs as doing those operations. diff --git a/configure.ac b/configure.ac index 5d8198ebc..26e3a6b72 100644 --- a/configure.ac +++ b/configure.ac @@ -565,6 +565,7 @@ AC_ARG_ENABLE(config-udev-kms, AS_HELP_STRING([--enable-config-udev-kms], [Bu AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) AC_ARG_ENABLE(config-wscons, AS_HELP_STRING([--enable-config-wscons], [Build wscons config support (default: auto)]), [CONFIG_WSCONS=$enableval], [CONFIG_WSCONS=auto]) AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes]) +AC_ARG_ENABLE(xaa, AS_HELP_STRING([--enable-xaa], [Build XAA (default: enabled)]), [XAA=$enableval], [XAA=yes]) AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) AC_ARG_ENABLE(windowsdri, AS_HELP_STRING([--enable-windowsdri], [Build XWin with WindowsDRI extension (default: auto)]), [WINDOWSDRI=$enableval], [WINDOWSDRI=auto]) @@ -654,6 +655,7 @@ case $host_os in INT10MODULE=no PCI=no VGAHW=no + XAA=no XF86UTILS=no XF86VIDMODE=no XSELINUX=no @@ -1335,6 +1337,7 @@ XI_LIB='$(top_builddir)/Xi/libXi.la' XI_INC='-I$(top_srcdir)/Xi' AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) +AM_CONDITIONAL(XAA, test "x$XAA" = xyes) AM_CONDITIONAL(VGAHW, test "x$VGAHW" = xyes) AM_CONDITIONAL(INT10MODULE, test "x$INT10MODULE" = xyes) @@ -2300,6 +2303,7 @@ miext/Makefile miext/sync/Makefile miext/damage/Makefile miext/shadow/Makefile +miext/cw/Makefile miext/rootless/Makefile os/Makefile pseudoramiX/Makefile @@ -2349,6 +2353,7 @@ hw/xfree86/shadowfb/Makefile hw/xfree86/vgahw/Makefile hw/xfree86/x86emu/Makefile hw/xfree86/xkb/Makefile +hw/xfree86/xaa/Makefile hw/xfree86/utils/Makefile hw/xfree86/utils/man/Makefile hw/xfree86/utils/gtf/Makefile diff --git a/exa/exa.c b/exa/exa.c index b16875845..36417410b 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -505,14 +505,29 @@ exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) ExaScreenPriv(pScreen); ExaGCPriv(pGC); PixmapPtr pTile = NULL; + Bool finish_current_tile = FALSE; - /* Either of these conditions is enough to trigger access to a tile pixmap. - * With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid - * tile pixmap pointer. - */ + /* Either of these conditions is enough to trigger access to a tile pixmap. */ + /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */ if (pGC->fillStyle == FillTiled || ((changes & GCTile) && !pGC->tileIsPixel)) { pTile = pGC->tile.pixmap; + + /* Sometimes tile pixmaps are swapped, you need access to: + * - The current tile if it depth matches. + * - Or the rotated tile if that one matches depth and !(changes & GCTile). + * - Or the current tile pixmap and a newly created one. + */ + if (pTile && pTile->drawable.depth != pDrawable->depth && + !(changes & GCTile)) { + PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC); + + if (pRotatedTile && + pRotatedTile->drawable.depth == pDrawable->depth) + pTile = pRotatedTile; + else + finish_current_tile = TRUE; /* CreatePixmap will be called. */ + } } if (pGC->stipple) @@ -529,6 +544,8 @@ exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) if (pTile) exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC); + if (finish_current_tile && pGC->tile.pixmap) + exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_AUX_DEST); if (pGC->stipple) exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK); } diff --git a/fb/Makefile.am b/fb/Makefile.am index 333aa06a9..65b5d9432 100644 --- a/fb/Makefile.am +++ b/fb/Makefile.am @@ -14,6 +14,8 @@ libwfb_la_LIBADD = $(PIXMAN_LIBS) libfb_la_SOURCES = \ fb.h \ + fb24_32.c \ + fb24_32.h \ fballpriv.c \ fbarc.c \ fbbits.c \ diff --git a/fb/fb.h b/fb/fb.h index 8ab050d0f..1157f59ef 100644 --- a/fb/fb.h +++ b/fb/fb.h @@ -89,6 +89,9 @@ #if GLYPHPADBYTES != 4 #error "GLYPHPADBYTES must be 4" #endif +/* for driver compat - intel UXA needs the second one at least */ +#define FB_24BIT +#define FB_24_32BIT #define FB_STIP_SHIFT LOG2_BITMAP_PAD #define FB_STIP_UNIT (1 << FB_STIP_SHIFT) #define FB_STIP_MASK (FB_STIP_UNIT - 1) @@ -328,6 +331,32 @@ extern _X_EXPORT void fbSetBits(FbStip * bits, int stride, FbStip data); #define FbLaneCase(n,a) FbLaneCase4(n,(CARD8 *) (a),0) +/* Rotate a filled pixel value to the specified alignement */ +#define FbRot24(p,b) (FbScrRight(p,b) | FbScrLeft(p,24-(b))) +#define FbRot24Stip(p,b) (FbStipRight(p,b) | FbStipLeft(p,24-(b))) + +/* step a filled pixel value to the next/previous FB_UNIT alignment */ +#define FbNext24Pix(p) (FbRot24(p,(24-FB_UNIT%24))) +#define FbPrev24Pix(p) (FbRot24(p,FB_UNIT%24)) +#define FbNext24Stip(p) (FbRot24(p,(24-FB_STIP_UNIT%24))) +#define FbPrev24Stip(p) (FbRot24(p,FB_STIP_UNIT%24)) + +/* step a rotation value to the next/previous rotation value */ +#define FbNext24Rot(r) ((r) == 0 ? 16 : (r) - 8) +#define FbPrev24Rot(r) ((r) == 16 ? 0 : (r) + 8) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define FbFirst24Rot(x) (((x) + 16) % 24) +#else +#define FbFirst24Rot(x) ((x) % 24) +#endif + +#define FbNext24RotStip(r) ((r) == 0 ? 16 : (r) - 8) +#define FbPrev24RotStip(r) ((r) == 16 ? 0 : (r) + 8) + +/* Whether 24-bit specific code is needed for this filled pixel value */ +#define FbCheck24Pix(p) ((p) == FbNext24Pix(p)) + /* Macros for dealing with dashing */ #define FbDashDeclare \ @@ -404,6 +433,8 @@ fbGetScreenPrivateKey(void); /* private field of a screen */ typedef struct { + unsigned char win32bpp; /* window bpp for 32-bpp images */ + unsigned char pix32bpp; /* pixmap bpp for 32-bpp images */ #ifdef FB_ACCESS_WRAPPER SetupWrapProcPtr setupWrap; /* driver hook to set pixmap access wrapping */ FinishWrapProcPtr finishWrap; /* driver hook to clean up pixmap access wrapping */ @@ -421,6 +452,7 @@ typedef struct { FbBits bgand, bgxor; /* for stipples */ FbBits fg, bg, pm; /* expanded and filled */ unsigned int dashLength; /* total of all dash elements */ + unsigned char bpp; /* current drawable bpp */ } FbGCPrivRec, *FbGCPrivPtr; #define fbGetGCPrivateKey(pGC) (&fbGetScreenPrivate((pGC)->pScreen)->gcPrivateKeyRec) @@ -430,6 +462,7 @@ typedef struct { #define fbGetCompositeClip(pGC) ((pGC)->pCompositeClip) #define fbGetExpose(pGC) ((pGC)->fExpose) +#define fbGetRotatedPixmap(pGC) ((pGC)->pRotatedPixmap) #define fbGetScreenPixmap(s) ((PixmapPtr) (s)->devPrivate) @@ -506,6 +539,64 @@ typedef struct { */ #define FbEvenTile(w) ((w) <= FB_UNIT && FbPowerOfTwo(w)) +/* + * fb24_32.c + */ +extern _X_EXPORT void + +fb24_32GetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart); + +extern _X_EXPORT void + +fb24_32SetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); + +extern _X_EXPORT void + +fb24_32PutZImage(DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, int width, int height, CARD8 *src, FbStride srcStride); + +extern _X_EXPORT void + +fb24_32GetImage(DrawablePtr pDrawable, + int x, + int y, + int w, + int h, unsigned int format, unsigned long planeMask, char *d); + +extern _X_EXPORT void + +fb24_32CopyMtoN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure); + +extern _X_EXPORT PixmapPtr + fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel); + +extern _X_EXPORT Bool + fb24_32CreateScreenResources(ScreenPtr pScreen); + +extern _X_EXPORT Bool + +fb24_32ModifyPixmapHeader(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, void *pPixData); + /* * fballpriv.c */ @@ -620,6 +711,47 @@ extern _X_EXPORT void extern _X_EXPORT void +fbBresSolid24(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbBresDash24(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x, int y, int e, int e1, int e3, int len); + +extern _X_EXPORT void + +fbDots24(FbBits * dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint * pts, + int npt, + int xorg, int yorg, int xoff, int yoff, FbBits and, FbBits xor); + +extern _X_EXPORT void + +fbArc24(FbBits * dst, + FbStride dstStride, + int dstBpp, xArc * arc, int dx, int dy, FbBits and, FbBits xor); + +extern _X_EXPORT void +fbPolyline24(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr ptsOrig); + +extern _X_EXPORT void + fbPolySegment24(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg); + +extern _X_EXPORT void + fbBresSolid32(DrawablePtr pDrawable, GCPtr pGC, int dashOffset, @@ -679,6 +811,17 @@ fbBlt(FbBits * src, int width, int height, int alu, FbBits pm, int bpp, Bool reverse, Bool upsidedown); +extern _X_EXPORT void + +fbBlt24(FbBits * srcLine, + FbStride srcStride, + int srcX, + FbBits * dstLine, + FbStride dstStride, + int dstX, + int width, + int height, int alu, FbBits pm, Bool reverse, Bool upsidedown); + extern _X_EXPORT void fbBltStip(FbStip * src, FbStride srcStride, /* in FbStip units, not FbBits units */ int srcX, FbStip * dst, FbStride dstStride, /* in FbStip units, not FbBits units */ @@ -699,6 +842,17 @@ fbBltOne(FbStip * src, int width, int height, FbBits fgand, FbBits fbxor, FbBits bgand, FbBits bgxor); +extern _X_EXPORT void + fbBltOne24(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + FbBits fgand, /* rrop values */ + FbBits fgxor, FbBits bgand, FbBits bgxor); + extern _X_EXPORT void fbBltPlane(FbBits * src, @@ -960,6 +1114,12 @@ fbDestroyGlyphCache(void); */ extern _X_EXPORT PixmapPtr + +fbCreatePixmapBpp(ScreenPtr pScreen, int width, int height, int depth, int bpp, + unsigned usage_hint); + +extern _X_EXPORT PixmapPtr + fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, unsigned usage_hint); @@ -1097,6 +1257,12 @@ fbSolid(FbBits * dst, FbStride dstStride, int dstX, int bpp, int width, int height, FbBits and, FbBits xor); +extern _X_EXPORT void + +fbSolid24(FbBits * dst, + FbStride dstStride, + int dstX, int width, int height, FbBits and, FbBits xor); + /* * fbutil.c */ diff --git a/fb/fb24_32.c b/fb/fb24_32.c new file mode 100644 index 000000000..b95019eb6 --- /dev/null +++ b/fb/fb24_32.c @@ -0,0 +1,548 @@ +/* + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "fb.h" + +/* X apps don't like 24bpp images, this code exposes 32bpp images */ + +/* + * These two functions do a full CopyArea while reformatting + * the data between 24 and 32bpp. They try to go a bit faster + * by reading/writing aligned CARD32s where it's easy + */ + +#define Get8(a) ((CARD32) READ(a)) + +#if BITMAP_BIT_ORDER == MSBFirst +#define Get24(a) ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2)) +#define Put24(a,p) ((WRITE((a+0), (CARD8) ((p) >> 16))), \ + (WRITE((a+1), (CARD8) ((p) >> 8))), \ + (WRITE((a+2), (CARD8) (p)))) +#else +#define Get24(a) (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16)) +#define Put24(a,p) ((WRITE((a+0), (CARD8) (p))), \ + (WRITE((a+1), (CARD8) ((p) >> 8))), \ + (WRITE((a+2), (CARD8) ((p) >> 16)))) +#endif + +typedef void (*fb24_32BltFunc) (CARD8 *srcLine, + FbStride srcStride, + int srcX, + CARD8 *dstLine, + FbStride dstStride, + int dstX, + int width, int height, int alu, FbBits pm); + +static void +fb24_32BltDown(CARD8 *srcLine, + FbStride srcStride, + int srcX, + CARD8 *dstLine, + FbStride dstStride, + int dstX, int width, int height, int alu, FbBits pm) +{ + CARD32 *src; + CARD8 *dst; + int w; + Bool destInvarient; + CARD32 pixel, dpixel; + + FbDeclareMergeRop(); + + srcLine += srcX * 4; + dstLine += dstX * 3; + + FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff)); + destInvarient = FbDestInvarientMergeRop(); + + while (height--) { + src = (CARD32 *) srcLine; + dst = dstLine; + srcLine += srcStride; + dstLine += dstStride; + w = width; + if (destInvarient) { + while (((long) dst & 3) && w) { + w--; + pixel = READ(src++); + pixel = FbDoDestInvarientMergeRop(pixel); + Put24(dst, pixel); + dst += 3; + } + /* Do four aligned pixels at a time */ + while (w >= 4) { + CARD32 s0, s1; + + s0 = READ(src++); + s0 = FbDoDestInvarientMergeRop(s0); + s1 = READ(src++); + s1 = FbDoDestInvarientMergeRop(s1); +#if BITMAP_BIT_ORDER == LSBFirst + WRITE((CARD32 *) dst, (s0 & 0xffffff) | (s1 << 24)); +#else + WRITE((CARD32 *) dst, (s0 << 8) | ((s1 & 0xffffff) >> 16)); +#endif + s0 = READ(src++); + s0 = FbDoDestInvarientMergeRop(s0); +#if BITMAP_BIT_ORDER == LSBFirst + WRITE((CARD32 *) (dst + 4), + ((s1 & 0xffffff) >> 8) | (s0 << 16)); +#else + WRITE((CARD32 *) (dst + 4), + (s1 << 16) | ((s0 & 0xffffff) >> 8)); +#endif + s1 = READ(src++); + s1 = FbDoDestInvarientMergeRop(s1); +#if BITMAP_BIT_ORDER == LSBFirst + WRITE((CARD32 *) (dst + 8), + ((s0 & 0xffffff) >> 16) | (s1 << 8)); +#else + WRITE((CARD32 *) (dst + 8), (s0 << 24) | (s1 & 0xffffff)); +#endif + dst += 12; + w -= 4; + } + while (w--) { + pixel = READ(src++); + pixel = FbDoDestInvarientMergeRop(pixel); + Put24(dst, pixel); + dst += 3; + } + } + else { + while (w--) { + pixel = READ(src++); + dpixel = Get24(dst); + pixel = FbDoMergeRop(pixel, dpixel); + Put24(dst, pixel); + dst += 3; + } + } + } +} + +static void +fb24_32BltUp(CARD8 *srcLine, + FbStride srcStride, + int srcX, + CARD8 *dstLine, + FbStride dstStride, + int dstX, int width, int height, int alu, FbBits pm) +{ + CARD8 *src; + CARD32 *dst; + int w; + Bool destInvarient; + CARD32 pixel; + + FbDeclareMergeRop(); + + FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff))); + destInvarient = FbDestInvarientMergeRop(); + + srcLine += srcX * 3; + dstLine += dstX * 4; + + while (height--) { + w = width; + src = srcLine; + dst = (CARD32 *) dstLine; + srcLine += srcStride; + dstLine += dstStride; + if (destInvarient) { + while (((long) src & 3) && w) { + w--; + pixel = Get24(src); + src += 3; + WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); + } + /* Do four aligned pixels at a time */ + while (w >= 4) { + CARD32 s0, s1; + + s0 = READ((CARD32 *) src); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = s0 & 0xffffff; +#else + pixel = s0 >> 8; +#endif + WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); + s1 = READ((CARD32 *) (src + 4)); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff); +#else + pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16); +#endif + WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); + s0 = READ((CARD32 *) (src + 8)); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff); +#else + pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24); +#endif + WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = s0 >> 8; +#else + pixel = s0 & 0xffffff; +#endif + WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); + src += 12; + w -= 4; + } + while (w) { + w--; + pixel = Get24(src); + src += 3; + WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); + } + } + else { + while (w--) { + pixel = Get24(src); + src += 3; + WRITE(dst, FbDoMergeRop(pixel, READ(dst))); + dst++; + } + } + } +} + +/* + * Spans functions; probably unused. + */ +void +fb24_32GetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart) +{ + FbBits *srcBits; + CARD8 *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + CARD8 *dst; + + fbGetDrawable(pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof(FbBits); + + while (nspans--) { + dst = (CARD8 *) pchardstStart; + fb24_32BltUp(src + (ppt->y + srcYoff) * srcStride, srcStride, + ppt->x + srcXoff, + dst, 1, 0, *pwidth, 1, GXcopy, FB_ALLONES); + + pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } + + fbFinishAccess(pDrawable); +} + +void +fb24_32SetSpans(DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + FbBits *dstBits; + CARD8 *dst, *d, *s; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + BoxPtr pbox; + int n; + int x1, x2; + + fbGetDrawable(pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dst = (CARD8 *) dstBits; + dstStride *= sizeof(FbBits); + while (nspans--) { + d = dst + (ppt->y + dstYoff) * dstStride; + s = (CARD8 *) src; + n = RegionNumRects(pClip); + pbox = RegionRects(pClip); + while (n--) { + if (pbox->y1 > ppt->y) + break; + if (pbox->y2 > ppt->y) { + x1 = ppt->x; + x2 = x1 + *pwidth; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (x1 < x2) + fb24_32BltDown(s, + 0, + (x1 - ppt->x), + d, + dstStride, + x1 + dstXoff, + (x2 - x1), 1, pGC->alu, pPriv->pm); + } + } + src += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } + + fbFinishAccess(pDrawable); +} + +/* + * Clip and put 32bpp Z-format images to a 24bpp drawable + */ +void +fb24_32PutZImage(DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, int width, int height, CARD8 *src, FbStride srcStride) +{ + FbBits *dstBits; + CARD8 *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + int nbox; + BoxPtr pbox; + int x1, y1, x2, y2; + + fbGetDrawable(pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dstStride *= sizeof(FbBits); + dst = (CARD8 *) dstBits; + + for (nbox = RegionNumRects(pClip), + pbox = RegionRects(pClip); nbox--; pbox++) { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + 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; + fb24_32BltDown(src + (y1 - y) * srcStride, + srcStride, + (x1 - x), + dst + (y1 + dstYoff) * dstStride, + dstStride, x1 + dstXoff, (x2 - x1), (y2 - y1), alu, pm); + } + + fbFinishAccess(pDrawable); +} + +void +fb24_32GetImage(DrawablePtr pDrawable, + int x, + int y, + int w, + int h, unsigned int format, unsigned long planeMask, char *d) +{ + FbBits *srcBits; + CARD8 *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + FbStride dstStride; + FbBits pm; + + fbGetDrawable(pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof(FbBits); + + x += pDrawable->x; + y += pDrawable->y; + + pm = fbReplicatePixel(planeMask, 32); + dstStride = PixmapBytePad(w, pDrawable->depth); + if (pm != FB_ALLONES) + memset(d, 0, dstStride * h); + fb24_32BltUp(src + (y + srcYoff) * srcStride, srcStride, x + srcXoff, + (CARD8 *) d, dstStride, 0, w, h, GXcopy, pm); + + fbFinishAccess(pDrawable); +} + +void +fb24_32CopyMtoN(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + FbBits *srcBits; + CARD8 *src; + FbStride srcStride; + int srcBpp; + FbBits *dstBits; + CARD8 *dst; + FbStride dstStride; + int dstBpp; + fb24_32BltFunc blt; + int srcXoff, srcYoff; + int dstXoff, dstYoff; + + fbGetDrawable(pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof(FbBits); + fbGetDrawable(pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dst = (CARD8 *) dstBits; + dstStride *= sizeof(FbBits); + if (srcBpp == 24) + blt = fb24_32BltUp; + else + blt = fb24_32BltDown; + + while (nbox--) { + (*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff), + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff), + (pbox->x2 - pbox->x1), + (pbox->y2 - pbox->y1), pGC->alu, pPriv->pm); + pbox++; + } + + fbFinishAccess(pSrcDrawable); + fbFinishAccess(pDstDrawable); +} + +PixmapPtr +fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel) +{ + ScreenPtr pScreen = pOldTile->drawable.pScreen; + PixmapPtr pNewTile; + FbBits *old, *new; + FbStride oldStride, newStride; + int oldBpp, newBpp; + fb24_32BltFunc blt; + _X_UNUSED int oldXoff, oldYoff; + _X_UNUSED int newXoff, newYoff; + + pNewTile = pScreen->CreatePixmap(pScreen, pOldTile->drawable.width, + pOldTile->drawable.height, + pOldTile->drawable.depth, + pOldTile->usage_hint); + if (!pNewTile) + return 0; + fbGetDrawable(&pOldTile->drawable, + old, oldStride, oldBpp, oldXoff, oldYoff); + fbGetDrawable(&pNewTile->drawable, + new, newStride, newBpp, newXoff, newYoff); + if (oldBpp == 24) + blt = fb24_32BltUp; + else + blt = fb24_32BltDown; + + (*blt) ((CARD8 *) old, + oldStride * sizeof(FbBits), + 0, + (CARD8 *) new, + newStride * sizeof(FbBits), + 0, + pOldTile->drawable.width, + pOldTile->drawable.height, GXcopy, FB_ALLONES); + + fbFinishAccess(&pOldTile->drawable); + fbFinishAccess(&pNewTile->drawable); + + return pNewTile; +} + +typedef struct { + void *pbits; + int width; +} miScreenInitParmsRec, *miScreenInitParmsPtr; + +Bool +fb24_32CreateScreenResources(ScreenPtr pScreen) +{ + miScreenInitParmsPtr pScrInitParms; + int pitch; + Bool retval; + + /* get the pitch before mi destroys it */ + pScrInitParms = (miScreenInitParmsPtr) pScreen->devPrivate; + pitch = BitmapBytePad(pScrInitParms->width * 24); + + if ((retval = miCreateScreenResources(pScreen))) { + /* fix the screen pixmap */ + PixmapPtr pPix = (PixmapPtr) pScreen->devPrivate; + + pPix->drawable.bitsPerPixel = 24; + pPix->devKind = pitch; + } + + return retval; +} + +Bool +fb24_32ModifyPixmapHeader(PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, int devKind, void *pPixData) +{ + int bpp, w; + + if (!pPixmap) + return FALSE; + bpp = bitsPerPixel; + if (bpp <= 0) + bpp = pPixmap->drawable.bitsPerPixel; + if (bpp == 24) { + if (devKind < 0) { + w = width; + if (w <= 0) + w = pPixmap->drawable.width; + devKind = BitmapBytePad(w * 24); + } + } + return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, + devKind, pPixData); +} diff --git a/fb/fb24_32.h b/fb/fb24_32.h new file mode 100644 index 000000000..77eef2339 --- /dev/null +++ b/fb/fb24_32.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2000 SuSE, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of SuSE not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. SuSE makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, SuSE, Inc. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifndef _FB24_32_H_ +#define _FB24_32_H_ + +Bool + +fb24_32FinishScreenInit(ScreenPtr pScreen, + void *pbits, + int xsize, + int ysize, int dpix, int dpiy, int width, int bpp); + +Bool + +fb24_32ScreenInit(ScreenPtr pScreen, + void *pbits, + int xsize, int ysize, int dpix, int dpiy, int width, int bpp); + +#endif diff --git a/fb/fbarc.c b/fb/fbarc.c index fe14aed61..c1b7f7785 100644 --- a/fb/fbarc.c +++ b/fb/fbarc.c @@ -48,6 +48,9 @@ fbPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs) case 16: arc = fbArc16; break; + case 24: + arc = fbArc24; + break; case 32: arc = fbArc32; break; diff --git a/fb/fbbits.c b/fb/fbbits.c index 7435ad56a..d7d089c17 100644 --- a/fb/fbbits.c +++ b/fb/fbbits.c @@ -83,6 +83,64 @@ #undef BITS #undef BITS2 +#define BRESSOLID fbBresSolid24 +#define BRESDASH fbBresDash24 +#define DOTS fbDots24 +#define ARC fbArc24 +#define POLYLINE fbPolyline24 +#define POLYSEGMENT fbPolySegment24 + +#define BITS CARD32 +#define BITSUNIT BYTE +#define BITSMUL 3 + +#define FbDoTypeStore(b,t,x,s) WRITE(((t *) (b)), (x) >> (s)) +#define FbDoTypeRRop(b,t,a,x,s) WRITE((t *) (b), FbDoRRop(READ((t *) (b)),\ + (a) >> (s), \ + (x) >> (s))) +#define FbDoTypeMaskRRop(b,t,a,x,m,s) WRITE((t *) (b), FbDoMaskRRop(READ((t *) (b)),\ + (a) >> (s), \ + (x) >> (s), \ + (m) >> (s))) +#if BITMAP_BIT_ORDER == LSBFirst +#define BITSSTORE(b,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeStore (b, CARD8, x, 0), \ + FbDoTypeStore ((b) + 1, CARD16, x, 8)) : \ + (FbDoTypeStore (b, CARD16, x, 0), \ + FbDoTypeStore ((b) + 2, CARD8, x, 16))) +#define BITSRROP(b,a,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeRRop(b,CARD8,a,x,0), \ + FbDoTypeRRop((b)+1,CARD16,a,x,8)) : \ + (FbDoTypeRRop(b,CARD16,a,x,0), \ + FbDoTypeRRop((b)+2,CARD8,a,x,16))) +#else +#define BITSSTORE(b,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeStore (b, CARD8, x, 16), \ + FbDoTypeStore ((b) + 1, CARD16, x, 0)) : \ + (FbDoTypeStore (b, CARD16, x, 8), \ + FbDoTypeStore ((b) + 2, CARD8, x, 0))) +#define BITSRROP(b,a,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeRRop (b, CARD8, a, x, 16), \ + FbDoTypeRRop ((b) + 1, CARD16, a, x, 0)) : \ + (FbDoTypeRRop (b, CARD16, a, x, 8), \ + FbDoTypeRRop ((b) + 2, CARD8, a, x, 0))) +#endif + +#include "fbbits.h" + +#undef BITSSTORE +#undef BITSRROP +#undef BITSMUL +#undef BITSUNIT +#undef BITS + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef POLYLINE +#undef POLYSEGMENT + #define BRESSOLID fbBresSolid32 #define BRESDASH fbBresDash32 #define DOTS fbDots32 diff --git a/fb/fbbits.h b/fb/fbbits.h index d99ead8f8..be32d8cf0 100644 --- a/fb/fbbits.h +++ b/fb/fbbits.h @@ -31,6 +31,12 @@ #include #endif +#ifdef BITSMUL +#define MUL BITSMUL +#else +#define MUL 1 +#endif + #ifdef BITSSTORE #define STORE(b,x) BITSSTORE(b,x) #else @@ -80,17 +86,17 @@ BRESSOLID(DrawablePtr pDrawable, fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); bits = - ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff); + ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL; bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); if (signdy < 0) bitsStride = -bitsStride; if (axis == X_AXIS) { - majorStep = signdx; + majorStep = signdx * MUL; minorStep = bitsStride; } else { majorStep = bitsStride; - minorStep = signdx; + minorStep = signdx * MUL; } while (len--) { STORE(bits, xor); @@ -137,17 +143,17 @@ BRESDASH(DrawablePtr pDrawable, FbDashInit(pGC, pPriv, dashOffset, dashlen, even); bits = - ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff); + ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL; bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); if (signdy < 0) bitsStride = -bitsStride; if (axis == X_AXIS) { - majorStep = signdx; + majorStep = signdx * MUL; minorStep = bitsStride; } else { majorStep = bitsStride; - minorStep = signdx; + minorStep = signdx * MUL; } if (dashlen >= len) dashlen = len; @@ -254,13 +260,13 @@ DOTS(FbBits * dst, ul = coordToInt(pBox->x1 - xorg, pBox->y1 - yorg); lr = coordToInt(pBox->x2 - xorg - 1, pBox->y2 - yorg - 1); - bits += bitsStride * (yorg + yoff) + (xorg + xoff); + bits += bitsStride * (yorg + yoff) + (xorg + xoff) * MUL; if (and == 0) { while (npt--) { pt = *pts++; if (!isClipped(pt, ul, lr)) { - point = bits + intToY(pt) * bitsStride + intToX(pt); + point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL; STORE(point, bxor); } } @@ -269,7 +275,7 @@ DOTS(FbBits * dst, while (npt--) { pt = *pts++; if (!isClipped(pt, ul, lr)) { - point = bits + intToY(pt) * bitsStride + intToX(pt); + point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL; RROP(point, band, bxor); } } @@ -305,8 +311,8 @@ ARC(FbBits * dst, do360 = miZeroArcSetup(arc, &info, TRUE); yorgp = bits + ((info.yorg + drawY) * bitsStride); yorgop = bits + ((info.yorgo + drawY) * bitsStride); - info.xorg = (info.xorg + drawX); - info.xorgo = (info.xorgo + drawX); + info.xorg = (info.xorg + drawX) * MUL; + info.xorgo = (info.xorgo + drawX) * MUL; MIARCSETUP(); yoffset = y ? bitsStride : 0; dyoffset = 0; @@ -333,37 +339,37 @@ ARC(FbBits * dst, if (do360 && (arc->width == arc->height) && !(arc->width & 1)) { int xoffset = bitsStride; UNIT *yorghb = yorgp + (info.h * bitsStride) + info.xorg; - UNIT *yorgohb = yorghb - info.h; + UNIT *yorgohb = yorghb - info.h * MUL; yorgp += info.xorg; yorgop += info.xorg; - yorghb += info.h; + yorghb += info.h * MUL; while (1) { if (andBits == 0) { - ARCCOPY(yorgp + yoffset + x); - ARCCOPY(yorgp + yoffset - x); - ARCCOPY(yorgop - yoffset - x); - ARCCOPY(yorgop - yoffset + x); + ARCCOPY(yorgp + yoffset + x * MUL); + ARCCOPY(yorgp + yoffset - x * MUL); + ARCCOPY(yorgop - yoffset - x * MUL); + ARCCOPY(yorgop - yoffset + x * MUL); } else { - ARCRROP(yorgp + yoffset + x); - ARCRROP(yorgp + yoffset - x); - ARCRROP(yorgop - yoffset - x); - ARCRROP(yorgop - yoffset + x); + ARCRROP(yorgp + yoffset + x * MUL); + ARCRROP(yorgp + yoffset - x * MUL); + ARCRROP(yorgop - yoffset - x * MUL); + ARCRROP(yorgop - yoffset + x * MUL); } if (a < 0) break; if (andBits == 0) { - ARCCOPY(yorghb - xoffset - y); - ARCCOPY(yorgohb - xoffset + y); - ARCCOPY(yorgohb + xoffset + y); - ARCCOPY(yorghb + xoffset - y); + ARCCOPY(yorghb - xoffset - y * MUL); + ARCCOPY(yorgohb - xoffset + y * MUL); + ARCCOPY(yorgohb + xoffset + y * MUL); + ARCCOPY(yorghb + xoffset - y * MUL); } else { - ARCRROP(yorghb - xoffset - y); - ARCRROP(yorgohb - xoffset + y); - ARCRROP(yorgohb + xoffset + y); - ARCRROP(yorghb + xoffset - y); + ARCRROP(yorghb - xoffset - y * MUL); + ARCRROP(yorgohb - xoffset + y * MUL); + ARCRROP(yorgohb + xoffset + y * MUL); + ARCRROP(yorghb + xoffset - y * MUL); } xoffset += bitsStride; MIARCCIRCLESTEP(yoffset += bitsStride; @@ -379,16 +385,16 @@ ARC(FbBits * dst, MIARCOCTANTSHIFT(dyoffset = bitsStride; ); if (andBits == 0) { - ARCCOPY(yorgp + yoffset + info.xorg + x); - ARCCOPY(yorgp + yoffset + info.xorgo - x); - ARCCOPY(yorgop - yoffset + info.xorgo - x); - ARCCOPY(yorgop - yoffset + info.xorg + x); + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); } else { - ARCRROP(yorgp + yoffset + info.xorg + x); - ARCRROP(yorgp + yoffset + info.xorgo - x); - ARCRROP(yorgop - yoffset + info.xorgo - x); - ARCRROP(yorgop - yoffset + info.xorg + x); + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); } MIARCSTEP(yoffset += dyoffset; , yoffset += bitsStride; @@ -405,23 +411,23 @@ ARC(FbBits * dst, } if (andBits == 0) { if (mask & 1) - ARCCOPY(yorgp + yoffset + info.xorg + x); + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); if (mask & 2) - ARCCOPY(yorgp + yoffset + info.xorgo - x); + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); if (mask & 4) - ARCCOPY(yorgop - yoffset + info.xorgo - x); + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); if (mask & 8) - ARCCOPY(yorgop - yoffset + info.xorg + x); + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); } else { if (mask & 1) - ARCRROP(yorgp + yoffset + info.xorg + x); + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); if (mask & 2) - ARCRROP(yorgp + yoffset + info.xorgo - x); + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); if (mask & 4) - ARCRROP(yorgop - yoffset + info.xorgo - x); + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); if (mask & 8) - ARCRROP(yorgop - yoffset + info.xorg + x); + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); } if ((x == info.end.x) || (y == info.end.y)) { mask = info.end.mask; @@ -436,26 +442,26 @@ ARC(FbBits * dst, mask = info.start.mask; if (andBits == 0) { if (mask & 1) - ARCCOPY(yorgp + yoffset + info.xorg + x); + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); if (mask & 4) - ARCCOPY(yorgop - yoffset + info.xorgo - x); + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); if (arc->height & 1) { if (mask & 2) - ARCCOPY(yorgp + yoffset + info.xorgo - x); + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); if (mask & 8) - ARCCOPY(yorgop - yoffset + info.xorg + x); + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); } } else { if (mask & 1) - ARCRROP(yorgp + yoffset + info.xorg + x); + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); if (mask & 4) - ARCRROP(yorgop - yoffset + info.xorgo - x); + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); if (arc->height & 1) { if (mask & 2) - ARCRROP(yorgp + yoffset + info.xorgo - x); + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); if (mask & 8) - ARCRROP(yorgop - yoffset + info.xorg + x); + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); } } } @@ -620,7 +626,7 @@ POLYLINE(DrawablePtr pDrawable, fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); bitsBase = - ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); + ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL; ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); @@ -643,12 +649,13 @@ POLYLINE(DrawablePtr pDrawable, npt--; } else { - bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1); + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL; for (;;) { CalcLineDeltas(intToX(pt1), intToY(pt1), intToX(pt2), intToY(pt2), len, e1, stepmajor, stepminor, 1, bitsStride, octant); + stepmajor *= MUL; if (len < e1) { e3 = len; len = e1; @@ -740,7 +747,7 @@ POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); bitsStride = dstStride * (sizeof(FbBits) / sizeof(UNIT)); bitsBase = - ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff); + ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL; ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); @@ -760,7 +767,11 @@ POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) intToX(pt2), intToY(pt2), len, e1, stepmajor, stepminor, 1, bitsStride, octant); - if (e1 == 0 && len > 3) { + if (e1 == 0 && len > 3 +#if MUL != 1 + && FbCheck24Pix(and) && FbCheck24Pix(xor) +#endif + ) { int x1, x2; FbBits *dstLine; int dstX, width; @@ -779,8 +790,8 @@ POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) if (!capNotLast) x2++; } - dstX = (x1 + xoff + dstXoff) * (sizeof(UNIT) * 8); - width = (x2 - x1) * (sizeof(UNIT) * 8); + dstX = (x1 + xoff + dstXoff) * (sizeof(UNIT) * 8 * MUL); + width = (x2 - x1) * (sizeof(UNIT) * 8 * MUL); dstLine = dst + (intToY(pt1) + yoff + dstYoff) * dstStride; dstLine += dstX >> FB_SHIFT; @@ -807,7 +818,8 @@ POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) endmask)); } else { - bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1); + stepmajor *= MUL; + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL; if (len < e1) { e3 = len; len = e1; @@ -854,6 +866,7 @@ POLYSEGMENT(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) } #endif +#undef MUL #undef STORE #undef RROP #undef UNIT diff --git a/fb/fbblt.c b/fb/fbblt.c index c1730ab6a..b4123656a 100644 --- a/fb/fbblt.c +++ b/fb/fbblt.c @@ -92,6 +92,12 @@ fbBlt(FbBits * srcLine, } } + if (bpp == 24 && !FbCheck24Pix(pm)) { + fbBlt24(srcLine, srcStride, srcX, dstLine, dstStride, dstX, + width, height, alu, pm, reverse, upsidedown); + return; + } + FbInitializeMergeRop(alu, pm); destInvarient = FbDestInvarientMergeRop(); if (upsidedown) { @@ -292,6 +298,228 @@ fbBlt(FbBits * srcLine, } } +#undef DEBUG_BLT24 +#ifdef DEBUG_BLT24 + +static unsigned long +getPixel(char *src, int x) +{ + unsigned long l; + + l = 0; + memcpy(&l, src + x * 3, 3); + return l; +} +#endif + +static void +fbBlt24Line(FbBits * src, + int srcX, + FbBits * dst, int dstX, int width, int alu, FbBits pm, Bool reverse) +{ +#ifdef DEBUG_BLT24 + char *origDst = (char *) dst; + FbBits *origLine = dst + ((dstX >> FB_SHIFT) - 1); + int origNlw = ((width + FB_MASK) >> FB_SHIFT) + 3; + int origX = dstX / 24; +#endif + + int leftShift, rightShift; + FbBits startmask, endmask; + int n; + + FbBits bits, bits1; + FbBits mask; + + int rot; + + FbDeclareMergeRop(); + + FbInitializeMergeRop(alu, FB_ALLONES); + FbMaskBits(dstX, width, startmask, n, endmask); +#ifdef DEBUG_BLT24 + ErrorF("dstX %d width %d reverse %d\n", dstX, width, reverse); +#endif + if (reverse) { + src += ((srcX + width - 1) >> FB_SHIFT) + 1; + dst += ((dstX + width - 1) >> FB_SHIFT) + 1; + rot = FbFirst24Rot(((dstX + width - 8) & FB_MASK)); + rot = FbPrev24Rot(rot); +#ifdef DEBUG_BLT24 + ErrorF("dstX + width - 8: %d rot: %d\n", (dstX + width - 8) & FB_MASK, + rot); +#endif + srcX = (srcX + width - 1) & FB_MASK; + dstX = (dstX + width - 1) & FB_MASK; + } + else { + src += srcX >> FB_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_MASK; + dstX &= FB_MASK; + rot = FbFirst24Rot(dstX); +#ifdef DEBUG_BLT24 + ErrorF("dstX: %d rot: %d\n", dstX, rot); +#endif + } + mask = FbRot24(pm, rot); +#ifdef DEBUG_BLT24 + ErrorF("pm 0x%x mask 0x%x\n", pm, mask); +#endif + if (srcX == dstX) { + if (reverse) { + if (endmask) { + bits = READ(--src); + --dst; + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask)); + mask = FbPrev24Pix(mask); + } + while (n--) { + bits = READ(--src); + --dst; + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask)); + mask = FbPrev24Pix(mask); + } + if (startmask) { + bits = READ(--src); + --dst; + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask)); + } + } + else { + if (startmask) { + bits = READ(src++); + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask)); + dst++; + mask = FbNext24Pix(mask); + } + while (n--) { + bits = READ(src++); + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask)); + dst++; + mask = FbNext24Pix(mask); + } + if (endmask) { + bits = READ(src); + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask)); + } + } + } + else { + if (srcX > dstX) { + leftShift = srcX - dstX; + rightShift = FB_UNIT - leftShift; + } + else { + rightShift = dstX - srcX; + leftShift = FB_UNIT - rightShift; + } + + bits1 = 0; + if (reverse) { + if (srcX < dstX) + bits1 = READ(--src); + if (endmask) { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(endmask, leftShift)) { + bits1 = READ(--src); + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask)); + mask = FbPrev24Pix(mask); + } + while (n--) { + bits = FbScrRight(bits1, rightShift); + bits1 = READ(--src); + bits |= FbScrLeft(bits1, leftShift); + --dst; + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask)); + mask = FbPrev24Pix(mask); + } + if (startmask) { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(startmask, leftShift)) { + bits1 = READ(--src); + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask)); + } + } + else { + if (srcX > dstX) + bits1 = READ(src++); + if (startmask) { + bits = FbScrLeft(bits1, leftShift); + bits1 = READ(src++); + bits |= FbScrRight(bits1, rightShift); + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask)); + dst++; + mask = FbNext24Pix(mask); + } + while (n--) { + bits = FbScrLeft(bits1, leftShift); + bits1 = READ(src++); + bits |= FbScrRight(bits1, rightShift); + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask)); + dst++; + mask = FbNext24Pix(mask); + } + if (endmask) { + bits = FbScrLeft(bits1, leftShift); + if (FbScrLeft(endmask, rightShift)) { + bits1 = READ(src); + bits |= FbScrRight(bits1, rightShift); + } + WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask)); + } + } + } +#ifdef DEBUG_BLT24 + { + int firstx, lastx, x; + + firstx = origX; + if (firstx) + firstx--; + lastx = origX + width / 24 + 1; + for (x = firstx; x <= lastx; x++) + ErrorF("%06x ", getPixel(origDst, x)); + ErrorF("\n"); + while (origNlw--) + ErrorF("%08x ", *origLine++); + ErrorF("\n"); + } +#endif +} + +void +fbBlt24(FbBits * srcLine, + FbStride srcStride, + int srcX, + FbBits * dstLine, + FbStride dstStride, + int dstX, + int width, + int height, int alu, FbBits pm, Bool reverse, Bool upsidedown) +{ + if (upsidedown) { + srcLine += (height - 1) * srcStride; + dstLine += (height - 1) * dstStride; + srcStride = -srcStride; + dstStride = -dstStride; + } + while (height--) { + fbBlt24Line(srcLine, srcX, dstLine, dstX, width, alu, pm, reverse); + srcLine += srcStride; + dstLine += dstStride; + } +#ifdef DEBUG_BLT24 + ErrorF("\n"); +#endif +} + void fbBltStip(FbStip * src, FbStride srcStride, /* in FbStip units, not FbBits units */ int srcX, FbStip * dst, FbStride dstStride, /* in FbStip units, not FbBits units */ diff --git a/fb/fbbltone.c b/fb/fbbltone.c index 7eac85b08..6d5ce4660 100644 --- a/fb/fbbltone.c +++ b/fb/fbbltone.c @@ -187,6 +187,13 @@ fbBltOne(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ Bool endNeedsLoad = FALSE; /* need load for endmask */ int startbyte, endbyte; + if (dstBpp == 24) { + fbBltOne24(src, srcStride, srcX, + dst, dstStride, dstX, dstBpp, + width, height, fgand, fgxor, bgand, bgxor); + return; + } + /* * Do not read past the end of the buffer! */ @@ -369,6 +376,266 @@ fbBltOne(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ } } +/* + * Crufty macros to initialize the mask array, most of this + * is to avoid compile-time warnings about shift overflow + */ + +#if BITMAP_BIT_ORDER == MSBFirst +#define Mask24Pos(x,r) ((x)*24-(r)) +#else +#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) +#endif + +#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) +#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ + Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) + +#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ + (Mask24Pos(x,r) < 0 ? \ + 0xffffffU >> Mask24Neg (x,r) : \ + 0xffffffU << Mask24Check(x,r)) : 0) + +#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) + +#define C2_24(b,r) \ + (SelMask24(b,0,r) | \ + SelMask24(b,1,r)) + +#define FbStip24Len 2 +#if BITMAP_BIT_ORDER == MSBFirst +#define FbStip24New(rot) (1 + (rot == 0)) +#else +#define FbStip24New(rot) (1 + (rot == 8)) +#endif + +const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { + /* rotate 0 */ + { + C2_24(0, 0), C2_24(1, 0), C2_24(2, 0), C2_24(3, 0), + }, + /* rotate 8 */ + { + C2_24(0, 8), C2_24(1, 8), C2_24(2, 8), C2_24(3, 8), + }, + /* rotate 16 */ + { + C2_24(0, 16), C2_24(1, 16), C2_24(2, 16), C2_24(3, 16), + } +}; + +#if BITMAP_BIT_ORDER == LSBFirst + +#define FbMergeStip24Bits(left, right, new) \ + (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) + +#define FbMergePartStip24Bits(left, right, llen, rlen) \ + (left | FbStipRight(right, llen)) + +#else + +#define FbMergeStip24Bits(left, right, new) \ + ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) + +#define FbMergePartStip24Bits(left, right, llen, rlen) \ + (FbStipLeft(left, rlen) | right) + +#endif + +#define fbFirstStipBits(len,stip) {\ + int __len = (len); \ + if (len <= remain) { \ + stip = FbLeftStipBits(bits, len); \ + } else { \ + stip = FbLeftStipBits(bits, remain); \ + bits = (src < srcEnd ? READ(src++) : 0); \ + __len = (len) - remain; \ + stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ + remain, __len); \ + remain = FB_STIP_UNIT; \ + } \ + bits = FbStipLeft (bits, __len); \ + remain -= __len; \ +} + +#define fbInitStipBits(offset,len,stip) {\ + bits = FbStipLeft (READ(src++),offset); \ + remain = FB_STIP_UNIT - offset; \ + fbFirstStipBits(len,stip); \ + stip = FbMergeStip24Bits (0, stip, len); \ +} + +#define fbNextStipBits(rot,stip) {\ + int __new = FbStip24New(rot); \ + FbStip __right; \ + fbFirstStipBits(__new, __right); \ + stip = FbMergeStip24Bits (stip, __right, __new); \ + rot = FbNext24Rot (rot); \ +} + +/* + * Use deep mask tables that incorporate rotation, pull + * a variable number of bits out of the stipple and + * reuse the right bits as needed for the next write + * + * Yes, this is probably too much code, but most 24-bpp screens + * have no acceleration so this code is used for stipples, copyplane + * and text + */ +void +fbBltOne24(FbStip * srcLine, FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + FbBits fgand, /* rrop values */ + FbBits fgxor, FbBits bgand, FbBits bgxor) +{ + FbStip *src, *srcEnd; + FbBits leftMask, rightMask, mask; + int nlMiddle, nl; + FbStip stip, bits; + int remain; + int dstS; + int firstlen; + int rot0, rot; + int nDst; + + /* + * Do not read past the end of the buffer! + */ + srcEnd = srcLine + height * srcStride; + + srcLine += srcX >> FB_STIP_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_STIP_MASK; + dstX &= FB_MASK; + rot0 = FbFirst24Rot(dstX); + + FbMaskBits(dstX, width, leftMask, nlMiddle, rightMask); + + dstS = (dstX + 23) / 24; + firstlen = FbStip24Len - dstS; + + nDst = nlMiddle; + if (leftMask) + nDst++; + dstStride -= nDst; + + /* opaque copy */ + if (bgand == 0 && fgand == 0) { + while (height--) { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits(srcX, firstlen, stip); + if (leftMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, (READ(dst) & ~leftMask) | + (FbOpaqueStipple(mask, + FbRot24(fgxor, rot), FbRot24(bgxor, rot)) + & leftMask)); + dst++; + fbNextStipBits(rot, stip); + } + nl = nlMiddle; + while (nl--) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, FbOpaqueStipple(mask, + FbRot24(fgxor, rot), + FbRot24(bgxor, rot))); + dst++; + fbNextStipBits(rot, stip); + } + if (rightMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, (READ(dst) & ~rightMask) | + (FbOpaqueStipple(mask, + FbRot24(fgxor, rot), FbRot24(bgxor, rot)) + & rightMask)); + } + dst += dstStride; + src += srcStride; + } + } + /* transparent copy */ + else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) { + while (height--) { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits(srcX, firstlen, stip); + if (leftMask) { + if (stip) { + mask = fbStipple24Bits[rot >> 3][stip] & leftMask; + WRITE(dst, + (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); + } + dst++; + fbNextStipBits(rot, stip); + } + nl = nlMiddle; + while (nl--) { + if (stip) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, + (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); + } + dst++; + fbNextStipBits(rot, stip); + } + if (rightMask) { + if (stip) { + mask = fbStipple24Bits[rot >> 3][stip] & rightMask; + WRITE(dst, + (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); + } + } + dst += dstStride; + } + } + else { + while (height--) { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits(srcX, firstlen, stip); + if (leftMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, FbStippleRRopMask(READ(dst), mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot), leftMask)); + dst++; + fbNextStipBits(rot, stip); + } + nl = nlMiddle; + while (nl--) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, FbStippleRRop(READ(dst), mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot))); + dst++; + fbNextStipBits(rot, stip); + } + if (rightMask) { + mask = fbStipple24Bits[rot >> 3][stip]; + WRITE(dst, FbStippleRRopMask(READ(dst), mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot), rightMask)); + } + dst += dstStride; + } + } +} + /* * Not very efficient, but simple -- copy a single plane * from an N bit image to a 1 bit image @@ -401,6 +668,7 @@ fbBltPlane(FbBits * src, FbStip dstUnion; int w; int wt; + int rot0; if (!width) return; @@ -414,8 +682,19 @@ fbBltPlane(FbBits * src, w = width / srcBpp; pm = fbReplicatePixel(planeMask, srcBpp); - srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); - srcMask0 = pm & FbBitsMask(0, srcBpp); + if (srcBpp == 24) { + int tmpw = 24; + + rot0 = FbFirst24Rot(srcX); + if (srcX + tmpw > FB_UNIT) + tmpw = FB_UNIT - srcX; + srcMaskFirst = FbRot24(pm, rot0) & FbBitsMask(srcX, tmpw); + } + else { + rot0 = 0; + srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); + srcMask0 = pm & FbBitsMask(0, srcBpp); + } dstMaskFirst = FbStipMask(dstX, 1); while (height--) { @@ -425,6 +704,8 @@ fbBltPlane(FbBits * src, src += srcStride; srcMask = srcMaskFirst; + if (srcBpp == 24) + srcMask0 = FbRot24(pm, rot0) & FbBitsMask(0, srcBpp); srcBits = READ(s++); dstMask = dstMaskFirst; @@ -436,6 +717,8 @@ fbBltPlane(FbBits * src, while (wt--) { if (!srcMask) { srcBits = READ(s++); + if (srcBpp == 24) + srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0, 24); srcMask = srcMask0; } if (!dstMask) { diff --git a/fb/fbcopy.c b/fb/fbcopy.c index 3af128ada..6af10ccf7 100644 --- a/fb/fbcopy.c +++ b/fb/fbcopy.c @@ -241,8 +241,14 @@ fbCopyArea(DrawablePtr pSrcDrawable, GCPtr pGC, int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut) { + miCopyProc copy; + + if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) + copy = fb24_32CopyMtoN; + else + copy = fbCopyNtoN; return miDoCopy(pSrcDrawable, pDstDrawable, pGC, xIn, yIn, - widthSrc, heightSrc, xOut, yOut, fbCopyNtoN, 0, 0); + widthSrc, heightSrc, xOut, yOut, copy, 0, 0); } RegionPtr diff --git a/fb/fbgc.c b/fb/fbgc.c index 2ab9ecad1..19c613158 100644 --- a/fb/fbgc.c +++ b/fb/fbgc.c @@ -71,6 +71,7 @@ fbCreateGC(GCPtr pGC) pGC->miTranslate = 1; pGC->fExpose = 1; + fbGetGCPrivate(pGC)->bpp = BitsPerPixel(pGC->depth); return TRUE; } @@ -128,6 +129,35 @@ fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) miComputeCompositeClip(pGC, pDrawable); } + if (pPriv->bpp != pDrawable->bitsPerPixel) { + changes |= GCStipple | GCForeground | GCBackground | GCPlaneMask; + pPriv->bpp = pDrawable->bitsPerPixel; + } + if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { + (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); + fbGetRotatedPixmap(pGC) = 0; + } + + if (pGC->fillStyle == FillTiled) { + PixmapPtr pOldTile, pNewTile; + + pOldTile = pGC->tile.pixmap; + if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { + pNewTile = fbGetRotatedPixmap(pGC); + if (!pNewTile || + pNewTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { + if (pNewTile) + (*pGC->pScreen->DestroyPixmap) (pNewTile); + pNewTile = + fb24_32ReformatTile(pOldTile, pDrawable->bitsPerPixel); + } + if (pNewTile) { + fbGetRotatedPixmap(pGC) = pOldTile; + pGC->tile.pixmap = pNewTile; + changes |= GCTile; + } + } + } if (changes & GCTile) { if (!pGC->tileIsPixel && FbEvenTile(pGC->tile.pixmap->drawable.width * diff --git a/fb/fbgetsp.c b/fb/fbgetsp.c index 445a4e385..9a163b27e 100644 --- a/fb/fbgetsp.c +++ b/fb/fbgetsp.c @@ -44,6 +44,11 @@ fbGetSpans(DrawablePtr pDrawable, if (!fbDrawableEnabled(pDrawable)) return; + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + fb24_32GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); + return; + } + fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); while (nspans--) { diff --git a/fb/fbglyph.c b/fb/fbglyph.c index 1bdc2d4fd..61cb8de33 100644 --- a/fb/fbglyph.c +++ b/fb/fbglyph.c @@ -53,6 +53,185 @@ fbGlyphIn(RegionPtr pRegion, int x, int y, int width, int height) return RegionContainsRect(pRegion, &box) == rgnIN; } +#define WRITE1(d,n,fg) WRITE((d) + (n), (CARD8) fg) +#define WRITE2(d,n,fg) WRITE((CARD16 *) &(d[n]), (CARD16) fg) +#define WRITE4(d,n,fg) WRITE((CARD32 *) &(d[n]), (CARD32) fg) +#define WRITE8(d) WRITE4(d,0,_ABCA), WRITE4(d,4,_BCAB) + +/* + * This is a bit tricky, but it's brief. Write 12 bytes worth + * of dest, which is four pixels, at a time. This gives constant + * code for each pattern as they're always aligned the same + * + * a b c d a b c d a b c d bytes + * A B C A B C A B C A B C pixels + * + * f0 f1 f2 + * A B C A B C A B C A B C pixels LSB + * C A B C A B C A B C A B pixels MSB + * + * LSB MSB + * A f0 f1 + * B f1 f2 + * C f2 f0 + * A B f0 f2 + * B C f1 f0 + * C A f2 f1 + * A B C A f0 f1 + * B C A B f1 f2 + * C A B C f2 f0 + */ + +#undef _A +#undef _B +#undef _C +#undef _AB +#undef _BC +#undef _CA +#undef _ABCA +#undef _BCAB +#undef _CABC + +#if IMAGE_BYTE_ORDER == MSBFirst +#define _A f1 +#define _B f2 +#define _C f0 +#define _AB f2 +#define _BC f0 +#define _CA f1 +#define _ABCA f1 +#define _BCAB f2 +#define _CABC f0 +#define CASE(a,b,c,d) ((a << 3) | (b << 2) | (c << 1) | d) +#else +#define _A f0 +#define _B f1 +#define _C f2 +#define _AB f0 +#define _BC f1 +#define _CA f2 +#define _ABCA f0 +#define _BCAB f1 +#define _CABC f2 +#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3)) +#endif + +static void +fbGlyph24(FbBits * dstBits, + FbStride dstStride, + int dstBpp, FbStip * stipple, FbBits fg, int x, int height) +{ + int lshift; + FbStip bits; + CARD8 *dstLine; + CARD8 *dst; + FbStip f0, f1, f2; + int n; + int shift; + + f0 = fg; + f1 = FbRot24(f0, 16); + f2 = FbRot24(f0, 8); + + dstLine = (CARD8 *) dstBits; + dstLine += (x & ~3) * 3; + dstStride *= (sizeof(FbBits) / sizeof(CARD8)); + shift = x & 3; + lshift = 4 - shift; + while (height--) { + bits = READ(stipple++); + n = lshift; + dst = dstLine; + while (bits) { + switch (FbStipMoveLsb(FbLeftStipBits(bits, n), 4, n)) { + case CASE(0, 0, 0, 0): + break; + case CASE(1, 0, 0, 0): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + break; + case CASE(0, 1, 0, 0): + WRITE1(dst, 3, _A); + WRITE2(dst, 4, _BC); + break; + case CASE(1, 1, 0, 0): + WRITE4(dst, 0, _ABCA); + WRITE2(dst, 4, _BC); + break; + case CASE(0, 0, 1, 0): + WRITE2(dst, 6, _AB); + WRITE1(dst, 8, _C); + break; + case CASE(1, 0, 1, 0): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + + WRITE2(dst, 6, _AB); + WRITE1(dst, 8, _C); + break; + case CASE(0, 1, 1, 0): + WRITE1(dst, 3, _A); + WRITE4(dst, 4, _BCAB); + WRITE1(dst, 8, _C); + break; + case CASE(1, 1, 1, 0): + WRITE8(dst); + WRITE1(dst, 8, _C); + break; + case CASE(0, 0, 0, 1): + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(1, 0, 0, 1): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(0, 1, 0, 1): + WRITE1(dst, 3, _A); + WRITE2(dst, 4, _BC); + + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(1, 1, 0, 1): + WRITE4(dst, 0, _ABCA); + WRITE2(dst, 4, _BC); + + WRITE1(dst, 9, _A); + WRITE2(dst, 10, _BC); + break; + case CASE(0, 0, 1, 1): + WRITE2(dst, 6, _AB); + WRITE4(dst, 8, _CABC); + break; + case CASE(1, 0, 1, 1): + WRITE2(dst, 0, _AB); + WRITE1(dst, 2, _C); + + WRITE2(dst, 6, _AB); + WRITE4(dst, 8, _CABC); + break; + case CASE(0, 1, 1, 1): + WRITE1(dst, 3, _A); + WRITE4(dst, 4, _BCAB); + WRITE4(dst, 8, _CABC); + break; + case CASE(1, 1, 1, 1): + WRITE8(dst); + WRITE4(dst, 8, _CABC); + break; + } + bits = FbStipLeft(bits, n); + n = 4; + dst += 12; + } + dstLine += dstStride; + } +} + void fbPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, @@ -82,6 +261,9 @@ fbPolyGlyphBlt(DrawablePtr pDrawable, case 16: glyph = fbGlyph16; break; + case 24: + glyph = fbGlyph24; + break; case 32: glyph = fbGlyph32; break; @@ -150,6 +332,9 @@ fbImageGlyphBlt(DrawablePtr pDrawable, case 16: glyph = fbGlyph16; break; + case 24: + glyph = fbGlyph24; + break; case 32: glyph = fbGlyph32; break; diff --git a/fb/fbimage.c b/fb/fbimage.c index bd24728fd..1949a9f82 100644 --- a/fb/fbimage.c +++ b/fb/fbimage.c @@ -68,9 +68,20 @@ fbPutImage(DrawablePtr pDrawable, } break; case ZPixmap: - srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof(FbStip); - fbPutZImage(pDrawable, fbGetCompositeClip(pGC), - pGC->alu, pPriv->pm, x, y, w, h, src, srcStride); + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + srcStride = PixmapBytePad(w, pDrawable->depth); + fb24_32PutZImage(pDrawable, + fbGetCompositeClip(pGC), + pGC->alu, + (FbBits) pGC->planemask, + x, y, w, h, (CARD8 *) pImage, srcStride); + } + else { + srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof(FbStip); + fbPutZImage(pDrawable, + fbGetCompositeClip(pGC), + pGC->alu, pPriv->pm, x, y, w, h, src, srcStride); + } } } @@ -222,6 +233,12 @@ fbGetImage(DrawablePtr pDrawable, if (!fbDrawableEnabled(pDrawable)) return; + if (format == ZPixmap && + pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + fb24_32GetImage(pDrawable, x, y, w, h, format, planeMask, d); + return; + } + fbGetDrawable(pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); x += pDrawable->x; diff --git a/fb/fbline.c b/fb/fbline.c index 38c3c6c16..3e582e6fd 100644 --- a/fb/fbline.c +++ b/fb/fbline.c @@ -104,6 +104,9 @@ fbPolyLine(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) case 16: line = fbPolyline16; break; + case 24: + line = fbPolyline24; + break; case 32: line = fbPolyline32; break; @@ -136,6 +139,9 @@ fbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pseg) case 16: seg = fbPolySegment16; break; + case 24: + seg = fbPolySegment24; + break; case 32: seg = fbPolySegment32; break; diff --git a/fb/fboverlay.c b/fb/fboverlay.c index d47a7c67b..a22d5e96c 100644 --- a/fb/fboverlay.c +++ b/fb/fboverlay.c @@ -56,6 +56,10 @@ fbOverlayCreateWindow(WindowPtr pWin) if (pWin->drawable.class != InputOutput) return TRUE; + if (pWin->drawable.bitsPerPixel == 32) + pWin->drawable.bitsPerPixel = + fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; + for (i = 0; i < pScrPriv->nlayers; i++) { pPixmap = pScrPriv->layer[i].u.run.pixmap; if (pWin->drawable.depth == pPixmap->drawable.depth) { @@ -256,6 +260,30 @@ fbOverlaySetupScreen(ScreenPtr pScreen, pbits1, xsize, ysize, dpix, dpiy, width1, bpp1); } +static Bool +fb24_32OverlayCreateScreenResources(ScreenPtr pScreen) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + int pitch; + Bool retval; + int i; + + if ((retval = fbOverlayCreateScreenResources(pScreen))) { + for (i = 0; i < pScrPriv->nlayers; i++) { + /* fix the screen pixmap */ + PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap; + + if (pPix->drawable.bitsPerPixel == 32) { + pPix->drawable.bitsPerPixel = 24; + pitch = BitmapBytePad(pPix->drawable.width * 24); + pPix->devKind = pitch; + } + } + } + + return retval; +} + Bool fbOverlayFinishScreenInit(ScreenPtr pScreen, void *pbits1, @@ -272,6 +300,7 @@ fbOverlayFinishScreenInit(ScreenPtr pScreen, DepthPtr depths; int nvisuals; int ndepths; + int bpp = 0, imagebpp = 32; VisualID defaultVisual; FbOverlayScrPrivPtr pScrPriv; @@ -286,6 +315,36 @@ fbOverlayFinishScreenInit(ScreenPtr pScreen, if (!pScrPriv) return FALSE; + if (bpp1 == 32 || bpp2 == 32) + bpp = 32; + else if (bpp1 == 24 || bpp2 == 24) + bpp = 24; + + if (bpp == 24) { + int f; + + imagebpp = 32; + /* + * Check to see if we're advertising a 24bpp image format, + * in which case windows will use it in preference to a 32 bit + * format. + */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) { + if (screenInfo.formats[f].bitsPerPixel == 24) { + imagebpp = 24; + break; + } + } + } + if (imagebpp == 32) { + fbGetScreenPrivate(pScreen)->win32bpp = bpp; + fbGetScreenPrivate(pScreen)->pix32bpp = bpp; + } + else { + fbGetScreenPrivate(pScreen)->win32bpp = 32; + fbGetScreenPrivate(pScreen)->pix32bpp = 32; + } + if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1, &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) | ((unsigned long) 1 << (bpp2 - 1)), 8)) { @@ -323,6 +382,10 @@ fbOverlayFinishScreenInit(ScreenPtr pScreen, pScreen->CreateWindow = fbOverlayCreateWindow; pScreen->WindowExposures = fbOverlayWindowExposures; pScreen->CopyWindow = fbOverlayCopyWindow; + if (bpp == 24 && imagebpp == 32) { + pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; + pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources; + } return TRUE; } diff --git a/fb/fbpixmap.c b/fb/fbpixmap.c index af5d7bec0..3010a0263 100644 --- a/fb/fbpixmap.c +++ b/fb/fbpixmap.c @@ -29,15 +29,14 @@ #include "fb.h" PixmapPtr -fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, - unsigned usage_hint) +fbCreatePixmapBpp(ScreenPtr pScreen, int width, int height, int depth, int bpp, + unsigned usage_hint) { PixmapPtr pPixmap; size_t datasize; size_t paddedWidth; int adjust; int base; - int bpp = BitsPerPixel(depth); paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits); if (paddedWidth / 4 > 32767 || height > 32767) @@ -86,6 +85,18 @@ fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, return pPixmap; } +PixmapPtr +fbCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint) +{ + int bpp; + + bpp = BitsPerPixel(depth); + if (bpp == 32 && depth <= 24) + bpp = fbGetScreenPrivate(pScreen)->pix32bpp; + return fbCreatePixmapBpp(pScreen, width, height, depth, bpp, usage_hint); +} + Bool fbDestroyPixmap(PixmapPtr pPixmap) { diff --git a/fb/fbpoint.c b/fb/fbpoint.c index d4c95eea7..be7c801d5 100644 --- a/fb/fbpoint.c +++ b/fb/fbpoint.c @@ -61,13 +61,33 @@ fbDots(FbBits * dstOrig, y = pts->y + yorg; pts++; if (x1 <= x && x < x2 && y1 <= y && y < y2) { - FbStip mask; x = (x + xoff) * dstBpp; d = dst + ((y + yoff) * dstStride) + (x >> FB_STIP_SHIFT); x &= FB_STIP_MASK; + if (dstBpp == 24) { + FbStip leftMask, rightMask; + int n, rot; + FbStip andT, xorT; - mask = FbStipMask(x, dstBpp); - WRITE(d, FbDoMaskRRop(READ(d), and, xor, mask)); + rot = FbFirst24Rot(x); + andT = FbRot24Stip(and, rot); + xorT = FbRot24Stip(xor, rot); + FbMaskStip(x, 24, leftMask, n, rightMask); + if (leftMask) { + WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, leftMask)); + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + d++; + } + if (rightMask) + WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, rightMask)); + } + else { + FbStip mask; + + mask = FbStipMask(x, dstBpp); + WRITE(d, FbDoMaskRRop(READ(d), and, xor, mask)); + } } } } @@ -111,6 +131,9 @@ fbPolyPoint(DrawablePtr pDrawable, case 16: dots = fbDots16; break; + case 24: + dots = fbDots24; + break; case 32: dots = fbDots32; break; diff --git a/fb/fbscreen.c b/fb/fbscreen.c index 4ab807ab5..71bcc5d30 100644 --- a/fb/fbscreen.c +++ b/fb/fbscreen.c @@ -135,13 +135,20 @@ fbSetupScreen(ScreenPtr pScreen, void *pbits, /* pointer to screen bitmap */ #ifdef FB_ACCESS_WRAPPER Bool -wfbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, - int dpix, int dpiy, int width, int bpp, +wfbFinishScreenInit(ScreenPtr pScreen, + void *pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp, SetupWrapProcPtr setupWrap, FinishWrapProcPtr finishWrap) #else Bool -fbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, - int dpix, int dpiy, int width, int bpp) +fbFinishScreenInit(ScreenPtr pScreen, + void *pbits, + int xsize, int ysize, int dpix, int dpiy, int width, int bpp) #endif { VisualPtr visuals; @@ -150,6 +157,7 @@ fbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, int ndepths; int rootdepth; VisualID defaultVisual; + int imagebpp = bpp; #ifdef FB_DEBUG int stride; @@ -161,16 +169,43 @@ fbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, fbSetBits((FbStip *) ((char *) pbits + stride * ysize), stride / sizeof(FbStip), FB_TAIL_BITS); #endif - /* fb requires power-of-two bpp */ - if (Ones(bpp) != 1) - return FALSE; + /* + * By default, a 24bpp screen will use 32bpp images, this avoids + * problems with many applications which just can't handle packed + * pixels. If you want real 24bit images, include a 24bpp + * format in the pixmap formats + */ + if (bpp == 24) { + int f; + + imagebpp = 32; + /* + * Check to see if we're advertising a 24bpp image format, + * in which case windows will use it in preference to a 32 bit + * format. + */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) { + if (screenInfo.formats[f].bitsPerPixel == 24) { + imagebpp = 24; + break; + } + } + } + if (imagebpp == 32) { + fbGetScreenPrivate(pScreen)->win32bpp = bpp; + fbGetScreenPrivate(pScreen)->pix32bpp = bpp; + } + else { + fbGetScreenPrivate(pScreen)->win32bpp = 32; + fbGetScreenPrivate(pScreen)->pix32bpp = 32; + } #ifdef FB_ACCESS_WRAPPER fbGetScreenPrivate(pScreen)->setupWrap = setupWrap; fbGetScreenPrivate(pScreen)->finishWrap = finishWrap; #endif rootdepth = 0; if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &rootdepth, - &defaultVisual, ((unsigned long) 1 << (bpp - 1)), + &defaultVisual, ((unsigned long) 1 << (imagebpp - 1)), 8)) return FALSE; if (!miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, @@ -179,15 +214,24 @@ fbFinishScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, return FALSE; /* overwrite miCloseScreen with our own */ pScreen->CloseScreen = fbCloseScreen; + if (bpp == 24 && imagebpp == 32) { + pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; + pScreen->CreateScreenResources = fb24_32CreateScreenResources; + } return TRUE; } /* dts * (inch/dot) * (25.4 mm / inch) = mm */ #ifdef FB_ACCESS_WRAPPER Bool -wfbScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, - int dpix, int dpiy, int width, int bpp, - SetupWrapProcPtr setupWrap, FinishWrapProcPtr finishWrap) +wfbScreenInit(ScreenPtr pScreen, + void *pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp, SetupWrapProcPtr setupWrap, FinishWrapProcPtr finishWrap) { if (!fbSetupScreen(pScreen, pbits, xsize, ysize, dpix, dpiy, width, bpp)) return FALSE; @@ -198,8 +242,9 @@ wfbScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, } #else Bool -fbScreenInit(ScreenPtr pScreen, void *pbits, int xsize, int ysize, - int dpix, int dpiy, int width, int bpp) +fbScreenInit(ScreenPtr pScreen, + void *pbits, + int xsize, int ysize, int dpix, int dpiy, int width, int bpp) { if (!fbSetupScreen(pScreen, pbits, xsize, ysize, dpix, dpiy, width, bpp)) return FALSE; diff --git a/fb/fbseg.c b/fb/fbseg.c index 6c3d69363..c3c196ab4 100644 --- a/fb/fbseg.c +++ b/fb/fbseg.c @@ -279,6 +279,157 @@ fbBresFillDash(DrawablePtr pDrawable, fbSetFg(pDrawable, pGC, fg); } +static void +fbBresSolid24RRop(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + FbStip and = pPriv->and; + FbStip xor = pPriv->xor; + FbStip leftMask, rightMask; + int nl; + FbStip *d; + int x; + int rot; + FbStip andT, xorT; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) { + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot(x); + andT = FbRot24Stip(and, rot); + xorT = FbRot24Stip(xor, rot); + FbMaskStip(x, 24, leftMask, nl, rightMask); + if (leftMask) { + WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, leftMask)); + d++; + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + } + if (rightMask) + WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, rightMask)); + if (axis == X_AXIS) { + x1 += signdx; + e += e1; + if (e >= 0) { + e += e3; + dst += dstStride; + } + } + else { + dst += dstStride; + e += e1; + if (e >= 0) { + e += e3; + x1 += signdx; + } + } + } + + fbFinishAccess(pDrawable); +} + +static void +fbBresDash24RRop(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, int x1, int y1, int e, int e1, int e3, int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + FbStip andT, xorT; + FbStip fgand = pPriv->and; + FbStip fgxor = pPriv->xor; + FbStip bgand = pPriv->bgand; + FbStip bgxor = pPriv->bgxor; + FbStip leftMask, rightMask; + int nl; + FbStip *d; + int x; + int rot; + + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + + fbGetStipDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + /* compute current dash position */ + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) { + if (even || doOdd) { + if (even) { + andT = fgand; + xorT = fgxor; + } + else { + andT = bgand; + xorT = bgxor; + } + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot(x); + andT = FbRot24Stip(andT, rot); + xorT = FbRot24Stip(xorT, rot); + FbMaskStip(x, 24, leftMask, nl, rightMask); + if (leftMask) { + WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, leftMask)); + d++; + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + } + if (rightMask) + WRITE(d, FbDoMaskRRop(READ(d), andT, xorT, rightMask)); + } + if (axis == X_AXIS) { + x1 += signdx; + e += e1; + if (e >= 0) { + e += e3; + dst += dstStride; + } + } + else { + dst += dstStride; + e += e1; + if (e >= 0) { + e += e3; + x1 += signdx; + } + } + FbDashStep(dashlen, even); + } + + fbFinishAccess(pDrawable); +} + /* * For drivers that want to bail drawing some lines, this * function takes care of selecting the appropriate rasterizer @@ -296,6 +447,8 @@ fbSelectBres(DrawablePtr pDrawable, GCPtr pGC) bres = fbBresFill; if (pGC->fillStyle == FillSolid) { bres = fbBresSolid; + if (dstBpp == 24) + bres = fbBresSolid24RRop; if (pPriv->and == 0) { switch (dstBpp) { case 8: @@ -304,6 +457,9 @@ fbSelectBres(DrawablePtr pDrawable, GCPtr pGC) case 16: bres = fbBresSolid16; break; + case 24: + bres = fbBresSolid24; + break; case 32: bres = fbBresSolid32; break; @@ -315,6 +471,8 @@ fbSelectBres(DrawablePtr pDrawable, GCPtr pGC) bres = fbBresFillDash; if (pGC->fillStyle == FillSolid) { bres = fbBresDash; + if (dstBpp == 24) + bres = fbBresDash24RRop; if (pPriv->and == 0 && (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) { switch (dstBpp) { @@ -324,6 +482,9 @@ fbSelectBres(DrawablePtr pDrawable, GCPtr pGC) case 16: bres = fbBresDash16; break; + case 24: + bres = fbBresDash24; + break; case 32: bres = fbBresDash32; break; diff --git a/fb/fbsetsp.c b/fb/fbsetsp.c index fe94e283c..e09d2e3f3 100644 --- a/fb/fbsetsp.c +++ b/fb/fbsetsp.c @@ -42,6 +42,10 @@ fbSetSpans(DrawablePtr pDrawable, int xoff; int x1, x2; + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) { + fb24_32SetSpans(pDrawable, pGC, src, ppt, pwidth, nspans, fSorted); + return; + } fbGetDrawable(pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); while (nspans--) { d = dst + (ppt->y + dstYoff) * dstStride; diff --git a/fb/fbsolid.c b/fb/fbsolid.c index 1ee165950..cad286a43 100644 --- a/fb/fbsolid.c +++ b/fb/fbsolid.c @@ -37,6 +37,10 @@ fbSolid(FbBits * dst, int n, nmiddle; int startbyte, endbyte; + if (bpp == 24 && (!FbCheck24Pix(and) || !FbCheck24Pix(xor))) { + fbSolid24(dst, dstStride, dstX, width, height, and, xor); + return; + } dst += dstX >> FB_SHIFT; dstX &= FB_MASK; FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte, @@ -63,3 +67,113 @@ fbSolid(FbBits * dst, dst += dstStride; } } + +void +fbSolid24(FbBits * dst, + FbStride dstStride, + int dstX, int width, int height, FbBits and, FbBits xor) +{ + FbBits startmask, endmask; + FbBits xor0 = 0, xor1 = 0, xor2 = 0; + FbBits and0 = 0, and1 = 0, and2 = 0; + FbBits xorS = 0, andS = 0, xorE = 0, andE = 0; + int n, nmiddle; + int rotS, rot; + + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + /* + * Rotate pixel values this far across the word to align on + * screen pixel boundaries + */ + rot = FbFirst24Rot(dstX); + FbMaskBits(dstX, width, startmask, nmiddle, endmask); + if (startmask) + dstStride--; + dstStride -= nmiddle; + + /* + * Precompute rotated versions of the rasterop values + */ + rotS = rot; + xor = FbRot24(xor, rotS); + and = FbRot24(and, rotS); + if (startmask) { + xorS = xor; + andS = and; + xor = FbNext24Pix(xor); + and = FbNext24Pix(and); + } + + if (nmiddle) { + xor0 = xor; + and0 = and; + xor1 = FbNext24Pix(xor0); + and1 = FbNext24Pix(and0); + xor2 = FbNext24Pix(xor1); + and2 = FbNext24Pix(and1); + } + + if (endmask) { + switch (nmiddle % 3) { + case 0: + xorE = xor; + andE = and; + break; + case 1: + xorE = xor1; + andE = and1; + break; + case 2: + xorE = xor2; + andE = and2; + break; + } + } + + while (height--) { + if (startmask) { + WRITE(dst, FbDoMaskRRop(READ(dst), andS, xorS, startmask)); + dst++; + } + n = nmiddle; + if (!and0) { + while (n >= 3) { + WRITE(dst++, xor0); + WRITE(dst++, xor1); + WRITE(dst++, xor2); + n -= 3; + } + if (n) { + WRITE(dst++, xor0); + n--; + if (n) { + WRITE(dst++, xor1); + } + } + } + else { + while (n >= 3) { + WRITE(dst, FbDoRRop(READ(dst), and0, xor0)); + dst++; + WRITE(dst, FbDoRRop(READ(dst), and1, xor1)); + dst++; + WRITE(dst, FbDoRRop(READ(dst), and2, xor2)); + dst++; + n -= 3; + } + if (n) { + WRITE(dst, FbDoRRop(READ(dst), and0, xor0)); + dst++; + n--; + if (n) { + WRITE(dst, FbDoRRop(READ(dst), and1, xor1)); + dst++; + } + } + } + if (endmask) + WRITE(dst, FbDoMaskRRop(READ(dst), andE, xorE, endmask)); + dst += dstStride; + } +} diff --git a/fb/fbwindow.c b/fb/fbwindow.c index fca871d62..7a5fac869 100644 --- a/fb/fbwindow.c +++ b/fb/fbwindow.c @@ -33,6 +33,9 @@ fbCreateWindow(WindowPtr pWin) { dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), fbGetScreenPixmap(pWin->drawable.pScreen)); + if (pWin->drawable.bitsPerPixel == 32 && pWin->drawable.depth <= 24) + pWin->drawable.bitsPerPixel = + fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; return TRUE; } @@ -133,6 +136,13 @@ fbFixupWindowPixmap(DrawablePtr pDrawable, PixmapPtr *ppPixmap) { PixmapPtr pPixmap = *ppPixmap; + if (pPixmap->drawable.bitsPerPixel != pDrawable->bitsPerPixel) { + pPixmap = fb24_32ReformatTile(pPixmap, pDrawable->bitsPerPixel); + if (!pPixmap) + return; + (*pDrawable->pScreen->DestroyPixmap) (*ppPixmap); + *ppPixmap = pPixmap; + } if (FbEvenTile(pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel)) fbPadPixmap(pPixmap); } diff --git a/fb/wfbrename.h b/fb/wfbrename.h index ffdcbed96..b2d2ff772 100644 --- a/fb/wfbrename.h +++ b/fb/wfbrename.h @@ -1,22 +1,35 @@ +#define fb24_32CopyMtoN wfb24_32CopyMtoN +#define fb24_32CreateScreenResources wfb24_32CreateScreenResources +#define fb24_32GetImage wfb24_32GetImage +#define fb24_32GetSpans wfb24_32GetSpans +#define fb24_32ModifyPixmapHeader wfb24_32ModifyPixmapHeader +#define fb24_32PutZImage wfb24_32PutZImage +#define fb24_32ReformatTile wfb24_32ReformatTile +#define fb24_32SetSpans wfb24_32SetSpans #define fbAddTraps wfbAddTraps #define fbAddTriangles wfbAddTriangles #define fbAllocatePrivates wfbAllocatePrivates #define fbArc16 wfbArc16 +#define fbArc24 wfbArc24 #define fbArc32 wfbArc32 #define fbArc8 wfbArc8 #define fbBlt wfbBlt +#define fbBlt24 wfbBlt24 #define fbBltOne wfbBltOne +#define fbBltOne24 wfbBltOne24 #define fbBltPlane wfbBltPlane #define fbBltStip wfbBltStip #define fbBres wfbBres #define fbBresDash wfbBresDash #define fbBresDash16 wfbBresDash16 +#define fbBresDash24 wfbBresDash24 #define fbBresDash32 wfbBresDash32 #define fbBresDash8 wfbBresDash8 #define fbBresFill wfbBresFill #define fbBresFillDash wfbBresFillDash #define fbBresSolid wfbBresSolid #define fbBresSolid16 wfbBresSolid16 +#define fbBresSolid24 wfbBresSolid24 #define fbBresSolid32 wfbBresSolid32 #define fbBresSolid8 wfbBresSolid8 #define fbChangeWindowAttributes wfbChangeWindowAttributes @@ -34,6 +47,7 @@ #define fbCreateDefColormap wfbCreateDefColormap #define fbCreateGC wfbCreateGC #define fbCreatePixmap wfbCreatePixmap +#define fbCreatePixmapBpp wfbCreatePixmapBpp #define fbCreateWindow wfbCreateWindow #define fbDestroyGlyphCache wfbDestroyGlyphCache #define fbDestroyPixmap wfbDestroyPixmap @@ -41,6 +55,7 @@ #define fbDoCopy wfbDoCopy #define fbDots wfbDots #define fbDots16 wfbDots16 +#define fbDots24 wfbDots24 #define fbDots32 wfbDots32 #define fbDots8 wfbDots8 #define fbExpandDirectColors wfbExpandDirectColors @@ -56,6 +71,7 @@ #define fbGetSpans wfbGetSpans #define _fbGetWindowPixmap _wfbGetWindowPixmap #define fbGlyph16 wfbGlyph16 +#define fbGlyph24 wfbGlyph24 #define fbGlyph32 wfbGlyph32 #define fbGlyph8 wfbGlyph8 #define fbGlyphs wfbGlyphs @@ -66,6 +82,7 @@ #define fbListInstalledColormaps wfbListInstalledColormaps #define FbMergeRopBits wFbMergeRopBits #define fbOver wfbOver +#define fbOver24 wfbOver24 #define fbOverlayCloseScreen wfbOverlayCloseScreen #define fbOverlayCopyWindow wfbOverlayCopyWindow #define fbOverlayCreateScreenResources wfbOverlayCreateScreenResources @@ -86,11 +103,13 @@ #define fbPolyGlyphBlt wfbPolyGlyphBlt #define fbPolyLine wfbPolyLine #define fbPolyline16 wfbPolyline16 +#define fbPolyline24 wfbPolyline24 #define fbPolyline32 wfbPolyline32 #define fbPolyline8 wfbPolyline8 #define fbPolyPoint wfbPolyPoint #define fbPolySegment wfbPolySegment #define fbPolySegment16 wfbPolySegment16 +#define fbPolySegment24 wfbPolySegment24 #define fbPolySegment32 wfbPolySegment32 #define fbPolySegment8 wfbPolySegment8 #define fbPositionWindow wfbPositionWindow @@ -115,6 +134,7 @@ #define fbSetVisualTypesAndMasks wfbSetVisualTypesAndMasks #define _fbSetWindowPixmap _wfbSetWindowPixmap #define fbSolid wfbSolid +#define fbSolid24 wfbSolid24 #define fbSolidBoxClipped wfbSolidBoxClipped #define fbTrapezoids wfbTrapezoids #define fbTriangles wfbTriangles diff --git a/glamor/glamor_core.c b/glamor/glamor_core.c index 9a7510da0..57f8f2389 100644 --- a/glamor/glamor_core.c +++ b/glamor/glamor_core.c @@ -198,6 +198,43 @@ glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) * Preempt fbValidateGC by doing its work and masking the change out, so * that we can do the Prepare/finish_access. */ +#ifdef FB_24_32BIT + if ((changes & GCTile) && fbGetRotatedPixmap(gc)) { + gc->pScreen->DestroyPixmap(fbGetRotatedPixmap(gc)); + fbGetRotatedPixmap(gc) = 0; + } + + if (gc->fillStyle == FillTiled) { + PixmapPtr old_tile, new_tile; + + old_tile = gc->tile.pixmap; + if (old_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { + new_tile = fbGetRotatedPixmap(gc); + if (!new_tile || + new_tile->drawable.bitsPerPixel != drawable->bitsPerPixel) { + if (new_tile) + gc->pScreen->DestroyPixmap(new_tile); + /* fb24_32ReformatTile will do direct access of a newly- + * allocated pixmap. + */ + glamor_fallback + ("GC %p tile FB_24_32 transformat %p.\n", gc, old_tile); + + if (glamor_prepare_access + (&old_tile->drawable, GLAMOR_ACCESS_RO)) { + new_tile = + fb24_32ReformatTile(old_tile, drawable->bitsPerPixel); + glamor_finish_access(&old_tile->drawable); + } + } + if (new_tile) { + fbGetRotatedPixmap(gc) = old_tile; + gc->tile.pixmap = new_tile; + changes |= GCTile; + } + } + } +#endif if (changes & GCTile) { if (!gc->tileIsPixel) { glamor_pixmap_private *pixmap_priv = diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am index baf380d4d..c996752d5 100644 --- a/hw/xfree86/Makefile.am +++ b/hw/xfree86/Makefile.am @@ -26,6 +26,8 @@ if XF86UTILS XF86UTILS_SUBDIR = utils endif +XAA_SUBDIR = xaa + if VGAHW VGAHW_SUBDIR = vgahw endif @@ -36,12 +38,12 @@ endif SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \ ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \ - $(DRI2_SUBDIR) . i2c dixmods xkb \ + $(DRI2_SUBDIR) . i2c dixmods xkb xaa \ fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \ $(GLAMOR_EGL_SUBDIR) drivers -DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \ - parser ramdac shadowfb vgahw \ +DIST_SUBDIR = common ddc i2c x86emu int10 fbdevhw os-support \ + parser ramdac shadowfb vgahw xaa \ loader dixmods xkb dri dri2 exa modes \ utils doc man glamor_egl drivers diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am index 39c1e90f0..bd8c0dd22 100644 --- a/hw/xfree86/common/Makefile.am +++ b/hw/xfree86/common/Makefile.am @@ -60,8 +60,7 @@ sdk_HEADERS = compiler.h xf86.h xf86Module.h xf86Opt.h \ xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \ $(XVSDKINCS) $(XF86VMODE_SDK) $(DGA_SDK) xorgVersion.h \ xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h \ - xf86platformBus.h xf86MatchDrivers.h \ - xaarop.h + xf86platformBus.h xf86MatchDrivers.h CLEANFILES = $(BUILT_SOURCES) @@ -90,8 +89,7 @@ EXTRA_DIST = \ modeline2c.awk \ xf86VGAarbiter.h \ xf86VGAarbiterPriv.h \ - $(DISTKBDSOURCES) \ - xaarop.h + $(DISTKBDSOURCES) if LNXACPI XORG_CFLAGS += -DHAVE_ACPI diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h index eb788d3fd..568e8469d 100644 --- a/hw/xfree86/common/compiler.h +++ b/hw/xfree86/common/compiler.h @@ -212,6 +212,42 @@ extern _X_EXPORT void xf86WriteMmio32Le (void *, unsigned long, unsigned int); #define write_mem_barrier() /* NOP */ #endif +#include /* needed for memmove */ + +static __inline__ uint32_t +ldl_u(uint32_t * p) +{ + uint32_t ret; + + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ uint16_t +ldw_u(uint16_t * p) +{ + uint16_t ret; + + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ void +stl_u(uint32_t val, uint32_t * p) +{ + uint32_t tmp = val; + + memmove(p, &tmp, sizeof(*p)); +} + +static __inline__ void +stw_u(uint16_t val, uint16_t * p) +{ + uint16_t tmp = val; + + memmove(p, &tmp, sizeof(*p)); +} + #ifdef __GNUC__ #if defined(__alpha__) diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h index 927a7a7f1..fbbffaa14 100644 --- a/hw/xfree86/common/xf86.h +++ b/hw/xfree86/common/xf86.h @@ -81,6 +81,9 @@ extern _X_EXPORT Bool xf86DRI2Enabled(void); #define BOOLTOSTRING(b) ((b) ? "TRUE" : "FALSE") +#define PIX24TOBPP(p) (((p) == Pix24Use24) ? 24 : \ + (((p) == Pix24Use32) ? 32 : 0)) + /* Compatibility functions for pre-input-thread drivers */ static inline _X_DEPRECATED int xf86BlockSIGIO(void) { input_lock(); return 0; } static inline _X_DEPRECATED void xf86UnblockSIGIO(int wasset) { input_unlock(); } @@ -147,8 +150,8 @@ extern _X_EXPORT EntityInfoPtr xf86GetEntityInfo(int entityIndex); extern _X_EXPORT Bool xf86IsEntityPrimary(int entityIndex); extern _X_EXPORT ScrnInfoPtr xf86FindScreenForEntity(int entityIndex); -#define xf86SetLastScrnFlag(e, s) do { } while (0) - +extern _X_EXPORT int xf86GetLastScrnFlag(int entityIndex); +extern _X_EXPORT void xf86SetLastScrnFlag(int entityIndex, int scrnIndex); extern _X_EXPORT Bool xf86IsEntityShared(int entityIndex); extern _X_EXPORT void xf86SetEntityShared(int entityIndex); extern _X_EXPORT Bool xf86IsEntitySharable(int entityIndex); @@ -271,6 +274,8 @@ extern _X_EXPORT const char * xf86GetVisualName(int visual); extern _X_EXPORT int xf86GetVerbosity(void); +extern _X_EXPORT Pix24Flags +xf86GetPix24(void); extern _X_EXPORT int xf86GetDepth(void); extern _X_EXPORT rgb diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c index fd144dbe7..d647b32b8 100644 --- a/hw/xfree86/common/xf86Bus.c +++ b/hw/xfree86/common/xf86Bus.c @@ -573,6 +573,25 @@ xf86PostProbe(void) " for all framebuffer devices\n"); } +int +xf86GetLastScrnFlag(int entityIndex) +{ + if (entityIndex < xf86NumEntities) { + return xf86Entities[entityIndex]->lastScrnFlag; + } + else { + return -1; + } +} + +void +xf86SetLastScrnFlag(int entityIndex, int scrnIndex) +{ + if (entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->lastScrnFlag = scrnIndex; + } +} + Bool xf86IsEntityShared(int entityIndex) { diff --git a/hw/xfree86/common/xf86Bus.h b/hw/xfree86/common/xf86Bus.h index 0d44a8a61..52b497af6 100644 --- a/hw/xfree86/common/xf86Bus.h +++ b/hw/xfree86/common/xf86Bus.h @@ -51,6 +51,7 @@ typedef struct { Bool active; Bool inUse; BusRec bus; + int lastScrnFlag; DevUnion *entityPrivates; int numInstances; GDevPtr *devices; diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 8d8ebf1b5..f19cd15eb 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -629,6 +629,7 @@ typedef enum { FLAG_DPMS_STANDBYTIME, FLAG_DPMS_SUSPENDTIME, FLAG_DPMS_OFFTIME, + FLAG_PIXMAP, FLAG_NOPM, FLAG_XINERAMA, FLAG_LOG, @@ -674,6 +675,8 @@ static OptionInfoRec FlagOptions[] = { {0}, FALSE}, {FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER, {0}, FALSE}, + {FLAG_PIXMAP, "Pixmap", OPTV_INTEGER, + {0}, FALSE}, {FLAG_NOPM, "NoPM", OPTV_BOOLEAN, {0}, FALSE}, {FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN, @@ -717,6 +720,7 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) { XF86OptionPtr optp, tmp; int i; + Pix24Flags pix24 = Pix24DontCare; Bool value; MessageType from; const char *s; @@ -939,6 +943,34 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) i, MAX_TIME_IN_MIN); #endif + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i); + switch (i) { + case 24: + pix24 = Pix24Use24; + break; + case 32: + pix24 = Pix24Use32; + break; + case -1: + break; + default: + ErrorF("Pixmap option's value (%d) must be 24 or 32\n", i); + break; + } + if (xf86Pix24 != Pix24DontCare) { + xf86Info.pixmap24 = xf86Pix24; + xf86Info.pix24From = X_CMDLINE; + } + else if (pix24 != Pix24DontCare) { + xf86Info.pixmap24 = pix24; + xf86Info.pix24From = X_CONFIG; + } + else { + xf86Info.pixmap24 = Pix24DontCare; + xf86Info.pix24From = X_DEFAULT; + } + #ifdef PANORAMIX from = X_DEFAULT; if (!noPanoramiXExtension) diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c index 65a3192df..afb183ac3 100644 --- a/hw/xfree86/common/xf86Globals.c +++ b/hw/xfree86/common/xf86Globals.c @@ -117,6 +117,8 @@ xf86InfoRec xf86Info = { .vidModeAllowNonLocal = FALSE, .miscModInDevEnabled = TRUE, .miscModInDevAllowNonLocal = FALSE, + .pixmap24 = Pix24DontCare, + .pix24From = X_DEFAULT, .pmFlag = TRUE, #if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) .forceInputDevices = FALSE, @@ -185,6 +187,7 @@ char *xf86KeyboardName = NULL; int xf86Verbose = DEFAULT_VERBOSE; int xf86LogVerbose = DEFAULT_LOG_VERBOSE; int xf86FbBpp = -1; +Pix24Flags xf86Pix24 = Pix24DontCare; int xf86Depth = -1; rgb xf86Weight = { 0, 0, 0 }; diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c index 98dc3722a..951dd68b0 100644 --- a/hw/xfree86/common/xf86Helper.c +++ b/hw/xfree86/common/xf86Helper.c @@ -345,15 +345,33 @@ xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad) * Also find a Display subsection matching the depth/bpp found. * * Sets the following ScrnInfoRec fields: - * bitsPerPixel, depth, display, imageByteOrder, + * bitsPerPixel, pixmap24, depth, display, imageByteOrder, * bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats, * formats, fbFormat. */ +/* Can the screen handle 24 bpp pixmaps */ +#define DO_PIX24(f) ((f & Support24bppFb) || \ + ((f & Support32bppFb) && (f & SupportConvert24to32))) + /* Can the screen handle 32 bpp pixmaps */ #define DO_PIX32(f) ((f & Support32bppFb) || \ ((f & Support24bppFb) && (f & SupportConvert32to24))) +/* Does the screen prefer 32bpp fb for 24bpp pixmaps */ +#define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \ + && (f & PreferConvert24to32)) + +/* Does the screen prefer 24bpp fb for 32bpp pixmaps */ +#define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \ + && (f & PreferConvert32to24)) + +/* Can the screen handle 32bpp pixmaps for 24bpp fb */ +#define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24)) + +/* Can the screen handle 24bpp pixmaps for 32bpp fb */ +#define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32)) + #ifndef GLOBAL_DEFAULT_DEPTH #define GLOBAL_DEFAULT_DEPTH 24 #endif @@ -364,15 +382,16 @@ xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, { int i; DispPtr disp; + Pix24Flags pix24 = xf86Info.pixmap24; + Bool nomatch = FALSE; scrp->bitsPerPixel = -1; scrp->depth = -1; + scrp->pixmap24 = Pix24DontCare; scrp->bitsPerPixelFrom = X_DEFAULT; scrp->depthFrom = X_DEFAULT; if (xf86FbBpp > 0) { - if (xf86FbBpp == 24) /* lol no */ - xf86FbBpp = 32; scrp->bitsPerPixel = xf86FbBpp; scrp->bitsPerPixelFrom = X_CMDLINE; } @@ -451,14 +470,57 @@ xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, scrp->bitsPerPixel = 8; else if (scrp->depth <= 16) scrp->bitsPerPixel = 16; - else if (scrp->depth <= 24 && DO_PIX32(depth24flags)) { - scrp->bitsPerPixel = 32; + else if (scrp->depth <= 24) { + /* + * Figure out if a choice is possible based on the depth24 + * and pix24 flags. + */ + /* Check pix24 first */ + if (pix24 != Pix24DontCare) { + if (pix24 == Pix24Use32) { + if (DO_PIX32(depth24flags)) { + if (CHOOSE24FOR32(depth24flags)) + scrp->bitsPerPixel = 24; + else + scrp->bitsPerPixel = 32; + } + else { + nomatch = TRUE; + } + } + else if (pix24 == Pix24Use24) { + if (DO_PIX24(depth24flags)) { + if (CHOOSE32FOR24(depth24flags)) + scrp->bitsPerPixel = 32; + else + scrp->bitsPerPixel = 24; + } + else { + nomatch = TRUE; + } + } + } + else { + if (DO_PIX32(depth24flags)) { + if (CHOOSE24FOR32(depth24flags)) + scrp->bitsPerPixel = 24; + else + scrp->bitsPerPixel = 32; + } + else if (DO_PIX24(depth24flags)) { + if (CHOOSE32FOR24(depth24flags)) + scrp->bitsPerPixel = 32; + else + scrp->bitsPerPixel = 24; + } + } } else if (scrp->depth <= 32) scrp->bitsPerPixel = 32; else { xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "No bpp for depth (%d)\n", scrp->depth); + "Specified depth (%d) is greater than 32\n", + scrp->depth); return FALSE; } } @@ -469,7 +531,11 @@ xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, return FALSE; } if (scrp->bitsPerPixel < 0) { - if ((depth24flags & (Support24bppFb | Support32bppFb)) == + if (nomatch) + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Driver can't support depth 24 pixmap format (%d)\n", + PIX24TOBPP(pix24)); + else if ((depth24flags & (Support24bppFb | Support32bppFb)) == NoDepth24Support) xf86DrvMsg(scrp->scrnIndex, X_ERROR, "Driver can't support depth 24\n"); @@ -507,6 +573,7 @@ xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, case 4: case 8: case 16: + case 24: case 32: break; default: @@ -522,6 +589,14 @@ xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, return FALSE; } + /* set scrp->pixmap24 if the driver isn't flexible */ + if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) { + scrp->pixmap24 = Pix24Use24; + } + if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) { + scrp->pixmap24 = Pix24Use32; + } + /* * Find the Display subsection matching the depth/fbbpp and initialise * scrp->display with it. @@ -1377,6 +1452,12 @@ xf86GetVerbosity(void) return max(xf86Verbose, xf86LogVerbose); } +Pix24Flags +xf86GetPix24(void) +{ + return xf86Info.pixmap24; +} + int xf86GetDepth(void) { diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c index 5695e71ac..3c6f262cc 100644 --- a/hw/xfree86/common/xf86Init.c +++ b/hw/xfree86/common/xf86Init.c @@ -289,6 +289,9 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) int i, j, k, scr_index; const char **modulelist; void **optionlist; + Pix24Flags screenpix24, pix24; + MessageType pix24From = X_DEFAULT; + Bool pix24Fail = FALSE; Bool autoconfig = FALSE; Bool sigio_blocked = FALSE; Bool want_hw_access = FALSE; @@ -521,6 +524,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) * Collect all pixmap formats and check for conflicts at the display * level. Should we die here? Or just delete the offending screens? */ + screenpix24 = Pix24DontCare; for (i = 0; i < xf86NumScreens; i++) { if (xf86Screens[i]->imageByteOrder != xf86Screens[0]->imageByteOrder) @@ -536,7 +540,38 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) if (xf86Screens[i]->bitmapBitOrder != xf86Screens[0]->bitmapBitOrder) FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); + + /* Determine the depth 24 pixmap format the screens would like */ + if (xf86Screens[i]->pixmap24 != Pix24DontCare) { + if (screenpix24 == Pix24DontCare) + screenpix24 = xf86Screens[i]->pixmap24; + else if (screenpix24 != xf86Screens[i]->pixmap24) + FatalError + ("Inconsistent depth 24 pixmap format. Exiting\n"); + } + } + /* check if screenpix24 is consistent with the config/cmdline */ + if (xf86Info.pixmap24 != Pix24DontCare) { + pix24 = xf86Info.pixmap24; + pix24From = xf86Info.pix24From; + if (screenpix24 != Pix24DontCare && + screenpix24 != xf86Info.pixmap24) + pix24Fail = TRUE; } + else if (screenpix24 != Pix24DontCare) { + pix24 = screenpix24; + pix24From = X_PROBED; + } + else + pix24 = Pix24Use32; + + if (pix24Fail) + FatalError("Screen(s) can't use the required depth 24 pixmap format" + " (%d). Exiting\n", PIX24TOBPP(pix24)); + + /* Initialise the depth 24 format */ + for (j = 0; j < numFormats && formats[j].depth != 24; j++); + formats[j].bitsPerPixel = PIX24TOBPP(pix24); /* Collect additional formats */ for (i = 0; i < xf86NumScreens; i++) { @@ -562,6 +597,15 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) } } formatsDone = TRUE; + + /* If a screen uses depth 24, show what the pixmap format is */ + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->depth == 24) { + xf86Msg(pix24From, "Depth 24 pixmap format is %d bpp\n", + PIX24TOBPP(pix24)); + break; + } + } } else { /* @@ -1036,8 +1080,12 @@ ddxProcessArgument(int argc, char **argv, int i) xf86sFlag = TRUE; return 0; } - if (!strcmp(argv[i], "-pixmap32") || !strcmp(argv[i], "-pixmap24")) { - /* silently accept */ + if (!strcmp(argv[i], "-pixmap24")) { + xf86Pix24 = Pix24Use24; + return 1; + } + if (!strcmp(argv[i], "-pixmap32")) { + xf86Pix24 = Pix24Use32; return 1; } if (!strcmp(argv[i], "-fbbpp")) { @@ -1217,6 +1265,8 @@ ddxUseMsg(void) ErrorF("-verbose [n] verbose startup messages\n"); ErrorF("-logverbose [n] verbose log messages\n"); ErrorF("-quiet minimal startup messages\n"); + ErrorF("-pixmap24 use 24bpp pixmaps for depth 24\n"); + ErrorF("-pixmap32 use 32bpp pixmaps for depth 24\n"); ErrorF("-fbbpp n set bpp for the framebuffer. Default: 8\n"); ErrorF("-depth n set colour depth. Default: 8\n"); ErrorF @@ -1307,6 +1357,30 @@ PixmapFormatPtr xf86GetPixFormat(ScrnInfoPtr pScrn, int depth) { int i; + static PixmapFormatRec format; /* XXX not reentrant */ + + /* + * When the formats[] list initialisation isn't complete, check the + * depth 24 pixmap config/cmdline options and screen-specified formats. + */ + + if (!formatsDone) { + if (depth == 24) { + Pix24Flags pix24 = Pix24DontCare; + + format.depth = 24; + format.scanlinePad = BITMAP_SCANLINE_PAD; + if (xf86Info.pixmap24 != Pix24DontCare) + pix24 = xf86Info.pixmap24; + else if (pScrn->pixmap24 != Pix24DontCare) + pix24 = pScrn->pixmap24; + if (pix24 == Pix24Use24) + format.bitsPerPixel = 24; + else + format.bitsPerPixel = 32; + return &format; + } + } for (i = 0; i < numFormats; i++) if (formats[i].depth == depth) diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h index d5185d8df..3fe703a73 100644 --- a/hw/xfree86/common/xf86Priv.h +++ b/hw/xfree86/common/xf86Priv.h @@ -68,6 +68,7 @@ extern _X_EXPORT char *xf86PointerName; extern _X_EXPORT char *xf86KeyboardName; extern _X_EXPORT int xf86FbBpp; extern _X_EXPORT int xf86Depth; +extern _X_EXPORT Pix24Flags xf86Pix24; extern _X_EXPORT rgb xf86Weight; extern _X_EXPORT Gamma xf86Gamma; diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h index 31861148f..0ffb5e3a9 100644 --- a/hw/xfree86/common/xf86Privstr.h +++ b/hw/xfree86/common/xf86Privstr.h @@ -78,6 +78,8 @@ typedef struct { Bool miscModInDevEnabled; /* Allow input devices to be * changed */ Bool miscModInDevAllowNonLocal; + Pix24Flags pixmap24; + MessageType pix24From; Bool pmFlag; MessageType iglxFrom; XF86_GlxVisuals glxVisuals; diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h index 9072932cb..66ae25f08 100644 --- a/hw/xfree86/common/xf86str.h +++ b/hw/xfree86/common/xf86str.h @@ -421,6 +421,13 @@ typedef struct _confdrirec { typedef void *(*funcPointer) (void); +/* flags for depth 24 pixmap options */ +typedef enum { + Pix24DontCare = 0, + Pix24Use24, + Pix24Use32 +} Pix24Flags; + /* Power management events: so far we only support APM */ typedef enum { @@ -587,6 +594,7 @@ typedef struct _ScrnInfoRec { PixmapFormatRec fbFormat; int bitsPerPixel; /* fb bpp */ + Pix24Flags pixmap24; /* pixmap pref for depth 24 */ int depth; /* depth of default visual */ MessageType depthFrom; /* set from config? */ MessageType bitsPerPixelFrom; /* set from config? */ diff --git a/hw/xfree86/doc/README.modes b/hw/xfree86/doc/README.modes index 54543bf0a..13d31fc44 100644 --- a/hw/xfree86/doc/README.modes +++ b/hw/xfree86/doc/README.modes @@ -133,10 +133,11 @@ this function computes an initial configuration for the server. It tries to enable as much hardware as possible using some fairly simple heuristics. The 'canGrow' parameter indicates that the frame buffer does not have a fixed -size. When the frame buffer has a fixed size, the configuration selects a -'reasonablely large' frame buffer so that common reconfiguration options are -possible. For resizable frame buffers, the frame buffer is set to the smallest -size that encloses the desired configuration. +size (fixed size frame buffers are required by XAA). When the frame buffer +has a fixed size, the configuration selects a 'reasonablely large' frame +buffer so that common reconfiguration options are possible. For resizable +frame buffers, the frame buffer is set to the smallest size that encloses +the desired configuration. 3.2 ScreenInit functions diff --git a/hw/xfree86/doc/ddxDesign.xml b/hw/xfree86/doc/ddxDesign.xml index 1eed293fe..a046fd0e8 100644 --- a/hw/xfree86/doc/ddxDesign.xml +++ b/hw/xfree86/doc/ddxDesign.xml @@ -331,8 +331,8 @@ that. This is a significant difference compared with the old design. The entry points for drawing operations are already taken care of by -the framebuffer code. Extensions and enhancements to framebuffer code -are outside the scope of this document. +the framebuffer code (including, XAA). Extensions and enhancements to +framebuffer code are outside the scope of this document. @@ -1960,9 +1960,10 @@ also include the video card's saved state. -Per-screen data for other modules that the driver uses that is reset for each -server generation is hooked into the ScrnInfoRec -through its privates field. +Per-screen data for other modules that the driver uses (for example, +the XAA module) that is reset for each server generation is hooked into +the ScrnInfoRec through it's privates +field. @@ -3235,6 +3236,14 @@ The following include files are typically required by video drivers: + + If a driver uses XAA, it needs these: + + "xaa.h" + "xaalocal.h" + + + If a driver uses the fb manager, it needs this: @@ -3453,6 +3462,31 @@ manager is allowed to manage. This is typically a box with a width of can be fit within the total video memory, however, the driver can reserve areas at the extremities by passing a smaller area to the manager. + + +xf86InitFBManager() must be called before XAA is +initialized since XAA uses the manager for it's pixmap cache. + + + +An alternative function is provided to allow the driver to initialize +the framebuffer manager with a Region rather than a box. + + + Bool xf86InitFBManagerRegion(ScreenPtr pScreen, + RegionPtr FullRegion); + + +xf86InitFBManagerRegion(), unlike +xf86InitFBManager(), does not remove the area used for +the visible screen so that area should not be included in the region +passed to the function. xf86InitFBManagerRegion() is +useful when non-contiguous areas are available to be managed, and is +required when multiple framebuffers are stored in video memory (as in +the case where an overlay of a different depth is stored as a second +framebuffer in offscreen memory). + + @@ -8255,6 +8289,12 @@ ZZZPreInit(ScrnInfoPtr pScrn, int flags) ZZZFreeRec(pScrn); return FALSE; + /* Load XAA if needed */ + if (!pZzz->noAccel || pZzz->hwCursor) + if (!xf86LoadSubModule(pScrn, "xaa")) { + ZZZFreeRec(pScrn); + return FALSE; + } /* Done */ return TRUE; diff --git a/hw/xfree86/doc/exa-driver.txt b/hw/xfree86/doc/exa-driver.txt index da39d3f91..048307ee7 100644 --- a/hw/xfree86/doc/exa-driver.txt +++ b/hw/xfree86/doc/exa-driver.txt @@ -8,10 +8,15 @@ from system memory, and Porter-Duff compositing and transform operations. Configuration ------------- +A new config file option, AccelMethod, should be added to your driver, to allow +the user to select between the EXA and XAA acceleration APIs. + Some drivers implement a per-instance useEXA flag to track whether EXA is -active or not. +active or not. It can be helpful to also conditionalize XAA support with an +ifdef so that it can easily be turned off/removed in the future. -Setting the flag can be done in the driver's Options parsing routine. +Setting the flag and checking for AccelMethod can be done in the driver's +Options parsing routine. Loading EXA ------------ diff --git a/hw/xfree86/int10/generic.c b/hw/xfree86/int10/generic.c index 191571192..7ed2dfb9c 100644 --- a/hw/xfree86/int10/generic.c +++ b/hw/xfree86/int10/generic.c @@ -20,42 +20,6 @@ #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) -#include /* needed for memmove */ - -static __inline__ uint32_t -ldl_u(uint32_t * p) -{ - uint32_t ret; - - memmove(&ret, p, sizeof(*p)); - return ret; -} - -static __inline__ uint16_t -ldw_u(uint16_t * p) -{ - uint16_t ret; - - memmove(&ret, p, sizeof(*p)); - return ret; -} - -static __inline__ void -stl_u(uint32_t val, uint32_t * p) -{ - uint32_t tmp = val; - - memmove(p, &tmp, sizeof(*p)); -} - -static __inline__ void -stw_u(uint16_t val, uint16_t * p) -{ - uint16_t tmp = val; - - memmove(p, &tmp, sizeof(*p)); -} - static uint8_t read_b(xf86Int10InfoPtr pInt, int addr); static uint16_t read_w(xf86Int10InfoPtr pInt, int addr); static uint32_t read_l(xf86Int10InfoPtr pInt, int addr); diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man index 3ec6e2c25..145d4a374 100644 --- a/hw/xfree86/man/Xorg.man +++ b/hw/xfree86/man/Xorg.man @@ -294,6 +294,21 @@ Disable Silken Mouse support. Disable the automatic switching on X server reset and shutdown to the VT that was active when the server started, if supported by the OS. .TP 8 +.B \-pixmap24 +Set the internal pixmap format for depth 24 pixmaps to 24 bits per pixel. +The default is usually 32 bits per pixel. There is normally little +reason to use this option. Some client applications don't like this +pixmap format, even though it is a perfectly legal format. This is +equivalent to the +.B Pixmap +xorg.conf(__filemansuffix__) file option. +.TP 8 +.B \-pixmap32 +Set the internal pixmap format for depth 24 pixmaps to 32 bits per pixel. +This is usually the default. This is equivalent to the +.B Pixmap +xorg.conf(__filemansuffix__) file option. +.TP 8 .BI \-pointer " pointer-name" Use the xorg.conf(@filemansuffix@) file .B InputDevice diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man index d0aef7be8..53d33111f 100644 --- a/hw/xfree86/man/xorg.conf.man +++ b/hw/xfree86/man/xorg.conf.man @@ -614,6 +614,14 @@ option set (see the MONITOR section below). Set the maximum number of clients allowed to connect to the X server. Acceptable values are 64, 128, 256 or 512. .TP 7 +.BI "Option \*qPixmap\*q \*q" bpp \*q +This sets the pixmap format to use for depth 24. +Allowed values for +.I bpp +are 24 and 32. +Default: 32 unless driver constraints don't allow this (which is rare). +Note: some clients don't behave well when this value is set to 24. +.TP 7 .BI "Option \*qNoPM\*q \*q" boolean \*q Disables something to do with power management events. Default: PM enabled on platforms that support it. diff --git a/hw/xfree86/ramdac/.gitignore b/hw/xfree86/ramdac/.gitignore new file mode 100644 index 000000000..c55c8c1ab --- /dev/null +++ b/hw/xfree86/ramdac/.gitignore @@ -0,0 +1,2 @@ +# Add & Override for this directory and it's subdirectories +xf86BitOrder.c diff --git a/hw/xfree86/ramdac/Makefile.am b/hw/xfree86/ramdac/Makefile.am index ffae2c31f..8e14f2678 100644 --- a/hw/xfree86/ramdac/Makefile.am +++ b/hw/xfree86/ramdac/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libramdac.la -libramdac_la_SOURCES = xf86CursorRD.c xf86HWCurs.c +libramdac_la_SOURCES = xf86CursorRD.c xf86HWCurs.c xf86BitOrder.c sdk_HEADERS = xf86Cursor.h @@ -8,3 +8,13 @@ EXTRA_DIST = xf86CursorPriv.h CURSOR.NOTES AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) AM_CPPFLAGS = $(XORG_INCS) + +DISTCLEANFILES = xf86BitOrder.c + +AM_CFLAGS = -DXAAReverseBitOrder=xf86ReverseBitOrder -DRAMDAC_MODULE \ + $(DIX_CFLAGS) $(XORG_CFLAGS) +INCLUDES = $(XORG_INCS) + +xf86BitOrder.c: + $(AM_V_GEN)echo "#define XAAReverseBitOrder xf86ReverseBitOrder" > $@ + $(AM_V_GEN)echo "#include \"$(srcdir)/../xaa/xaaBitOrder.c\"" >> $@ diff --git a/hw/xfree86/ramdac/xf86CursorPriv.h b/hw/xfree86/ramdac/xf86CursorPriv.h index 397d2a14b..aeb99ca30 100644 --- a/hw/xfree86/ramdac/xf86CursorPriv.h +++ b/hw/xfree86/ramdac/xf86CursorPriv.h @@ -44,6 +44,8 @@ void xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed); Bool xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr); Bool xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr); +CARD32 xf86ReverseBitOrder(CARD32 data); + extern _X_EXPORT DevPrivateKeyRec xf86CursorScreenKeyRec; #define xf86CursorScreenKey (&xf86CursorScreenKeyRec) diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c index ddba5e6c6..48963c6c8 100644 --- a/hw/xfree86/ramdac/xf86HWCurs.c +++ b/hw/xfree86/ramdac/xf86HWCurs.c @@ -25,7 +25,7 @@ static void xf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs); -static CARD32 +CARD32 xf86ReverseBitOrder(CARD32 v) { return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) | diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh index 5fd5b5c2f..9d95c5052 100755 --- a/hw/xfree86/sdksyms.sh +++ b/hw/xfree86/sdksyms.sh @@ -177,6 +177,20 @@ cat > sdksyms.c << EOF #endif +/* hw/xfree86/xaa/Makefile.am -- module */ +/* +#include "xaa.h" +#include "xaalocal.h" +#include "xaarop.h" + */ + + +/* hw/xfree86/dixmods/extmod/Makefile.am -- module */ +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + + /* hw/xfree86/parser/Makefile.am */ #include "xf86Parser.h" #include "xf86Optrec.h" @@ -200,6 +214,7 @@ cat > sdksyms.c << EOF #include "mizerarc.h" #include "micoord.h" #include "mifillarc.h" +#include "miwideline.h" #include "mistruct.h" #include "mioverlay.h" diff --git a/hw/xfree86/xaa/.gitignore b/hw/xfree86/xaa/.gitignore new file mode 100644 index 000000000..1211d01e1 --- /dev/null +++ b/hw/xfree86/xaa/.gitignore @@ -0,0 +1,4 @@ +# Add & Override for this directory and it's subdirectories +[lms]-xaa*.c +[lm]f3-xaa*.c +[lm][f3]-xaa*.c diff --git a/hw/xfree86/xaa/Makefile.am b/hw/xfree86/xaa/Makefile.am new file mode 100644 index 000000000..5614d723a --- /dev/null +++ b/hw/xfree86/xaa/Makefile.am @@ -0,0 +1,79 @@ +LSB_FIRST = l-xaaBitmap.c l-xaaStipple.c l-xaaTEGlyph.c +LSB_3_FIRST = l3-xaaBitmap.c l3-xaaStipple.c +MSB_FIRST = m-xaaBitmap.c m-xaaStipple.c m-xaaTEGlyph.c +MSB_3_FIRST = m3-xaaBitmap.c m3-xaaStipple.c +LSB_FIXED = lf-xaaBitmap.c lf-xaaStipple.c lf-xaaTEGlyph.c +LSB_3_FIXED = lf3-xaaBitmap.c lf3-xaaStipple.c +MSB_FIXED = mf-xaaBitmap.c mf-xaaStipple.c mf-xaaTEGlyph.c +MSB_3_FIXED = mf3-xaaBitmap.c mf3-xaaStipple.c +POLYSEG = s-xaaLine.c s-xaaDashLine.c + +if XAA + +libxaa_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG) +libxaa_la_LIBADD = $(PIXMAN_LIBS) +if COMPOSITE +libxaa_la_LIBADD += $(top_builddir)/miext/cw/libcw.la +endif + +module_LTLIBRARIES = libxaa.la +libxaa_la_SOURCES = xaaInit.c xaaGC.c xaaInitAccel.c xaaFallback.c \ + xaaBitBlt.c xaaCpyArea.c xaaGCmisc.c xaaCpyWin.c \ + xaaCpyPlane.c xaaFillRect.c xaaTEText.c xaaNonTEText.c \ + xaaPCache.c xaaSpans.c xaaROP.c xaaImage.c \ + xaaRect.c xaaLineMisc.c xaaBitOrder.c \ + xaaFillPoly.c xaaWideLine.c xaaTables.c xaaFillArc.c \ + xaaLine.c xaaDashLine.c xaaOverlay.c xaaOffscreen.c \ + xaaOverlayDF.c xaaStateChange.c xaaPict.c $(POLYSEG) \ + $(LSB_FIRST) $(MSB_FIRST) $(LSB_FIXED) $(MSB_FIXED) \ + $(LSB_3_FIRST) $(MSB_3_FIRST) $(LSB_3_FIXED) $(MSB_3_FIXED) +${POLYSEG}: + $(AM_V_GEN)echo "#define POLYSEGMENT" > $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:s-%=%}"' >> $@ +${LSB_FIRST}: + $(AM_V_GEN)echo "#define LSBFIRST" > $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:l-%=%}"' >> $@ +${LSB_3_FIRST}: + $(AM_V_GEN)echo "#define LSBFIRST" > $@ + $(AM_V_GEN)echo "#define TRIPLE_BITS" >> $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:l3-%=%}"' >> $@ +${LSB_FIXED}: + $(AM_V_GEN)echo "#define LSBFIRST" > $@ + $(AM_V_GEN)echo "#define FIXEDBASE" >> $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:lf-%=%}"' >> $@ +${LSB_3_FIXED}: + $(AM_V_GEN)echo "#define LSBFIRST" > $@ + $(AM_V_GEN)echo "#define TRIPLE_BITS" >> $@ + $(AM_V_GEN)echo "#define FIXEDBASE" >> $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:lf3-%=%}"' >> $@ +${MSB_FIRST}: + $(AM_V_GEN)echo "#define MSBFIRST" > $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:m-%=%}"' >> $@ +${MSB_3_FIRST}: + $(AM_V_GEN)echo "#define MSBFIRST" > $@ + $(AM_V_GEN)echo "#define TRIPLE_BITS" >> $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:m3-%=%}"' >> $@ +${MSB_FIXED}: + $(AM_V_GEN)echo "#define MSBFIRST" > $@ + $(AM_V_GEN)echo "#define FIXEDBASE" >> $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:mf-%=%}"' >> $@ +${MSB_3_FIXED}: + $(AM_V_GEN)echo "#define MSBFIRST" > $@ + $(AM_V_GEN)echo "#define TRIPLE_BITS" >> $@ + $(AM_V_GEN)echo "#define FIXEDBASE" >> $@ + $(AM_V_GEN)echo '#include "$(srcdir)/${@:mf3-%=%}"' >> $@ + +endif # XAA + +DISTCLEANFILES = $(POLYSEG) \ + $(LSB_FIRST) $(LSB_FIXED) $(MSB_FIRST) $(MSB_FIXED) \ + $(LSB_3_FIRST) $(LSB_3_FIXED) $(MSB_3_FIRST) $(MSB_3_FIXED) + +sdk_HEADERS = xaa.h xaalocal.h xaarop.h +EXTRA_DIST = xaacexp.h xaawrap.h xaaLine.c xaaDashLine.c \ + xaaStipple.c xaaTEGlyph.c xaaNonTEGlyph.c xaaBitmap.c \ + XAA.HOWTO + +INCLUDES = $(XORG_INCS) -I$(srcdir)/../../../miext/cw + +AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/hw/xfree86/xaa/XAA.HOWTO b/hw/xfree86/xaa/XAA.HOWTO new file mode 100644 index 000000000..cbd71c138 --- /dev/null +++ b/hw/xfree86/xaa/XAA.HOWTO @@ -0,0 +1,1427 @@ + + + XAA.HOWTO + + This file describes how to add basic XAA support to a chipset driver. + +0) What is XAA +1) XAA Initialization and Shutdown +2) The Primitives + 2.0 Generic Flags + 2.1 Screen to Screen Copies + 2.2 Solid Fills + 2.3 Solid Lines + 2.4 Dashed Lines + 2.5 Color Expand Fills + 2.5.1 Screen to Screen Color Expansion + 2.5.2 CPU to Screen Color Expansion + 2.5.2.1 The Direct Method + 2.5.2.2 The Indirect Method + 2.6 8x8 Mono Pattern Fills + 2.7 8x8 Color Pattern Fills + 2.8 Image Writes + 2.8.1 The Direct Method + 2.8.2 The Indirect Method + 2.9 Clipping +3) The Pixmap Cache +4) Offscreen Pixmaps + +/********************************************************************/ + +0) WHAT IS XAA + + XAA (the XFree86 Acceleration Architecture) is a device dependent +layer that encapsulates the unaccelerated framebuffer rendering layer, +intercepting rendering commands sent to it from higher levels of the +server. For rendering tasks where hardware acceleration is not +possible, XAA allows the requests to proceed to the software rendering +code. Otherwise, XAA breaks the sometimes complicated X primitives +into simpler primitives more suitable for hardware acceleration and +will use accelerated functions exported by the chipset driver to +render these. + + XAA provides a simple, easy to use driver interface that allows +the driver to communicate its acceleration capabilities and restrictions +back to XAA. XAA will use the information provided by the driver +to determine whether or not acceleration will be possible for a +particular X primitive. + + + +1) XAA INITIALIZATION AND SHUTDOWN + + All relevant prototypes and defines are in xaa.h. + + To Initialize the XAA layer, the driver should allocate an XAAInfoRec +via XAACreateInfoRec(), fill it out as described in this document +and pass it to XAAInit(). XAAInit() must be called _after_ the +framebuffer initialization (usually cfb?ScreenInit or similar) since +it is "wrapping" that layer. XAAInit() should be called _before_ the +cursor initialization (usually miDCInitialize) since the cursor +layer needs to "wrap" all the rendering code including XAA. + + When shutting down, the driver should free the XAAInfoRec +structure in its CloseScreen function via XAADestroyInfoRec(). +The prototypes for the functions mentioned above are as follows: + + XAAInfoRecPtr XAACreateInfoRec(void); + Bool XAAInit(ScreenPtr, XAAInfoRecPtr); + void XAADestroyInfoRec(XAAInfoRec); + + The driver informs XAA of it's acceleration capablities by +filling out an XAAInfoRec structure and passing it to XAAInit(). +The XAAInfoRec structure contains many fields, most of which are +function pointers and flags. Each primitive will typically have +two functions and a set of flags associated with it, but it may +have more. These two functions are the "SetupFor" and "Subsequent" +functions. The "SetupFor" function tells the driver that the +hardware should be initialized for a particular type of graphics +operation. After the "SetupFor" function, one or more calls to the +"Subsequent" function will be made to indicate that an instance +of the particular primitive should be rendered by the hardware. +The details of each instance (width, height, etc...) are given +with each "Subsequent" function. The set of flags associated +with each primitive lets the driver tell XAA what its hardware +limitations are (eg. It doesn't support a planemask, it can only +do one of the raster-ops, etc...). + + Of the XAAInfoRec fields, one is required. This is the +Sync function. XAA initialization will fail if this function +is not provided. + +void Sync(ScrnInfoPtr pScrn) /* Required */ + + Sync will be called when XAA needs to be certain that all + graphics coprocessor operations are finished, such as when + the framebuffer must be written to or read from directly + and it must be certain that the accelerator will not be + overwriting the area of interest. + + One needs to make certain that the Sync function not only + waits for the accelerator fifo to empty, but that it waits for + the rendering of that last operation to complete. + + It is guaranteed that no direct framebuffer access will + occur after a "SetupFor" or "Subsequent" function without + the Sync function being called first. + + + +2) THE PRIMITIVES + +2.0 Generic Flags + + Each primitive type has a set of flags associated with it which +allow the driver to tell XAA what the hardware limitations are. +The common ones are as follows: + +/* Foreground, Background, rop and planemask restrictions */ + + GXCOPY_ONLY + + This indicates that the accelerator only supports GXcopy + for the particular primitive. + + ROP_NEEDS_SOURCE + + This indicates that the accelerator doesn't supports a + particular primitive with rops that don't involve the source. + These rops are GXclear, GXnoop, GXinvert and GXset. If neither + this flag nor GXCOPY_ONLY is defined, it is assumed that the + accelerator supports all 16 raster operations (rops) for that + primitive. + + NO_PLANEMASK + + This indicates that the accelerator does not support a hardware + write planemask for the particular primitive. + + RGB_EQUAL + + This indicates that the particular primitive requires the red, + green and blue bytes of the foreground color (and background color, + if applicable) to be equal. This is useful for 24bpp when a graphics + coprocessor is used in 8bpp mode, which is not uncommon in older + hardware since some have no support for or only limited support for + acceleration at 24bpp. This way, many operations will be accelerated + for the common case of "grayscale" colors. This flag should only + be used in 24bpp. + + In addition to the common ones listed above which are possible for +nearly all primitives, each primitive may have its own flags specific +to that primitive. If such flags exist they are documented in the +descriptions of those primitives below. + + + + +2.1 Screen to Screen Copies + + The SetupFor and Subsequent ScreenToScreenCopy functions provide + an interface for copying rectangular areas from video memory to + video memory. To accelerate this primitive the driver should + provide both the SetupFor and Subsequent functions and indicate + the hardware restrictions via the ScreenToScreenCopyFlags. The + NO_PLANEMASK, GXCOPY_ONLY and ROP_NEEDS_SOURCE flags as described + in Section 2.0 are valid as well as the following: + + NO_TRANSPARENCY + + This indicates that the accelerator does not support skipping + of color keyed pixels when copying from the source to the destination. + + TRANSPARENCY_GXCOPY_ONLY + + This indicates that the accelerator supports skipping of color keyed + pixels only when the rop is GXcopy. + + ONLY_LEFT_TO_RIGHT_BITBLT + + This indicates that the hardware only accepts blitting when the + x direction is positive. + + ONLY_TWO_BITBLT_DIRECTIONS + + This indicates that the hardware can only cope with blitting when + the direction of x is the same as the direction in y. + + +void SetupForScreenToScreenCopy( ScrnInfoPtr pScrn, + int xdir, int ydir, + int rop, + unsigned int planemask, + int trans_color ) + + When this is called, SubsequentScreenToScreenCopy will be called + one or more times directly after. If ydir is 1, then the accelerator + should copy starting from the top (minimum y) of the source and + proceed downward. If ydir is -1, then the accelerator should copy + starting from the bottom of the source (maximum y) and proceed + upward. If xdir is 1, then the accelerator should copy each + y scanline starting from the leftmost pixel of the source. If + xdir is -1, it should start from the rightmost pixel. + If trans_color is not -1 then trans_color indicates that the + accelerator should not copy pixels with the color trans_color + from the source to the destination, but should skip them. + Trans_color is always -1 if the NO_TRANSPARENCY flag is set. + + +void SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, + int x1, int y1, + int x2, int y2, + int width, int height) + + Copy a rectangle "width" x "height" from the source (x1,y1) to the + destination (x2,y2) using the parameters passed by the last + SetupForScreenToScreenCopy call. (x1,y1) and (x2,y2) always denote + the upper left hand corners of the source and destination regardless + of which xdir and ydir values are given by SetupForScreenToScreenCopy. + + + +2.2 Solid Fills + + The SetupFor and Subsequent SolidFill(Rect/Trap) functions provide + an interface for filling rectangular areas of the screen with a + foreground color. To accelerate this primitive the driver should + provide both the SetupForSolidFill and SubsequentSolidFillRect + functions and indicate the hardware restrictions via the SolidFillFlags. + The driver may optionally provide a SubsequentSolidFillTrap if + it is capable of rendering the primitive correctly. + The GXCOPY_ONLY, ROP_NEEDS_SOURCE, NO_PLANEMASK and RGB_EQUAL flags + as described in Section 2.0 are valid. + + +void SetupForSolidFill(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask) + + SetupForSolidFill indicates that any combination of the following + may follow it. + + SubsequentSolidFillRect + SubsequentSolidFillTrap + + + +void SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) + + Fill a rectangle of dimensions "w" by "h" with origin at (x,y) + using the color, rop and planemask given by the last + SetupForSolidFill call. + +void SubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR) + + These parameters describe a trapezoid via a version of + Bresenham's parameters. "y" is the top line. "h" is the + number of spans to be filled in the positive Y direction. + "left" and "right" indicate the starting X values of the + left and right edges. dy/dx describes the edge slope. + These are not the deltas between the beginning and ending + points on an edge. They merely describe the slope. "e" is + the initial error term. It's the relationships between dx, + dy and e that define the edge. + If your engine does not do bresenham trapezoids or does + not allow the programmer to specify the error term then + you are not expected to be able to accelerate them. + + +2.3 Solid Lines + + XAA provides an interface for drawing thin lines. In order to + draw X lines correctly a high degree of accuracy is required. + This usually limits line acceleration to hardware which has a + Bresenham line engine, though depending on the algorithm used, + other line engines may come close if they accept 16 bit line + deltas. XAA has both a Bresenham line interface and a two-point + line interface for drawing lines of arbitrary orientation. + Additionally there is a SubsequentSolidHorVertLine which will + be used for all horizontal and vertical lines. Horizontal and + vertical lines are handled separately since hardware that doesn't + have a line engine (or has one that is unusable due to precision + problems) can usually draw these lines by some other method such + as drawing them as thin rectangles. Even for hardware that can + draw arbitrary lines via the Bresenham or two-point interfaces, + the SubsequentSolidHorVertLine is used for horizontal and vertical + lines since most hardware is able to render the horizontal lines + and sometimes the vertical lines faster by other methods (Hint: + try rendering horizontal lines as flattened rectangles). If you have + not provided a SubsequentSolidHorVertLine but you have provided + Bresenham or two-point lines, a SubsequentSolidHorVertLine function + will be supplied for you. + + The flags field associated with Solid Lines is SolidLineFlags and + the GXCOPY_ONLY, ROP_NEEDS_SOURCE, NO_PLANEMASK and RGB_EQUAL flags as + described in Section 2.0 are valid restrictions. + + Some line engines have line biases hardcoded to comply with + Microsoft line biasing rules. A tell-tale sign of this is the + hardware lines not matching the software lines in the zeroth and + fourth octants. The driver can set the flag: + + MICROSOFT_ZERO_LINE_BIAS + + in the AccelInfoRec.Flags field to adjust the software lines to + match the hardware lines. This is in the generic flags field + rather than the SolidLineFlags since this flag applies to all + software zero-width lines on the screen and not just the solid ones. + + +void SetupForSolidLine(ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask) + + SetupForSolidLine indicates that any combination of the following + may follow it. + + SubsequentSolidBresenhamLine + SubsequentSolidTwoPointLine + SubsequentSolidHorVertLine + + +void SubsequentSolidHorVertLine( ScrnInfoPtr pScrn, + int x, int y, int len, int dir ) + + All vertical and horizontal solid thin lines are rendered with + this function. The line starts at coordinate (x,y) and extends + "len" pixels inclusive. In the direction indicated by "dir." + The direction is either DEGREES_O or DEGREES_270. That is, it + always extends to the right or down. + + + +void SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags) + + Draw a line from (x1,y1) to (x2,y2). If the flags field contains + the flag OMIT_LAST, the last pixel should not be drawn. Otherwise, + the pixel at (x2,y2) should be drawn. + + If you use the TwoPoint line interface there is a good possibility + that your line engine has hard-coded line biases that do not match + the default X zero-width lines. If so, you may need to set the + MICROSOFT_ZERO_LINE_BIAS flag described above. Note that since + any vertex in the 16-bit signed coordinate system is valid, your + line engine is expected to handle 16-bit values if you have hardware + line clipping enabled. If your engine cannot handle 16-bit values, + you should not use hardware line clipping. + + +void SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, + int x, int y, int major, int minor, int err, int len, int octant) + + "X" and "y" are the starting point of the line. "Major" and "minor" + are the major and minor step constants. "Err" is the initial error + term. "Len" is the number of pixels to be drawn (inclusive). "Octant" + can be any combination of the following flags OR'd together: + + Y_MAJOR Y is the major axis (X otherwise) + X_DECREASING The line is drawn from right to left + Y_DECREASING The line is drawn from bottom to top + + The major, minor and err terms are the "raw" Bresenham parameters + consistent with a line engine that does: + + e = err; + while(len--) { + DRAW_POINT(x,y); + e += minor; + if(e >= 0) { + e -= major; + TAKE_ONE_STEP_ALONG_MINOR_AXIS; + } + TAKE_ONE_STEP_ALONG_MAJOR_AXIS; + } + + IBM 8514 style Bresenham line interfaces require their parameters + modified in the following way: + + Axial = minor; + Diagonal = minor - major; + Error = minor + err; + +SolidBresenhamLineErrorTermBits + + This field allows the driver to tell XAA how many bits large its + Bresenham parameter registers are. Many engines have registers that + only accept 12 or 13 bit Bresenham parameters, and the parameters + for clipped lines may overflow these if they are not scaled down. + If this field is not set, XAA will assume the engine can accomodate + 16 bit parameters, otherwise, it will scale the parameters to the + size specified. + + +2.4 Dashed Lines + + The same degree of accuracy required by the solid lines is required + for drawing dashed lines as well. The dash pattern itself is a + buffer of binary data where ones are expanded into the foreground + color and zeros either correspond to the background color or + indicate transparency depending on whether or not DoubleDash or + OnOffDashes are being drawn. + + The flags field associated with dashed Lines is DashedLineFlags and + the GXCOPY_ONLY, ROP_NEEDS_SOURCE, NO_PLANEMASK and RGB_EQUAL flags as + described in Section 2.0 are valid restrictions. Additionally, the + following flags are valid: + + NO_TRANSPARENCY + + This indicates that the driver cannot support dashed lines + with transparent backgrounds (OnOffDashes). + + TRANSPARENCY_ONLY + + This indicates that the driver cannot support dashes with + both a foreground and background color (DoubleDashes). + + LINE_PATTERN_POWER_OF_2_ONLY + + This indicates that only patterns with a power of 2 length + can be accelerated. + + LINE_PATTERN_LSBFIRST_MSBJUSTIFIED + LINE_PATTERN_LSBFIRST_LSBJUSTIFIED + LINE_PATTERN_MSBFIRST_MSBJUSTIFIED + LINE_PATTERN_MSBFIRST_LSBJUSTIFIED + + These describe how the line pattern should be packed. + The pattern buffer is DWORD padded. LSBFIRST indicates + that the pattern runs from the LSB end to the MSB end. + MSBFIRST indicates that the pattern runs from the MSB end + to the LSB end. When the pattern does not completely fill + the DWORD padded buffer, the pattern will be justified + towards the MSB or LSB end based on the flags above. + + + The following field indicates the maximum length dash pattern that + should be accelerated. + + int DashPatternMaxLength + + +void SetupForDashedLine(ScrnInfoPtr pScrn, + int fg, int bg, int rop, unsigned int planemask, + int length, unsigned char *pattern) + + + SetupForDashedLine indicates that any combination of the following + may follow it. + + SubsequentDashedBresenhamLine + SubsequentDashedTwoPointLine + + If "bg" is -1, then the background (pixels corresponding to clear + bits in the pattern) should remain unmodified. "Bg" indicates the + background color otherwise. "Length" indicates the length of + the pattern in bits and "pattern" points to the DWORD padded buffer + holding the pattern which has been packed according to the flags + set above. + + +void SubsequentDashedTwoPointLine( ScrnInfoPtr pScrn, + int x1, int y1, int x2, int y2, int flags, int phase) + +void SubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, + int x1, int y1, int major, int minor, int err, int len, int octant, + int phase) + + These are the same as the SubsequentSolidTwoPointLine and + SubsequentBresenhamLine functions except for the addition + of the "phase" field which indicates the offset into the dash + pattern that the pixel at (x1,y1) corresponds to. + + As with the SubsequentBresenhamLine, there is an + + int DashedBresenhamLineErrorTermBits + + field which indicates the size of the error term registers + used with dashed lines. This is usually the same value as + the field for the solid lines (because it's usually the same + register). + + + +2.5 Color Expansion Fills + + When filling a color expansion rectangle, the accelerator + paints each pixel depending on whether or not a bit in a + corresponding bitmap is set or clear. Opaque expansions are + when a set bit corresponds to the foreground color and a clear + bit corresponds to the background color. A transparent expansion + is when a set bit corresponds to the foreground color and a + clear bit indicates that the pixel should remain unmodified. + + The graphics accelerator usually has access to the source + bitmap in one of two ways: 1) the bitmap data is sent serially + to the accelerator by the CPU through some memory mapped aperture + or 2) the accelerator reads the source bitmap out of offscreen + video memory. Some types of primitives are better suited towards + one method or the other. Type 2 is useful for reusable patterns + such as stipples which can be cached in offscreen memory. The + aperature method can be used for stippling but the CPU must pass + the data across the bus each time a stippled fill is to be performed. + For expanding 1bpp client pixmaps or text strings to the screen, + the aperature method is usually superior because the intermediate + copy in offscreen memory needed by the second method would only be + used once. Unfortunately, many accelerators can only do one of these + methods and not both. + + XAA provides both ScreenToScreen and CPUToScreen color expansion + interfaces for doing color expansion fills. The ScreenToScreen + functions can only be used with hardware that supports reading + of source bitmaps from offscreen video memory, and these are only + used for cacheable patterns such as stipples. There are two + variants of the CPUToScreen routines - a direct method intended + for hardware that has a transfer aperature, and an indirect method + intended for hardware without transfer aperatures or hardware + with unusual transfer requirements. Hardware that can only expand + bitmaps from video memory should supply ScreenToScreen routines + but also ScanlineCPUToScreen (indirect) routines to optimize transfers + of non-cacheable data. Hardware that can only accept source bitmaps + through an aperature should supply CPUToScreen (or ScanlineCPUToScreen) + routines. Hardware that can do both should provide both ScreenToScreen + and CPUToScreen routines. + + For both ScreenToScreen and CPUToScreen interfaces, the GXCOPY_ONLY, + ROP_NEEDS_SOURCE, NO_PLANEMASK and RGB_EQUAL flags described in + Section 2.0 are valid as well as the following: + + /* bit order requirements (one of these must be set) */ + + BIT_ORDER_IN_BYTE_LSBFIRST + + This indicates that least significant bit in each byte of the source + data corresponds to the leftmost of that block of 8 pixels. This + is the prefered format. + + BIT_ORDER_IN_BYTE_MSBFIRST + + This indicates that most significant bit in each byte of the source + data corresponds to the leftmost of that block of 8 pixels. + + /* transparency restrictions */ + + NO_TRANSPARENCY + + This indicates that the accelerator cannot do a transparent expansion. + + TRANSPARENCY_ONLY + + This indicates that the accelerator cannot do an opaque expansion. + In cases where where the background needs to be filled, XAA will + render the primitive in two passes when using the CPUToScreen + interface, but will not do so with the ScreenToScreen interface + since that would require caching of two patterns. Some + ScreenToScreen hardware may be able to render two passes at the + driver level and remove the TRANSPARENCY_ONLY restriction if + it can render pixels corresponding to the zero bits. + + + +2.5.1 Screen To Screen Color Expansion + + The ScreenToScreenColorExpandFill routines provide an interface + for doing expansion blits from source patterns stored in offscreen + video memory. + + void SetupForScreenToScreenColorExpandFill (ScrnInfoPtr pScrn, + int fg, int bg, + int rop, unsigned int planemask) + + + Ones in the source bitmap will correspond to the fg color. + Zeros in the source bitmap will correspond to the bg color + unless bg = -1. In that case the pixels corresponding to the + zeros in the bitmap shall be left unmodified by the accelerator. + + For hardware that doesn't allow an easy implementation of skipleft, the + driver can replace CacheMonoStipple function with one that stores multiple + rotated copies of the stipple and select between them. In this case the + driver should set CacheColorExpandDensity to tell XAA how many copies of + the pattern are stored in the width of a cache slot. For instance if the + hardware can specify the starting address in bytes, then 8 rotated copies + of the stipple are needed and CacheColorExpandDensity should be set to 8. + + void SubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int offset ) + + + Fill a rectangle "w" x "h" at location (x,y). The source pitch + between scanlines is the framebuffer pitch (pScrn->displayWidth + pixels) and srcx and srcy indicate the start of the source pattern + in units of framebuffer pixels. "Offset" indicates the bit offset + into the pattern that corresponds to the pixel being painted at + "x" on the screen. Some hardware accepts source coordinates in + units of bits which makes implementation of the offset trivial. + In that case, the bit address of the source bit corresponding to + the pixel painted at (x,y) would be: + + (srcy * pScrn->displayWidth + srcx) * pScrn->bitsPerPixel + offset + + It should be noted that the offset assumes LSBFIRST hardware. + For MSBFIRST hardware, the driver may need to implement the + offset by bliting only from byte boundaries and hardware clipping. + + + +2.5.2 CPU To Screen Color Expansion + + + The CPUToScreenColorExpandFill routines provide an interface for + doing expansion blits from source patterns stored in system memory. + There are two varieties of this primitive, a CPUToScreenColorExpandFill + and a ScanlineCPUToScreenColorExpandFill. With the + CPUToScreenColorExpandFill method, the source data is sent serially + through a memory mapped aperature. With the Scanline version, the + data is rendered scanline at a time into intermediate buffers with + a call to SubsequentColorExpandScanline following each scanline. + + These two methods have separate flags fields, the + CPUToScreenColorExpandFillFlags and ScanlineCPUToScreenColorExpandFillFlags + respectively. Flags specific to one method or the other are described + in sections 2.5.2.1 and 2.5.2.2 but for both cases the bit order and + transparency restrictions listed at the beginning of section 2.5 are + valid as well as the following: + + /* clipping (optional) */ + + LEFT_EDGE_CLIPPING + + This indicates that the accelerator supports omission of up to + 31 pixels on the left edge of the rectangle to be filled. This + is beneficial since it allows transfer of the source bitmap to + always occur from DWORD boundaries. + + LEFT_EDGE_CLIPPING_NEGATIVE_X + + This flag indicates that the accelerator can render color expansion + rectangles even if the value of x origin is negative (off of + the screen on the left edge). + + /* misc */ + + TRIPLE_BITS_24BPP + + When enabled (must be in 24bpp mode), color expansion functions + are expected to require three times the amount of bits to be + transferred so that 24bpp grayscale colors can be used with color + expansion in 8bpp coprocessor mode. Each bit is expanded to 3 + bits when writing the monochrome data. + + + 2.5.1 The Direct Method + + + Using the direct method of color expansion XAA will send all + bitmap data to the accelerator serially through an memory mapped + transfer window defined by the following two fields: + + unsigned char *ColorExpandBase + + This indicates the memory address of the beginning of the aperture. + + int ColorExpandRange + + This indicates the size in bytes of the aperture. + + The driver should specify how the transfered data should be padded. + There are options for both the padding of each Y scanline and for the + total transfer to the aperature. + One of the following two flags must be set: + + CPU_TRANSFER_PAD_DWORD + + This indicates that the total transfer (sum of all scanlines) sent + to the aperature must be DWORD padded. This is the default behavior. + + CPU_TRANSFER_PAD_QWORD + + This indicates that the total transfer (sum of all scanlines) sent + to the aperature must be QWORD padded. With this set, XAA will send + an extra DWORD to the aperature when needed to ensure that only + an even number of DWORDs are sent. + + And then there are the flags for padding of each scanline: + + SCANLINE_PAD_DWORD + + This indicates that each Y scanline should be DWORD padded. + This is the only option available and is the default. + + Finally, there is the CPU_TRANSFER_BASE_FIXED flag which indicates + that the aperture is a single register rather than a range of + registers, and XAA should write all of the data to the first DWORD. + If the ColorExpandRange is not large enough to accomodate scanlines + the width of the screen, this option will be forced. That is, the + ColorExpandRange must be: + + ((virtualX + 31)/32) * 4 bytes or more. + + ((virtualX + 62)/32 * 4) if LEFT_EDGE_CLIPPING_NEGATIVE_X is set. + + If the TRIPLE_BITS_24BPP flag is set, the required area should be + multiplied by three. + + +void SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask) + + + + Ones in the source bitmap will correspond to the fg color. + Zeros in the source bitmap will correspond to the bg color + unless bg = -1. In that case the pixels corresponding to the + zeros in the bitmap shall be left unmodified by the accelerator. + + +void SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft ) + + When this function is called, the accelerator should be setup + to fill a rectangle of dimension "w" by "h" with origin at (x,y) + in the fill style prescribed by the last call to + SetupForCPUToScreenColorExpandFill. XAA will pass the data to + the aperture immediately after this function is called. If the + skipleft is non-zero (and LEFT_EDGE_CLIPPING has been enabled), then + the accelerator _should_not_ render skipleft pixels on the leftmost + edge of the rectangle. Some engines have an alignment feature + like this built in, some others can do this using a clipping + window. + + It can be arranged for XAA to call Sync() after it is through + calling the Subsequent function by setting SYNC_AFTER_COLOR_EXPAND + in the CPUToScreenColorExpandFillFlags. This can provide the driver + with an oportunity to reset a clipping window if needed. + + +2.5.2 The Indirect Method + + Using the indirect method, XAA will render the bitmap data scanline + at a time to one or more buffers. These buffers may be memory + mapped apertures or just intermediate storage. + + int NumScanlineColorExpandBuffers + + This indicates the number of buffers available. + + unsigned char **ScanlineColorExpandBuffers + + This is an array of pointers to the memory locations of each buffer. + Each buffer is expected to be large enough to accommodate scanlines + the width of the screen. That is: + + ((virtualX + 31)/32) * 4 bytes or more. + + ((virtualX + 62)/32 * 4) if LEFT_EDGE_CLIPPING_NEGATIVE_X is set. + + Scanlines are always DWORD padded. + If the TRIPLE_BITS_24BPP flag is set, the required area should be + multiplied by three. + + +void SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask) + + Ones in the source bitmap will correspond to the fg color. + Zeros in the source bitmap will correspond to the bg color + unless bg = -1. In that case the pixels corresponding to the + zeros in the bitmap shall be left unmodified by the accelerator. + + +void SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft ) + +void SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) + + + When SubsequentScanlineCPUToScreenColorExpandFill is called, XAA + will begin transfering the source data scanline at a time, calling + SubsequentColorExpandScanline after each scanline. If more than + one buffer is available, XAA will cycle through the buffers. + Subsequent scanlines will use the next buffer and go back to the + buffer 0 again when the last buffer is reached. The index into + the ScanlineColorExpandBuffers array is presented as "bufno" + with each SubsequentColorExpandScanline call. + + The skipleft field is the same as for the direct method. + + The indirect method can be use to send the source data directly + to a memory mapped aperture represented by a single color expand + buffer, scanline at a time, but more commonly it is used to place + the data into offscreen video memory so that the accelerator can + blit it to the visible screen from there. In the case where the + accelerator permits rendering into offscreen video memory while + the accelerator is active, several buffers can be used so that + XAA can be placing source data into the next buffer while the + accelerator is blitting the current buffer. For cases where + the accelerator requires some special manipulation of the source + data first, the buffers can be in system memory. The CPU can + manipulate these buffers and then send the data to the accelerator. + + + +2.6 8x8 Mono Pattern Fills + + XAA provides support for two types of 8x8 hardware patterns - + "Mono" patterns and "Color" patterns. Mono pattern data is + 64 bits of color expansion data with ones indicating the + foreground color and zeros indicating the background color. + The source bitmaps for the 8x8 mono patterns can be presented + to the graphics accelerator in one of two ways. They can be + passed as two DWORDS to the 8x8 mono pattern functions or + they can be cached in offscreen memory and their locations + passed to the 8x8 mono pattern functions. In addition to the + GXCOPY_ONLY, ROP_NEEDS_SOURCE, NO_PLANEMASK and RGB_EQUAL flags + defined in Section 2.0, the following are defined for the + Mono8x8PatternFillFlags: + + HARDWARE_PATTERN_PROGRAMMED_BITS + + This indicates that the 8x8 patterns should be packed into two + DWORDS and passed to the 8x8 mono pattern functions. The default + behavior is to cache the patterns in offscreen video memory and + pass the locations of these patterns to the functions instead. + The pixmap cache must be enabled for the default behavior (8x8 + pattern caching) to work. See Section 3 for how to enable the + pixmap cache. The pixmap cache is not necessary for + HARDWARE_PATTERN_PROGRAMMED_BITS. + + HARDWARE_PATTERN_PROGRAMMED_ORIGIN + + If the hardware supports programmable pattern offsets then + this option should be set. See the table below for further + infomation. + + HARDWARE_PATTERN_SCREEN_ORIGIN + + Some hardware wants the pattern offset specified with respect to the + upper left-hand corner of the primitive being drawn. Other hardware + needs the option HARDWARE_PATTERN_SCREEN_ORIGIN set to indicate that + all pattern offsets should be referenced to the upper left-hand + corner of the screen. HARDWARE_PATTERN_SCREEN_ORIGIN is preferable + since this is more natural for the X-Window system and offsets will + have to be recalculated for each Subsequent function otherwise. + + BIT_ORDER_IN_BYTE_MSBFIRST + BIT_ORDER_IN_BYTE_LSBFIRST + + As with other color expansion routines this indicates whether the + most or the least significant bit in each byte from the pattern is + the leftmost on the screen. + + TRANSPARENCY_ONLY + NO_TRANSPARENCY + + This means the same thing as for the color expansion rect routines + except that for TRANSPARENCY_ONLY XAA will not render the primitive + in two passes since this is more easily handled by the driver. + It is recommended that TRANSPARENCY_ONLY hardware handle rendering + of opaque patterns in two passes (the background can be filled as + a rectangle in GXcopy) in the Subsequent function so that the + TRANSPARENCY_ONLY restriction can be removed. + + + + Additional information about cached patterns... + For the case where HARDWARE_PATTERN_PROGRAMMED_BITS is not set and + the pattern must be cached in offscreen memory, the first pattern + starts at the cache slot boundary which is set by the + CachePixelGranularity field used to configure the pixmap cache. + One should ensure that the CachePixelGranularity reflects any + alignment restrictions that the accelerator may put on 8x8 pattern + storage locations. When HARDWARE_PATTERN_PROGRAMMED_ORIGIN is set + there is only one pattern stored. When this flag is not set, + all 64 pre-rotated copies of the pattern are cached in offscreen memory. + The MonoPatternPitch field can be used to specify the X position pixel + granularity that each of these patterns must align on. If the + MonoPatternPitch is not supplied, the patterns will be densely packed + within the cache slot. The behavior of the default XAA 8x8 pattern + caching mechanism to store all 8x8 patterns linearly in video memory. + If the accelerator needs the patterns stored in a more unusual fashion, + the driver will need to provide its own 8x8 mono pattern caching + routines for XAA to use. + + The following table describes the meanings of the "patx" and "paty" + fields in both the SetupFor and Subsequent functions. + + With HARDWARE_PATTERN_SCREEN_ORIGIN + ----------------------------------- + + HARDWARE_PATTERN_PROGRAMMED_BITS and HARDWARE_PATTERN_PROGRAMMED_ORIGIN + + SetupFor: patx and paty are the first and second DWORDS of the + 8x8 mono pattern. + + Subsequent: patx and paty are the x,y offset into that pattern. + All Subsequent calls will have the same offset in + the case of HARDWARE_PATTERN_SCREEN_ORIGIN so only + the offset specified by the first Subsequent call + after a SetupFor call will need to be observed. + + HARDWARE_PATTERN_PROGRAMMED_BITS only + + SetupFor: patx and paty hold the first and second DWORDS of + the 8x8 mono pattern pre-rotated to match the desired + offset. + + Subsequent: These just hold the same patterns and can be ignored. + + HARDWARE_PATTERN_PROGRAMMED_ORIGIN only + + SetupFor: patx and paty hold the x,y coordinates of the offscreen + memory location where the 8x8 pattern is stored. The + bits are stored linearly in memory at that location. + + Subsequent: patx and paty hold the offset into the pattern. + All Subsequent calls will have the same offset in + the case of HARDWARE_PATTERN_SCREEN_ORIGIN so only + the offset specified by the first Subsequent call + after a SetupFor call will need to be observed. + + Neither programmed bits or origin + + SetupFor: patx and paty hold the x,y coordinates of the offscreen + memory location where the pre-rotated 8x8 pattern is + stored. + + Subsequent: patx and paty are the same as in the SetupFor function + and can be ignored. + + + Without HARDWARE_PATTERN_SCREEN_ORIGIN + -------------------------------------- + + HARDWARE_PATTERN_PROGRAMMED_BITS and HARDWARE_PATTERN_PROGRAMMED_ORIGIN + + SetupFor: patx and paty are the first and second DWORDS of the + 8x8 mono pattern. + + Subsequent: patx and paty are the x,y offset into that pattern. + + HARDWARE_PATTERN_PROGRAMMED_BITS only + + SetupFor: patx and paty holds the first and second DWORDS of + the unrotated 8x8 mono pattern. This can be ignored. + + Subsequent: patx and paty hold the rotated 8x8 pattern to be + rendered. + + HARDWARE_PATTERN_PROGRAMMED_ORIGIN only + + SetupFor: patx and paty hold the x,y coordinates of the offscreen + memory location where the 8x8 pattern is stored. The + bits are stored linearly in memory at that location. + + Subsequent: patx and paty hold the offset into the pattern. + + Neither programmed bits or origin + + SetupFor: patx and paty hold the x,y coordinates of the offscreen + memory location where the unrotated 8x8 pattern is + stored. This can be ignored. + + Subsequent: patx and paty hold the x,y coordinates of the + rotated 8x8 pattern to be rendered. + + + +void SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, unsigned int planemask) + + SetupForMono8x8PatternFill indicates that any combination of the + following may follow it. + + SubsequentMono8x8PatternFillRect + SubsequentMono8x8PatternFillTrap + + The fg, bg, rop and planemask fields have the same meaning as the + ones used for the other color expansion routines. Patx's and paty's + meaning can be determined from the table above. + + +void SubsequentMono8x8PatternFillRect( ScrnInfoPtr pScrn, + int patx, int paty, int x, int y, int w, int h) + + Fill a rectangle of dimensions "w" by "h" with origin at (x,y) + using the parameters give by the last SetupForMono8x8PatternFill + call. The meanings of patx and paty can be determined by the + table above. + +void SubsequentMono8x8PatternFillTrap( ScrnInfoPtr pScrn, + int patx, int paty, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) + + The meanings of patx and paty can be determined by the table above. + The rest of the fields have the same meanings as those in the + SubsequentSolidFillTrap function. + + + +2.7 8x8 Color Pattern Fills + + 8x8 color pattern data is 64 pixels of full color data that + is stored linearly in offscreen video memory. 8x8 color patterns + are useful as a substitute for 8x8 mono patterns when tiling, + doing opaque stipples, or in the case where transperency is + supported, regular stipples. 8x8 color pattern fills also have + the additional benefit of being able to tile full color 8x8 + patterns instead of just 2 color ones like the mono patterns. + However, full color 8x8 patterns aren't used very often in the + X Window system so you might consider passing this primitive + by if you already can do mono patterns, especially if they + require alot of cache area. Color8x8PatternFillFlags is + the flags field for this primitive and the GXCOPY_ONLY, + ROP_NEEDS_SOURCE and NO_PLANEMASK flags as described in + Section 2.0 are valid as well as the following: + + + HARDWARE_PATTERN_PROGRAMMED_ORIGIN + + If the hardware supports programmable pattern offsets then + this option should be set. + + HARDWARE_PATTERN_SCREEN_ORIGIN + + Some hardware wants the pattern offset specified with respect to the + upper left-hand corner of the primitive being drawn. Other hardware + needs the option HARDWARE_PATTERN_SCREEN_ORIGIN set to indicate that + all pattern offsets should be referenced to the upper left-hand + corner of the screen. HARDWARE_PATTERN_SCREEN_ORIGIN is preferable + since this is more natural for the X-Window system and offsets will + have to be recalculated for each Subsequent function otherwise. + + NO_TRANSPARENCY + TRANSPARENCY_GXCOPY_ONLY + + These mean the same as for the ScreenToScreenCopy functions. + + + The following table describes the meanings of patx and paty passed + to the SetupFor and Subsequent fields: + + HARDWARE_PATTERN_PROGRAMMED_ORIGIN && HARDWARE_PATTERN_SCREEN_ORIGIN + + SetupFor: patx and paty hold the x,y location of the unrotated + pattern. + + Subsequent: patx and paty hold the pattern offset. For the case + of HARDWARE_PATTERN_SCREEN_ORIGIN all Subsequent calls + have the same offset so only the first call will need + to be observed. + + + HARDWARE_PATTERN_PROGRAMMED_ORIGIN only + + SetupFor: patx and paty hold the x,y location of the unrotated + pattern. + + Subsequent: patx and paty hold the pattern offset. + + HARDWARE_PATTERN_SCREEN_ORIGIN + + SetupFor: patx and paty hold the x,y location of the rotated pattern. + + Subsequent: patx and paty hold the same location as the SetupFor + function so these can be ignored. + + neither flag + + SetupFor: patx and paty hold the x,y location of the unrotated + pattern. This can be ignored. + + Subsequent: patx and paty hold the x,y location of the rotated + pattern. + + Additional information about cached patterns... + All 8x8 color patterns are cached in offscreen video memory so + the pixmap cache must be enabled to use them. The first pattern + starts at the cache slot boundary which is set by the + CachePixelGranularity field used to configure the pixmap cache. + One should ensure that the CachePixelGranularity reflects any + alignment restrictions that the accelerator may put on 8x8 pattern + storage locations. When HARDWARE_PATTERN_PROGRAMMED_ORIGIN is set + there is only one pattern stored. When this flag is not set, + all 64 rotations off the pattern are accessible but it is assumed + that the accelerator is capable of accessing data stored on 8 + pixel boundaries. If the accelerator has stricter alignment + requirements than this the dirver will need to provide its own + 8x8 color pattern caching routines. + + +void SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, + int rop, unsigned int planemask, int trans_color) + + SetupForColor8x8PatternFill indicates that any combination of the + following may follow it. + + SubsequentColor8x8PatternFillRect + SubsequentColor8x8PatternFillTrap (not implemented yet) + + For the meanings of patx and paty, see the table above. Trans_color + means the same as for the ScreenToScreenCopy functions. + + + +void SubsequentColor8x8PatternFillRect( ScrnInfoPtr pScrn, + int patx, int paty, int x, int y, int w, int h) + + Fill a rectangle of dimensions "w" by "h" with origin at (x,y) + using the parameters give by the last SetupForColor8x8PatternFill + call. The meanings of patx and paty can be determined by the + table above. + +void SubsequentColor8x8PatternFillTrap( ScrnInfoPtr pScrn, + int patx, int paty, int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR ) + + For the meanings of patx and paty, see the table above. + The rest of the fields have the same meanings as those in the + SubsequentSolidFillTrap function. + + + +2.8 Image Writes + + XAA provides a mechanism for transfering full color pixel data from + system memory to video memory through the accelerator. This is + useful for dealing with alignment issues and performing raster ops + on the data when writing it to the framebuffer. As with color + expansion rectangles, there is a direct and indirect method. The + direct method sends all data through a memory mapped aperature. + The indirect method sends the data to an intermediated buffer scanline + at a time. + + The direct and indirect methods have separate flags fields, the + ImageWriteFlags and ScanlineImageWriteFlags respectively. + Flags specific to one method or the other are described in sections + 2.8.1 and 2.8.2 but for both cases the GXCOPY_ONLY, ROP_NEEDS_SOURCE + and NO_PLANEMASK flags described in Section 2.0 are valid as well as + the following: + + NO_GXCOPY + + In order to have accelerated image transfers faster than the + software versions for GXcopy, the engine needs to support clipping, + be using the direct method and have a large enough image transfer + range so that CPU_TRANSFER_BASE_FIXED doesn't need to be set. + If these are not supported, then it is unlikely that transfering + the data through the accelerator will be of any advantage for the + simple case of GXcopy. In fact, it may be much slower. For such + cases it's probably best to set the NO_GXCOPY flag so that + Image writes will only be used for the more complicated rops. + + /* transparency restrictions */ + + NO_TRANSPARENCY + + This indicates that the accelerator does not support skipping + of color keyed pixels when copying from the source to the destination. + + TRANSPARENCY_GXCOPY_ONLY + + This indicates that the accelerator supports skipping of color keyed + pixels only when the rop is GXcopy. + + /* clipping (optional) */ + + LEFT_EDGE_CLIPPING + + This indicates that the accelerator supports omission of up to + 3 pixels on the left edge of the rectangle to be filled. This + is beneficial since it allows transfer from the source pixmap to + always occur from DWORD boundaries. + + LEFT_EDGE_CLIPPING_NEGATIVE_X + + This flag indicates that the accelerator can fill areas with + image write data even if the value of x origin is negative (off of + the screen on the left edge). + + +2.8.1 The Direct Method + + Using the direct method of ImageWrite XAA will send all + bitmap data to the accelerator serially through an memory mapped + transfer window defined by the following two fields: + + unsigned char *ImageWriteBase + + This indicates the memory address of the beginning of the aperture. + + int ImageWriteRange + + This indicates the size in bytes of the aperture. + + The driver should specify how the transfered data should be padded. + There are options for both the padding of each Y scanline and for the + total transfer to the aperature. + One of the following two flags must be set: + + CPU_TRANSFER_PAD_DWORD + + This indicates that the total transfer (sum of all scanlines) sent + to the aperature must be DWORD padded. This is the default behavior. + + CPU_TRANSFER_PAD_QWORD + + This indicates that the total transfer (sum of all scanlines) sent + to the aperature must be QWORD padded. With this set, XAA will send + an extra DWORD to the aperature when needed to ensure that only + an even number of DWORDs are sent. + + And then there are the flags for padding of each scanline: + + SCANLINE_PAD_DWORD + + This indicates that each Y scanline should be DWORD padded. + This is the only option available and is the default. + + Finally, there is the CPU_TRANSFER_BASE_FIXED flag which indicates + that the aperture is a single register rather than a range of + registers, and XAA should write all of the data to the first DWORD. + XAA will automatically select CPU_TRANSFER_BASE_FIXED if the + ImageWriteRange is not large enough to accomodate an entire scanline. + + +void SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask, + int trans_color, int bpp, int depth) + + If trans_color is not -1 then trans_color indicates the transparency + color key and pixels with color trans_color passed through the + aperature should not be transfered to the screen but should be + skipped. Bpp and depth indicate the bits per pixel and depth of + the source pixmap. Trans_color is always -1 if the NO_TRANSPARENCY + flag is set. + + +void SubsequentImageWriteRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft) + + + Data passed through the aperature should be copied to a rectangle + of width "w" and height "h" with origin (x,y). If LEFT_EDGE_CLIPPING + has been enabled, skipleft will correspond to the number of pixels + on the left edge that should not be drawn. Skipleft is zero + otherwise. + + It can be arranged for XAA to call Sync() after it is through + calling the Subsequent functions by setting SYNC_AFTER_IMAGE_WRITE + in the ImageWriteFlags. This can provide the driver with an + oportunity to reset a clipping window if needed. + +2.8.2 The Indirect Method + + Using the indirect method, XAA will render the pixel data scanline + at a time to one or more buffers. These buffers may be memory + mapped apertures or just intermediate storage. + + int NumScanlineImageWriteBuffers + + This indicates the number of buffers available. + + unsigned char **ScanlineImageWriteBuffers + + This is an array of pointers to the memory locations of each buffer. + Each buffer is expected to be large enough to accommodate scanlines + the width of the screen. That is: + + pScrn->VirtualX * pScreen->bitsPerPixel/8 bytes or more. + + If LEFT_EDGE_CLIPPING_NEGATIVE_X is set, add an additional 4 + bytes to that requirement in 8 and 16bpp, 12 bytes in 24bpp. + + Scanlines are always DWORD padded. + +void SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int trans_color, + int bpp, int depth) + + If trans_color is not -1 then trans_color indicates the transparency + color key and pixels with color trans_color in the buffer should not + be transfered to the screen but should be skipped. Bpp and depth + indicate the bits per pixel and depth of the source bitmap. + Trans_color is always -1 if the NO_TRANSPARENCY flag is set. + + +void SubsequentImageWriteRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft) + + +void SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) + + + When SubsequentImageWriteRect is called, XAA will begin + transfering the source data scanline at a time, calling + SubsequentImageWriteScanline after each scanline. If more than + one buffer is available, XAA will cycle through the buffers. + Subsequent scanlines will use the next buffer and go back to the + buffer 0 again when the last buffer is reached. The index into + the ScanlineImageWriteBuffers array is presented as "bufno" + with each SubsequentImageWriteScanline call. + + The skipleft field is the same as for the direct method. + + The indirect method can be use to send the source data directly + to a memory mapped aperture represented by a single image write + buffer, scanline at a time, but more commonly it is used to place + the data into offscreen video memory so that the accelerator can + blit it to the visible screen from there. In the case where the + accelerator permits rendering into offscreen video memory while + the accelerator is active, several buffers can be used so that + XAA can be placing source data into the next buffer while the + accelerator is blitting the current buffer. For cases where + the accelerator requires some special manipulation of the source + data first, the buffers can be in system memory. The CPU can + manipulate these buffers and then send the data to the accelerator. + + +2.9 Clipping + + XAA supports hardware clipping rectangles. To use clipping + in this way it is expected that the graphics accelerator can + clip primitives with verticies anywhere in the 16 bit signed + coordinate system. + +void SetClippingRectangle ( ScrnInfoPtr pScrn, + int left, int top, int right, int bottom) + +void DisableClipping (ScrnInfoPtr pScrn) + + When SetClippingRectangle is called, all hardware rendering + following it should be clipped to the rectangle specified + until DisableClipping is called. + + The ClippingFlags field indicates which operations this sort + of Set/Disable pairing can be used with. Any of the following + flags may be OR'd together. + + HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND + HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY + HARDWARE_CLIP_MONO_8x8_FILL + HARDWARE_CLIP_COLOR_8x8_FILL + HARDWARE_CLIP_SOLID_FILL + HARDWARE_CLIP_DASHED_LINE + HARDWARE_CLIP_SOLID_LINE + + + +3) XAA PIXMAP CACHE + + /* NOTE: XAA has no knowledge of framebuffer particulars so until + the framebuffer is able to render into offscreen memory, usage + of the pixmap cache requires that the driver provide ImageWrite + routines or a WritePixmap or WritePixmapToCache replacement so + that patterns can even be placed in the cache. + + ADDENDUM: XAA can now load the pixmap cache without requiring + that the driver supply an ImageWrite function, but this can + only be done on linear framebuffers. If you have a linear + framebuffer, set LINEAR_FRAMEBUFFER in the XAAInfoRec.Flags + field and XAA will then be able to upload pixmaps into the + cache without the driver providing functions to do so. + */ + + + The XAA pixmap cache provides a mechanism for caching of patterns + in offscreen video memory so that tiled fills and in some cases + stippling can be done by blitting the source patterns from offscreen + video memory. The pixmap cache also provides the mechanism for caching + of 8x8 color and mono hardware patterns. Any unused offscreen video + memory gets used for the pixmap cache and that information is + provided by the XFree86 Offscreen Memory Manager. XAA registers a + callback with the manager so that it can be informed of any changes + in the offscreen memory configuration. The driver writer does not + need to deal with any of this since it is all automatic. The driver + merely needs to initialize the Offscreen Memory Manager as described + in the DESIGN document and set the PIXMAP_CACHE flag in the + XAAInfoRec.Flags field. The Offscreen Memory Manager initialization + must occur before XAA is initialized or else pixmap cache + initialization will fail. + + PixmapCacheFlags is an XAAInfoRec field which allows the driver to + control pixmap cache behavior to some extent. Currently only one + flag is defined: + + DO_NOT_BLIT_STIPPLES + + This indicates that the stippling should not be done by blitting + from the pixmap cache. This does not apply to 8x8 pattern fills. + + + CachePixelGranularity is an optional field. If the hardware requires + that a 8x8 patterns have some particular pixel alignment it should + be reflected in this field. Ignoring this field or setting it to + zero or one means there are no alignment issues. + + +4) OFFSCREEN PIXMAPS + + XAA has the ability to store pixmap drawables in offscreen video + memory and render into them with full hardware acceleration. Placement + of pixmaps in the cache is done automatically on a first-come basis and + only if there is room. To enable this feature, set the OFFSCREEN_PIXMAPS + flag in the XAAInfoRec.Flags field. This is only available when a + ScreenToScreenCopy function is provided, when the Offscreen memory + manager has been initialized and when the LINEAR_FRAMEBUFFER flag is + also set. + + int maxOffPixWidth + int maxOffPixHeight + + These two fields allow the driver to limit the maximum dimensions + of an offscreen pixmap. If one of these is not set, it is assumed + that there is no limit on that dimension. Note that if an offscreen + pixmap with a particular dimension is allowed, then your driver will be + expected to render primitives as large as that pixmap. + +$XFree86: xc/programs/Xserver/hw/xfree86/xaa/XAA.HOWTO,v 1.12 2000/04/12 14:44:42 tsi Exp $ diff --git a/hw/xfree86/xaa/xaa.h b/hw/xfree86/xaa/xaa.h new file mode 100644 index 000000000..9f3e7639c --- /dev/null +++ b/hw/xfree86/xaa/xaa.h @@ -0,0 +1,1038 @@ + +#ifndef _XAA_H +#define _XAA_H + +#define XAA_VERSION_MAJOR 1 +#define XAA_VERSION_MINOR 2 +#define XAA_VERSION_RELEASE 1 + +/* + + ******** OPERATION SPECIFIC FLAGS ********* + + **** solid/dashed line flags **** + +--------- -------- +23 LINE_PATTERN_LSBFIRST_MSBJUSTIFIED +22 LINE_PATTERN_LSBFIRST_LSBJUSTIFIED +21 LINE_PATTERN_MSBFIRST_MSBJUSTIFIED +20 LINE_PATTERN_MSBFIRST_LSBJUSTIFIED +19 LINE_PATTERN_POWER_OF_2_ONLY +18 LINE_LIMIT_COORDS +17 . +16 . +--------- ------- + + **** screen to screen copy flags **** + +--------- -------- +23 ONLY_LEFT_TO_RIGHT_BITBLT +22 ONLY_TWO_BITBLT_DIRECTIONS +21 . +20 . +19 . +18 . +17 . +16 . +--------- ------- + + **** clipping flags **** + +--------- -------- +23 . +22 HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND +21 HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY +20 HARDWARE_CLIP_MONO_8x8_FILL +19 HARDWARE_CLIP_COLOR_8x8_FILL +18 HARDWARE_CLIP_SOLID_FILL +17 HARDWARE_CLIP_DASHED_LINE +16 HARDWARE_CLIP_SOLID_LINE +--------- ------- + + **** hardware pattern flags **** + +--------- -------- +23 . +22 . +21 HARDWARE_PATTERN_SCREEN_ORIGIN +20 . +19 . +18 . +17 HARDWARE_PATTERN_PROGRAMMED_ORIGIN +16 HARDWARE_PATTERN_PROGRAMMED_BITS +--------- ------- + + **** write pixmap flags **** + +--------- -------- +23 . +22 . +21 . +20 . +19 . +18 . +17 . +16 CONVERT_32BPP_TO_24BPP +--------- ------- + + ******** GENERIC FLAGS ********* + +--------- ------- +15 SYNC_AFTER_COLOR_EXPAND +14 CPU_TRANSFER_PAD_QWORD +13 . +12 LEFT_EDGE_CLIPPING_NEGATIVE_X +11 LEFT_EDGE_CLIPPING +10 CPU_TRANSFER_BASE_FIXED + 9 BIT_ORDER_IN_BYTE_MSBFIRST + 8 TRANSPARENCY_GXCOPY_ONLY +--------- ------- + 7 NO_TRANSPARENCY + 6 TRANSPARENCY_ONLY + 5 ROP_NEEDS_SOURCE + 4 TRIPLE_BITS_24BPP + 3 RGB_EQUAL + 2 NO_PLANEMASK + 1 NO_GXCOPY + 0 GXCOPY_ONLY +--------- ------- + + +*/ + +#include "gcstruct.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "regionstr.h" +#include "xf86fbman.h" + +#include "picturestr.h" + +/* Flags */ +#define PIXMAP_CACHE 0x00000001 +#define MICROSOFT_ZERO_LINE_BIAS 0x00000002 +#define OFFSCREEN_PIXMAPS 0x00000004 +#define LINEAR_FRAMEBUFFER 0x00000008 + +/* GC fg, bg, and planemask restrictions */ +#define GXCOPY_ONLY 0x00000001 +#define NO_GXCOPY 0x00000002 +#define NO_PLANEMASK 0x00000004 +#define RGB_EQUAL 0x00000008 +#define TRIPLE_BITS_24BPP 0x00000010 +#define ROP_NEEDS_SOURCE 0x00000020 + +/* transparency restrictions */ +#define TRANSPARENCY_ONLY 0x00000040 +#define NO_TRANSPARENCY 0x00000080 +#define TRANSPARENCY_GXCOPY_ONLY 0x00000100 + +/* bit order restrictions */ +#define BIT_ORDER_IN_BYTE_MSBFIRST 0x00000200 +#define BIT_ORDER_IN_BYTE_LSBFIRST 0x00000000 + +/* transfer base restriction */ +#define CPU_TRANSFER_BASE_FIXED 0x00000400 + +/* skipleft restrictions */ +#define LEFT_EDGE_CLIPPING 0x00000800 +#define LEFT_EDGE_CLIPPING_NEGATIVE_X 0x00001000 + +/* data padding */ +#define CPU_TRANSFER_PAD_DWORD 0x00000000 +#define CPU_TRANSFER_PAD_QWORD 0x00004000 +#define SCANLINE_PAD_DWORD 0x00000000 + +#define SYNC_AFTER_COLOR_EXPAND 0x00008000 +#define SYNC_AFTER_IMAGE_WRITE SYNC_AFTER_COLOR_EXPAND + +/* hardware pattern */ +#define HARDWARE_PATTERN_PROGRAMMED_BITS 0x00010000 +#define HARDWARE_PATTERN_PROGRAMMED_ORIGIN 0x00020000 +#define HARDWARE_PATTERN_SCREEN_ORIGIN 0x00200000 + +/* copyarea flags */ +#define ONLY_TWO_BITBLT_DIRECTIONS 0x00400000 +#define ONLY_LEFT_TO_RIGHT_BITBLT 0x00800000 + +/* line flags */ +#define LINE_PATTERN_LSBFIRST_MSBJUSTIFIED 0x00800000 +#define LINE_PATTERN_LSBFIRST_LSBJUSTIFIED 0x00400000 +#define LINE_PATTERN_MSBFIRST_MSBJUSTIFIED 0x00200000 +#define LINE_PATTERN_MSBFIRST_LSBJUSTIFIED 0x00100000 +#define LINE_PATTERN_POWER_OF_2_ONLY 0x00080000 +#define LINE_LIMIT_COORDS 0x00040000 + +/* clipping flags */ +#define HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND 0x00400000 +#define HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY 0x00200000 +#define HARDWARE_CLIP_MONO_8x8_FILL 0x00100000 +#define HARDWARE_CLIP_COLOR_8x8_FILL 0x00080000 +#define HARDWARE_CLIP_SOLID_FILL 0x00040000 +#define HARDWARE_CLIP_DASHED_LINE 0x00020000 +#define HARDWARE_CLIP_SOLID_LINE 0x00010000 + +#define HARDWARE_CLIP_LINE 0x00000000 + +/* image write flags */ +#define CONVERT_32BPP_TO_24BPP 0x00010000 + +/* pixmap cache flags */ +#define CACHE_MONO_8x8 0x00000001 +#define CACHE_COLOR_8x8 0x00000002 +#define DO_NOT_BLIT_STIPPLES 0x00000004 +#define DO_NOT_TILE_MONO_DATA 0x00000008 +#define DO_NOT_TILE_COLOR_DATA 0x00000010 + +#define DEGREES_0 0 +#define DEGREES_90 1 +#define DEGREES_180 2 +#define DEGREES_270 3 + +#define OMIT_LAST 1 + +/* render flags */ + +#define XAA_RENDER_POWER_OF_2_TILE_ONLY 0x00000008 +#define XAA_RENDER_NO_SRC_ALPHA 0x00000004 +#define XAA_RENDER_IMPRECISE_ONLY 0x00000002 +#define XAA_RENDER_NO_TILE 0x00000001 + +#define XAA_RENDER_REPEAT 0x00000001 + +typedef void (*ValidateGCProcPtr) (GCPtr pGC, + unsigned long changes, DrawablePtr pDraw); + +typedef struct { + unsigned char *bits; + int width; + int height; + int yoff; + int srcwidth; + int start; + int end; +} NonTEGlyphInfo, *NonTEGlyphPtr; + +typedef struct { + int x; + int y; + int w; + int h; + int orig_w; + int orig_h; + unsigned long serialNumber; + int pat0; + int pat1; + int fg; + int bg; + int trans_color; + DDXPointPtr offsets; + DevUnion devPrivate; +} XAACacheInfoRec, *XAACacheInfoPtr; + +typedef struct _PixmapLink { + PixmapPtr pPix; + struct _PixmapLink *next; + FBAreaPtr area; +} PixmapLink, *PixmapLinkPtr; + +typedef struct _XAAInfoRec { + ScrnInfoPtr pScrn; + int Flags; + + void (*Sync) (ScrnInfoPtr pScrn); + + /* Restore Accel State is a driver callback that is used + * when another screen on the same device has been active. + * This allows multihead on a single device to work. + * If The entityProp has IS_SHARED_ACCEL defined then this + * function is required. + */ + + void (*RestoreAccelState) (ScrnInfoPtr pScrn); + + /***************** Low Level *****************/ + +/* Blits */ + void (*SetupForScreenToScreenCopy) (ScrnInfoPtr pScrn, + int xdir, int ydir, + int rop, + unsigned int planemask, + int trans_color); + int ScreenToScreenCopyFlags; + + void (*SubsequentScreenToScreenCopy) (ScrnInfoPtr pScrn, + int xsrc, int ysrc, + int xdst, int ydst, int w, int h); + +/* Solid fills */ + void (*SetupForSolidFill) (ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask); + int SolidFillFlags; + + void (*SubsequentSolidFillRect) (ScrnInfoPtr pScrn, + int x, int y, int w, int h); + + void (*SubsequentSolidFillTrap) (ScrnInfoPtr pScrn, + int y, int h, + int left, int dxL, int dyL, int eL, + int right, int dxR, int dyR, int eR); + +/* Solid lines */ + + void (*SetupForSolidLine) (ScrnInfoPtr pScrn, + int color, int rop, unsigned int planemask); + int SolidLineFlags; + + void (*SubsequentSolidTwoPointLine) (ScrnInfoPtr pScrn, + int xa, int ya, int xb, int yb, + int flags); + + void (*SubsequentSolidBresenhamLine) (ScrnInfoPtr pScrn, + int x, int y, int absmaj, int absmin, + int err, int len, int octant); + int SolidBresenhamLineErrorTermBits; + + void (*SubsequentSolidHorVertLine) (ScrnInfoPtr pScrn, + int x, int y, int len, int dir); + +/* Dashed lines */ + + void (*SetupForDashedLine) (ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask, + int length, unsigned char *pattern); + int DashedLineFlags; + int DashPatternMaxLength; + + void (*SubsequentDashedTwoPointLine) (ScrnInfoPtr pScrn, + int xa, int ya, int xb, int yb, + int flags, int phase); + + void (*SubsequentDashedBresenhamLine) (ScrnInfoPtr pScrn, + int x, int y, int absmaj, int absmin, + int err, int len, int flags, + int phase); + int DashedBresenhamLineErrorTermBits; + +/* Clipper */ + + void (*SetClippingRectangle) (ScrnInfoPtr pScrn, + int left, int top, int right, int bottom); + int ClippingFlags; + + void (*DisableClipping) (ScrnInfoPtr pScrn); + +/* 8x8 mono pattern fills */ + void (*SetupForMono8x8PatternFill) (ScrnInfoPtr pScrn, + int patx, int paty, + int fg, int bg, + int rop, unsigned int planemask); + int Mono8x8PatternFillFlags; + + void (*SubsequentMono8x8PatternFillRect) (ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h); + + void (*SubsequentMono8x8PatternFillTrap) (ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, + int eL, int right, int dxR, + int dyR, int eR); + +/* 8x8 color pattern fills */ + + void (*SetupForColor8x8PatternFill) (ScrnInfoPtr pScrn, + int patx, int paty, + int rop, + unsigned int planemask, + int transparency_color); + int Color8x8PatternFillFlags; + + void (*SubsequentColor8x8PatternFillRect) (ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h); + + void (*SubsequentColor8x8PatternFillTrap) (ScrnInfoPtr pScrn, + int patx, int paty, + int y, int h, + int left, int dxL, int dyL, + int eL, int right, int dxR, + int dyR, int eR); + +/* Color expansion */ + + void (*SetupForCPUToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask); + int CPUToScreenColorExpandFillFlags; + + void (*SubsequentCPUToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft); + + unsigned char *ColorExpandBase; + int ColorExpandRange; + +/* Scanline color expansion */ + + void (*SetupForScanlineCPUToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask); + int ScanlineCPUToScreenColorExpandFillFlags; + + void (*SubsequentScanlineCPUToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int x, int y, int w, + int h, int skipleft); + + void (*SubsequentColorExpandScanline) (ScrnInfoPtr pScrn, int bufno); + + int NumScanlineColorExpandBuffers; + unsigned char **ScanlineColorExpandBuffers; + +/* Screen to screen color expansion */ + + void (*SetupForScreenToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask); + int ScreenToScreenColorExpandFillFlags; + + void (*SubsequentScreenToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, + int skipleft); + +/* Image transfers */ + + void (*SetupForImageWrite) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int transparency_color, int bpp, int depth); + int ImageWriteFlags; + + void (*SubsequentImageWriteRect) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft); + unsigned char *ImageWriteBase; + int ImageWriteRange; + +/* Scanline Image transfers */ + + void (*SetupForScanlineImageWrite) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth); + int ScanlineImageWriteFlags; + + void (*SubsequentScanlineImageWriteRect) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int skipleft); + + void (*SubsequentImageWriteScanline) (ScrnInfoPtr pScrn, int bufno); + + int NumScanlineImageWriteBuffers; + unsigned char **ScanlineImageWriteBuffers; + + /* Image Reads - OBSOLETE AND NOT USED */ + + void (*SetupForImageRead) (ScrnInfoPtr pScrn, int bpp, int depth); + int ImageReadFlags; + + unsigned char *ImageReadBase; + int ImageReadRange; + + void (*SubsequentImageReadRect) (ScrnInfoPtr pScrn, + int x, int y, int w, int h); + + /***************** Mid Level *****************/ + void (*ScreenToScreenBitBlt) (ScrnInfoPtr pScrn, + int nbox, + DDXPointPtr pptSrc, + BoxPtr pbox, + int xdir, int ydir, + int alu, unsigned int planmask); + int ScreenToScreenBitBltFlags; + + void (*WriteBitmap) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, int rop, unsigned int planemask); + int WriteBitmapFlags; + + void (*FillSolidRects) (ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox); + int FillSolidRectsFlags; + + void (*FillMono8x8PatternRects) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int pat0, int pat1, int xorg, int yorg); + int FillMono8x8PatternRectsFlags; + + void (*FillColor8x8PatternRects) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + XAACacheInfoPtr pCache); + int FillColor8x8PatternRectsFlags; + + void (*FillCacheBltRects) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, XAACacheInfoPtr pCache); + int FillCacheBltRectsFlags; + + void (*FillColorExpandRects) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + int FillColorExpandRectsFlags; + + void (*FillCacheExpandRects) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + int FillCacheExpandRectsFlags; + + void (*FillImageWriteRects) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + int FillImageWriteRectsFlags; + + void (*FillSolidSpans) (ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int n, + DDXPointPtr points, int *widths, int fSorted); + int FillSolidSpansFlags; + + void (*FillMono8x8PatternSpans) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr points, + int *widths, + int fSorted, + int pat0, int pat1, int xorg, int yorg); + int FillMono8x8PatternSpansFlags; + + void (*FillColor8x8PatternSpans) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr points, + int *widths, + int fSorted, + XAACacheInfoPtr pCache, + int xorg, int yorg); + int FillColor8x8PatternSpansFlags; + + void (*FillCacheBltSpans) (ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr points, + int *widths, + int fSorted, + XAACacheInfoPtr pCache, int xorg, int yorg); + int FillCacheBltSpansFlags; + + void (*FillColorExpandSpans) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr points, + int *widths, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + int FillColorExpandSpansFlags; + + void (*FillCacheExpandSpans) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + int FillCacheExpandSpansFlags; + + void (*TEGlyphRenderer) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + int TEGlyphRendererFlags; + + void (*NonTEGlyphRenderer) (ScrnInfoPtr pScrn, + int x, int y, int n, + NonTEGlyphPtr glyphs, + BoxPtr pbox, + int fg, int rop, unsigned int planemask); + int NonTEGlyphRendererFlags; + + void (*WritePixmap) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int rop, + unsigned int planemask, + int transparency_color, int bpp, int depth); + int WritePixmapFlags; + + void (*ReadPixmap) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth); + int ReadPixmapFlags; + + /***************** GC Level *****************/ + RegionPtr (*CopyArea) (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC * pGC, + int srcx, int srcy, + int width, int height, int dstx, int dsty); + int CopyAreaFlags; + + RegionPtr (*CopyPlane) (DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, unsigned long bitPlane); + int CopyPlaneFlags; + + void (*PushPixelsSolid) (GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, int dy, int xOrg, int yOrg); + int PushPixelsFlags; + + /** PolyFillRect **/ + + void (*PolyFillRectSolid) (DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit); + int PolyFillRectSolidFlags; + + void (*PolyFillRectStippled) (DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, xRectangle *prectInit); + int PolyFillRectStippledFlags; + + void (*PolyFillRectOpaqueStippled) (DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, xRectangle *prectInit); + int PolyFillRectOpaqueStippledFlags; + + void (*PolyFillRectTiled) (DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit); + int PolyFillRectTiledFlags; + + /** FillSpans **/ + + void (*FillSpansSolid) (DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + int FillSpansSolidFlags; + + void (*FillSpansStippled) (DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + int FillSpansStippledFlags; + + void (*FillSpansOpaqueStippled) (DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + int FillSpansOpaqueStippledFlags; + + void (*FillSpansTiled) (DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + int FillSpansTiledFlags; + + int (*PolyText8TE) (DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars); + int PolyText8TEFlags; + + int (*PolyText16TE) (DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars); + int PolyText16TEFlags; + + void (*ImageText8TE) (DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars); + int ImageText8TEFlags; + + void (*ImageText16TE) (DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars); + int ImageText16TEFlags; + + void (*ImageGlyphBltTE) (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + int ImageGlyphBltTEFlags; + + void (*PolyGlyphBltTE) (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + int PolyGlyphBltTEFlags; + + int (*PolyText8NonTE) (DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars); + int PolyText8NonTEFlags; + + int (*PolyText16NonTE) (DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars); + int PolyText16NonTEFlags; + + void (*ImageText8NonTE) (DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars); + int ImageText8NonTEFlags; + + void (*ImageText16NonTE) (DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars); + int ImageText16NonTEFlags; + + void (*ImageGlyphBltNonTE) (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + int ImageGlyphBltNonTEFlags; + + void (*PolyGlyphBltNonTE) (DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + int PolyGlyphBltNonTEFlags; + + void (*PolyRectangleThinSolid) (DrawablePtr pDrawable, + GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit); + int PolyRectangleThinSolidFlags; + + void (*PolylinesWideSolid) (DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts); + int PolylinesWideSolidFlags; + + void (*PolylinesThinSolid) (DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts); + int PolylinesThinSolidFlags; + + void (*PolySegmentThinSolid) (DrawablePtr pDrawable, + GCPtr pGC, int nseg, xSegment * pSeg); + int PolySegmentThinSolidFlags; + + void (*PolylinesThinDashed) (DrawablePtr pDrawable, + GCPtr pGC, + int mode, int npt, DDXPointPtr pPts); + int PolylinesThinDashedFlags; + + void (*PolySegmentThinDashed) (DrawablePtr pDrawable, + GCPtr pGC, int nseg, xSegment * pSeg); + int PolySegmentThinDashedFlags; + + void (*FillPolygonSolid) (DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, int count, DDXPointPtr ptsIn); + int FillPolygonSolidFlags; + + void (*FillPolygonStippled) (DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, int count, DDXPointPtr ptsIn); + int FillPolygonStippledFlags; + + void (*FillPolygonOpaqueStippled) (DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, int count, DDXPointPtr ptsIn); + int FillPolygonOpaqueStippledFlags; + + void (*FillPolygonTiled) (DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, int count, DDXPointPtr ptsIn); + int FillPolygonTiledFlags; + + void (*PolyFillArcSolid) (DrawablePtr pDraw, + GCPtr pGC, int narcs, xArc * parcs); + int PolyFillArcSolidFlags; + + void (*PutImage) (DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, + int y, + int w, int h, int leftPad, int format, char *pImage); + int PutImageFlags; + + /* Validation masks */ + + unsigned long FillSpansMask; + ValidateGCProcPtr ValidateFillSpans; + unsigned long SetSpansMask; + ValidateGCProcPtr ValidateSetSpans; + unsigned long PutImageMask; + ValidateGCProcPtr ValidatePutImage; + unsigned long CopyAreaMask; + ValidateGCProcPtr ValidateCopyArea; + unsigned long CopyPlaneMask; + ValidateGCProcPtr ValidateCopyPlane; + unsigned long PolyPointMask; + ValidateGCProcPtr ValidatePolyPoint; + unsigned long PolylinesMask; + ValidateGCProcPtr ValidatePolylines; + unsigned long PolySegmentMask; + ValidateGCProcPtr ValidatePolySegment; + unsigned long PolyRectangleMask; + ValidateGCProcPtr ValidatePolyRectangle; + unsigned long PolyArcMask; + ValidateGCProcPtr ValidatePolyArc; + unsigned long FillPolygonMask; + ValidateGCProcPtr ValidateFillPolygon; + unsigned long PolyFillRectMask; + ValidateGCProcPtr ValidatePolyFillRect; + unsigned long PolyFillArcMask; + ValidateGCProcPtr ValidatePolyFillArc; + unsigned long PolyText8Mask; + ValidateGCProcPtr ValidatePolyText8; + unsigned long PolyText16Mask; + ValidateGCProcPtr ValidatePolyText16; + unsigned long ImageText8Mask; + ValidateGCProcPtr ValidateImageText8; + unsigned long ImageText16Mask; + ValidateGCProcPtr ValidateImageText16; + unsigned long PolyGlyphBltMask; + ValidateGCProcPtr ValidatePolyGlyphBlt; + unsigned long ImageGlyphBltMask; + ValidateGCProcPtr ValidateImageGlyphBlt; + unsigned long PushPixelsMask; + ValidateGCProcPtr ValidatePushPixels; + + void (*ComputeDash) (GCPtr pGC); + + /* Pixmap Cache */ + + int PixmapCacheFlags; + Bool UsingPixmapCache; + Bool CanDoMono8x8; + Bool CanDoColor8x8; + + void (*InitPixmapCache) (ScreenPtr pScreen, RegionPtr areas, void * data); + void (*ClosePixmapCache) (ScreenPtr pScreen); + + int (*StippledFillChooser) (GCPtr pGC); + int (*OpaqueStippledFillChooser) (GCPtr pGC); + int (*TiledFillChooser) (GCPtr pGC); + + int CachePixelGranularity; + int MaxCacheableTileWidth; + int MaxCacheableTileHeight; + int MaxCacheableStippleWidth; + int MaxCacheableStippleHeight; + + XAACacheInfoPtr(*CacheTile) (ScrnInfoPtr Scrn, PixmapPtr pPix); + XAACacheInfoPtr(*CacheStipple) (ScrnInfoPtr Scrn, PixmapPtr pPix, + int fg, int bg); + XAACacheInfoPtr(*CacheMonoStipple) (ScrnInfoPtr Scrn, PixmapPtr pPix); + XAACacheInfoPtr(*CacheMono8x8Pattern) (ScrnInfoPtr Scrn, int pat0, + int pat1); + XAACacheInfoPtr(*CacheColor8x8Pattern) (ScrnInfoPtr Scrn, PixmapPtr pPix, + int fg, int bg); + + int MonoPatternPitch; + int CacheWidthMono8x8Pattern; + int CacheHeightMono8x8Pattern; + + int ColorPatternPitch; + int CacheWidthColor8x8Pattern; + int CacheHeightColor8x8Pattern; + + int CacheColorExpandDensity; + + void (*WriteBitmapToCache) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, int fg, int bg); + void (*WritePixmapToCache) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, int bpp, int depth); + void (*WriteMono8x8PatternToCache) (ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache); + void (*WriteColor8x8PatternToCache) (ScrnInfoPtr pScrn, + PixmapPtr pPix, + XAACacheInfoPtr pCache); + + char *PixmapCachePrivate; + + /* Miscellaneous */ + + GC ScratchGC; + int PreAllocSize; + unsigned char *PreAllocMem; + + CharInfoPtr CharInfo[255]; + NonTEGlyphInfo GlyphInfo[255]; + + unsigned int FullPlanemask; /* deprecated */ + + PixmapLinkPtr OffscreenPixmaps; + int maxOffPixWidth; + int maxOffPixHeight; + + XAACacheInfoRec ScratchCacheInfoRec; + + BoxPtr ClipBox; + + Bool NeedToSync; + + char *dgaSaves; + + /* These can be supplied to override the defaults */ + + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CopyWindowProcPtr CopyWindow; + + unsigned int offscreenDepths; + Bool offscreenDepthsInitialized; + + CARD32 FullPlanemasks[32]; + + Bool (*Composite) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + + Bool (*Glyphs) (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, GlyphListPtr list, GlyphPtr * glyphs); + + /* The old SetupForCPUToScreenAlphaTexture function is no longer used because + * it doesn't pass in enough information to write a conforming + * implementation. See SetupForCPUToScreenAlphaTexture2. + */ + Bool (*SetupForCPUToScreenAlphaTexture) (ScrnInfoPtr pScrn, + int op, + CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + int alphaType, + CARD8 *alphaPtr, + int alphaPitch, + int width, int height, int flags); + void (*SubsequentCPUToScreenAlphaTexture) (ScrnInfoPtr pScrn, + int dstx, + int dsty, + int srcx, + int srcy, int width, int height); + int CPUToScreenAlphaTextureFlags; + CARD32 *CPUToScreenAlphaTextureFormats; + + /* The old SetupForCPUToScreenTexture function is no longer used because + * it doesn't pass in enough information to write a conforming + * implementation. See SetupForCPUToScreenTexture2. + */ + Bool (*SetupForCPUToScreenTexture) (ScrnInfoPtr pScrn, + int op, + int texType, + CARD8 *texPtr, + int texPitch, + int width, int height, int flags); + void (*SubsequentCPUToScreenTexture) (ScrnInfoPtr pScrn, + int dstx, + int dsty, + int srcx, + int srcy, int width, int height); + int CPUToScreenTextureFlags; + CARD32 *CPUToScreenTextureFormats; + + /* these were added for 4.3.0 */ + BoxRec SolidLineLimits; + BoxRec DashedLineLimits; + + /* These were added for X.Org 6.8.0 */ + Bool (*SetupForCPUToScreenAlphaTexture2) (ScrnInfoPtr pScrn, + int op, + CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + CARD32 maskFormat, + CARD32 dstFormat, + CARD8 *alphaPtr, + int alphaPitch, + int width, int height, int flags); + CARD32 *CPUToScreenAlphaTextureDstFormats; + + Bool (*SetupForCPUToScreenTexture2) (ScrnInfoPtr pScrn, + int op, + CARD32 srcFormat, + CARD32 dstFormat, + CARD8 *texPtr, + int texPitch, + int width, int height, int flags); + CARD32 *CPUToScreenTextureDstFormats; +} XAAInfoRec, *XAAInfoRecPtr; + +#define SET_SYNC_FLAG(infoRec) (infoRec)->NeedToSync = TRUE + +extern _X_EXPORT Bool + XAAInit(ScreenPtr pScreen, XAAInfoRecPtr infoRec); + +extern _X_EXPORT XAAInfoRecPtr XAACreateInfoRec(void); + +extern _X_EXPORT void + XAADestroyInfoRec(XAAInfoRecPtr infoRec); + +typedef void (*DepthChangeFuncPtr) (ScrnInfoPtr pScrn, int depth); + +extern _X_EXPORT Bool + XAAInitDualFramebufferOverlay(ScreenPtr pScreen, DepthChangeFuncPtr callback); + +#endif /* _XAA_H */ diff --git a/hw/xfree86/xaa/xaaBitBlt.c b/hw/xfree86/xaa/xaaBitBlt.c new file mode 100644 index 000000000..2c062b1ca --- /dev/null +++ b/hw/xfree86/xaa/xaaBitBlt.c @@ -0,0 +1,228 @@ + +/* + This is a lighter version of cfbBitBlt. We calculate the boxes + when accelerating pixmap->screen and screen->screen copies. + We also pass the GC to the doBitBlt function so that it has access + to the fg and bg so CopyPlane can use this. +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "mi.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "xaalocal.h" + +RegionPtr +XAABitBlt(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC * pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + void (*doBitBlt) (DrawablePtr, DrawablePtr, GCPtr, RegionPtr, + DDXPointPtr)/*, unsigned long bitPlane*/) +{ + + RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ + RegionPtr prgnExposed; + Bool freeSrcClip = FALSE; + RegionRec rgnDst; + DDXPointPtr pptSrc, ppt; + DDXPointRec origDest; + BoxPtr pbox; + BoxRec fastBox; + int i, dx, dy, numRects; + xRectangle origSource; + int fastClip = 0; /* for fast clipping with pixmap source */ + int fastExpose = 0; /* for fast exposures with pixmap source */ + + origSource.x = srcx; + origSource.y = srcy; + origSource.width = width; + origSource.height = height; + origDest.x = dstx; + origDest.y = dsty; + + if (pSrcDrawable->pScreen->SourceValidate) { + (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, + width, height, + pGC->subWindowMode); + } + + srcx += pSrcDrawable->x; + srcy += pSrcDrawable->y; + + /* clip the source */ + if (pSrcDrawable->type == DRAWABLE_PIXMAP) { + if ((pSrcDrawable == pDstDrawable) && (pGC->clientClip == NULL)) + prgnSrcClip = pGC->pCompositeClip; + else + fastClip = 1; + } + else { /* Window */ + if (pGC->subWindowMode == IncludeInferiors) { + if (!((WindowPtr) pSrcDrawable)->parent) { + /* + * special case bitblt from root window in + * IncludeInferiors mode; just like from a pixmap + */ + fastClip = 1; + } + else if ((pSrcDrawable == pDstDrawable) && (pGC->clientClip == NULL)) { + prgnSrcClip = pGC->pCompositeClip; + } + else { + prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable); + freeSrcClip = TRUE; + } + } + else { + prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList; + } + } + + fastBox.x1 = srcx; + fastBox.y1 = srcy; + fastBox.x2 = srcx + width; + fastBox.y2 = srcy + height; + + /* Don't create a source region if we are doing a fast clip */ + if (fastClip) { + fastExpose = 1; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (fastBox.x1 < pSrcDrawable->x) { + fastBox.x1 = pSrcDrawable->x; + fastExpose = 0; + } + if (fastBox.y1 < pSrcDrawable->y) { + fastBox.y1 = pSrcDrawable->y; + fastExpose = 0; + } + if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { + fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + fastExpose = 0; + } + if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { + fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + fastExpose = 0; + } + } + else { + RegionInit(&rgnDst, &fastBox, 1); + RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip); + } + + dstx += pDstDrawable->x; + dsty += pDstDrawable->y; + + if (pDstDrawable->type == DRAWABLE_WINDOW) { + if (!((WindowPtr) pDstDrawable)->realized) { + if (!fastClip) + RegionUninit(&rgnDst); + if (freeSrcClip) + RegionDestroy(prgnSrcClip); + return NULL; + } + } + + dx = srcx - dstx; + dy = srcy - dsty; + + /* Translate and clip the dst to the destination composite clip */ + if (fastClip) { + RegionPtr cclip; + + /* Translate the region directly */ + fastBox.x1 -= dx; + fastBox.x2 -= dx; + fastBox.y1 -= dy; + fastBox.y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + + cclip = pGC->pCompositeClip; + if (RegionNumRects(cclip) == 1) { + BoxPtr pBox = RegionRects(cclip); + + if (fastBox.x1 < pBox->x1) + fastBox.x1 = pBox->x1; + if (fastBox.x2 > pBox->x2) + fastBox.x2 = pBox->x2; + if (fastBox.y1 < pBox->y1) + fastBox.y1 = pBox->y1; + if (fastBox.y2 > pBox->y2) + fastBox.y2 = pBox->y2; + + /* Check to see if the region is empty */ + if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) { + RegionNull(&rgnDst); + } + else { + RegionInit(&rgnDst, &fastBox, 1); + } + } + else { + /* We must turn off fastClip now, since we must create + a full blown region. It is intersected with the + composite clip below. */ + fastClip = 0; + RegionInit(&rgnDst, &fastBox, 1); + } + } + else { + RegionTranslate(&rgnDst, -dx, -dy); + } + + if (!fastClip) { + RegionIntersect(&rgnDst, &rgnDst, pGC->pCompositeClip); + } + + /* Do bit blitting */ + numRects = RegionNumRects(&rgnDst); + if (numRects && width && height) { + if (!(pptSrc = (DDXPointPtr) malloc(numRects * sizeof(DDXPointRec)))) { + RegionUninit(&rgnDst); + if (freeSrcClip) + RegionDestroy(prgnSrcClip); + return NULL; + } + pbox = RegionRects(&rgnDst); + ppt = pptSrc; + for (i = numRects; --i >= 0; pbox++, ppt++) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc); + free(pptSrc); + } + + prgnExposed = NULL; + if (pGC->fExpose) { + /* Pixmap sources generate a NoExposed (we return NULL to do this) */ + if (!fastExpose) + prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + origSource.x, origSource.y, + (int) origSource.width, + (int) origSource.height, + origDest.x, origDest.y/*, bitPlane*/); + } + RegionUninit(&rgnDst); + if (freeSrcClip) + RegionDestroy(prgnSrcClip); + return prgnExposed; +} diff --git a/hw/xfree86/xaa/xaaBitOrder.c b/hw/xfree86/xaa/xaaBitOrder.c new file mode 100644 index 000000000..3d9b980e1 --- /dev/null +++ b/hw/xfree86/xaa/xaaBitOrder.c @@ -0,0 +1,16 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xaalocal.h" + +CARD32 +XAAReverseBitOrder(CARD32 v) +{ + return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) | + ((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) | + ((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) | + ((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7)); +} diff --git a/hw/xfree86/xaa/xaaBitmap.c b/hw/xfree86/xaa/xaaBitmap.c new file mode 100644 index 000000000..45d5a09be --- /dev/null +++ b/hw/xfree86/xaa/xaaBitmap.c @@ -0,0 +1,477 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xaa.h" +#include "xaalocal.h" +#include "xaacexp.h" +#include "xf86.h" + +/********** byte swapping ***************/ + +#ifdef FIXEDBASE +#define DEST(i) *dest +#define RETURN(i) return(dest) +#else +#define DEST(i) dest[i] +#define RETURN(i) return(dest + i) +#endif + +#ifdef MSBFIRST +#define SOURCE(i) SWAP_BITS_IN_BYTES(src[i]) +#else +#define SOURCE(i) src[i] +#endif + +typedef CARD32 *(*BitmapScanlineProcPtr) (CARD32 *, CARD32 *, int, int); + +#ifdef TRIPLE_BITS +static CARD32 * +BitmapScanline(CARD32 *src, CARD32 *base, int count, int skipleft) +{ + CARD32 bits; + + while (count >= 3) { + bits = *src; + WRITE_BITS3(bits); + src++; + count -= 3; + } + if (count == 2) { + bits = *src; + WRITE_BITS2(bits); + } + else if (count == 1) { + bits = *src; + WRITE_BITS1(bits); + } + + return base; +} + +static CARD32 * +BitmapScanline_Inverted(CARD32 *src, CARD32 *base, int count, int skipleft) +{ + CARD32 bits; + + while (count >= 3) { + bits = ~(*src); + WRITE_BITS3(bits); + src++; + count -= 3; + } + if (count == 2) { + bits = ~(*src); + WRITE_BITS2(bits); + } + else if (count == 1) { + bits = ~(*src); + WRITE_BITS1(bits); + } + + return base; +} + +static CARD32 * +BitmapScanline_Shifted(CARD32 *src, CARD32 *base, int count, int skipleft) +{ + CARD32 bits; + + while (count >= 3) { + bits = SHIFT_R(*src, skipleft) | SHIFT_L(*(src + 1), (32 - skipleft)); + WRITE_BITS3(bits); + src++; + count -= 3; + } + if (count == 2) { + bits = SHIFT_R(*src, skipleft) | SHIFT_L(*(src + 1), (32 - skipleft)); + WRITE_BITS2(bits); + } + else if (count == 1) { + bits = SHIFT_R(*src, skipleft) | SHIFT_L(*(src + 1), (32 - skipleft)); + WRITE_BITS1(bits); + } + + return base; +} + +static CARD32 * +BitmapScanline_Shifted_Inverted(CARD32 *src, CARD32 *base, + int count, int skipleft) +{ + CARD32 bits; + + while (count >= 3) { + bits = + ~(SHIFT_R(*src, skipleft) | SHIFT_L(*(src + 1), (32 - skipleft))); + WRITE_BITS3(bits); + src++; + count -= 3; + } + if (count == 2) { + bits = + ~(SHIFT_R(*src, skipleft) | SHIFT_L(*(src + 1), (32 - skipleft))); + WRITE_BITS2(bits); + } + else if (count == 1) { + bits = + ~(SHIFT_R(*src, skipleft) | SHIFT_L(*(src + 1), (32 - skipleft))); + WRITE_BITS1(bits); + } + + return base; +} + +#define BitmapScanline_Shifted_Careful BitmapScanline_Shifted +#define BitmapScanline_Shifted_Inverted_Careful BitmapScanline_Shifted_Inverted + +#else +static CARD32 * +BitmapScanline(CARD32 *src, CARD32 *dest, int count, int skipleft) +{ + while (count >= 4) { + DEST(0) = SOURCE(0); + DEST(1) = SOURCE(1); + DEST(2) = SOURCE(2); + DEST(3) = SOURCE(3); + count -= 4; + src += 4; +#ifndef FIXEDBASE + dest += 4; +#endif + } + + if (!count) + return dest; + DEST(0) = SOURCE(0); + if (count == 1) + RETURN(1); + DEST(1) = SOURCE(1); + if (count == 2) + RETURN(2); + DEST(2) = SOURCE(2); + RETURN(3); +} + +static CARD32 * +BitmapScanline_Inverted(CARD32 *src, CARD32 *dest, int count, int skipleft) +{ + while (count >= 4) { + DEST(0) = ~SOURCE(0); + DEST(1) = ~SOURCE(1); + DEST(2) = ~SOURCE(2); + DEST(3) = ~SOURCE(3); + count -= 4; + src += 4; +#ifndef FIXEDBASE + dest += 4; +#endif + } + + if (!count) + return dest; + DEST(0) = ~SOURCE(0); + if (count == 1) + RETURN(1); + DEST(1) = ~SOURCE(1); + if (count == 2) + RETURN(2); + DEST(2) = ~SOURCE(2); + RETURN(3); +} + +static CARD32 * +BitmapScanline_Shifted(CARD32 *bits, CARD32 *base, int count, int skipleft) +{ + while (count--) { + register CARD32 tmp = SHIFT_R(*bits, skipleft) | + SHIFT_L(*(bits + 1), (32 - skipleft)); + WRITE_BITS(tmp); + bits++; + } + return base; +} + +static CARD32 * +BitmapScanline_Shifted_Inverted(CARD32 *bits, CARD32 *base, + int count, int skipleft) +{ + while (count--) { + register CARD32 tmp = ~(SHIFT_R(*bits, skipleft) | + SHIFT_L(*(bits + 1), (32 - skipleft))); + WRITE_BITS(tmp); + bits++; + } + return base; +} + +static CARD32 * +BitmapScanline_Shifted_Careful(CARD32 *bits, CARD32 *base, + int count, int skipleft) +{ + register CARD32 tmp; + + while (--count) { + tmp = SHIFT_R(*bits, skipleft) | SHIFT_L(*(bits + 1), (32 - skipleft)); + WRITE_BITS(tmp); + bits++; + } + tmp = SHIFT_R(*bits, skipleft); + WRITE_BITS(tmp); + + return base; +} + +static CARD32 * +BitmapScanline_Shifted_Inverted_Careful(CARD32 *bits, CARD32 *base, + int count, int skipleft) +{ + register CARD32 tmp; + + while (--count) { + tmp = + ~(SHIFT_R(*bits, skipleft) | SHIFT_L(*(bits + 1), (32 - skipleft))); + WRITE_BITS(tmp); + bits++; + } + tmp = ~(SHIFT_R(*bits, skipleft)); + WRITE_BITS(tmp); + return base; +} + +#endif + +/* + When the accelerator is TRANSPARENCY_ONLY, WriteBitmap can do + the fill in two passes, inverting the source on the second pass. + For GXcopy we can fill the backing rectangle as a solid rect and + avoid the invert. +*/ + +void +#ifdef TRIPLE_BITS + EXPNAME(XAAWriteBitmapColorExpand3) ( +#else + EXPNAME(XAAWriteBitmapColorExpand) ( +#endif + ScrnInfoPtr pScrn, + int x, int y, int w, int H, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + unsigned char *srcp = src; + int SecondPassColor = -1; + int shift = 0, dwords; + BitmapScanlineProcPtr firstFunc; + BitmapScanlineProcPtr secondFunc; + int flag; + int h = H; + +#ifdef TRIPLE_BITS + if ((bg != -1) && + ((infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) || + ((infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) && + (!CHECK_RGB_EQUAL(bg))))) { +#else + if ((bg != -1) && + (infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { +#endif + if ((rop == GXcopy) && infoRec->SetupForSolidFill) { + (*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + } + else + SecondPassColor = bg; + bg = -1; + } + +#ifdef TRIPLE_BITS + if (skipleft) { +#else + if (skipleft && + (!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING) || + (!(infoRec-> + CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (skipleft > x)))) { +#endif + if ((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) { + /* don't read past the end */ + firstFunc = BitmapScanline_Shifted_Careful; + secondFunc = BitmapScanline_Shifted_Inverted_Careful; + } + else { + firstFunc = BitmapScanline_Shifted; + secondFunc = BitmapScanline_Shifted_Inverted; + } + shift = skipleft; + skipleft = 0; + } + else { + firstFunc = BitmapScanline; + secondFunc = BitmapScanline_Inverted; + w += skipleft; + x -= skipleft; + } + +#ifdef TRIPLE_BITS + dwords = (3 * w + 31) >> 5; +#else + dwords = (w + 31) >> 5; +#endif + + SECOND_PASS: + + flag = (infoRec->CPUToScreenColorExpandFillFlags + & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01); + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, x, y, w, h, + skipleft); + + base = (CARD32 *) infoRec->ColorExpandBase; + +#ifndef FIXEDBASE + if ((dwords * h) <= infoRec->ColorExpandRange) + while (h--) { + base = (*firstFunc) ((CARD32 *) srcp, base, dwords, shift); + srcp += srcwidth; + } + else +#endif + while (h--) { + (*firstFunc) ((CARD32 *) srcp, base, dwords, shift); + srcp += srcwidth; + } + + if (flag) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + + if (SecondPassColor != -1) { + h = H; /* Reset height */ + fg = SecondPassColor; + SecondPassColor = -1; + firstFunc = secondFunc; + srcp = src; + goto SECOND_PASS; + } + + if (infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +#ifndef FIXEDBASE + +void +#ifdef TRIPLE_BITS + EXPNAME(XAAWriteBitmapScanlineColorExpand3) ( +#else + EXPNAME(XAAWriteBitmapScanlineColorExpand) ( +#endif + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + unsigned char *srcp = src; + int SecondPassColor = -1; + int shift = 0, dwords, bufferNo; + BitmapScanlineProcPtr firstFunc; + BitmapScanlineProcPtr secondFunc; + +#ifdef TRIPLE_BITS + if ((bg != -1) && + ((infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) + || ((infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) && + (!CHECK_RGB_EQUAL(bg))))) { +#else + if ((bg != -1) && + (infoRec-> + ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { +#endif + if ((rop == GXcopy) && infoRec->SetupForSolidFill) { + (*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + } + else + SecondPassColor = bg; + bg = -1; + } + +#ifdef TRIPLE_BITS + if (skipleft) { +#else + if (skipleft && + (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + LEFT_EDGE_CLIPPING) || + (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X) && (skipleft > x)))) { +#endif + if ((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) { + /* don't read past the end */ + firstFunc = BitmapScanline_Shifted_Careful; + secondFunc = BitmapScanline_Shifted_Inverted_Careful; + } + else { + firstFunc = BitmapScanline_Shifted; + secondFunc = BitmapScanline_Shifted_Inverted; + } + shift = skipleft; + skipleft = 0; + } + else { + firstFunc = BitmapScanline; + secondFunc = BitmapScanline_Inverted; + w += skipleft; + x -= skipleft; + } + +#ifdef TRIPLE_BITS + dwords = (3 * w + 31) >> 5; +#else + dwords = (w + 31) >> 5; +#endif + + SECOND_PASS: + + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, x, y, w, h, + skipleft); + + bufferNo = 0; + + while (h--) { + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + (*firstFunc) ((CARD32 *) srcp, base, dwords, shift); + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + srcp += srcwidth; + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + if (SecondPassColor != -1) { + fg = SecondPassColor; + SecondPassColor = -1; + firstFunc = secondFunc; + srcp = src; + goto SECOND_PASS; + } + + SET_SYNC_FLAG(infoRec); +} + +#endif diff --git a/hw/xfree86/xaa/xaaCpyArea.c b/hw/xfree86/xaa/xaaCpyArea.c new file mode 100644 index 000000000..dc2aee64e --- /dev/null +++ b/hw/xfree86/xaa/xaaCpyArea.c @@ -0,0 +1,409 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "migc.h" +#include "gcstruct.h" +#include "pixmapstr.h" + +/* + Written mostly by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). + */ + +RegionPtr +XAACopyArea(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC * pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (pDstDrawable->type == DRAWABLE_WINDOW) { + if ((pSrcDrawable->type == DRAWABLE_WINDOW) || + IS_OFFSCREEN_PIXMAP(pSrcDrawable)) { + if (infoRec->ScreenToScreenBitBlt && + CHECK_ROP(pGC, infoRec->ScreenToScreenBitBltFlags) && + CHECK_ROPSRC(pGC, infoRec->ScreenToScreenBitBltFlags) && + CHECK_PLANEMASK(pGC, infoRec->ScreenToScreenBitBltFlags)) + return (XAABitBlt(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + XAADoBitBlt/*, 0L*/)); + } + else { + if (infoRec->WritePixmap && + ((pDstDrawable->bitsPerPixel == pSrcDrawable->bitsPerPixel) || + ((pDstDrawable->bitsPerPixel == 24) && + (pSrcDrawable->bitsPerPixel == 32) && + (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && + CHECK_ROP(pGC, infoRec->WritePixmapFlags) && + CHECK_ROPSRC(pGC, infoRec->WritePixmapFlags) && + CHECK_PLANEMASK(pGC, infoRec->WritePixmapFlags) && + CHECK_NO_GXCOPY(pGC, infoRec->WritePixmapFlags)) + return (XAABitBlt(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + XAADoImageWrite/*, 0L*/)); + } + } + else if (IS_OFFSCREEN_PIXMAP(pDstDrawable)) { + if ((pSrcDrawable->type == DRAWABLE_WINDOW) || + IS_OFFSCREEN_PIXMAP(pSrcDrawable)) { + if (infoRec->ScreenToScreenBitBlt && + CHECK_ROP(pGC, infoRec->ScreenToScreenBitBltFlags) && + CHECK_ROPSRC(pGC, infoRec->ScreenToScreenBitBltFlags) && + CHECK_PLANEMASK(pGC, infoRec->ScreenToScreenBitBltFlags)) + return (XAABitBlt(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + XAADoBitBlt/*, 0L*/)); + } + } + + return (XAAFallbackOps.CopyArea(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty)); +} + +void +XAADoBitBlt(DrawablePtr pSrc, + DrawablePtr pDst, GC * pGC, RegionPtr prgnDst, DDXPointPtr pptSrc) +{ + int nbox, careful; + BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; + DDXPointPtr pptTmp, pptNew1, pptNew2; + int xdir, ydir; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + /* XXX we have to err on the side of safety when both are windows, + * because we don't know if IncludeInferiors is being used. + */ + careful = ((pSrc == pDst) || + ((pSrc->type == DRAWABLE_WINDOW) && + (pDst->type == DRAWABLE_WINDOW))); + + pbox = RegionRects(prgnDst); + nbox = RegionNumRects(prgnDst); + + pboxNew1 = NULL; + pptNew1 = NULL; + pboxNew2 = NULL; + pptNew2 = NULL; + if (careful && (pptSrc->y < pbox->y1)) { + /* walk source botttom to top */ + ydir = -1; + + if (nbox > 1) { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); + if (!pboxNew1) + return; + pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); + if (!pptNew1) { + free(pboxNew1); + return; + } + pboxBase = pboxNext = pbox + nbox - 1; + while (pboxBase >= pbox) { + while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext + 1; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp <= pboxBase) { + *pboxNew1++ = *pboxTmp++; + *pptNew1++ = *pptTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + pptNew1 -= nbox; + pptSrc = pptNew1; + } + } + else { + /* walk source top to bottom */ + ydir = 1; + } + + if (careful && (pptSrc->x < pbox->x1)) { + /* walk source right to left */ + xdir = -1; + + if (nbox > 1) { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); + pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); + if (!pboxNew2 || !pptNew2) { + free(pptNew2); + free(pboxNew2); + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox + nbox) { + while ((pboxNext < pbox + nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp != pboxBase) { + *pboxNew2++ = *--pboxTmp; + *pptNew2++ = *--pptTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + pptNew2 -= nbox; + pptSrc = pptNew2; + } + } + else { + /* walk source left to right */ + xdir = 1; + } + + (*infoRec->ScreenToScreenBitBlt) (infoRec->pScrn, nbox, pptSrc, pbox, + xdir, ydir, pGC->alu, pGC->planemask); + + if (pboxNew2) { + free(pptNew2); + free(pboxNew2); + } + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + +} + +void +XAADoImageWrite(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, RegionPtr prgnDst, DDXPointPtr pptSrc) +{ + int srcwidth; + unsigned char *psrcBase; /* start of image */ + unsigned char *srcPntr; /* index into the image */ + BoxPtr pbox = RegionRects(prgnDst); + int nbox = RegionNumRects(prgnDst); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int Bpp = pSrc->bitsPerPixel >> 3; + + psrcBase = (unsigned char *) ((PixmapPtr) pSrc)->devPrivate.ptr; + srcwidth = (int) ((PixmapPtr) pSrc)->devKind; + + for (; nbox; pbox++, pptSrc++, nbox--) { + srcPntr = psrcBase + (pptSrc->y * srcwidth) + (pptSrc->x * Bpp); + + (*infoRec->WritePixmap) (infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + srcPntr, srcwidth, pGC->alu, pGC->planemask, + -1, pSrc->bitsPerPixel, pSrc->depth); + } +} + +void +XAADoImageRead(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, RegionPtr prgnDst, DDXPointPtr pptSrc) +{ + int dstwidth; + unsigned char *pdstBase; /* start of image */ + unsigned char *dstPntr; /* index into the image */ + BoxPtr pbox = RegionRects(prgnDst); + int nbox = RegionNumRects(prgnDst); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int Bpp = pSrc->bitsPerPixel >> 3; /* wouldn't get here unless both + src and dst have same bpp */ + + pdstBase = (unsigned char *) ((PixmapPtr) pDst)->devPrivate.ptr; + dstwidth = (int) ((PixmapPtr) pDst)->devKind; + + for (; nbox; pbox++, pptSrc++, nbox--) { + dstPntr = pdstBase + (pbox->y1 * dstwidth) + (pbox->x1 * Bpp); + + (*infoRec->ReadPixmap) (infoRec->pScrn, pptSrc->x, pptSrc->y, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + dstPntr, dstwidth, pSrc->bitsPerPixel, + pSrc->depth); + } +} + +void +XAAScreenToScreenBitBlt(ScrnInfoPtr pScrn, + int nbox, + DDXPointPtr pptSrc, + BoxPtr pbox, + int xdir, int ydir, int alu, unsigned int planemask) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int dirsetup; + + if ((!(infoRec->CopyAreaFlags & ONLY_TWO_BITBLT_DIRECTIONS) + || (xdir == ydir)) && + (!(infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) + || (xdir == 1))) { + (*infoRec->SetupForScreenToScreenCopy) (pScrn, + xdir, ydir, alu, planemask, -1); + for (; nbox; pbox++, pptSrc++, nbox--) + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pptSrc->x, + pptSrc->y, pbox->x1, + pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + SET_SYNC_FLAG(infoRec); + return; + } + + if (infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) { + /* + * This is the case of a chip that only supports xdir = 1, + * with ydir = 1 or ydir = -1, but we have xdir = -1. + */ + (*infoRec->SetupForScreenToScreenCopy) (pScrn, + 1, ydir, alu, planemask, -1); + for (; nbox; pbox++, pptSrc++, nbox--) + if (pptSrc->y != pbox->y1 || pptSrc->x >= pbox->x1) + /* No problem. Do a xdir = 1 blit instead. */ + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pptSrc->x, pptSrc->y, + pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + else { + /* + * This is the difficult case. Needs striping into + * non-overlapping horizontal chunks. + */ + int stripeWidth, w, fullStripes, extra, i; + + stripeWidth = 16; + w = pbox->x2 - pbox->x1; + if (pbox->x1 - pptSrc->x < stripeWidth) + stripeWidth = pbox->x1 - pptSrc->x; + fullStripes = w / stripeWidth; + extra = w % stripeWidth; + + /* First, take care of the little bit on the far right */ + if (extra) + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pptSrc->x + + fullStripes * + stripeWidth, + pptSrc->y, + pbox->x1 + + fullStripes * + stripeWidth, + pbox->y1, extra, + pbox->y2 - + pbox->y1); + + /* Now, take care of the rest of the blit */ + for (i = fullStripes - 1; i >= 0; i--) + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pptSrc->x + + i * stripeWidth, + pptSrc->y, + pbox->x1 + + i * stripeWidth, + pbox->y1, + stripeWidth, + pbox->y2 - + pbox->y1); + } + SET_SYNC_FLAG(infoRec); + return; + } + + /* + * 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++, pptSrc++, nbox--) { + if (xdir == 1 && pptSrc->y != pbox->y1) { + /* Do a xdir = ydir = -1 blit instead. */ + if (dirsetup != -1) { + (*infoRec->SetupForScreenToScreenCopy) (pScrn, + -1, -1, alu, planemask, + -1); + dirsetup = -1; + } + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pptSrc->x, + pptSrc->y, pbox->x1, + pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + } + else if (xdir == -1 && pptSrc->y != pbox->y1) { + /* Do a xdir = ydir = 1 blit instead. */ + if (dirsetup != 1) { + (*infoRec->SetupForScreenToScreenCopy) (pScrn, + 1, 1, alu, planemask, + -1); + dirsetup = 1; + } + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pptSrc->x, + pptSrc->y, pbox->x1, + pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + } + else if (xdir == 1) { + /* + * xdir = 1, ydir = -1. + * Perform line-by-line xdir = ydir = 1 blits, going up. + */ + int i; + + if (dirsetup != 1) { + (*infoRec->SetupForScreenToScreenCopy) (pScrn, + 1, 1, alu, planemask, + -1); + dirsetup = 1; + } + for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pptSrc->x, + pptSrc->y + i, + pbox->x1, + 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) { + (*infoRec->SetupForScreenToScreenCopy) (pScrn, + -1, -1, alu, planemask, + -1); + dirsetup = -1; + } + for (i = 0; i < pbox->y2 - pbox->y1; i++) + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pptSrc->x, + pptSrc->y + i, + pbox->x1, + pbox->y1 + i, + pbox->x2 - pbox->x1, + 1); + } + } /* next box */ + SET_SYNC_FLAG(infoRec); +} diff --git a/hw/xfree86/xaa/xaaCpyPlane.c b/hw/xfree86/xaa/xaaCpyPlane.c new file mode 100644 index 000000000..b78353724 --- /dev/null +++ b/hw/xfree86/xaa/xaaCpyPlane.c @@ -0,0 +1,204 @@ + +/* + A CopyPlane function that handles bitmap->screen copies and + sends anything else to the Fallback. + + Also, a PushPixels for solid fill styles. + + Written by Mark Vojkovich (markv@valinux.com) + +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "servermd.h" + +#include +#include "scrnintstr.h" +#include "mi.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" + +static void XAACopyPlane1toNColorExpand(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, RegionPtr rgnDst, + DDXPointPtr pptSrc); +static void XAACopyPlaneNtoNColorExpand(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, RegionPtr rgnDst, + DDXPointPtr pptSrc); + +static unsigned long TmpBitPlane; + +RegionPtr +XAACopyPlaneColorExpansion(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + if ((pSrc->type == DRAWABLE_PIXMAP) && !XAA_DEPTH_BUG(pGC)) { + if (pSrc->bitsPerPixel == 1) { + return (XAABitBlt(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, + XAACopyPlane1toNColorExpand/*, bitPlane*/)); + } + else if (bitPlane < (1 << pDst->depth)) { + TmpBitPlane = bitPlane; + return (XAABitBlt(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, + XAACopyPlaneNtoNColorExpand/*, bitPlane*/)); + } + } + + return (XAAFallbackOps.CopyPlane(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, bitPlane)); +} + +static void +XAACopyPlane1toNColorExpand(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, RegionPtr rgnDst, DDXPointPtr pptSrc) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + BoxPtr pbox = RegionRects(rgnDst); + int numrects = RegionNumRects(rgnDst); + unsigned char *src = ((PixmapPtr) pSrc)->devPrivate.ptr; + int srcwidth = ((PixmapPtr) pSrc)->devKind; + + while (numrects--) { + (*infoRec->WriteBitmap) (infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + src + (srcwidth * pptSrc->y) + + ((pptSrc->x >> 5) << 2), srcwidth, + pptSrc->x & 31, pGC->fgPixel, pGC->bgPixel, + pGC->alu, pGC->planemask); + pbox++; + pptSrc++; + } +} + +static void +XAACopyPlaneNtoNColorExpand(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, RegionPtr rgnDst, DDXPointPtr pptSrc) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + BoxPtr pbox = RegionRects(rgnDst); + int numrects = RegionNumRects(rgnDst); + unsigned char *src = ((PixmapPtr) pSrc)->devPrivate.ptr; + unsigned char *data, *srcPtr, *dataPtr; + int srcwidth = ((PixmapPtr) pSrc)->devKind; + int pitch, width, height, h, i, index, offset; + int Bpp = pSrc->bitsPerPixel >> 3; + unsigned long mask = TmpBitPlane; + + if (TmpBitPlane < (1 << 8)) { + offset = 0; + } + else if (TmpBitPlane < (1 << 16)) { + offset = 1; + mask >>= 8; + } + else if (TmpBitPlane < (1 << 24)) { + offset = 2; + mask >>= 16; + } + else { + offset = 3; + mask >>= 24; + } + + if (IS_OFFSCREEN_PIXMAP(pSrc)) + SYNC_CHECK(pSrc); + + while (numrects--) { + width = pbox->x2 - pbox->x1; + h = height = pbox->y2 - pbox->y1; + pitch = BitmapBytePad(width); + + if (!(data = calloc(height, pitch))) + goto ALLOC_FAILED; + + dataPtr = data; + srcPtr = ((pptSrc->y) * srcwidth) + src + ((pptSrc->x) * Bpp) + offset; + + while (h--) { + for (i = index = 0; i < width; i++, index += Bpp) { + if (mask & srcPtr[index]) + dataPtr[i >> 3] |= (1 << (i & 7)); + } + dataPtr += pitch; + srcPtr += srcwidth; + } + + (*infoRec->WriteBitmap) (infoRec->pScrn, + pbox->x1, pbox->y1, width, height, data, pitch, + 0, pGC->fgPixel, pGC->bgPixel, pGC->alu, + pGC->planemask); + + free(data); + + ALLOC_FAILED: + + pbox++; + pptSrc++; + } +} + +void +XAAPushPixelsSolidColorExpansion(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int MaxBoxes = RegionNumRects(pGC->pCompositeClip); + BoxPtr pbox, pClipBoxes; + int nboxes, srcx, srcy; + xRectangle TheRect; + unsigned char *src = pBitMap->devPrivate.ptr; + int srcwidth = pBitMap->devKind; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + TheRect.x = xOrg; + TheRect.y = yOrg; + TheRect.width = dx; + TheRect.height = dy; + + if (MaxBoxes > (infoRec->PreAllocSize / sizeof(BoxRec))) { + pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec)); + if (!pClipBoxes) + return; + } + else + pClipBoxes = (BoxPtr) infoRec->PreAllocMem; + + nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); + pbox = pClipBoxes; + + while (nboxes--) { + srcx = pbox->x1 - xOrg; + srcy = pbox->y1 - yOrg; + (*infoRec->WriteBitmap) (infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + src + (srcwidth * srcy) + ((srcx >> 5) << 2), + srcwidth, srcx & 31, + pGC->fgPixel, -1, pGC->alu, pGC->planemask); + pbox++; + } + + if (pClipBoxes != (BoxPtr) infoRec->PreAllocMem) + free(pClipBoxes); +} diff --git a/hw/xfree86/xaa/xaaCpyWin.c b/hw/xfree86/xaa/xaaCpyWin.c new file mode 100644 index 000000000..e851f4a37 --- /dev/null +++ b/hw/xfree86/xaa/xaaCpyWin.c @@ -0,0 +1,78 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "xaawrap.h" + +/* + Written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). +*/ + +void +XAACopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + DDXPointPtr pptSrc, ppt; + RegionRec rgnDst; + BoxPtr pbox; + int dx, dy, nbox; + WindowPtr pwinRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); + + if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { + XAA_SCREEN_PROLOGUE(pScreen, CopyWindow); + if (infoRec->pScrn->vtSema && infoRec->NeedToSync) { + (*infoRec->Sync) (infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + XAA_SCREEN_EPILOGUE(pScreen, CopyWindow, XAACopyWindow); + return; + } + + pwinRoot = pScreen->root; + + RegionNull(&rgnDst); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + RegionTranslate(prgnSrc, -dx, -dy); + RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); + + pbox = RegionRects(&rgnDst); + nbox = RegionNumRects(&rgnDst); + if (!nbox || !(pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { + RegionUninit(&rgnDst); + return; + } + ppt = pptSrc; + + while (nbox--) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + ppt++; + pbox++; + } + + infoRec->ScratchGC.planemask = ~0L; + infoRec->ScratchGC.alu = GXcopy; + + XAADoBitBlt((DrawablePtr) pwinRoot, (DrawablePtr) pwinRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + + free(pptSrc); + RegionUninit(&rgnDst); +} diff --git a/hw/xfree86/xaa/xaaDashLine.c b/hw/xfree86/xaa/xaaDashLine.c new file mode 100644 index 000000000..c7e52cd0b --- /dev/null +++ b/hw/xfree86/xaa/xaaDashLine.c @@ -0,0 +1,353 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "miline.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +void +#ifdef POLYSEGMENT + XAAPolySegmentDashed(DrawablePtr pDrawable, + GCPtr pGC, int nseg, xSegment * pSeg +#else +XAAPolyLinesDashed(DrawablePtr pDrawable, GCPtr pGC, int mode, /* Origin or Previous */ + int npt, /* number of points */ + DDXPointPtr pptInit +#endif + ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAGCPtr pGCPriv = (XAAGCPtr) dixLookupPrivate(&pGC->devPrivates, + XAAGetGCKey()); + BoxPtr pboxInit = RegionRects(pGC->pCompositeClip); + int nboxInit = RegionNumRects(pGC->pCompositeClip); + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + int xorg = pDrawable->x; + int yorg = pDrawable->y; + int nbox; + BoxPtr pbox; + +#ifndef POLYSEGMENT + DDXPointPtr ppt; +#endif + unsigned int oc1, oc2; + int dmin, dmaj, e, octant; + int x1, x2, y1, y2, tmp, len, offset; + int PatternLength, PatternOffset; + + if (!nboxInit) + return; + + if (infoRec->DashedLineFlags & LINE_LIMIT_COORDS) { + int minValX = infoRec->DashedLineLimits.x1; + int maxValX = infoRec->DashedLineLimits.x2; + int minValY = infoRec->DashedLineLimits.y1; + int maxValY = infoRec->DashedLineLimits.y2; + +#ifdef POLYSEGMENT + int n = nseg; + xSegment *s = pSeg; + + while (n--) +#else + int n = npt; + int xorgtmp = xorg; + int yorgtmp = yorg; + + ppt = pptInit; + x2 = ppt->x + xorgtmp; + y2 = ppt->y + yorgtmp; + while (--n) +#endif + { +#ifdef POLYSEGMENT + x1 = s->x1 + xorg; + y1 = s->y1 + yorg; + x2 = s->x2 + xorg; + y2 = s->y2 + yorg; + s++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) { + xorgtmp = x1; + yorgtmp = y1; + } + x2 = ppt->x + xorgtmp; + y2 = ppt->y + yorgtmp; +#endif + if (x1 > maxValX || x1 < minValX || + x2 > maxValX || x2 < minValX || + y1 > maxValY || y1 < minValY || y2 > maxValY || y2 < minValY) { +#ifdef POLYSEGMENT + XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg); +#else + XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit); +#endif + return; + } + } + } + + PatternLength = pGCPriv->DashLength; + PatternOffset = pGC->dashOffset % PatternLength; + + (*infoRec->SetupForDashedLine) (infoRec->pScrn, pGC->fgPixel, + (pGC->lineStyle == + LineDoubleDash) ? pGC->bgPixel : -1, + pGC->alu, pGC->planemask, PatternLength, + pGCPriv->DashPattern); + +#ifdef POLYSEGMENT + while (nseg--) +#else + ppt = pptInit; + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; + while (--npt) +#endif + { + nbox = nboxInit; + pbox = pboxInit; + +#ifdef POLYSEGMENT + x1 = pSeg->x1 + xorg; + y1 = pSeg->y1 + yorg; + x2 = pSeg->x2 + xorg; + y2 = pSeg->y2 + yorg; + pSeg++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) { + xorg = x1; + yorg = y1; + } + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; +#endif + + if (infoRec->SubsequentDashedBresenhamLine) { + if ((dmaj = x2 - x1) < 0) { + dmaj = -dmaj; + octant = XDECREASING; + } + else + octant = 0; + + if ((dmin = y2 - y1) < 0) { + dmin = -dmin; + octant |= YDECREASING; + } + + if (dmin >= dmaj) { + tmp = dmin; + dmin = dmaj; + dmaj = tmp; + octant |= YMAJOR; + } + + e = -dmaj - ((bias >> octant) & 1); + len = dmaj; + dmin <<= 1; + dmaj <<= 1; + } + else { /* Muffle compiler */ + dmin = dmaj = e = octant = len = 0; + } + + while (nbox--) { + oc1 = oc2 = 0; + OUTCODES(oc1, x1, y1, pbox); + OUTCODES(oc2, x2, y2, pbox); + if (!(oc1 | oc2)) { /* uncliped */ + if (infoRec->SubsequentDashedTwoPointLine) { + (*infoRec->SubsequentDashedTwoPointLine) (infoRec->pScrn, + x1, y1, x2, y2, +#ifdef POLYSEGMENT + (pGC->capStyle != + CapNotLast) ? 0 : +#endif + OMIT_LAST, + PatternOffset); + } + else { + (*infoRec->SubsequentDashedBresenhamLine) (infoRec->pScrn, + x1, y1, dmaj, + dmin, e, +#ifdef POLYSEGMENT + (pGC->capStyle != + CapNotLast) + ? (len + 1) : +#endif + len, octant, + PatternOffset); + } + break; + } + else if (oc1 & oc2) { /* completely clipped */ + pbox++; + } + else if (infoRec->ClippingFlags & HARDWARE_CLIP_DASHED_LINE) { + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x2 - 1, pbox->y2 - 1); + + if (infoRec->SubsequentDashedBresenhamLine) { + (*infoRec->SubsequentDashedBresenhamLine) (infoRec->pScrn, + x1, y1, dmaj, + dmin, e, +#ifdef POLYSEGMENT + (pGC->capStyle != + CapNotLast) + ? (len + 1) : +#endif + len, octant, + PatternOffset); + } + else { + (*infoRec->SubsequentDashedTwoPointLine) (infoRec->pScrn, + x1, y1, x2, y2, +#ifdef POLYSEGMENT + (pGC->capStyle != + CapNotLast) ? 0 : +#endif + OMIT_LAST, + PatternOffset); + } + (*infoRec->DisableClipping) (infoRec->pScrn); + pbox++; + } + else { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int err, adx, ady; + + if (octant & YMAJOR) { + ady = dmaj >> 1; + adx = dmin >> 1; + } + else { + ady = dmin >> 1; + adx = dmaj >> 1; + } + + if (miZeroClipLine(pbox->x1, pbox->y1, + pbox->x2 - 1, pbox->y2 - 1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) { + pbox++; + continue; + } + + if (octant & YMAJOR) + len = abs(new_y2 - new_y1); + else + len = abs(new_x2 - new_x1); +#ifdef POLYSEGMENT + if (clip2 != 0 || pGC->capStyle != CapNotLast) + len++; +#else + len += (clip2 != 0); +#endif + if (len) { + int abserr, clipdx, clipdy; + + /* unwind bresenham error term to first point */ + if (clip1) { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + + if (octant & YMAJOR) + err = e + clipdy * dmin - clipdx * dmaj; + else + err = e + clipdx * dmin - clipdy * dmaj; + } + else + err = e; + +#define range infoRec->DashedBresenhamLineErrorTermBits + abserr = abs(err); + while ((abserr & range) || (dmaj & range) || (dmin & range)) { + dmin >>= 1; + dmaj >>= 1; + abserr >>= 1; + err /= 2; + } + + if (octant & YMAJOR) + offset = abs(new_y1 - y1); + else + offset = abs(new_x1 - x1); + + offset += PatternOffset; + offset %= PatternLength; + + (*infoRec->SubsequentDashedBresenhamLine) (infoRec->pScrn, + new_x1, new_y1, + dmaj, dmin, err, + len, octant, + offset); + } + pbox++; + } + } /* while (nbox--) */ +#ifndef POLYSEGMENT + len = abs(y2 - y1); + tmp = abs(x2 - x1); + PatternOffset += (len > tmp) ? len : tmp; + PatternOffset %= PatternLength; +#endif + } /* while (nline--) */ + +#ifndef POLYSEGMENT + /* paint the last point if the end style isn't CapNotLast. + (Assume that a projecting, butt, or round cap that is one + pixel wide is the same as the single pixel of the endpoint.) + */ + + if ((pGC->capStyle != CapNotLast) && + ((ppt->x + xorg != pptInit->x + pDrawable->x) || + (ppt->y + yorg != pptInit->y + pDrawable->y) || + (ppt == pptInit + 1))) { + nbox = nboxInit; + pbox = pboxInit; + while (nbox--) { + if ((x2 >= pbox->x1) && (y2 >= pbox->y1) && + (x2 < pbox->x2) && (y2 < pbox->y2)) { + if (infoRec->SubsequentDashedTwoPointLine) { + (*infoRec->SubsequentDashedTwoPointLine) (infoRec->pScrn, + x2, y2, x2, y2, 0, + PatternOffset); + } + else { + (*infoRec->SubsequentDashedBresenhamLine) (infoRec->pScrn, + x2, y2, 2, 0, -1, + 1, 0, + PatternOffset); + } + break; + } + else + pbox++; + } + } +#endif + + SET_SYNC_FLAG(infoRec); +} diff --git a/hw/xfree86/xaa/xaaFallback.c b/hw/xfree86/xaa/xaaFallback.c new file mode 100644 index 000000000..2e7cad9bc --- /dev/null +++ b/hw/xfree86/xaa/xaaFallback.c @@ -0,0 +1,281 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "xaawrap.h" + +static void +XAAFillSpansFallback(DrawablePtr pDraw, + GC * pGC, + int nInit, + DDXPointPtr pptInit, int *pwidthInit, int fSorted) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->FillSpans) (pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAASetSpansFallback(DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + register DDXPointPtr ppt, + int *pwidth, int nspans, int fSorted) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->SetSpans) (pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPutImageFallback(DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, int format, char *pImage) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PutImage) (pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + XAA_GC_OP_EPILOGUE(pGC); +} + +static RegionPtr +XAACopyAreaFallback(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, + int srcx, int srcy, + int width, int height, int dstx, int dsty) +{ + RegionPtr ret; + + XAA_GC_OP_PROLOGUE(pGC); + if ((pSrc->type == DRAWABLE_WINDOW) || (pDst->type == DRAWABLE_WINDOW) || + IS_OFFSCREEN_PIXMAP(pSrc) || IS_OFFSCREEN_PIXMAP(pDst)) { + SYNC_CHECK(pGC); + } + ret = (*pGC->ops->CopyArea) (pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + XAA_GC_OP_EPILOGUE(pGC); + return ret; +} + +static RegionPtr +XAACopyPlaneFallback(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + RegionPtr ret; + + XAA_GC_OP_PROLOGUE(pGC); + if ((pSrc->type == DRAWABLE_WINDOW) || (pDst->type == DRAWABLE_WINDOW) || + IS_OFFSCREEN_PIXMAP(pSrc) || IS_OFFSCREEN_PIXMAP(pDst)) { + SYNC_CHECK(pGC); + } + ret = (*pGC->ops->CopyPlane) (pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, + bitPlane); + XAA_GC_OP_EPILOGUE(pGC); + return ret; +} + +static void +XAAPolyPointFallback(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, xPoint * pptInit) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolyPoint) (pDraw, pGC, mode, npt, pptInit); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolylinesFallback(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->Polylines) (pDraw, pGC, mode, npt, pptInit); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolySegmentFallback(DrawablePtr pDraw, GCPtr pGC, int nseg, xSegment * pSeg) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolySegment) (pDraw, pGC, nseg, pSeg); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolyRectangleFallback(DrawablePtr pDraw, + GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolyRectangle) (pDraw, pGC, nRectsInit, pRectsInit); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolyArcFallback(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolyArc) (pDraw, pGC, narcs, parcs); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAFillPolygonFallback(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->FillPolygon) (pDraw, pGC, shape, mode, count, ptsIn); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolyFillRectFallback(DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolyFillRect) (pDraw, pGC, nrectFill, prectInit); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolyFillArcFallback(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, parcs); + XAA_GC_OP_EPILOGUE(pGC); +} + +static int +XAAPolyText8Fallback(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + int ret; + + XAA_GC_OP_PROLOGUE(pGC); + SYNC_CHECK(pGC); + ret = (*pGC->ops->PolyText8) (pDraw, pGC, x, y, count, chars); + XAA_GC_OP_EPILOGUE(pGC); + return ret; +} + +static int +XAAPolyText16Fallback(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + int ret; + + XAA_GC_OP_PROLOGUE(pGC); + SYNC_CHECK(pGC); + ret = (*pGC->ops->PolyText16) (pDraw, pGC, x, y, count, chars); + XAA_GC_OP_EPILOGUE(pGC); + return ret; +} + +static void +XAAImageText8Fallback(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->ImageText8) (pDraw, pGC, x, y, count, chars); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAImageText16Fallback(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->ImageText16) (pDraw, pGC, x, y, count, chars); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAImageGlyphBltFallback(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->ImageGlyphBlt) (pDraw, pGC, xInit, yInit, nglyph, ppci, + pglyphBase); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPolyGlyphBltFallback(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PolyGlyphBlt) (pDraw, pGC, xInit, yInit, nglyph, ppci, + pglyphBase); + XAA_GC_OP_EPILOGUE(pGC); +} + +static void +XAAPushPixelsFallback(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, int dx, int dy, int xOrg, int yOrg) +{ + XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC); + SYNC_CHECK(pGC); + (*pGC->ops->PushPixels) (pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + XAA_GC_OP_EPILOGUE(pGC); +} + +GCOps XAAFallbackOps = { + XAAFillSpansFallback, XAASetSpansFallback, + XAAPutImageFallback, XAACopyAreaFallback, + XAACopyPlaneFallback, XAAPolyPointFallback, + XAAPolylinesFallback, XAAPolySegmentFallback, + XAAPolyRectangleFallback, XAAPolyArcFallback, + XAAFillPolygonFallback, XAAPolyFillRectFallback, + XAAPolyFillArcFallback, XAAPolyText8Fallback, + XAAPolyText16Fallback, XAAImageText8Fallback, + XAAImageText16Fallback, XAAImageGlyphBltFallback, + XAAPolyGlyphBltFallback, XAAPushPixelsFallback, +}; + +GCOps * +XAAGetFallbackOps(void) +{ + return &XAAFallbackOps; +} diff --git a/hw/xfree86/xaa/xaaFillArc.c b/hw/xfree86/xaa/xaaFillArc.c new file mode 100644 index 000000000..fb7e7201f --- /dev/null +++ b/hw/xfree86/xaa/xaaFillArc.c @@ -0,0 +1,202 @@ +/* + * Copyright 1996 The XFree86 Project + * + * 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 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 + * HARM HANEMAAYER 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. + * + * Written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). + */ + +/* + * Filled solid arcs, based on cfbfillarc.c. + * + * Fill arc using calls to low-level span fill. Because the math for + * each span can be done concurrently with the drawing of the span + * with a graphics coprocessor operation, this is faster than just + * using miPolyFillArc, which first calculates all the spans and then + * calls FillSpans. + * + * Clipped arcs are dispatched to FillSpans. + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "mifillarc.h" +#include "mi.h" + +/* + * This is based on the integer-math versions from mi. Perhaps on a + * Pentium, the floating-point (double)-math version is faster. + */ + +static void +XAAFillEllipseSolid(DrawablePtr pDraw, GCPtr pGC, xArc * arc) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + register int x, y, e; + int yk, xk, ym, xm, dx, dy, xorg, yorg; + int slw; + miFillArcRec info; + + (*infoRec->SetupForSolidFill) (infoRec->pScrn, pGC->fgPixel, pGC->alu, + pGC->planemask); + + miFillArcSetup(arc, &info); + MIFILLARCSETUP(); + if (pGC->miTranslate) { + xorg += pDraw->x; + yorg += pDraw->y; + } + while (y > 0) { + MIFILLARCSTEP(slw); + if (slw > 0) { + (*infoRec->SubsequentSolidFillRect) (infoRec->pScrn, xorg - x, + yorg - y, slw, 1); + if (miFillArcLower(slw)) + (*infoRec->SubsequentSolidFillRect) (infoRec->pScrn, + xorg - x, yorg + y + dy, + slw, 1); + } + } + + SET_SYNC_FLAG(infoRec); +} + +#define ADDSPAN(l,r) \ + if (r >= l) \ + (*infoRec->SubsequentSolidFillRect)( \ + infoRec->pScrn, l, ya, r - l + 1, 1); + +#define ADDSLICESPANS(flip) \ + if (!flip) \ + { \ + ADDSPAN(xl, xr); \ + } \ + else \ + { \ + xc = xorg - x; \ + ADDSPAN(xc, xr); \ + xc += slw - 1; \ + ADDSPAN(xl, xc); \ + } + +static void +XAAFillArcSliceSolid(DrawablePtr pDraw, GCPtr pGC, xArc * arc) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; + register int x, y, e; + miFillArcRec info; + miArcSliceRec slice; + int ya, xl, xr, xc; + + (*infoRec->SetupForSolidFill) (infoRec->pScrn, pGC->fgPixel, pGC->alu, + pGC->planemask); + + miFillArcSetup(arc, &info); + miFillArcSliceSetup(arc, &slice, pGC); + MIFILLARCSETUP(); + slw = arc->height; + if (slice.flip_top || slice.flip_bot) + slw += (arc->height >> 1) + 1; + if (pGC->miTranslate) { + xorg += pDraw->x; + yorg += pDraw->y; + slice.edge1.x += pDraw->x; + slice.edge2.x += pDraw->x; + } + while (y > 0) { + MIFILLARCSTEP(slw); + MIARCSLICESTEP(slice.edge1); + MIARCSLICESTEP(slice.edge2); + if (miFillSliceUpper(slice)) { + ya = yorg - y; + MIARCSLICEUPPER(xl, xr, slice, slw); + + ADDSLICESPANS(slice.flip_top); + } + if (miFillSliceLower(slice)) { + ya = yorg + y + dy; + MIARCSLICELOWER(xl, xr, slice, slw); + ADDSLICESPANS(slice.flip_bot); + } + } + + SET_SYNC_FLAG(infoRec); +} + +void +XAAPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) +{ + register xArc *arc; + register int i; + int x2, y2; + BoxRec box; + RegionPtr cclip; + + cclip = pGC->pCompositeClip; + + if (!RegionNumRects(cclip)) + return; + + for (arc = parcs, i = narcs; --i >= 0; arc++) { + if (miFillArcEmpty(arc)) + continue; + if (miCanFillArc(arc)) { + box.x1 = arc->x + pDraw->x; + box.y1 = arc->y + pDraw->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int) arc->width + 1; + box.x2 = x2; + y2 = box.y1 + (int) arc->height + 1; + box.y2 = y2; + if ((x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) && + (RegionContainsRect(cclip, &box) == rgnIN)) { + if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) + XAAFillEllipseSolid(pDraw, pGC, arc); + else + XAAFillArcSliceSolid(pDraw, pGC, arc); + continue; + } + } + miPolyFillArc(pDraw, pGC, 1, arc); + } +} diff --git a/hw/xfree86/xaa/xaaFillPoly.c b/hw/xfree86/xaa/xaaFillPoly.c new file mode 100644 index 000000000..c6f64759c --- /dev/null +++ b/hw/xfree86/xaa/xaaFillPoly.c @@ -0,0 +1,991 @@ + +/* + * Copyright 1996 The XFree86 Project + * + * 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 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 + * HARM HANEMAAYER 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. + * + */ + +/* + * Written by Mark Vojkovich. Loosly based on an original version + * written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net) which + * only did solid rectangles and didn't have trapezoid support. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "mi.h" +#include "micoord.h" + +#include "xaa.h" +#include "xaalocal.h" + +#define POLY_USE_MI 0 +#define POLY_FULLY_CLIPPED 1 +#define POLY_IS_EASY 2 + +#define Setup(c,x,vertex,dx,dy,e,sign,step,DX) {\ + x = intToX(vertex); \ + if ((dy = intToY(c) - y)) { \ + DX = dx = intToX(c) - x; \ + step = 0; \ + if (dx >= 0) \ + { \ + e = 0; \ + sign = 1; \ + if (dx >= dy) {\ + step = dx / dy; \ + dx %= dy; \ + } \ + } \ + else \ + { \ + e = 1 - dy; \ + sign = -1; \ + dx = -dx; \ + if (dx >= dy) { \ + step = - (dx / dy); \ + dx %= dy; \ + } \ + } \ + } \ + x += origin; \ + vertex = c; \ +} + +#define Step(x,dx,dy,e,sign,step) {\ + x += step; \ + if ((e += dx) > 0) \ + { \ + x += sign; \ + e -= dy; \ + } \ +} + +#define FixError(x, dx, dy, e, sign, step, h) { \ + e += (h) * dx; \ + x += (h) * step; \ + if(e > 0) { \ + x += e * sign/dy; \ + e %= dy; \ + if(e) { \ + x += sign; \ + e -= dy; \ + } \ + } \ +} + +/* + XAAIsEasyPoly - + + Checks CoordModeOrigin one rect polygons to see if we need + to use Mi. + Returns: POLY_USE_MI, POLY_FULLY_CLIPPED or POLY_IS_EASY + as well as the void * to the "top" point and the y + extents. +*/ + +int +XAAIsEasyPolygon(DDXPointPtr ptsIn, int count, BoxPtr extents, int origin, DDXPointPtr * topPoint, /* return */ + int *topY, int *bottomY, /* return */ + int shape) +{ + int c = 0, vertex1, vertex2; + + *topY = 32767; + *bottomY = 0; + + origin -= (origin & 0x8000) << 1; + vertex1 = extents->x1 - origin; + vertex2 = extents->x2 - origin /* - 0x00010001 */ ; + /* I think this was an error in cfb ^ */ + + if (shape == Convex) { + while (count--) { + c = *((int *) ptsIn); + if (((c - vertex1) | (vertex2 - c)) & 0x80008000) + return POLY_USE_MI; + + c = intToY(c); + if (c < *topY) { + *topY = c; + *topPoint = ptsIn; + } + ptsIn++; + if (c > *bottomY) + *bottomY = c; + } + } + else { + int yFlip = 0; + int dx2, dx1, x1, x2; + + x2 = x1 = -1; + dx2 = dx1 = 1; + + while (count--) { + c = *((int *) ptsIn); + if (((c - vertex1) | (vertex2 - c)) & 0x80008000) + return POLY_USE_MI; + c = intToY(c); + if (c < *topY) { + *topY = c; + *topPoint = ptsIn; + } + ptsIn++; + if (c > *bottomY) + *bottomY = c; + if (c == x1) + continue; + if (dx1 > 0) { + if (x2 < 0) + x2 = c; + else + dx2 = dx1 = (c - x1) >> 31; + } + else if ((c - x1) >> 31 != dx1) { + dx1 = ~dx1; + yFlip++; + } + x1 = c; + } + x1 = (x2 - c) >> 31; + if (x1 != dx1) + yFlip++; + if (x1 != dx2) + yFlip++; + if (yFlip != 2) { + if (*topY == *bottomY) + return POLY_FULLY_CLIPPED; + else + return POLY_USE_MI; + } + } + if (*topY == *bottomY) + return POLY_FULLY_CLIPPED; + + return POLY_IS_EASY; +} + +void +XAAFillPolygonSolid(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int origin, vertex1, vertex2; + int *vertex1p, *vertex2p, *endp; + int x1 = 0, x2 = 0; + int dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0; + int DX1 = 0, DX2 = 0, e1 = 0, e2 = 0; + int step1 = 0, step2 = 0, sign1 = 0, sign2 = 0; + int c, y, maxy, h, yoffset; + DDXPointPtr topPoint; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + if (mode == CoordModePrevious) { + register DDXPointPtr ppt = ptsIn + 1; + + for (origin = 1; origin < count; origin++, ppt++) { + ppt->x += (ppt - 1)->x; + ppt->y += (ppt - 1)->y; + } + mode = CoordModeOrigin; + } + + if (RegionNumRects(pGC->pCompositeClip) != 1) { + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + origin = coordToInt(pDraw->x, pDraw->y); + + switch (XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents, + origin, &topPoint, &y, &maxy, shape)) { + case POLY_USE_MI: + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + case POLY_FULLY_CLIPPED: + return; + } + + endp = (int *) ptsIn + count; + vertex2p = vertex1p = (int *) topPoint; + origin = pDraw->x; + yoffset = pDraw->y; + vertex2 = vertex1 = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + + (*infoRec->SetupForSolidFill) (infoRec->pScrn, pGC->fgPixel, pGC->alu, + pGC->planemask); + + while (1) { + if (y == intToY(vertex1)) { + do { + if (vertex1p == (int *) ptsIn) + vertex1p = endp; + c = *--vertex1p; + Setup(c, x1, vertex1, dx1, dy1, e1, sign1, step1, DX1) + } while (y >= intToY(vertex1)); + h = dy1; + } + else { + Step(x1, dx1, dy1, e1, sign1, step1) + h = intToY(vertex1) - y; + } + if (y == intToY(vertex2)) { + do { + c = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + Setup(c, x2, vertex2, dx2, dy2, e2, sign2, step2, DX2) + } while (y >= intToY(vertex2)); + if (dy2 < h) + h = dy2; + } + else { + Step(x2, dx2, dy2, e2, sign2, step2) + if ((c = (intToY(vertex2) - y)) < h) + h = c; + } + + /* fill spans for this segment */ + if (DX1 | DX2) { + if (infoRec->SubsequentSolidFillTrap && (h > 6)) { + if (x1 == x2) { + while (x1 == x2) { + y++; + if (!--h) + break; + Step(x1, dx1, dy1, e1, sign1, step1) + Step(x2, dx2, dy2, e2, sign2, step2) + } + if (y == maxy) + break; + if (!h) + continue; + } + + if (x1 < x2) + (*infoRec->SubsequentSolidFillTrap) (infoRec->pScrn, + y + yoffset, h, + x1, DX1, dy1, e1, + x2 - 1, DX2, dy2, e2); + else + (*infoRec->SubsequentSolidFillTrap) (infoRec->pScrn, + y + yoffset, h, + x2, DX2, dy2, e2, + x1 - 1, DX1, dy1, e1); + y += h; + if (--h) { + FixError(x1, dx1, dy1, e1, sign1, step1, h); + FixError(x2, dx2, dy2, e2, sign2, step2, h); + h = 0; + } + } + else { + while (1) { + if (x2 > x1) + (*infoRec->SubsequentSolidFillRect) (infoRec->pScrn, + x1, y + yoffset, + x2 - x1, 1); + else if (x1 > x2) + (*infoRec->SubsequentSolidFillRect) (infoRec->pScrn, + x2, y + yoffset, + x1 - x2, 1); + y++; + if (!--h) + break; + Step(x1, dx1, dy1, e1, sign1, step1) + Step(x2, dx2, dy2, e2, sign2, step2) + } + } + } + else { + if (x2 > x1) + (*infoRec->SubsequentSolidFillRect) (infoRec->pScrn, + x1, y + yoffset, x2 - x1, + h); + else if (x1 > x2) + (*infoRec->SubsequentSolidFillRect) (infoRec->pScrn, + x2, y + yoffset, x1 - x2, + h); + + y += h; + h = 0; + } + if (y == maxy) + break; + } + SET_SYNC_FLAG(infoRec); +} + +void +XAAFillPolygonHelper(ScrnInfoPtr pScrn, + DDXPointPtr ptsIn, + int count, + DDXPointPtr topPoint, + int y, + int maxy, + int origin, + RectFuncPtr RectFunc, + TrapFuncPtr TrapFunc, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + int *vertex1p, *vertex2p, *endp; + int vertex1, vertex2; + int x1 = 0, x2 = 0; + int dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0; + int DX1 = 0, DX2 = 0, e1 = 0, e2 = 0; + int step1 = 0, step2 = 0, sign1 = 0, sign2 = 0; + int c, h, yoffset; + + endp = (int *) ptsIn + count; + vertex2p = vertex1p = (int *) topPoint; + yoffset = intToY(origin); + origin = intToX(origin); + vertex2 = vertex1 = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + + while (1) { + if (y == intToY(vertex1)) { + do { + if (vertex1p == (int *) ptsIn) + vertex1p = endp; + c = *--vertex1p; + Setup(c, x1, vertex1, dx1, dy1, e1, sign1, step1, DX1) + } while (y >= intToY(vertex1)); + h = dy1; + } + else { + Step(x1, dx1, dy1, e1, sign1, step1) + h = intToY(vertex1) - y; + } + if (y == intToY(vertex2)) { + do { + c = *vertex2p++; + if (vertex2p == endp) + vertex2p = (int *) ptsIn; + Setup(c, x2, vertex2, dx2, dy2, e2, sign2, step2, DX2) + } while (y >= intToY(vertex2)); + if (dy2 < h) + h = dy2; + } + else { + Step(x2, dx2, dy2, e2, sign2, step2) + if ((c = (intToY(vertex2) - y)) < h) + h = c; + } + + /* fill spans for this segment */ + if (DX1 | DX2) { + if (TrapFunc && (h > 6)) { + if (x1 == x2) { + while (x1 == x2) { + y++; + if (!--h) + break; + Step(x1, dx1, dy1, e1, sign1, step1) + Step(x2, dx2, dy2, e2, sign2, step2) + } + if (y == maxy) + break; + if (!h) + continue; + } + + if (x1 < x2) + (*TrapFunc) (pScrn, y + yoffset, h, + x1, DX1, dy1, e1, + x2 - 1, DX2, dy2, e2, xorg, yorg, pCache); + else + (*TrapFunc) (pScrn, y + yoffset, h, + x2, DX2, dy2, e2, + x1 - 1, DX1, dy1, e1, xorg, yorg, pCache); + y += h; + if (--h) { + FixError(x1, dx1, dy1, e1, sign1, step1, h); + FixError(x2, dx2, dy2, e2, sign2, step2, h); + h = 0; + } + } + else { + while (1) { + if (x2 > x1) + (*RectFunc) (pScrn, + x1, y + yoffset, x2 - x1, 1, xorg, yorg, + pCache); + else if (x1 > x2) + (*RectFunc) (pScrn, + x2, y + yoffset, x1 - x2, 1, xorg, yorg, + pCache); + y++; + if (!--h) + break; + Step(x1, dx1, dy1, e1, sign1, step1) + Step(x2, dx2, dy2, e2, sign2, step2) + } + } + } + else { + if (x2 > x1) + (*RectFunc) (pScrn, + x1, y + yoffset, x2 - x1, h, xorg, yorg, pCache); + else if (x1 > x2) + (*RectFunc) (pScrn, + x2, y + yoffset, x1 - x2, h, xorg, yorg, pCache); + + y += h; + h = 0; + } + if (y == maxy) + break; + } +} + + /*****************\ + | Solid Helpers | + \*****************/ + +static void +SolidTrapHelper(ScrnInfoPtr pScrn, + int y, int h, + int x1, int dx1, int dy1, int e1, + int x2, int dx2, int dy2, int e2, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SubsequentSolidFillTrap) (pScrn, + y, h, x1, dx1, dy1, e1, x2, dx2, dy2, + e2); +} + +static void +SolidRectHelper(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); +} + + /*********************\ + | Mono 8x8 Patterns | + \*********************/ + +static void +Mono8x8PatternTrapHelper_ScreenOrigin(ScrnInfoPtr pScrn, + int y, int h, + int x1, int dx1, int dy1, int e1, + int x2, int dx2, int dy2, int e2, + int xorg, int yorg, + XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SubsequentMono8x8PatternFillTrap) (pScrn, xorg, yorg, + y, h, x1, dx1, dy1, e1, x2, + dx2, dy2, e2); +} + +static void +Mono8x8PatternRectHelper_ScreenOrigin(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int xorg, int yorg, + XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, xorg, yorg, + x, y, w, h); +} + +static void +Mono8x8PatternRectHelper(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + xorg = (x - xorg) & 0x07; + yorg = (y - yorg) & 0x07; + + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + if (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) { + int patx = pCache->pat0; + int paty = pCache->pat1; + + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + else { + int slot = (yorg << 3) + xorg; + + xorg = pCache->x + pCache->offsets[slot].x; + yorg = pCache->y + pCache->offsets[slot].y; + } + } + + (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, xorg, yorg, + x, y, w, h); +} + + /****************\ + | Cache Expand | + \****************/ + +static void +CacheExpandRectHelper(ScrnInfoPtr pScrn, + int X, int Y, int Width, int Height, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, phaseY, phaseX, skipleft, w, blit_w, blit_h; + int cacheWidth; + + cacheWidth = (pCache->w * pScrn->bitsPerPixel) / + infoRec->CacheColorExpandDensity; + + phaseY = (Y - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + phaseX = (X - xorg) % pCache->orig_w; + if (phaseX < 0) + phaseX += pCache->orig_w; + + while (1) { + w = Width; + skipleft = phaseX; + x = X; + blit_h = pCache->h - phaseY; + if (blit_h > Height) + blit_h = Height; + + while (1) { + blit_w = cacheWidth - skipleft; + if (blit_w > w) + blit_w = w; + (*infoRec->SubsequentScreenToScreenColorExpandFill) (pScrn, x, Y, + blit_w, blit_h, + pCache->x, + pCache->y + + phaseY, + skipleft); + w -= blit_w; + if (!w) + break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + } + Height -= blit_h; + if (!Height) + break; + Y += blit_h; + phaseY = (phaseY + blit_h) % pCache->orig_h; + } +} + + /**************\ + | Cache Blit | + \**************/ + +static void +CacheBltRectHelper(ScrnInfoPtr pScrn, + int X, int Y, int Width, int Height, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, phaseY, phaseX, skipleft, w, blit_w, blit_h; + + phaseY = (Y - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + phaseX = (X - xorg) % pCache->orig_w; + if (phaseX < 0) + phaseX += pCache->orig_w; + + while (1) { + w = Width; + skipleft = phaseX; + x = X; + blit_h = pCache->h - phaseY; + if (blit_h > Height) + blit_h = Height; + + while (1) { + blit_w = pCache->w - skipleft; + if (blit_w > w) + blit_w = w; + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pCache->x + skipleft, + pCache->y + phaseY, x, Y, + blit_w, blit_h); + w -= blit_w; + if (!w) + break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + } + Height -= blit_h; + if (!Height) + break; + Y += blit_h; + phaseY = (phaseY + blit_h) % pCache->orig_h; + } +} + + /**********************\ + | Stippled Polygons | + \**********************/ + +void +XAAFillPolygonStippled(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + int origin, type, patx, paty, fg, bg; + int y, maxy, xorg, yorg; + DDXPointPtr topPoint; + XAACacheInfoPtr pCache = NULL; + RectFuncPtr RectFunc = NULL; + TrapFuncPtr TrapFunc = NULL; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + if (mode == CoordModePrevious) { + register DDXPointPtr ppt = ptsIn + 1; + + for (origin = 1; origin < count; origin++, ppt++) { + ppt->x += (ppt - 1)->x; + ppt->y += (ppt - 1)->y; + } + mode = CoordModeOrigin; + } + + if (RegionNumRects(pGC->pCompositeClip) != 1) { + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + if (pGC->fillStyle == FillStippled) { + type = (*infoRec->StippledFillChooser) (pGC); + fg = pGC->fgPixel; + bg = -1; + } + else { + type = (*infoRec->OpaqueStippledFillChooser) (pGC); + fg = pGC->fgPixel; + bg = pGC->bgPixel; + } + + if (!type) { + (*XAAFallbackOps.FillPolygon) (pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + if ((type == DO_COLOR_EXPAND) || (type == DO_COLOR_8x8)) { + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + origin = pDraw->x; + + switch (XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents, + origin, &topPoint, &y, &maxy, shape)) { + case POLY_USE_MI: + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + case POLY_FULLY_CLIPPED: + return; + } + + xorg = (pDraw->x + pGC->patOrg.x); + yorg = (pDraw->y + pGC->patOrg.y); + + if ((fg == bg) && (bg != -1) && infoRec->SetupForSolidFill) { + + (*infoRec->SetupForSolidFill) (infoRec->pScrn, fg, + pGC->alu, pGC->planemask); + + RectFunc = SolidRectHelper; + TrapFunc = infoRec->SubsequentSolidFillTrap ? SolidTrapHelper : NULL; + } + else + switch (type) { + case DO_MONO_8x8: + patx = pPriv->pattern0; + paty = pPriv->pattern1; + if (infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_SCREEN_ORIGIN) { + xorg = (-xorg) & 0x07; + yorg = (-yorg) & 0x07; + if (infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS) { + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + } + else { + XAACacheInfoPtr pCache = + (*infoRec->CacheMono8x8Pattern) (infoRec->pScrn, patx, + paty); + patx = pCache->x; + paty = pCache->y; + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + patx += pCache->offsets[slot].x; + paty += pCache->offsets[slot].y; + xorg = patx; + yorg = paty; + } + } + RectFunc = Mono8x8PatternRectHelper_ScreenOrigin; + if (infoRec->SubsequentMono8x8PatternFillTrap) + TrapFunc = Mono8x8PatternTrapHelper_ScreenOrigin; + } + else { /* !HARDWARE_PATTERN_SCREEN_ORIGIN */ + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS)) { + pCache = + (*infoRec->CacheMono8x8Pattern) (infoRec->pScrn, patx, + paty); + patx = pCache->x; + paty = pCache->y; + } + else { + pCache = &(infoRec->ScratchCacheInfoRec); + pCache->pat0 = patx; + pCache->pat1 = paty; + } + RectFunc = Mono8x8PatternRectHelper; + } + + (*infoRec->SetupForMono8x8PatternFill) (infoRec->pScrn, + patx, paty, fg, bg, + pGC->alu, pGC->planemask); + break; + case DO_CACHE_EXPAND: + pCache = + (*infoRec->CacheMonoStipple) (infoRec->pScrn, pGC->stipple); + + (*infoRec->SetupForScreenToScreenColorExpandFill) (infoRec->pScrn, + fg, bg, pGC->alu, + pGC->planemask); + + RectFunc = CacheExpandRectHelper; + break; + case DO_CACHE_BLT: + pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple, + fg, bg); + (*infoRec->SetupForScreenToScreenCopy) (infoRec->pScrn, 1, 1, + pGC->alu, pGC->planemask, + pCache->trans_color); + + RectFunc = CacheBltRectHelper; + break; + default: + return; + } + + XAAFillPolygonHelper(infoRec->pScrn, ptsIn, count, topPoint, + y, maxy, origin, RectFunc, TrapFunc, xorg, yorg, + pCache); + + SET_SYNC_FLAG(infoRec); +} + + /*******************\ + | Tiled Polygons | + \*******************/ + +void +XAAFillPolygonTiled(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + int origin, type, patx, paty; + int y, maxy, xorg, yorg; + DDXPointPtr topPoint; + XAACacheInfoPtr pCache = NULL; + RectFuncPtr RectFunc = NULL; + TrapFuncPtr TrapFunc = NULL; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + if (mode == CoordModePrevious) { + register DDXPointPtr ppt = ptsIn + 1; + + for (origin = 1; origin < count; origin++, ppt++) { + ppt->x += (ppt - 1)->x; + ppt->y += (ppt - 1)->y; + } + mode = CoordModeOrigin; + } + + if (RegionNumRects(pGC->pCompositeClip) != 1) { + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + type = (*infoRec->TiledFillChooser) (pGC); + + if (!type || (type == DO_IMAGE_WRITE)) { + (*XAAFallbackOps.FillPolygon) (pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + if (type == DO_COLOR_8x8) { + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + return; + } + + origin = pDraw->x; + + switch (XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents, + origin, &topPoint, &y, &maxy, shape)) { + case POLY_USE_MI: + miFillPolygon(pDraw, pGC, shape, mode, count, ptsIn); + case POLY_FULLY_CLIPPED: + return; + } + + xorg = (pDraw->x + pGC->patOrg.x); + yorg = (pDraw->y + pGC->patOrg.y); + + switch (type) { + case DO_MONO_8x8: + patx = pPriv->pattern0; + paty = pPriv->pattern1; + if (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) { + xorg = (-xorg) & 0x07; + yorg = (-yorg) & 0x07; + if (infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS) { + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + } + else { + XAACacheInfoPtr pCache = + (*infoRec->CacheMono8x8Pattern) (infoRec->pScrn, patx, + paty); + patx = pCache->x; + paty = pCache->y; + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + patx += pCache->offsets[slot].x; + paty += pCache->offsets[slot].y; + xorg = patx; + yorg = paty; + } + } + RectFunc = Mono8x8PatternRectHelper_ScreenOrigin; + if (infoRec->SubsequentMono8x8PatternFillTrap) + TrapFunc = Mono8x8PatternTrapHelper_ScreenOrigin; + } + else { /* !HARDWARE_PATTERN_SCREEN_ORIGIN */ + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS)) { + pCache = + (*infoRec->CacheMono8x8Pattern) (infoRec->pScrn, patx, + paty); + patx = pCache->x; + paty = pCache->y; + } + else { + pCache = &(infoRec->ScratchCacheInfoRec); + pCache->pat0 = patx; + pCache->pat1 = paty; + } + RectFunc = Mono8x8PatternRectHelper; + } + + (*infoRec->SetupForMono8x8PatternFill) (infoRec->pScrn, + patx, paty, pPriv->fg, + pPriv->bg, pGC->alu, + pGC->planemask); + break; + case DO_CACHE_BLT: + pCache = (*infoRec->CacheTile) (infoRec->pScrn, pGC->tile.pixmap); + (*infoRec->SetupForScreenToScreenCopy) (infoRec->pScrn, 1, 1, + pGC->alu, pGC->planemask, -1); + + RectFunc = CacheBltRectHelper; + break; + case DO_PIXMAP_COPY: + pCache = &(infoRec->ScratchCacheInfoRec); + pCache->x = pPriv->offscreenArea->box.x1; + pCache->y = pPriv->offscreenArea->box.y1; + pCache->w = pCache->orig_w = pPriv->offscreenArea->box.x2 - pCache->x; + pCache->h = pCache->orig_h = pPriv->offscreenArea->box.y2 - pCache->y; + + (*infoRec->SetupForScreenToScreenCopy) (infoRec->pScrn, 1, 1, + pGC->alu, pGC->planemask, -1); + + RectFunc = CacheBltRectHelper; + break; + default: + return; + } + + XAAFillPolygonHelper(infoRec->pScrn, ptsIn, count, topPoint, + y, maxy, origin, RectFunc, TrapFunc, xorg, yorg, + pCache); + + SET_SYNC_FLAG(infoRec); +} diff --git a/hw/xfree86/xaa/xaaFillRect.c b/hw/xfree86/xaa/xaaFillRect.c new file mode 100644 index 000000000..ec0fb9df7 --- /dev/null +++ b/hw/xfree86/xaa/xaaFillRect.c @@ -0,0 +1,1101 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +static void XAARenderSolidRects(GCPtr, int, BoxPtr, int, int); +static void XAARenderColor8x8Rects(GCPtr, int, BoxPtr, int, int); +static void XAARenderMono8x8Rects(GCPtr, int, BoxPtr, int, int); +static void XAARenderColorExpandRects(GCPtr, int, BoxPtr, int, int); +static void XAARenderCacheExpandRects(GCPtr, int, BoxPtr, int, int); +static void XAARenderCacheBltRects(GCPtr, int, BoxPtr, int, int); +static void XAARenderImageWriteRects(GCPtr, int, BoxPtr, int, int); +static void XAARenderPixmapCopyRects(GCPtr, int, BoxPtr, int, int); + +void +XAAPolyFillRect(DrawablePtr pDraw, GCPtr pGC, int nrectFill, /* number of rectangles to fill */ + xRectangle *prectInit /* Pointer to first rectangle to fill */ + ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int xorg = pDraw->x; + int yorg = pDraw->y; + int type = 0; + ClipAndRenderRectsFunc function; + + if ((nrectFill <= 0) || !pGC->planemask) + return; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + switch (pGC->fillStyle) { + case FillSolid: + type = DO_SOLID; + break; + case FillStippled: + type = (*infoRec->StippledFillChooser) (pGC); + break; + case FillOpaqueStippled: + if ((pGC->fgPixel == pGC->bgPixel) && infoRec->FillSolidRects && + CHECK_PLANEMASK(pGC, infoRec->FillSolidRectsFlags) && + CHECK_ROP(pGC, infoRec->FillSolidRectsFlags) && + CHECK_ROPSRC(pGC, infoRec->FillSolidRectsFlags) && + CHECK_FG(pGC, infoRec->FillSolidRectsFlags)) + type = DO_SOLID; + else + type = (*infoRec->OpaqueStippledFillChooser) (pGC); + break; + case FillTiled: + type = (*infoRec->TiledFillChooser) (pGC); + break; + } + + switch (type) { + case DO_SOLID: + function = XAARenderSolidRects; + break; + case DO_COLOR_8x8: + function = XAARenderColor8x8Rects; + break; + case DO_MONO_8x8: + function = XAARenderMono8x8Rects; + break; + case DO_CACHE_BLT: + function = XAARenderCacheBltRects; + break; + case DO_COLOR_EXPAND: + function = XAARenderColorExpandRects; + break; + case DO_CACHE_EXPAND: + function = XAARenderCacheExpandRects; + break; + case DO_IMAGE_WRITE: + function = XAARenderImageWriteRects; + break; + case DO_PIXMAP_COPY: + function = XAARenderPixmapCopyRects; + break; + default: + (*XAAFallbackOps.PolyFillRect) (pDraw, pGC, nrectFill, prectInit); + return; + } + + if (xorg | yorg) { + int n = nrectFill; + xRectangle *prect = prectInit; + + while (n--) { + prect->x += xorg; + prect->y += yorg; + prect++; + } + } + + XAAClipAndRenderRects(pGC, function, nrectFill, prectInit, xorg, yorg); +} + + /*********************\ + | Solid Rects | + \*********************/ + +static void +XAARenderSolidRects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + (*infoRec->FillSolidRects) (infoRec->pScrn, + pGC->fgPixel, pGC->alu, pGC->planemask, nboxes, + pClipBoxes); +} + + /************************\ + | Mono 8x8 Rects | + \************************/ + +static void +XAARenderMono8x8Rects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAPixmapPtr pPriv; + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + case FillTiled: + pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + fg = pPriv->fg; + bg = pPriv->bg; + break; + default: /* Muffle compiler */ + pPriv = NULL; /* Kaboom */ + fg = -1; + bg = -1; + break; + } + + (*infoRec->FillMono8x8PatternRects) (infoRec->pScrn, + fg, bg, pGC->alu, pGC->planemask, + nboxes, pClipBoxes, pPriv->pattern0, + pPriv->pattern1, + (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y)); +} + + /*************************\ + | Color 8x8 Rects | + \*************************/ + +static void +XAARenderColor8x8Rects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAACacheInfoPtr pCache; + PixmapPtr pPix; + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + pPix = pGC->stipple; + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + pPix = pGC->stipple; + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + case FillTiled: + pPix = pGC->tile.pixmap; + fg = -1; + bg = -1; + break; + default: /* Muffle compiler */ + pPix = NULL; + fg = -1; + bg = -1; + break; + } + + pCache = (*infoRec->CacheColor8x8Pattern) (infoRec->pScrn, pPix, fg, bg); + (*infoRec->FillColor8x8PatternRects) (infoRec->pScrn, + pGC->alu, pGC->planemask, nboxes, + pClipBoxes, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pCache); +} + + /****************************\ + | Color Expand Rects | + \****************************/ + +static void +XAARenderColorExpandRects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + default: /* Muffle compiler */ + fg = -1; + bg = -1; + break; + } + + (*infoRec->FillColorExpandRects) (infoRec->pScrn, fg, bg, + pGC->alu, pGC->planemask, nboxes, + pClipBoxes, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pGC->stipple); +} + + /*************************\ + | Cache Blt Rects | + \*************************/ + +static void +XAARenderCacheBltRects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAACacheInfoPtr pCache; + + switch (pGC->fillStyle) { + case FillStippled: + pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple, + pGC->fgPixel, -1); + break; + case FillOpaqueStippled: + pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple, + pGC->fgPixel, pGC->bgPixel); + break; + case FillTiled: + pCache = (*infoRec->CacheTile) (infoRec->pScrn, pGC->tile.pixmap); + break; + default: /* Muffle compiler */ + pCache = NULL; + break; + } + + (*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu, + pGC->planemask, nboxes, pClipBoxes, + (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pCache); +} + + /****************************\ + | Cache Expand Rects | + \****************************/ + +static void +XAARenderCacheExpandRects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + default: /* Muffle compiler */ + fg = -1; + bg = -1; + break; + } + + (*infoRec->FillCacheExpandRects) (infoRec->pScrn, fg, bg, + pGC->alu, pGC->planemask, nboxes, + pClipBoxes, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pGC->stipple); +} + + /***************************\ + | Image Write Rects | + \***************************/ + +static void +XAARenderImageWriteRects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + (*infoRec->FillImageWriteRects) (infoRec->pScrn, pGC->alu, + pGC->planemask, nboxes, pClipBoxes, + (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pGC->tile.pixmap); +} + + /***************************\ + | Pixmap Copy Rects | + \***************************/ + +static void +XAARenderPixmapCopyRects(GCPtr pGC, + int nboxes, BoxPtr pClipBoxes, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAACacheInfoPtr pCache = &(infoRec->ScratchCacheInfoRec); + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + + pCache->x = pPriv->offscreenArea->box.x1; + pCache->y = pPriv->offscreenArea->box.y1; + pCache->w = pCache->orig_w = pPriv->offscreenArea->box.x2 - pCache->x; + pCache->h = pCache->orig_h = pPriv->offscreenArea->box.y2 - pCache->y; + pCache->trans_color = -1; + + (*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu, + pGC->planemask, nboxes, pClipBoxes, + (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pCache); +} + + /************\ + | Solid | + \************/ + +void +XAAFillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask, int nBox, /* number of rectangles to fill */ + BoxPtr pBox /* Pointer to first rectangle to fill */ + ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SetupForSolidFill) (pScrn, fg, rop, planemask); + while (nBox--) { + (*infoRec->SubsequentSolidFillRect) (pScrn, pBox->x1, pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + pBox++; + } + SET_SYNC_FLAG(infoRec); +} + + /*********************\ + | 8x8 Mono Patterns | + \*********************/ + +void +XAAFillMono8x8PatternRectsScreenOrigin(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int pattern0, int pattern1, + int xorigin, int yorigin) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int patx = pattern0, paty = pattern1; + int xorg = (-xorigin) & 0x07; + int yorg = (-yorigin) & 0x07; + + if (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) { + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + } + else { + XAACacheInfoPtr pCache = + (*infoRec->CacheMono8x8Pattern) (pScrn, pattern0, pattern1); + patx = pCache->x; + paty = pCache->y; + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + patx += pCache->offsets[slot].x; + paty += pCache->offsets[slot].y; + xorg = patx; + yorg = paty; + } + } + + (*infoRec->SetupForMono8x8PatternFill) (pScrn, patx, paty, + fg, bg, rop, planemask); + + while (nBox--) { + (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, + xorg, yorg, pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + pBox++; + } + SET_SYNC_FLAG(infoRec); +} + +void +XAAFillMono8x8PatternRects(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int pattern0, int pattern1, int xorigin, int yorigin) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int patx = pattern0, paty = pattern1; + int xorg, yorg; + XAACacheInfoPtr pCache = NULL; + + if (!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS)) { + pCache = (*infoRec->CacheMono8x8Pattern) (pScrn, pattern0, pattern1); + patx = pCache->x; + paty = pCache->y; + } + + (*infoRec->SetupForMono8x8PatternFill) (pScrn, patx, paty, + fg, bg, rop, planemask); + + while (nBox--) { + xorg = (pBox->x1 - xorigin) & 0x07; + yorg = (pBox->y1 - yorigin) & 0x07; + + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + if (infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS) { + patx = pattern0; + paty = pattern1; + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + else { + int slot = (yorg << 3) + xorg; + + xorg = patx + pCache->offsets[slot].x; + yorg = paty + pCache->offsets[slot].y; + } + } + + (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, + xorg, yorg, pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} + + /**********************\ + | 8x8 Color Patterns | + \**********************/ + +void +XAAFillColor8x8PatternRectsScreenOrigin(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorigin, int yorigin, + XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int patx = pCache->x, paty = pCache->y; + int xorg = (-xorigin) & 0x07; + int yorg = (-yorigin) & 0x07; + + if (!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + paty += pCache->offsets[slot].y; + patx += pCache->offsets[slot].x; + xorg = patx; + yorg = paty; + } + + (*infoRec->SetupForColor8x8PatternFill) (pScrn, patx, paty, + rop, planemask, + pCache->trans_color); + + while (nBox--) { + (*infoRec->SubsequentColor8x8PatternFillRect) (pScrn, + xorg, yorg, pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + pBox++; + } + SET_SYNC_FLAG(infoRec); +} + +void +XAAFillColor8x8PatternRects(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorigin, int yorigin, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int xorg, yorg; + + (*infoRec->SetupForColor8x8PatternFill) (pScrn, pCache->x, pCache->y, + rop, planemask, + pCache->trans_color); + + while (nBox--) { + xorg = (pBox->x1 - xorigin) & 0x07; + yorg = (pBox->y1 - yorigin) & 0x07; + + if (!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + yorg = pCache->y + pCache->offsets[slot].y; + xorg = pCache->x + pCache->offsets[slot].x; + } + + (*infoRec->SubsequentColor8x8PatternFillRect) (pScrn, + xorg, yorg, pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + pBox->y2 - pBox->y1); + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} + + /***************\ + | Cache Blits | + \***************/ + +void +XAAFillCacheBltRects(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int xorg, int yorg, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h; + + (*infoRec->SetupForScreenToScreenCopy) (pScrn, 1, 1, rop, planemask, + pCache->trans_color); + + while (nBox--) { + y = pBox->y1; + phaseY = (y - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + phaseX = (pBox->x1 - xorg) % pCache->orig_w; + if (phaseX < 0) + phaseX += pCache->orig_w; + height = pBox->y2 - y; + width = pBox->x2 - pBox->x1; + +#if 0 + if (rop == GXcopy) { + while (1) { + w = width; + skipleft = phaseX; + x = pBox->x1; + blit_h = pCache->h - phaseY; + if (blit_h > height) + blit_h = height; + + while (1) { + blit_w = pCache->w - skipleft; + if (blit_w > w) + blit_w = w; + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pCache->x + + skipleft, + pCache->y + + phaseY, x, y, + blit_w, blit_h); + w -= blit_w; + if (!w) + break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + if (blit_w >= pCache->orig_w) + break; + } + + /* Expand horizontally */ + if (w) { + skipleft -= phaseX; + if (skipleft < 0) + skipleft += pCache->orig_w; + blit_w = x - pBox->x1 - skipleft; + while (w) { + if (blit_w > w) + blit_w = w; + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pBox->x1 + + skipleft, y, + x, y, blit_w, + blit_h); + w -= blit_w; + x += blit_w; + blit_w <<= 1; + } + } + + height -= blit_h; + if (!height) + break; + y += blit_h; + phaseY = (phaseY + blit_h) % pCache->orig_h; + if (blit_h >= pCache->orig_h) + break; + } + + /* Expand vertically */ + if (height) { + blit_w = pBox->x2 - pBox->x1; + phaseY -= (pBox->y1 - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + blit_h = y - pBox->y1 - phaseY; + while (height) { + if (blit_h > height) + blit_h = height; + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pBox->x1, + pBox->y1 + phaseY, + pBox->x1, y, + blit_w, blit_h); + height -= blit_h; + y += blit_h; + blit_h <<= 1; + } + } + } + else +#endif + { + while (1) { + w = width; + skipleft = phaseX; + x = pBox->x1; + blit_h = pCache->h - phaseY; + if (blit_h > height) + blit_h = height; + + while (1) { + blit_w = pCache->w - skipleft; + if (blit_w > w) + blit_w = w; + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pCache->x + + skipleft, + pCache->y + + phaseY, x, y, + blit_w, blit_h); + w -= blit_w; + if (!w) + break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + } + height -= blit_h; + if (!height) + break; + y += blit_h; + phaseY = (phaseY + blit_h) % pCache->orig_h; + } + } + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} + + /*******************\ + | Cache Expansion | + \*******************/ + +void +XAAFillCacheExpandRects(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h; + int cacheWidth; + XAACacheInfoPtr pCache; + + pCache = (*infoRec->CacheMonoStipple) (pScrn, pPix); + + cacheWidth = (pCache->w * pScrn->bitsPerPixel) / + infoRec->CacheColorExpandDensity; + + (*infoRec->SetupForScreenToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + while (nBox--) { + y = pBox->y1; + phaseY = (y - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + phaseX = (pBox->x1 - xorg) % pCache->orig_w; + if (phaseX < 0) + phaseX += pCache->orig_w; + height = pBox->y2 - y; + width = pBox->x2 - pBox->x1; + + while (1) { + w = width; + skipleft = phaseX; + x = pBox->x1; + blit_h = pCache->h - phaseY; + if (blit_h > height) + blit_h = height; + + while (1) { + blit_w = cacheWidth - skipleft; + if (blit_w > w) + blit_w = w; + (*infoRec->SubsequentScreenToScreenColorExpandFill) (pScrn, x, + y, blit_w, + blit_h, + pCache->x, + pCache->y + + phaseY, + skipleft); + w -= blit_w; + if (!w) + break; + x += blit_w; + skipleft = (skipleft + blit_w) % pCache->orig_w; + } + height -= blit_h; + if (!height) + break; + y += blit_h; + phaseY = (phaseY + blit_h) % pCache->orig_h; + } + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} + + /******************\ + | Image Writes | + \******************/ + +/* This requires all LEFT_EDGE clipping. You get too many problems + with reading past the edge of the pattern otherwise */ + +static void +WriteColumn(ScrnInfoPtr pScrn, + unsigned char *pSrc, + int x, int y, int w, int h, + int xoff, int yoff, int pHeight, int srcwidth, int Bpp) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + unsigned char *src; + Bool PlusOne = FALSE; + int skipleft, dwords; + + pSrc += (Bpp * xoff); + + if ((skipleft = (long) pSrc & 0x03L)) { + if (Bpp == 3) + skipleft = 4 - skipleft; + else + skipleft /= Bpp; + + x -= skipleft; + w += skipleft; + + if (Bpp == 3) + pSrc -= 3 * skipleft; + else /* is this Alpha friendly ? */ + pSrc = (unsigned char *) ((long) pSrc & ~0x03L); + } + + src = pSrc + (yoff * srcwidth); + + dwords = bytes_to_int32(w * Bpp); + + if ((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && + ((dwords * h) & 0x01)) { + PlusOne = TRUE; + } + + (*infoRec->SubsequentImageWriteRect) (pScrn, x, y, w, h, skipleft); + + if (dwords > infoRec->ImageWriteRange) { + while (h--) { + XAAMoveDWORDS_FixedBase((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords); + src += srcwidth; + yoff++; + if (yoff >= pHeight) { + yoff = 0; + src = pSrc; + } + } + } + else { + if (srcwidth == (dwords << 2)) { + int maxLines = infoRec->ImageWriteRange / dwords; + int step; + + while (h) { + step = pHeight - yoff; + if (step > maxLines) + step = maxLines; + if (step > h) + step = h; + + XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords * step); + + src += (srcwidth * step); + yoff += step; + if (yoff >= pHeight) { + yoff = 0; + src = pSrc; + } + h -= step; + } + } + else { + while (h--) { + XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords); + src += srcwidth; + yoff++; + if (yoff >= pHeight) { + yoff = 0; + src = pSrc; + } + } + } + } + + if (PlusOne) { + CARD32 *base = (CARD32 *) infoRec->ImageWriteBase; + + *base = 0x00000000; + } +} + +void +XAAFillImageWriteRects(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, phaseY, phaseX, height, width, blit_w; + int pHeight = pPix->drawable.height; + int pWidth = pPix->drawable.width; + int Bpp = pPix->drawable.bitsPerPixel >> 3; + int srcwidth = pPix->devKind; + + (*infoRec->SetupForImageWrite) (pScrn, rop, planemask, -1, + pPix->drawable.bitsPerPixel, + pPix->drawable.depth); + + while (nBox--) { + x = pBox->x1; + phaseY = (pBox->y1 - yorg) % pHeight; + if (phaseY < 0) + phaseY += pHeight; + phaseX = (x - xorg) % pWidth; + if (phaseX < 0) + phaseX += pWidth; + height = pBox->y2 - pBox->y1; + width = pBox->x2 - x; + + while (1) { + blit_w = pWidth - phaseX; + if (blit_w > width) + blit_w = width; + + WriteColumn(pScrn, pPix->devPrivate.ptr, x, pBox->y1, + blit_w, height, phaseX, phaseY, pHeight, srcwidth, Bpp); + + width -= blit_w; + if (!width) + break; + x += blit_w; + phaseX = (phaseX + blit_w) % pWidth; + } + pBox++; + } + + if (infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + + /*************\ + | Utilities | + \*************/ + +void +XAAClipAndRenderRects(GCPtr pGC, + ClipAndRenderRectsFunc BoxFunc, + int nrectFill, xRectangle *prect, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int Right, Bottom, MaxBoxes; + BoxPtr pextent, pboxClipped, pboxClippedBase; + + MaxBoxes = infoRec->PreAllocSize / sizeof(BoxRec); + pboxClippedBase = (BoxPtr) infoRec->PreAllocMem; + pboxClipped = pboxClippedBase; + + if (RegionNumRects(pGC->pCompositeClip) == 1) { + pextent = RegionRects(pGC->pCompositeClip); + while (nrectFill--) { + pboxClipped->x1 = max(pextent->x1, prect->x); + pboxClipped->y1 = max(pextent->y1, prect->y); + + Right = (int) prect->x + (int) prect->width; + pboxClipped->x2 = min(pextent->x2, Right); + + Bottom = (int) prect->y + (int) prect->height; + pboxClipped->y2 = min(pextent->y2, Bottom); + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) { + pboxClipped++; + if (pboxClipped >= (pboxClippedBase + MaxBoxes)) { + (*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg); + pboxClipped = pboxClippedBase; + } + } + } + } + else { + pextent = RegionExtents(pGC->pCompositeClip); + while (nrectFill--) { + int n; + BoxRec box, *pbox; + + box.x1 = max(pextent->x1, prect->x); + box.y1 = max(pextent->y1, prect->y); + + Right = (int) prect->x + (int) prect->width; + box.x2 = min(pextent->x2, Right); + + Bottom = (int) prect->y + (int) prect->height; + box.y2 = min(pextent->y2, Bottom); + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = RegionNumRects(pGC->pCompositeClip); + pbox = RegionRects(pGC->pCompositeClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while (n--) { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if (pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) { + pboxClipped++; + if (pboxClipped >= (pboxClippedBase + MaxBoxes)) { + (*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg); + pboxClipped = pboxClippedBase; + } + } + } + } + } + + if (pboxClipped != pboxClippedBase) + (*BoxFunc) (pGC, pboxClipped - pboxClippedBase, pboxClippedBase, + xorg, yorg); +} + +int +XAAGetRectClipBoxes(GCPtr pGC, + BoxPtr pboxClippedBase, + int nrectFill, xRectangle *prectInit) +{ + int Right, Bottom; + BoxPtr pextent, pboxClipped = pboxClippedBase; + xRectangle *prect = prectInit; + RegionPtr prgnClip = pGC->pCompositeClip; + + if (RegionNumRects(prgnClip) == 1) { + pextent = RegionRects(prgnClip); + while (nrectFill--) { + pboxClipped->x1 = max(pextent->x1, prect->x); + pboxClipped->y1 = max(pextent->y1, prect->y); + + Right = (int) prect->x + (int) prect->width; + pboxClipped->x2 = min(pextent->x2, Right); + + Bottom = (int) prect->y + (int) prect->height; + pboxClipped->y2 = min(pextent->y2, Bottom); + + prect++; + if ((pboxClipped->x1 < pboxClipped->x2) && + (pboxClipped->y1 < pboxClipped->y2)) { + pboxClipped++; + } + } + } + else { + pextent = RegionExtents(prgnClip); + while (nrectFill--) { + int n; + BoxRec box, *pbox; + + box.x1 = max(pextent->x1, prect->x); + box.y1 = max(pextent->y1, prect->y); + + Right = (int) prect->x + (int) prect->width; + box.x2 = min(pextent->x2, Right); + + Bottom = (int) prect->y + (int) prect->height; + box.y2 = min(pextent->y2, Bottom); + + prect++; + + if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) + continue; + + n = RegionNumRects(prgnClip); + pbox = RegionRects(prgnClip); + + /* clip the rectangle to each box in the clip region + this is logically equivalent to calling Intersect() + */ + while (n--) { + pboxClipped->x1 = max(box.x1, pbox->x1); + pboxClipped->y1 = max(box.y1, pbox->y1); + pboxClipped->x2 = min(box.x2, pbox->x2); + pboxClipped->y2 = min(box.y2, pbox->y2); + pbox++; + + /* see if clipping left anything */ + if (pboxClipped->x1 < pboxClipped->x2 && + pboxClipped->y1 < pboxClipped->y2) { + pboxClipped++; + } + } + } + } + + return pboxClipped - pboxClippedBase; +} diff --git a/hw/xfree86/xaa/xaaGC.c b/hw/xfree86/xaa/xaaGC.c new file mode 100644 index 000000000..d2f3fc9cd --- /dev/null +++ b/hw/xfree86/xaa/xaaGC.c @@ -0,0 +1,564 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "migc.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "xaawrap.h" + +static void XAAValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); +static void XAAChangeGC(GCPtr pGC, unsigned long mask); +static void XAACopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void XAADestroyGC(GCPtr pGC); +static void XAAChangeClip(GCPtr pGC, int type, void * pvalue, int nrects); +static void XAADestroyClip(GCPtr pGC); +static void XAACopyClip(GCPtr pgcDst, GCPtr pgcSrc); + +GCFuncs XAAGCFuncs = { + XAAValidateGC, XAAChangeGC, XAACopyGC, XAADestroyGC, + XAAChangeClip, XAADestroyClip, XAACopyClip +}; + +extern GCOps XAAPixmapOps; + +Bool +XAACreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + XAAGCPtr pGCPriv = (XAAGCPtr) dixLookupPrivate(&pGC->devPrivates, + XAAGetGCKey()); + Bool ret; + + XAA_SCREEN_PROLOGUE(pScreen, CreateGC); + + if ((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->wrapOps = NULL; + pGCPriv->wrapFuncs = pGC->funcs; + pGCPriv->XAAOps = &XAAFallbackOps; + pGC->funcs = &XAAGCFuncs; + } + + XAA_SCREEN_EPILOGUE(pScreen, CreateGC, XAACreateGC); + + return ret; +} + +static void +XAAValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + XAA_GC_FUNC_PROLOGUE(pGC); + + (*pGC->funcs->ValidateGC) (pGC, changes, pDraw); + + if ((changes & GCPlaneMask) && + ((pGC->planemask & infoRec->FullPlanemasks[pGC->depth - 1]) == + infoRec->FullPlanemasks[pGC->depth - 1])) { + pGC->planemask = ~0; + } + + if (pGC->depth != 32) { + /* 0xffffffff is reserved for transparency */ + if (pGC->bgPixel == 0xffffffff) + pGC->bgPixel = 0x7fffffff; + if (pGC->fgPixel == 0xffffffff) + pGC->fgPixel = 0x7fffffff; + } + + if ((pDraw->type == DRAWABLE_PIXMAP) && !IS_OFFSCREEN_PIXMAP(pDraw)) { + pGCPriv->flags = OPS_ARE_PIXMAP; + pGCPriv->changes |= changes; + + /* make sure we're not using videomemory pixmaps to render + onto system memory drawables */ + + if ((pGC->fillStyle == FillTiled) && + IS_OFFSCREEN_PIXMAP(pGC->tile.pixmap) && + !OFFSCREEN_PIXMAP_LOCKED(pGC->tile.pixmap)) { + + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + FBAreaPtr area = pPriv->offscreenArea; + + XAARemoveAreaCallback(area); /* clobbers pPriv->offscreenArea */ + xf86FreeOffscreenArea(area); + } + } + else if (!infoRec->pScrn->vtSema && (pDraw->type == DRAWABLE_WINDOW)) { + pGCPriv->flags = 0; + pGCPriv->changes |= changes; + } + else { + if (!(pGCPriv->flags & OPS_ARE_ACCEL)) { + changes |= pGCPriv->changes; + pGCPriv->changes = 0; + } + pGCPriv->flags = OPS_ARE_ACCEL; + +#if 1 + /* Ugh. If we can't use the blitter on offscreen pixmaps used + as tiles, then we need to move them out as cfb can't handle + tiles with non-zero origins */ + + if ((pGC->fillStyle == FillTiled) && + IS_OFFSCREEN_PIXMAP(pGC->tile.pixmap) && + (DO_PIXMAP_COPY != (*infoRec->TiledFillChooser) (pGC))) { + + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + FBAreaPtr area = pPriv->offscreenArea; + + XAARemoveAreaCallback(area); /* clobbers pPriv->offscreenArea */ + xf86FreeOffscreenArea(area); + } +#endif + } + + XAA_GC_FUNC_EPILOGUE(pGC); + + if (!(pGCPriv->flags & OPS_ARE_ACCEL)) + return; + + if ((changes & GCTile) && !pGC->tileIsPixel && pGC->tile.pixmap) { + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + + if (pixPriv->flags & DIRTY) { + pixPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); + pGC->tile.pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + } + if ((changes & GCStipple) && pGC->stipple) { + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + + if (pixPriv->flags & DIRTY) { + pixPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); + pGC->stipple->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + } + + /* If our Ops are still the default ones we need to allocate new ones */ + if (pGC->ops == &XAAFallbackOps) { + if (!(pGCPriv->XAAOps = malloc(sizeof(GCOps)))) { + pGCPriv->XAAOps = &XAAFallbackOps; + return; + } + /* make a modifiable copy of the default ops */ + memcpy(pGCPriv->XAAOps, &XAAFallbackOps, sizeof(GCOps)); + pGC->ops = pGCPriv->XAAOps; + changes = ~0; + } + + if (!changes) + return; + + if ((changes & GCDashList) && infoRec->ComputeDash) + infoRec->ComputeDash(pGC); + + if (changes & infoRec->FillSpansMask) + (*infoRec->ValidateFillSpans) (pGC, changes, pDraw); + + if (changes & infoRec->SetSpansMask) + (*infoRec->ValidateSetSpans) (pGC, changes, pDraw); + + if (changes & infoRec->PutImageMask) + (*infoRec->ValidatePutImage) (pGC, changes, pDraw); + + if (changes & infoRec->CopyAreaMask) + (*infoRec->ValidateCopyArea) (pGC, changes, pDraw); + + if (changes & infoRec->CopyPlaneMask) + (*infoRec->ValidateCopyPlane) (pGC, changes, pDraw); + + if (changes & infoRec->PolyPointMask) + (*infoRec->ValidatePolyPoint) (pGC, changes, pDraw); + + if (changes & infoRec->PolylinesMask) + (*infoRec->ValidatePolylines) (pGC, changes, pDraw); + + if (changes & infoRec->PolySegmentMask) + (*infoRec->ValidatePolySegment) (pGC, changes, pDraw); + + if (changes & infoRec->PolyRectangleMask) + (*infoRec->ValidatePolyRectangle) (pGC, changes, pDraw); + + if (changes & infoRec->PolyArcMask) + (*infoRec->ValidatePolyArc) (pGC, changes, pDraw); + + if (changes & infoRec->FillPolygonMask) + (*infoRec->ValidateFillPolygon) (pGC, changes, pDraw); + + if (changes & infoRec->PolyFillRectMask) + (*infoRec->ValidatePolyFillRect) (pGC, changes, pDraw); + + if (changes & infoRec->PolyFillArcMask) + (*infoRec->ValidatePolyFillArc) (pGC, changes, pDraw); + + if (changes & infoRec->PolyGlyphBltMask) + (*infoRec->ValidatePolyGlyphBlt) (pGC, changes, pDraw); + + if (changes & infoRec->ImageGlyphBltMask) + (*infoRec->ValidateImageGlyphBlt) (pGC, changes, pDraw); + + if (changes & infoRec->PolyText8Mask) + (*infoRec->ValidatePolyText8) (pGC, changes, pDraw); + + if (changes & infoRec->PolyText16Mask) + (*infoRec->ValidatePolyText16) (pGC, changes, pDraw); + + if (changes & infoRec->ImageText8Mask) + (*infoRec->ValidateImageText8) (pGC, changes, pDraw); + + if (changes & infoRec->ImageText16Mask) + (*infoRec->ValidateImageText16) (pGC, changes, pDraw); + + if (changes & infoRec->PushPixelsMask) + (*infoRec->ValidatePushPixels) (pGC, changes, pDraw); +} + +static void +XAADestroyGC(GCPtr pGC) +{ + XAA_GC_FUNC_PROLOGUE(pGC); + + if (pGCPriv->XAAOps != &XAAFallbackOps) + free(pGCPriv->XAAOps); + + free(pGCPriv->DashPattern); + pGCPriv->flags = 0; + + (*pGC->funcs->DestroyGC) (pGC); + XAA_GC_FUNC_EPILOGUE(pGC); +} + +static void +XAAChangeGC(GCPtr pGC, unsigned long mask) +{ + XAA_GC_FUNC_PROLOGUE(pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + XAA_GC_FUNC_EPILOGUE(pGC); + + /* we have to assume that shared memory pixmaps are dirty + because we can't wrap all operations on them */ + + if ((mask & GCTile) && !pGC->tileIsPixel && + PIXMAP_IS_SHARED(pGC->tile.pixmap)) { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + + pPixPriv->flags |= DIRTY; + } + + if ((mask & GCStipple) && PIXMAP_IS_SHARED(pGC->stipple)) { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + + pPixPriv->flags |= DIRTY; + } +} + +static void +XAACopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + XAA_GC_FUNC_PROLOGUE(pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + XAA_GC_FUNC_EPILOGUE(pGCDst); +} + +static void +XAAChangeClip(GCPtr pGC, int type, void * pvalue, int nrects) +{ + XAA_GC_FUNC_PROLOGUE(pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + XAA_GC_FUNC_EPILOGUE(pGC); +} + +static void +XAACopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + XAA_GC_FUNC_PROLOGUE(pgcDst); + (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc); + XAA_GC_FUNC_EPILOGUE(pgcDst); +} + +static void +XAADestroyClip(GCPtr pGC) +{ + XAA_GC_FUNC_PROLOGUE(pGC); + (*pGC->funcs->DestroyClip) (pGC); + XAA_GC_FUNC_EPILOGUE(pGC); +} + +/**** Pixmap Wrappers ****/ + +static void +XAAFillSpansPixmap(DrawablePtr pDraw, + GC * pGC, + int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->FillSpans) (pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAASetSpansPixmap(DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + register DDXPointPtr ppt, + int *pwidth, int nspans, int fSorted) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->SetSpans) (pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPutImagePixmap(DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, int format, char *pImage) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PutImage) (pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static RegionPtr +XAACopyAreaPixmap(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + RegionPtr ret; + + if (infoRec->pScrn->vtSema && + ((pSrc->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pSrc))) { + if (infoRec->ReadPixmap && (pGC->alu == GXcopy) && + (pSrc->bitsPerPixel == pDst->bitsPerPixel) && + ((pGC->planemask & infoRec->FullPlanemasks[pSrc->depth - 1]) + == infoRec->FullPlanemasks[pSrc->depth - 1])) { + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE((PixmapPtr) (pDst)); + + pixPriv->flags |= DIRTY; + + return (XAABitBlt(pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + XAADoImageRead/*, 0L*/)); + } + else if (infoRec->NeedToSync) { + (*infoRec->Sync) (infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + } + + { + XAA_PIXMAP_OP_PROLOGUE(pGC, pDst); + ret = (*pGC->ops->CopyArea) (pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, + dsty); + XAA_PIXMAP_OP_EPILOGUE(pGC); + } + return ret; +} + +static RegionPtr +XAACopyPlanePixmap(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + RegionPtr ret; + + XAA_PIXMAP_OP_PROLOGUE(pGC, pDst); + + if (infoRec->pScrn->vtSema && + ((pSrc->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pSrc))) { + if (infoRec->NeedToSync) { + (*infoRec->Sync) (infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + } + + ret = (*pGC->ops->CopyPlane) (pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, + bitPlane); + XAA_PIXMAP_OP_EPILOGUE(pGC); + return ret; +} + +static void +XAAPolyPointPixmap(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, xPoint * pptInit) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyPoint) (pDraw, pGC, mode, npt, pptInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolylinesPixmap(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->Polylines) (pDraw, pGC, mode, npt, pptInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolySegmentPixmap(DrawablePtr pDraw, GCPtr pGC, int nseg, xSegment * pSeg) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolySegment) (pDraw, pGC, nseg, pSeg); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyRectanglePixmap(DrawablePtr pDraw, + GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyRectangle) (pDraw, pGC, nRectsInit, pRectsInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyArcPixmap(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyArc) (pDraw, pGC, narcs, parcs); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAFillPolygonPixmap(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->FillPolygon) (pDraw, pGC, shape, mode, count, ptsIn); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyFillRectPixmap(DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyFillRect) (pDraw, pGC, nrectFill, prectInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyFillArcPixmap(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, parcs); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static int +XAAPolyText8Pixmap(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + int ret; + + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + ret = (*pGC->ops->PolyText8) (pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); + return ret; +} + +static int +XAAPolyText16Pixmap(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + int ret; + + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + ret = (*pGC->ops->PolyText16) (pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); + return ret; +} + +static void +XAAImageText8Pixmap(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageText8) (pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAImageText16Pixmap(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageText16) (pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAImageGlyphBltPixmap(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageGlyphBlt) (pDraw, pGC, xInit, yInit, nglyph, + ppci, pglyphBase); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyGlyphBltPixmap(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyGlyphBlt) (pDraw, pGC, xInit, yInit, nglyph, + ppci, pglyphBase); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPushPixelsPixmap(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, int dx, int dy, int xOrg, int yOrg) +{ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PushPixels) (pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +GCOps XAAPixmapOps = { + XAAFillSpansPixmap, XAASetSpansPixmap, + XAAPutImagePixmap, XAACopyAreaPixmap, + XAACopyPlanePixmap, XAAPolyPointPixmap, + XAAPolylinesPixmap, XAAPolySegmentPixmap, + XAAPolyRectanglePixmap, XAAPolyArcPixmap, + XAAFillPolygonPixmap, XAAPolyFillRectPixmap, + XAAPolyFillArcPixmap, XAAPolyText8Pixmap, + XAAPolyText16Pixmap, XAAImageText8Pixmap, + XAAImageText16Pixmap, XAAImageGlyphBltPixmap, + XAAPolyGlyphBltPixmap, XAAPushPixelsPixmap, +}; diff --git a/hw/xfree86/xaa/xaaGCmisc.c b/hw/xfree86/xaa/xaaGCmisc.c new file mode 100644 index 000000000..ca69aae74 --- /dev/null +++ b/hw/xfree86/xaa/xaaGCmisc.c @@ -0,0 +1,412 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include +#include "dixfontstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "migc.h" +#include "mi.h" +#include "gcstruct.h" +#include "pixmapstr.h" + +void +XAAValidateCopyArea(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (infoRec->CopyArea && + CHECK_PLANEMASK(pGC, infoRec->CopyAreaFlags) && + CHECK_ROP(pGC, infoRec->CopyAreaFlags) && + CHECK_ROPSRC(pGC, infoRec->CopyAreaFlags) + ) + pGC->ops->CopyArea = infoRec->CopyArea; + else + pGC->ops->CopyArea = XAAFallbackOps.CopyArea; +} + +void +XAAValidatePutImage(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (infoRec->PutImage && + CHECK_PLANEMASK(pGC, infoRec->PutImageFlags) && + CHECK_ROP(pGC, infoRec->PutImageFlags) && + CHECK_ROPSRC(pGC, infoRec->PutImageFlags) && + CHECK_COLORS(pGC, infoRec->PutImageFlags) + ) + pGC->ops->PutImage = infoRec->PutImage; + else + pGC->ops->PutImage = XAAFallbackOps.PutImage; +} + +void +XAAValidateCopyPlane(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (infoRec->CopyPlane && + CHECK_PLANEMASK(pGC, infoRec->CopyPlaneFlags) && + CHECK_ROP(pGC, infoRec->CopyPlaneFlags) && + CHECK_ROPSRC(pGC, infoRec->CopyPlaneFlags) && + CHECK_COLORS(pGC, infoRec->CopyPlaneFlags) + ) + pGC->ops->CopyPlane = infoRec->CopyPlane; + else + pGC->ops->CopyPlane = XAAFallbackOps.CopyPlane; +} + +void +XAAValidatePushPixels(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (infoRec->PushPixelsSolid && + (pGC->fillStyle == FillSolid) && + CHECK_PLANEMASK(pGC, infoRec->PushPixelsFlags) && + CHECK_ROP(pGC, infoRec->PushPixelsFlags) && + CHECK_ROPSRC(pGC, infoRec->PushPixelsFlags) && + CHECK_FG(pGC, infoRec->PushPixelsFlags) && + (!(infoRec->PushPixelsFlags & TRANSPARENCY_GXCOPY_ONLY) || + (pGC->alu == GXcopy)) + ) + pGC->ops->PushPixels = infoRec->PushPixelsSolid; + else + pGC->ops->PushPixels = XAAFallbackOps.PushPixels; + +} + +/* We make the assumption that the FillSpans, PolyFillRect, FillPolygon + and PolyFillArc functions are linked in a way that they all have + the same rop/color/planemask restrictions. If the driver provides + a GC level replacement for these, it will need to supply a new + Validate functions if it breaks this assumption */ + +void +XAAValidateFillSpans(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (pGC->fillStyle != FillTiled) + changes &= ~GCTile; + if ((pGC->fillStyle == FillTiled) || (pGC->fillStyle == FillSolid)) + changes &= ~GCStipple; + if (!changes) + return; + + pGC->ops->FillSpans = XAAFallbackOps.FillSpans; + pGC->ops->PolyFillRect = XAAFallbackOps.PolyFillRect; + pGC->ops->FillPolygon = XAAFallbackOps.FillPolygon; + pGC->ops->PolyFillArc = XAAFallbackOps.PolyFillArc; + + switch (pGC->fillStyle) { + case FillSolid: + if (infoRec->FillSpansSolid && + CHECK_PLANEMASK(pGC, infoRec->FillSpansSolidFlags) && + CHECK_ROP(pGC, infoRec->FillSpansSolidFlags) && + CHECK_ROPSRC(pGC, infoRec->FillSpansSolidFlags) && + CHECK_FG(pGC, infoRec->FillSpansSolidFlags) + ) { + pGC->ops->FillSpans = infoRec->FillSpansSolid; + pGC->ops->PolyFillRect = infoRec->PolyFillRectSolid; + pGC->ops->FillPolygon = infoRec->FillPolygonSolid; + pGC->ops->PolyFillArc = infoRec->PolyFillArcSolid; + } + break; + /* The [Stippled/OpaqueStippled/Tiled]FillChooser + functions do the validating */ + case FillStippled: + if (infoRec->FillSpansStippled) { + pGC->ops->FillSpans = infoRec->FillSpansStippled; + pGC->ops->PolyFillRect = infoRec->PolyFillRectStippled; + if (infoRec->FillPolygonStippled) + pGC->ops->FillPolygon = infoRec->FillPolygonStippled; + else + pGC->ops->FillPolygon = miFillPolygon; + pGC->ops->PolyFillArc = miPolyFillArc; + } + break; + case FillOpaqueStippled: + if (infoRec->FillSpansOpaqueStippled) { + pGC->ops->FillSpans = infoRec->FillSpansOpaqueStippled; + pGC->ops->PolyFillRect = infoRec->PolyFillRectOpaqueStippled; + if (infoRec->FillPolygonOpaqueStippled) + pGC->ops->FillPolygon = infoRec->FillPolygonOpaqueStippled; + else + pGC->ops->FillPolygon = miFillPolygon; + pGC->ops->PolyFillArc = miPolyFillArc; + } + break; + case FillTiled: + if (infoRec->FillSpansTiled) { + pGC->ops->FillSpans = infoRec->FillSpansTiled; + pGC->ops->PolyFillRect = infoRec->PolyFillRectTiled; + if (infoRec->FillPolygonTiled) + pGC->ops->FillPolygon = infoRec->FillPolygonTiled; + else + pGC->ops->FillPolygon = miFillPolygon; + pGC->ops->PolyFillArc = miPolyFillArc; + } + break; + default: + return; + } +} + +/* We make the assumption that these Text8/16 and GlyphBlt functions + are linked in a way that they all have the same rop/color/planemask + restrictions. If the driver provides a GC level replacement for + these, it will need to supply a new Validate functions if it breaks + this assumption */ + +void +XAAValidatePolyGlyphBlt(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + Bool BigFont = FALSE; + + pGC->ops->PolyText8 = XAAFallbackOps.PolyText8; + pGC->ops->PolyText16 = XAAFallbackOps.PolyText16; + pGC->ops->PolyGlyphBlt = XAAFallbackOps.PolyGlyphBlt; + + if (!pGC->font) + return; + if (pGC->fillStyle != FillSolid) + return; + + if ((FONTMAXBOUNDS(pGC->font, rightSideBearing) - + FONTMINBOUNDS(pGC->font, leftSideBearing) > 32)) + BigFont = TRUE; + + /* no funny business */ + if ((FONTMINBOUNDS(pGC->font, characterWidth) <= 0) || + ((FONTASCENT(pGC->font) + FONTDESCENT(pGC->font)) <= 0)) + return; + + /* Check for TE Fonts */ + if (!TERMINALFONT(pGC->font) || BigFont) { + if (infoRec->PolyGlyphBltNonTE && + CHECK_PLANEMASK(pGC, infoRec->PolyGlyphBltNonTEFlags) && + CHECK_ROP(pGC, infoRec->PolyGlyphBltNonTEFlags) && + CHECK_ROPSRC(pGC, infoRec->PolyGlyphBltNonTEFlags) && + CHECK_FG(pGC, infoRec->PolyGlyphBltNonTEFlags) && + (!(infoRec->PolyGlyphBltNonTEFlags & TRANSPARENCY_GXCOPY_ONLY) || + (pGC->alu == GXcopy)) + ) { + pGC->ops->PolyText8 = infoRec->PolyText8NonTE; + pGC->ops->PolyText16 = infoRec->PolyText16NonTE; + pGC->ops->PolyGlyphBlt = infoRec->PolyGlyphBltNonTE; + } + } + else { + if (infoRec->PolyGlyphBltTE && + CHECK_PLANEMASK(pGC, infoRec->PolyGlyphBltTEFlags) && + CHECK_ROP(pGC, infoRec->PolyGlyphBltTEFlags) && + CHECK_ROPSRC(pGC, infoRec->PolyGlyphBltNonTEFlags) && + CHECK_FG(pGC, infoRec->PolyGlyphBltTEFlags) && + (!(infoRec->PolyGlyphBltTEFlags & TRANSPARENCY_GXCOPY_ONLY) || + (pGC->alu == GXcopy)) + ) { + pGC->ops->PolyText8 = infoRec->PolyText8TE; + pGC->ops->PolyText16 = infoRec->PolyText16TE; + pGC->ops->PolyGlyphBlt = infoRec->PolyGlyphBltTE; + } + } +} + +void +XAAValidateImageGlyphBlt(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + Bool BigFont = FALSE; + + pGC->ops->ImageText8 = XAAFallbackOps.ImageText8; + pGC->ops->ImageText16 = XAAFallbackOps.ImageText16; + pGC->ops->ImageGlyphBlt = XAAFallbackOps.ImageGlyphBlt; + + if (!pGC->font) + return; + + if ((FONTMAXBOUNDS(pGC->font, rightSideBearing) - + FONTMINBOUNDS(pGC->font, leftSideBearing) > 32)) + BigFont = TRUE; + + /* no funny business */ + if ((FONTMINBOUNDS(pGC->font, characterWidth) <= 0) || + ((FONTASCENT(pGC->font) + FONTDESCENT(pGC->font)) <= 0)) + return; + + /* Check for TE Fonts */ + if (!TERMINALFONT(pGC->font) || BigFont || (pGC->depth == 32)) { + if (infoRec->ImageGlyphBltNonTE && + CHECK_PLANEMASK(pGC, infoRec->ImageGlyphBltNonTEFlags) && + CHECK_FG(pGC, infoRec->ImageGlyphBltNonTEFlags) && + infoRec->SetupForSolidFill && + CHECK_PLANEMASK(pGC, infoRec->SolidFillFlags) && + CHECK_BG(pGC, infoRec->SolidFillFlags)) { + pGC->ops->ImageText8 = infoRec->ImageText8NonTE; + pGC->ops->ImageText16 = infoRec->ImageText16NonTE; + pGC->ops->ImageGlyphBlt = infoRec->ImageGlyphBltNonTE; + } + } + else if (infoRec->ImageGlyphBltTE && + CHECK_PLANEMASK(pGC, infoRec->ImageGlyphBltTEFlags)) { + if (!(infoRec->ImageGlyphBltTEFlags & TRANSPARENCY_ONLY) && + CHECK_COLORS(pGC, infoRec->ImageGlyphBltTEFlags)) { + pGC->ops->ImageText8 = infoRec->ImageText8TE; + pGC->ops->ImageText16 = infoRec->ImageText16TE; + pGC->ops->ImageGlyphBlt = infoRec->ImageGlyphBltTE; + } + else { + if (CHECK_FG(pGC, infoRec->ImageGlyphBltTEFlags) && + infoRec->SetupForSolidFill && + CHECK_PLANEMASK(pGC, infoRec->SolidFillFlags) && + CHECK_BG(pGC, infoRec->SolidFillFlags)) { + pGC->ops->ImageText8 = infoRec->ImageText8TE; + pGC->ops->ImageText16 = infoRec->ImageText16TE; + pGC->ops->ImageGlyphBlt = infoRec->ImageGlyphBltTE; + } + } + } +} + +void +XAAValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAGCPtr pGCPriv = (XAAGCPtr) dixLookupPrivate(&pGC->devPrivates, + XAAGetGCKey()); + + if (pGC->lineStyle == LineSolid) + changes &= ~GCDashList; + if (!changes) + return; + + pGC->ops->PolySegment = XAAFallbackOps.PolySegment; + pGC->ops->Polylines = XAAFallbackOps.Polylines; + pGC->ops->PolyRectangle = XAAFallbackOps.PolyRectangle; + pGC->ops->PolyArc = XAAFallbackOps.PolyArc; + + if ((pGC->ops->FillSpans != XAAFallbackOps.FillSpans) && + (pGC->lineWidth > 0)) { + + pGC->ops->PolyArc = miPolyArc; + pGC->ops->PolySegment = miPolySegment; + pGC->ops->PolyRectangle = miPolyRectangle; + if (pGC->lineStyle == LineSolid) + pGC->ops->Polylines = miWideLine; + else + pGC->ops->Polylines = miWideDash; + } + + if ((pGC->lineWidth == 0) && (pGC->fillStyle == FillSolid)) { + + if (pGC->lineStyle == LineSolid) { + + if (infoRec->PolyRectangleThinSolid && + CHECK_PLANEMASK(pGC, infoRec->PolyRectangleThinSolidFlags) && + CHECK_ROP(pGC, infoRec->PolyRectangleThinSolidFlags) && + CHECK_ROPSRC(pGC, infoRec->PolyRectangleThinSolidFlags) && + CHECK_FG(pGC, infoRec->PolyRectangleThinSolidFlags)) { + + pGC->ops->PolyRectangle = infoRec->PolyRectangleThinSolid; + } + + if (infoRec->PolySegmentThinSolid && + CHECK_PLANEMASK(pGC, infoRec->PolySegmentThinSolidFlags) && + CHECK_ROP(pGC, infoRec->PolySegmentThinSolidFlags) && + CHECK_ROPSRC(pGC, infoRec->PolySegmentThinSolidFlags) && + CHECK_FG(pGC, infoRec->PolySegmentThinSolidFlags)) { + + pGC->ops->PolySegment = infoRec->PolySegmentThinSolid; + } + + if (infoRec->PolylinesThinSolid && + CHECK_PLANEMASK(pGC, infoRec->PolylinesThinSolidFlags) && + CHECK_ROP(pGC, infoRec->PolylinesThinSolidFlags) && + CHECK_ROPSRC(pGC, infoRec->PolylinesThinSolidFlags) && + CHECK_FG(pGC, infoRec->PolylinesThinSolidFlags)) { + + pGC->ops->Polylines = infoRec->PolylinesThinSolid; + } + } + else if ((pGC->lineStyle == LineOnOffDash) && pGCPriv->DashPattern) { + + if (infoRec->PolySegmentThinDashed && + !(infoRec->PolySegmentThinDashedFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->PolySegmentThinDashedFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_PLANEMASK(pGC, infoRec->PolySegmentThinDashedFlags) && + CHECK_ROP(pGC, infoRec->PolySegmentThinDashedFlags) && + CHECK_ROPSRC(pGC, infoRec->PolySegmentThinDashedFlags) && + CHECK_FG(pGC, infoRec->PolySegmentThinDashedFlags)) { + + pGC->ops->PolySegment = infoRec->PolySegmentThinDashed; + } + + if (infoRec->PolylinesThinDashed && + !(infoRec->PolylinesThinDashedFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->PolylinesThinDashedFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_PLANEMASK(pGC, infoRec->PolylinesThinDashedFlags) && + CHECK_ROP(pGC, infoRec->PolylinesThinDashedFlags) && + CHECK_ROPSRC(pGC, infoRec->PolylinesThinDashedFlags) && + CHECK_FG(pGC, infoRec->PolylinesThinDashedFlags)) { + + pGC->ops->Polylines = infoRec->PolylinesThinDashed; + } + + if (pGC->ops->Polylines != XAAFallbackOps.Polylines) + pGC->ops->PolyRectangle = miPolyRectangle; + + } + else if (pGCPriv->DashPattern && (pGC->depth != 32)) { + /* LineDoubleDash */ + if (infoRec->PolySegmentThinDashed && + !(infoRec->PolySegmentThinDashedFlags & TRANSPARENCY_ONLY) && + CHECK_PLANEMASK(pGC, infoRec->PolySegmentThinDashedFlags) && + CHECK_ROP(pGC, infoRec->PolySegmentThinDashedFlags) && + CHECK_ROPSRC(pGC, infoRec->PolySegmentThinDashedFlags) && + CHECK_COLORS(pGC, infoRec->PolySegmentThinDashedFlags)) { + + pGC->ops->PolySegment = infoRec->PolySegmentThinDashed; + } + + if (infoRec->PolylinesThinDashed && + !(infoRec->PolylinesThinDashedFlags & TRANSPARENCY_ONLY) && + CHECK_PLANEMASK(pGC, infoRec->PolylinesThinDashedFlags) && + CHECK_ROP(pGC, infoRec->PolylinesThinDashedFlags) && + CHECK_ROPSRC(pGC, infoRec->PolylinesThinDashedFlags) && + CHECK_COLORS(pGC, infoRec->PolylinesThinDashedFlags)) { + + pGC->ops->Polylines = infoRec->PolylinesThinDashed; + } + + if (pGC->ops->Polylines != XAAFallbackOps.Polylines) + pGC->ops->PolyRectangle = miPolyRectangle; + + } + } + + if (infoRec->PolylinesWideSolid && + (pGC->lineWidth > 0) && + (pGC->fillStyle == FillSolid) && + (pGC->lineStyle == LineSolid) && + CHECK_PLANEMASK(pGC, infoRec->PolylinesWideSolidFlags) && + CHECK_ROP(pGC, infoRec->PolylinesWideSolidFlags) && + CHECK_ROPSRC(pGC, infoRec->PolylinesWideSolidFlags) && + CHECK_FG(pGC, infoRec->PolylinesWideSolidFlags)) { + + pGC->ops->Polylines = infoRec->PolylinesWideSolid; + } +} diff --git a/hw/xfree86/xaa/xaaImage.c b/hw/xfree86/xaa/xaaImage.c new file mode 100644 index 000000000..4457c9efa --- /dev/null +++ b/hw/xfree86/xaa/xaaImage.c @@ -0,0 +1,534 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "servermd.h" + +#include +#include "scrnintstr.h" +#include "mi.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +void +XAAMoveDWORDS_FixedBase(register CARD32 *dest, + register CARD32 *src, register int dwords) +{ + while (dwords & ~0x03) { + *dest = *src; + *dest = *(src + 1); + *dest = *(src + 2); + *dest = *(src + 3); + dwords -= 4; + src += 4; + } + + if (!dwords) + return; + *dest = *src; + if (dwords == 1) + return; + *dest = *(src + 1); + if (dwords == 2) + return; + *dest = *(src + 2); +} + +void +XAAMoveDWORDS(register CARD32 *dest, register CARD32 *src, register int dwords) +{ + while (dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + *(dest + 3) = *(src + 3); + src += 4; + dest += 4; + dwords -= 4; + } + if (!dwords) + return; + *dest = *src; + if (dwords == 1) + return; + *(dest + 1) = *(src + 1); + if (dwords == 2) + return; + *(dest + 2) = *(src + 2); +} + +void +XAAMoveDWORDS_FixedSrc(register CARD32 *dest, + register CARD32 *src, register int dwords) +{ + while (dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *src; + *(dest + 2) = *src; + *(dest + 3) = *src; + dest += 4; + dwords -= 4; + } + if (!dwords) + return; + *dest = *src; + if (dwords == 1) + return; + *(dest + 1) = *src; + if (dwords == 2) + return; + *(dest + 2) = *src; +} + +static void +XAAWritePixmap32To24(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *srcInit, int srcwidth, /* bytes */ + int rop, unsigned int planemask, int trans) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int count, dwords = bytes_to_int32(w * 3); + CARD32 *src, *dst; + Bool PlusOne = FALSE; + + if ((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && + ((dwords * h) & 0x01)) { + PlusOne = TRUE; + } + + (*infoRec->SetupForImageWrite) (pScrn, rop, planemask, trans, 24, 24); + (*infoRec->SubsequentImageWriteRect) (pScrn, x, y, w, h, 0); + + if (dwords > infoRec->ImageWriteRange) { + dst = (CARD32 *) infoRec->ImageWriteBase; + while (h--) { + src = (CARD32 *) srcInit; + count = w; + + while (count >= 4) { + *dst = (src[0] & 0x00ffffff) | (src[1] << 24); + *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + *dst = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); + src += 4; + count -= 4; + } + switch (count) { + case 0: + break; + case 1: + *dst = src[0]; + break; + case 2: + *dst = (src[0] & 0x00ffffff) | (src[1] << 24); + *dst = src[1] >> 8; + break; + default: + *dst = (src[0] & 0x00ffffff) | (src[1] << 24); + *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + *dst = src[2] >> 16; + break; + } + srcInit += srcwidth; + } + } + else { + while (h--) { + dst = (CARD32 *) infoRec->ImageWriteBase; + src = (CARD32 *) srcInit; + count = w; + + while (count >= 4) { + dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); + dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + dst[2] = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); + dst += 3; + src += 4; + count -= 4; + } + switch (count) { + case 0: + break; + case 1: + dst[0] = src[0]; + break; + case 2: + dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); + dst[1] = src[1] >> 8; + break; + default: + dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); + dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + dst[2] = src[2] >> 16; + break; + } + srcInit += srcwidth; + } + } + + if (PlusOne) { + CARD32 *base = (CARD32 *) infoRec->ImageWriteBase; + + *base = 0x00000000; + } + + if (infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); + +} + +void +XAAWritePixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *src, int srcwidth, /* bytes */ + int rop, unsigned int planemask, int trans, int bpp, int depth) +{ + XAAInfoRecPtr infoRec; + int dwords, skipleft, Bpp; + Bool beCareful, PlusOne; + + if ((bpp == 32) && (pScrn->bitsPerPixel == 24)) { + XAAWritePixmap32To24(pScrn, x, y, w, h, src, srcwidth, + rop, planemask, trans); + return; + } + + infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + beCareful = PlusOne = FALSE; + Bpp = bpp >> 3; + + if ((skipleft = (long) src & 0x03L)) { + if (!(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + if (Bpp == 3) + skipleft = 4 - skipleft; + else + skipleft /= Bpp; + + if ((x < skipleft) && !(infoRec->ImageWriteFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + x -= skipleft; + w += skipleft; + + if (Bpp == 3) + src -= 3 * skipleft; + else /* is this Alpha friendly ? */ + src = (unsigned char *) ((long) src & ~0x03L); + } + + BAD_ALIGNMENT: + + dwords = bytes_to_int32(w * Bpp); + + if ((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && + ((dwords * h) & 0x01)) { + PlusOne = TRUE; + } + + (*infoRec->SetupForImageWrite) (pScrn, rop, planemask, trans, bpp, depth); + (*infoRec->SubsequentImageWriteRect) (pScrn, x, y, w, h, skipleft); + + if (beCareful) { + /* in cases with bad alignment we have to be careful not + to read beyond the end of the source */ + if (((x * Bpp) + (dwords << 2)) > srcwidth) + h--; + else + beCareful = FALSE; + } + + if (dwords > infoRec->ImageWriteRange) { + while (h--) { + XAAMoveDWORDS_FixedBase((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords); + src += srcwidth; + } + if (beCareful) { + int shift = ((long) src & 0x03L) << 3; + + if (--dwords) + XAAMoveDWORDS_FixedBase((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords); + src = (unsigned char *) ((long) (src + (dwords << 2)) & ~0x03L); + *((CARD32 *) infoRec->ImageWriteBase) = *((CARD32 *) src) >> shift; + } + } + else { + if (srcwidth == (dwords << 2)) { + int decrement = infoRec->ImageWriteRange / dwords; + + while (h > decrement) { + XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords * decrement); + src += (srcwidth * decrement); + h -= decrement; + } + if (h) { + XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords * h); + if (beCareful) + src += (srcwidth * h); + } + } + else { + while (h--) { + XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords); + src += srcwidth; + } + } + + if (beCareful) { + int shift = ((long) src & 0x03L) << 3; + + if (--dwords) + XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, + (CARD32 *) src, dwords); + src = (unsigned char *) ((long) (src + (dwords << 2)) & ~0x03L); + + ((CARD32 *) infoRec->ImageWriteBase)[dwords] = + *((CARD32 *) src) >> shift; + } + } + + if (PlusOne) { + CARD32 *base = (CARD32 *) infoRec->ImageWriteBase; + + *base = 0x00000000; + } + + if (infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +void +XAAWritePixmapScanline(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *src, int srcwidth, /* bytes */ + int rop, + unsigned int planemask, int trans, int bpp, int depth) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int dwords, skipleft, bufferNo = 0, Bpp = bpp >> 3; + Bool beCareful = FALSE; + CARD32 *base; + + if ((skipleft = (long) src & 0x03L)) { + if (!(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + if (Bpp == 3) + skipleft = 4 - skipleft; + else + skipleft /= Bpp; + + if ((x < skipleft) && !(infoRec->ScanlineImageWriteFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + x -= skipleft; + w += skipleft; + + if (Bpp == 3) + src -= 3 * skipleft; + else + src = (unsigned char *) ((long) src & ~0x03L); + } + + BAD_ALIGNMENT: + + dwords = bytes_to_int32(w * Bpp); + + (*infoRec->SetupForScanlineImageWrite) (pScrn, rop, planemask, trans, bpp, + depth); + (*infoRec->SubsequentScanlineImageWriteRect) (pScrn, x, y, w, h, skipleft); + + if (beCareful) { + /* in cases with bad alignment we have to be careful not + to read beyond the end of the source */ + if (((x * Bpp) + (dwords << 2)) > srcwidth) + h--; + else + beCareful = FALSE; + } + + while (h--) { + base = (CARD32 *) infoRec->ScanlineImageWriteBuffers[bufferNo]; + XAAMoveDWORDS(base, (CARD32 *) src, dwords); + (*infoRec->SubsequentImageWriteScanline) (pScrn, bufferNo++); + src += srcwidth; + if (bufferNo >= infoRec->NumScanlineImageWriteBuffers) + bufferNo = 0; + } + + if (beCareful) { + int shift = ((long) src & 0x03L) << 3; + + base = (CARD32 *) infoRec->ScanlineImageWriteBuffers[bufferNo]; + if (--dwords) + XAAMoveDWORDS(base, (CARD32 *) src, dwords); + src = (unsigned char *) ((long) (src + (dwords << 2)) & ~0x03L); + + base[dwords] = *((CARD32 *) src) >> shift; + (*infoRec->SubsequentImageWriteScanline) (pScrn, bufferNo); + } + + SET_SYNC_FLAG(infoRec); +} + +void +XAAPutImage(DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, int leftPad, int format, char *pImage) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int bpp = BitsPerPixel(depth); + Bool depthBug = FALSE; + + if (!w || !h) + return; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + depthBug = XAA_DEPTH_BUG(pGC); + + if (((format == ZPixmap) && infoRec->WritePixmap && + ((pDraw->bitsPerPixel == bpp) || + ((pDraw->bitsPerPixel == 24) && (bpp == 32) && + (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && + CHECK_ROP(pGC, infoRec->WritePixmapFlags) && + CHECK_ROPSRC(pGC, infoRec->WritePixmapFlags) && + CHECK_PLANEMASK(pGC, infoRec->WritePixmapFlags) && + CHECK_NO_GXCOPY(pGC, infoRec->WritePixmapFlags)) || + ((format == XYBitmap) && !depthBug && infoRec->WriteBitmap && + CHECK_ROP(pGC, infoRec->WriteBitmapFlags) && + CHECK_ROPSRC(pGC, infoRec->WriteBitmapFlags) && + CHECK_PLANEMASK(pGC, infoRec->WriteBitmapFlags) && + CHECK_COLORS(pGC, infoRec->WriteBitmapFlags) && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) || + ((format == XYPixmap) && !depthBug && infoRec->WriteBitmap && + CHECK_ROP(pGC, infoRec->WriteBitmapFlags) && + CHECK_ROPSRC(pGC, infoRec->WriteBitmapFlags) && + !(infoRec->WriteBitmapFlags & NO_PLANEMASK) && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY))) { + + int MaxBoxes = RegionNumRects(pGC->pCompositeClip); + BoxPtr pbox, pClipBoxes; + int nboxes, srcx, srcy, srcwidth; + xRectangle TheRect; + + TheRect.x = pDraw->x + x; + TheRect.y = pDraw->y + y; + TheRect.width = w; + TheRect.height = h; + + if (MaxBoxes > (infoRec->PreAllocSize / sizeof(BoxRec))) { + pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec)); + if (!pClipBoxes) + return; + } + else + pClipBoxes = (BoxPtr) infoRec->PreAllocMem; + + nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); + pbox = pClipBoxes; + + if (format == XYBitmap) { + srcwidth = BitmapBytePad(leftPad + w); + while (nboxes--) { + srcx = pbox->x1 - TheRect.x + leftPad; + srcy = pbox->y1 - TheRect.y; + (*infoRec->WriteBitmap) (infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1, + (unsigned char *) pImage + + (srcwidth * srcy) + ((srcx >> 5) << 2), + srcwidth, srcx & 31, pGC->fgPixel, + pGC->bgPixel, pGC->alu, + pGC->planemask); + pbox++; + } + } + else if (format == ZPixmap) { + int Bpp = bpp >> 3; + + srcwidth = PixmapBytePad(leftPad + w, depth); + while (nboxes--) { + srcx = pbox->x1 - TheRect.x + leftPad; + srcy = pbox->y1 - TheRect.y; + (*infoRec->WritePixmap) (infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1, + (unsigned char *) pImage + + (srcwidth * srcy) + (srcx * Bpp), + srcwidth, pGC->alu, pGC->planemask, -1, + Bpp << 3, depth); + pbox++; + } + } + else { /* XYPixmap */ + int depth = pGC->depth; + int numBox, increment; + unsigned long i, mask; + BoxPtr pntBox; + + srcwidth = BitmapBytePad(w + leftPad); + increment = h * srcwidth; + i = 1 << (depth - 1); + mask = ~0; + + if ((infoRec->pScrn->overlayFlags & OVERLAY_8_32_PLANAR) && + (pGC->depth == 8)) { + i = 0x80000000; + mask = 0xff000000; + } + + for (; i & mask; i >>= 1, pImage += increment) { + if (i & pGC->planemask) { + pntBox = pbox; + numBox = nboxes; + while (numBox--) { + srcx = pntBox->x1 - TheRect.x + leftPad; + srcy = pntBox->y1 - TheRect.y; + (*infoRec->WriteBitmap) (infoRec->pScrn, + pntBox->x1, pntBox->y1, + pntBox->x2 - pntBox->x1, + pntBox->y2 - pntBox->y1, + (unsigned char *) pImage + + (srcwidth * srcy) + + ((srcx >> 5) << 2), srcwidth, + srcx & 31, ~0, 0, pGC->alu, i); + pntBox++; + } + } + } + + } + + if (pClipBoxes != (BoxPtr) infoRec->PreAllocMem) + free(pClipBoxes); + } + else + XAAFallbackOps.PutImage(pDraw, pGC, depth, x, y, w, h, leftPad, + format, pImage); +} diff --git a/hw/xfree86/xaa/xaaInit.c b/hw/xfree86/xaa/xaaInit.c new file mode 100644 index 000000000..93b5c5629 --- /dev/null +++ b/hw/xfree86/xaa/xaaInit.c @@ -0,0 +1,635 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "xf86fbman.h" +#include "servermd.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define MAX_PREALLOC_MEM 65536 /* MUST be >= 1024 */ + +#define MIN_OFFPIX_SIZE (320*200) + +static Bool XAACloseScreen(ScreenPtr pScreen); +static void XAAGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, + char *pdstLine); +static void XAAGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart); +static PixmapPtr XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, + unsigned usage_hint); +static Bool XAADestroyPixmap(PixmapPtr pPixmap); +static Bool XAAEnterVT(ScrnInfoPtr pScrn); +static void XAALeaveVT(ScrnInfoPtr pScrn); +static int XAASetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr devRet); +static void XAAEnableDisableFBAccess(ScrnInfoPtr pScrn, Bool enable); +static Bool XAAChangeWindowAttributes(WindowPtr pWin, unsigned long mask); + +static DevPrivateKeyRec XAAScreenKeyRec; + +#define XAAScreenKey (&XAAScreenKeyRec) +static DevPrivateKeyRec XAAGCKeyRec; + +#define XAAGCKey (&XAAGCKeyRec) +static DevPrivateKeyRec XAAPixmapKeyRec; + +#define XAAPixmapKey (&XAAPixmapKeyRec) + +DevPrivateKey +XAAGetScreenKey(void) +{ + return XAAScreenKey; +} + +DevPrivateKey +XAAGetGCKey(void) +{ + return XAAGCKey; +} + +DevPrivateKey +XAAGetPixmapKey(void) +{ + return XAAPixmapKey; +} + +/* temp kludge */ +static Bool SwitchedOut = FALSE; + +XAAInfoRecPtr +XAACreateInfoRec(void) +{ + XAAInfoRecPtr infoRec; + + infoRec = calloc(1, sizeof(XAAInfoRec)); + if (infoRec) + infoRec->CachePixelGranularity = -1; + + return infoRec; +} + +void +XAADestroyInfoRec(XAAInfoRecPtr infoRec) +{ + if (!infoRec) + return; + + if (infoRec->ClosePixmapCache) + (*infoRec->ClosePixmapCache) (xf86ScrnToScreen(infoRec->pScrn)); + + free(infoRec->PreAllocMem); + + free(infoRec->PixmapCachePrivate); + + free(infoRec); +} + +Bool +XAAInit(ScreenPtr pScreen, XAAInfoRecPtr infoRec) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XAAScreenPtr pScreenPriv; + int i; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + /* Return successfully if no acceleration wanted */ + if (!infoRec) + return TRUE; + + if (!dixRegisterPrivateKey(&XAAGCKeyRec, PRIVATE_GC, sizeof(XAAGCRec))) + return FALSE; + + if (!dixRegisterPrivateKey + (&XAAPixmapKeyRec, PRIVATE_PIXMAP, sizeof(XAAPixmapRec))) + return FALSE; + + if (!dixRegisterPrivateKey(&XAAScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!(pScreenPriv = malloc(sizeof(XAAScreenRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, XAAScreenKey, pScreenPriv); + + if (!xf86FBManagerRunning(pScreen)) + infoRec->Flags &= ~(PIXMAP_CACHE | OFFSCREEN_PIXMAPS); + if (!(infoRec->Flags & LINEAR_FRAMEBUFFER)) + infoRec->Flags &= ~OFFSCREEN_PIXMAPS; + + if (!infoRec->FullPlanemask) { /* for backwards compatibility */ + infoRec->FullPlanemask = (1 << pScrn->depth) - 1; + infoRec->FullPlanemasks[pScrn->depth - 1] = infoRec->FullPlanemask; + } + + for (i = 0; i < 32; i++) { + if (!infoRec->FullPlanemasks[i]) /* keep any set by caller */ + infoRec->FullPlanemasks[i] = (1 << (i + 1)) - 1; + } + + if (!XAAInitAccel(pScreen, infoRec)) + return FALSE; + pScreenPriv->AccelInfoRec = infoRec; + infoRec->ScratchGC.pScreen = pScreen; + + if (!infoRec->GetImage) + infoRec->GetImage = XAAGetImage; + if (!infoRec->GetSpans) + infoRec->GetSpans = XAAGetSpans; + if (!infoRec->CopyWindow) + infoRec->CopyWindow = XAACopyWindow; + + pScreenPriv->CreateGC = pScreen->CreateGC; + pScreen->CreateGC = XAACreateGC; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = XAACloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreen->GetImage = infoRec->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreen->GetSpans = infoRec->GetSpans; + pScreenPriv->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = infoRec->CopyWindow; + pScreenPriv->CreatePixmap = pScreen->CreatePixmap; + pScreen->CreatePixmap = XAACreatePixmap; + pScreenPriv->DestroyPixmap = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = XAADestroyPixmap; + pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pScreen->ChangeWindowAttributes = XAAChangeWindowAttributes; + + pScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = XAAEnterVT; + pScreenPriv->LeaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = XAALeaveVT; + pScreenPriv->SetDGAMode = pScrn->SetDGAMode; + pScrn->SetDGAMode = XAASetDGAMode; + pScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; + pScrn->EnableDisableFBAccess = XAAEnableDisableFBAccess; + + pScreenPriv->WindowExposures = pScreen->WindowExposures; + if (ps) { + pScreenPriv->Composite = ps->Composite; + ps->Composite = XAAComposite; + pScreenPriv->Glyphs = ps->Glyphs; + ps->Glyphs = XAAGlyphs; + } + if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) + XAASetupOverlay8_32Planar(pScreen); + + infoRec->PreAllocMem = malloc(MAX_PREALLOC_MEM); + if (infoRec->PreAllocMem) + infoRec->PreAllocSize = MAX_PREALLOC_MEM; + + if (infoRec->Flags & PIXMAP_CACHE) + xf86RegisterFreeBoxCallback(pScreen, infoRec->InitPixmapCache, + (void *) infoRec); + + if (infoRec->Flags & MICROSOFT_ZERO_LINE_BIAS) + miSetZeroLineBias(pScreen, OCTANT1 | OCTANT2 | OCTANT3 | OCTANT4); + +#ifdef COMPOSITE + /* Initialize the composite wrapper. This needs to happen after the + * wrapping above (so it comes before us), but before all other extensions, + * so it doesn't confuse them. (particularly damage). + */ + miInitializeCompositeWrapper(pScreen); +#endif + + return TRUE; +} + +static Bool +XAACloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + + pScrn->EnterVT = pScreenPriv->EnterVT; + pScrn->LeaveVT = pScreenPriv->LeaveVT; + pScrn->EnableDisableFBAccess = pScreenPriv->EnableDisableFBAccess; + + pScreen->CreateGC = pScreenPriv->CreateGC; + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->CopyWindow = pScreenPriv->CopyWindow; + pScreen->WindowExposures = pScreenPriv->WindowExposures; + pScreen->CreatePixmap = pScreenPriv->CreatePixmap; + pScreen->DestroyPixmap = pScreenPriv->DestroyPixmap; + pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes; + + /* We leave it up to the client to free the XAAInfoRec */ + + free((void *) pScreenPriv); + + return (*pScreen->CloseScreen) (pScreen); +} + +static void +XAAGetImage(DrawablePtr pDraw, + int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, char *pdstLine) +{ + ScreenPtr pScreen = pDraw->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = infoRec->pScrn; + + if (pScrn->vtSema && + ((pDraw->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pDraw))) { + if (infoRec->ReadPixmap && (format == ZPixmap) && + ((planemask & infoRec->FullPlanemasks[pDraw->depth - 1]) == + infoRec->FullPlanemasks[pDraw->depth - 1]) && + (pDraw->bitsPerPixel == BitsPerPixel(pDraw->depth))) { + (*infoRec->ReadPixmap) (pScrn, + sx + pDraw->x, sy + pDraw->y, w, h, + (unsigned char *) pdstLine, + PixmapBytePad(w, pDraw->depth), + pDraw->bitsPerPixel, pDraw->depth); + return; + } + SYNC_CHECK(pDraw); + } + + XAA_SCREEN_PROLOGUE(pScreen, GetImage); + (*pScreen->GetImage) (pDraw, sx, sy, w, h, format, planemask, pdstLine); + XAA_SCREEN_EPILOGUE(pScreen, GetImage, XAAGetImage); +} + +static void +XAAGetSpans(DrawablePtr pDraw, + int wMax, DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDraw->pScreen; + + XAA_SCREEN_PROLOGUE(pScreen, GetSpans); + if (xf86ScreenToScrn(pScreen)->vtSema && + ((pDraw->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pDraw))) { + SYNC_CHECK(pDraw); + } + (*pScreen->GetSpans) (pDraw, wMax, ppt, pwidth, nspans, pdstStart); + XAA_SCREEN_EPILOGUE(pScreen, GetSpans, XAAGetSpans); +} + +static int +XAAPixmapBPP(ScreenPtr pScreen, int depth) +{ + PixmapPtr pPix; + int bpp; + DestroyPixmapProcPtr destroyPixmap; + + XAA_SCREEN_PROLOGUE(pScreen, CreatePixmap); + pPix = (*pScreen->CreatePixmap) (pScreen, 1, 1, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + XAA_SCREEN_EPILOGUE(pScreen, CreatePixmap, XAACreatePixmap); + if (!pPix) + return 0; + bpp = pPix->drawable.bitsPerPixel; + destroyPixmap = pScreen->DestroyPixmap; + XAA_SCREEN_PROLOGUE(pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPix); + XAA_SCREEN_EPILOGUE(pScreen, DestroyPixmap, destroyPixmap); + return bpp; +} + +static void +XAAInitializeOffscreenDepths(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + int d, dep; + + infoRec->offscreenDepthsInitialized = TRUE; + infoRec->offscreenDepths = 0; + if (infoRec->Flags & OFFSCREEN_PIXMAPS) { + for (d = 0; d < pScreen->numDepths; d++) { + dep = pScreen->allowedDepths[d].depth; + if (XAAPixmapBPP(pScreen, dep) == pScrn->bitsPerPixel) + infoRec->offscreenDepths |= (1 << (dep - 1)); + } + } +} + +static PixmapPtr +XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XAAPixmapPtr pPriv; + PixmapPtr pPix = NULL; + int size = w * h; + + if (w > 32767 || h > 32767) + return NullPixmap; + + if (!infoRec->offscreenDepthsInitialized) + XAAInitializeOffscreenDepths(pScreen); + + if (pScrn->vtSema && + (usage_hint != CREATE_PIXMAP_USAGE_GLYPH_PICTURE) && + (infoRec->offscreenDepths & (1 << (depth - 1))) && + (size >= MIN_OFFPIX_SIZE) && !SwitchedOut && + (!infoRec->maxOffPixWidth || (w <= infoRec->maxOffPixWidth)) && + (!infoRec->maxOffPixHeight || (h <= infoRec->maxOffPixHeight))) { + PixmapLinkPtr pLink; + PixmapPtr pScreenPix; + FBAreaPtr area; + int gran = 0; + + switch (pScrn->bitsPerPixel) { + case 24: + case 8: + gran = 4; + break; + case 16: + gran = 2; + break; + case 32: + gran = 1; + break; + default: + break; + } + + if (BITMAP_SCANLINE_PAD == 64) + gran *= 2; + + if (!(area = xf86AllocateOffscreenArea(pScreen, w, h, gran, 0, + XAARemoveAreaCallback, NULL))) { + goto BAILOUT; + } + + if (!(pLink = malloc(sizeof(PixmapLink)))) { + xf86FreeOffscreenArea(area); + goto BAILOUT; + } + + XAA_SCREEN_PROLOGUE(pScreen, CreatePixmap); + pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, usage_hint); + XAA_SCREEN_EPILOGUE(pScreen, CreatePixmap, XAACreatePixmap); + + if (!pPix) { + free(pLink); + xf86FreeOffscreenArea(area); + goto BAILOUT; + } + + pScreenPix = (*pScreen->GetScreenPixmap) (pScreen); + + pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + pPix->drawable.x = area->box.x1; + pPix->drawable.y = area->box.y1; + pPix->drawable.width = w; + pPix->drawable.height = h; + pPix->drawable.bitsPerPixel = pScrn->bitsPerPixel; + pPix->devKind = pScreenPix->devKind; + pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr; + area->devPrivate.ptr = pPix; + + pPriv->flags = OFFSCREEN; + pPriv->offscreenArea = area; + pPriv->freeData = FALSE; + + pLink->next = infoRec->OffscreenPixmaps; + pLink->pPix = pPix; + infoRec->OffscreenPixmaps = pLink; + return pPix; + } + BAILOUT: + XAA_SCREEN_PROLOGUE(pScreen, CreatePixmap); + pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint); + XAA_SCREEN_EPILOGUE(pScreen, CreatePixmap, XAACreatePixmap); + + if (pPix) { + pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + pPriv->flags = 0; + pPriv->offscreenArea = NULL; + pPriv->freeData = FALSE; + if (!w || !h) /* either scratch or shared memory */ + pPriv->flags |= SHARED_PIXMAP; + } + + return pPix; +} + +static Bool +XAADestroyPixmap(PixmapPtr pPix) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + Bool ret; + + if (pPix->refcnt == 1) { + if (pPriv->flags & OFFSCREEN) { + if (pPriv->flags & DGA_PIXMAP) + free(pPriv->offscreenArea); + else { + FBAreaPtr area = pPriv->offscreenArea; + PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; + PixmapLinkPtr prev = NULL; + + while (pLink->pPix != pPix) { + prev = pLink; + pLink = pLink->next; + } + + if (prev) + prev->next = pLink->next; + else + infoRec->OffscreenPixmaps = pLink->next; + + if (!area) + area = pLink->area; + + xf86FreeOffscreenArea(area); + pPriv->offscreenArea = NULL; + free(pLink); + } + } + + if (pPriv->freeData) { /* pixmaps that were once in video ram */ + free(pPix->devPrivate.ptr); + pPix->devPrivate.ptr = NULL; + } + } + + XAA_SCREEN_PROLOGUE(pScreen, DestroyPixmap); + ret = (*pScreen->DestroyPixmap) (pPix); + XAA_SCREEN_EPILOGUE(pScreen, DestroyPixmap, XAADestroyPixmap); + + return ret; +} + +static Bool +XAAChangeWindowAttributes(WindowPtr pWin, unsigned long mask) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + Bool ret; + + XAA_SCREEN_PROLOGUE(pScreen, ChangeWindowAttributes); + ret = (*pScreen->ChangeWindowAttributes) (pWin, mask); + XAA_SCREEN_EPILOGUE(pScreen, ChangeWindowAttributes, + XAAChangeWindowAttributes); + + /* we have to assume that shared memory pixmaps are dirty + because we can't wrap operations on them */ + + if ((mask & CWBackPixmap) && (pWin->backgroundState == BackgroundPixmap) && + PIXMAP_IS_SHARED(pWin->background.pixmap)) { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pWin->background.pixmap); + + pPixPriv->flags |= DIRTY; + } + if ((mask & CWBorderPixmap) && !(pWin->borderIsPixel) && + PIXMAP_IS_SHARED(pWin->border.pixmap)) { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pWin->border.pixmap); + + pPixPriv->flags |= DIRTY; + } + + return ret; +} + +/* These two aren't really needed for anything */ + +static Bool +XAAEnterVT(ScrnInfoPtr pScrn) +{ + Bool ret; + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + + pScrn->EnterVT = pScreenPriv->EnterVT; + ret = ((*pScreenPriv->EnterVT) (pScrn)); + pScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = XAAEnterVT; + return ret; +} + +static void +XAALeaveVT(ScrnInfoPtr pScrn) +{ + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + XAAInfoRecPtr infoRec = pScreenPriv->AccelInfoRec; + + if (infoRec->NeedToSync) { + (*infoRec->Sync) (infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + + pScrn->LeaveVT = pScreenPriv->LeaveVT; + (*pScreenPriv->LeaveVT) (pScrn); + pScreenPriv->LeaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = XAALeaveVT; +} + +typedef struct { + Bool UsingPixmapCache; + Bool CanDoColor8x8; + Bool CanDoMono8x8; +} SavedCacheState, *SavedCacheStatePtr; + +static int +XAASetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr devRet) +{ + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + int ret; + + if (!num && infoRec->dgaSaves) { /* restore old pixmap cache state */ + SavedCacheStatePtr state = (SavedCacheStatePtr) infoRec->dgaSaves; + + infoRec->UsingPixmapCache = state->UsingPixmapCache; + infoRec->CanDoColor8x8 = state->CanDoColor8x8; + infoRec->CanDoMono8x8 = state->CanDoMono8x8; + free(infoRec->dgaSaves); + infoRec->dgaSaves = NULL; + } + + ret = (*pScreenPriv->SetDGAMode) (pScrn, num, devRet); + if (ret != Success) + return ret; + + if (num && devRet->pPix) { /* accelerate this pixmap */ + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(devRet->pPix); + FBAreaPtr area; + + if ((area = malloc(sizeof(FBArea)))) { + area->pScreen = pScreen; + area->box.x1 = 0; + area->box.x2 = 0; + area->box.y1 = devRet->mode->pixmapWidth; + area->box.y2 = devRet->mode->pixmapHeight; + area->granularity = 0; + area->MoveAreaCallback = 0; + area->RemoveAreaCallback = 0; + area->devPrivate.ptr = 0; + + pixPriv->flags |= OFFSCREEN | DGA_PIXMAP; + pixPriv->offscreenArea = area; + + if (!infoRec->dgaSaves) { /* save pixmap cache state */ + SavedCacheStatePtr state = malloc(sizeof(SavedCacheState)); + + state->UsingPixmapCache = infoRec->UsingPixmapCache; + state->CanDoColor8x8 = infoRec->CanDoColor8x8; + state->CanDoMono8x8 = infoRec->CanDoMono8x8; + infoRec->dgaSaves = (char *) state; + + infoRec->UsingPixmapCache = FALSE; + if (infoRec->PixmapCacheFlags & CACHE_MONO_8x8) + infoRec->CanDoMono8x8 = FALSE; + if (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8) + infoRec->CanDoColor8x8 = FALSE; + } + } + } + + return ret; +} + +static void +XAAEnableDisableFBAccess(ScrnInfoPtr pScrn, Bool enable) +{ + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr) dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + + if (!enable) { + if ((infoRec->Flags & OFFSCREEN_PIXMAPS) && (infoRec->OffscreenPixmaps)) + XAAMoveOutOffscreenPixmaps(pScreen); + if (infoRec->Flags & PIXMAP_CACHE) + XAAInvalidatePixmapCache(pScreen); + SwitchedOut = TRUE; + } + + (*pScreenPriv->EnableDisableFBAccess) (pScrn, enable); + + if (enable) { + if ((infoRec->Flags & OFFSCREEN_PIXMAPS) && (infoRec->OffscreenPixmaps)) + XAAMoveInOffscreenPixmaps(pScreen); + SwitchedOut = FALSE; + } +} diff --git a/hw/xfree86/xaa/xaaInitAccel.c b/hw/xfree86/xaa/xaaInitAccel.c new file mode 100644 index 000000000..a36e0b71b --- /dev/null +++ b/hw/xfree86/xaa/xaaInitAccel.c @@ -0,0 +1,1571 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xf86fbman.h" +#include "servermd.h" + +/* + * XAA Config options + */ + +typedef enum { + XAAOPT_SCREEN_TO_SCREEN_COPY, + XAAOPT_SOLID_FILL_RECT, + XAAOPT_SOLID_FILL_TRAP, + XAAOPT_SOLID_TWO_POINT_LINE, + XAAOPT_SOLID_BRESENHAM_LINE, + XAAOPT_SOLID_HORVERT_LINE, + XAAOPT_DASHED_TWO_POINT_LINE, + XAAOPT_DASHED_BRESENHAM_LINE, + XAAOPT_MONO_8x8_PATTERN_FILL_RECT, + XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, + XAAOPT_COL_8x8_PATTERN_FILL_RECT, + XAAOPT_COL_8x8_PATTERN_FILL_TRAP, + XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, + XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, + XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, + XAAOPT_IMAGE_WRITE_RECT, + XAAOPT_SCANLINE_IMAGE_WRITE_RECT, + XAAOPT_WRITE_BITMAP, + XAAOPT_WRITE_PIXMAP, + XAAOPT_PIXMAP_CACHE, + XAAOPT_OFFSCREEN_PIXMAPS, + XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE +} XAAOpts; + +static const OptionInfoRec XAAOptions[] = { + {XAAOPT_SCREEN_TO_SCREEN_COPY, "XaaNoScreenToScreenCopy", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SOLID_FILL_RECT, "XaaNoSolidFillRect", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SOLID_FILL_TRAP, "XaaNoSolidFillTrap", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SOLID_TWO_POINT_LINE, "XaaNoSolidTwoPointLine", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SOLID_BRESENHAM_LINE, "XaaNoSolidBresenhamLine", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SOLID_HORVERT_LINE, "XaaNoSolidHorVertLine", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_DASHED_TWO_POINT_LINE, "XaaNoDashedTwoPointLine", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_DASHED_BRESENHAM_LINE, "XaaNoDashedBresenhamLine", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_MONO_8x8_PATTERN_FILL_RECT, "XaaNoMono8x8PatternFillRect", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, "XaaNoMono8x8PatternFillTrap", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_COL_8x8_PATTERN_FILL_RECT, "XaaNoColor8x8PatternFillRect", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_COL_8x8_PATTERN_FILL_TRAP, "XaaNoColor8x8PatternFillTrap", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, "XaaNoCPUToScreenColorExpandFill", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, + "XaaNoScanlineCPUToScreenColorExpandFill", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, "XaaNoScreenToScreenColorExpandFill", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_IMAGE_WRITE_RECT, "XaaNoImageWriteRect", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_SCANLINE_IMAGE_WRITE_RECT, "XaaNoScanlineImageWriteRect", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_WRITE_BITMAP, "XaaNoWriteBitmap", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_WRITE_PIXMAP, "XaaNoWritePixmap", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_PIXMAP_CACHE, "XaaNoPixmapCache", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_OFFSCREEN_PIXMAPS, "XaaNoOffscreenPixmaps", + OPTV_BOOLEAN, {0}, FALSE}, + {XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE, "XaaOffscreenPixmaps", + OPTV_BOOLEAN, {0}, FALSE}, + {-1, NULL, + OPTV_NONE, {0}, FALSE} +}; + +static XF86ModuleVersionInfo xaaVersRec = { + "xaa", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + XAA_VERSION_MAJOR, + XAA_VERSION_MINOR, + XAA_VERSION_RELEASE, + ABI_CLASS_VIDEODRV, /* requires the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0, 0, 0, 0} +}; + +_X_EXPORT XF86ModuleData xaaModuleData = { &xaaVersRec, NULL, NULL }; + +Bool +XAAInitAccel(ScreenPtr pScreen, XAAInfoRecPtr infoRec) +{ + int index = pScreen->myNum; + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + Bool HaveScreenToScreenCopy = FALSE; + Bool HaveColorExpansion = FALSE; + Bool HaveScanlineColorExpansion = FALSE; + Bool HaveSolidFillRect = FALSE; + Bool HaveMono8x8PatternFillRect = FALSE; + Bool HaveColor8x8PatternFillRect = FALSE; + Bool HaveSolidFillTrap = FALSE; + Bool HaveMono8x8PatternFillTrap = FALSE; + Bool HaveColor8x8PatternFillTrap = FALSE; + Bool HaveSolidTwoPointLine = FALSE; + Bool HaveSolidBresenhamLine = FALSE; + Bool HaveSolidHorVertLine = FALSE; + Bool HaveDashedTwoPointLine = FALSE; + Bool HaveDashedBresenhamLine = FALSE; + Bool HaveImageWriteRect = FALSE; + Bool HaveScanlineImageWriteRect = FALSE; + Bool HaveScreenToScreenColorExpandFill = FALSE; + OptionInfoPtr options; + int is_shared = 0; + int i; + + options = xnfalloc(sizeof(XAAOptions)); + (void) memcpy(options, XAAOptions, sizeof(XAAOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + infoRec->pScrn = pScrn; + infoRec->NeedToSync = FALSE; + + /* must have a Sync function */ + if (!infoRec->Sync) + return FALSE; + for (i = 0; i < pScrn->numEntities; i++) { + if (xf86IsEntityShared(pScrn->entityList[i])) + is_shared = 1; + } + + /* If this PCI entity has IS_SHARED_ACCEL set in entityProp + * then a RestoreAccelState function is required + */ + if (!infoRec->RestoreAccelState && is_shared) + return FALSE; + + if (infoRec->RestoreAccelState) { + if (!XAAInitStateWrap(pScreen, infoRec)) + return FALSE; + } + + if (serverGeneration == 1) + xf86DrvMsg(index, X_INFO, + "Using XFree86 Acceleration Architecture (XAA)\n"); + + /************** Low Level *************/ + + if (!infoRec->SetClippingRectangle || !infoRec->DisableClipping) { + infoRec->ClippingFlags = 0; + infoRec->SetClippingRectangle = NULL; + infoRec->DisableClipping = NULL; + } + + /**** CopyArea ****/ + + if (infoRec->SetupForScreenToScreenCopy && + infoRec->SubsequentScreenToScreenCopy && + !xf86ReturnOptValBool(options, XAAOPT_SCREEN_TO_SCREEN_COPY, FALSE)) { + HaveScreenToScreenCopy = TRUE; + } + else { + infoRec->ScreenToScreenCopyFlags = 0; + infoRec->SetupForScreenToScreenCopy = NULL; + infoRec->SubsequentScreenToScreenCopy = NULL; + } + + /**** Solid Filled Rects ****/ + + if (infoRec->SetupForSolidFill && infoRec->SubsequentSolidFillRect && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_FILL_RECT, FALSE)) { + HaveSolidFillRect = TRUE; + if (infoRec->SubsequentSolidFillTrap && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_FILL_TRAP, FALSE)) + HaveSolidFillTrap = TRUE; + else + infoRec->SubsequentSolidFillTrap = NULL; + } + else { + infoRec->SolidFillFlags = 0; + infoRec->SetupForSolidFill = NULL; + infoRec->SubsequentSolidFillRect = NULL; + infoRec->SubsequentSolidFillTrap = NULL; + } + + /**** Solid lines ****/ + + if (infoRec->SetupForSolidLine) { + if (infoRec->SubsequentSolidTwoPointLine && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_TWO_POINT_LINE, FALSE)) + HaveSolidTwoPointLine = TRUE; + if (infoRec->SubsequentSolidBresenhamLine && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_BRESENHAM_LINE, + FALSE)) { + HaveSolidBresenhamLine = TRUE; + + if (infoRec->SolidBresenhamLineErrorTermBits) + infoRec->SolidBresenhamLineErrorTermBits = + ~((1 << infoRec->SolidBresenhamLineErrorTermBits) - 1); + } + + if (infoRec->SubsequentSolidHorVertLine && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_HORVERT_LINE, FALSE)) + HaveSolidHorVertLine = TRUE; + else if (HaveSolidTwoPointLine) { + infoRec->SubsequentSolidHorVertLine = XAASolidHorVertLineAsTwoPoint; + HaveSolidHorVertLine = TRUE; + } + else if (HaveSolidBresenhamLine) { + infoRec->SubsequentSolidHorVertLine = + XAASolidHorVertLineAsBresenham; + HaveSolidHorVertLine = TRUE; + } + } + + /* XXX Should this also check for XAAOPT_SOLID_HORVERT_LINE? */ + if (!HaveSolidTwoPointLine && + !HaveSolidBresenhamLine && !HaveSolidHorVertLine && HaveSolidFillRect) { + infoRec->SetupForSolidLine = infoRec->SetupForSolidFill; + infoRec->SubsequentSolidHorVertLine = XAASolidHorVertLineAsRects; + infoRec->SolidLineFlags = infoRec->SolidFillFlags; + HaveSolidHorVertLine = TRUE; + } + + if (!HaveSolidTwoPointLine) + infoRec->SubsequentSolidTwoPointLine = NULL; + if (!HaveSolidBresenhamLine) + infoRec->SubsequentSolidBresenhamLine = NULL; + if (!HaveSolidHorVertLine) + infoRec->SubsequentSolidHorVertLine = NULL; + + /* Disable all if nothing left over */ + if (!HaveSolidTwoPointLine && + !HaveSolidBresenhamLine && !HaveSolidHorVertLine) { + infoRec->SolidLineFlags = 0; + infoRec->SetupForSolidLine = NULL; + } + + /**** 8x8 Mono Pattern Filled Rects ****/ + + if (infoRec->SetupForMono8x8PatternFill && + infoRec->SubsequentMono8x8PatternFillRect && + !xf86ReturnOptValBool(options, + XAAOPT_MONO_8x8_PATTERN_FILL_RECT, FALSE)) { + HaveMono8x8PatternFillRect = TRUE; + if (infoRec->SubsequentMono8x8PatternFillTrap && + !xf86ReturnOptValBool(options, + XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, FALSE)) + HaveMono8x8PatternFillTrap = TRUE; + + if (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) { + infoRec->CanDoMono8x8 = TRUE; + } + else { /* others require caching */ + int min_pitch; + + infoRec->PixmapCacheFlags |= CACHE_MONO_8x8; + + switch (pScrn->bitsPerPixel) { + case 32: + min_pitch = 2; + break; + case 24: + min_pitch = 3; + break; + case 16: + min_pitch = 4; + break; + default: + min_pitch = 8; + break; + } + + if (min_pitch > infoRec->MonoPatternPitch) + infoRec->MonoPatternPitch = min_pitch; + + if (infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + if (!infoRec->CacheWidthMono8x8Pattern || + !infoRec->CacheHeightMono8x8Pattern) { + infoRec->CacheWidthMono8x8Pattern = + infoRec->MonoPatternPitch; + infoRec->CacheHeightMono8x8Pattern = 1; + } + } + else { + int numPerLine = 128 / infoRec->MonoPatternPitch; + + if (!infoRec->CacheWidthMono8x8Pattern || + !infoRec->CacheHeightMono8x8Pattern) { + infoRec->CacheWidthMono8x8Pattern = + numPerLine * infoRec->MonoPatternPitch; + infoRec->CacheHeightMono8x8Pattern = + (64 + numPerLine - 1) / numPerLine; + } + } + } + } + else { + infoRec->Mono8x8PatternFillFlags = 0; + infoRec->SetupForMono8x8PatternFill = NULL; + infoRec->SubsequentMono8x8PatternFillRect = NULL; + } + + /**** Dashed lines ****/ + + if (infoRec->SetupForDashedLine && infoRec->DashPatternMaxLength) { + if (infoRec->SubsequentDashedTwoPointLine && + !xf86ReturnOptValBool(options, XAAOPT_DASHED_TWO_POINT_LINE, FALSE)) + HaveDashedTwoPointLine = TRUE; + if (infoRec->SubsequentDashedBresenhamLine && + !xf86ReturnOptValBool(options, XAAOPT_DASHED_BRESENHAM_LINE, + FALSE)) { + HaveDashedBresenhamLine = TRUE; + + if (infoRec->DashedBresenhamLineErrorTermBits) + infoRec->DashedBresenhamLineErrorTermBits = + ~((1 << infoRec->DashedBresenhamLineErrorTermBits) - 1); + } + } + + if (!HaveDashedTwoPointLine) + infoRec->SubsequentDashedTwoPointLine = NULL; + if (!HaveDashedBresenhamLine) + infoRec->SubsequentDashedBresenhamLine = NULL; + + /* Disable all if nothing left over */ + if (!HaveDashedTwoPointLine && !HaveDashedBresenhamLine) { + infoRec->DashedLineFlags = 0; + infoRec->SetupForDashedLine = NULL; + } + + /**** 8x8 Color Pattern Filled Rects ****/ + + if (infoRec->SetupForColor8x8PatternFill && + infoRec->SubsequentColor8x8PatternFillRect && + !xf86ReturnOptValBool(options, XAAOPT_COL_8x8_PATTERN_FILL_RECT, + FALSE)) { + HaveColor8x8PatternFillRect = TRUE; + if (infoRec->SubsequentColor8x8PatternFillTrap && + !xf86ReturnOptValBool(options, XAAOPT_COL_8x8_PATTERN_FILL_TRAP, + FALSE)) + HaveColor8x8PatternFillTrap = TRUE; + else + infoRec->SubsequentColor8x8PatternFillTrap = NULL; + + infoRec->PixmapCacheFlags |= CACHE_COLOR_8x8; + + if (infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + if (!infoRec->CacheWidthColor8x8Pattern || + !infoRec->CacheHeightColor8x8Pattern) { + infoRec->CacheWidthColor8x8Pattern = 64; + infoRec->CacheHeightColor8x8Pattern = 1; + } + } + else { + if (!infoRec->CacheWidthColor8x8Pattern || + !infoRec->CacheHeightColor8x8Pattern) { + infoRec->CacheWidthColor8x8Pattern = 128; + infoRec->CacheHeightColor8x8Pattern = 8; + } + } + } + else { + infoRec->Color8x8PatternFillFlags = 0; + infoRec->SetupForColor8x8PatternFill = NULL; + infoRec->SubsequentColor8x8PatternFillRect = NULL; + infoRec->SubsequentColor8x8PatternFillTrap = NULL; + } + + /**** Color Expansion ****/ + + if (infoRec->SetupForCPUToScreenColorExpandFill && + infoRec->ColorExpandBase && + infoRec->SubsequentCPUToScreenColorExpandFill && + !xf86ReturnOptValBool(options, XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, + FALSE)) { + int dwordsNeeded = pScrn->virtualX; + + infoRec->ColorExpandRange >>= 2; /* convert to DWORDS */ + HaveColorExpansion = TRUE; + + if (infoRec->CPUToScreenColorExpandFillFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X) + dwordsNeeded += 31; + dwordsNeeded = (dwordsNeeded + 31) >> 5; + if (dwordsNeeded > infoRec->ColorExpandRange) + infoRec->CPUToScreenColorExpandFillFlags |= CPU_TRANSFER_BASE_FIXED; + } + else { + infoRec->CPUToScreenColorExpandFillFlags = 0; + infoRec->SetupForCPUToScreenColorExpandFill = NULL; + infoRec->SubsequentCPUToScreenColorExpandFill = NULL; + } + + /**** Scanline Color Expansion ****/ + + if (infoRec->SetupForScanlineCPUToScreenColorExpandFill && + infoRec->SubsequentScanlineCPUToScreenColorExpandFill && + infoRec->SubsequentColorExpandScanline && + infoRec->ScanlineColorExpandBuffers && + (infoRec->NumScanlineColorExpandBuffers > 0) && + !xf86ReturnOptValBool(options, + XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, + FALSE)) { + HaveScanlineColorExpansion = TRUE; + } + else { + infoRec->ScanlineCPUToScreenColorExpandFillFlags = 0; + infoRec->SetupForScanlineCPUToScreenColorExpandFill = NULL; + infoRec->SubsequentScanlineCPUToScreenColorExpandFill = NULL; + infoRec->SubsequentColorExpandScanline = NULL; + } + + /**** Screen to Screen Color Expansion ****/ + + if (infoRec->SetupForScreenToScreenColorExpandFill && + infoRec->SubsequentScreenToScreenColorExpandFill && + !xf86ReturnOptValBool(options, XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, + FALSE)) { + HaveScreenToScreenColorExpandFill = TRUE; + if (!infoRec->CacheColorExpandDensity) + infoRec->CacheColorExpandDensity = 1; + } + else { + infoRec->ScreenToScreenColorExpandFillFlags = 0; + infoRec->SetupForScreenToScreenColorExpandFill = NULL; + infoRec->SubsequentScreenToScreenColorExpandFill = NULL; + } + + /**** Image Writes ****/ + + if (infoRec->SetupForImageWrite && infoRec->ImageWriteBase && + infoRec->SubsequentImageWriteRect && + !xf86ReturnOptValBool(options, XAAOPT_IMAGE_WRITE_RECT, FALSE)) { + + infoRec->ImageWriteRange >>= 2; /* convert to DWORDS */ + if (infoRec->ImageWriteFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->ImageWriteRange = 0; + HaveImageWriteRect = TRUE; + } + else { + infoRec->ImageWriteFlags = 0; + infoRec->SetupForImageWrite = NULL; + infoRec->SubsequentImageWriteRect = NULL; + } + + /**** Scanline Image Writes ****/ + + if (infoRec->SetupForScanlineImageWrite && + infoRec->SubsequentScanlineImageWriteRect && + infoRec->SubsequentImageWriteScanline && + infoRec->ScanlineImageWriteBuffers && + (infoRec->NumScanlineImageWriteBuffers > 0) && + !xf86ReturnOptValBool(options, XAAOPT_SCANLINE_IMAGE_WRITE_RECT, + FALSE)) { + HaveScanlineImageWriteRect = TRUE; + } + else { + infoRec->ScanlineImageWriteFlags = 0; + infoRec->SetupForScanlineImageWrite = NULL; + infoRec->SubsequentScanlineImageWriteRect = NULL; + infoRec->SubsequentImageWriteScanline = NULL; + } + +#ifndef __i386__ + /* XAA makes some unaligned accesses when clipping is not available */ +#define CLIP_FLAGS (LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X) + if (HaveImageWriteRect && + ((infoRec->ImageWriteFlags & CLIP_FLAGS) != CLIP_FLAGS)) { + HaveImageWriteRect = FALSE; + } + if (HaveScanlineImageWriteRect && + ((infoRec->ScanlineImageWriteFlags & CLIP_FLAGS) != CLIP_FLAGS)) { + HaveScanlineImageWriteRect = FALSE; + } +#endif + + if (serverGeneration == 1) { + if (HaveScreenToScreenCopy) + xf86ErrorF("\tScreen to screen bit blits\n"); + if (HaveSolidFillRect) + xf86ErrorF("\tSolid filled rectangles\n"); + if (HaveSolidFillTrap) + xf86ErrorF("\tSolid filled trapezoids\n"); + if (HaveMono8x8PatternFillRect) + xf86ErrorF("\t8x8 mono pattern filled rectangles\n"); + if (HaveMono8x8PatternFillTrap) + xf86ErrorF("\t8x8 mono pattern filled trapezoids\n"); + if (HaveColor8x8PatternFillRect) + xf86ErrorF("\t8x8 color pattern filled rectangles\n"); + if (HaveColor8x8PatternFillTrap) + xf86ErrorF("\t8x8 color pattern filled trapezoids\n"); + + if (HaveColorExpansion) + xf86ErrorF("\tCPU to Screen color expansion\n"); + else if (HaveScanlineColorExpansion) + xf86ErrorF("\tIndirect CPU to Screen color expansion\n"); + + if (HaveScreenToScreenColorExpandFill) + xf86ErrorF("\tScreen to Screen color expansion\n"); + + if (HaveSolidTwoPointLine || HaveSolidBresenhamLine) + xf86ErrorF("\tSolid Lines\n"); + else if (HaveSolidHorVertLine) + xf86ErrorF("\tSolid Horizontal and Vertical Lines\n"); + + if (HaveDashedTwoPointLine || HaveDashedBresenhamLine) + xf86ErrorF("\tDashed Lines\n"); + + if (HaveImageWriteRect) + xf86ErrorF("\tImage Writes\n"); + else if (HaveScanlineImageWriteRect) + xf86ErrorF("\tScanline Image Writes\n"); + + } + +#define XAAMSG(s) do { if (serverGeneration == 1) xf86ErrorF(s); } while (0) + + if ((infoRec->Flags & OFFSCREEN_PIXMAPS) && HaveScreenToScreenCopy && + xf86ReturnOptValBool(options, + XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE, FALSE)) { + XAAMSG("\tOffscreen Pixmaps\n"); + } + else { + infoRec->Flags &= ~OFFSCREEN_PIXMAPS; + } + + /************** Mid Level *************/ + + /**** ScreenToScreenBitBlt ****/ + + if (infoRec->ScreenToScreenBitBlt) { + XAAMSG("\tDriver provided ScreenToScreenBitBlt replacement\n"); + } + else if (HaveScreenToScreenCopy) { + infoRec->ScreenToScreenBitBlt = XAAScreenToScreenBitBlt; + infoRec->ScreenToScreenBitBltFlags = infoRec->ScreenToScreenCopyFlags; + } + + /**** FillSolidRects ****/ + + if (infoRec->FillSolidRects) { + XAAMSG("\tDriver provided FillSolidRects replacement\n"); + } + else if (HaveSolidFillRect) { + infoRec->FillSolidRects = XAAFillSolidRects; + infoRec->FillSolidRectsFlags = infoRec->SolidFillFlags; + } + + /**** FillSolidSpans ****/ + + if (infoRec->FillSolidSpans) { + XAAMSG("\tDriver provided FillSolidSpans replacement\n"); + } + else if (HaveSolidFillRect) { + infoRec->FillSolidSpans = XAAFillSolidSpans; + infoRec->FillSolidSpansFlags = infoRec->SolidFillFlags; + } + + /**** FillMono8x8PatternRects ****/ + + if (infoRec->FillMono8x8PatternRects) { + XAAMSG("\tDriver provided FillMono8x8PatternRects replacement\n"); + } + else if (HaveMono8x8PatternFillRect) { + infoRec->FillMono8x8PatternRects = + (infoRec-> + Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillMono8x8PatternRectsScreenOrigin : XAAFillMono8x8PatternRects; + + infoRec->FillMono8x8PatternRectsFlags = + infoRec->Mono8x8PatternFillFlags; + } + + /**** FillMono8x8PatternSpans ****/ + + if (infoRec->FillMono8x8PatternSpans) { + XAAMSG("\tDriver provided FillMono8x8PatternSpans replacement\n"); + } + else if (HaveMono8x8PatternFillRect) { + infoRec->FillMono8x8PatternSpans = + (infoRec-> + Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillMono8x8PatternSpansScreenOrigin : XAAFillMono8x8PatternSpans; + + infoRec->FillMono8x8PatternSpansFlags = + infoRec->Mono8x8PatternFillFlags; + } + + /**** FillColor8x8Rects ****/ + + if (infoRec->FillColor8x8PatternRects) { + XAAMSG("\tDriver provided FillColor8x8PatternRects replacement\n"); + } + else if (HaveColor8x8PatternFillRect) { + infoRec->FillColor8x8PatternRects = + (infoRec-> + Color8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillColor8x8PatternRectsScreenOrigin : + XAAFillColor8x8PatternRects; + + infoRec->FillColor8x8PatternRectsFlags = + infoRec->Color8x8PatternFillFlags; + } + + /**** FillColor8x8Spans ****/ + + if (infoRec->FillColor8x8PatternSpans) { + XAAMSG("\tDriver provided FillColor8x8PatternSpans replacement\n"); + } + else if (HaveColor8x8PatternFillRect) { + infoRec->FillColor8x8PatternSpans = + (infoRec-> + Color8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillColor8x8PatternSpansScreenOrigin : + XAAFillColor8x8PatternSpans; + + infoRec->FillColor8x8PatternSpansFlags = + infoRec->Color8x8PatternFillFlags; + } + + /**** FillCacheBltRects ****/ + + if (infoRec->FillCacheBltRects) { + XAAMSG("\tDriver provided FillCacheBltRects replacement\n"); + } + else if (HaveScreenToScreenCopy) { + infoRec->FillCacheBltRects = XAAFillCacheBltRects; + infoRec->FillCacheBltRectsFlags = infoRec->ScreenToScreenCopyFlags; + } + + /**** FillCacheBltSpans ****/ + + if (infoRec->FillCacheBltSpans) { + XAAMSG("\tDriver provided FillCacheBltSpans replacement\n"); + } + else if (HaveScreenToScreenCopy) { + infoRec->FillCacheBltSpans = XAAFillCacheBltSpans; + infoRec->FillCacheBltSpansFlags = infoRec->ScreenToScreenCopyFlags; + } + + /**** FillCacheExpandRects ****/ + + if (infoRec->FillCacheExpandRects) { + XAAMSG("\tDriver provided FillCacheExpandRects replacement\n"); + } + else if (HaveScreenToScreenColorExpandFill) { + infoRec->FillCacheExpandRects = XAAFillCacheExpandRects; + infoRec->FillCacheExpandRectsFlags = + infoRec->ScreenToScreenColorExpandFillFlags; + } + + /**** FillCacheExpandSpans ****/ + + if (infoRec->FillCacheExpandSpans) { + XAAMSG("\tDriver provided FillCacheExpandSpans replacement\n"); + } + else if (HaveScreenToScreenColorExpandFill) { + infoRec->FillCacheExpandSpans = XAAFillCacheExpandSpans; + infoRec->FillCacheExpandSpansFlags = + infoRec->ScreenToScreenColorExpandFillFlags; + } + + /**** FillColorExpandRects ****/ + + if (infoRec->FillColorExpandRects) { + XAAMSG("\tDriver provided FillColorExpandRects replacement\n"); + } + else if (HaveColorExpansion) { + if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { + if (infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3MSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3MSBFirst; + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3LSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3LSBFirst; + } + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsMSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsMSBFirst; + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsLSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsLSBFirst; + } + } + infoRec->FillColorExpandRectsFlags = + infoRec->CPUToScreenColorExpandFillFlags; + } + else if (HaveScanlineColorExpansion) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + TRIPLE_BITS_24BPP) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRects3MSBFirst; + else + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRects3LSBFirst; + } + else { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRectsMSBFirst; + else + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRectsLSBFirst; + } + infoRec->FillColorExpandRectsFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + } + + /**** FillColorExpandSpans ****/ + + if (infoRec->FillColorExpandSpans) { + XAAMSG("\tDriver provided FillColorExpandSpans replacement\n"); + } + else if (HaveColorExpansion) { + if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { + if (infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3MSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3MSBFirst; + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3LSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3LSBFirst; + } + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansMSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansMSBFirst; + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansLSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansLSBFirst; + } + } + infoRec->FillColorExpandSpansFlags = + infoRec->CPUToScreenColorExpandFillFlags; + } + else if (HaveScanlineColorExpansion) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + TRIPLE_BITS_24BPP) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpans3MSBFirst; + else + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpans3LSBFirst; + } + else { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpansMSBFirst; + else + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpansLSBFirst; + } + infoRec->FillColorExpandSpansFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + } + + /**** FillImageWriteRects ****/ + + if (infoRec->FillImageWriteRects) { + XAAMSG("\tDriver provided FillImageWriteRects replacement\n"); + } + else if (HaveImageWriteRect && + (infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { + infoRec->FillImageWriteRects = XAAFillImageWriteRects; + infoRec->FillImageWriteRectsFlags = infoRec->ImageWriteFlags; + } + + /**** WriteBitmap ****/ + + if (infoRec->WriteBitmap && + !xf86ReturnOptValBool(options, XAAOPT_WRITE_BITMAP, FALSE)) { + XAAMSG("\tDriver provided WriteBitmap replacement\n"); + } + else if (HaveColorExpansion) { + if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { + if (infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpand3MSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpand3MSBFirst; + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpand3LSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpand3LSBFirst; + } + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpandMSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpandMSBFirst; + } + else { + if (infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpandLSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpandLSBFirst; + } + } + infoRec->WriteBitmapFlags = infoRec->CPUToScreenColorExpandFillFlags; + } + else if (HaveScanlineColorExpansion) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + TRIPLE_BITS_24BPP) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpand3MSBFirst; + else + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpand3LSBFirst; + } + else { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpandMSBFirst; + else + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpandLSBFirst; + } + infoRec->WriteBitmapFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + } + else + infoRec->WriteBitmap = NULL; + + /**** TE Glyphs ****/ + + if (infoRec->TEGlyphRenderer) { + XAAMSG("\tDriver provided TEGlyphRenderer replacement\n"); + } + else if (HaveColorExpansion) { + infoRec->TEGlyphRendererFlags = + infoRec->CPUToScreenColorExpandFillFlags; + + if (infoRec->TEGlyphRendererFlags & TRIPLE_BITS_24BPP) { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRenderer3MSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRenderer3MSBFirst; + } + else { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRenderer3LSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRenderer3LSBFirst; + } + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & RGB_EQUAL)) { + infoRec->TEGlyphRendererFlags &= ~RGB_EQUAL; + XAAMSG("WARNING: TEGlyphRenderer cannot support RGB_EQUAL" + " without solid fills\n"); + } + } + else { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRendererMSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererMSBFirst; + } + else { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRendererLSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererLSBFirst; + } + } + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + infoRec->TEGlyphRendererFlags &= ~TRANSPARENCY_ONLY; + XAAMSG("WARNING: TEGlyphRenderer cannot support TRANPARENCY_ONLY" + " without solid fills\n"); + } + + } + else if (HaveScanlineColorExpansion) { + infoRec->TEGlyphRendererFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + + if (infoRec->TEGlyphRendererFlags & TRIPLE_BITS_24BPP) { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanline3MSBFirst; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanline3LSBFirst; + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & RGB_EQUAL)) { + infoRec->TEGlyphRendererFlags &= ~RGB_EQUAL; + XAAMSG("WARNING: TEGlyphRenderer cannot support RGB_EQUAL" + " without solid fills\n"); + } + } + else { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanlineMSBFirst; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanlineLSBFirst; + } + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + infoRec->TEGlyphRendererFlags &= ~TRANSPARENCY_ONLY; + XAAMSG("WARNING: TEGlyphRenderer cannot support TRANPARENCY_ONLY" + " without solid fills\n"); + } + } + + /**** NonTE Glyphs ****/ + + if (infoRec->NonTEGlyphRenderer) { + XAAMSG("\tDriver provided NonTEGlyphRenderer replacement\n"); + } + else if (infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { + infoRec->NonTEGlyphRenderer = XAANonTEGlyphRenderer; + infoRec->NonTEGlyphRendererFlags = infoRec->WriteBitmapFlags; + } + + /**** WritePixmap ****/ + + if (infoRec->WritePixmap && + !xf86ReturnOptValBool(options, XAAOPT_WRITE_PIXMAP, FALSE)) { + XAAMSG("\tDriver provided WritePixmap replacement\n"); + } + else if (HaveImageWriteRect) { + infoRec->WritePixmap = XAAWritePixmap; + infoRec->WritePixmapFlags = + infoRec->ImageWriteFlags | CONVERT_32BPP_TO_24BPP; + } + else if (HaveScanlineImageWriteRect) { + infoRec->WritePixmap = XAAWritePixmapScanline; + infoRec->WritePixmapFlags = infoRec->ScanlineImageWriteFlags; + } + else + infoRec->WritePixmap = NULL; + + /**** ReadPixmap ****/ + + if (infoRec->ReadPixmap) { + XAAMSG("\tDriver provided ReadPixmap replacement\n"); + } + + /************** GC Level *************/ + + /**** CopyArea ****/ + + if (infoRec->CopyArea) { + XAAMSG("\tDriver provided GC level CopyArea replacement\n"); + } + else if (infoRec->ScreenToScreenBitBlt) { + infoRec->CopyArea = XAACopyArea; + infoRec->CopyAreaFlags = infoRec->ScreenToScreenBitBltFlags; + + /* most GC level primitives use one mid-level primitive so + the GC level primitive gets the mid-level primitive flag + and we use that at GC validation time. But CopyArea uses + more than one mid-level primitive so we have to essentially + do a GC validation every time that primitive is used. + The CopyAreaFlags would only be used for filtering out the + common denominators. Here we assume that if you don't do + ScreenToScreenBitBlt you aren't going to do the others. + We also assume that ScreenToScreenBitBlt has the least + restrictions. */ + } + + if (infoRec->CopyPlane) { + XAAMSG("\tDriver provided GC level CopyPlane replacement\n"); + } + else if (infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) { + infoRec->CopyPlane = XAACopyPlaneColorExpansion; + infoRec->CopyPlaneFlags = infoRec->WriteBitmapFlags; + } + + if (infoRec->PushPixelsSolid) { + XAAMSG("\tDriver provided GC level PushPixelsSolid replacement\n"); + } + else if (infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { + infoRec->PushPixelsSolid = XAAPushPixelsSolidColorExpansion; + infoRec->PushPixelsFlags = infoRec->WriteBitmapFlags; + } + + if (infoRec->FillSolidRects) { + if (!infoRec->PolyFillRectSolid) { + infoRec->PolyFillRectSolid = XAAPolyFillRect; + infoRec->PolyFillRectSolidFlags = infoRec->FillSolidRectsFlags; + } + } + if (infoRec->FillSolidSpans) { + if (!infoRec->FillSpansSolid) { + infoRec->FillSpansSolid = XAAFillSpans; + infoRec->FillSpansSolidFlags = infoRec->FillSolidSpansFlags; + } + } + + if (infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || + infoRec->FillCacheBltRects || infoRec->FillColorExpandRects || + infoRec->FillCacheExpandRects) { + if (!infoRec->PolyFillRectStippled) { + + infoRec->PolyFillRectStippled = XAAPolyFillRect; + infoRec->PolyFillRectStippledFlags = 0; + } + } + + if (infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || + infoRec->FillCacheBltSpans || infoRec->FillColorExpandSpans || + infoRec->FillCacheExpandSpans) { + if (!infoRec->FillSpansStippled) { + + infoRec->FillSpansStippled = XAAFillSpans; + infoRec->FillSpansStippledFlags = 0; + } + } + + if (infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || + infoRec->FillCacheBltRects || infoRec->FillColorExpandRects || + infoRec->FillCacheExpandRects) { + if (!infoRec->PolyFillRectOpaqueStippled) { + + infoRec->PolyFillRectOpaqueStippled = XAAPolyFillRect; + infoRec->PolyFillRectOpaqueStippledFlags = 0; + } + } + + if (infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || + infoRec->FillCacheBltSpans || infoRec->FillColorExpandSpans || + infoRec->FillCacheExpandSpans) { + if (!infoRec->FillSpansOpaqueStippled) { + + infoRec->FillSpansOpaqueStippled = XAAFillSpans; + infoRec->FillSpansOpaqueStippledFlags = 0; + } + } + + if (infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || + infoRec->FillCacheBltRects || infoRec->FillImageWriteRects) { + if (!infoRec->PolyFillRectTiled) { + + infoRec->PolyFillRectTiled = XAAPolyFillRect; + infoRec->PolyFillRectTiledFlags = 0; + } + } + + if (infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || + infoRec->FillCacheBltSpans) { + if (!infoRec->FillSpansTiled) { + + infoRec->FillSpansTiled = XAAFillSpans; + infoRec->FillSpansTiledFlags = 0; + } + } + + if (infoRec->TEGlyphRenderer && + !(infoRec->TEGlyphRendererFlags & NO_TRANSPARENCY)) { + + if (!infoRec->PolyText8TE) { + infoRec->PolyText8TE = XAAPolyText8TEColorExpansion; + infoRec->PolyText8TEFlags = infoRec->TEGlyphRendererFlags; + } + + if (!infoRec->PolyText16TE) { + infoRec->PolyText16TE = XAAPolyText16TEColorExpansion; + infoRec->PolyText16TEFlags = infoRec->TEGlyphRendererFlags; + } + + if (!infoRec->PolyGlyphBltTE) { + infoRec->PolyGlyphBltTE = XAAPolyGlyphBltTEColorExpansion; + infoRec->PolyGlyphBltTEFlags = infoRec->TEGlyphRendererFlags; + } + } + + if (infoRec->TEGlyphRenderer && + !(infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + + if (!infoRec->ImageText8TE) { + infoRec->ImageText8TE = XAAImageText8TEColorExpansion; + infoRec->ImageText8TEFlags = infoRec->TEGlyphRendererFlags; + } + + if (!infoRec->ImageText16TE) { + infoRec->ImageText16TE = XAAImageText16TEColorExpansion; + infoRec->ImageText16TEFlags = infoRec->TEGlyphRendererFlags; + } + + if (!infoRec->ImageGlyphBltTE) { + infoRec->ImageGlyphBltTE = XAAImageGlyphBltTEColorExpansion; + infoRec->ImageGlyphBltTEFlags = infoRec->TEGlyphRendererFlags; + } + } + + if (infoRec->NonTEGlyphRenderer) { + if (!infoRec->PolyText8NonTE) { + infoRec->PolyText8NonTE = XAAPolyText8NonTEColorExpansion; + infoRec->PolyText8NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + + if (!infoRec->PolyText16NonTE) { + infoRec->PolyText16NonTE = XAAPolyText16NonTEColorExpansion; + infoRec->PolyText16NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + if (!infoRec->PolyGlyphBltNonTE) { + infoRec->PolyGlyphBltNonTE = XAAPolyGlyphBltNonTEColorExpansion; + infoRec->PolyGlyphBltNonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + } + + if (infoRec->NonTEGlyphRenderer && HaveSolidFillRect) { + if (!infoRec->ImageText8NonTE) { + infoRec->ImageText8NonTE = XAAImageText8NonTEColorExpansion; + infoRec->ImageText8NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + + if (!infoRec->ImageText16NonTE) { + infoRec->ImageText16NonTE = XAAImageText16NonTEColorExpansion; + infoRec->ImageText16NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + + if (!infoRec->ImageGlyphBltNonTE) { + infoRec->ImageGlyphBltNonTE = XAAImageGlyphBltNonTEColorExpansion; + infoRec->ImageGlyphBltNonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + } + + if (!infoRec->PolyRectangleThinSolid && HaveSolidHorVertLine) { + infoRec->PolyRectangleThinSolid = XAAPolyRectangleThinSolid; + infoRec->PolyRectangleThinSolidFlags = infoRec->SolidLineFlags; + } + + if (!infoRec->FillPolygonSolid && HaveSolidFillRect) { + infoRec->FillPolygonSolid = XAAFillPolygonSolid; + infoRec->FillPolygonSolidFlags = infoRec->SolidFillFlags; + } + + if (!infoRec->FillPolygonStippled && (HaveMono8x8PatternFillRect || + HaveScreenToScreenColorExpandFill || + HaveScreenToScreenCopy)) { + infoRec->FillPolygonStippled = XAAFillPolygonStippled; + infoRec->FillPolygonStippledFlags = infoRec->SolidFillFlags; + } + + if (!infoRec->FillPolygonOpaqueStippled && (HaveMono8x8PatternFillRect || + HaveScreenToScreenColorExpandFill + || HaveScreenToScreenCopy)) { + infoRec->FillPolygonOpaqueStippled = XAAFillPolygonStippled; + infoRec->FillPolygonOpaqueStippledFlags = infoRec->SolidFillFlags; + } + + if (!infoRec->FillPolygonTiled && (HaveMono8x8PatternFillRect || + HaveScreenToScreenColorExpandFill || + HaveScreenToScreenCopy)) { + infoRec->FillPolygonTiled = XAAFillPolygonTiled; + infoRec->FillPolygonTiledFlags = infoRec->SolidFillFlags; + } + + if (!infoRec->PolyFillArcSolid && HaveSolidFillRect) { + infoRec->PolyFillArcSolid = XAAPolyFillArcSolid; + infoRec->PolyFillArcSolidFlags = infoRec->SolidFillFlags; + } + + if (!infoRec->PolylinesWideSolid && HaveSolidFillRect) { + infoRec->PolylinesWideSolid = XAAPolylinesWideSolid; + infoRec->PolylinesWideSolidFlags = + infoRec->SolidFillFlags | GXCOPY_ONLY; + } + + if (!infoRec->PutImage && (infoRec->WritePixmap || + (infoRec->WriteBitmap && + !(infoRec-> + WriteBitmapFlags & TRANSPARENCY_ONLY)))) { + infoRec->PutImage = XAAPutImage; + + /* See comment for CopyArea above. But here we make fewer + assumptions. The driver can provide the PutImageFlags if + it wants too */ + } + + if (HaveSolidHorVertLine && + (HaveSolidBresenhamLine || (HaveSolidTwoPointLine && + (infoRec-> + ClippingFlags & + HARDWARE_CLIP_SOLID_LINE)))) { + if (!infoRec->PolylinesThinSolid) { + infoRec->PolylinesThinSolid = XAAPolyLines; + infoRec->PolylinesThinSolidFlags = infoRec->SolidLineFlags; + } + if (!infoRec->PolySegmentThinSolid) { + infoRec->PolySegmentThinSolid = XAAPolySegment; + infoRec->PolySegmentThinSolidFlags = infoRec->SolidLineFlags; + } + } + + if (HaveDashedBresenhamLine || (HaveDashedTwoPointLine && + (infoRec-> + ClippingFlags & + HARDWARE_CLIP_DASHED_LINE))) { + if (!infoRec->PolylinesThinDashed) { + infoRec->PolylinesThinDashed = XAAPolyLinesDashed; + infoRec->PolylinesThinDashedFlags = infoRec->DashedLineFlags; + } + if (!infoRec->PolySegmentThinDashed) { + infoRec->PolySegmentThinDashed = XAAPolySegmentDashed; + infoRec->PolySegmentThinDashedFlags = infoRec->DashedLineFlags; + } + } + + if (infoRec->PolylinesThinDashed || infoRec->PolySegmentThinDashed) { + if (!infoRec->ComputeDash) + infoRec->ComputeDash = XAAComputeDash; + } + + { + Bool haveTexture = infoRec->CPUToScreenTextureFormats && + infoRec->CPUToScreenTextureDstFormats && + infoRec->SetupForCPUToScreenTexture2 && + infoRec->SubsequentCPUToScreenTexture; + Bool haveAlphaTexture = infoRec->CPUToScreenAlphaTextureFormats && + infoRec->CPUToScreenAlphaTextureDstFormats && + infoRec->SetupForCPUToScreenAlphaTexture2 && + infoRec->SubsequentCPUToScreenAlphaTexture; + + if (!infoRec->Composite && (haveTexture || haveAlphaTexture)) + infoRec->Composite = XAADoComposite; + + if (!infoRec->Glyphs && infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { + infoRec->Glyphs = XAADoGlyphs; + } + } + + /************ Validation Functions **************/ + + if (!infoRec->ValidateCopyArea && infoRec->CopyArea) { + infoRec->CopyAreaMask = GCWhenForced; + if ((infoRec->CopyAreaFlags & GXCOPY_ONLY) || + (infoRec->CopyAreaFlags & ROP_NEEDS_SOURCE)) + infoRec->CopyAreaMask |= GCFunction; + if (infoRec->CopyAreaFlags & NO_PLANEMASK) + infoRec->CopyAreaMask |= GCPlaneMask; + infoRec->ValidateCopyArea = XAAValidateCopyArea; + } + + if (!infoRec->ValidateCopyPlane && infoRec->CopyPlane) { + infoRec->CopyPlaneMask = GCWhenForced; + if ((infoRec->CopyPlaneFlags & GXCOPY_ONLY) || + (infoRec->CopyPlaneFlags & ROP_NEEDS_SOURCE)) + infoRec->CopyPlaneMask |= GCFunction; + if (infoRec->CopyPlaneFlags & NO_PLANEMASK) + infoRec->CopyPlaneMask |= GCPlaneMask; + if (infoRec->CopyPlaneFlags & RGB_EQUAL) + infoRec->CopyPlaneMask |= GCForeground | GCBackground; + infoRec->ValidateCopyPlane = XAAValidateCopyPlane; + } + + if (!infoRec->ValidatePutImage && infoRec->PutImage) { + infoRec->PutImageMask = GCWhenForced; + if ((infoRec->PutImageFlags & GXCOPY_ONLY) || + (infoRec->PutImageFlags & ROP_NEEDS_SOURCE)) + infoRec->PutImageMask |= GCFunction; + if (infoRec->PutImageFlags & NO_PLANEMASK) + infoRec->PutImageMask |= GCPlaneMask; + if (infoRec->PutImageFlags & RGB_EQUAL) + infoRec->PutImageMask |= GCForeground | GCBackground; + infoRec->ValidatePutImage = XAAValidatePutImage; + } + + if (!infoRec->ValidatePushPixels && infoRec->PushPixelsSolid) { + infoRec->PushPixelsMask = GCFillStyle; + if ((infoRec->PushPixelsFlags & GXCOPY_ONLY) || + (infoRec->PushPixelsFlags & ROP_NEEDS_SOURCE) || + (infoRec->PushPixelsFlags & TRANSPARENCY_GXCOPY_ONLY)) + infoRec->PushPixelsMask |= GCFunction; + if (infoRec->PushPixelsFlags & NO_PLANEMASK) + infoRec->PushPixelsMask |= GCPlaneMask; + if (infoRec->PushPixelsFlags & RGB_EQUAL) + infoRec->PushPixelsMask |= GCForeground; + infoRec->ValidatePushPixels = XAAValidatePushPixels; + } + + /* By default XAA assumes the FillSpans, PolyFillRects, FillPolygon + and PolyFillArcs have the same restrictions. If you supply GC + level replacements for any of these and alter this relationship + you may need to supply replacement validation routines */ + + if (!infoRec->ValidateFillSpans && + (infoRec->FillSpansSolid || infoRec->FillSpansStippled || + infoRec->FillSpansOpaqueStippled || infoRec->FillSpansTiled)) { + + int compositeFlags = infoRec->FillSpansSolidFlags | + infoRec->FillSpansStippledFlags | + infoRec->FillSpansOpaqueStippledFlags | + infoRec->FillSpansTiledFlags; + + infoRec->FillSpansMask = GCFillStyle | GCTile | GCStipple; + + if ((compositeFlags & GXCOPY_ONLY) || + (compositeFlags & ROP_NEEDS_SOURCE)) + infoRec->FillSpansMask |= GCFunction; + if (compositeFlags & NO_PLANEMASK) + infoRec->FillSpansMask |= GCPlaneMask; + if (compositeFlags & RGB_EQUAL) + infoRec->FillSpansMask |= GCForeground; + infoRec->ValidateFillSpans = XAAValidateFillSpans; + } + + /* By default XAA only provides Validations for the GlyphBlt + functions and not the text higher up. This is because the + Text8/16 and GlyphBlt are linked. If you break this linkage, + you may need to have the driver supply its own Validation + routines */ + + if (!infoRec->ValidatePolyGlyphBlt && + (infoRec->PolyGlyphBltTE || infoRec->PolyGlyphBltNonTE)) { + int compositeFlags = infoRec->PolyGlyphBltTEFlags | + infoRec->PolyGlyphBltNonTEFlags; + + infoRec->PolyGlyphBltMask = GCFillStyle | GCFont; + if ((compositeFlags & GXCOPY_ONLY) || + (compositeFlags & ROP_NEEDS_SOURCE) || + (infoRec->PolyGlyphBltNonTEFlags & TRANSPARENCY_GXCOPY_ONLY)) + infoRec->PolyGlyphBltMask |= GCFunction; + if (compositeFlags & NO_PLANEMASK) + infoRec->PolyGlyphBltMask |= GCPlaneMask; + if (compositeFlags & RGB_EQUAL) + infoRec->PolyGlyphBltMask |= GCForeground; + infoRec->ValidatePolyGlyphBlt = XAAValidatePolyGlyphBlt; + } + + if (!infoRec->ValidateImageGlyphBlt && + (infoRec->ImageGlyphBltTE || infoRec->ImageGlyphBltNonTE)) { + int compositeFlags = infoRec->ImageGlyphBltTEFlags | + infoRec->ImageGlyphBltNonTEFlags; + + if (infoRec->ImageGlyphBltNonTE) + compositeFlags |= infoRec->SolidFillFlags; + + infoRec->ImageGlyphBltMask = GCFont; + if (compositeFlags & NO_PLANEMASK) + infoRec->ImageGlyphBltMask |= GCPlaneMask; + if (compositeFlags & RGB_EQUAL) + infoRec->ImageGlyphBltMask |= GCForeground | GCBackground; + infoRec->ValidateImageGlyphBlt = XAAValidateImageGlyphBlt; + } + + /* By default XAA only provides a Validation function for the + Polylines and does segments and polylines at the same time */ + + if (!infoRec->ValidatePolylines && infoRec->ValidateFillSpans) { + int compositeFlags = infoRec->PolyRectangleThinSolidFlags | + infoRec->PolylinesWideSolidFlags | + infoRec->PolylinesThinSolidFlags | + infoRec->PolySegmentThinSolidFlags | + infoRec->PolySegmentThinDashedFlags | + infoRec->PolylinesThinDashedFlags; + + infoRec->ValidatePolylines = XAAValidatePolylines; + infoRec->PolylinesMask = + infoRec->FillSpansMask | GCLineStyle | GCLineWidth; + + if (infoRec->PolySegmentThinDashed || infoRec->PolylinesThinDashed) + infoRec->PolylinesMask |= GCDashList; + if (compositeFlags & NO_PLANEMASK) + infoRec->PolylinesMask |= GCPlaneMask; + if ((compositeFlags & GXCOPY_ONLY) || + (compositeFlags & ROP_NEEDS_SOURCE)) + infoRec->PolylinesMask |= GCFunction; + if (compositeFlags & RGB_EQUAL) + infoRec->PolylinesMask |= GCForeground; + } + + /**** Fill choosers ****/ + + if (!infoRec->StippledFillChooser) + infoRec->StippledFillChooser = XAAStippledFillChooser; + + if (!infoRec->OpaqueStippledFillChooser) + infoRec->OpaqueStippledFillChooser = XAAOpaqueStippledFillChooser; + + if (!infoRec->TiledFillChooser) + infoRec->TiledFillChooser = XAATiledFillChooser; + + /**** Setup the pixmap cache ****/ + + if (infoRec->WriteBitmapToCache) { + } + else if (infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) + infoRec->WriteBitmapToCache = XAAWriteBitmapToCache; + else if (infoRec->Flags & LINEAR_FRAMEBUFFER) + infoRec->WriteBitmapToCache = XAAWriteBitmapToCacheLinear; + else + infoRec->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES; + + if (infoRec->WritePixmapToCache) { + } + else if (infoRec->WritePixmap && !(infoRec->WritePixmapFlags & NO_GXCOPY)) + infoRec->WritePixmapToCache = XAAWritePixmapToCache; + else if (infoRec->Flags & LINEAR_FRAMEBUFFER) + infoRec->WritePixmapToCache = XAAWritePixmapToCacheLinear; + else + infoRec->Flags &= ~PIXMAP_CACHE; + + if (xf86ReturnOptValBool(options, XAAOPT_PIXMAP_CACHE, FALSE)) + infoRec->Flags &= ~PIXMAP_CACHE; + + if (infoRec->WriteMono8x8PatternToCache) { + } + else if (infoRec->PixmapCacheFlags & CACHE_MONO_8x8) { + if (infoRec->WritePixmapToCache) + infoRec->WriteMono8x8PatternToCache = XAAWriteMono8x8PatternToCache; + else + infoRec->PixmapCacheFlags &= ~CACHE_MONO_8x8; + } + + if (infoRec->WriteColor8x8PatternToCache) { + } + else if (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8) { + if (infoRec->WritePixmapToCache && infoRec->WriteBitmapToCache) + infoRec->WriteColor8x8PatternToCache = + XAAWriteColor8x8PatternToCache; + else + infoRec->PixmapCacheFlags &= ~CACHE_COLOR_8x8; + } + + if (infoRec->CachePixelGranularity < 0) { + switch (pScrn->bitsPerPixel) { + case 24: + case 8: + infoRec->CachePixelGranularity = 4; + break; + case 16: + infoRec->CachePixelGranularity = 2; + break; + case 32: + infoRec->CachePixelGranularity = 1; + break; + default: + break; + } + + if (BITMAP_SCANLINE_PAD == 64) + infoRec->CachePixelGranularity *= 2; + } + + free(options); + + if (!infoRec->CacheTile && infoRec->WritePixmapToCache) + infoRec->CacheTile = XAACacheTile; + if (!infoRec->CacheMonoStipple && infoRec->WritePixmapToCache) + infoRec->CacheMonoStipple = XAACacheMonoStipple; + if (!infoRec->CacheStipple && infoRec->WriteBitmapToCache) + infoRec->CacheStipple = XAACacheStipple; + if (!infoRec->CacheMono8x8Pattern && infoRec->WriteMono8x8PatternToCache) + infoRec->CacheMono8x8Pattern = XAACacheMono8x8Pattern; + if (!infoRec->CacheColor8x8Pattern && infoRec->WriteColor8x8PatternToCache) + infoRec->CacheColor8x8Pattern = XAACacheColor8x8Pattern; + + if ((infoRec->Flags & PIXMAP_CACHE) && !infoRec->InitPixmapCache) { + infoRec->InitPixmapCache = XAAInitPixmapCache; + infoRec->ClosePixmapCache = XAAClosePixmapCache; + } + + return TRUE; +} diff --git a/hw/xfree86/xaa/xaaLine.c b/hw/xfree86/xaa/xaaLine.c new file mode 100644 index 000000000..d7c60975e --- /dev/null +++ b/hw/xfree86/xaa/xaaLine.c @@ -0,0 +1,422 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "miline.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +void +#ifdef POLYSEGMENT + XAAPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg +#else +XAAPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode, /* Origin or Previous */ + int npt, /* number of points */ + DDXPointPtr pptInit +#endif + ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + BoxPtr pboxInit = RegionRects(pGC->pCompositeClip); + int nboxInit = RegionNumRects(pGC->pCompositeClip); + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + int xorg = pDrawable->x; + int yorg = pDrawable->y; + int nbox; + BoxPtr pbox; + +#ifndef POLYSEGMENT + DDXPointPtr ppt; +#endif + int x1, x2, y1, y2, tmp, len; + + if (!nboxInit) + return; + + if (infoRec->SolidLineFlags & LINE_LIMIT_COORDS) { + int minValX = infoRec->SolidLineLimits.x1; + int maxValX = infoRec->SolidLineLimits.x2; + int minValY = infoRec->SolidLineLimits.y1; + int maxValY = infoRec->SolidLineLimits.y2; + +#ifdef POLYSEGMENT + int n = nseg; + xSegment *s = pSeg; + + while (n--) +#else + int n = npt; + int xorgtmp = xorg; + int yorgtmp = yorg; + + ppt = pptInit; + x2 = ppt->x + xorgtmp; + y2 = ppt->y + yorgtmp; + while (--n) +#endif + { +#ifdef POLYSEGMENT + x1 = s->x1 + xorg; + y1 = s->y1 + yorg; + x2 = s->x2 + xorg; + y2 = s->y2 + yorg; + s++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) { + xorgtmp = x1; + yorgtmp = y1; + } + x2 = ppt->x + xorgtmp; + y2 = ppt->y + yorgtmp; +#endif + if (x1 > maxValX || x1 < minValX || + x2 > maxValX || x2 < minValX || + y1 > maxValY || y1 < minValY || y2 > maxValY || y2 < minValY) { +#ifdef POLYSEGMENT + XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg); +#else + XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit); +#endif + return; + } + } + } + + (*infoRec->SetupForSolidLine) (infoRec->pScrn, pGC->fgPixel, + pGC->alu, pGC->planemask); + +#ifdef POLYSEGMENT + while (nseg--) +#else + ppt = pptInit; + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; + while (--npt) +#endif + { + nbox = nboxInit; + pbox = pboxInit; + +#ifdef POLYSEGMENT + x1 = pSeg->x1 + xorg; + y1 = pSeg->y1 + yorg; + x2 = pSeg->x2 + xorg; + y2 = pSeg->y2 + yorg; + pSeg++; +#else + x1 = x2; + y1 = y2; + ++ppt; + if (mode == CoordModePrevious) { + xorg = x1; + yorg = y1; + } + x2 = ppt->x + xorg; + y2 = ppt->y + yorg; +#endif + + if (x1 == x2) { /* vertical line */ + /* make the line go top to bottom of screen, keeping + endpoint semantics + */ + if (y1 > y2) { + tmp = y2; + y2 = y1 + 1; + y1 = tmp + 1; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + y1--; +#endif + } +#ifdef POLYSEGMENT + else if (pGC->capStyle != CapNotLast) + y2++; +#endif + /* get to first band that might contain part of line */ + while (nbox && (pbox->y2 <= y1)) { + pbox++; + nbox--; + } + + /* stop when lower edge of box is beyond end of line */ + while (nbox && (y2 >= pbox->y1)) { + if ((x1 >= pbox->x1) && (x1 < pbox->x2)) { + tmp = max(y1, pbox->y1); + len = min(y2, pbox->y2) - tmp; + if (len) + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, + x1, tmp, len, + DEGREES_270); + } + nbox--; + pbox++; + } +#ifndef POLYSEGMENT + y2 = ppt->y + yorg; +#endif + } + else if (y1 == y2) { /* horizontal line */ + /* force line from left to right, keeping endpoint semantics */ + if (x1 > x2) { + tmp = x2; + x2 = x1 + 1; + x1 = tmp + 1; +#ifdef POLYSEGMENT + if (pGC->capStyle != CapNotLast) + x1--; +#endif + } +#ifdef POLYSEGMENT + else if (pGC->capStyle != CapNotLast) + x2++; +#endif + + /* find the correct band */ + while (nbox && (pbox->y2 <= y1)) { + pbox++; + nbox--; + } + + /* try to draw the line, if we haven't gone beyond it */ + if (nbox && (pbox->y1 <= y1)) { + int orig_y = pbox->y1; + + /* when we leave this band, we're done */ + while (nbox && (orig_y == pbox->y1)) { + if (pbox->x2 <= x1) { + /* skip boxes until one might contain start point */ + nbox--; + pbox++; + continue; + } + + /* stop if left of box is beyond right of line */ + if (pbox->x1 >= x2) { + nbox = 0; + break; + } + + tmp = max(x1, pbox->x1); + len = min(x2, pbox->x2) - tmp; + if (len) + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, + tmp, y1, len, + DEGREES_0); + nbox--; + pbox++; + } + } +#ifndef POLYSEGMENT + x2 = ppt->x + xorg; +#endif + } + else { /* sloped line */ + unsigned int oc1, oc2; + int dmin, dmaj, e, octant; + + if (infoRec->SubsequentSolidBresenhamLine) { + if ((dmaj = x2 - x1) < 0) { + dmaj = -dmaj; + octant = XDECREASING; + } + else + octant = 0; + + if ((dmin = y2 - y1) < 0) { + dmin = -dmin; + octant |= YDECREASING; + } + + if (dmin >= dmaj) { + tmp = dmin; + dmin = dmaj; + dmaj = tmp; + octant |= YMAJOR; + } + + e = -dmaj - ((bias >> octant) & 1); + len = dmaj; + dmin <<= 1; + dmaj <<= 1; + } + else { /* Muffle compiler */ + dmin = dmaj = e = octant = len = 0; + } + + while (nbox--) { + oc1 = oc2 = 0; + OUTCODES(oc1, x1, y1, pbox); + OUTCODES(oc2, x2, y2, pbox); + if (!(oc1 | oc2)) { /* unclipped */ + if (infoRec->SubsequentSolidTwoPointLine) { + (*infoRec->SubsequentSolidTwoPointLine) (infoRec->pScrn, + x1, y1, x2, y2, +#ifdef POLYSEGMENT + (pGC-> + capStyle != + CapNotLast) ? + 0 : +#endif + OMIT_LAST); + } + else { + (*infoRec->SubsequentSolidBresenhamLine) (infoRec-> + pScrn, x1, y1, + dmaj, dmin, e, +#ifdef POLYSEGMENT + (pGC-> + capStyle != + CapNotLast) + ? (len + 1) : +#endif + len, octant); + } + break; + } + else if (oc1 & oc2) { /* completely clipped */ + pbox++; + } + else if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE) { + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x2 - 1, + pbox->y2 - 1); + + if (infoRec->SubsequentSolidBresenhamLine) { + (*infoRec->SubsequentSolidBresenhamLine) (infoRec-> + pScrn, x1, y1, + dmaj, dmin, e, +#ifdef POLYSEGMENT + (pGC-> + capStyle != + CapNotLast) + ? (len + 1) : +#endif + len, octant); + } + else { + (*infoRec->SubsequentSolidTwoPointLine) (infoRec->pScrn, + x1, y1, x2, y2, +#ifdef POLYSEGMENT + (pGC-> + capStyle != + CapNotLast) ? + 0 : +#endif + OMIT_LAST); + } + (*infoRec->DisableClipping) (infoRec->pScrn); + pbox++; + } + else { + int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2; + int clip1 = 0, clip2 = 0; + int err, adx, ady; + + if (octant & YMAJOR) { + ady = dmaj >> 1; + adx = dmin >> 1; + } + else { + ady = dmin >> 1; + adx = dmaj >> 1; + } + + if (miZeroClipLine(pbox->x1, pbox->y1, + pbox->x2 - 1, pbox->y2 - 1, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, &clip1, &clip2, + octant, bias, oc1, oc2) == -1) { + pbox++; + continue; + } + + if (octant & YMAJOR) + len = abs(new_y2 - new_y1); + else + len = abs(new_x2 - new_x1); +#ifdef POLYSEGMENT + if (clip2 != 0 || pGC->capStyle != CapNotLast) + len++; +#else + len += (clip2 != 0); +#endif + if (len) { + int abserr, clipdx, clipdy; + + /* unwind bresenham error term to first point */ + if (clip1) { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + + if (octant & YMAJOR) + err = e + clipdy * dmin - clipdx * dmaj; + else + err = e + clipdx * dmin - clipdy * dmaj; + } + else + err = e; + +#define range infoRec->SolidBresenhamLineErrorTermBits + abserr = abs(err); + while ((abserr & range) || + (dmaj & range) || (dmin & range)) { + dmin >>= 1; + dmaj >>= 1; + abserr >>= 1; + err /= 2; + } + + (*infoRec->SubsequentSolidBresenhamLine) (infoRec-> + pScrn, new_x1, + new_y1, dmaj, + dmin, err, + len, octant); + } + pbox++; + } + } /* while (nbox--) */ + } /* sloped line */ + } /* while (nline--) */ + +#ifndef POLYSEGMENT + /* paint the last point if the end style isn't CapNotLast. + (Assume that a projecting, butt, or round cap that is one + pixel wide is the same as the single pixel of the endpoint.) + */ + + if ((pGC->capStyle != CapNotLast) && + ((ppt->x + xorg != pptInit->x + pDrawable->x) || + (ppt->y + yorg != pptInit->y + pDrawable->y) || + (ppt == pptInit + 1))) { + nbox = nboxInit; + pbox = pboxInit; + while (nbox--) { + if ((x2 >= pbox->x1) && (y2 >= pbox->y1) && + (x2 < pbox->x2) && (y2 < pbox->y2)) { + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, x2, y2, + 1, DEGREES_0); + break; + } + else + pbox++; + } + } +#endif + + SET_SYNC_FLAG(infoRec); +} diff --git a/hw/xfree86/xaa/xaaLineMisc.c b/hw/xfree86/xaa/xaaLineMisc.c new file mode 100644 index 000000000..4379778f6 --- /dev/null +++ b/hw/xfree86/xaa/xaaLineMisc.c @@ -0,0 +1,149 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "miline.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +void +XAASolidHorVertLineAsRects(ScrnInfoPtr pScrn, int x, int y, int len, int dir) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + if (dir == DEGREES_0) + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, len, 1); + else + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, 1, len); +} + +void +XAASolidHorVertLineAsTwoPoint(ScrnInfoPtr pScrn, int x, int y, int len, int dir) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + len--; + + if (dir == DEGREES_0) + (*infoRec->SubsequentSolidTwoPointLine) (pScrn, x, y, x + len, y, 0); + else + (*infoRec->SubsequentSolidTwoPointLine) (pScrn, x, y, x, y + len, 0); +} + +void +XAASolidHorVertLineAsBresenham(ScrnInfoPtr pScrn, + int x, int y, int len, int dir) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + if (dir == DEGREES_0) + (*infoRec->SubsequentSolidBresenhamLine) (pScrn, x, y, len << 1, 0, + -len, len, 0); + else + (*infoRec->SubsequentSolidBresenhamLine) (pScrn, x, y, len << 1, 0, + -len, len, YMAJOR); +} + +void +XAAComputeDash(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAGCPtr pGCPriv = (XAAGCPtr) dixLookupPrivate(&pGC->devPrivates, + XAAGetGCKey()); + Bool EvenDash = (pGC->numInDashList & 0x01) ? FALSE : TRUE; + int PatternLength = 0; + unsigned char *DashPtr = (unsigned char *) pGC->dash; + CARD32 *ptr; + int count = pGC->numInDashList; + int shift, value, direction; + Bool set; + + free(pGCPriv->DashPattern); + + pGCPriv->DashPattern = NULL; + pGCPriv->DashLength = 0; + + while (count--) + PatternLength += *(DashPtr++); + + if (!EvenDash) + PatternLength <<= 1; + + if (PatternLength > infoRec->DashPatternMaxLength) + return; + + if ((infoRec->DashedLineFlags & LINE_PATTERN_POWER_OF_2_ONLY) && + (PatternLength & (PatternLength - 1))) + return; + + pGCPriv->DashPattern = calloc((PatternLength + 31) >> 5, 4); + if (!pGCPriv->DashPattern) + return; + pGCPriv->DashLength = PatternLength; + + if (infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | + LINE_PATTERN_LSBFIRST_LSBJUSTIFIED)) { + direction = 1; + set = TRUE; + DashPtr = (unsigned char *) pGC->dash; + } + else { + direction = -1; + set = FALSE; + DashPtr = (unsigned char *) pGC->dash + pGC->numInDashList - 1; + } + + if (infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | + LINE_PATTERN_MSBFIRST_MSBJUSTIFIED)) + shift = 32 - (PatternLength & 31); + else + shift = 0; + + ptr = (CARD32 *) (pGCPriv->DashPattern); + + CONCATENATE: + + count = pGC->numInDashList; + + while (count--) { + value = *DashPtr; + DashPtr += direction; + while (value) { + if (value < (32 - shift)) { + if (set) + *ptr |= XAAShiftMasks[value] << shift; + shift += value; + break; + } + else { + if (set) + *ptr |= ~0L << shift; + value -= (32 - shift); + shift = 0; + ptr++; + } + } + if (set) + set = FALSE; + else + set = TRUE; + } + + if (!EvenDash) { + EvenDash = TRUE; + if (infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | + LINE_PATTERN_LSBFIRST_LSBJUSTIFIED)) + DashPtr = (unsigned char *) pGC->dash; + else + DashPtr = (unsigned char *) pGC->dash + pGC->numInDashList; + goto CONCATENATE; + } +} diff --git a/hw/xfree86/xaa/xaaNonTEGlyph.c b/hw/xfree86/xaa/xaaNonTEGlyph.c new file mode 100644 index 000000000..bfe7f9a09 --- /dev/null +++ b/hw/xfree86/xaa/xaaNonTEGlyph.c @@ -0,0 +1,192 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xaa.h" +#include "xaalocal.h" +#include "xaacexp.h" +#include "xf86.h" + +/* Not used anymore because the algorithm isn't correct. It doesn't + handle overlapping characters properly */ + +#ifdef TRIPLE_BITS +#define NonTEGlyphFunc EXPNAME(XAANonTEGlyphScanlineFunc3) +#else +#define NonTEGlyphFunc EXPNAME(XAANonTEGlyphScanlineFunc) +#endif + +/******************************************************************** + + Here we have NonTEGlyphRenders for a bunch of different color + expansion types. The driver may provide its own renderer, but + this is the default one which renders using lower-level primitives + exported by the chipset driver. + +********************************************************************/ + +/* Since the dimensions of the text string and the backing rectangle + do not always coincide, it is possible that wBack or wText + may be 0! The NonTEGlyphRender must always check for this. */ + +/* This gets built for MSBFIRST or LSBFIRST with FIXEDBASE or not, + with TRIPLE_BITS or not. A total of 8 versions */ + +/* if the backing rectangle and text are of the same dimensions + then we can draw in one pass */ + +void +#ifdef TRIPLE_BITS + EXPNAME(XAANonTEGlyphRenderer3) ( +#else + EXPNAME(XAANonTEGlyphRenderer) ( +#endif + ScrnInfoPtr pScrn, + int xText, int wText, + int y, int h, int skipleft, int startline, + NonTEGlyphInfo * glyphp, + int fg, int rop, unsigned int planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base = (CARD32 *) infoRec->ColorExpandBase; + +#ifdef TRIPLE_BITS + int dwords = ((3 * wText + 31) >> 5) * h; +#else + int dwords = ((wText + 31) >> 5) * h; +#endif + + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, fg, -1, rop, + planemask); + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, xText, y, wText, h, + 0); + +#ifndef FIXEDBASE +#ifdef TRIPLE_BITS + if ((((3 * wText + 31) >> 5) * h) <= infoRec->ColorExpandRange) +#else + if ((((wText + 31) >> 5) * h) <= infoRec->ColorExpandRange) +#endif + while (h--) + base = NonTEGlyphFunc(base, glyphp, startline++, wText, skipleft); + else +#endif + while (h--) + NonTEGlyphFunc(base, glyphp, startline++, wText, skipleft); + + if ((infoRec->CPUToScreenColorExpandFillFlags & CPU_TRANSFER_PAD_QWORD) && + (dwords & 1)) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + + if (infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +#ifndef FIXEDBASE +/* Scanline version of above gets built for LSBFIRST and MSBFIRST */ + +void +#ifdef TRIPLE_BITS + EXPNAME(XAANonTEGlyphRendererScanline3) ( +#else + EXPNAME(XAANonTEGlyphRendererScanline) ( +#endif + ScrnInfoPtr pScrn, + int xText, int wText, + int y, int h, int skipleft, + int startline, + NonTEGlyphInfo * glyphp, int fg, + int rop, unsigned int planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int bufferNo = 0; + CARD32 *base; + + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, -1, rop, + planemask); + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, xText, y, + wText, h, 0); + + while (h--) { + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + NonTEGlyphFunc(base, glyphp, startline++, wText, skipleft); + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + SET_SYNC_FLAG(infoRec); +} + +#endif + +/******************************************************************** + + Generic NonTE scanline rendering code. + +********************************************************************/ + +CARD32 * +NonTEGlyphFunc(CARD32 *base, + NonTEGlyphInfo * glyphp, int line, int TotalWidth, int skipleft) +{ + CARD32 bits = 0; + int shift = glyphp->width; + + if (skipleft) { + if ((line >= glyphp->firstline) && (line <= glyphp->lastline)) + bits = SHIFT_R(glyphp->bitsp[line], skipleft); + shift -= skipleft; + } + else if ((line >= glyphp->firstline) && (line <= glyphp->lastline)) + bits = glyphp->bitsp[line]; + + while (TotalWidth > 32) { + while (shift < 32) { + glyphp++; + if ((line >= glyphp->firstline) && (line <= glyphp->lastline)) + bits |= SHIFT_L(glyphp->bitsp[line], shift); + shift += glyphp->width; + } +#ifdef TRIPLE_BITS + WRITE_BITS3(bits); +#else + WRITE_BITS(bits); +#endif + shift &= 31; + if (shift && (line >= glyphp->firstline) && (line <= glyphp->lastline)) + bits = SHIFT_R(glyphp->bitsp[line], glyphp->width - shift); + else + bits = 0; + TotalWidth -= 32; + } + + if (TotalWidth) { + TotalWidth -= shift; + while (TotalWidth > 0) { + glyphp++; + if ((line >= glyphp->firstline) && (line <= glyphp->lastline)) + bits |= SHIFT_L(glyphp->bitsp[line], shift); + shift += glyphp->width; + TotalWidth -= glyphp->width; + } +#ifdef TRIPLE_BITS + if (shift >= 22) { + WRITE_BITS3(bits); + } + else if (shift >= 11) { + WRITE_BITS2(bits); + } + else { + WRITE_BITS1(bits); + } +#else + WRITE_BITS(bits); +#endif + } + + return base; +} diff --git a/hw/xfree86/xaa/xaaNonTEText.c b/hw/xfree86/xaa/xaaNonTEText.c new file mode 100644 index 000000000..bbbbc9533 --- /dev/null +++ b/hw/xfree86/xaa/xaaNonTEText.c @@ -0,0 +1,591 @@ + +/******************************************************************** + + In this file we have GC level replacements for PolyText8/16, + ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for NonTE (proportional) + fonts. The idea is that everything in this file is device independent. + The mentioned GCOps are merely wrappers for the + PolyGlyphBltNonTEColorExpansion and ImageGlyphBltNonTEColorExpansion + functions which calculate the boxes containing arbitrarily clipped + text and passes them to the NonTEGlyphRenderer which will usually + be a lower level XAA function which renders these clipped glyphs using + the basic color expansion functions exported by the chipset driver. + The NonTEGlyphRenderer itself may optionally be driver supplied to + facilitate work-arounds/optimizations at a higher level than usual. + + Written by Mark Vojkovich (mvojkovi@ucsd.edu) + +********************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include "scrnintstr.h" +#include "dixfontstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaacexp.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" + +static void ImageGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, + int xInit, int yInit, FontPtr font, + int fg, int bg, unsigned planemask, + RegionPtr cclip, int nglyph, + unsigned char *gBase, + CharInfoPtr * ppci); +static int PolyGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, int xInit, + int yInit, FontPtr font, int fg, + int rop, unsigned planemask, + RegionPtr cclip, int nglyph, + unsigned char *gBase, + CharInfoPtr * ppci); + +/******************************************************************** + + GC level replacements for PolyText8/16 and ImageText8/16 + for NonTE fonts when using color expansion. + +********************************************************************/ + +int +XAAPolyText8NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + int width = 0; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, Linear8Bit, &n, + infoRec->CharInfo); + + if (n) { + width = PolyGlyphBltNonTEColorExpansion(infoRec->pScrn, + x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, + pGC->alu, pGC->planemask, + pGC->pCompositeClip, n, + FONTGLYPHS(pGC->font), + infoRec->CharInfo); + } + + return x + width; +} + +int +XAAPolyText16NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + int width = 0; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, + (FONTLASTROW(pGC->font) == + 0) ? Linear16Bit : TwoD16Bit, &n, + infoRec->CharInfo); + + if (n) { + width = PolyGlyphBltNonTEColorExpansion(infoRec->pScrn, + x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, + pGC->alu, pGC->planemask, + pGC->pCompositeClip, n, + FONTGLYPHS(pGC->font), + infoRec->CharInfo); + } + + return x + width; +} + +void +XAAImageText8NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, char *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, Linear8Bit, &n, + infoRec->CharInfo); + + if (n) + ImageGlyphBltNonTEColorExpansion(infoRec->pScrn, x + pDraw->x, + y + pDraw->y, pGC->font, pGC->fgPixel, + pGC->bgPixel, pGC->planemask, + pGC->pCompositeClip, n, + FONTGLYPHS(pGC->font), + infoRec->CharInfo); +} + +void +XAAImageText16NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, int count, unsigned short *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, + (FONTLASTROW(pGC->font) == + 0) ? Linear16Bit : TwoD16Bit, &n, + infoRec->CharInfo); + + if (n) + ImageGlyphBltNonTEColorExpansion(infoRec->pScrn, x + pDraw->x, + y + pDraw->y, pGC->font, pGC->fgPixel, + pGC->bgPixel, pGC->planemask, + pGC->pCompositeClip, n, + FONTGLYPHS(pGC->font), + infoRec->CharInfo); +} + +/******************************************************************** + + GC level replacements for ImageGlyphBlt and PolyGlyphBlt for + NonTE fonts when using color expansion. + +********************************************************************/ + +void +XAAImageGlyphBltNonTEColorExpansion(DrawablePtr pDraw, GCPtr pGC, int xInit, int yInit, unsigned int nglyph, CharInfoPtr * ppci, /* array of character info */ + void * pglyphBase /* start of array of glyphs */ + ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + ImageGlyphBltNonTEColorExpansion(infoRec->pScrn, xInit + pDraw->x, + yInit + pDraw->y, pGC->font, pGC->fgPixel, + pGC->bgPixel, pGC->planemask, + pGC->pCompositeClip, nglyph, + (unsigned char *) pglyphBase, ppci); +} + +void +XAAPolyGlyphBltNonTEColorExpansion(DrawablePtr pDraw, GCPtr pGC, int xInit, int yInit, unsigned int nglyph, CharInfoPtr * ppci, /* array of character info */ + void * pglyphBase /* start of array of glyphs */ + ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + PolyGlyphBltNonTEColorExpansion(infoRec->pScrn, xInit + pDraw->x, + yInit + pDraw->y, pGC->font, pGC->fgPixel, + pGC->alu, pGC->planemask, + pGC->pCompositeClip, nglyph, + (unsigned char *) pglyphBase, ppci); +} + +/******************************************************************** + + ImageGlyphBltNonTEColorExpansion - + PolyGlyphBltNonTEColorExpansion - + + These guys compute the clipped pieces of text and send it to + the lower-level function which will handle acceleration of + arbitrarily clipped text. + +********************************************************************/ + +static int +CollectCharacterInfo(NonTEGlyphPtr glyphs, + unsigned int nglyph, CharInfoPtr * ppci, FontPtr pfont) +{ + int i, w = 0; + + for (i = 0; i < nglyph; i++, ppci++, glyphs++) { + glyphs->bits = (unsigned char *) ((*ppci)->bits); + glyphs->start = w + (*ppci)->metrics.leftSideBearing; + glyphs->end = w + (*ppci)->metrics.rightSideBearing; + glyphs->yoff = (*ppci)->metrics.ascent; + glyphs->height = glyphs->yoff + (*ppci)->metrics.descent; + glyphs->srcwidth = PADGLYPHWIDTHBYTES(glyphs->end - glyphs->start); + w += (*ppci)->metrics.characterWidth; + } + return w; +} + +static void +PolyGlyphBltAsSingleBitmap(ScrnInfoPtr pScrn, + int nglyph, + FontPtr font, + int xInit, + int yInit, + int nbox, + BoxPtr pbox, int fg, int rop, unsigned planemask) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *block, *pntr, *bits; + int pitch, topLine, botLine, top, bot, height; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge; + int bitPitch, shift, size, i, skippix; + NonTEGlyphPtr glyphs = infoRec->GlyphInfo; + Bool extra; + + Left = xInit + infoRec->GlyphInfo[0].start; + Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; + Top = yInit - FONTMAXBOUNDS(font, ascent); + Bottom = yInit + FONTMAXBOUNDS(font, descent); + + /* get into the first band that may contain part of our string */ + while (nbox && (Top >= pbox->y2)) { + pbox++; + nbox--; + } + + if (!nbox) + return; + + pitch = (Right - Left + 31) >> 5; + size = (pitch << 2) * (Bottom - Top); + block = calloc(1, size); + + topLine = 10000; + botLine = -10000; + + while (nglyph--) { + top = -glyphs->yoff; + bot = top + glyphs->height; + if (top < topLine) + topLine = top; + if (bot > botLine) + botLine = bot; + skippix = glyphs->start - infoRec->GlyphInfo[0].start; + bits = (CARD32 *) glyphs->bits; + bitPitch = glyphs->srcwidth >> 2; + pntr = block + ((FONTMAXBOUNDS(font, ascent) + top) * pitch) + + (skippix >> 5); + shift = skippix & 31; + extra = ((shift + glyphs->end - glyphs->start) > 32); + + for (i = top; i < bot; i++) { + *pntr |= SHIFT_L(*bits, shift); + if (extra) + *(pntr + 1) |= SHIFT_R(*bits, 32 - shift); + pntr += pitch; + bits += bitPitch; + } + + glyphs++; + } + + pntr = block + ((FONTMAXBOUNDS(font, ascent) + topLine) * pitch); + + Top = yInit + topLine; + Bottom = yInit + botLine; + + while (nbox && (Top >= pbox->y2)) { + pbox++; + nbox--; + } + + while (nbox && (Bottom > pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if (RightEdge > LeftEdge) { + skippix = LeftEdge - Left; + topLine = max(Top, pbox->y1); + botLine = min(Bottom, pbox->y2); + height = botLine - topLine; + + if (height > 0) + (*infoRec->WriteBitmap) (pScrn, LeftEdge, topLine, + RightEdge - LeftEdge, height, + (unsigned char *) (pntr + + ((topLine - + Top) * pitch) + + (skippix >> 5)), + pitch << 2, skippix & 31, fg, -1, rop, + planemask); + } + + nbox--; + pbox++; + } + + free(block); +} + +static void +ImageGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, + int xInit, int yInit, + FontPtr font, + int fg, int bg, + unsigned planemask, + RegionPtr cclip, + int nglyph, + unsigned char *gBase, CharInfoPtr * ppci) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int skippix, skipglyph, width, n, i; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge, ytop, ybot; + int nbox = RegionNumRects(cclip); + BoxPtr pbox = RegionRects(cclip); + Bool AlreadySetup = FALSE; + + width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font); + + /* find our backing rectangle dimensions */ + Left = xInit; + Right = Left + width; + Top = yInit - FONTASCENT(font); + Bottom = yInit + FONTDESCENT(font); + + /* get into the first band that may contain part of our box */ + while (nbox && (Top >= pbox->y2)) { + pbox++; + nbox--; + } + + while (nbox && (Bottom >= pbox->y1)) { + /* handle backing rect first */ + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + if (RightEdge > LeftEdge) { + ytop = max(Top, pbox->y1); + ybot = min(Bottom, pbox->y2); + + if (ybot > ytop) { + if (!AlreadySetup) { + (*infoRec->SetupForSolidFill) (pScrn, bg, GXcopy, + planemask); + AlreadySetup = TRUE; + } + (*infoRec->SubsequentSolidFillRect) (pScrn, + LeftEdge, ytop, + RightEdge - LeftEdge, + ybot - ytop); + } + } + nbox--; + pbox++; + } + + nbox = RegionNumRects(cclip); + pbox = RegionRects(cclip); + + if (infoRec->WriteBitmap && (nglyph > 1) && + ((FONTMAXBOUNDS(font, rightSideBearing) - + FONTMINBOUNDS(font, leftSideBearing)) <= 32)) { + PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font, + xInit, yInit, nbox, pbox, + fg, GXcopy, planemask); + + return; + } + + /* compute an approximate but covering bounding box */ + Left = xInit + infoRec->GlyphInfo[0].start; + Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; + Top = yInit - FONTMAXBOUNDS(font, ascent); + Bottom = yInit + FONTMAXBOUNDS(font, descent); + + /* get into the first band that may contain part of our box */ + while (nbox && (Top >= pbox->y2)) { + pbox++; + nbox--; + } + + /* stop when the lower edge of the box is beyond our string */ + while (nbox && (Bottom >= pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if (RightEdge > LeftEdge) { /* we're possibly drawing something */ + ytop = max(Top, pbox->y1); + ybot = min(Bottom, pbox->y2); + if (ybot > ytop) { + skippix = LeftEdge - xInit; + skipglyph = 0; + while (skippix >= infoRec->GlyphInfo[skipglyph].end) + skipglyph++; + + skippix = RightEdge - xInit; + n = 0; + i = skipglyph; + while ((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) { + i++; + n++; + } + + if (n) + (*infoRec->NonTEGlyphRenderer) (pScrn, + xInit, yInit, n, + infoRec->GlyphInfo + + skipglyph, pbox, fg, GXcopy, + planemask); + } + } + + nbox--; + pbox++; + } +} + +static int +PolyGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, + int xInit, int yInit, + FontPtr font, + int fg, int rop, + unsigned planemask, + RegionPtr cclip, + int nglyph, + unsigned char *gBase, CharInfoPtr * ppci) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int skippix, skipglyph, width, n, i; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge; + int nbox = RegionNumRects(cclip); + BoxPtr pbox = RegionRects(cclip); + + width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font); + + if (!nbox) + return width; + + if ((infoRec->WriteBitmap) && (rop == GXcopy) && (nglyph > 1) && + ((FONTMAXBOUNDS(font, rightSideBearing) - + FONTMINBOUNDS(font, leftSideBearing)) <= 32)) { + + PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font, + xInit, yInit, nbox, pbox, + fg, rop, planemask); + + return width; + } + + /* compute an approximate but covering bounding box */ + Left = xInit + infoRec->GlyphInfo[0].start; + Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; + Top = yInit - FONTMAXBOUNDS(font, ascent); + Bottom = yInit + FONTMAXBOUNDS(font, descent); + + /* get into the first band that may contain part of our string */ + while (nbox && (Top >= pbox->y2)) { + pbox++; + nbox--; + } + + /* stop when the lower edge of the box is beyond our string */ + while (nbox && (Bottom >= pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if (RightEdge > LeftEdge) { /* we're possibly drawing something */ + + skippix = LeftEdge - xInit; + skipglyph = 0; + while (skippix >= infoRec->GlyphInfo[skipglyph].end) + skipglyph++; + + skippix = RightEdge - xInit; + n = 0; + i = skipglyph; + while ((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) { + i++; + n++; + } + + if (n) + (*infoRec->NonTEGlyphRenderer) (pScrn, + xInit, yInit, n, + infoRec->GlyphInfo + skipglyph, + pbox, fg, rop, planemask); + } + + nbox--; + pbox++; + } + return width; +} + +/* It is possible that the none of the glyphs passed to the + NonTEGlyphRenderer will be drawn. This function being called + indicates that part of the text string's bounding box is visible + but not necessarily that any of the characters are visible */ + +void +XAANonTEGlyphRenderer(ScrnInfoPtr pScrn, + int x, int y, int n, + NonTEGlyphPtr glyphs, + BoxPtr pbox, int fg, int rop, unsigned int planemask) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x1, x2, y1, y2, i, w, h, skipleft, skiptop; + unsigned char *src; + + for (i = 0; i < n; i++, glyphs++) { + x1 = x + glyphs->start; + x2 = x + glyphs->end; + y1 = y - glyphs->yoff; + y2 = y1 + glyphs->height; + + if (y1 < pbox->y1) { + skiptop = pbox->y1 - y1; + y1 = pbox->y1; + } + else + skiptop = 0; + if (y2 > pbox->y2) + y2 = pbox->y2; + h = y2 - y1; + if (h <= 0) + continue; + + if (x1 < pbox->x1) { + skipleft = pbox->x1 - x1; + x1 = pbox->x1; + } + else + skipleft = 0; + if (x2 > pbox->x2) + x2 = pbox->x2; + + w = x2 - x1; + + if (w > 0) { + src = glyphs->bits + (skiptop * glyphs->srcwidth); + + if (skipleft) { + src += (skipleft >> 5) << 2; + skipleft &= 31; + } + + (*infoRec->WriteBitmap) (pScrn, x1, y1, w, h, src, + glyphs->srcwidth, skipleft, fg, -1, rop, + planemask); + } + } + +} diff --git a/hw/xfree86/xaa/xaaOffscreen.c b/hw/xfree86/xaa/xaaOffscreen.c new file mode 100644 index 000000000..e14ef1f27 --- /dev/null +++ b/hw/xfree86/xaa/xaaOffscreen.c @@ -0,0 +1,163 @@ + +/* + Copyright (c) 1999 - The XFree86 Project Inc. + + Written by Mark Vojkovich + +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "xf86fbman.h" +#include "servermd.h" + +void +XAAMoveOutOffscreenPixmaps(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; + XAAPixmapPtr pPriv; + + while (pLink) { + pPriv = XAA_GET_PIXMAP_PRIVATE(pLink->pPix); + pLink->area = pPriv->offscreenArea; + XAAMoveOutOffscreenPixmap(pLink->pPix); + pLink = pLink->next; + } +} + +void +XAAMoveInOffscreenPixmaps(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; + PixmapPtr pPix, pScreenPix, tmpPix; + void * data; + XAAPixmapPtr pPriv; + GCPtr pGC; + FBAreaPtr area; + + pScreenPix = (*pScreen->GetScreenPixmap) (pScreen); + + while (pLink) { + pPix = pLink->pPix; + pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + area = pLink->area; + + data = pPix->devPrivate.ptr; + tmpPix = GetScratchPixmapHeader(pScreen, + pPix->drawable.width, + pPix->drawable.height, + pPix->drawable.depth, + pPix->drawable.bitsPerPixel, + pPix->devKind, data); + + pPriv->freeData = FALSE; + + pPix->drawable.x = area->box.x1; + pPix->drawable.y = area->box.y1; + pPix->devKind = pScreenPix->devKind; + pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr; + pPix->drawable.bitsPerPixel = infoRec->pScrn->bitsPerPixel; + pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + if (!tmpPix) { + pPriv->offscreenArea = area; + free(data); + pLink = pLink->next; + continue; + } + + pGC = GetScratchGC(pPix->drawable.depth, pScreen); + ValidateGC((DrawablePtr) pPix, pGC); + + (*pGC->ops->CopyArea) ((DrawablePtr) tmpPix, (DrawablePtr) pPix, pGC, + 0, 0, pPix->drawable.width, + pPix->drawable.height, 0, 0); + + free(data); + tmpPix->devPrivate.ptr = NULL; + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(tmpPix); + + pPriv->offscreenArea = area; + pLink->area = NULL; + pLink = pLink->next; + } +} + +void +XAARemoveAreaCallback(FBAreaPtr area) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(area->pScreen); + PixmapPtr pPix = (PixmapPtr) area->devPrivate.ptr; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + + XAAMoveOutOffscreenPixmap(pPix); + + pPriv->flags &= ~OFFSCREEN; + + DELIST_OFFSCREEN_PIXMAP(pPix); +} + +void +XAAMoveOutOffscreenPixmap(PixmapPtr pPix) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + int width, height, devKind, bitsPerPixel; + PixmapPtr tmpPix; + unsigned char *data; + GCPtr pGC; + + width = pPix->drawable.width; + height = pPix->drawable.height; + bitsPerPixel = pPix->drawable.bitsPerPixel; + + devKind = BitmapBytePad(width * bitsPerPixel); + if (!(data = malloc(devKind * height))) + FatalError("Out of memory\n"); + + tmpPix = GetScratchPixmapHeader(pScreen, width, height, + pPix->drawable.depth, bitsPerPixel, devKind, + data); + if (!tmpPix) { + free(data); + FatalError("Out of memory\n"); + } + + pGC = GetScratchGC(pPix->drawable.depth, pScreen); + ValidateGC((DrawablePtr) tmpPix, pGC); + + (*pGC->ops->CopyArea) ((DrawablePtr) pPix, (DrawablePtr) tmpPix, + pGC, 0, 0, width, height, 0, 0); + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(tmpPix); + + pPix->drawable.x = 0; + pPix->drawable.y = 0; + pPix->devKind = devKind; + pPix->devPrivate.ptr = data; + pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pPriv->offscreenArea = NULL; + pPriv->freeData = TRUE; +} diff --git a/hw/xfree86/xaa/xaaOverlay.c b/hw/xfree86/xaa/xaaOverlay.c new file mode 100644 index 000000000..25d18da96 --- /dev/null +++ b/hw/xfree86/xaa/xaaOverlay.c @@ -0,0 +1,122 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "mioverlay.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +static void +XAACopyWindow8_32(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + DDXPointPtr pptSrc, ppt; + RegionRec rgnDst; + BoxPtr pbox; + int dx, dy, nbox; + WindowPtr pwinRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); + Bool doUnderlay = miOverlayCopyUnderlay(pScreen); + RegionPtr borderClip = &pWin->borderClip; + Bool freeReg = FALSE; + + if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt || + (infoRec->ScreenToScreenBitBltFlags & NO_PLANEMASK)) { + XAA_SCREEN_PROLOGUE(pScreen, CopyWindow); + if (infoRec->pScrn->vtSema && infoRec->NeedToSync) { + (*infoRec->Sync) (infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + XAA_SCREEN_EPILOGUE(pScreen, CopyWindow, XAACopyWindow8_32); + return; + } + + pwinRoot = pScreen->root; + + if (doUnderlay) + freeReg = miOverlayCollectUnderlayRegions(pWin, &borderClip); + + RegionNull(&rgnDst); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + RegionTranslate(prgnSrc, -dx, -dy); + RegionIntersect(&rgnDst, borderClip, prgnSrc); + + pbox = RegionRects(&rgnDst); + nbox = RegionNumRects(&rgnDst); + if (!nbox || !(pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { + RegionUninit(&rgnDst); + return; + } + ppt = pptSrc; + + while (nbox--) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + ppt++; + pbox++; + } + + infoRec->ScratchGC.planemask = doUnderlay ? 0x00ffffff : 0xff000000; + infoRec->ScratchGC.alu = GXcopy; + + XAADoBitBlt((DrawablePtr) pwinRoot, (DrawablePtr) pwinRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + + free(pptSrc); + RegionUninit(&rgnDst); + if (freeReg) + RegionDestroy(borderClip); +} + +static void +XAASetColorKey8_32(ScreenPtr pScreen, int nbox, BoxPtr pbox) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = infoRec->pScrn; + + /* I'm counting on writes being clipped away while switched away. + If this isn't going to be true then I need to be wrapping instead. */ + if (!infoRec->pScrn->vtSema) + return; + + (*infoRec->FillSolidRects) (pScrn, pScrn->colorKey << 24, GXcopy, + 0xff000000, nbox, pbox); + + SET_SYNC_FLAG(infoRec); +} + +void +XAASetupOverlay8_32Planar(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + int i; + + pScreen->CopyWindow = XAACopyWindow8_32; + + if (!(infoRec->FillSolidRectsFlags & NO_PLANEMASK)) + miOverlaySetTransFunction(pScreen, XAASetColorKey8_32); + + infoRec->FullPlanemask = ~0; + for (i = 0; i < 32; i++) /* haven't thought about this much */ + infoRec->FullPlanemasks[i] = ~0; +} diff --git a/hw/xfree86/xaa/xaaOverlayDF.c b/hw/xfree86/xaa/xaaOverlayDF.c new file mode 100644 index 000000000..90521c70d --- /dev/null +++ b/hw/xfree86/xaa/xaaOverlayDF.c @@ -0,0 +1,906 @@ +/* + Copyright (c) 1999 - The XFree86 Project Inc. + + Written by Mark Vojkovich +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "servermd.h" + +/* Screen funcs */ + +static void XAAOverCopyWindow(WindowPtr, DDXPointRec, RegionPtr); +static void XAAOverWindowExposures(WindowPtr, RegionPtr/*, RegionPtr*/); + +static int XAAOverStippledFillChooser(GCPtr); +static int XAAOverOpaqueStippledFillChooser(GCPtr); +static int XAAOverTiledFillChooser(GCPtr); + +/* GC funcs */ + +static RegionPtr XAAOverCopyArea(DrawablePtr, DrawablePtr, GC *, + int, int, int, int, int, int); +static RegionPtr XAAOverCopyPlane(DrawablePtr, DrawablePtr, GCPtr, + int, int, int, int, int, int, unsigned long); +static void XAAOverPushPixelsSolid(GCPtr, PixmapPtr, DrawablePtr, int, + int, int, int); +static void XAAOverPolyFillRectSolid(DrawablePtr, GCPtr, int, xRectangle *); +static void XAAOverPolyFillRectStippled(DrawablePtr, GCPtr, int, xRectangle *); +static void XAAOverPolyFillRectOpaqueStippled(DrawablePtr, GCPtr, + int, xRectangle *); +static void XAAOverPolyFillRectTiled(DrawablePtr, GCPtr, int, xRectangle *); +static void XAAOverFillSpansSolid(DrawablePtr, GCPtr, int, DDXPointPtr, + int *, int); +static void XAAOverFillSpansStippled(DrawablePtr, GCPtr, int, DDXPointPtr, + int *, int); +static void XAAOverFillSpansOpaqueStippled(DrawablePtr, GCPtr, int, + DDXPointPtr, int *, int); +static void XAAOverFillSpansTiled(DrawablePtr, GCPtr, int, DDXPointPtr, + int *, int); +static int XAAOverPolyText8TE(DrawablePtr, GCPtr, int, int, int, char *); +static int XAAOverPolyText16TE(DrawablePtr, GCPtr, int, int, int, + unsigned short *); +static void XAAOverImageText8TE(DrawablePtr, GCPtr, int, int, int, char *); +static void XAAOverImageText16TE(DrawablePtr, GCPtr, int, int, int, + unsigned short *); +static void XAAOverImageGlyphBltTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr *, void *); +static void XAAOverPolyGlyphBltTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr *, void *); +static int XAAOverPolyText8NonTE(DrawablePtr, GCPtr, int, int, int, char *); +static int XAAOverPolyText16NonTE(DrawablePtr, GCPtr, int, int, int, + unsigned short *); +static void XAAOverImageText8NonTE(DrawablePtr, GCPtr, int, int, int, char *); +static void XAAOverImageText16NonTE(DrawablePtr, GCPtr, int, int, int, + unsigned short *); +static void XAAOverImageGlyphBltNonTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr *, void *); +static void XAAOverPolyGlyphBltNonTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr *, void *); +static void XAAOverPolyRectangleThinSolid(DrawablePtr, GCPtr, int, + xRectangle *); +static void XAAOverPolylinesWideSolid(DrawablePtr, GCPtr, int, int, + DDXPointPtr); +static void XAAOverPolylinesThinSolid(DrawablePtr, GCPtr, int, int, + DDXPointPtr); +static void XAAOverPolySegmentThinSolid(DrawablePtr, GCPtr, int, xSegment *); +static void XAAOverPolylinesThinDashed(DrawablePtr, GCPtr, int, int, + DDXPointPtr); +static void XAAOverPolySegmentThinDashed(DrawablePtr, GCPtr, int, xSegment *); +static void XAAOverFillPolygonSolid(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverFillPolygonStippled(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverFillPolygonOpaqueStippled(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverFillPolygonTiled(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverPolyFillArcSolid(DrawablePtr, GCPtr, int, xArc *); +static void XAAOverPutImage(DrawablePtr, GCPtr, int, int, int, int, int, + int, int, char *); + +typedef struct { + ScrnInfoPtr pScrn; + DepthChangeFuncPtr callback; + int currentDepth; +/* GC funcs */ + RegionPtr (*CopyArea) (DrawablePtr, DrawablePtr, GC *, + int, int, int, int, int, int); + RegionPtr (*CopyPlane) (DrawablePtr, DrawablePtr, GCPtr, + int, int, int, int, int, int, unsigned long); + void (*PushPixelsSolid) (GCPtr, PixmapPtr, DrawablePtr, int, int, int, int); + void (*PolyFillRectSolid) (DrawablePtr, GCPtr, int, xRectangle *); + void (*PolyFillRectStippled) (DrawablePtr, GCPtr, int, xRectangle *); + void (*PolyFillRectOpaqueStippled) (DrawablePtr, GCPtr, int, xRectangle *); + void (*PolyFillRectTiled) (DrawablePtr, GCPtr, int, xRectangle *); + void (*FillSpansSolid) (DrawablePtr, GCPtr, int, DDXPointPtr, int *, int); + void (*FillSpansStippled) (DrawablePtr, GCPtr, int, DDXPointPtr, int *, + int); + void (*FillSpansOpaqueStippled) (DrawablePtr, GCPtr, int, DDXPointPtr, + int *, int); + void (*FillSpansTiled) (DrawablePtr, GCPtr, int, DDXPointPtr, int *, int); + int (*PolyText8TE) (DrawablePtr, GCPtr, int, int, int, char *); + int (*PolyText16TE) (DrawablePtr, GCPtr, int, int, int, unsigned short *); + void (*ImageText8TE) (DrawablePtr, GCPtr, int, int, int, char *); + void (*ImageText16TE) (DrawablePtr, GCPtr, int, int, int, unsigned short *); + void (*ImageGlyphBltTE) (DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr *, void *); + void (*PolyGlyphBltTE) (DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr *, void *); + int (*PolyText8NonTE) (DrawablePtr, GCPtr, int, int, int, char *); + int (*PolyText16NonTE) (DrawablePtr, GCPtr, int, int, int, + unsigned short *); + void (*ImageText8NonTE) (DrawablePtr, GCPtr, int, int, int, char *); + void (*ImageText16NonTE) (DrawablePtr, GCPtr, int, int, int, + unsigned short *); + void (*ImageGlyphBltNonTE) (DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr *, void *); + void (*PolyGlyphBltNonTE) (DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr *, void *); + void (*PolyRectangleThinSolid) (DrawablePtr, GCPtr, int, xRectangle *); + void (*PolylinesWideSolid) (DrawablePtr, GCPtr, int, int, DDXPointPtr); + + void (*PolylinesThinSolid) (DrawablePtr, GCPtr, int, int, DDXPointPtr); + void (*PolySegmentThinSolid) (DrawablePtr, GCPtr, int, xSegment *); + void (*PolylinesThinDashed) (DrawablePtr, GCPtr, int, int, DDXPointPtr); + void (*PolySegmentThinDashed) (DrawablePtr, GCPtr, int, xSegment *); + void (*FillPolygonSolid) (DrawablePtr, GCPtr, int, int, int, DDXPointPtr); + void (*FillPolygonStippled) (DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); + void (*FillPolygonOpaqueStippled) (DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); + void (*FillPolygonTiled) (DrawablePtr, GCPtr, int, int, int, DDXPointPtr); + void (*PolyFillArcSolid) (DrawablePtr, GCPtr, int, xArc *); + void (*PutImage) (DrawablePtr, GCPtr, int, int, int, int, int, int, + int, char *); + int (*StippledFillChooser) (GCPtr); + int (*OpaqueStippledFillChooser) (GCPtr); + int (*TiledFillChooser) (GCPtr); +} XAAOverlayRec, *XAAOverlayPtr; + +static DevPrivateKeyRec XAAOverlayKeyRec; + +#define XAAOverlayKey (&XAAOverlayKeyRec) + +#define GET_OVERLAY_PRIV(pScreen) \ + (XAAOverlayPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAOverlayKey) + +#define SWITCH_DEPTH(d) \ + if(pOverPriv->currentDepth != d) { \ + (*pOverPriv->callback)(pOverPriv->pScrn, d); \ + pOverPriv->currentDepth = d; \ + } + +Bool +XAAInitDualFramebufferOverlay(ScreenPtr pScreen, DepthChangeFuncPtr callback) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAOverlayPtr pOverPriv; + + if (!dixRegisterPrivateKey(&XAAOverlayKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!(pOverPriv = malloc(sizeof(XAAOverlayRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, XAAOverlayKey, pOverPriv); + + pOverPriv->pScrn = pScrn; + pOverPriv->callback = callback; + pOverPriv->currentDepth = -1; + + /* Overwrite key screen functions. The XAA core will clean up */ + + pScreen->CopyWindow = XAAOverCopyWindow; + pScreen->WindowExposures = XAAOverWindowExposures; + + pOverPriv->StippledFillChooser = infoRec->StippledFillChooser; + pOverPriv->OpaqueStippledFillChooser = infoRec->OpaqueStippledFillChooser; + pOverPriv->TiledFillChooser = infoRec->TiledFillChooser; + + infoRec->StippledFillChooser = XAAOverStippledFillChooser; + infoRec->OpaqueStippledFillChooser = XAAOverOpaqueStippledFillChooser; + infoRec->TiledFillChooser = XAAOverTiledFillChooser; + + /* wrap all XAA GC rendering */ + + pOverPriv->CopyArea = infoRec->CopyArea; + pOverPriv->CopyPlane = infoRec->CopyPlane; + pOverPriv->PushPixelsSolid = infoRec->PushPixelsSolid; + pOverPriv->PolyFillRectSolid = infoRec->PolyFillRectSolid; + pOverPriv->PolyFillRectStippled = infoRec->PolyFillRectStippled; + pOverPriv->PolyFillRectOpaqueStippled = infoRec->PolyFillRectOpaqueStippled; + pOverPriv->PolyFillRectTiled = infoRec->PolyFillRectTiled; + pOverPriv->FillSpansSolid = infoRec->FillSpansSolid; + pOverPriv->FillSpansStippled = infoRec->FillSpansStippled; + pOverPriv->FillSpansOpaqueStippled = infoRec->FillSpansOpaqueStippled; + pOverPriv->FillSpansTiled = infoRec->FillSpansTiled; + pOverPriv->PolyText8TE = infoRec->PolyText8TE; + pOverPriv->PolyText16TE = infoRec->PolyText16TE; + pOverPriv->ImageText8TE = infoRec->ImageText8TE; + pOverPriv->ImageText16TE = infoRec->ImageText16TE; + pOverPriv->ImageGlyphBltTE = infoRec->ImageGlyphBltTE; + pOverPriv->PolyGlyphBltTE = infoRec->PolyGlyphBltTE; + pOverPriv->PolyText8NonTE = infoRec->PolyText8NonTE; + pOverPriv->PolyText16NonTE = infoRec->PolyText16NonTE; + pOverPriv->ImageText8NonTE = infoRec->ImageText8NonTE; + pOverPriv->ImageText16NonTE = infoRec->ImageText16NonTE; + pOverPriv->ImageGlyphBltNonTE = infoRec->ImageGlyphBltNonTE; + pOverPriv->PolyGlyphBltNonTE = infoRec->PolyGlyphBltNonTE; + pOverPriv->PolyRectangleThinSolid = infoRec->PolyRectangleThinSolid; + pOverPriv->PolylinesWideSolid = infoRec->PolylinesWideSolid; + pOverPriv->PolylinesThinSolid = infoRec->PolylinesThinSolid; + pOverPriv->PolySegmentThinSolid = infoRec->PolySegmentThinSolid; + pOverPriv->PolylinesThinDashed = infoRec->PolylinesThinDashed; + pOverPriv->PolySegmentThinDashed = infoRec->PolySegmentThinDashed; + pOverPriv->FillPolygonSolid = infoRec->FillPolygonSolid; + pOverPriv->FillPolygonStippled = infoRec->FillPolygonStippled; + pOverPriv->FillPolygonOpaqueStippled = infoRec->FillPolygonOpaqueStippled; + pOverPriv->FillPolygonTiled = infoRec->FillPolygonTiled; + pOverPriv->PolyFillArcSolid = infoRec->PolyFillArcSolid; + pOverPriv->PutImage = infoRec->PutImage; + + if (infoRec->CopyArea) + infoRec->CopyArea = XAAOverCopyArea; + if (infoRec->CopyPlane) + infoRec->CopyPlane = XAAOverCopyPlane; + if (infoRec->PushPixelsSolid) + infoRec->PushPixelsSolid = XAAOverPushPixelsSolid; + if (infoRec->PolyFillRectSolid) + infoRec->PolyFillRectSolid = XAAOverPolyFillRectSolid; + if (infoRec->PolyFillRectStippled) + infoRec->PolyFillRectStippled = XAAOverPolyFillRectStippled; + if (infoRec->PolyFillRectOpaqueStippled) + infoRec->PolyFillRectOpaqueStippled = XAAOverPolyFillRectOpaqueStippled; + if (infoRec->PolyFillRectTiled) + infoRec->PolyFillRectTiled = XAAOverPolyFillRectTiled; + if (infoRec->FillSpansSolid) + infoRec->FillSpansSolid = XAAOverFillSpansSolid; + if (infoRec->FillSpansStippled) + infoRec->FillSpansStippled = XAAOverFillSpansStippled; + if (infoRec->FillSpansOpaqueStippled) + infoRec->FillSpansOpaqueStippled = XAAOverFillSpansOpaqueStippled; + if (infoRec->FillSpansTiled) + infoRec->FillSpansTiled = XAAOverFillSpansTiled; + if (infoRec->PolyText8TE) + infoRec->PolyText8TE = XAAOverPolyText8TE; + if (infoRec->PolyText16TE) + infoRec->PolyText16TE = XAAOverPolyText16TE; + if (infoRec->ImageText8TE) + infoRec->ImageText8TE = XAAOverImageText8TE; + if (infoRec->ImageText16TE) + infoRec->ImageText16TE = XAAOverImageText16TE; + if (infoRec->ImageGlyphBltTE) + infoRec->ImageGlyphBltTE = XAAOverImageGlyphBltTE; + if (infoRec->PolyGlyphBltTE) + infoRec->PolyGlyphBltTE = XAAOverPolyGlyphBltTE; + if (infoRec->PolyText8NonTE) + infoRec->PolyText8NonTE = XAAOverPolyText8NonTE; + if (infoRec->PolyText16NonTE) + infoRec->PolyText16NonTE = XAAOverPolyText16NonTE; + if (infoRec->ImageText8NonTE) + infoRec->ImageText8NonTE = XAAOverImageText8NonTE; + if (infoRec->ImageText16NonTE) + infoRec->ImageText16NonTE = XAAOverImageText16NonTE; + if (infoRec->ImageGlyphBltNonTE) + infoRec->ImageGlyphBltNonTE = XAAOverImageGlyphBltNonTE; + if (infoRec->PolyGlyphBltNonTE) + infoRec->PolyGlyphBltNonTE = XAAOverPolyGlyphBltNonTE; + if (infoRec->PolyRectangleThinSolid) + infoRec->PolyRectangleThinSolid = XAAOverPolyRectangleThinSolid; + if (infoRec->PolylinesWideSolid) + infoRec->PolylinesWideSolid = XAAOverPolylinesWideSolid; + if (infoRec->PolylinesThinSolid) + infoRec->PolylinesThinSolid = XAAOverPolylinesThinSolid; + if (infoRec->PolySegmentThinSolid) + infoRec->PolySegmentThinSolid = XAAOverPolySegmentThinSolid; + if (infoRec->PolylinesThinDashed) + infoRec->PolylinesThinDashed = XAAOverPolylinesThinDashed; + if (infoRec->PolySegmentThinDashed) + infoRec->PolySegmentThinDashed = XAAOverPolySegmentThinDashed; + if (infoRec->FillPolygonSolid) + infoRec->FillPolygonSolid = XAAOverFillPolygonSolid; + if (infoRec->FillPolygonStippled) + infoRec->FillPolygonStippled = XAAOverFillPolygonStippled; + if (infoRec->FillPolygonOpaqueStippled) + infoRec->FillPolygonOpaqueStippled = XAAOverFillPolygonOpaqueStippled; + if (infoRec->FillPolygonTiled) + infoRec->FillPolygonTiled = XAAOverFillPolygonTiled; + if (infoRec->PolyFillArcSolid) + infoRec->PolyFillArcSolid = XAAOverPolyFillArcSolid; + if (infoRec->PutImage) + infoRec->PutImage = XAAOverPutImage; + + return TRUE; +} + +/*********************** Screen functions ************************/ + +void +XAAOverCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); + ScrnInfoPtr pScrn = infoRec->pScrn; + DDXPointPtr ppt, pptSrc; + RegionRec rgnDst; + BoxPtr pbox; + int i, nbox, dx, dy; + WindowPtr pRoot = pScreen->root; + + if (!pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { + XAA_SCREEN_PROLOGUE(pScreen, CopyWindow); + if (pScrn->vtSema && infoRec->NeedToSync) { + (*infoRec->Sync) (pScrn); + infoRec->NeedToSync = FALSE; + } + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + XAA_SCREEN_EPILOGUE(pScreen, CopyWindow, XAAOverCopyWindow); + return; + } + + infoRec->ScratchGC.alu = GXcopy; + infoRec->ScratchGC.planemask = ~0; + + RegionNull(&rgnDst); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + RegionTranslate(prgnSrc, -dx, -dy); + RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); + + nbox = RegionNumRects(&rgnDst); + if (nbox && (pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { + + pbox = RegionRects(&rgnDst); + for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + SWITCH_DEPTH(8); + XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + + if (pWin->drawable.bitsPerPixel != 8) { + SWITCH_DEPTH(pScrn->depth); + XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + } + + free(pptSrc); + } + + RegionUninit(&rgnDst); + + if (pWin->drawable.depth == 8) { + RegionNull(&rgnDst); + miSegregateChildren(pWin, &rgnDst, pScrn->depth); + if (RegionNotEmpty(&rgnDst)) { + RegionIntersect(&rgnDst, &rgnDst, prgnSrc); + nbox = RegionNumRects(&rgnDst); + if (nbox && + (pptSrc = (DDXPointPtr) malloc(nbox * sizeof(DDXPointRec)))) { + + pbox = RegionRects(&rgnDst); + for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + SWITCH_DEPTH(pScrn->depth); + XAADoBitBlt((DrawablePtr) pRoot, (DrawablePtr) pRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + free(pptSrc); + } + } + RegionUninit(&rgnDst); + } +} + +void +XAAOverWindowExposures(WindowPtr pWin, RegionPtr pReg/*, RegionPtr pOtherReg*/) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if ((pWin->drawable.bitsPerPixel != 8) && infoRec->pScrn->vtSema) { + if (RegionNumRects(pReg) && infoRec->FillSolidRects) { + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); + + SWITCH_DEPTH(8); + (*infoRec->FillSolidRects) (infoRec->pScrn, + infoRec->pScrn->colorKey, GXcopy, ~0, + RegionNumRects(pReg), + RegionRects(pReg)); + miWindowExposures(pWin, pReg/*, pOtherReg*/); + return; + } + else if (infoRec->NeedToSync) { + (*infoRec->Sync) (infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + } + + XAA_SCREEN_PROLOGUE(pScreen, WindowExposures); + (*pScreen->WindowExposures) (pWin, pReg/*, pOtherReg*/); + XAA_SCREEN_EPILOGUE(pScreen, WindowExposures, XAAOverWindowExposures); +} + +/********************* Choosers *************************/ + +static int +XAAOverStippledFillChooser(GCPtr pGC) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + int ret; + + ret = (*pOverPriv->StippledFillChooser) (pGC); + + if ((pGC->depth == 8) && ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { + ret = 0; + } + + return ret; +} + +static int +XAAOverOpaqueStippledFillChooser(GCPtr pGC) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + int ret; + + ret = (*pOverPriv->OpaqueStippledFillChooser) (pGC); + + if ((pGC->depth == 8) && ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { + ret = 0; + } + + return ret; +} + +static int +XAAOverTiledFillChooser(GCPtr pGC) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + int ret; + + ret = (*pOverPriv->TiledFillChooser) (pGC); + + if ((pGC->depth == 8) && ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { + ret = 0; + } + + return ret; +} + +/**************************** GC Functions **************************/ + +static RegionPtr +XAAOverCopyArea(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->CopyArea) (pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); +} + +static RegionPtr +XAAOverCopyPlane(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->CopyPlane) (pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, + bitPlane); + +} + +static void +XAAOverPushPixelsSolid(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, int dx, int dy, int xOrg, int yOrg) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PushPixelsSolid) (pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); +} + +static void +XAAOverPolyFillRectSolid(DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectSolid) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAOverPolyFillRectStippled(DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectStippled) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAOverPolyFillRectOpaqueStippled(DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectOpaqueStippled) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAOverPolyFillRectTiled(DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectTiled) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAOverFillSpansSolid(DrawablePtr pDraw, + GCPtr pGC, + int nInit, DDXPointPtr ppt, int *pwidth, int fSorted) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansSolid) (pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static void +XAAOverFillSpansStippled(DrawablePtr pDraw, + GCPtr pGC, + int nInit, DDXPointPtr ppt, int *pwidth, int fSorted) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansStippled) (pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static void +XAAOverFillSpansOpaqueStippled(DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansOpaqueStippled) (pDraw, pGC, nInit, ppt, pwidth, + fSorted); +} + +static void +XAAOverFillSpansTiled(DrawablePtr pDraw, + GCPtr pGC, + int nInit, DDXPointPtr ppt, int *pwidth, int fSorted) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansTiled) (pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static int +XAAOverPolyText8TE(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText8TE) (pDraw, pGC, x, y, count, chars); +} + +static int +XAAOverPolyText16TE(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText16TE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageText8TE(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText8TE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageText16TE(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, unsigned short *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText16TE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageGlyphBltTE(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageGlyphBltTE) (pDraw, pGC, xInit, yInit, nglyph, ppci, + pglyphBase); +} + +static void +XAAOverPolyGlyphBltTE(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyGlyphBltTE) (pDraw, pGC, xInit, yInit, nglyph, ppci, + pglyphBase); +} + +static int +XAAOverPolyText8NonTE(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText8NonTE) (pDraw, pGC, x, y, count, chars); +} + +static int +XAAOverPolyText16NonTE(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText16NonTE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageText8NonTE(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText8NonTE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageText16NonTE(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText16NonTE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageGlyphBltNonTE(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageGlyphBltNonTE) (pDraw, pGC, xInit, yInit, nglyph, ppci, + pglyphBase); +} + +static void +XAAOverPolyGlyphBltNonTE(DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyGlyphBltNonTE) (pDraw, pGC, xInit, yInit, nglyph, ppci, + pglyphBase); +} + +static void +XAAOverPolyRectangleThinSolid(DrawablePtr pDraw, + GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyRectangleThinSolid) (pDraw, pGC, nRectsInit, pRectsInit); +} + +static void +XAAOverPolylinesWideSolid(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolylinesWideSolid) (pDraw, pGC, mode, npt, pPts); +} + +static void +XAAOverPolylinesThinSolid(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolylinesThinSolid) (pDraw, pGC, mode, npt, pPts); +} + +static void +XAAOverPolySegmentThinSolid(DrawablePtr pDraw, + GCPtr pGC, int nseg, xSegment * pSeg) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolySegmentThinSolid) (pDraw, pGC, nseg, pSeg); +} + +static void +XAAOverPolylinesThinDashed(DrawablePtr pDraw, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolylinesThinDashed) (pDraw, pGC, mode, npt, pPts); +} + +static void +XAAOverPolySegmentThinDashed(DrawablePtr pDraw, + GCPtr pGC, int nseg, xSegment * pSeg) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolySegmentThinDashed) (pDraw, pGC, nseg, pSeg); +} + +static void +XAAOverFillPolygonSolid(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonSolid) (pDraw, pGC, shape, mode, count, ptsIn); +} + +static void +XAAOverFillPolygonStippled(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonStippled) (pDraw, pGC, shape, mode, count, ptsIn); +} + +static void +XAAOverFillPolygonOpaqueStippled(DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonOpaqueStippled) (pDraw, pGC, shape, mode, count, + ptsIn); +} + +static void +XAAOverFillPolygonTiled(DrawablePtr pDraw, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonTiled) (pDraw, pGC, shape, mode, count, ptsIn); +} + +static void +XAAOverPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillArcSolid) (pDraw, pGC, narcs, parcs); +} + +static void +XAAOverPutImage(DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, + int y, int w, int h, int leftPad, int format, char *pImage) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PutImage) (pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); +} diff --git a/hw/xfree86/xaa/xaaPCache.c b/hw/xfree86/xaa/xaaPCache.c new file mode 100644 index 000000000..7d917ee3f --- /dev/null +++ b/hw/xfree86/xaa/xaaPCache.c @@ -0,0 +1,2527 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "gc.h" +#include "mi.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "regionstr.h" +#include "servermd.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaacexp.h" +#include "xaalocal.h" +#include "xaawrap.h" + +#define MAX_COLOR 32 +#define MAX_MONO 32 +#define MAX_8 32 +#define MAX_128 32 +#define MAX_256 32 +#define MAX_512 16 + +static int CacheInitIndex = -1; + +#define CACHEINIT(p) ((p)->privates[CacheInitIndex].val) + +typedef struct _CacheLink { + int x; + int y; + int w; + int h; + struct _CacheLink *next; +} CacheLink, *CacheLinkPtr; + +static void +TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num) +{ + while (num--) { + array->x = list->x; + array->y = list->y; + array->w = list->w; + array->h = list->h; + array->serialNumber = 0; + array->fg = array->bg = -1; + list = list->next; + array++; + } +} + +static CacheLinkPtr +Enlist(CacheLinkPtr link, int x, int y, int w, int h) +{ + CacheLinkPtr newLink; + + newLink = malloc(sizeof(CacheLink)); + newLink->next = link; + newLink->x = x; + newLink->y = y; + newLink->w = w; + newLink->h = h; + return newLink; +} + +static CacheLinkPtr +Delist(CacheLinkPtr link) +{ + CacheLinkPtr ret = NULL; + + if (link) { + ret = link->next; + free(link); + } + return ret; +} + +static void +FreeList(CacheLinkPtr link) +{ + CacheLinkPtr tmp; + + while (link) { + tmp = link; + link = link->next; + free(tmp); + } +} + +static CacheLinkPtr +QuadLinks(CacheLinkPtr big, CacheLinkPtr little) +{ + /* CAUTION: This doesn't free big */ + int w1, w2, h1, h2; + + while (big) { + w1 = big->w >> 1; + w2 = big->w - w1; + h1 = big->h >> 1; + h2 = big->h - h1; + + little = Enlist(little, big->x, big->y, w1, h1); + little = Enlist(little, big->x + w1, big->y, w2, h1); + little = Enlist(little, big->x, big->y + h1, w1, h2); + little = Enlist(little, big->x + w1, big->y + h1, w2, h2); + + big = big->next; + } + return little; +} + +static void +SubdivideList(CacheLinkPtr * large, CacheLinkPtr * small) +{ + CacheLinkPtr big = *large; + CacheLinkPtr little = *small; + int size = big->w >> 1; + + little = Enlist(little, big->x, big->y, size, size); + little = Enlist(little, big->x + size, big->y, size, size); + little = Enlist(little, big->x, big->y + size, size, size); + little = Enlist(little, big->x + size, big->y + size, size, size); + *small = little; + big = Delist(big); + *large = big; +} + +static void +FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv) +{ + if (!pPriv) + return; + + free(pPriv->Info512); + free(pPriv->Info256); + free(pPriv->Info128); + free(pPriv->InfoColor); + free(pPriv->InfoMono); + free(pPriv->InfoPartial); + + free(pPriv); +} + +void +XAAClosePixmapCache(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if (infoRec->PixmapCachePrivate) + FreePixmapCachePrivate((XAAPixmapCachePrivatePtr) infoRec-> + PixmapCachePrivate); + + infoRec->PixmapCachePrivate = NULL; +} + +static CacheLinkPtr +ThinOutPartials(CacheLinkPtr ListPartial, int *num, int *maxw, int *maxh) +{ +/* This guy's job is to get at least 4 big slots out of a list of fragments */ + + CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; + int Num64, Num32, Num16, Num8, NumKeepers; + int w, h; + + List64 = List32 = List16 = List8 = ListKeepers = NULL; + Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; + w = h = 0; + + /* We sort partials by how large a square tile they can cache. + If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile, + we free it. */ + + pCur = ListPartial; + while (pCur) { + next = pCur->next; + if ((pCur->w >= 64) && (pCur->h >= 64)) { + pCur->next = List64; + List64 = pCur; + Num64++; + } + else if ((pCur->w >= 32) && (pCur->h >= 32)) { + pCur->next = List32; + List32 = pCur; + Num32++; + } + else if ((pCur->w >= 16) && (pCur->h >= 16)) { + pCur->next = List16; + List16 = pCur; + Num16++; + } + else if ((pCur->w >= 8) && (pCur->h >= 8)) { + pCur->next = List8; + List8 = pCur; + Num8++; + } + else { + free(pCur); + } + + pCur = next; + } + + /* We save all the tiles from the largest bin that we can get + at least 4 of. If there are too few of a bigger slot, we + cut it in fourths to make smaller slots. */ + + if (Num64 >= 4) { + ListKeepers = List64; + List64 = NULL; + NumKeepers = Num64; + goto GOT_EM; + } + else if (Num64) { + List32 = QuadLinks(List64, List32); + Num32 += Num64 * 4; + Num64 = 0; + } + + if (Num32 >= 4) { + ListKeepers = List32; + List32 = NULL; + NumKeepers = Num32; + goto GOT_EM; + } + else if (Num32) { + List16 = QuadLinks(List32, List16); + Num16 += Num32 * 4; + Num32 = 0; + } + + if (Num16 >= 4) { + ListKeepers = List16; + List16 = NULL; + NumKeepers = Num16; + goto GOT_EM; + } + else if (Num16) { + List8 = QuadLinks(List16, List8); + Num8 += Num16 * 4; + Num16 = 0; + } + + if (Num8 >= 4) { + ListKeepers = List8; + List8 = NULL; + NumKeepers = Num8; + goto GOT_EM; + } + + GOT_EM: + + /* Free the ones we aren't using */ + + if (List64) + FreeList(List64); + if (List32) + FreeList(List32); + if (List16) + FreeList(List16); + if (List8) + FreeList(List8); + + /* Enlarge the slots if we can */ + + if (ListKeepers) { + CacheLinkPtr pLink = ListKeepers; + + w = h = 128; + + while (pLink) { + if (pLink->w < w) + w = pLink->w; + if (pLink->h < h) + h = pLink->h; + pLink = pLink->next; + } + } + + *maxw = w; + *maxh = h; + *num = NumKeepers; + return ListKeepers; +} + +static void +ConvertColorToMono(CacheLinkPtr * ColorList, + int ColorW, int ColorH, + CacheLinkPtr * MonoList, int MonoW, int MonoH) +{ + int x, y, w; + + x = (*ColorList)->x; + y = (*ColorList)->y; + *ColorList = Delist(*ColorList); + + while (ColorH) { + ColorH -= MonoH; + for (w = 0; w <= (ColorW - MonoW); w += MonoW) + *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH); + } +} + +static void +ConvertAllPartialsTo8x8(int *NumMono, int *NumColor, + CacheLinkPtr ListPartial, + CacheLinkPtr * ListMono, + CacheLinkPtr * ListColor, XAAInfoRecPtr infoRec) +{ +/* This guy extracts as many 8x8 slots as it can out of fragments */ + + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + int x, y, w, Height, Width; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + CacheLinkPtr pLink = ListPartial; + CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; + + if (DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if (MonoH > ColorH) + ColorH = MonoH; + if (MonoW > ColorW) + ColorW = MonoW; + } + + /* Break up the area into as many Color and Mono slots as we can */ + + while (pLink) { + Height = pLink->h; + Width = pLink->w; + x = pLink->x; + y = pLink->y; + + if (DoColor) { + while (Height >= ColorH) { + Height -= ColorH; + for (w = 0; w <= (Width - ColorW); w += ColorW) { + ColorList = + Enlist(ColorList, x + w, y + Height, ColorW, ColorH); + (*NumColor)++; + } + } + } + + if (DoMono && (Height >= MonoH)) { + while (Height >= MonoH) { + Height -= MonoH; + for (w = 0; w <= (Width - MonoW); w += MonoW) { + MonoList = + Enlist(MonoList, x + w, y + Height, MonoW, MonoH); + (*NumMono)++; + } + } + } + + pLink = pLink->next; + } + + *ListMono = MonoList; + *ListColor = ColorList; + FreeList(ListPartial); +} + +static CacheLinkPtr +ExtractOneThatFits(CacheLinkPtr * initList, int w, int h) +{ + CacheLinkPtr list = *initList; + CacheLinkPtr prev = NULL; + + while (list) { + if ((list->w >= w) && (list->h >= h)) + break; + prev = list; + list = list->next; + } + + if (list) { + if (prev) + prev->next = list->next; + else + *initList = list->next; + + list->next = NULL; + } + + return list; +} + +static CacheLinkPtr +ConvertSomePartialsTo8x8(int *NumMono, int *NumColor, int *NumPartial, + CacheLinkPtr ListPartial, + CacheLinkPtr * ListMono, + CacheLinkPtr * ListColor, + int *maxw, int *maxh, XAAInfoRecPtr infoRec) +{ +/* This guy tries to get 4 of each type of 8x8 slot requested out of + a list of fragments all while trying to retain some big fragments + for the cache blits */ + + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; + CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; + int Num64, Num32, Num16, Num8, NumKeepers; + int w, h, Width, Height; + int MonosPerColor = 1; + + if (DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if (MonoH > ColorH) + ColorH = MonoH; + if (MonoW > ColorW) + ColorW = MonoW; + MonosPerColor = (ColorH / MonoH) * (ColorW / MonoW); + } + + List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = + NULL; + Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; + Width = Height = 0; + + /* We sort partials by how large a square tile they can cache. + We make 8x8 patterns from the leftovers if we can. */ + + pCur = ListPartial; + while (pCur) { + next = pCur->next; + if ((pCur->w >= 64) && (pCur->h >= 64)) { + pCur->next = List64; + List64 = pCur; + Num64++; + } + else if ((pCur->w >= 32) && (pCur->h >= 32)) { + pCur->next = List32; + List32 = pCur; + Num32++; + } + else if ((pCur->w >= 16) && (pCur->h >= 16)) { + pCur->next = List16; + List16 = pCur; + Num16++; + } + else if ((pCur->w >= 8) && (pCur->h >= 8)) { + pCur->next = List8; + List8 = pCur; + Num8++; + } + else { + h = pCur->h; + if (DoColor && (pCur->w >= ColorW) && (h >= ColorH)) { + while (h >= ColorH) { + h -= ColorH; + for (w = 0; w <= (pCur->w - ColorW); w += ColorW) { + ColorList = Enlist(ColorList, + pCur->x + w, pCur->y + h, ColorW, + ColorH); + (*NumColor)++; + } + } + } + if (DoMono && (pCur->w >= MonoW) && (h >= MonoH)) { + while (h >= MonoH) { + h -= MonoH; + for (w = 0; w <= (pCur->w - MonoW); w += MonoW) { + MonoList = Enlist(MonoList, + pCur->x + w, pCur->y + h, MonoW, + MonoH); + (*NumMono)++; + } + } + } + free(pCur); + } + + pCur = next; + } + + /* Try to extract at least 4 of each type of 8x8 slot that we need */ + + if (DoColor) { + CacheLinkPtr theOne; + + while (*NumColor < 4) { + theOne = NULL; + if (Num8) { + if ((theOne = ExtractOneThatFits(&List8, ColorW, ColorH))) + Num8--; + } + if (Num16 && !theOne) { + if ((theOne = ExtractOneThatFits(&List16, ColorW, ColorH))) + Num16--; + } + if (Num32 && !theOne) { + if ((theOne = ExtractOneThatFits(&List32, ColorW, ColorH))) + Num32--; + } + if (Num64 && !theOne) { + if ((theOne = ExtractOneThatFits(&List64, ColorW, ColorH))) + Num64--; + } + + if (!theOne) + break; + + ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, + &MonoList, &ColorList, infoRec); + + if (DoMono) { + while (*NumColor && (*NumMono < 4)) { + ConvertColorToMono(&ColorList, ColorW, ColorH, + &MonoList, MonoW, MonoH); + (*NumColor)--; + *NumMono += MonosPerColor; + } + } + } + } + + if (DoMono) { + CacheLinkPtr theOne; + + while (*NumMono < 4) { + theOne = NULL; + if (Num8) { + if ((theOne = ExtractOneThatFits(&List8, MonoW, MonoH))) + Num8--; + } + if (Num16 && !theOne) { + if ((theOne = ExtractOneThatFits(&List16, MonoW, MonoH))) + Num16--; + } + if (Num32 && !theOne) { + if ((theOne = ExtractOneThatFits(&List32, MonoW, MonoH))) + Num32--; + } + if (Num64 && !theOne) { + if ((theOne = ExtractOneThatFits(&List64, MonoW, MonoH))) + Num64--; + } + + if (!theOne) + break; + + ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, + &MonoList, &ColorList, infoRec); + } + } + + /* We save all the tiles from the largest bin that we can get + at least 4 of. If there are too few of a bigger slot, we + cut it in fourths to make smaller slots. */ + + if (Num64 >= 4) { + ListKeepers = List64; + List64 = NULL; + NumKeepers = Num64; + goto GOT_EM; + } + else if (Num64) { + List32 = QuadLinks(List64, List32); + Num32 += Num64 * 4; + Num64 = 0; + } + + if (Num32 >= 4) { + ListKeepers = List32; + List32 = NULL; + NumKeepers = Num32; + goto GOT_EM; + } + else if (Num32) { + List16 = QuadLinks(List32, List16); + Num16 += Num32 * 4; + Num32 = 0; + } + + if (Num16 >= 4) { + ListKeepers = List16; + List16 = NULL; + NumKeepers = Num16; + goto GOT_EM; + } + else if (Num16) { + List8 = QuadLinks(List16, List8); + Num8 += Num16 * 4; + Num16 = 0; + } + + if (Num8 >= 4) { + ListKeepers = List8; + List8 = NULL; + NumKeepers = Num8; + goto GOT_EM; + } + + GOT_EM: + + /* Free the ones we aren't using */ + + if (List64) + ConvertAllPartialsTo8x8(NumMono, NumColor, List64, + &MonoList, &ColorList, infoRec); + if (List32) + ConvertAllPartialsTo8x8(NumMono, NumColor, List32, + &MonoList, &ColorList, infoRec); + if (List16) + ConvertAllPartialsTo8x8(NumMono, NumColor, List16, + &MonoList, &ColorList, infoRec); + if (List8) + ConvertAllPartialsTo8x8(NumMono, NumColor, List8, + &MonoList, &ColorList, infoRec); + + /* Enlarge the slots if we can */ + + if (ListKeepers) { + CacheLinkPtr pLink = ListKeepers; + + Width = Height = 128; + + while (pLink) { + if (pLink->w < Width) + Width = pLink->w; + if (pLink->h < Height) + Height = pLink->h; + pLink = pLink->next; + } + } + + *ListMono = MonoList; + *ListColor = ColorList; + *maxw = Width; + *maxh = Height; + *NumPartial = NumKeepers; + return ListKeepers; +} + +void +XAAInitPixmapCache(ScreenPtr pScreen, RegionPtr areas, void * data) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XAAInfoRecPtr infoRec = (XAAInfoRecPtr) data; + XAAPixmapCachePrivatePtr pCachePriv; + BoxPtr pBox = RegionRects(areas); + int nBox = RegionNumRects(areas); + int Num512, Num256, Num128, NumPartial, NumColor, NumMono; + int Target512, Target256; + CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono; + int x, y, w, h, ntotal, granularity, width, height, i; + int MaxPartialWidth, MaxPartialHeight; + + infoRec->MaxCacheableTileWidth = 0; + infoRec->MaxCacheableTileHeight = 0; + infoRec->MaxCacheableStippleHeight = 0; + infoRec->MaxCacheableStippleWidth = 0; + infoRec->UsingPixmapCache = FALSE; + + if (!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE)) + return; + + /* Allocate a persistent per-screen init flag to control messages */ + if (CacheInitIndex < 0) + CacheInitIndex = xf86AllocateScrnInfoPrivateIndex(); + + /* free the old private data if it exists */ + if (infoRec->PixmapCachePrivate) { + FreePixmapCachePrivate((XAAPixmapCachePrivatePtr) infoRec-> + PixmapCachePrivate); + infoRec->PixmapCachePrivate = NULL; + } + + Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; + List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL; + granularity = infoRec->CachePixelGranularity; + if (granularity <= 1) + granularity = 0; + + /* go through the boxes and break it into as many pieces as we can fit */ + + while (nBox--) { + x = pBox->x1; + if (granularity) { + int tmp = x % granularity; + + if (tmp) + x += (granularity - tmp); + } + width = pBox->x2 - x; + if (width <= 0) { + pBox++; + continue; + } + + y = pBox->y1; + height = pBox->y2 - y; + + for (h = 0; h <= (height - 512); h += 512) { + for (w = 0; w <= (width - 512); w += 512) { + List512 = Enlist(List512, x + w, y + h, 512, 512); + Num512++; + } + for (; w <= (width - 256); w += 256) { + List256 = Enlist(List256, x + w, y + h, 256, 256); + List256 = Enlist(List256, x + w, y + h + 256, 256, 256); + Num256 += 2; + } + for (; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + List128 = Enlist(List128, x + w, y + h + 128, 128, 128); + List128 = Enlist(List128, x + w, y + h + 256, 128, 128); + List128 = Enlist(List128, x + w, y + h + 384, 128, 128); + Num128 += 4; + } + if (w < width) { + int d = width - w; + + ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128); + NumPartial += 4; + } + } + for (; h <= (height - 256); h += 256) { + for (w = 0; w <= (width - 256); w += 256) { + List256 = Enlist(List256, x + w, y + h, 256, 256); + Num256++; + } + for (; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + List128 = Enlist(List128, x + w, y + h + 128, 128, 128); + Num128 += 2; + } + if (w < width) { + int d = width - w; + + ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); + NumPartial += 2; + } + } + for (; h <= (height - 128); h += 128) { + for (w = 0; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + Num128++; + } + if (w < width) { + ListPartial = Enlist(ListPartial, x + w, y + h, width - w, 128); + NumPartial++; + } + } + if (h < height) { + int d = height - h; + + for (w = 0; w <= (width - 128); w += 128) { + ListPartial = Enlist(ListPartial, x + w, y + h, 128, d); + NumPartial++; + } + if (w < width) { + ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d); + NumPartial++; + } + } + pBox++; + } + +/* + by this point we've carved the space into as many 512x512, 256x256 + and 128x128 blocks as we could fit. We will then break larger + blocks into smaller ones if we need to. The rules are as follows: + + 512x512 - + 1) Don't take up more than half the memory. + 2) Don't bother if you can't get at least four. + 3) Don't make more than MAX_512. + 4) Don't have any of there are no 256x256s. + + 256x256 - + 1) Don't take up more than a quarter of the memory enless there + aren't any 512x512s. Then we can take up to half. + 2) Don't bother if you can't get at least four. + 3) Don't make more than MAX_256. + + 128x128 - + 1) Don't make more than MAX_128. + + We don't bother with the partial blocks unless we can use them + for 8x8 pattern fills or we are short on larger blocks. + +*/ + + ntotal = Num128 + (Num256 << 2) + (Num512 << 4); + + Target512 = ntotal >> 5; + if (Target512 < 4) + Target512 = 0; + if (!Target512) + Target256 = ntotal >> 3; + else + Target256 = ntotal >> 4; + if (Target256 < 4) + Target256 = 0; + + if (Num512 && Num256 < 4) { + while (Num512 && Num256 < Target256) { + SubdivideList(&List512, &List256); + Num256 += 4; + Num512--; + } + } + + if (!Num512) { /* no room */ + } + else if ((Num512 < 4) || (!Target512)) { + while (Num512) { + SubdivideList(&List512, &List256); + Num256 += 4; + Num512--; + } + } + else if ((Num512 > MAX_512) || (Num512 > Target512)) { + while (Num512 > MAX_512) { + SubdivideList(&List512, &List256); + Num256 += 4; + Num512--; + } + while (Num512 > Target512) { + if (Num256 < MAX_256) { + SubdivideList(&List512, &List256); + Num256 += 4; + Num512--; + } + else + break; + } + } + + if (!Num256) { /* no room */ + } + else if ((Num256 < 4) || (!Target256)) { + while (Num256) { + SubdivideList(&List256, &List128); + Num128 += 4; + Num256--; + } + } + else if ((Num256 > MAX_256) || (Num256 > Target256)) { + while (Num256 > MAX_256) { + SubdivideList(&List256, &List128); + Num128 += 4; + Num256--; + } + while (Num256 > Target256) { + if (Num128 < MAX_128) { + SubdivideList(&List256, &List128); + Num128 += 4; + Num256--; + } + else + break; + } + } + + if (Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { + CacheLinkPtr next; + int max = (Num128 > MAX_128) ? MAX_128 : 0; + + /* + * Note: next is set in this way to work around a code generation + * bug in gcc 2.7.2.3. + */ + next = List128->next; + while (Num128 > max) { + List128->next = ListPartial; + ListPartial = List128; + if ((List128 = next)) + next = List128->next; + NumPartial++; + Num128--; + } + } + + MaxPartialHeight = MaxPartialWidth = 0; + + /* at this point we have as many 512x512 and 256x256 slots as we + want but may have an excess of 128x128 slots. We still need + to find out if we need 8x8 slots. We take these from the + partials if we have them. Otherwise, we break some 128x128's */ + + if (!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) { + if (NumPartial) { + if (Num128) { /* don't bother with partials */ + FreeList(ListPartial); + NumPartial = 0; + ListPartial = NULL; + } + else { + /* We have no big slots. Weed out the unusable partials */ + ListPartial = ThinOutPartials(ListPartial, &NumPartial, + &MaxPartialWidth, + &MaxPartialHeight); + } + } + } + else { + int MonosPerColor = 1; + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + + if (DoColor) + infoRec->CanDoColor8x8 = FALSE; + if (DoMono) + infoRec->CanDoMono8x8 = FALSE; + + if (DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if (MonoH > ColorH) + ColorH = MonoH; + if (MonoW > ColorW) + ColorW = MonoW; + MonosPerColor = (ColorH / MonoH) * (ColorW / MonoW); + } + + if (Num128) { + if (NumPartial) { /* use all for 8x8 slots */ + ConvertAllPartialsTo8x8(&NumMono, &NumColor, + ListPartial, &ListMono, &ListColor, + infoRec); + NumPartial = 0; + ListPartial = NULL; + } + + /* Get some 8x8 slots from the 128 slots */ + while ((Num128 > 4) && + ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) { + CacheLinkPtr tmp = NULL; + + tmp = Enlist(tmp, List128->x, List128->y, + List128->w, List128->h); + List128 = Delist(List128); + Num128--; + + ConvertAllPartialsTo8x8(&NumMono, &NumColor, + tmp, &ListMono, &ListColor, infoRec); + } + } + else if (NumPartial) { + /* We have share partials between 8x8 slots and tiles. */ + ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor, + &NumPartial, ListPartial, + &ListMono, &ListColor, + &MaxPartialWidth, + &MaxPartialHeight, infoRec); + } + + if (DoMono && DoColor) { + if (NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { + int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; + + while (NumColor > max) { + ConvertColorToMono(&ListColor, ColorW, ColorH, + &ListMono, MonoW, MonoH); + NumColor--; + NumMono += MonosPerColor; + } + } + + /* favor Mono slots over Color ones */ + while ((NumColor > 4) && (NumMono < MAX_MONO)) { + ConvertColorToMono(&ListColor, ColorW, ColorH, + &ListMono, MonoW, MonoH); + NumColor--; + NumMono += MonosPerColor; + } + } + + if (NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) { + int max = (NumMono > MAX_MONO) ? MAX_MONO : 0; + + while (NumMono > max) { + ListMono = Delist(ListMono); + NumMono--; + } + } + if (NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { + int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; + + while (NumColor > max) { + ListColor = Delist(ListColor); + NumColor--; + } + } + } + + pCachePriv = calloc(1, sizeof(XAAPixmapCachePrivate)); + if (!pCachePriv) { + if (Num512) + FreeList(List512); + if (Num256) + FreeList(List256); + if (Num128) + FreeList(List128); + if (NumPartial) + FreeList(ListPartial); + if (NumColor) + FreeList(ListColor); + if (NumMono) + FreeList(ListMono); + return; + } + + infoRec->PixmapCachePrivate = (char *) pCachePriv; + + if (Num512) { + pCachePriv->Info512 = calloc(Num512, sizeof(XAACacheInfoRec)); + if (!pCachePriv->Info512) + Num512 = 0; + if (Num512) + TransferList(List512, pCachePriv->Info512, Num512); + FreeList(List512); + pCachePriv->Num512x512 = Num512; + } + if (Num256) { + pCachePriv->Info256 = calloc(Num256, sizeof(XAACacheInfoRec)); + if (!pCachePriv->Info256) + Num256 = 0; + if (Num256) + TransferList(List256, pCachePriv->Info256, Num256); + FreeList(List256); + pCachePriv->Num256x256 = Num256; + } + if (Num128) { + pCachePriv->Info128 = calloc(Num128, sizeof(XAACacheInfoRec)); + if (!pCachePriv->Info128) + Num128 = 0; + if (Num128) + TransferList(List128, pCachePriv->Info128, Num128); + FreeList(List128); + pCachePriv->Num128x128 = Num128; + } + + if (NumPartial) { + pCachePriv->InfoPartial = calloc(NumPartial, sizeof(XAACacheInfoRec)); + if (!pCachePriv->InfoPartial) + NumPartial = 0; + if (NumPartial) + TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial); + FreeList(ListPartial); + pCachePriv->NumPartial = NumPartial; + } + + if (NumColor) { + pCachePriv->InfoColor = calloc(NumColor, sizeof(XAACacheInfoRec)); + if (!pCachePriv->InfoColor) + NumColor = 0; + if (NumColor) + TransferList(ListColor, pCachePriv->InfoColor, NumColor); + FreeList(ListColor); + pCachePriv->NumColor = NumColor; + } + + if (NumMono) { + pCachePriv->InfoMono = calloc(NumMono, sizeof(XAACacheInfoRec)); + if (!pCachePriv->InfoMono) + NumMono = 0; + if (NumMono) + TransferList(ListMono, pCachePriv->InfoMono, NumMono); + FreeList(ListMono); + pCachePriv->NumMono = NumMono; + } + + if (NumPartial) { + infoRec->MaxCacheableTileWidth = MaxPartialWidth; + infoRec->MaxCacheableTileHeight = MaxPartialHeight; + } + if (Num128) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128; + if (Num256) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256; + if (Num512) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512; + + infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight; + infoRec->MaxCacheableStippleWidth = + infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel; + if (infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) + infoRec->MaxCacheableStippleWidth /= 3; + + if (NumMono) { + if (!(infoRec->Mono8x8PatternFillFlags & + (HARDWARE_PATTERN_PROGRAMMED_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS))) { + int numPerLine = + infoRec->CacheWidthMono8x8Pattern / infoRec->MonoPatternPitch; + + for (i = 0; i < 64; i++) { + pCachePriv->MonoOffsets[i].y = i / numPerLine; + pCachePriv->MonoOffsets[i].x = (i % numPerLine) * + infoRec->MonoPatternPitch; + } + } + infoRec->CanDoMono8x8 = TRUE; + } + if (NumColor) { + if (!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + + for (i = 0; i < 64; i++) { + pCachePriv->ColorOffsets[i].y = i & 0x07; + pCachePriv->ColorOffsets[i].x = i & ~0x07; + } + } + infoRec->CanDoColor8x8 = TRUE; + } + + if (!CACHEINIT(pScrn)) { + xf86ErrorF("\tSetting up tile and stipple cache:\n"); + if (NumPartial) + xf86ErrorF("\t\t%i %ix%i slots\n", + NumPartial, MaxPartialWidth, MaxPartialHeight); + if (Num128) + xf86ErrorF("\t\t%i 128x128 slots\n", Num128); + if (Num256) + xf86ErrorF("\t\t%i 256x256 slots\n", Num256); + if (Num512) + xf86ErrorF("\t\t%i 512x512 slots\n", Num512); + if (NumColor) + xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor); + if (NumMono) + xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono); + } + + if (!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) { + if (!CACHEINIT(pScrn)) + xf86ErrorF("\t\tNot enough video memory for pixmap cache\n"); + } + else + infoRec->UsingPixmapCache = TRUE; + + CACHEINIT(pScrn) = 1; +} + +#if X_BYTE_ORDER == X_BIG_ENDIAN +static CARD32 StippleMasks[4] = { + 0x80808080, + 0xC0C0C0C0, + 0x00000000, + 0xF0F0F0F0 +}; +#else +static CARD32 StippleMasks[4] = { + 0x01010101, + 0x03030303, + 0x00000000, + 0x0F0F0F0F +}; +#endif + +Bool +XAACheckStippleReducibility(PixmapPtr pPixmap) +{ + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); + CARD32 *IntPtr = (CARD32 *) pPixmap->devPrivate.ptr; + int w = pPixmap->drawable.width; + int h = pPixmap->drawable.height; + int i; + CARD32 bits[8]; + CARD32 mask = SHIFT_R(0xFFFFFFFF, 24); + + pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR; + pPriv->flags &= ~REDUCIBLE_TO_8x8; + + if ((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) + return FALSE; + + i = (h > 8) ? 8 : h; + + switch (w) { + case 32: + while (i--) { + bits[i] = IntPtr[i] & mask; + if ((bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) || + (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 16)), 16)) || + (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 24)), 24))) + return FALSE; + } + break; + case 16: + while (i--) { + bits[i] = IntPtr[i] & mask; + if (bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask, 8), 8)))) + return FALSE; + } + break; + default: + while (i--) + bits[i] = IntPtr[i] & mask; + break; + } + + switch (h) { + case 32: + if ((IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) || + (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) || + (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) || + (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) || + (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) || + (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) || + (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) || + (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31])) + return FALSE; + /* fall through */ + case 16: + if ((IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) || + (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) || + (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) || + (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15])) + return FALSE; + case 8: + break; + case 1: + bits[1] = bits[0]; + case 2: + bits[2] = bits[0]; + bits[3] = bits[1]; + case 4: + bits[4] = bits[0]; + bits[5] = bits[1]; + bits[6] = bits[2]; + bits[7] = bits[3]; + break; + } + + pPriv->flags |= REDUCIBLE_TO_8x8; + + pPriv->pattern0 = + bits[0] | SHIFT_L(bits[1], 8) | SHIFT_L(bits[2], 16) | SHIFT_L(bits[3], + 24); + pPriv->pattern1 = + bits[4] | SHIFT_L(bits[5], 8) | SHIFT_L(bits[6], 16) | SHIFT_L(bits[7], + 24); + + if (w < 8) { + pPriv->pattern0 &= StippleMasks[w - 1]; + pPriv->pattern1 &= StippleMasks[w - 1]; + + switch (w) { + case 1: + pPriv->pattern0 |= SHIFT_L(pPriv->pattern0, 1); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1, 1); + case 2: + pPriv->pattern0 |= SHIFT_L(pPriv->pattern0, 2); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1, 2); + case 4: + pPriv->pattern0 |= SHIFT_L(pPriv->pattern0, 4); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1, 4); + } + } + + if (infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); + pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); + } + + return TRUE; +} + +Bool +XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono) +{ + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + CARD32 *IntPtr; + int w = pPixmap->drawable.width; + int h = pPixmap->drawable.height; + int pitch = pPixmap->devKind >> 2; + int dwords, i, j; + + pPriv->flags |= REDUCIBILITY_CHECKED; + pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR); + + if ((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) + return FALSE; + + dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5; + i = (h > 8) ? 8 : h; + + if (w > 8) { + IntPtr = (CARD32 *) pPixmap->devPrivate.ptr; + switch (pPixmap->drawable.bitsPerPixel) { + case 8: + while (i--) { + for (j = 2; j < dwords; j++) + if (IntPtr[j] != IntPtr[j & 0x01]) + return FALSE; + IntPtr += pitch; + } + break; + case 16: + while (i--) { + for (j = 4; j < dwords; j++) + if (IntPtr[j] != IntPtr[j & 0x03]) + return FALSE; + IntPtr += pitch; + } + break; + case 24: + while (i--) { + for (j = 6; j < dwords; j++) + if (IntPtr[j] != IntPtr[j % 6]) + return FALSE; + IntPtr += pitch; + } + break; + case 32: + while (i--) { + for (j = 8; j < dwords; j++) + if (IntPtr[j] != IntPtr[j & 0x07]) + return FALSE; + IntPtr += pitch; + } + break; + default: + return FALSE; + } + + } + + if (h == 32) { + CARD32 *IntPtr2, *IntPtr3, *IntPtr4; + + i = 8; + IntPtr = (CARD32 *) pPixmap->devPrivate.ptr; + IntPtr2 = IntPtr + (pitch << 3); + IntPtr3 = IntPtr2 + (pitch << 3); + IntPtr4 = IntPtr3 + (pitch << 3); + while (i--) { + for (j = 0; j < dwords; j++) + if ((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) || + (IntPtr[j] != IntPtr4[j])) + return FALSE; + IntPtr += pitch; + IntPtr2 += pitch; + IntPtr3 += pitch; + IntPtr4 += pitch; + } + } + else if (h == 16) { + CARD32 *IntPtr2; + + i = 8; + IntPtr = (CARD32 *) pPixmap->devPrivate.ptr; + IntPtr2 = IntPtr + (pitch << 3); + while (i--) { + for (j = 0; j < dwords; j++) + if (IntPtr[j] != IntPtr2[j]) + return FALSE; + IntPtr += pitch; + IntPtr2 += pitch; + } + } + + pPriv->flags |= REDUCIBLE_TO_8x8; + + if (checkMono) { + XAAInfoRecPtr infoRec = + GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); + unsigned char bits[8]; + int fg, bg = -1, x, y; + + i = (h > 8) ? 8 : h; + j = (w > 8) ? 8 : w; + + if (pPixmap->drawable.bitsPerPixel == 8) { + unsigned char *srcp = pPixmap->devPrivate.ptr; + + fg = srcp[0]; + pitch = pPixmap->devKind; + for (y = 0; y < i; y++) { + bits[y] = 0; + for (x = 0; x < j; x++) { + if (srcp[x] != fg) { + if (bg == -1) + bg = srcp[x]; + else if (bg != srcp[x]) + return TRUE; + } + else + bits[y] |= 1 << x; + } + srcp += pitch; + } + } + else if (pPixmap->drawable.bitsPerPixel == 16) { + unsigned short *srcp = (unsigned short *) pPixmap->devPrivate.ptr; + + fg = srcp[0]; + pitch = pPixmap->devKind >> 1; + for (y = 0; y < i; y++) { + bits[y] = 0; + for (x = 0; x < j; x++) { + if (srcp[x] != fg) { + if (bg == -1) + bg = srcp[x]; + else if (bg != srcp[x]) + return TRUE; + } + else + bits[y] |= 1 << x; + } + srcp += pitch; + } + } + else if (pPixmap->drawable.bitsPerPixel == 24) { + CARD32 val; + unsigned char *srcp = pPixmap->devPrivate.ptr; + + fg = *((CARD32 *) srcp) & 0x00FFFFFF; + pitch = pPixmap->devKind; + j *= 3; + for (y = 0; y < i; y++) { + bits[y] = 0; + for (x = 0; x < j; x += 3) { + val = *((CARD32 *) (srcp + x)) & 0x00FFFFFF; + if (val != fg) { + if (bg == -1) + bg = val; + else if (bg != val) + return TRUE; + } + else + bits[y] |= 1 << (x / 3); + } + srcp += pitch; + } + } + else if (pPixmap->drawable.bitsPerPixel == 32) { + IntPtr = (CARD32 *) pPixmap->devPrivate.ptr; + fg = IntPtr[0]; + for (y = 0; y < i; y++) { + bits[y] = 0; + for (x = 0; x < j; x++) { + if (IntPtr[x] != fg) { + if (bg == -1) + bg = IntPtr[x]; + else if (bg != IntPtr[x]) + return TRUE; + } + else + bits[y] |= 1 << x; + } + IntPtr += pitch; + } + } + else + return TRUE; + + pPriv->fg = fg; + if (bg == -1) + pPriv->bg = fg; + else + pPriv->bg = bg; + + if (h < 8) { + switch (h) { + case 1: + bits[1] = bits[0]; + case 2: + bits[2] = bits[0]; + bits[3] = bits[1]; + case 4: + bits[4] = bits[0]; + bits[5] = bits[1]; + bits[6] = bits[2]; + bits[7] = bits[3]; + break; + } + } + + pPriv->pattern0 = + bits[0] | (bits[1] << 8) | (bits[2] << 16) | (bits[3] << 24); + pPriv->pattern1 = + bits[4] | (bits[5] << 8) | (bits[6] << 16) | (bits[7] << 24); + + if (w < 8) { + switch (w) { + case 1: + pPriv->pattern0 |= (pPriv->pattern0 << 1); + pPriv->pattern1 |= (pPriv->pattern1 << 1); + case 2: + pPriv->pattern0 |= (pPriv->pattern0 << 2); + pPriv->pattern1 |= (pPriv->pattern1 << 2); + case 4: + pPriv->pattern0 |= (pPriv->pattern0 << 4); + pPriv->pattern1 |= (pPriv->pattern1 << 4); + } + } + pPriv->flags |= REDUCIBLE_TO_2_COLOR; + + if (infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); + pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); + } + + } + + return TRUE; +} + +void +XAATileCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache, int w, int h) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SetupForScreenToScreenCopy) (pScrn, 1, 1, GXcopy, ~0, -1); + + while ((w << 1) <= pCache->w) { + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pCache->x, pCache->y, + pCache->x + w, pCache->y, w, + h); + w <<= 1; + } + if (w != pCache->w) { + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pCache->x, pCache->y, + pCache->x + w, pCache->y, + pCache->w - w, h); + w = pCache->w; + } + + while ((h << 1) <= pCache->h) { + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pCache->x, pCache->y, + pCache->x, pCache->y + h, w, + h); + h <<= 1; + } + if (h != pCache->h) { + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, pCache->x, pCache->y, + pCache->x, pCache->y + h, w, + pCache->h - h); + } + SET_SYNC_FLAG(infoRec); +} + +XAACacheInfoPtr +XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + int size = max(w, h); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if (size <= 128) { + if (pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } + else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } + else if (size <= 256) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } + else if (size <= 512) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } + else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheTile()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for (i = 0; i < max; i++, pCache++) { + if (pCache->serialNumber == pPix->drawable.serialNumber) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if (*current >= max) + *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; + pCache->orig_h = h; + (*infoRec->WritePixmapToCache) (pScrn, pCache->x, pCache->y, w, h, + pPix->devPrivate.ptr, pPix->devKind, + pPix->drawable.bitsPerPixel, + pPix->drawable.depth); + if (!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACacheInfoPtr +XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel; + int *current; + StippleScanlineProcPtr StippleFunc; + unsigned char *data, *srcPtr, *dstPtr; + + if ((h <= 128) && (w <= 128 * bpp)) { + if (pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } + else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } + else if ((h <= 256) && (w <= 256 * bpp)) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } + else if ((h <= 512) && (w <= 526 * bpp)) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } + else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for (i = 0; i < max; i++, pCache++) { + if ((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if (*current >= max) + *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; + pCache->orig_h = h; + + if (w <= 32) { + if (w & (w - 1)) + funcNo = 1; + else + funcNo = 0; + } + else + funcNo = 2; + + pad = BitmapBytePad(pCache->w * bpp); + dwords = bytes_to_int32(pad); + dstPtr = data = (unsigned char *) malloc(pad * pCache->h); + srcPtr = (unsigned char *) pPix->devPrivate.ptr; + + if (infoRec-> + ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; + else + StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo]; + + /* don't bother generating more than we'll ever use */ + max = ((pScrn->displayWidth + w - 1) + 31) >> 5; + if (dwords > max) + dwords = max; + + for (i = 0; i < h; i++) { + (*StippleFunc) ((CARD32 *) dstPtr, (CARD32 *) srcPtr, 0, w, dwords); + srcPtr += pPix->devKind; + dstPtr += pad; + } + + while ((h << 1) <= pCache->h) { + memcpy(data + (pad * h), data, pad * h); + h <<= 1; + } + + if (h < pCache->h) + memcpy(data + (pad * h), data, pad * (pCache->h - h)); + + (*infoRec->WritePixmapToCache) (pScrn, pCache->x, pCache->y, pCache->w, + pCache->h, data, pad, bpp, pScrn->depth); + + free(data); + + return pCache; +} + +XAACacheInfoPtr +XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if ((h <= 128) && (w <= 128)) { + if (pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } + else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } + else if ((h <= 256) && (w <= 256)) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } + else if ((h <= 512) && (w <= 526)) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } + else { /* something's wrong */ + ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for (i = 0; i < max; i++, pCache++) { + if ((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if (*current >= max) + *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; + pCache->orig_h = h; + + /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */ + (*infoRec->WriteBitmapToCache) (pScrn, pCache->x, pCache->y, + pPix->drawable.width, pPix->drawable.height, + pPix->devPrivate.ptr, pPix->devKind, 1, 2); + if (!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACachePlanarMonoStippleProc +XAAGetCachePlanarMonoStipple(void) +{ + return XAACachePlanarMonoStipple; +} + +XAACacheInfoPtr +XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + int size = max(w, h); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if (size <= 128) { + if (pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } + else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } + else if (size <= 256) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } + else if (size <= 512) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } + else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + /* lets look for it */ + if (bg == -1) + for (i = 0; i < max; i++, pCache++) { + if ((pCache->serialNumber == pPix->drawable.serialNumber) && + (fg == pCache->fg) && (pCache->fg != pCache->bg)) { + pCache->trans_color = pCache->bg; + return pCache; + } + } + else + for (i = 0; i < max; i++, pCache++) { + if ((pCache->serialNumber == pPix->drawable.serialNumber) && + (fg == pCache->fg) && (bg == pCache->bg)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if (*current >= max) + *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->fg = fg; + if (bg == -1) + pCache->trans_color = bg = fg ^ 1; + else + pCache->trans_color = -1; + pCache->bg = bg; + + pCache->orig_w = w; + pCache->orig_h = h; + (*infoRec->WriteBitmapToCache) (pScrn, pCache->x, pCache->y, + pPix->drawable.width, pPix->drawable.height, + pPix->devPrivate.ptr, pPix->devKind, fg, + bg); + if (!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACacheInfoPtr +XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache = pCachePriv->InfoMono; + int i; + + for (i = 0; i < pCachePriv->NumMono; i++, pCache++) { + if (pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1)) + return pCache; + } + + /* OK, let's cache it */ + pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++]; + if (pCachePriv->CurrentMono >= pCachePriv->NumMono) + pCachePriv->CurrentMono = 0; + + pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */ + pCache->pat0 = pat0; + pCache->pat1 = pat1; + + (*infoRec->WriteMono8x8PatternToCache) (pScrn, pCache); + + return pCache; +} + +XAACacheInfoPtr +XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache = pCachePriv->InfoColor; + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + int i; + + if (!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) { + for (i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if (pCache->serialNumber == pPix->drawable.serialNumber) { + pCache->trans_color = -1; + return pCache; + } + } + pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; + if (pCachePriv->CurrentColor >= pCachePriv->NumColor) + pCachePriv->CurrentColor = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->fg = pCache->bg = -1; + } + else { + int pat0 = pixPriv->pattern0; + int pat1 = pixPriv->pattern1; + + if (fg == -1) { /* it's a tile */ + fg = pixPriv->fg; + bg = pixPriv->bg; + } + + if (bg == -1) { /* stipple */ + for (i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if (pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && + (pCache->fg == fg) && (pCache->bg != fg)) { + pCache->trans_color = pCache->bg; + return pCache; + } + } + } + else { /* opaque stipple */ + for (i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if (pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && + (pCache->fg == fg) && (pCache->bg == bg)) { + pCache->trans_color = -1; + return pCache; + } + } + } + pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; + if (pCachePriv->CurrentColor >= pCachePriv->NumColor) + pCachePriv->CurrentColor = 0; + + if (bg == -1) + pCache->trans_color = bg = fg ^ 1; + else + pCache->trans_color = -1; + + pCache->pat0 = pat0; + pCache->pat1 = pat1; + pCache->fg = fg; + pCache->bg = bg; + pCache->serialNumber = 1; + } + + (*infoRec->WriteColor8x8PatternToCache) (pScrn, pPix, pCache); + + return pCache; +} + +void +XAAWriteBitmapToCache(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, int bg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->WriteBitmap) (pScrn, x, y, w, h, src, srcwidth, + 0, fg, bg, GXcopy, ~0); +} + +void +XAAWriteBitmapToCacheLinear(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, int bg) +{ + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + PixmapPtr pScreenPix, pDstPix; + ChangeGCVal gcvals[2]; + GCPtr pGC; + + pScreenPix = (*pScreen->GetScreenPixmap) (pScreen); + + pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width, + y + h, pScreenPix->drawable.depth, + pScreenPix->drawable.bitsPerPixel, + pScreenPix->devKind, + pScreenPix->devPrivate.ptr); + + pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen); + gcvals[0].val = fg; + gcvals[1].val = bg; + ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcvals); + ValidateGC((DrawablePtr) pDstPix, pGC); + + /* We've unwrapped already so these ops miss a sync */ + SYNC_CHECK(pScrn); + + (*pGC->ops->PutImage) ((DrawablePtr) pDstPix, pGC, 1, x, y, w, h, 0, + XYBitmap, (void *) src); + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(pDstPix); +} + +void +XAAWritePixmapToCache(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, int srcwidth, int bpp, int depth) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->WritePixmap) (pScrn, x, y, w, h, src, srcwidth, + GXcopy, ~0, -1, bpp, depth); +} + +void +XAAWritePixmapToCacheLinear(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, int bpp, int depth) +{ + ScreenPtr pScreen = xf86ScrnToScreen(pScrn); + PixmapPtr pScreenPix, pDstPix; + GCPtr pGC; + + pScreenPix = (*pScreen->GetScreenPixmap) (pScreen); + + pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h, + depth, bpp, pScreenPix->devKind, + pScreenPix->devPrivate.ptr); + + pGC = GetScratchGC(depth, pScreen); + ValidateGC((DrawablePtr) pDstPix, pGC); + + /* We've unwrapped already so these ops miss a sync */ + SYNC_CHECK(pScrn); + + if (bpp == BitsPerPixel(depth)) + (*pGC->ops->PutImage) ((DrawablePtr) pDstPix, pGC, depth, x, y, w, + h, 0, ZPixmap, (void *) src); + else { + PixmapPtr pSrcPix; + + pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp, + srcwidth, (void *) src); + + (*pGC->ops->CopyArea) ((DrawablePtr) pSrcPix, (DrawablePtr) pDstPix, + pGC, 0, 0, w, h, x, y); + + FreeScratchPixmapHeader(pSrcPix); + } + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(pDstPix); +} + +void +XAAWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + unsigned char *data; + int pad, Bpp = (pScrn->bitsPerPixel >> 3); + + pCache->offsets = pCachePriv->MonoOffsets; + + pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); + + data = (unsigned char *) malloc(pad * pCache->h); + if (!data) + return; + + if (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + CARD32 *ptr = (CARD32 *) data; + + ptr[0] = pCache->pat0; + ptr[1] = pCache->pat1; + } + else { + CARD32 *ptr; + DDXPointPtr pPoint = pCache->offsets; + int patx, paty, i; + + for (i = 0; i < 64; i++, pPoint++) { + patx = pCache->pat0; + paty = pCache->pat1; + XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + ptr = (CARD32 *) (data + (pad * pPoint->y) + (Bpp * pPoint->x)); + ptr[0] = patx; + ptr[1] = paty; + } + } + + (*infoRec->WritePixmapToCache) (pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, + pScrn->bitsPerPixel, pScrn->depth); + + free(data); +} + +void +XAAWriteColor8x8PatternToCache(ScrnInfoPtr pScrn, + PixmapPtr pPix, XAACacheInfoPtr pCache) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + int pad, i, w, h, nw, nh, Bpp; + unsigned char *data, *srcPtr, *dstPtr; + + pCache->offsets = pCachePriv->ColorOffsets; + + if (pixPriv->flags & REDUCIBLE_TO_2_COLOR) { + CARD32 *ptr; + + pad = BitmapBytePad(pCache->w); + data = (unsigned char *) malloc(pad * pCache->h); + if (!data) + return; + + if (infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + ptr = (CARD32 *) data; + ptr[0] = pCache->pat0; + ptr[1] = pCache->pat1; + } + else { + int patx, paty; + + ptr = (CARD32 *) data; + ptr[0] = ptr[2] = pCache->pat0; + ptr[1] = ptr[3] = pCache->pat1; + for (i = 1; i < 8; i++) { + patx = pCache->pat0; + paty = pCache->pat1; + XAARotateMonoPattern(&patx, &paty, i, 0, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + ptr = (CARD32 *) (data + (pad * i)); + ptr[0] = ptr[2] = patx; + ptr[1] = ptr[3] = paty; + } + } + + (*infoRec->WriteBitmapToCache) (pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, + pCache->fg, pCache->bg); + + free(data); + return; + } + + Bpp = pScrn->bitsPerPixel >> 3; + h = min(8, pPix->drawable.height); + w = min(8, pPix->drawable.width); + pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); + + data = (unsigned char *) malloc(pad * pCache->h); + if (!data) + return; + + /* Write and expand horizontally. */ + for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--; + srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) { + nw = w; + memcpy(dstPtr, srcPtr, w * Bpp); + while (nw != 8) { + memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp); + nw <<= 1; + } + } + nh = h; + /* Expand vertically. */ + while (nh != 8) { + memcpy(data + (nh * pScrn->bitsPerPixel), data, + nh * pScrn->bitsPerPixel); + nh <<= 1; + } + + if (!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int j; + unsigned char *ptr = data + (128 * Bpp); + + memcpy(data + (64 * Bpp), data, 64 * Bpp); + for (i = 1; i < 8; i++, ptr += (128 * Bpp)) { + for (j = 0; j < 8; j++) { + memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp, + (8 - i) * Bpp); + memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, + i * Bpp); + } + memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp); + } + } + + (*infoRec->WritePixmapToCache) (pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, + pScrn->bitsPerPixel, pScrn->depth); + + free(data); +} + +int +XAAStippledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->stipple; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if (!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckStippleReducibility(pPixmap); + } + + if (pPriv->flags & REDUCIBLE_TO_8x8) { + if (infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_FG(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if (infoRec->CanDoColor8x8 && + !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC, infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if (infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / + infoRec->CacheColorExpandDensity) && + !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC, infoRec->FillCacheExpandSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillCacheExpandSpansFlags) && + CHECK_FG(pGC, infoRec->FillCacheExpandSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillCacheExpandSpansFlags)) { + + return DO_CACHE_EXPAND; + } + + if (infoRec->UsingPixmapCache && + !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && + infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if (infoRec->FillColorExpandSpans && + !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC, infoRec->FillColorExpandSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillColorExpandSpansFlags) && + CHECK_FG(pGC, infoRec->FillColorExpandSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillColorExpandSpansFlags)) { + + return DO_COLOR_EXPAND; + } + + return 0; +} + +int +XAAOpaqueStippledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->stipple; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if (XAA_DEPTH_BUG(pGC)) + return 0; + + if (!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckStippleReducibility(pPixmap); + } + + if (pPriv->flags & REDUCIBLE_TO_8x8) { + if (infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_COLORS(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if (infoRec->CanDoColor8x8 && + CHECK_ROP(pGC, infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if (infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / + infoRec->CacheColorExpandDensity) && + !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC, infoRec->FillCacheExpandSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillCacheExpandSpansFlags) && + CHECK_COLORS(pGC, infoRec->FillCacheExpandSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillCacheExpandSpansFlags)) { + + return DO_CACHE_EXPAND; + } + + if (infoRec->UsingPixmapCache && + !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && + infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + CHECK_ROP(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if (infoRec->FillColorExpandSpans && + !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC, infoRec->FillColorExpandSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillColorExpandSpansFlags) && + CHECK_COLORS(pGC, infoRec->FillColorExpandSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillColorExpandSpansFlags)) { + + return DO_COLOR_EXPAND; + } + + return 0; +} + +int +XAATiledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->tile.pixmap; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if (IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans && + CHECK_ROP(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillCacheBltSpansFlags)) { + + return DO_PIXMAP_COPY; + } + + if (!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckTileReducibility(pPixmap, infoRec->CanDoMono8x8); + } + + if (pPriv->flags & REDUCIBLE_TO_8x8) { + if ((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC, infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillMono8x8PatternSpansFlags) && + (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) && + CHECK_PLANEMASK(pGC, infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if (infoRec->CanDoColor8x8 && + CHECK_ROP(pGC, infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if (infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + CHECK_ROP(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC, infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if (infoRec->FillImageWriteRects && + CHECK_NO_GXCOPY(pGC, infoRec->FillImageWriteRectsFlags) && + CHECK_ROP(pGC, infoRec->FillImageWriteRectsFlags) && + CHECK_ROPSRC(pGC, infoRec->FillImageWriteRectsFlags) && + CHECK_PLANEMASK(pGC, infoRec->FillImageWriteRectsFlags)) { + + return DO_IMAGE_WRITE; + } + + return 0; +} + +static int RotateMasksX[8] = { + 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F, + 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101 +}; + +static int RotateMasksY[4] = { + 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF +}; + +void +XAARotateMonoPattern(int *pat0, int *pat1, int xorg, int yorg, Bool msbfirst) +{ + int tmp, mask; + + if (xorg) { + if (msbfirst) + xorg = 8 - xorg; + mask = RotateMasksX[xorg]; + *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask); + *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask); + } + if (yorg >= 4) { + tmp = *pat0; + *pat0 = *pat1; + *pat1 = tmp; + yorg -= 4; + } + if (yorg) { + mask = RotateMasksY[yorg]; + yorg <<= 3; + tmp = *pat0; + *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask); + *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask); + } +} + +void +XAAInvalidatePixmapCache(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr) infoRec->PixmapCachePrivate; + int i; + + if (!pCachePriv) + return; + + for (i = 0; i < pCachePriv->Num512x512; i++) + (pCachePriv->Info512)[i].serialNumber = 0; + for (i = 0; i < pCachePriv->Num256x256; i++) + (pCachePriv->Info256)[i].serialNumber = 0; + for (i = 0; i < pCachePriv->Num128x128; i++) + (pCachePriv->Info128)[i].serialNumber = 0; + for (i = 0; i < pCachePriv->NumPartial; i++) + (pCachePriv->InfoPartial)[i].serialNumber = 0; + for (i = 0; i < pCachePriv->NumMono; i++) + (pCachePriv->InfoMono)[i].serialNumber = 0; + for (i = 0; i < pCachePriv->NumColor; i++) + (pCachePriv->InfoColor)[i].serialNumber = 0; +} diff --git a/hw/xfree86/xaa/xaaPict.c b/hw/xfree86/xaa/xaaPict.c new file mode 100644 index 000000000..0721768ed --- /dev/null +++ b/hw/xfree86/xaa/xaaPict.c @@ -0,0 +1,654 @@ +/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "picturestr.h" +#include "glyphstr.h" +#include "picture.h" +#include "mipict.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "xaacexp.h" +#include "xf86fbman.h" +#include "servermd.h" + +Bool +XAAGetPixelFromRGBA(CARD32 *pixel, + CARD16 red, + CARD16 green, CARD16 blue, CARD16 alpha, CARD32 format) +{ + int rbits, bbits, gbits, abits; + int rshift, bshift, gshift, ashift; + + *pixel = 0; + + if (!PICT_FORMAT_COLOR(format)) + 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; + + *pixel |= (blue >> (16 - bbits)) << bshift; + *pixel |= (red >> (16 - rbits)) << rshift; + *pixel |= (green >> (16 - gbits)) << gshift; + *pixel |= (alpha >> (16 - abits)) << ashift; + + return TRUE; +} + +Bool +XAAGetRGBAFromPixel(CARD32 pixel, + CARD16 *red, + CARD16 *green, CARD16 *blue, CARD16 *alpha, CARD32 format) +{ + int rbits, bbits, gbits, abits; + int rshift, bshift, gshift, ashift; + + if (!PICT_FORMAT_COLOR(format)) + 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; + + *red = ((pixel >> rshift) & ((1 << rbits) - 1)) << (16 - rbits); + while (rbits < 16) { + *red |= *red >> rbits; + rbits <<= 1; + } + + *green = ((pixel >> gshift) & ((1 << gbits) - 1)) << (16 - gbits); + while (gbits < 16) { + *green |= *green >> gbits; + gbits <<= 1; + } + + *blue = ((pixel >> bshift) & ((1 << bbits) - 1)) << (16 - bbits); + while (bbits < 16) { + *blue |= *blue >> bbits; + bbits <<= 1; + } + + if (abits) { + *alpha = ((pixel >> ashift) & ((1 << abits) - 1)) << (16 - abits); + while (abits < 16) { + *alpha |= *alpha >> abits; + abits <<= 1; + } + } + else + *alpha = 0xffff; + + return TRUE; +} + +/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */ + +void +XAA_888_plus_PICT_a8_to_8888(CARD32 color, CARD8 *alphaPtr, /* in bytes */ + int alphaPitch, CARD32 *dstPtr, int dstPitch, /* in dwords */ + int width, int height) +{ + int x; + + color &= 0x00ffffff; + + while (height--) { + for (x = 0; x < width; x++) + dstPtr[x] = color | (alphaPtr[x] << 24); + dstPtr += dstPitch; + alphaPtr += alphaPitch; + } +} + +#define DRAWABLE_IS_ON_CARD(pDraw) \ + (pDraw->type == DRAWABLE_WINDOW || \ + (pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw))) + +Bool +XAADoComposite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + RegionRec region; + CARD32 *formats, *dstformats; + int flags = 0; + BoxPtr pbox; + int nbox, w, h; + + if (!RegionNumRects(pDst->pCompositeClip)) + return TRUE; + + if (!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable)) + return FALSE; + + if (DRAWABLE_IS_ON_CARD(pSrc->pDrawable)) + return FALSE; + + if (pSrc->transform || (pMask && pMask->transform)) + return FALSE; + + if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) + return FALSE; + + if ((pSrc->repeat && pSrc->repeatType != RepeatNormal) || + (pMask && pMask->repeat && pMask->repeatType != RepeatNormal)) { + return FALSE; + } + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if (pMask) { + if (pMask->componentAlpha) + return FALSE; + + /* for now we only do it if there is a 1x1 (solid) source */ + + if ((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) { + CARD16 red, green, blue, alpha; + CARD32 pixel = + *((CARD32 *) (((PixmapPtr) (pSrc->pDrawable))->devPrivate.ptr)); + + if (!XAAGetRGBAFromPixel + (pixel, &red, &green, &blue, &alpha, pSrc->format)) + return FALSE; + + xMask += pMask->pDrawable->x; + yMask += pMask->pDrawable->y; + + /* pull out color expandable operations here */ + if ((pMask->format == PICT_a1) && (alpha == 0xffff) && + (op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) && + (!(infoRec->WriteBitmapFlags & RGB_EQUAL) || + ((red == green) && (green == blue)))) { + PixmapPtr pPix = (PixmapPtr) (pMask->pDrawable); + int skipleft; + + if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, + yDst, width, height)) + return TRUE; + + nbox = RegionNumRects(®ion); + pbox = RegionRects(®ion); + + if (!nbox) + return TRUE; + + XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format); + + xMask -= xDst; + yMask -= yDst; + + while (nbox--) { + skipleft = pbox->x1 + xMask; + + (*infoRec->WriteBitmap) (infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1, + (unsigned char *) (pPix-> + devPrivate. + ptr) + + (pPix->devKind * + (pbox->y1 + yMask)) + + ((skipleft >> 3) & ~3), + pPix->devKind, skipleft & 31, + pixel, -1, GXcopy, ~0); + pbox++; + } + + /* WriteBitmap sets the Sync flag */ + RegionUninit(®ion); + return TRUE; + } + + formats = infoRec->CPUToScreenAlphaTextureFormats; + dstformats = infoRec->CPUToScreenAlphaTextureDstFormats; + if (!formats || !dstformats) + return FALSE; + + w = pMask->pDrawable->width; + h = pMask->pDrawable->height; + + if (pMask->repeat) { + if ((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) + || + ((infoRec-> + CPUToScreenAlphaTextureFlags & + XAA_RENDER_POWER_OF_2_TILE_ONLY) && ((h & (h - 1)) || + (w & (w - 1))))) { + return FALSE; + } + flags |= XAA_RENDER_REPEAT; + } + + if ((alpha != 0xffff) && + (infoRec-> + CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA)) + return FALSE; + + while (*formats != pMask->format) { + if (!(*formats)) + return FALSE; + formats++; + } + while (*dstformats != pDst->format) { + if (!(*dstformats)) + return FALSE; + dstformats++; + } + + if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return TRUE; + + nbox = RegionNumRects(®ion); + pbox = RegionRects(®ion); + + if (!nbox) { + RegionUninit(®ion); + return TRUE; + } + + if (!(infoRec->SetupForCPUToScreenAlphaTexture2) (infoRec->pScrn, + op, red, green, + blue, alpha, + pMask->format, + pDst->format, + ((PixmapPtr) + (pMask-> + pDrawable))-> + devPrivate.ptr, + ((PixmapPtr) + (pMask-> + pDrawable))-> + devKind, w, h, + flags)) { + RegionUninit(®ion); + return FALSE; + } + + xMask -= xDst; + yMask -= yDst; + + while (nbox--) { + (*infoRec->SubsequentCPUToScreenAlphaTexture) (infoRec->pScrn, + pbox->x1, + pbox->y1, + pbox->x1 + xMask, + pbox->y1 + yMask, + pbox->x2 - + pbox->x1, + pbox->y2 - + pbox->y1); + pbox++; + } + + SET_SYNC_FLAG(infoRec); + RegionUninit(®ion); + return TRUE; + } + } + else { + formats = infoRec->CPUToScreenTextureFormats; + dstformats = infoRec->CPUToScreenTextureDstFormats; + if (!formats || !dstformats) + return FALSE; + + w = pSrc->pDrawable->width; + h = pSrc->pDrawable->height; + + if (pSrc->repeat) { + if ((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) || + ((infoRec->CPUToScreenTextureFlags & + XAA_RENDER_POWER_OF_2_TILE_ONLY) && + ((h & (h - 1)) || (w & (w - 1))))) { + return FALSE; + } + flags |= XAA_RENDER_REPEAT; + } + + while (*formats != pSrc->format) { + if (!(*formats)) + return FALSE; + formats++; + } + while (*dstformats != pDst->format) { + if (!(*dstformats)) + return FALSE; + dstformats++; + } + + if (!miComputeCompositeRegion(®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return TRUE; + + nbox = RegionNumRects(®ion); + pbox = RegionRects(®ion); + + if (!nbox) { + RegionUninit(®ion); + return TRUE; + } + + if (!(infoRec->SetupForCPUToScreenTexture2) (infoRec->pScrn, + op, pSrc->format, + pDst->format, + ((PixmapPtr) + (pSrc->pDrawable))-> + devPrivate.ptr, + ((PixmapPtr) + (pSrc->pDrawable))-> + devKind, w, h, flags)) { + RegionUninit(®ion); + return FALSE; + } + + xSrc -= xDst; + ySrc -= yDst; + + while (nbox--) { + (*infoRec->SubsequentCPUToScreenTexture) (infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x1 + xSrc, + pbox->y1 + ySrc, + pbox->x2 - pbox->x1, + pbox->y2 - pbox->y1); + pbox++; + } + + SET_SYNC_FLAG(infoRec); + RegionUninit(®ion); + return TRUE; + } + + return FALSE; +} + +static void +XAACompositeSrcCopy(PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + int i, nbox; + int xoff, yoff; + BoxPtr pbox; + DDXPointPtr pptSrc; + RegionRec region; + + 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, width, height)) + return; + + nbox = RegionNumRects(®ion); + pbox = RegionRects(®ion); + + if (!nbox) { + RegionUninit(®ion); + return; + } + pptSrc = malloc(sizeof(DDXPointRec) * nbox); + if (!pptSrc) { + RegionUninit(®ion); + return; + } + xoff = xSrc - xDst; + yoff = ySrc - yDst; + for (i = 0; i < nbox; i++) { + pptSrc[i].x = pbox[i].x1 + xoff; + pptSrc[i].y = pbox[i].y1 + yoff; + } + + infoRec->ScratchGC.planemask = ~0L; + infoRec->ScratchGC.alu = GXcopy; + + XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, ®ion, + pptSrc); + + free(pptSrc); + RegionUninit(®ion); + return; +} + +void +XAAComposite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + XAA_RENDER_PROLOGUE(pScreen, Composite); + + if (!pMask && infoRec->pScrn->vtSema && + infoRec->ScreenToScreenBitBlt && + pSrc->pDrawable && + DRAWABLE_IS_ON_CARD(pSrc->pDrawable) && + DRAWABLE_IS_ON_CARD(pDst->pDrawable) && + !pSrc->transform && + (!pSrc->repeat || (xSrc >= 0 && ySrc >= 0 && + xSrc + width <= pSrc->pDrawable->width && + ySrc + height <= pSrc->pDrawable->height)) && + ((op == PictOpSrc && + ((pSrc->format == pDst->format) || + (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)))) { + XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height); + } + else if (!pSrc->pDrawable || (pMask && !pMask->pDrawable) || + !infoRec->Composite || + !(*infoRec->Composite) (op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) { + if (infoRec->pScrn->vtSema && + ((pSrc->pDrawable && + (pSrc->pDrawable->type == DRAWABLE_WINDOW || + IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || + pDst->pDrawable->type == DRAWABLE_WINDOW || + IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { + SYNC_CHECK(pDst->pDrawable); + } + (*GetPictureScreen(pScreen)->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, yDst, width, height); + } + + if (pDst->pDrawable->type == DRAWABLE_PIXMAP) + (XAA_GET_PIXMAP_PRIVATE((PixmapPtr) (pDst->pDrawable)))->flags |= DIRTY; + + XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite); +} + +Bool +XAADoGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if (!RegionNumRects(pDst->pCompositeClip)) + return TRUE; + + if (!infoRec->pScrn->vtSema || + ((pDst->pDrawable->type != DRAWABLE_WINDOW) && + !IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) + return FALSE; + + if ((pSrc->pDrawable->type != DRAWABLE_PIXMAP) || + IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) + return FALSE; + + /* + * If it looks like we have a chance of being able to draw these + * glyphs with an accelerated Composite, do that now to avoid + * unneeded and costly syncs. + */ + if (maskFormat) { + if (!infoRec->CPUToScreenAlphaTextureFormats) + return FALSE; + } + else { + if (!infoRec->CPUToScreenTextureFormats) + return FALSE; + } + + miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + + return TRUE; +} + +void +XAAGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + XAA_RENDER_PROLOGUE(pScreen, Glyphs); + + if (!pSrc->pDrawable || !infoRec->Glyphs || + !(*infoRec->Glyphs) (op, pSrc, pDst, maskFormat, + xSrc, ySrc, nlist, list, glyphs)) { + if (infoRec->pScrn->vtSema && + ((pSrc->pDrawable && + (pSrc->pDrawable->type == DRAWABLE_WINDOW || + IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || + pDst->pDrawable->type == DRAWABLE_WINDOW || + IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { + SYNC_CHECK(pDst->pDrawable); + } + (*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat, + xSrc, ySrc, nlist, list, glyphs); + } + + if (pDst->pDrawable->type == DRAWABLE_PIXMAP) + (XAA_GET_PIXMAP_PRIVATE((PixmapPtr) (pDst->pDrawable)))->flags |= DIRTY; + + XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs); +} diff --git a/hw/xfree86/xaa/xaaROP.c b/hw/xfree86/xaa/xaaROP.c new file mode 100644 index 000000000..3b6ec9385 --- /dev/null +++ b/hw/xfree86/xaa/xaaROP.c @@ -0,0 +1,182 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaarop.h" +#include "xaa.h" +#include "xaalocal.h" + +int XAACopyROP[16] = { + ROP_0, /* GXclear */ + ROP_DSa, /* GXand */ + ROP_SDna, /* GXandReverse */ + ROP_S, /* GXcopy */ + ROP_DSna, /* GXandInverted */ + ROP_D, /* GXnoop */ + ROP_DSx, /* GXxor */ + ROP_DSo, /* GXor */ + ROP_DSon, /* GXnor */ + ROP_DSxn, /* GXequiv */ + ROP_Dn, /* GXinvert */ + ROP_SDno, /* GXorReverse */ + ROP_Sn, /* GXcopyInverted */ + ROP_DSno, /* GXorInverted */ + ROP_DSan, /* GXnand */ + ROP_1 /* GXset */ +}; + +int XAACopyROP_PM[16] = { + ROP_0, /* not used */ + ROP_DSPnoa, + ROP_DPSnaon, + ROP_DPSDxax, + ROP_DPSana, + ROP_D, /* not used */ + ROP_DPSax, + ROP_DPSao, + ROP_DPSaon, + ROP_DPSaxn, + ROP_Dn, /* not used */ + ROP_DPSanan, + ROP_PSDPxox, /* is that correct ? */ + ROP_DPSnao, + ROP_DSPnoan, + ROP_1 /* not used */ +}; + +int XAAPatternROP[16] = { + ROP_0, + ROP_DPa, + ROP_PDna, + ROP_P, + ROP_DPna, + ROP_D, + ROP_DPx, + ROP_DPo, + ROP_DPon, + ROP_PDxn, + ROP_Dn, + ROP_PDno, + ROP_Pn, + ROP_DPno, + ROP_DPan, + ROP_1 +}; + +int XAAPatternROP_PM[16] = { + ROP_DPna, + ROP_DPSnoa, + ROP_DSPnaon, + ROP_DSPDxax, + ROP_DPSana, + ROP_D, + ROP_DPSax, + ROP_DPSao, + ROP_DPSaon, + ROP_DPSaxn, + ROP_DPx, + ROP_DPSanan, + ROP_SPDSxox, /* is that correct ? */ + ROP_DSPnao, + ROP_DPSnoan, + ROP_DPo +}; + +int +XAAGetCopyROP(int i) +{ + return XAACopyROP[i]; +} + +int +XAAGetCopyROP_PM(int i) +{ + return XAACopyROP_PM[i]; +} + +int +XAAGetPatternROP(int i) +{ + return XAAPatternROP[i]; +} + +int +XAAGetPatternROP_PM(int i) +{ + return XAAPatternROP_PM[i]; +} + +int +XAAHelpPatternROP(ScrnInfoPtr pScrn, int *fg, int *bg, int pm, int *rop) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int ret = 0; + + pm &= infoRec->FullPlanemasks[pScrn->depth - 1]; + + if (pm == infoRec->FullPlanemasks[pScrn->depth - 1]) { + if (!NO_SRC_ROP(*rop)) + ret |= ROP_PAT; + *rop = XAAPatternROP[*rop]; + } + else { + switch (*rop) { + case GXnoop: + break; + case GXset: + case GXclear: + case GXinvert: + ret |= ROP_PAT; + *fg = pm; + if (*bg != -1) + *bg = pm; + break; + default: + ret |= ROP_PAT | ROP_SRC; + break; + } + *rop = XAAPatternROP_PM[*rop]; + } + + return ret; +} + +int +XAAHelpSolidROP(ScrnInfoPtr pScrn, int *fg, int pm, int *rop) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int ret = 0; + + pm &= infoRec->FullPlanemasks[pScrn->depth - 1]; + + if (pm == infoRec->FullPlanemasks[pScrn->depth - 1]) { + if (!NO_SRC_ROP(*rop)) + ret |= ROP_PAT; + *rop = XAAPatternROP[*rop]; + } + else { + switch (*rop) { + case GXnoop: + break; + case GXset: + case GXclear: + case GXinvert: + ret |= ROP_PAT; + *fg = pm; + break; + default: + ret |= ROP_PAT | ROP_SRC; + break; + } + *rop = XAAPatternROP_PM[*rop]; + } + + return ret; +} diff --git a/hw/xfree86/xaa/xaaRect.c b/hw/xfree86/xaa/xaaRect.c new file mode 100644 index 000000000..002090085 --- /dev/null +++ b/hw/xfree86/xaa/xaaRect.c @@ -0,0 +1,121 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +/* + Much of this file based on code by + Harm Hanemaayer (H.Hanemaayer@inter.nl.net). +*/ + +void +XAAPolyRectangleThinSolid(DrawablePtr pDrawable, + GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int nClipRects; /* number of clip rectangles */ + BoxPtr pClipRects; /* points to the list of clip rects */ + int xOrigin; /* Drawables x origin */ + int yOrigin; /* Drawables x origin */ + xRectangle *pRect; /* list of rects */ + int nRects; /* running count of number of rects */ + int origX1, origY1; /* original rectangle's U/L corner */ + int origX2, origY2; /* original rectangle's L/R corner */ + int clippedX1; /* clipped rectangle's left x */ + int clippedY1; /* clipped rectangle's top y */ + int clippedX2; /* clipped rectangle's right x */ + int clippedY2; /* clipped rectangle's bottom y */ + int clipXMin; /* upper left corner of clip rect */ + int clipYMin; /* upper left corner of clip rect */ + int clipXMax; /* lower right corner of clip rect */ + int clipYMax; /* lower right corner of clip rect */ + int width, height; /* width and height of rect */ + + nClipRects = RegionNumRects(pGC->pCompositeClip); + pClipRects = RegionRects(pGC->pCompositeClip); + + if (!nClipRects) + return; + + xOrigin = pDrawable->x; + yOrigin = pDrawable->y; + + (*infoRec->SetupForSolidLine) (infoRec->pScrn, + pGC->fgPixel, pGC->alu, pGC->planemask); + + for (; nClipRects > 0; nClipRects--, pClipRects++) { + clipYMin = pClipRects->y1; + clipYMax = pClipRects->y2 - 1; + clipXMin = pClipRects->x1; + clipXMax = pClipRects->x2 - 1; + + for (pRect = pRectsInit, nRects = nRectsInit; + nRects > 0; nRects--, pRect++) { + /* translate rectangle data over to the drawable */ + origX1 = pRect->x + xOrigin; + origY1 = pRect->y + yOrigin; + origX2 = origX1 + pRect->width; + origY2 = origY1 + pRect->height; + + /* reject entire rectangle if completely outside clip rect */ + if ((origX1 > clipXMax) || (origX2 < clipXMin) || + (origY1 > clipYMax) || (origY2 < clipYMin)) + continue; + + /* clip the rectangle */ + clippedX1 = max(origX1, clipXMin); + clippedX2 = min(origX2, clipXMax); + clippedY1 = max(origY1, clipYMin); + clippedY2 = min(origY2, clipYMax); + + width = clippedX2 - clippedX1 + 1; + + if (origY1 >= clipYMin) { + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, + clippedX1, clippedY1, + width, DEGREES_0); + + /* don't overwrite corner */ + clippedY1++; + } + + if ((origY2 <= clipYMax) && (origY1 != origY2)) { + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, + clippedX1, clippedY2, + width, DEGREES_0); + + /* don't overwrite corner */ + clippedY2--; + } + + if (clippedY2 < clippedY1) + continue; + + height = clippedY2 - clippedY1 + 1; + + /* draw vertical edges using lines if not clipped out */ + if (origX1 >= clipXMin) + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, + clippedX1, clippedY1, + height, DEGREES_270); + + if ((origX2 <= clipXMax) && (origX2 != origX1)) + (*infoRec->SubsequentSolidHorVertLine) (infoRec->pScrn, + clippedX2, clippedY1, + height, DEGREES_270); + } + } + + SET_SYNC_FLAG(infoRec); +} diff --git a/hw/xfree86/xaa/xaaSpans.c b/hw/xfree86/xaa/xaaSpans.c new file mode 100644 index 000000000..5cfcb8f22 --- /dev/null +++ b/hw/xfree86/xaa/xaaSpans.c @@ -0,0 +1,876 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miwideline.h" +#include "xaa.h" +#include "xaalocal.h" + +static void XAARenderSolidSpans(GCPtr, int, DDXPointPtr, int *, int, int, int); +static void XAARenderColor8x8Spans(GCPtr, int, DDXPointPtr, int *, int, int, + int); +static void XAARenderMono8x8Spans(GCPtr, int, DDXPointPtr, int *, int, int, + int); +static void XAARenderCacheBltSpans(GCPtr, int, DDXPointPtr, int *, int, int, + int); +static void XAARenderColorExpandSpans(GCPtr, int, DDXPointPtr, int *, int, int, + int); +static void XAARenderCacheExpandSpans(GCPtr, int, DDXPointPtr, int *, int, int, + int); +static void XAARenderPixmapCopySpans(GCPtr, int, DDXPointPtr, int *, int, int, + int); + +void +XAAFillSpans(DrawablePtr pDraw, GC * pGC, int nInit, /* number of spans to fill */ + DDXPointPtr pptInit, /* void * to list of start points */ + int *pwidthInit, /* void * to list of n widths */ + int fSorted) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int type = 0; + ClipAndRenderSpansFunc function; + Bool fastClip = FALSE; + + if ((nInit <= 0) || !pGC->planemask) + return; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + switch (pGC->fillStyle) { + case FillSolid: + type = DO_SOLID; + break; + case FillStippled: + type = (*infoRec->StippledFillChooser) (pGC); + break; + case FillOpaqueStippled: + if ((pGC->fgPixel == pGC->bgPixel) && infoRec->FillSpansSolid && + CHECK_PLANEMASK(pGC, infoRec->FillSpansSolidFlags) && + CHECK_ROP(pGC, infoRec->FillSpansSolidFlags) && + CHECK_ROPSRC(pGC, infoRec->FillSpansSolidFlags) && + CHECK_FG(pGC, infoRec->FillSpansSolidFlags)) + type = DO_SOLID; + else + type = (*infoRec->OpaqueStippledFillChooser) (pGC); + break; + case FillTiled: + type = (*infoRec->TiledFillChooser) (pGC); + break; + } + + switch (type) { + case DO_SOLID: + function = XAARenderSolidSpans; + if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL) + fastClip = TRUE; + break; + case DO_COLOR_8x8: + function = XAARenderColor8x8Spans; + if (infoRec->ClippingFlags & HARDWARE_CLIP_COLOR_8x8_FILL) + fastClip = TRUE; + break; + case DO_MONO_8x8: + function = XAARenderMono8x8Spans; + if (infoRec->ClippingFlags & HARDWARE_CLIP_MONO_8x8_FILL) + fastClip = TRUE; + break; + case DO_CACHE_BLT: + function = XAARenderCacheBltSpans; + if (infoRec->ClippingFlags & HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY) + fastClip = TRUE; + break; + case DO_COLOR_EXPAND: + function = XAARenderColorExpandSpans; + break; + case DO_CACHE_EXPAND: + function = XAARenderCacheExpandSpans; + if (infoRec->ClippingFlags & + HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND) + fastClip = TRUE; + break; + case DO_PIXMAP_COPY: + function = XAARenderPixmapCopySpans; + if (infoRec->ClippingFlags & HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY) + fastClip = TRUE; + break; + case DO_IMAGE_WRITE: + default: + (*XAAFallbackOps.FillSpans) (pDraw, pGC, nInit, pptInit, + pwidthInit, fSorted); + return; + } + + if ((nInit < 10) || (RegionNumRects(pGC->pCompositeClip) != 1)) + fastClip = FALSE; + + if (fastClip) { + infoRec->ClipBox = &pGC->pCompositeClip->extents; + (*function) (pGC, nInit, pptInit, pwidthInit, fSorted, + pDraw->x, pDraw->y); + infoRec->ClipBox = NULL; + } + else + XAAClipAndRenderSpans(pGC, pptInit, pwidthInit, nInit, fSorted, + function, pDraw->x, pDraw->y); +} + + /*********************\ + | Solid Spans | + \*********************/ + +static void +XAARenderSolidSpans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + (*infoRec->FillSolidSpans) (infoRec->pScrn, pGC->fgPixel, + pGC->alu, pGC->planemask, n, ppt, pwidth, + fSorted); +} + + /************************\ + | Mono 8x8 Spans | + \************************/ + +static void +XAARenderMono8x8Spans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAPixmapPtr pPriv; + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + case FillTiled: + pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + fg = pPriv->fg; + bg = pPriv->bg; + break; + default: /* Muffle compiler */ + pPriv = NULL; /* Kaboom */ + fg = -1; + bg = -1; + break; + } + + (*infoRec->FillMono8x8PatternSpans) (infoRec->pScrn, + fg, bg, pGC->alu, pGC->planemask, + n, ppt, pwidth, fSorted, + pPriv->pattern0, pPriv->pattern1, + (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y)); +} + + /*************************\ + | Color 8x8 Spans | + \*************************/ + +static void +XAARenderColor8x8Spans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAACacheInfoPtr pCache; + PixmapPtr pPix; + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + pPix = pGC->stipple; + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + pPix = pGC->stipple; + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + case FillTiled: + pPix = pGC->tile.pixmap; + fg = -1; + bg = -1; + break; + default: /* Muffle compiler */ + pPix = NULL; + fg = -1; + bg = -1; + break; + } + + pCache = (*infoRec->CacheColor8x8Pattern) (infoRec->pScrn, pPix, fg, bg); + + (*infoRec->FillColor8x8PatternSpans) (infoRec->pScrn, + pGC->alu, pGC->planemask, n, ppt, + pwidth, fSorted, pCache, + (yorg + pGC->patOrg.x), + (xorg + pGC->patOrg.y)); +} + + /****************************\ + | Color Expand Spans | + \****************************/ + +static void +XAARenderColorExpandSpans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + default: /* Muffle compiler */ + fg = -1; + bg = -1; + break; + } + + (*infoRec->FillColorExpandSpans) (infoRec->pScrn, fg, bg, + pGC->alu, pGC->planemask, n, ppt, pwidth, + fSorted, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pGC->stipple); + +} + + /*************************\ + | Cache Blt Spans | + \*************************/ + +static void +XAARenderCacheBltSpans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAACacheInfoPtr pCache; + + switch (pGC->fillStyle) { + case FillStippled: + pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple, + pGC->fgPixel, -1); + break; + case FillOpaqueStippled: + pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple, + pGC->fgPixel, pGC->bgPixel); + break; + case FillTiled: + pCache = (*infoRec->CacheTile) (infoRec->pScrn, pGC->tile.pixmap); + break; + default: /* Muffle compiler */ + pCache = NULL; + break; + } + + (*infoRec->FillCacheBltSpans) (infoRec->pScrn, + pGC->alu, pGC->planemask, n, ppt, pwidth, + fSorted, pCache, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y)); + +} + + /****************************\ + | Cache Expand Spans | + \****************************/ + +static void +XAARenderCacheExpandSpans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int fg, bg; + + switch (pGC->fillStyle) { + case FillStippled: + fg = pGC->fgPixel; + bg = -1; + break; + case FillOpaqueStippled: + fg = pGC->fgPixel; + bg = pGC->bgPixel; + break; + default: /* Muffle compiler */ + fg = -1; + bg = -1; + break; + } + + (*infoRec->FillCacheExpandSpans) (infoRec->pScrn, fg, bg, + pGC->alu, pGC->planemask, n, ppt, pwidth, + fSorted, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y), pGC->stipple); +} + + /***************************\ + | Pixmap Copy Spans | + \***************************/ + +static void +XAARenderPixmapCopySpans(GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAACacheInfoPtr pCache = &(infoRec->ScratchCacheInfoRec); + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + + pCache->x = pPriv->offscreenArea->box.x1; + pCache->y = pPriv->offscreenArea->box.y1; + pCache->w = pCache->orig_w = pPriv->offscreenArea->box.x2 - pCache->x; + pCache->h = pCache->orig_h = pPriv->offscreenArea->box.y2 - pCache->y; + pCache->trans_color = -1; + + (*infoRec->FillCacheBltSpans) (infoRec->pScrn, + pGC->alu, pGC->planemask, n, ppt, pwidth, + fSorted, pCache, (xorg + pGC->patOrg.x), + (yorg + pGC->patOrg.y)); +} + + /****************\ + | Solid | + \****************/ + +void +XAAFillSolidSpans(ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int n, DDXPointPtr ppt, int *pwidth, int fSorted) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SetupForSolidFill) (pScrn, fg, rop, planemask); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + if (*pwidth > 0) + (*infoRec->SubsequentSolidFillRect) (pScrn, ppt->x, ppt->y, + *pwidth, 1); + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + + /***************\ + | Mono 8x8 | + \***************/ + +void +XAAFillMono8x8PatternSpansScreenOrigin(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + int pattern0, int pattern1, + int xorigin, int yorigin) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int patx = pattern0, paty = pattern1; + int xorg = (-xorigin) & 0x07; + int yorg = (-yorigin) & 0x07; + + if (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) { + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + } + else { + XAACacheInfoPtr pCache = + (*infoRec->CacheMono8x8Pattern) (pScrn, pattern0, pattern1); + patx = pCache->x; + paty = pCache->y; + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + patx += pCache->offsets[slot].x; + paty += pCache->offsets[slot].y; + xorg = patx; + yorg = paty; + } + } + + (*infoRec->SetupForMono8x8PatternFill) (pScrn, patx, paty, + fg, bg, rop, planemask); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, + xorg, yorg, ppt->x, + ppt->y, *pwidth, 1); + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + +void +XAAFillMono8x8PatternSpans(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + int pattern0, int pattern1, int xorigin, int yorigin) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int patx = pattern0, paty = pattern1; + int xorg, yorg, slot; + XAACacheInfoPtr pCache = NULL; + + if (!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS)) { + pCache = (*infoRec->CacheMono8x8Pattern) (pScrn, pattern0, pattern1); + patx = pCache->x; + paty = pCache->y; + } + + (*infoRec->SetupForMono8x8PatternFill) (pScrn, patx, paty, + fg, bg, rop, planemask); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + xorg = (ppt->x - xorigin) & 0x07; + yorg = (ppt->y - yorigin) & 0x07; + + if (!(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + if (infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS) { + patx = pattern0; + paty = pattern1; + XAARotateMonoPattern(&patx, &paty, xorg, yorg, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + xorg = patx; + yorg = paty; + } + else { + slot = (yorg << 3) + xorg; + xorg = patx + pCache->offsets[slot].x; + yorg = paty + pCache->offsets[slot].y; + } + } + + (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, + xorg, yorg, ppt->x, + ppt->y, *pwidth, 1); + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + + /****************\ + | Color 8x8 | + \****************/ + +void +XAAFillColor8x8PatternSpansScreenOrigin(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + XAACacheInfoPtr pCache, + int xorigin, int yorigin) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int patx = pCache->x, paty = pCache->y; + int xorg = (-xorigin) & 0x07; + int yorg = (-yorigin) & 0x07; + + if (!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + int slot = (yorg << 3) + xorg; + + paty += pCache->offsets[slot].y; + patx += pCache->offsets[slot].x; + xorg = patx; + yorg = paty; + } + + (*infoRec->SetupForColor8x8PatternFill) (pScrn, patx, paty, + rop, planemask, + pCache->trans_color); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + (*infoRec->SubsequentColor8x8PatternFillRect) (pScrn, + xorg, yorg, ppt->x, + ppt->y, *pwidth, 1); + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + +void +XAAFillColor8x8PatternSpans(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + XAACacheInfoPtr pCache, int xorigin, int yorigin) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int xorg, yorg, slot; + + (*infoRec->SetupForColor8x8PatternFill) (pScrn, pCache->x, pCache->y, + rop, planemask, + pCache->trans_color); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + xorg = (ppt->x - xorigin) & 0x07; + yorg = (ppt->y - yorigin) & 0x07; + + if (!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + slot = (yorg << 3) + xorg; + yorg = pCache->y + pCache->offsets[slot].y; + xorg = pCache->x + pCache->offsets[slot].x; + } + + (*infoRec->SubsequentColor8x8PatternFillRect) (pScrn, + xorg, yorg, ppt->x, + ppt->y, *pwidth, 1); + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + + /*****************\ + | Cache Blit | + \*****************/ + +void +XAAFillCacheBltSpans(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, XAACacheInfoPtr pCache, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, w, phaseX, phaseY, blit_w; + + (*infoRec->SetupForScreenToScreenCopy) (pScrn, 1, 1, rop, planemask, + pCache->trans_color); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + x = ppt->x; + w = *pwidth; + phaseX = (x - xorg) % pCache->orig_w; + if (phaseX < 0) + phaseX += pCache->orig_w; + phaseY = (ppt->y - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + + while (1) { + blit_w = pCache->w - phaseX; + if (blit_w > w) + blit_w = w; + + (*infoRec->SubsequentScreenToScreenCopy) (pScrn, + pCache->x + phaseX, + pCache->y + phaseY, x, + ppt->y, blit_w, 1); + + w -= blit_w; + if (!w) + break; + x += blit_w; + phaseX = (phaseX + blit_w) % pCache->orig_w; + } + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + + /****************\ + | Cache Expand | + \****************/ + +void +XAAFillCacheExpandSpans(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, int xorg, int yorg, PixmapPtr pPix) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x, w, phaseX, phaseY, blit_w, cacheWidth; + XAACacheInfoPtr pCache; + + pCache = (*infoRec->CacheMonoStipple) (pScrn, pPix); + + cacheWidth = (pCache->w * pScrn->bitsPerPixel) / + infoRec->CacheColorExpandDensity; + + (*infoRec->SetupForScreenToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + if (infoRec->ClipBox) + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + + while (n--) { + x = ppt->x; + w = *pwidth; + phaseX = (x - xorg) % pCache->orig_w; + if (phaseX < 0) + phaseX += pCache->orig_w; + phaseY = (ppt->y - yorg) % pCache->orig_h; + if (phaseY < 0) + phaseY += pCache->orig_h; + + while (1) { + blit_w = cacheWidth - phaseX; + if (blit_w > w) + blit_w = w; + + (*infoRec->SubsequentScreenToScreenColorExpandFill) (pScrn, x, + ppt->y, blit_w, + 1, pCache->x, + pCache->y + + phaseY, + phaseX); + + w -= blit_w; + if (!w) + break; + x += blit_w; + phaseX = (phaseX + blit_w) % pCache->orig_w; + } + ppt++; + pwidth++; + } + + if (infoRec->ClipBox) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} + +void +XAAClipAndRenderSpans(GCPtr pGC, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted, + ClipAndRenderSpansFunc func, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + DDXPointPtr pptNew, pptBase; + int *pwidthBase, *pwidthNew; + int Right, numRects, MaxBoxes; + + MaxBoxes = infoRec->PreAllocSize / (sizeof(DDXPointRec) + sizeof(int)); + pptBase = (DDXPointRec *) infoRec->PreAllocMem; + pwidthBase = (int *) (&pptBase[MaxBoxes]); + + pptNew = pptBase; + pwidthNew = pwidthBase; + + numRects = RegionNumRects(pGC->pCompositeClip); + + if (numRects == 1) { + BoxPtr pextent = RegionRects(pGC->pCompositeClip); + + while (nspans--) { + if ((pextent->y1 <= ppt->y) && (ppt->y < pextent->y2)) { + pptNew->x = max(pextent->x1, ppt->x); + Right = ppt->x + *pwidth; + *pwidthNew = min(pextent->x2, Right) - pptNew->x; + + if (*pwidthNew > 0) { + pptNew->y = ppt->y; + pptNew++; + pwidthNew++; + + if (pptNew >= (pptBase + MaxBoxes)) { + (*func) (pGC, MaxBoxes, pptBase, pwidthBase, fSorted, + xorg, yorg); + pptNew = pptBase; + pwidthNew = pwidthBase; + } + } + } + ppt++; + pwidth++; + } + } + else if (numRects) { + BoxPtr pbox; + int nbox; + + while (nspans--) { + nbox = numRects; + pbox = RegionRects(pGC->pCompositeClip); + + /* find the first band */ + while (nbox && (pbox->y2 <= ppt->y)) { + pbox++; + nbox--; + } + + if (nbox && (pbox->y1 <= ppt->y)) { + int orig_y = pbox->y1; + + Right = ppt->x + *pwidth; + while (nbox && (orig_y == pbox->y1)) { + if (pbox->x2 <= ppt->x) { + nbox--; + pbox++; + continue; + } + + if (pbox->x1 >= Right) { + nbox = 0; + break; + } + + pptNew->x = max(pbox->x1, ppt->x); + *pwidthNew = min(pbox->x2, Right) - pptNew->x; + if (*pwidthNew > 0) { + pptNew->y = ppt->y; + pptNew++; + pwidthNew++; + + if (pptNew >= (pptBase + MaxBoxes)) { + (*func) (pGC, MaxBoxes, pptBase, pwidthBase, + fSorted, xorg, yorg); + pptNew = pptBase; + pwidthNew = pwidthBase; + } + } + pbox++; + nbox--; + } + } + ppt++; + pwidth++; + } + } + + if (pptNew != pptBase) + (*func) (pGC, pptNew - pptBase, pptBase, pwidthBase, fSorted, + xorg, yorg); +} diff --git a/hw/xfree86/xaa/xaaStateChange.c b/hw/xfree86/xaa/xaaStateChange.c new file mode 100644 index 000000000..c9fdf298f --- /dev/null +++ b/hw/xfree86/xaa/xaaStateChange.c @@ -0,0 +1,1665 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "servermd.h" + +#define XAA_STATE_WRAP(func) do {\ +if(infoRec->func) { \ + pStatePriv->func = infoRec->func;\ + infoRec->func = XAAStateWrap##func;\ +}} while(0) + +/* Wrap all XAA functions and allocate our private structure. + */ + +typedef struct _XAAStateWrapRec { + ScrnInfoPtr pScrn; + void (*RestoreAccelState) (ScrnInfoPtr pScrn); + void (*Sync) (ScrnInfoPtr pScrn); + void (*SetupForScreenToScreenCopy) (ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int trans_color); + void (*SetupForSolidFill) (ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask); + void (*SetupForSolidLine) (ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask); + void (*SetupForDashedLine) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int length, + unsigned char *pattern); + void (*SetClippingRectangle) (ScrnInfoPtr pScrn, int left, int top, + int right, int bottom); + void (*DisableClipping) (ScrnInfoPtr pScrn); + void (*SetupForMono8x8PatternFill) (ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask); + void (*SetupForColor8x8PatternFill) (ScrnInfoPtr pScrn, int patx, int paty, + int rop, unsigned int planemask, + int transparency_color); + void (*SetupForCPUToScreenColorExpandFill) (ScrnInfoPtr pScrn, int fg, + int bg, int rop, + unsigned int planemask); + void (*SetupForScanlineCPUToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); + void (*SetupForScreenToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); + void (*SetupForImageWrite) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth); + void (*SetupForScanlineImageWrite) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth); + void (*SetupForImageRead) (ScrnInfoPtr pScrn, int bpp, int depth); + void (*ScreenToScreenBitBlt) (ScrnInfoPtr pScrn, int nbox, + DDXPointPtr pptSrc, BoxPtr pbox, int xdir, + int ydir, int alu, unsigned int planmask); + void (*WriteBitmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int skipleft, + int fg, int bg, int rop, unsigned int planemask); + void (*FillSolidRects) (ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox); + void (*FillMono8x8PatternRects) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int pat0, int pat1, + int xorg, int yorg); + void (*FillColor8x8PatternRects) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + XAACacheInfoPtr pCache); + void (*FillCacheBltRects) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, XAACacheInfoPtr pCache); + void (*FillColorExpandRects) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix); + void (*FillCacheExpandRects) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + void (*FillImageWriteRects) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + void (*FillSolidSpans) (ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int n, DDXPointPtr points, + int *widths, int fSorted); + void (*FillMono8x8PatternSpans) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, int pat0, int pat1, + int xorg, int yorg); + void (*FillColor8x8PatternSpans) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg); + void (*FillCacheBltSpans) (ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, int fSorted, + XAACacheInfoPtr pCache, int xorg, int yorg); + void (*FillColorExpandSpans) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, int fSorted, + int xorg, int yorg, PixmapPtr pPix); + void (*FillCacheExpandSpans) (ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr ppt, int *pwidth, int fSorted, + int xorg, int yorg, PixmapPtr pPix); + void (*TEGlyphRenderer) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft, int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + void (*NonTEGlyphRenderer) (ScrnInfoPtr pScrn, int x, int y, int n, + NonTEGlyphPtr glyphs, BoxPtr pbox, int fg, + int rop, unsigned int planemask); + void (*WritePixmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth); + void (*ReadPixmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth); + RegionPtr (*CopyArea) (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GC * pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty); + RegionPtr (*CopyPlane) (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, + int dsty, unsigned long bitPlane); + void (*PushPixelsSolid) (GCPtr pGC, PixmapPtr pBitMap, + DrawablePtr pDrawable, int dx, int dy, int xOrg, + int yOrg); + void (*PolyFillRectSolid) (DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit); + void (*PolyFillRectStippled) (DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit); + void (*PolyFillRectOpaqueStippled) (DrawablePtr pDraw, GCPtr pGC, + int nrectFill, xRectangle *prectInit); + void (*PolyFillRectTiled) (DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit); + void (*FillSpansSolid) (DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + void (*FillSpansStippled) (DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + void (*FillSpansOpaqueStippled) (DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + void (*FillSpansTiled) (DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + int (*PolyText8TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + char *chars); + int (*PolyText16TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + unsigned short *chars); + void (*ImageText8TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + char *chars); + void (*ImageText16TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); + void (*ImageGlyphBltTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr * ppci, + void * pglyphBase); + void (*PolyGlyphBltTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr * ppci, + void * pglyphBase); + int (*PolyText8NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars); + int (*PolyText16NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); + void (*ImageText8NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars); + void (*ImageText16NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); + void (*ImageGlyphBltNonTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + void (*PolyGlyphBltNonTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + void (*PolyRectangleThinSolid) (DrawablePtr pDrawable, GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit); + void (*PolylinesWideSolid) (DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts); + void (*PolylinesThinSolid) (DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts); + void (*PolySegmentThinSolid) (DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment * pSeg); + void (*PolylinesThinDashed) (DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts); + void (*PolySegmentThinDashed) (DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment * pSeg); + void (*FillPolygonSolid) (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + void (*FillPolygonStippled) (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + void (*FillPolygonOpaqueStippled) (DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr ptsIn); + void (*FillPolygonTiled) (DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + void (*PolyFillArcSolid) (DrawablePtr pDraw, GCPtr pGC, int narcs, + xArc * parcs); + void (*PutImage) (DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *pImage); + ValidateGCProcPtr ValidateFillSpans; + ValidateGCProcPtr ValidateSetSpans; + ValidateGCProcPtr ValidatePutImage; + ValidateGCProcPtr ValidateCopyArea; + ValidateGCProcPtr ValidateCopyPlane; + ValidateGCProcPtr ValidatePolyPoint; + ValidateGCProcPtr ValidatePolylines; + ValidateGCProcPtr ValidatePolySegment; + ValidateGCProcPtr ValidatePolyRectangle; + ValidateGCProcPtr ValidatePolyArc; + ValidateGCProcPtr ValidateFillPolygon; + ValidateGCProcPtr ValidatePolyFillRect; + ValidateGCProcPtr ValidatePolyFillArc; + ValidateGCProcPtr ValidatePolyText8; + ValidateGCProcPtr ValidatePolyText16; + ValidateGCProcPtr ValidateImageText8; + ValidateGCProcPtr ValidateImageText16; + ValidateGCProcPtr ValidatePolyGlyphBlt; + ValidateGCProcPtr ValidateImageGlyphBlt; + ValidateGCProcPtr ValidatePushPixels; + void (*ComputeDash) (GCPtr pGC); + void (*InitPixmapCache) (ScreenPtr pScreen, RegionPtr areas, void * data); + void (*ClosePixmapCache) (ScreenPtr pScreen); + int (*StippledFillChooser) (GCPtr pGC); + int (*OpaqueStippledFillChooser) (GCPtr pGC); + int (*TiledFillChooser) (GCPtr pGC); + XAACacheInfoPtr(*CacheTile) (ScrnInfoPtr Scrn, PixmapPtr pPix); + XAACacheInfoPtr(*CacheStipple) (ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, + int bg); + XAACacheInfoPtr(*CacheMonoStipple) (ScrnInfoPtr Scrn, PixmapPtr pPix); + XAACacheInfoPtr(*CacheMono8x8Pattern) (ScrnInfoPtr Scrn, int pat0, + int pat1); + XAACacheInfoPtr(*CacheColor8x8Pattern) (ScrnInfoPtr Scrn, PixmapPtr pPix, + int fg, int bg); + void (*WriteBitmapToCache) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, + int bg); + void (*WritePixmapToCache) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int bpp, + int depth); + void (*WriteMono8x8PatternToCache) (ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache); + void (*WriteColor8x8PatternToCache) (ScrnInfoPtr pScrn, PixmapPtr pPix, + XAACacheInfoPtr pCache); + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CopyWindowProcPtr CopyWindow; + Bool (*SetupForCPUToScreenAlphaTexture2) (ScrnInfoPtr pScrn, int op, + CARD16 red, CARD16 green, + CARD16 blue, CARD16 alpha, + CARD32 maskFormat, + CARD32 dstFormat, CARD8 *alphaPtr, + int alphaPitch, int width, + int height, int flags); + Bool (*SetupForCPUToScreenTexture2) (ScrnInfoPtr pScrn, int op, + CARD32 srcFormat, CARD32 dstFormat, + CARD8 *texPtr, int texPitch, int width, + int height, int flags); +} XAAStateWrapRec, *XAAStateWrapPtr; + +static DevPrivateKeyRec XAAStateKeyRec; + +#define XAAStateKey (&XAAStateKeyRec) + +/* Wrap functions start here */ +#define GET_STATEPRIV_GC(pGC) XAAStateWrapPtr pStatePriv =\ +(XAAStateWrapPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAStateKey) + +#define GET_STATEPRIV_SCREEN(pScreen) XAAStateWrapPtr pStatePriv =\ +(XAAStateWrapPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAStateKey) + +#define GET_STATEPRIV_PSCRN(pScrn) XAAStateWrapPtr pStatePriv =\ +(XAAStateWrapPtr)dixLookupPrivate(&(pScrn)->pScreen->devPrivates, XAAStateKey) + +#define STATE_CHECK_SP(pStatePriv) {\ + ScrnInfoPtr pScrn = pStatePriv->pScrn;\ + int i = 0;\ + int need_change = 0;\ + while(i < pScrn->numEntities) {\ + if(xf86IsEntityShared(pScrn->entityList[i]) &&\ + xf86GetLastScrnFlag(pScrn->entityList[i]) != pScrn->scrnIndex) {\ + need_change = 1;\ + xf86SetLastScrnFlag(pScrn->entityList[i],\ + pScrn->scrnIndex);\ + }\ + i++;\ + }\ + if(need_change == 1) (*pStatePriv->RestoreAccelState)(pScrn);\ +} + +#define STATE_CHECK_PSCRN(pScrn) {\ + int i = 0;\ + int need_change = 0;\ + while(i < pScrn->numEntities) {\ + if(xf86IsEntityShared(pScrn->entityList[i]) &&\ + xf86GetLastScrnFlag(pScrn->entityList[i]) != pScrn->scrnIndex) {\ + need_change = 1;\ + xf86SetLastScrnFlag(pScrn->entityList[i],\ + pScrn->scrnIndex);\ + }\ + i++;\ + }\ + if(need_change == 1) (*pStatePriv->RestoreAccelState)(pScrn);\ +} + +static void +XAAStateWrapSync(ScrnInfoPtr pScrn) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->Sync) (pScrn); +} + +static void +XAAStateWrapSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int trans_color) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScreenToScreenCopy) (pScrn, xdir, ydir, rop, + planemask, trans_color); +} + +static void +XAAStateWrapSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForSolidFill) (pScrn, color, rop, planemask); +} + +static void +XAAStateWrapSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForSolidLine) (pScrn, color, rop, planemask); +} + +static void +XAAStateWrapSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int length, + unsigned char *pattern) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForDashedLine) (pScrn, fg, bg, rop, planemask, length, + pattern); +} + +static void +XAAStateWrapSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, + int right, int bottom) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetClippingRectangle) (pScrn, left, top, right, bottom); +} + +static void +XAAStateWrapDisableClipping(ScrnInfoPtr pScrn) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->DisableClipping) (pScrn); +} + +static void +XAAStateWrapSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForMono8x8PatternFill) (pScrn, patx, paty, fg, bg, rop, + planemask); +} + +static void +XAAStateWrapSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, + int rop, unsigned int planemask, + int transparency_color) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForColor8x8PatternFill) (pScrn, patx, paty, rop, + planemask, transparency_color); +} + +static void +XAAStateWrapSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, + int bg, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); +} + +static void +XAAStateWrapSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, + rop, planemask); +} + +static void +XAAStateWrapSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScreenToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); +} + +static void +XAAStateWrapSetupForImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForImageWrite) (pScrn, rop, planemask, + transparency_color, bpp, depth); +} + +static void +XAAStateWrapSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScanlineImageWrite) (pScrn, rop, planemask, + transparency_color, bpp, depth); +} + +static void +XAAStateWrapSetupForImageRead(ScrnInfoPtr pScrn, int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForImageRead) (pScrn, bpp, depth); +} + +static void +XAAStateWrapScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, + DDXPointPtr pptSrc, BoxPtr pbox, int xdir, + int ydir, int alu, unsigned int planmask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->ScreenToScreenBitBlt) (pScrn, nbox, + pptSrc, pbox, xdir, + ydir, alu, planmask); +} + +static void +XAAStateWrapWriteBitmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int skipleft, + int fg, int bg, int rop, unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteBitmap) (pScrn, x, y, w, h, + src, srcwidth, skipleft, + fg, bg, rop, planemask); +} + +static void +XAAStateWrapFillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillSolidRects) (pScrn, fg, rop, planemask, nBox, pBox); +} + +static void +XAAStateWrapFillMono8x8PatternRects(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int nBox, + BoxPtr pBox, int pat0, int pat1, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillMono8x8PatternRects) (pScrn, fg, bg, + rop, planemask, nBox, + pBox, pat0, pat1, xorg, yorg); +} + +static void +XAAStateWrapFillColor8x8PatternRects(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColor8x8PatternRects) (pScrn, rop, + planemask, nBox, + pBox, xorg, yorg, pCache); +} + +static void +XAAStateWrapFillCacheBltRects(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheBltRects) (pScrn, rop, + planemask, nBox, pBox, + xorg, yorg, pCache); +} + +static void +XAAStateWrapFillColorExpandRects(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColorExpandRects) (pScrn, fg, bg, rop, + planemask, nBox, + pBox, xorg, yorg, pPix); +} + +static void +XAAStateWrapFillCacheExpandRects(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheExpandRects) (pScrn, fg, bg, rop, + planemask, nBox, + pBox, xorg, yorg, pPix); +} + +static void +XAAStateWrapFillImageWriteRects(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillImageWriteRects) (pScrn, rop, + planemask, nBox, pBox, + xorg, yorg, pPix); +} + +static void +XAAStateWrapFillSolidSpans(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int n, DDXPointPtr points, + int *widths, int fSorted) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillSolidSpans) (pScrn, fg, rop, + planemask, n, points, widths, fSorted); +} + +static void +XAAStateWrapFillMono8x8PatternSpans(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, int pat0, int pat1, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillMono8x8PatternSpans) (pScrn, fg, bg, + rop, planemask, n, + points, widths, + fSorted, pat0, pat1, xorg, yorg); +} + +static void +XAAStateWrapFillColor8x8PatternSpans(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColor8x8PatternSpans) (pScrn, rop, + planemask, n, + points, widths, + fSorted, pCache, xorg, yorg); +} + +static void +XAAStateWrapFillCacheBltSpans(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheBltSpans) (pScrn, rop, + planemask, n, + points, widths, + fSorted, pCache, xorg, yorg); +} + +static void +XAAStateWrapFillColorExpandSpans(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, int fSorted, + int xorg, int yorg, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColorExpandSpans) (pScrn, fg, bg, rop, + planemask, n, + points, widths, fSorted, + xorg, yorg, pPix); +} + +static void +XAAStateWrapFillCacheExpandSpans(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr ppt, int *pwidth, int fSorted, + int xorg, int yorg, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheExpandSpans) (pScrn, fg, bg, rop, + planemask, n, + ppt, pwidth, fSorted, + xorg, yorg, pPix); +} + +static void +XAAStateWrapTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft, int startline, + unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->TEGlyphRenderer) (pScrn, x, y, w, h, + skipleft, startline, + glyphs, glyphWidth, fg, bg, rop, planemask); +} + +static void +XAAStateWrapNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n, + NonTEGlyphPtr glyphs, BoxPtr pbox, + int fg, int rop, unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->NonTEGlyphRenderer) (pScrn, x, y, n, + glyphs, pbox, fg, rop, planemask); +} + +static void +XAAStateWrapWritePixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WritePixmap) (pScrn, x, y, w, h, + src, srcwidth, rop, + planemask, transparency_color, bpp, depth); +} + +static void +XAAStateWrapReadPixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->ReadPixmap) (pScrn, x, y, w, h, dst, dstwidth, bpp, depth); +} + +static RegionPtr +XAAStateWrapCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GC * pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->CopyArea) (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); +} + +static RegionPtr +XAAStateWrapCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->CopyPlane) (pSrc, pDst, pGC, + srcx, srcy, width, height, + dstx, dsty, bitPlane); +} + +static void +XAAStateWrapPushPixelsSolid(GCPtr pGC, PixmapPtr pBitMap, + DrawablePtr pDrawable, int dx, int dy, int xOrg, + int yOrg) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PushPixelsSolid) (pGC, pBitMap, + pDrawable, dx, dy, xOrg, yOrg); +} + +static void +XAAStateWrapPolyFillRectSolid(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectSolid) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAStateWrapPolyFillRectStippled(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectStippled) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAStateWrapPolyFillRectOpaqueStippled(DrawablePtr pDraw, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectOpaqueStippled) (pDraw, pGC, + nrectFill, prectInit); +} + +static void +XAAStateWrapPolyFillRectTiled(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectTiled) (pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAStateWrapFillSpansSolid(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansSolid) (pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static void +XAAStateWrapFillSpansStippled(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansStippled) (pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static void +XAAStateWrapFillSpansOpaqueStippled(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansOpaqueStippled) (pDraw, pGC, nInit, + ppt, pwidth, fSorted); +} + +static void +XAAStateWrapFillSpansTiled(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansTiled) (pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static int +XAAStateWrapPolyText8TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText8TE) (pDraw, pGC, x, y, count, chars); +} + +static int +XAAStateWrapPolyText16TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText16TE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAStateWrapImageText8TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText8TE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAStateWrapImageText16TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText16TE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAStateWrapImageGlyphBltTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr * ppci, + void * pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageGlyphBltTE) (pDrawable, pGC, xInit, + yInit, nglyph, ppci, pglyphBase); +} + +static void +XAAStateWrapPolyGlyphBltTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr * ppci, + void * pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyGlyphBltTE) (pDrawable, pGC, xInit, + yInit, nglyph, ppci, pglyphBase); +} + +static int +XAAStateWrapPolyText8NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText8NonTE) (pDraw, pGC, x, y, count, chars); +} + +static int +XAAStateWrapPolyText16NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText16NonTE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAStateWrapImageText8NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText8NonTE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAStateWrapImageText16NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText16NonTE) (pDraw, pGC, x, y, count, chars); +} + +static void +XAAStateWrapImageGlyphBltNonTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageGlyphBltNonTE) (pDrawable, pGC, xInit, + yInit, nglyph, ppci, pglyphBase); +} + +static void +XAAStateWrapPolyGlyphBltNonTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyGlyphBltNonTE) (pDrawable, pGC, xInit, + yInit, nglyph, ppci, pglyphBase); +} + +static void +XAAStateWrapPolyRectangleThinSolid(DrawablePtr pDrawable, GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyRectangleThinSolid) (pDrawable, pGC, + nRectsInit, pRectsInit); +} + +static void +XAAStateWrapPolylinesWideSolid(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolylinesWideSolid) (pDrawable, pGC, mode, npt, pPts); +} + +static void +XAAStateWrapPolylinesThinSolid(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolylinesThinSolid) (pDrawable, pGC, mode, npt, pPts); +} + +static void +XAAStateWrapPolySegmentThinSolid(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment * pSeg) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolySegmentThinSolid) (pDrawable, pGC, nseg, pSeg); +} + +static void +XAAStateWrapPolylinesThinDashed(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolylinesThinDashed) (pDrawable, pGC, mode, npt, pPts); +} + +static void +XAAStateWrapPolySegmentThinDashed(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment * pSeg) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolySegmentThinDashed) (pDrawable, pGC, nseg, pSeg); +} + +static void +XAAStateWrapFillPolygonSolid(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonSolid) (pDrawable, pGC, shape, mode, count, ptsIn); +} + +static void +XAAStateWrapFillPolygonStippled(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonStippled) (pDrawable, pGC, shape, + mode, count, ptsIn); +} + +static void +XAAStateWrapFillPolygonOpaqueStippled(DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonOpaqueStippled) (pDrawable, pGC, + shape, mode, count, ptsIn); +} + +static void +XAAStateWrapFillPolygonTiled(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonTiled) (pDrawable, pGC, shape, mode, count, ptsIn); +} + +static void +XAAStateWrapPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, + xArc * parcs) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillArcSolid) (pDraw, pGC, narcs, parcs); +} + +static void +XAAStateWrapPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *pImage) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PutImage) (pDraw, pGC, depth, x, y, + w, h, leftPad, format, pImage); +} + +static void +XAAStateWrapValidateFillSpans(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateFillSpans) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateSetSpans(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateSetSpans) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePutImage(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePutImage) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateCopyArea(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateCopyArea) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateCopyPlane(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateCopyPlane) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyPoint(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyPoint) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolylines(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolylines) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolySegment(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolySegment) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyRectangle(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyRectangle) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyArc(GCPtr pGC, unsigned long changes, DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyArc) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateFillPolygon(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateFillPolygon) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyFillRect(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyFillRect) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyFillArc(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyFillArc) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyText8(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyText8) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyText16(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyText16) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateImageText8(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateImageText8) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateImageText16(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateImageText16) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePolyGlyphBlt(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyGlyphBlt) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidateImageGlyphBlt(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + (*pStatePriv->ValidateImageGlyphBlt) (pGC, changes, pDraw); +} + +static void +XAAStateWrapValidatePushPixels(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePushPixels) (pGC, changes, pDraw); +} + +static void +XAAStateWrapComputeDash(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ComputeDash) (pGC); +} + +static void +XAAStateWrapInitPixmapCache(ScreenPtr pScreen, RegionPtr areas, void * data) +{ + GET_STATEPRIV_SCREEN(pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->InitPixmapCache) (pScreen, areas, data); +} + +static void +XAAStateWrapClosePixmapCache(ScreenPtr pScreen) +{ + GET_STATEPRIV_SCREEN(pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ClosePixmapCache) (pScreen); +} + +static int +XAAStateWrapStippledFillChooser(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->StippledFillChooser) (pGC); +} + +static int +XAAStateWrapOpaqueStippledFillChooser(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->OpaqueStippledFillChooser) (pGC); +} + +static int +XAAStateWrapTiledFillChooser(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->TiledFillChooser) (pGC); +} + +static XAACacheInfoPtr +XAAStateWrapCacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheTile) (pScrn, pPix); +} + +static XAACacheInfoPtr +XAAStateWrapCacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheStipple) (pScrn, pPix, fg, bg); +} + +static XAACacheInfoPtr +XAAStateWrapCacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheMonoStipple) (pScrn, pPix); +} + +static XAACacheInfoPtr +XAAStateWrapCacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheMono8x8Pattern) (pScrn, pat0, pat1); +} + +static XAACacheInfoPtr +XAAStateWrapCacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, + int fg, int bg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheColor8x8Pattern) (pScrn, pPix, fg, bg); +} + +static void +XAAStateWrapWriteBitmapToCache(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, int bg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteBitmapToCache) (pScrn, x, y, w, h, + src, srcwidth, fg, bg); +} + +static void +XAAStateWrapWritePixmapToCache(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int bpp, + int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WritePixmapToCache) (pScrn, x, y, w, h, + src, srcwidth, bpp, depth); +} + +static void +XAAStateWrapWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteMono8x8PatternToCache) (pScrn, pCache); +} + +static void +XAAStateWrapWriteColor8x8PatternToCache(ScrnInfoPtr pScrn, PixmapPtr pPix, + XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteColor8x8PatternToCache) (pScrn, pPix, pCache); +} + +static void +XAAStateWrapGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planeMask, + char *pdstLine) +{ + GET_STATEPRIV_SCREEN(pDrawable->pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->GetImage) (pDrawable, sx, sy, w, h, + format, planeMask, pdstLine); +} + +static void +XAAStateWrapGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart) +{ + GET_STATEPRIV_SCREEN(pDrawable->pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); +} + +static void +XAAStateWrapCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + GET_STATEPRIV_SCREEN(pWindow->drawable.pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->CopyWindow) (pWindow, ptOldOrg, prgnSrc); +} + +static Bool +XAAStateWrapSetupForCPUToScreenAlphaTexture2(ScrnInfoPtr pScrn, + int op, CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + CARD32 srcFormat, + CARD32 dstFormat, + CARD8 *alphaPtr, + int alphaPitch, + int width, int height, int flags) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->SetupForCPUToScreenAlphaTexture2) (pScrn, op, red, + green, blue, alpha, + srcFormat, + dstFormat, alphaPtr, + alphaPitch, width, + height, flags); +} + +static Bool +XAAStateWrapSetupForCPUToScreenTexture2(ScrnInfoPtr pScrn, int op, + CARD32 srcFormat, + CARD32 dstFormat, + CARD8 *texPtr, int texPitch, + int width, int height, int flags) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->SetupForCPUToScreenTexture2) (pScrn, op, srcFormat, + dstFormat, texPtr, + texPitch, width, height, + flags); +} + +/* Setup Function */ +Bool +XAAInitStateWrap(ScreenPtr pScreen, XAAInfoRecPtr infoRec) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + XAAStateWrapPtr pStatePriv; + int i = 0; + + if (!dixRegisterPrivateKey(&XAAStateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + if (!(pStatePriv = malloc(sizeof(XAAStateWrapRec)))) + return FALSE; + dixSetPrivate(&pScreen->devPrivates, XAAStateKey, pStatePriv); + pStatePriv->RestoreAccelState = infoRec->RestoreAccelState; + pStatePriv->pScrn = pScrn; + + /* Initialize the last screen to -1 so whenever an accel function + * is called the proper state is setup + */ + while (i < pScrn->numEntities) { + xf86SetLastScrnFlag(pScrn->entityList[i], -1); + i++; + } +/* Do the wrapping */ + XAA_STATE_WRAP(Sync); + XAA_STATE_WRAP(SetupForScreenToScreenCopy); + XAA_STATE_WRAP(SetupForSolidFill); + XAA_STATE_WRAP(SetupForSolidLine); + XAA_STATE_WRAP(SetupForDashedLine); + XAA_STATE_WRAP(SetClippingRectangle); + XAA_STATE_WRAP(DisableClipping); + XAA_STATE_WRAP(SetupForMono8x8PatternFill); + XAA_STATE_WRAP(SetupForColor8x8PatternFill); + XAA_STATE_WRAP(SetupForCPUToScreenColorExpandFill); + XAA_STATE_WRAP(SetupForScanlineCPUToScreenColorExpandFill); + XAA_STATE_WRAP(SetupForScreenToScreenColorExpandFill); + XAA_STATE_WRAP(SetupForImageWrite); + XAA_STATE_WRAP(SetupForScanlineImageWrite); + XAA_STATE_WRAP(SetupForImageRead); + XAA_STATE_WRAP(ScreenToScreenBitBlt); + XAA_STATE_WRAP(WriteBitmap); + XAA_STATE_WRAP(FillSolidRects); + XAA_STATE_WRAP(FillMono8x8PatternRects); + XAA_STATE_WRAP(FillColor8x8PatternRects); + XAA_STATE_WRAP(FillCacheBltRects); + XAA_STATE_WRAP(FillColorExpandRects); + XAA_STATE_WRAP(FillCacheExpandRects); + XAA_STATE_WRAP(FillImageWriteRects); + XAA_STATE_WRAP(FillSolidSpans); + XAA_STATE_WRAP(FillMono8x8PatternSpans); + XAA_STATE_WRAP(FillColor8x8PatternSpans); + XAA_STATE_WRAP(FillCacheBltSpans); + XAA_STATE_WRAP(FillColorExpandSpans); + XAA_STATE_WRAP(FillCacheExpandSpans); + XAA_STATE_WRAP(TEGlyphRenderer); + XAA_STATE_WRAP(NonTEGlyphRenderer); + XAA_STATE_WRAP(WritePixmap); + XAA_STATE_WRAP(ReadPixmap); + XAA_STATE_WRAP(CopyArea); + XAA_STATE_WRAP(CopyPlane); + XAA_STATE_WRAP(PushPixelsSolid); + XAA_STATE_WRAP(PolyFillRectSolid); + XAA_STATE_WRAP(PolyFillRectStippled); + XAA_STATE_WRAP(PolyFillRectOpaqueStippled); + XAA_STATE_WRAP(PolyFillRectTiled); + XAA_STATE_WRAP(FillSpansSolid); + XAA_STATE_WRAP(FillSpansStippled); + XAA_STATE_WRAP(FillSpansOpaqueStippled); + XAA_STATE_WRAP(FillSpansTiled); + XAA_STATE_WRAP(PolyText8TE); + XAA_STATE_WRAP(PolyText16TE); + XAA_STATE_WRAP(ImageText8TE); + XAA_STATE_WRAP(ImageText16TE); + XAA_STATE_WRAP(ImageGlyphBltTE); + XAA_STATE_WRAP(PolyGlyphBltTE); + XAA_STATE_WRAP(PolyText8NonTE); + XAA_STATE_WRAP(PolyText16NonTE); + XAA_STATE_WRAP(ImageText8NonTE); + XAA_STATE_WRAP(ImageText16NonTE); + XAA_STATE_WRAP(ImageGlyphBltNonTE); + XAA_STATE_WRAP(PolyGlyphBltNonTE); + XAA_STATE_WRAP(PolyRectangleThinSolid); + XAA_STATE_WRAP(PolylinesWideSolid); + XAA_STATE_WRAP(PolylinesThinSolid); + XAA_STATE_WRAP(PolySegmentThinSolid); + XAA_STATE_WRAP(PolylinesThinDashed); + XAA_STATE_WRAP(PolySegmentThinDashed); + XAA_STATE_WRAP(FillPolygonSolid); + XAA_STATE_WRAP(FillPolygonStippled); + XAA_STATE_WRAP(FillPolygonOpaqueStippled); + XAA_STATE_WRAP(FillPolygonTiled); + XAA_STATE_WRAP(PolyFillArcSolid); + XAA_STATE_WRAP(PutImage); + XAA_STATE_WRAP(ValidateFillSpans); + XAA_STATE_WRAP(ValidateSetSpans); + XAA_STATE_WRAP(ValidatePutImage); + XAA_STATE_WRAP(ValidateCopyArea); + XAA_STATE_WRAP(ValidateCopyPlane); + XAA_STATE_WRAP(ValidatePolyPoint); + XAA_STATE_WRAP(ValidatePolylines); + XAA_STATE_WRAP(ValidatePolySegment); + XAA_STATE_WRAP(ValidatePolyRectangle); + XAA_STATE_WRAP(ValidatePolyArc); + XAA_STATE_WRAP(ValidateFillPolygon); + XAA_STATE_WRAP(ValidatePolyFillRect); + XAA_STATE_WRAP(ValidatePolyFillArc); + XAA_STATE_WRAP(ValidatePolyText8); + XAA_STATE_WRAP(ValidatePolyText16); + XAA_STATE_WRAP(ValidateImageText8); + XAA_STATE_WRAP(ValidateImageText16); + XAA_STATE_WRAP(ValidatePolyGlyphBlt); + XAA_STATE_WRAP(ValidateImageGlyphBlt); + XAA_STATE_WRAP(ValidatePushPixels); + XAA_STATE_WRAP(ComputeDash); + XAA_STATE_WRAP(InitPixmapCache); + XAA_STATE_WRAP(ClosePixmapCache); + XAA_STATE_WRAP(StippledFillChooser); + XAA_STATE_WRAP(OpaqueStippledFillChooser); + XAA_STATE_WRAP(TiledFillChooser); + XAA_STATE_WRAP(CacheTile); + XAA_STATE_WRAP(CacheStipple); + XAA_STATE_WRAP(CacheMonoStipple); + XAA_STATE_WRAP(CacheMono8x8Pattern); + XAA_STATE_WRAP(CacheColor8x8Pattern); + XAA_STATE_WRAP(WriteBitmapToCache); + XAA_STATE_WRAP(WritePixmapToCache); + XAA_STATE_WRAP(WriteMono8x8PatternToCache); + XAA_STATE_WRAP(WriteColor8x8PatternToCache); + XAA_STATE_WRAP(GetImage); + XAA_STATE_WRAP(GetSpans); + XAA_STATE_WRAP(CopyWindow); + XAA_STATE_WRAP(SetupForCPUToScreenAlphaTexture2); + XAA_STATE_WRAP(SetupForCPUToScreenTexture2); + return TRUE; +} diff --git a/hw/xfree86/xaa/xaaStipple.c b/hw/xfree86/xaa/xaaStipple.c new file mode 100644 index 000000000..fc74e3988 --- /dev/null +++ b/hw/xfree86/xaa/xaaStipple.c @@ -0,0 +1,915 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xaa.h" +#include "xaalocal.h" +#include "xaacexp.h" +#include "xf86.h" + +static CARD32 *StipplePowerOfTwo(CARD32 *, CARD32 *, int, int, int); +static CARD32 *StipplePowerOfTwo_Inverted(CARD32 *, CARD32 *, int, int, int); +static CARD32 *StippleUpTo32(CARD32 *, CARD32 *, int, int, int); +static CARD32 *StippleUpTo32_Inverted(CARD32 *, CARD32 *, int, int, int); +static CARD32 *StippleOver32(CARD32 *, CARD32 *, int, int, int); +static CARD32 *StippleOver32_Inverted(CARD32 *, CARD32 *, int, int, int); + +#ifdef TRIPLE_BITS +#define stipple_scanline_func EXPNAME(XAAStippleScanlineFunc3) +#define stipple_get_scanline_func EXPNAME(XAAGetStippleScanlineFunc3) +#else +#define stipple_scanline_func EXPNAME(XAAStippleScanlineFunc) +#define stipple_get_scanline_func EXPNAME(XAAGetStippleScanlineFunc) +#endif + +StippleScanlineProcPtr stipple_scanline_func[6] = { + StipplePowerOfTwo, + StippleUpTo32, + StippleOver32, + StipplePowerOfTwo_Inverted, + StippleUpTo32_Inverted, + StippleOver32_Inverted +}; + +StippleScanlineProcPtr * +stipple_get_scanline_func(void) +{ + return stipple_scanline_func; +} + +#ifdef FIXEDBASE +#define DEST(i) *dest +#define RETURN(i) return(dest) +#else +#define DEST(i) dest[i] +#define RETURN(i) return(dest + i) +#endif + +/* TRIPLE_BITS pattern expansion */ +#ifdef TRIPLE_BITS +#define EXPAND_PAT \ + CARD32 pat1 = byte_expand3[pat & 0xFF], \ + pat2 = byte_expand3[(pat & 0xFF00) >> 8], \ + pat3 = byte_expand3[(pat & 0xFF0000) >> 16], \ + pat4 = byte_expand3[(pat & 0xFF000000) >> 24], \ + patA = pat1 | (pat2 << 24), \ + patB = (pat2 >> 8) | (pat3 << 16), \ + patC = (pat3 >> 16) | (pat4 << 8) +#ifdef FIXED_BASE +#define WRITE_PAT1 { \ + *dest = patA; } +#define WRITE_PAT2 { \ + *dest = patA; \ + *dest = patB; } +#define WRITE_PAT3 { \ + *dest = patA; \ + *dest = patB; \ + *dest = patC; } +#else +#define WRITE_PAT1 { \ + *(dest++) = patA; } +#define WRITE_PAT2 { \ + *(dest) = patA; \ + *(dest + 1) = patB; \ + dest += 2; } +#define WRITE_PAT3 { \ + *(dest) = patA; \ + *(dest + 1) = patB; \ + *(dest + 2) = patC; \ + dest += 3; } +#endif +#endif + +#if !defined(FIXEDBASE) && !defined(MSBFIRST) && !defined(TRIPLE_BITS) + +unsigned int XAAShiftMasks[32] = { + /* gcc is rather pedantic about SHIFT_R(0xFFFFFFFF,32) */ + 0x00000000, SHIFT_R(0xFFFFFFFF, 31), + SHIFT_R(0xFFFFFFFF, 30), SHIFT_R(0xFFFFFFFF, 29), + SHIFT_R(0xFFFFFFFF, 28), SHIFT_R(0xFFFFFFFF, 27), + SHIFT_R(0xFFFFFFFF, 26), SHIFT_R(0xFFFFFFFF, 25), + SHIFT_R(0xFFFFFFFF, 24), SHIFT_R(0xFFFFFFFF, 23), + SHIFT_R(0xFFFFFFFF, 22), SHIFT_R(0xFFFFFFFF, 21), + SHIFT_R(0xFFFFFFFF, 20), SHIFT_R(0xFFFFFFFF, 19), + SHIFT_R(0xFFFFFFFF, 18), SHIFT_R(0xFFFFFFFF, 17), + SHIFT_R(0xFFFFFFFF, 16), SHIFT_R(0xFFFFFFFF, 15), + SHIFT_R(0xFFFFFFFF, 14), SHIFT_R(0xFFFFFFFF, 13), + SHIFT_R(0xFFFFFFFF, 12), SHIFT_R(0xFFFFFFFF, 11), + SHIFT_R(0xFFFFFFFF, 10), SHIFT_R(0xFFFFFFFF, 9), + SHIFT_R(0xFFFFFFFF, 8), SHIFT_R(0xFFFFFFFF, 7), + SHIFT_R(0xFFFFFFFF, 6), SHIFT_R(0xFFFFFFFF, 5), + SHIFT_R(0xFFFFFFFF, 4), SHIFT_R(0xFFFFFFFF, 3), + SHIFT_R(0xFFFFFFFF, 2), SHIFT_R(0xFFFFFFFF, 1) +}; + +#endif + +void +#ifdef TRIPLE_BITS + EXPNAME(XAAFillColorExpandRects3) ( +#else + EXPNAME(XAAFillColorExpandRects) ( +#endif + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + Bool TwoPass = FALSE, FirstPass = TRUE; + StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc; + int stipplewidth = pPix->drawable.width; + int stippleheight = pPix->drawable.height; + int srcwidth = pPix->devKind; + int dwords, srcy, srcx, funcNo = 2, h; + unsigned char *src = (unsigned char *) pPix->devPrivate.ptr; + unsigned char *srcp; + int flag; + + if (stipplewidth <= 32) { + if (stipplewidth & (stipplewidth - 1)) + funcNo = 1; + else + funcNo = 0; + } + StippleFunc = stipple_scanline_func[funcNo]; + SecondFunc = stipple_scanline_func[funcNo]; + FirstFunc = stipple_scanline_func[funcNo + 3]; + +#ifdef TRIPLE_BITS + if ((bg == -1) || + (!(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) && + (!(infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(bg))))) { +#else + if ((bg == -1) || + !(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { +#endif + /* one pass */ + } + else if ((rop == GXcopy) && infoRec->FillSolidRects) { + /* one pass but we fill background rects first */ + (*infoRec->FillSolidRects) (pScrn, bg, rop, planemask, nBox, pBox); + bg = -1; + } + else { + /* gotta do two passes */ + TwoPass = TRUE; + } + + if (!TwoPass) + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + while (nBox--) { +#ifdef TRIPLE_BITS + dwords = (3 * (pBox->x2 - pBox->x1) + 31) >> 5; +#else + dwords = (pBox->x2 - pBox->x1 + 31) >> 5; +#endif + + SECOND_PASS: + if (TwoPass) { + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, + (FirstPass) ? bg : + fg, -1, rop, + planemask); + StippleFunc = (FirstPass) ? FirstFunc : SecondFunc; + } + + h = pBox->y2 - pBox->y1; + flag = (infoRec->CPUToScreenColorExpandFillFlags + & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01); + + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, pBox->x1, + pBox->y1, + pBox->x2 - pBox->x1, + h, 0); + + base = (CARD32 *) infoRec->ColorExpandBase; + + srcy = (pBox->y1 - yorg) % stippleheight; + if (srcy < 0) + srcy += stippleheight; + srcx = (pBox->x1 - xorg) % stipplewidth; + if (srcx < 0) + srcx += stipplewidth; + + srcp = (srcwidth * srcy) + src; + +#ifndef FIXEDBASE + if ((dwords * h) <= infoRec->ColorExpandRange) { + while (h--) { + base = + (*StippleFunc) (base, (CARD32 *) srcp, srcx, stipplewidth, + dwords); + srcy++; + srcp += srcwidth; + if (srcy >= stippleheight) { + srcy = 0; + srcp = src; + } + } + } + else +#endif + while (h--) { + (*StippleFunc) (base, (CARD32 *) srcp, srcx, stipplewidth, + dwords); + srcy++; + srcp += srcwidth; + if (srcy >= stippleheight) { + srcy = 0; + srcp = src; + } + } + + if (flag) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + + if (TwoPass) { + if (FirstPass) { + FirstPass = FALSE; + goto SECOND_PASS; + } + else + FirstPass = TRUE; + } + + pBox++; + } + + if (infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +void +#ifdef TRIPLE_BITS + EXPNAME(XAAFillColorExpandSpans3) ( +#else + EXPNAME(XAAFillColorExpandSpans) ( +#endif + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + Bool TwoPass = FALSE, FirstPass = TRUE; + StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc; + int stipplewidth = pPix->drawable.width; + int stippleheight = pPix->drawable.height; + int dwords, srcy, srcx, funcNo = 2; + unsigned char *srcp; + + if (stipplewidth <= 32) { + if (stipplewidth & (stipplewidth - 1)) + funcNo = 1; + else + funcNo = 0; + } + StippleFunc = stipple_scanline_func[funcNo]; + SecondFunc = stipple_scanline_func[funcNo]; + FirstFunc = stipple_scanline_func[funcNo + 3]; + +#ifdef TRIPLE_BITS + if ((bg == -1) || + (!(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) && + (!(infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(bg))))) { +#else + if ((bg == -1) || + !(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { +#endif + /* one pass */ + } + else if ((rop == GXcopy) && infoRec->FillSolidSpans) { + /* one pass but we fill background rects first */ + (*infoRec->FillSolidSpans) (pScrn, bg, rop, planemask, n, ppt, pwidth, + fSorted); + bg = -1; + } + else { + /* gotta do two passes */ + TwoPass = TRUE; + } + + if (!TwoPass) + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + while (n--) { +#ifdef TRIPLE_BITS + dwords = (3 * *pwidth + 31) >> 5; +#else + dwords = (*pwidth + 31) >> 5; +#endif + + srcy = (ppt->y - yorg) % stippleheight; + if (srcy < 0) + srcy += stippleheight; + srcx = (ppt->x - xorg) % stipplewidth; + if (srcx < 0) + srcx += stipplewidth; + + srcp = (pPix->devKind * srcy) + (unsigned char *) pPix->devPrivate.ptr; + + SECOND_PASS: + if (TwoPass) { + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, + (FirstPass) ? bg : + fg, -1, rop, + planemask); + StippleFunc = (FirstPass) ? FirstFunc : SecondFunc; + } + + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, ppt->x, ppt->y, + *pwidth, 1, 0); + + base = (CARD32 *) infoRec->ColorExpandBase; + + (*StippleFunc) (base, (CARD32 *) srcp, srcx, stipplewidth, dwords); + + if ((infoRec->CPUToScreenColorExpandFillFlags & CPU_TRANSFER_PAD_QWORD) + && (dwords & 0x01)) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + + if (TwoPass) { + if (FirstPass) { + FirstPass = FALSE; + goto SECOND_PASS; + } + else + FirstPass = TRUE; + } + + ppt++; + pwidth++; + } + + if (infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +#ifndef FIXEDBASE + +void +#ifdef TRIPLE_BITS + EXPNAME(XAAFillScanlineColorExpandRects3) ( +#else + EXPNAME(XAAFillScanlineColorExpandRects) ( +#endif + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + Bool TwoPass = FALSE, FirstPass = TRUE; + StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc; + int stipplewidth = pPix->drawable.width; + int stippleheight = pPix->drawable.height; + int srcwidth = pPix->devKind; + int dwords, srcy, srcx, funcNo = 2, bufferNo, h; + unsigned char *src = pPix->devPrivate.ptr; + unsigned char *srcp; + + if (stipplewidth <= 32) { + if (stipplewidth & (stipplewidth - 1)) + funcNo = 1; + else + funcNo = 0; + } + StippleFunc = stipple_scanline_func[funcNo]; + SecondFunc = stipple_scanline_func[funcNo]; + FirstFunc = stipple_scanline_func[funcNo + 3]; + +#ifdef TRIPLE_BITS + if ((bg == -1) || + (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) + && (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(bg))))) { +#else + if ((bg == -1) || + !(infoRec-> + ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { +#endif + /* one pass */ + } + else if ((rop == GXcopy) && infoRec->FillSolidRects) { + /* one pass but we fill background rects first */ + (*infoRec->FillSolidRects) (pScrn, bg, rop, planemask, nBox, pBox); + bg = -1; + } + else { + /* gotta do two passes */ + TwoPass = TRUE; + } + + if (!TwoPass) + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, + rop, planemask); + + while (nBox--) { +#ifdef TRIPLE_BITS + dwords = (3 * (pBox->x2 - pBox->x1) + 31) >> 5; +#else + dwords = (pBox->x2 - pBox->x1 + 31) >> 5; +#endif + + SECOND_PASS: + if (TwoPass) { + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, + (FirstPass) + ? bg : fg, + -1, rop, + planemask); + StippleFunc = (FirstPass) ? FirstFunc : SecondFunc; + } + + h = pBox->y2 - pBox->y1; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, + pBox->x1, + pBox->y1, + pBox->x2 - + pBox->x1, h, + 0); + + bufferNo = 0; + + srcy = (pBox->y1 - yorg) % stippleheight; + if (srcy < 0) + srcy += stippleheight; + srcx = (pBox->x1 - xorg) % stipplewidth; + if (srcx < 0) + srcx += stipplewidth; + + srcp = (srcwidth * srcy) + src; + + while (h--) { + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + (*StippleFunc) (base, (CARD32 *) srcp, srcx, stipplewidth, dwords); + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + srcy++; + srcp += srcwidth; + if (srcy >= stippleheight) { + srcy = 0; + srcp = src; + } + } + + if (TwoPass) { + if (FirstPass) { + FirstPass = FALSE; + goto SECOND_PASS; + } + else + FirstPass = TRUE; + } + + pBox++; + } + + SET_SYNC_FLAG(infoRec); +} + +void +#ifdef TRIPLE_BITS + EXPNAME(XAAFillScanlineColorExpandSpans3) ( +#else + EXPNAME(XAAFillScanlineColorExpandSpans) ( +#endif + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + Bool TwoPass = FALSE, FirstPass = TRUE; + StippleScanlineProcPtr StippleFunc, FirstFunc, SecondFunc; + int stipplewidth = pPix->drawable.width; + int stippleheight = pPix->drawable.height; + int dwords, srcy, srcx, funcNo = 2; + unsigned char *srcp; + + if (stipplewidth <= 32) { + if (stipplewidth & (stipplewidth - 1)) + funcNo = 1; + else + funcNo = 0; + } + StippleFunc = stipple_scanline_func[funcNo]; + SecondFunc = stipple_scanline_func[funcNo]; + FirstFunc = stipple_scanline_func[funcNo + 3]; + +#ifdef TRIPLE_BITS + if ((bg == -1) || + (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) + && (!(infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(bg))))) { +#else + if ((bg == -1) || + !(infoRec-> + ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) { +#endif + /* one pass */ + } + else if ((rop == GXcopy) && infoRec->FillSolidSpans) { + /* one pass but we fill background rects first */ + (*infoRec->FillSolidSpans) (pScrn, bg, rop, planemask, n, ppt, pwidth, + fSorted); + bg = -1; + } + else { + /* gotta do two passes */ + TwoPass = TRUE; + } + + if (!TwoPass) + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, + rop, planemask); + + while (n--) { +#ifdef TRIPLE_BITS + dwords = (3 * *pwidth + 31) >> 5; +#else + dwords = (*pwidth + 31) >> 5; +#endif + + srcy = (ppt->y - yorg) % stippleheight; + if (srcy < 0) + srcy += stippleheight; + srcx = (ppt->x - xorg) % stipplewidth; + if (srcx < 0) + srcx += stipplewidth; + + srcp = (pPix->devKind * srcy) + (unsigned char *) pPix->devPrivate.ptr; + + SECOND_PASS: + if (TwoPass) { + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, + (FirstPass) + ? bg : fg, + -1, rop, + planemask); + StippleFunc = (FirstPass) ? FirstFunc : SecondFunc; + } + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, ppt->x, + ppt->y, + *pwidth, 1, + 0); + + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[0]; + + (*StippleFunc) (base, (CARD32 *) srcp, srcx, stipplewidth, dwords); + (*infoRec->SubsequentColorExpandScanline) (pScrn, 0); + + if (TwoPass) { + if (FirstPass) { + FirstPass = FALSE; + goto SECOND_PASS; + } + else + FirstPass = TRUE; + } + + ppt++; + pwidth++; + } + + SET_SYNC_FLAG(infoRec); +} + +#endif + +static CARD32 * +StipplePowerOfTwo(CARD32 *dest, CARD32 *src, int shift, int width, int dwords) +{ + CARD32 pat = *src; + + if (width < 32) { + pat &= XAAShiftMasks[width]; + while (width < 32) { + pat |= SHIFT_L(pat, width); + width <<= 1; + } + } + + if (shift) + pat = SHIFT_R(pat, shift) | SHIFT_L(pat, 32 - shift); + +#ifdef MSBFIRST + pat = SWAP_BITS_IN_BYTES(pat); +#endif + +#ifdef TRIPLE_BITS + { + EXPAND_PAT; + + while (dwords >= 3) { + WRITE_PAT3; + dwords -= 3; + } + if (dwords == 2) { + WRITE_PAT2; + } + else if (dwords == 1) { + WRITE_PAT1; + } + + return dest; + } +#else /* TRIPLE_BITS */ + while (dwords >= 4) { + DEST(0) = pat; + DEST(1) = pat; + DEST(2) = pat; + DEST(3) = pat; + dwords -= 4; +#ifndef FIXEDBASE + dest += 4; +#endif + } + + if (!dwords) + return dest; + DEST(0) = pat; + if (dwords == 1) + RETURN(1); + DEST(1) = pat; + if (dwords == 2) + RETURN(2); + DEST(2) = pat; + RETURN(3); +#endif /* TRIPLE_BITS */ +} + +static CARD32 * +StipplePowerOfTwo_Inverted(CARD32 *dest, CARD32 *src, + int shift, int width, int dwords) +{ + CARD32 pat = *src; + + if (width < 32) { + pat &= XAAShiftMasks[width]; + while (width < 32) { + pat |= SHIFT_L(pat, width); + width <<= 1; + } + } + + if (shift) + pat = SHIFT_R(pat, shift) | SHIFT_L(pat, 32 - shift); + +#ifdef MSBFIRST + pat = SWAP_BITS_IN_BYTES(pat); +#endif + + pat = ~pat; + +#ifdef TRIPLE_BITS + { + EXPAND_PAT; + + while (dwords >= 3) { + WRITE_PAT3; + dwords -= 3; + } + if (dwords == 2) { + WRITE_PAT2; + } + else if (dwords == 1) { + WRITE_PAT1; + } + + return dest; + } +#else /* TRIPLE_BITS */ + while (dwords >= 4) { + DEST(0) = pat; + DEST(1) = pat; + DEST(2) = pat; + DEST(3) = pat; + dwords -= 4; +#ifndef FIXEDBASE + dest += 4; +#endif + } + + if (!dwords) + return dest; + DEST(0) = pat; + if (dwords == 1) + RETURN(1); + DEST(1) = pat; + if (dwords == 2) + RETURN(2); + DEST(2) = pat; + RETURN(3); +#endif /* TRIPLE_BITS */ +} + +static CARD32 * +StippleUpTo32(CARD32 *base, CARD32 *src, int shift, int width, int dwords) +{ + CARD32 pat = *src & XAAShiftMasks[width]; + + while (width <= 15) { + pat |= SHIFT_L(pat, width); + width <<= 1; + } + pat |= SHIFT_L(pat, width); + + while (dwords--) { + CARD32 bits = SHIFT_R(pat, shift) | SHIFT_L(pat, width - shift); + +#ifdef TRIPLE_BITS + if (dwords >= 2) { + WRITE_BITS3(bits); + dwords -= 2; + } + else if (dwords > 0) { + WRITE_BITS2(bits); + dwords--; + } + else { + WRITE_BITS1(bits); + } +#else + WRITE_BITS(bits); +#endif + + shift += 32; + shift %= width; + } + return base; +} + +static CARD32 * +StippleUpTo32_Inverted(CARD32 *base, CARD32 *src, + int shift, int width, int dwords) +{ + CARD32 pat = *src & XAAShiftMasks[width]; + + while (width <= 15) { + pat |= SHIFT_L(pat, width); + width <<= 1; + } + pat |= SHIFT_L(pat, width); + + while (dwords--) { + CARD32 bits = ~(SHIFT_R(pat, shift) | SHIFT_L(pat, width - shift)); + +#ifdef TRIPLE_BITS + if (dwords >= 2) { + WRITE_BITS3(bits); + dwords -= 2; + } + else if (dwords > 0) { + WRITE_BITS2(bits); + dwords--; + } + else { + WRITE_BITS1(bits); + } +#else + WRITE_BITS(bits); +#endif + + shift += 32; + shift %= width; + } + return base; +} + +static CARD32 * +StippleOver32(CARD32 *base, CARD32 *src, int offset, int width, int dwords) +{ + CARD32 *srcp; + CARD32 bits; + int bitsleft, shift, usable; + + while (dwords--) { + bitsleft = width - offset; + srcp = src + (offset >> 5); + shift = offset & 31; + usable = 32 - shift; + + if (bitsleft < 32) { + if (bitsleft <= usable) { + bits = SHIFT_L(*src, bitsleft) | + (SHIFT_R(*srcp, shift) & XAAShiftMasks[bitsleft]); + } + else { + bits = SHIFT_L(*src, bitsleft) | + (SHIFT_L(srcp[1], usable) & XAAShiftMasks[bitsleft]) | + (SHIFT_R(*srcp, shift) & XAAShiftMasks[usable]); + } + } + else if (shift) + bits = SHIFT_R(*srcp, shift) | SHIFT_L(srcp[1], usable); + else + bits = *srcp; + +#ifdef TRIPLE_BITS + if (dwords >= 2) { + WRITE_BITS3(bits); + dwords -= 2; + } + else if (dwords > 0) { + WRITE_BITS2(bits); + dwords--; + } + else { + WRITE_BITS1(bits); + } +#else + WRITE_BITS(bits); +#endif + + offset += 32; + offset %= width; + } + return base; +} + +static CARD32 * +StippleOver32_Inverted(CARD32 *base, CARD32 *src, + int offset, int width, int dwords) +{ + CARD32 *srcp; + CARD32 bits; + int bitsleft, shift, usable; + + while (dwords--) { + bitsleft = width - offset; + srcp = src + (offset >> 5); + shift = offset & 31; + usable = 32 - shift; + + if (bitsleft < 32) { + if (bitsleft <= usable) { + bits = SHIFT_L(*src, bitsleft) | + (SHIFT_R(*srcp, shift) & XAAShiftMasks[bitsleft]); + } + else { + bits = SHIFT_L(*src, bitsleft) | + (SHIFT_L(srcp[1], usable) & XAAShiftMasks[bitsleft]) | + (SHIFT_R(*srcp, shift) & XAAShiftMasks[usable]); + } + } + else if (shift) + bits = SHIFT_R(*srcp, shift) | SHIFT_L(srcp[1], usable); + else + bits = *srcp; + + bits = ~bits; + +#ifdef TRIPLE_BITS + if (dwords >= 2) { + WRITE_BITS3(bits); + dwords -= 2; + } + else if (dwords > 0) { + WRITE_BITS2(bits); + dwords--; + } + else { + WRITE_BITS1(bits); + } +#else + WRITE_BITS(bits); +#endif + + offset += 32; + offset %= width; + } + return base; +} diff --git a/hw/xfree86/xaa/xaaTEGlyph.c b/hw/xfree86/xaa/xaaTEGlyph.c new file mode 100644 index 000000000..2926c1df2 --- /dev/null +++ b/hw/xfree86/xaa/xaaTEGlyph.c @@ -0,0 +1,1083 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xaa.h" +#include "xaalocal.h" +#include "xaacexp.h" +#include "xf86.h" + +/* scanline function for TRIPLE_BITS_24BPP */ +static CARD32 *DrawTextScanline3(CARD32 *base, CARD32 *mem, int width); + +/* Loop unrolled functions for common font widths */ +static CARD32 *DrawTETextScanlineGeneric(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth7(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth10(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth12(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth14(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth16(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth18(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth24(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); + +#ifdef USEASSEMBLER +#ifdef FIXEDBASE +#ifdef MSBFIRST +CARD32 *DrawTETextScanlineWidth6PMSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, + int line, int width, + int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PMSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, + int line, int width, + int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PMSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, + int line, int width, + int glyphwidth); +#else +CARD32 *DrawTETextScanlineWidth6PLSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, + int line, int width, + int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PLSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, + int line, int width, + int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PLSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, + int line, int width, + int glyphwidth); +#endif +#else +#ifdef MSBFIRST +CARD32 *DrawTETextScanlineWidth6PMSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PMSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PMSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +#else +CARD32 *DrawTETextScanlineWidth6PLSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PLSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PLSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +#endif +#endif +#else +static CARD32 *DrawTETextScanlineWidth6(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth8(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth9(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +#endif + +#define glyph_scanline_func EXPNAME(XAAGlyphScanlineFunc) +#define glyph_get_scanline_func EXPNAME(XAAGetGlyphScanlineFunc) + +GlyphScanlineFuncPtr glyph_scanline_func[32] = { + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, +#ifdef USEASSEMBLER +#ifdef FIXEDBASE +#ifdef MSBFIRST + DrawTETextScanlineWidth6PMSBFirstFixedBase, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PMSBFirstFixedBase, + DrawTETextScanlineWidth9PMSBFirstFixedBase, +#else + DrawTETextScanlineWidth6PLSBFirstFixedBase, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PLSBFirstFixedBase, + DrawTETextScanlineWidth9PLSBFirstFixedBase, +#endif +#else +#ifdef MSBFIRST + DrawTETextScanlineWidth6PMSBFirst, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PMSBFirst, + DrawTETextScanlineWidth9PMSBFirst, +#else + DrawTETextScanlineWidth6PLSBFirst, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PLSBFirst, + DrawTETextScanlineWidth9PLSBFirst, +#endif +#endif +#else + DrawTETextScanlineWidth6, DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8, DrawTETextScanlineWidth9, +#endif + DrawTETextScanlineWidth10, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth12, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth14, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth16, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth18, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth24, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric +}; + +GlyphScanlineFuncPtr * +glyph_get_scanline_func(void) +{ + return glyph_scanline_func; +} + +/******************************************************************** + + Here we have TEGlyphRenders for a bunch of different color + expansion types. The driver may provide its own renderer, but + this is the default one which renders using lower-level primitives + exported by the chipset driver. + +********************************************************************/ + +/* This gets built for MSBFIRST or LSBFIRST with FIXEDBASE or not. + A total of 4 versions */ + +void + +EXPNAME(XAATEGlyphRenderer) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base; + GlyphScanlineFuncPtr GlyphFunc = glyph_scanline_func[glyphWidth - 1]; + int dwords = 0; + + if ((bg != -1) && (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + (*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + if (skipleft && + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING) || + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (skipleft > x)))) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + + if (width > w) + width = w; + + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, x, y, width, h, + 0); + + base = (CARD32 *) infoRec->ColorExpandBase; + + while (count--) { + register CARD32 tmp = SHIFT_R(glyphs[0][line++], skipleft); + + WRITE_BITS(tmp); + } + + w -= width; + if ((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + ((((width + 31) >> 5) * h) & 1)) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + if (!w) + goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + w += skipleft; + x -= skipleft; + dwords = ((w + 31) >> 5) * h; + + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, x, y, w, h, + skipleft); + + base = (CARD32 *) infoRec->ColorExpandBase; + +#ifndef FIXEDBASE + if ((((w + 31) >> 5) * h) <= infoRec->ColorExpandRange) + while (h--) { + base = (*GlyphFunc) (base, glyphs, startline++, w, glyphWidth); + } + else +#endif + while (h--) { + (*GlyphFunc) (base, glyphs, startline++, w, glyphWidth); + } + + if ((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + (dwords & 1)) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + + THE_END: + + if (infoRec->TEGlyphRendererFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +/******************************************************************** + + This is the GlyphRenderer for TRIPLE_BITS_24BPP. It renders to a buffer + with the non FIXEDBASE LSB_FIRST code before tripling, and possibly + reversing the bits and sending them to the screen + +********************************************************************/ + +void + +EXPNAME(XAATEGlyphRenderer3) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base, *mem; + GlyphScanlineFuncPtr GlyphFunc = + XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; + int dwords = 0; + + if ((bg != -1) && + ((infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY) || + ((infoRec->TEGlyphRendererFlags & RGB_EQUAL) && + (!CHECK_RGB_EQUAL(bg))))) { + (*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + if (skipleft) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + CARD32 bits; + + if (width > w) + width = w; + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, x, y, width, h, + 0); + + base = (CARD32 *) infoRec->ColorExpandBase; + + while (count--) { + bits = SHIFT_R(glyphs[0][line++], skipleft); + if (width >= 22) { + WRITE_BITS3(bits); + } + else if (width >= 11) { + WRITE_BITS2(bits); + } + else { + WRITE_BITS1(bits); + } + } + + w -= width; + if ((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + ((((3 * width + 31) >> 5) * h) & 1)) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + if (!w) + goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + dwords = ((3 * w + 31) >> 5) * h; + mem = (CARD32 *) malloc(((w + 31) >> 3) * sizeof(char)); + if (!mem) + return; + + (*infoRec->SubsequentCPUToScreenColorExpandFill) (pScrn, x, y, w, h, 0); + + base = (CARD32 *) infoRec->ColorExpandBase; + +#ifndef FIXEDBASE + if ((((3 * w + 31) >> 5) * h) <= infoRec->ColorExpandRange) + while (h--) { + (*GlyphFunc) (mem, glyphs, startline++, w, glyphWidth); + base = DrawTextScanline3(base, mem, w); + } + else +#endif + while (h--) { + (*GlyphFunc) (mem, glyphs, startline++, w, glyphWidth); + DrawTextScanline3(base, mem, w); + } + + free(mem); + + if ((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + (dwords & 1)) { + base = (CARD32 *) infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + + THE_END: + + if (infoRec->TEGlyphRendererFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync) (pScrn); + else + SET_SYNC_FLAG(infoRec); +} + +#ifndef FIXEDBASE +/* Scanline version of above gets built for LSBFIRST and MSBFIRST */ + +void + +EXPNAME(XAATEGlyphRendererScanline) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int bufferNo; + CARD32 *base; + GlyphScanlineFuncPtr GlyphFunc = glyph_scanline_func[glyphWidth - 1]; + + if ((bg != -1) && (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + (*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + if (skipleft && + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING) || + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (skipleft > x)))) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + + if (width > w) + width = w; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, x, y, + width, h, 0); + + bufferNo = 0; + + while (count--) { + register CARD32 tmp = SHIFT_R(glyphs[0][line++], skipleft); + + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + WRITE_BITS(tmp); + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + w -= width; + if (!w) + goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + w += skipleft; + x -= skipleft; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, x, y, w, h, + skipleft); + + bufferNo = 0; + + while (h--) { + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + (*GlyphFunc) (base, glyphs, startline++, w, glyphWidth); + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + THE_END: + + SET_SYNC_FLAG(infoRec); +} + +void + +EXPNAME(XAATEGlyphRendererScanline3) (ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int bufferNo; + CARD32 *base, *mem; + GlyphScanlineFuncPtr GlyphFunc = + XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; + + if ((bg != -1) && + ((infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY) || + ((infoRec->TEGlyphRendererFlags & RGB_EQUAL) && + (!CHECK_RGB_EQUAL(bg))))) { + (*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, rop, + planemask); + + if (skipleft) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + CARD32 bits; + + if (width > w) + width = w; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, x, y, + width, h, 0); + + bufferNo = 0; + + while (count--) { + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + bits = SHIFT_R(glyphs[0][line++], skipleft); + if (width >= 22) { + WRITE_BITS3(bits); + } + else if (width >= 11) { + WRITE_BITS2(bits); + } + else { + WRITE_BITS1(bits); + } + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + w -= width; + if (!w) + goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + w += skipleft; + x -= skipleft; + mem = (CARD32 *) malloc(((w + 31) >> 3) * sizeof(char)); + if (!mem) + return; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, x, y, w, h, + skipleft); + + bufferNo = 0; + + while (h--) { + base = (CARD32 *) infoRec->ScanlineColorExpandBuffers[bufferNo]; + (*GlyphFunc) (mem, glyphs, startline++, w, glyphWidth); + DrawTextScanline3(base, mem, w); + (*infoRec->SubsequentColorExpandScanline) (pScrn, bufferNo++); + if (bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + free(mem); + + THE_END: + + SET_SYNC_FLAG(infoRec); +} + +#endif + +/******************************************************************** + + TRIPLE_BITS_24BPP scanline rendering code. + +********************************************************************/ + +static CARD32 * +DrawTextScanline3(CARD32 *base, CARD32 *mem, int width) +{ + + while (width > 32) { + WRITE_BITS3(*mem); + mem++; + width -= 32; + } + if (width) { + if (width >= 22) { + WRITE_BITS3(*mem); + } + else if (width >= 11) { + WRITE_BITS2(*mem); + } + else { + WRITE_BITS1(*mem); + } + } + + return base; +} + +/******************************************************************** + + Generic TE scanline rendering code. + +********************************************************************/ + +static CARD32 * +DrawTETextScanlineGeneric(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + CARD32 bits = (*glyphp)[line]; + int shift = glyphwidth; + + while (width > 32) { + while (shift < 32) { + glyphp++; + bits |= SHIFT_L((*glyphp)[line], shift); + shift += glyphwidth; + } + WRITE_BITS(bits); + shift &= 31; + if (shift) + bits = SHIFT_R((*glyphp)[line], (glyphwidth - shift)); + else + bits = 0; + width -= 32; + } + + if (width) { + width -= shift; + while (width > 0) { + glyphp++; + bits |= SHIFT_L((*glyphp)[line], shift); + shift += glyphwidth; + width -= glyphwidth; + } + WRITE_BITS(bits); + } + + return base; +} + +/******************************************************************** + + Loop unrolled TE font scanline rendering code + +********************************************************************/ + +#ifndef USEASSEMBLER +static CARD32 * +DrawTETextScanlineWidth6(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 6); + bits |= SHIFT_L(glyphp[2][line], 12); + bits |= SHIFT_L(glyphp[3][line], 18); + bits |= SHIFT_L(glyphp[4][line], 24); + bits |= SHIFT_L(glyphp[5][line], 30); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[5][line], 2); + bits |= SHIFT_L(glyphp[6][line], 4); + bits |= SHIFT_L(glyphp[7][line], 10); + bits |= SHIFT_L(glyphp[8][line], 16); + bits |= SHIFT_L(glyphp[9][line], 22); + bits |= SHIFT_L(glyphp[10][line], 28); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[10][line], 4); + bits |= SHIFT_L(glyphp[11][line], 2); + bits |= SHIFT_L(glyphp[12][line], 8); + bits |= SHIFT_L(glyphp[13][line], 14); + bits |= SHIFT_L(glyphp[14][line], 20); + bits |= SHIFT_L(glyphp[15][line], 26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); +#ifndef FIXEDBASE + base += 3; +#endif + width -= 96; + glyphp += 16; + } + return base; +} +#endif + +static CARD32 * +DrawTETextScanlineWidth7(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 7); + bits |= SHIFT_L(glyphp[2][line], 14); + bits |= SHIFT_L(glyphp[3][line], 21); + bits |= SHIFT_L(glyphp[4][line], 28); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[4][line], 4); + bits |= SHIFT_L(glyphp[5][line], 3); + bits |= SHIFT_L(glyphp[6][line], 10); + bits |= SHIFT_L(glyphp[7][line], 17); + bits |= SHIFT_L(glyphp[8][line], 24); + bits |= SHIFT_L(glyphp[9][line], 31); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[9][line], 1); + bits |= SHIFT_L(glyphp[10][line], 6); + bits |= SHIFT_L(glyphp[11][line], 13); + bits |= SHIFT_L(glyphp[12][line], 20); + bits |= SHIFT_L(glyphp[13][line], 27); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[13][line], 5); + bits |= SHIFT_L(glyphp[14][line], 2); + bits |= SHIFT_L(glyphp[15][line], 9); + bits |= SHIFT_L(glyphp[16][line], 16); + bits |= SHIFT_L(glyphp[17][line], 23); + bits |= SHIFT_L(glyphp[18][line], 30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[18][line], 2); + bits |= SHIFT_L(glyphp[19][line], 5); + bits |= SHIFT_L(glyphp[20][line], 12); + bits |= SHIFT_L(glyphp[21][line], 19); + bits |= SHIFT_L(glyphp[22][line], 26); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[22][line], 6); + bits |= SHIFT_L(glyphp[23][line], 1); + bits |= SHIFT_L(glyphp[24][line], 8); + bits |= SHIFT_L(glyphp[25][line], 15); + bits |= SHIFT_L(glyphp[26][line], 22); + bits |= SHIFT_L(glyphp[27][line], 29); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[27][line], 3); + bits |= SHIFT_L(glyphp[28][line], 4); + bits |= SHIFT_L(glyphp[29][line], 11); + bits |= SHIFT_L(glyphp[30][line], 18); + bits |= SHIFT_L(glyphp[31][line], 25); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); +#ifndef FIXEDBASE + base += 7; +#endif + width -= 224; + glyphp += 32; + } + return base; +} + +#ifndef USEASSEMBLER +static CARD32 * +DrawTETextScanlineWidth8(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 8); + bits |= SHIFT_L(glyphp[2][line], 16); + bits |= SHIFT_L(glyphp[3][line], 24); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = glyphp[4][line]; + bits |= SHIFT_L(glyphp[5][line], 8); + bits |= SHIFT_L(glyphp[6][line], 16); + bits |= SHIFT_L(glyphp[7][line], 24); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); +#ifndef FIXEDBASE + base += 2; +#endif + width -= 64; + glyphp += 8; + } + return base; +} +#endif + +#ifndef USEASSEMBLER +static CARD32 * +DrawTETextScanlineWidth9(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 9); + bits |= SHIFT_L(glyphp[2][line], 18); + bits |= SHIFT_L(glyphp[3][line], 27); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[3][line], 5); + bits |= SHIFT_L(glyphp[4][line], 4); + bits |= SHIFT_L(glyphp[5][line], 13); + bits |= SHIFT_L(glyphp[6][line], 22); + bits |= SHIFT_L(glyphp[7][line], 31); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[7][line], 1); + bits |= SHIFT_L(glyphp[8][line], 8); + bits |= SHIFT_L(glyphp[9][line], 17); + bits |= SHIFT_L(glyphp[10][line], 26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[10][line], 6); + bits |= SHIFT_L(glyphp[11][line], 3); + bits |= SHIFT_L(glyphp[12][line], 12); + bits |= SHIFT_L(glyphp[13][line], 21); + bits |= SHIFT_L(glyphp[14][line], 30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[14][line], 2); + bits |= SHIFT_L(glyphp[15][line], 7); + bits |= SHIFT_L(glyphp[16][line], 16); + bits |= SHIFT_L(glyphp[17][line], 25); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[17][line], 7); + bits |= SHIFT_L(glyphp[18][line], 2); + bits |= SHIFT_L(glyphp[19][line], 11); + bits |= SHIFT_L(glyphp[20][line], 20); + bits |= SHIFT_L(glyphp[21][line], 29); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[21][line], 3); + bits |= SHIFT_L(glyphp[22][line], 6); + bits |= SHIFT_L(glyphp[23][line], 15); + bits |= SHIFT_L(glyphp[24][line], 24); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); + bits = SHIFT_R(glyphp[24][line], 8); + bits |= SHIFT_L(glyphp[25][line], 1); + bits |= SHIFT_L(glyphp[26][line], 10); + bits |= SHIFT_L(glyphp[27][line], 19); + bits |= SHIFT_L(glyphp[28][line], 28); + WRITE_IN_BITORDER(base, 7, bits); + CHECKRETURN(8); + bits = SHIFT_R(glyphp[28][line], 4); + bits |= SHIFT_L(glyphp[29][line], 5); + bits |= SHIFT_L(glyphp[30][line], 14); + bits |= SHIFT_L(glyphp[31][line], 23); + WRITE_IN_BITORDER(base, 8, bits); + CHECKRETURN(9); +#ifndef FIXEDBASE + base += 9; +#endif + width -= 288; + glyphp += 32; + } + return base; +} +#endif + +static CARD32 * +DrawTETextScanlineWidth10(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 10); + bits |= SHIFT_L(glyphp[2][line], 20); + bits |= SHIFT_L(glyphp[3][line], 30); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[3][line], 2); + bits |= SHIFT_L(glyphp[4][line], 8); + bits |= SHIFT_L(glyphp[5][line], 18); + bits |= SHIFT_L(glyphp[6][line], 28); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[6][line], 4); + bits |= SHIFT_L(glyphp[7][line], 6); + bits |= SHIFT_L(glyphp[8][line], 16); + bits |= SHIFT_L(glyphp[9][line], 26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[9][line], 6); + bits |= SHIFT_L(glyphp[10][line], 4); + bits |= SHIFT_L(glyphp[11][line], 14); + bits |= SHIFT_L(glyphp[12][line], 24); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[12][line], 8); + bits |= SHIFT_L(glyphp[13][line], 2); + bits |= SHIFT_L(glyphp[14][line], 12); + bits |= SHIFT_L(glyphp[15][line], 22); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); +#ifndef FIXEDBASE + base += 5; +#endif + width -= 160; + glyphp += 16; + } + return base; +} + +static CARD32 * +DrawTETextScanlineWidth12(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 12); + bits |= SHIFT_L(glyphp[2][line], 24); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[2][line], 8); + bits |= SHIFT_L(glyphp[3][line], 4); + bits |= SHIFT_L(glyphp[4][line], 16); + bits |= SHIFT_L(glyphp[5][line], 28); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[5][line], 4); + bits |= SHIFT_L(glyphp[6][line], 8); + bits |= SHIFT_L(glyphp[7][line], 20); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); +#ifndef FIXEDBASE + base += 3; +#endif + width -= 96; + glyphp += 8; + } + return base; +} + +static CARD32 * +DrawTETextScanlineWidth14(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 14); + bits |= SHIFT_L(glyphp[2][line], 28); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[2][line], 4); + bits |= SHIFT_L(glyphp[3][line], 10); + bits |= SHIFT_L(glyphp[4][line], 24); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[4][line], 8); + bits |= SHIFT_L(glyphp[5][line], 6); + bits |= SHIFT_L(glyphp[6][line], 20); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[6][line], 12); + bits |= SHIFT_L(glyphp[7][line], 2); + bits |= SHIFT_L(glyphp[8][line], 16); + bits |= SHIFT_L(glyphp[9][line], 30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[9][line], 2); + bits |= SHIFT_L(glyphp[10][line], 12); + bits |= SHIFT_L(glyphp[11][line], 26); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[11][line], 6); + bits |= SHIFT_L(glyphp[12][line], 8); + bits |= SHIFT_L(glyphp[13][line], 22); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[13][line], 10); + bits |= SHIFT_L(glyphp[14][line], 4); + bits |= SHIFT_L(glyphp[15][line], 18); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); +#ifndef FIXEDBASE + base += 7; +#endif + width -= 224; + glyphp += 16; + } + return base; +} + +static CARD32 * +DrawTETextScanlineWidth16(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 16); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = glyphp[2][line]; + bits |= SHIFT_L(glyphp[3][line], 16); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = glyphp[4][line]; + bits |= SHIFT_L(glyphp[5][line], 16); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = glyphp[6][line]; + bits |= SHIFT_L(glyphp[7][line], 16); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); +#ifndef FIXEDBASE + base += 4; +#endif + width -= 128; + glyphp += 8; + } + return base; +} + +static CARD32 * +DrawTETextScanlineWidth18(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 18); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[1][line], 14); + bits |= SHIFT_L(glyphp[2][line], 4); + bits |= SHIFT_L(glyphp[3][line], 22); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[3][line], 10); + bits |= SHIFT_L(glyphp[4][line], 8); + bits |= SHIFT_L(glyphp[5][line], 26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[5][line], 6); + bits |= SHIFT_L(glyphp[6][line], 12); + bits |= SHIFT_L(glyphp[7][line], 30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[7][line], 2); + bits |= SHIFT_L(glyphp[8][line], 16); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[8][line], 16); + bits |= SHIFT_L(glyphp[9][line], 2); + bits |= SHIFT_L(glyphp[10][line], 20); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[10][line], 12); + bits |= SHIFT_L(glyphp[11][line], 6); + bits |= SHIFT_L(glyphp[12][line], 24); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); + bits = SHIFT_R(glyphp[12][line], 8); + bits |= SHIFT_L(glyphp[13][line], 10); + bits |= SHIFT_L(glyphp[14][line], 28); + WRITE_IN_BITORDER(base, 7, bits); + CHECKRETURN(8); + bits = SHIFT_R(glyphp[14][line], 4); + bits |= SHIFT_L(glyphp[15][line], 14); + WRITE_IN_BITORDER(base, 8, bits); + CHECKRETURN(9); +#ifndef FIXEDBASE + base += 9; +#endif + width -= 288; + glyphp += 16; + } + return base; +} + +static CARD32 * +DrawTETextScanlineWidth24(CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth) +{ + while (1) { + unsigned int bits; + + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line], 24); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[1][line], 8); + bits |= SHIFT_L(glyphp[2][line], 16); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[2][line], 16); + bits |= SHIFT_L(glyphp[3][line], 8); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); +#ifndef FIXEDBASE + base += 3; +#endif + width -= 96; + glyphp += 4; + } + return base; +} diff --git a/hw/xfree86/xaa/xaaTEText.c b/hw/xfree86/xaa/xaaTEText.c new file mode 100644 index 000000000..f8d4effc1 --- /dev/null +++ b/hw/xfree86/xaa/xaaTEText.c @@ -0,0 +1,295 @@ + +/******************************************************************** + + In this file we have GC level replacements for PolyText8/16, + ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for TE (fixed) fonts. + The idea is that everything in this file is device independent. + The mentioned GCOps are merely wrappers for XAAGlyphBltTEColorExpansion + which calculates the boxes containing arbitrarily clipped text + and passes them to the TEGlyphRenderer which will usually be a lower + level XAA function which renders these clipped glyphs using + the basic color expansion functions exported by the chipset driver. + The TEGlyphRenderer itself may optionally be driver supplied to + facilitate work-arounds/optimizations at a higher level than usual. + + v1.0 - Mark Vojkovich (mvojkovi@ucsd.edu) + +********************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include "scrnintstr.h" +#include "dixfontstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" + +static void XAAGlyphBltTEColorExpansion(ScrnInfoPtr pScrn, int xInit, + int yInit, FontPtr font, int fg, int bg, + int rop, unsigned int planemask, + RegionPtr cclip, int nglyph, + unsigned char *gBase, + CharInfoPtr * ppci); + +/******************************************************************** + + GC level replacements for PolyText8/16 and ImageText8/16 + for TE fonts when using color expansion. + +********************************************************************/ + +int +XAAPolyText8TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, Linear8Bit, &n, + infoRec->CharInfo); + + /* we have divorced XAAGlyphBltTEColorExpansion from the drawable */ + if (n) + XAAGlyphBltTEColorExpansion(infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, -1, pGC->alu, + pGC->planemask, pGC->pCompositeClip, n, + FONTGLYPHS(pGC->font), infoRec->CharInfo); + + return (x + (n * FONTMAXBOUNDS(pGC->font, characterWidth))); +} + +int +XAAPolyText16TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, + (FONTLASTROW(pGC->font) == + 0) ? Linear16Bit : TwoD16Bit, &n, + infoRec->CharInfo); + + if (n) + XAAGlyphBltTEColorExpansion(infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, -1, pGC->alu, + pGC->planemask, pGC->pCompositeClip, n, + FONTGLYPHS(pGC->font), infoRec->CharInfo); + + return (x + (n * FONTMAXBOUNDS(pGC->font, characterWidth))); +} + +void +XAAImageText8TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, Linear8Bit, &n, + infoRec->CharInfo); + + if (n) + XAAGlyphBltTEColorExpansion(infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, + GXcopy, pGC->planemask, pGC->pCompositeClip, + n, FONTGLYPHS(pGC->font), + infoRec->CharInfo); +} + +void +XAAImageText16TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs) (pGC->font, (unsigned long) count, + (unsigned char *) chars, + (FONTLASTROW(pGC->font) == + 0) ? Linear16Bit : TwoD16Bit, &n, + infoRec->CharInfo); + + if (n) + XAAGlyphBltTEColorExpansion(infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, + GXcopy, pGC->planemask, pGC->pCompositeClip, + n, FONTGLYPHS(pGC->font), + infoRec->CharInfo); +} + +/******************************************************************** + + GC level replacements for ImageGlyphBlt and PolyGlyphBlt for + TE fonts when using color expansion. + +********************************************************************/ + +void +XAAImageGlyphBltTEColorExpansion(DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + XAAGlyphBltTEColorExpansion(infoRec->pScrn, xInit + pDrawable->x, + yInit + pDrawable->y, pGC->font, pGC->fgPixel, + pGC->bgPixel, GXcopy, pGC->planemask, + pGC->pCompositeClip, nglyph, + (unsigned char *) pglyphBase, ppci); +} + +void +XAAPolyGlyphBltTEColorExpansion(DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + XAAGlyphBltTEColorExpansion(infoRec->pScrn, xInit + pDrawable->x, + yInit + pDrawable->y, pGC->font, pGC->fgPixel, + -1, pGC->alu, pGC->planemask, + pGC->pCompositeClip, nglyph, + (unsigned char *) pglyphBase, ppci); +} + +/******************************************************************** + + XAAGlyphBltTEColorExpansion - + + This guy computes the clipped pieces of text and sends it to + the lower-level function which will handle acceleration of + arbitrarily clipped text. + +********************************************************************/ + +static void +XAAGlyphBltTEColorExpansion(ScrnInfoPtr pScrn, + int xInit, int yInit, + FontPtr font, + int fg, int bg, + int rop, + unsigned int planemask, + RegionPtr cclip, + int nglyph, + unsigned char *gBase, CharInfoPtr * ppci) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int skippix, skipglyphs; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge, ytop, ybot; + int nbox = RegionNumRects(cclip); + BoxPtr pbox = RegionRects(cclip); + unsigned int **glyphs = NULL; + int glyphWidth = FONTMAXBOUNDS(font, characterWidth); + + /* find the size of the box */ + Left = xInit; + Right = Left + (glyphWidth * nglyph); + Top = yInit - FONTASCENT(font); + Bottom = yInit + FONTDESCENT(font); + + /* get into the first band that may contain part of our string */ + while (nbox && (Top >= pbox->y2)) { + pbox++; + nbox--; + } + + /* stop when the lower edge of the box is beyond our string */ + while (nbox && (Bottom > pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if (RightEdge > LeftEdge) { /* we have something to draw */ + unsigned int *fallbackBits = NULL; + + ytop = max(Top, pbox->y1); + ybot = min(Bottom, pbox->y2); + + if ((skippix = LeftEdge - Left)) { + skipglyphs = skippix / glyphWidth; + skippix %= glyphWidth; + } + else + skipglyphs = 0; + + if (!glyphs) { + int count; + + glyphs = (unsigned int **) (infoRec->PreAllocMem); + + for (count = 0; count < nglyph; count++) { + glyphs[count] = (unsigned int *) + FONTGLYPHBITS(gBase, *ppci++); + if (!glyphs[count]) { + /* Glyphs with NULL bits do exist in the wild. + Replace with blank bits in that case */ + + if (!fallbackBits) { + int fontHeight = Bottom - Top + 1; + + fallbackBits = calloc(glyphWidth * fontHeight, 1); + if (!fallbackBits) + return; + } + glyphs[count] = fallbackBits; + } + } + + /* our new unrolled TE code only writes DWORDS at a time + so it can read up to 6 characters past the last one + we're displaying */ + glyphs[count + 0] = glyphs[0]; + glyphs[count + 1] = glyphs[0]; + glyphs[count + 2] = glyphs[0]; + glyphs[count + 3] = glyphs[0]; + glyphs[count + 4] = glyphs[0]; + glyphs[count + 5] = glyphs[0]; + } + + /* x, y, w, h, skipleft, skiptop, glyphp, glyphWidth, fg, bg, rop, pm */ + + (*infoRec->TEGlyphRenderer) (pScrn, + LeftEdge, ytop, RightEdge - LeftEdge, + ybot - ytop, skippix, ytop - Top, + glyphs + skipglyphs, glyphWidth, fg, + bg, rop, planemask); + + free(fallbackBits); + } + + nbox--; + pbox++; + } +} diff --git a/hw/xfree86/xaa/xaaTables.c b/hw/xfree86/xaa/xaaTables.c new file mode 100644 index 000000000..35641da59 --- /dev/null +++ b/hw/xfree86/xaa/xaaTables.c @@ -0,0 +1,152 @@ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif +#include "xaalocal.h" +/* + * This is a table of 24-bit values, indexed with an 8-bit byte value, then + * expands each bit to three consecutive bits. This is required for color + * expansion in 24bpp mode with the coprocessor in 8bpp mode, with LSB-first + * bit order within a byte. + */ + +unsigned int byte_expand3[256] = { + 0x000000, 0x000007, 0x000038, 0x00003F, 0x0001C0, 0x0001C7, 0x0001F8, + 0x0001FF, + 0x000E00, 0x000E07, 0x000E38, 0x000E3F, 0x000FC0, 0x000FC7, 0x000FF8, + 0x000FFF, + 0x007000, 0x007007, 0x007038, 0x00703F, 0x0071C0, 0x0071C7, 0x0071F8, + 0x0071FF, + 0x007E00, 0x007E07, 0x007E38, 0x007E3F, 0x007FC0, 0x007FC7, 0x007FF8, + 0x007FFF, + 0x038000, 0x038007, 0x038038, 0x03803F, 0x0381C0, 0x0381C7, 0x0381F8, + 0x0381FF, + 0x038E00, 0x038E07, 0x038E38, 0x038E3F, 0x038FC0, 0x038FC7, 0x038FF8, + 0x038FFF, + 0x03F000, 0x03F007, 0x03F038, 0x03F03F, 0x03F1C0, 0x03F1C7, 0x03F1F8, + 0x03F1FF, + 0x03FE00, 0x03FE07, 0x03FE38, 0x03FE3F, 0x03FFC0, 0x03FFC7, 0x03FFF8, + 0x03FFFF, + 0x1C0000, 0x1C0007, 0x1C0038, 0x1C003F, 0x1C01C0, 0x1C01C7, 0x1C01F8, + 0x1C01FF, + 0x1C0E00, 0x1C0E07, 0x1C0E38, 0x1C0E3F, 0x1C0FC0, 0x1C0FC7, 0x1C0FF8, + 0x1C0FFF, + 0x1C7000, 0x1C7007, 0x1C7038, 0x1C703F, 0x1C71C0, 0x1C71C7, 0x1C71F8, + 0x1C71FF, + 0x1C7E00, 0x1C7E07, 0x1C7E38, 0x1C7E3F, 0x1C7FC0, 0x1C7FC7, 0x1C7FF8, + 0x1C7FFF, + 0x1F8000, 0x1F8007, 0x1F8038, 0x1F803F, 0x1F81C0, 0x1F81C7, 0x1F81F8, + 0x1F81FF, + 0x1F8E00, 0x1F8E07, 0x1F8E38, 0x1F8E3F, 0x1F8FC0, 0x1F8FC7, 0x1F8FF8, + 0x1F8FFF, + 0x1FF000, 0x1FF007, 0x1FF038, 0x1FF03F, 0x1FF1C0, 0x1FF1C7, 0x1FF1F8, + 0x1FF1FF, + 0x1FFE00, 0x1FFE07, 0x1FFE38, 0x1FFE3F, 0x1FFFC0, 0x1FFFC7, 0x1FFFF8, + 0x1FFFFF, + 0xE00000, 0xE00007, 0xE00038, 0xE0003F, 0xE001C0, 0xE001C7, 0xE001F8, + 0xE001FF, + 0xE00E00, 0xE00E07, 0xE00E38, 0xE00E3F, 0xE00FC0, 0xE00FC7, 0xE00FF8, + 0xE00FFF, + 0xE07000, 0xE07007, 0xE07038, 0xE0703F, 0xE071C0, 0xE071C7, 0xE071F8, + 0xE071FF, + 0xE07E00, 0xE07E07, 0xE07E38, 0xE07E3F, 0xE07FC0, 0xE07FC7, 0xE07FF8, + 0xE07FFF, + 0xE38000, 0xE38007, 0xE38038, 0xE3803F, 0xE381C0, 0xE381C7, 0xE381F8, + 0xE381FF, + 0xE38E00, 0xE38E07, 0xE38E38, 0xE38E3F, 0xE38FC0, 0xE38FC7, 0xE38FF8, + 0xE38FFF, + 0xE3F000, 0xE3F007, 0xE3F038, 0xE3F03F, 0xE3F1C0, 0xE3F1C7, 0xE3F1F8, + 0xE3F1FF, + 0xE3FE00, 0xE3FE07, 0xE3FE38, 0xE3FE3F, 0xE3FFC0, 0xE3FFC7, 0xE3FFF8, + 0xE3FFFF, + 0xFC0000, 0xFC0007, 0xFC0038, 0xFC003F, 0xFC01C0, 0xFC01C7, 0xFC01F8, + 0xFC01FF, + 0xFC0E00, 0xFC0E07, 0xFC0E38, 0xFC0E3F, 0xFC0FC0, 0xFC0FC7, 0xFC0FF8, + 0xFC0FFF, + 0xFC7000, 0xFC7007, 0xFC7038, 0xFC703F, 0xFC71C0, 0xFC71C7, 0xFC71F8, + 0xFC71FF, + 0xFC7E00, 0xFC7E07, 0xFC7E38, 0xFC7E3F, 0xFC7FC0, 0xFC7FC7, 0xFC7FF8, + 0xFC7FFF, + 0xFF8000, 0xFF8007, 0xFF8038, 0xFF803F, 0xFF81C0, 0xFF81C7, 0xFF81F8, + 0xFF81FF, + 0xFF8E00, 0xFF8E07, 0xFF8E38, 0xFF8E3F, 0xFF8FC0, 0xFF8FC7, 0xFF8FF8, + 0xFF8FFF, + 0xFFF000, 0xFFF007, 0xFFF038, 0xFFF03F, 0xFFF1C0, 0xFFF1C7, 0xFFF1F8, + 0xFFF1FF, + 0xFFFE00, 0xFFFE07, 0xFFFE38, 0xFFFE3F, 0xFFFFC0, 0xFFFFC7, 0xFFFFF8, + 0xFFFFFF +}; + +/* + * This is a table of 24-bit values, indexed with an 8-bit byte value, + * that reverses the bit order of a byte and then expands each bit to three + * consecutive bits. This is required for color expansion in 24bpp mode + * with the coprocessor in 8bpp mode, with MSB-first bit order within a + * byte. + */ + +unsigned int byte_reversed_expand3[256] = { + 0x000000, 0x0000E0, 0x00001C, 0x0000FC, 0x008003, 0x0080E3, 0x00801F, + 0x0080FF, + 0x007000, 0x0070E0, 0x00701C, 0x0070FC, 0x00F003, 0x00F0E3, 0x00F01F, + 0x00F0FF, + 0x000E00, 0x000EE0, 0x000E1C, 0x000EFC, 0x008E03, 0x008EE3, 0x008E1F, + 0x008EFF, + 0x007E00, 0x007EE0, 0x007E1C, 0x007EFC, 0x00FE03, 0x00FEE3, 0x00FE1F, + 0x00FEFF, + 0xC00100, 0xC001E0, 0xC0011C, 0xC001FC, 0xC08103, 0xC081E3, 0xC0811F, + 0xC081FF, + 0xC07100, 0xC071E0, 0xC0711C, 0xC071FC, 0xC0F103, 0xC0F1E3, 0xC0F11F, + 0xC0F1FF, + 0xC00F00, 0xC00FE0, 0xC00F1C, 0xC00FFC, 0xC08F03, 0xC08FE3, 0xC08F1F, + 0xC08FFF, + 0xC07F00, 0xC07FE0, 0xC07F1C, 0xC07FFC, 0xC0FF03, 0xC0FFE3, 0xC0FF1F, + 0xC0FFFF, + 0x380000, 0x3800E0, 0x38001C, 0x3800FC, 0x388003, 0x3880E3, 0x38801F, + 0x3880FF, + 0x387000, 0x3870E0, 0x38701C, 0x3870FC, 0x38F003, 0x38F0E3, 0x38F01F, + 0x38F0FF, + 0x380E00, 0x380EE0, 0x380E1C, 0x380EFC, 0x388E03, 0x388EE3, 0x388E1F, + 0x388EFF, + 0x387E00, 0x387EE0, 0x387E1C, 0x387EFC, 0x38FE03, 0x38FEE3, 0x38FE1F, + 0x38FEFF, + 0xF80100, 0xF801E0, 0xF8011C, 0xF801FC, 0xF88103, 0xF881E3, 0xF8811F, + 0xF881FF, + 0xF87100, 0xF871E0, 0xF8711C, 0xF871FC, 0xF8F103, 0xF8F1E3, 0xF8F11F, + 0xF8F1FF, + 0xF80F00, 0xF80FE0, 0xF80F1C, 0xF80FFC, 0xF88F03, 0xF88FE3, 0xF88F1F, + 0xF88FFF, + 0xF87F00, 0xF87FE0, 0xF87F1C, 0xF87FFC, 0xF8FF03, 0xF8FFE3, 0xF8FF1F, + 0xF8FFFF, + 0x070000, 0x0700E0, 0x07001C, 0x0700FC, 0x078003, 0x0780E3, 0x07801F, + 0x0780FF, + 0x077000, 0x0770E0, 0x07701C, 0x0770FC, 0x07F003, 0x07F0E3, 0x07F01F, + 0x07F0FF, + 0x070E00, 0x070EE0, 0x070E1C, 0x070EFC, 0x078E03, 0x078EE3, 0x078E1F, + 0x078EFF, + 0x077E00, 0x077EE0, 0x077E1C, 0x077EFC, 0x07FE03, 0x07FEE3, 0x07FE1F, + 0x07FEFF, + 0xC70100, 0xC701E0, 0xC7011C, 0xC701FC, 0xC78103, 0xC781E3, 0xC7811F, + 0xC781FF, + 0xC77100, 0xC771E0, 0xC7711C, 0xC771FC, 0xC7F103, 0xC7F1E3, 0xC7F11F, + 0xC7F1FF, + 0xC70F00, 0xC70FE0, 0xC70F1C, 0xC70FFC, 0xC78F03, 0xC78FE3, 0xC78F1F, + 0xC78FFF, + 0xC77F00, 0xC77FE0, 0xC77F1C, 0xC77FFC, 0xC7FF03, 0xC7FFE3, 0xC7FF1F, + 0xC7FFFF, + 0x3F0000, 0x3F00E0, 0x3F001C, 0x3F00FC, 0x3F8003, 0x3F80E3, 0x3F801F, + 0x3F80FF, + 0x3F7000, 0x3F70E0, 0x3F701C, 0x3F70FC, 0x3FF003, 0x3FF0E3, 0x3FF01F, + 0x3FF0FF, + 0x3F0E00, 0x3F0EE0, 0x3F0E1C, 0x3F0EFC, 0x3F8E03, 0x3F8EE3, 0x3F8E1F, + 0x3F8EFF, + 0x3F7E00, 0x3F7EE0, 0x3F7E1C, 0x3F7EFC, 0x3FFE03, 0x3FFEE3, 0x3FFE1F, + 0x3FFEFF, + 0xFF0100, 0xFF01E0, 0xFF011C, 0xFF01FC, 0xFF8103, 0xFF81E3, 0xFF811F, + 0xFF81FF, + 0xFF7100, 0xFF71E0, 0xFF711C, 0xFF71FC, 0xFFF103, 0xFFF1E3, 0xFFF11F, + 0xFFF1FF, + 0xFF0F00, 0xFF0FE0, 0xFF0F1C, 0xFF0FFC, 0xFF8F03, 0xFF8FE3, 0xFF8F1F, + 0xFF8FFF, + 0xFF7F00, 0xFF7FE0, 0xFF7F1C, 0xFF7FFC, 0xFFFF03, 0xFFFFE3, 0xFFFF1F, + 0xFFFFFF, +}; diff --git a/hw/xfree86/xaa/xaaWideLine.c b/hw/xfree86/xaa/xaaWideLine.c new file mode 100644 index 000000000..b8a53c1c8 --- /dev/null +++ b/hw/xfree86/xaa/xaaWideLine.c @@ -0,0 +1,924 @@ +/* + +XAAPolylinesWideSolid does not maintain a span list and subsequently does +not follow the "touch-each-pixel-once" rules for wide lines and arcs. +This means it can only be used in the case where we have +miSpansEasyRop(pGC->alu). Since we clip spans on the fly, we +limited usage of this function to one rect situations. This +function is used only for solid lines. + + Adapted from miWideLine by Mark Vojkovich (mvojkovi@ucsd.edu) +Original mi code written by Keith Packard. + +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "windowstr.h" +#include "gcstruct.h" +#include "regionstr.h" +#include "miwideline.h" +#include "mi.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +#define DRAW_POINT(pScrn, x, y) \ + if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, 1); \ + else XAAPointHelper(pScrn, x, y) + +#define FILL_RECT(pScrn, x, y, w, h) \ + if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); \ + else XAAFillRectHelper(pScrn, x, y, w, h) + +#define FILL_SPAN(pScrn, x, y, w) \ + if(hardClip) (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, 1); \ + else XAASpanHelper(pScrn, x, y, w) + +#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ + if (ybase == edgey) { \ + if (edgeleft) { \ + if (edge->x > xcl) \ + xcl = edge->x; \ + } else { \ + if (edge->x < xcr) \ + xcr = edge->x; \ + } \ + edgey++; \ + edge->x += edge->stepx; \ + edge->e += edge->dx; \ + if (edge->e > 0) { \ + edge->x += edge->signdx; \ + edge->e -= edge->dy; \ + } \ + } + +static void +XAAPointHelper(ScrnInfoPtr pScrn, int x, int y) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + BoxPtr extents = infoRec->ClipBox; + + if ((x >= extents->x1) && (x < extents->x2) && + (y >= extents->y1) && (y < extents->y2)) + (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, 1, 1); +} + +static void +XAAFillRectHelper(ScrnInfoPtr pScrn, int x1, int y1, int dx, int dy) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + BoxPtr extents = infoRec->ClipBox; + int x2 = x1 + dx; + int y2 = y1 + dy; + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 >= extents->x2) + x2 = extents->x2; + if ((dx = x2 - x1) < 1) + return; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 >= extents->y2) + y2 = extents->y2; + if ((dy = y2 - y1) < 1) + return; + + (*infoRec->SubsequentSolidFillRect) (pScrn, x1, y1, dx, dy); +} + +static void +XAASpanHelper(ScrnInfoPtr pScrn, int x1, int y, int width) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + BoxPtr extents = infoRec->ClipBox; + int x2; + + if ((y < extents->y1) || (y >= extents->y2)) + return; + + x2 = x1 + width; + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + width = x2 - x1; + + if (width > 0) + (*infoRec->SubsequentSolidFillRect) (pScrn, x1, y, width, 1); + +} + +#define FixError(x, dx, dy, e, sign, step, h) { \ + e += (h) * dx; \ + x += (h) * step; \ + if(e > 0) { \ + x += e * sign/dy; \ + e %= dy; \ + if(e) { \ + x += sign; \ + e -= dy; \ + } \ + } \ +} + +static void +XAAFillPolyHelper(GCPtr pGC, int y, /* start y coordinate */ + int overall_height, /* height of entire segment */ + PolyEdgePtr left, PolyEdgePtr right, + int left_count, int right_count) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + BoxPtr extents = infoRec->ClipBox; + int left_x, left_e, left_stepx, left_signdx, left_dy, left_dx; + int right_x, right_e, right_stepx, right_signdx, right_dy, right_dx; + int height, left_height, right_height; + int xorg; + Bool hardClip; + + if ((y >= extents->y2) || ((y + overall_height) <= extents->y1)) + return; + + /* Muffle compiler */ + left_x = left_e = left_stepx = left_signdx = left_dy = left_dx = 0; + right_x = right_e = right_stepx = right_signdx = right_dy = right_dx = 0; + + left_height = right_height = 0; + xorg = 0; + + hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); + + while ((left_count || left_height) && (right_count || right_height)) { + if (!left_height && left_count) { + left_height = left->height; + left_x = left->x + xorg; + left_stepx = left->stepx; + left_signdx = left->signdx; + left_e = left->e; + left_dy = left->dy; + left_dx = left->dx; + left_count--; + left++; + } + if (!right_height && right_count) { + right_height = right->height; + right_x = right->x + xorg + 1; + right_stepx = right->stepx; + right_signdx = right->signdx; + right_e = right->e; + right_dy = right->dy; + right_dx = right->dx; + right_count--; + right++; + } + + height = (left_height > right_height) ? right_height : left_height; + + left_height -= height; + right_height -= height; + + if (hardClip && infoRec->SubsequentSolidFillTrap && (height > 6)) { + int right_DX, left_DX; + + right_DX = (right_dx * right_signdx) + (right_stepx * right_dy); + left_DX = (left_dx * left_signdx) + (left_stepx * left_dy); + + (*infoRec->SubsequentSolidFillTrap) (infoRec->pScrn, y, height, + left_x, left_DX, left_dy, + left_e, right_x - 1, right_DX, + right_dy, right_e); + + FixError(left_x, left_dx, left_dy, left_e, left_signdx, + left_stepx, height); + FixError(right_x, right_dx, right_dy, right_e, right_signdx, + right_stepx, height); + y += height; + continue; + } + + while (height--) { + if (right_x > left_x) { + FILL_SPAN(infoRec->pScrn, left_x, y, right_x - left_x); + } + y++; + + left_x += left_stepx; + left_e += left_dx; + if (left_e > 0) { + left_x += left_signdx; + left_e -= left_dy; + } + right_x += right_stepx; + right_e += right_dx; + if (right_e > 0) { + right_x += right_signdx; + right_e -= right_dy; + } + + } + } +} + +static void +XAAWideSegment(GCPtr pGC, + int x1, int y1, int x2, int y2, + Bool projectLeft, Bool projectRight, + LineFacePtr leftFace, LineFacePtr rightFace) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + double l, L, r; + double xa, ya; + double projectXoff, projectYoff; + double k; + double maxy; + int x, y; + int dx, dy; + int finaly; + PolyEdgePtr left, right; + PolyEdgePtr top, bottom; + int lefty, righty, topy, bottomy; + int signdx; + PolyEdgeRec lefts[2], rights[2]; + LineFacePtr tface; + int lw = pGC->lineWidth; + Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); + + /* draw top-to-bottom always */ + if ((y2 < y1) || ((y2 == y1) && (x2 < x1))) { + x = x1; + x1 = x2; + x2 = x; + + y = y1; + y1 = y2; + y2 = y; + + x = projectLeft; + projectLeft = projectRight; + projectRight = x; + + tface = leftFace; + leftFace = rightFace; + rightFace = tface; + } + + dy = y2 - y1; + signdx = 1; + dx = x2 - x1; + if (dx < 0) + signdx = -1; + + leftFace->x = x1; + leftFace->y = y1; + leftFace->dx = dx; + leftFace->dy = dy; + + rightFace->x = x2; + rightFace->y = y2; + rightFace->dx = -dx; + rightFace->dy = -dy; + + if (!dy) { + rightFace->xa = 0; + rightFace->ya = (double) lw / 2.0; + rightFace->k = -(double) (lw * dx) / 2.0; + leftFace->xa = 0; + leftFace->ya = -rightFace->ya; + leftFace->k = rightFace->k; + x = x1; + if (projectLeft) + x -= (lw >> 1); + y = y1 - (lw >> 1); + dx = x2 - x; + if (projectRight) + dx += ((lw + 1) >> 1); + dy = lw; + FILL_RECT(infoRec->pScrn, x, y, dx, dy); + } + else if (!dx) { + leftFace->xa = (double) lw / 2.0; + leftFace->ya = 0; + leftFace->k = (double) (lw * dy) / 2.0; + rightFace->xa = -leftFace->xa; + rightFace->ya = 0; + rightFace->k = leftFace->k; + y = y1; + if (projectLeft) + y -= lw >> 1; + x = x1 - (lw >> 1); + dy = y2 - y; + if (projectRight) + dy += ((lw + 1) >> 1); + dx = lw; + FILL_RECT(infoRec->pScrn, x, y, dx, dy); + } + else { + l = ((double) lw) / 2.0; + L = sqrt((double) (dx * dx + dy * dy)); + + if (dx < 0) { + right = &rights[1]; + left = &lefts[0]; + top = &rights[0]; + bottom = &lefts[1]; + } + else { + right = &rights[0]; + left = &lefts[1]; + top = &lefts[0]; + bottom = &rights[1]; + } + r = l / L; + + /* coord of upper bound at integral y */ + ya = -r * dx; + xa = r * dy; + + projectXoff = -ya; + projectYoff = xa; + + /* xa * dy - ya * dx */ + k = l * L; + + leftFace->xa = xa; + leftFace->ya = ya; + leftFace->k = k; + rightFace->xa = -xa; + rightFace->ya = -ya; + rightFace->k = k; + + if (projectLeft) + righty = miPolyBuildEdge(xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 0, right); + else + righty = miPolyBuildEdge(xa, ya, k, dx, dy, x1, y1, 0, right); + + /* coord of lower bound at integral y */ + ya = -ya; + xa = -xa; + + /* xa * dy - ya * dx */ + k = -k; + + if (projectLeft) + lefty = miPolyBuildEdge(xa - projectXoff, ya - projectYoff, + k, dx, dy, x1, y1, 1, left); + else + lefty = miPolyBuildEdge(xa, ya, k, dx, dy, x1, y1, 1, left); + + /* coord of top face at integral y */ + + if (signdx > 0) { + ya = -ya; + xa = -xa; + } + + if (projectLeft) { + double xap = xa - projectXoff; + double yap = ya - projectYoff; + + topy = miPolyBuildEdge(xap, yap, xap * dx + yap * dy, + -dy, dx, x1, y1, dx > 0, top); + } + else + topy = miPolyBuildEdge(xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); + + /* coord of bottom face at integral y */ + + if (projectRight) { + double xap = xa + projectXoff; + double yap = ya + projectYoff; + + bottomy = miPolyBuildEdge(xap, yap, xap * dx + yap * dy, + -dy, dx, x2, y2, dx < 0, bottom); + maxy = -ya + projectYoff; + } + else { + bottomy = miPolyBuildEdge(xa, ya, 0.0, + -dy, dx, x2, y2, dx < 0, bottom); + maxy = -ya; + } + + finaly = ICEIL(maxy) + y2; + + if (dx < 0) { + left->height = bottomy - lefty; + right->height = finaly - righty; + top->height = righty - topy; + } + else { + right->height = bottomy - righty; + left->height = finaly - lefty; + top->height = lefty - topy; + } + bottom->height = finaly - bottomy; + XAAFillPolyHelper(pGC, topy, + bottom->height + bottomy - topy, lefts, rights, 2, 2); + } +} + +static void +XAALineArcI(GCPtr pGC, int xorg, int yorg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int x, y, e, ex; + int slw = pGC->lineWidth; + Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); + + y = (slw >> 1) + 1; + if (slw & 1) + e = -((y << 2) + 3); + else + e = -(y << 3); + ex = -4; + x = 0; + while (y) { + e += (y << 3) - 4; + while (e >= 0) { + x++; + e += (ex = -((x << 3) + 4)); + } + y--; + slw = (x << 1) + 1; + if ((e == ex) && (slw > 1)) + slw--; + + FILL_SPAN(infoRec->pScrn, xorg - x, yorg - y, slw); + + if ((y != 0) && ((slw > 1) || (e != ex))) { + FILL_SPAN(infoRec->pScrn, xorg - x, yorg + y, slw); + } + } +} + +static void +XAALineArcD(GCPtr pGC, + double xorg, + double yorg, + PolyEdgePtr edge1, + int edgey1, + Bool edgeleft1, PolyEdgePtr edge2, int edgey2, Bool edgeleft2) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + double radius, x0, y0, el, er, yk, xlk, xrk, k; + int xbase, ybase, y, boty, xl, xr, xcl, xcr; + int ymin, ymax; + Bool edge1IsMin, edge2IsMin; + int ymin1, ymin2; + Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); + + xbase = floor(xorg); + x0 = xorg - xbase; + ybase = ICEIL(yorg); + y0 = yorg - ybase; + + xlk = x0 + x0 + 1.0; + xrk = x0 + x0 - 1.0; + yk = y0 + y0 - 1.0; + radius = ((double) pGC->lineWidth) / 2.0; + y = floor(radius - y0 + 1.0); + ybase -= y; + ymin = ybase; + ymax = 65536; + edge1IsMin = FALSE; + ymin1 = edgey1; + if (edge1->dy >= 0) { + if (!edge1->dy) { + if (edgeleft1) + edge1IsMin = TRUE; + else + ymax = edgey1; + edgey1 = 65536; + } + else if ((edge1->signdx < 0) == edgeleft1) + edge1IsMin = TRUE; + } + edge2IsMin = FALSE; + ymin2 = edgey2; + if (edge2->dy >= 0) { + if (!edge2->dy) { + if (edgeleft2) + edge2IsMin = TRUE; + else + ymax = edgey2; + edgey2 = 65536; + } + else if ((edge2->signdx < 0) == edgeleft2) + edge2IsMin = TRUE; + } + if (edge1IsMin) { + ymin = ymin1; + if (edge2IsMin && (ymin1 > ymin2)) + ymin = ymin2; + } + else if (edge2IsMin) + ymin = ymin2; + el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); + er = el + xrk; + xl = 1; + xr = 0; + if (x0 < 0.5) { + xl = 0; + el -= xlk; + } + boty = (y0 < -0.5) ? 1 : 0; + if (ybase + y - boty > ymax) + boty = ymax - ybase - y; + while (y > boty) { + k = (y << 1) + yk; + er += k; + while (er > 0.0) { + xr++; + er += xrk - (xr << 1); + } + el += k; + while (el >= 0.0) { + xl--; + el += (xl << 1) - xlk; + } + y--; + ybase++; + if (ybase < ymin) + continue; + xcl = xl + xbase; + xcr = xr + xbase; + CLIPSTEPEDGE(edgey1, edge1, edgeleft1); + CLIPSTEPEDGE(edgey2, edge2, edgeleft2); + if (xcr >= xcl) { + FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1); + } + } + er = xrk - (xr << 1) - er; + el = (xl << 1) - xlk - el; + boty = floor(-y0 - radius + 1.0); + if (ybase + y - boty > ymax) + boty = ymax - ybase - y; + while (y > boty) { + k = (y << 1) + yk; + er -= k; + while ((er >= 0.0) && (xr >= 0)) { + xr--; + er += xrk - (xr << 1); + } + el -= k; + while ((el > 0.0) && (xl <= 0)) { + xl++; + el += (xl << 1) - xlk; + } + y--; + ybase++; + if (ybase < ymin) + continue; + xcl = xl + xbase; + xcr = xr + xbase; + CLIPSTEPEDGE(edgey1, edge1, edgeleft1); + CLIPSTEPEDGE(edgey2, edge2, edgeleft2); + if (xcr >= xcl) { + FILL_SPAN(infoRec->pScrn, xcl, ybase, xcr - xcl + 1); + } + } +} + +static void +XAALineArc(GCPtr pGC, + LineFacePtr leftFace, + LineFacePtr rightFace, double xorg, double yorg, Bool isInt) +{ + int xorgi, yorgi; + PolyEdgeRec edge1, edge2; + int edgey1, edgey2; + Bool edgeleft1, edgeleft2; + + if (isInt) { + xorgi = leftFace ? leftFace->x : rightFace->x; + yorgi = leftFace ? leftFace->y : rightFace->y; + } + else { /* Muffle compiler */ + xorgi = yorgi = 0; + } + edgey1 = 65536; + edgey2 = 65536; + edge1.x = 0; /* not used, keep memory checkers happy */ + edge1.dy = -1; + edge2.x = 0; /* not used, keep memory checkers happy */ + edge2.dy = -1; + edgeleft1 = FALSE; + edgeleft2 = FALSE; + + if ((pGC->lineWidth > 2) && + ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || + (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) { + if (isInt) { + xorg = (double) xorgi; + yorg = (double) yorgi; + } + + if (leftFace && rightFace) + miRoundJoinClip(leftFace, rightFace, &edge1, &edge2, + &edgey1, &edgey2, &edgeleft1, &edgeleft2); + else if (leftFace) + edgey1 = miRoundCapClip(leftFace, isInt, &edge1, &edgeleft1); + else if (rightFace) + edgey2 = miRoundCapClip(rightFace, isInt, &edge2, &edgeleft2); + + isInt = FALSE; + } + + if (isInt) { + if (pGC->lineWidth == 1) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); + + DRAW_POINT(infoRec->pScrn, xorgi, yorgi); + } + else + XAALineArcI(pGC, xorgi, yorgi); + } + else + XAALineArcD(pGC, xorg, yorg, &edge1, edgey1, edgeleft1, + &edge2, edgey2, edgeleft2); + +} + +static void +XAALineJoin(GCPtr pGC, LineFacePtr pLeft, LineFacePtr pRight) +{ + double mx = 0, my = 0; + double denom = 0; + PolyVertexRec vertices[4]; + PolySlopeRec slopes[4]; + int edgecount; + PolyEdgeRec left[4], right[4]; + int nleft, nright; + int y, height; + int swapslopes; + int joinStyle = pGC->joinStyle; + int lw = pGC->lineWidth; + + if (lw == 1) { + /* Lines going in the same direction have no join */ + if ((pLeft->dx >= 0) == (pRight->dx <= 0)) + return; + if (joinStyle != JoinRound) { + denom = -pLeft->dx * (double) pRight->dy + pRight->dx * + (double) pLeft->dy; + if (denom == 0.0) + return; /* no join to draw */ + } + if (joinStyle != JoinMiter) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + Bool hardClip = (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL); + + DRAW_POINT(infoRec->pScrn, pLeft->x, pLeft->y); + return; + } + } + else { + if (joinStyle == JoinRound) { + XAALineArc(pGC, pLeft, pRight, (double) 0.0, (double) 0.0, TRUE); + return; + } + denom = -pLeft->dx * (double) pRight->dy + pRight->dx * + (double) pLeft->dy; + if (denom == 0.0) + return; /* no join to draw */ + } + + swapslopes = 0; + if (denom > 0) { + pLeft->xa = -pLeft->xa; + pLeft->ya = -pLeft->ya; + pLeft->dx = -pLeft->dx; + pLeft->dy = -pLeft->dy; + } + else { + swapslopes = 1; + pRight->xa = -pRight->xa; + pRight->ya = -pRight->ya; + pRight->dx = -pRight->dx; + pRight->dy = -pRight->dy; + } + + vertices[0].x = pRight->xa; + vertices[0].y = pRight->ya; + slopes[0].dx = -pRight->dy; + slopes[0].dy = pRight->dx; + slopes[0].k = 0; + + vertices[1].x = 0; + vertices[1].y = 0; + slopes[1].dx = pLeft->dy; + slopes[1].dy = -pLeft->dx; + slopes[1].k = 0; + + vertices[2].x = pLeft->xa; + vertices[2].y = pLeft->ya; + + if (joinStyle == JoinMiter) { + my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - + pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx)) / + denom; + if (pLeft->dy != 0) + mx = pLeft->xa + (my - pLeft->ya) * + (double) pLeft->dx / (double) pLeft->dy; + else + mx = pRight->xa + (my - pRight->ya) * + (double) pRight->dx / (double) pRight->dy; + + /* check miter limit */ + if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) + joinStyle = JoinBevel; + } + + if (joinStyle == JoinMiter) { + slopes[2].dx = pLeft->dx; + slopes[2].dy = pLeft->dy; + slopes[2].k = pLeft->k; + if (swapslopes) { + slopes[2].dx = -slopes[2].dx; + slopes[2].dy = -slopes[2].dy; + slopes[2].k = -slopes[2].k; + } + vertices[3].x = mx; + vertices[3].y = my; + slopes[3].dx = pRight->dx; + slopes[3].dy = pRight->dy; + slopes[3].k = pRight->k; + if (swapslopes) { + slopes[3].dx = -slopes[3].dx; + slopes[3].dy = -slopes[3].dy; + slopes[3].k = -slopes[3].k; + } + edgecount = 4; + } + else { + double scale, dx, dy, adx, ady; + + adx = dx = pRight->xa - pLeft->xa; + ady = dy = pRight->ya - pLeft->ya; + if (adx < 0) + adx = -adx; + if (ady < 0) + ady = -ady; + scale = ady; + if (adx > ady) + scale = adx; + slopes[2].dx = (dx * 65536) / scale; + slopes[2].dy = (dy * 65536) / scale; + slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - + (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; + edgecount = 3; + } + + y = miPolyBuildPoly(vertices, slopes, edgecount, pLeft->x, pLeft->y, + left, right, &nleft, &nright, &height); + XAAFillPolyHelper(pGC, y, height, left, right, nleft, nright); +} + +void +XAAPolylinesWideSolid(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int x1, y1, x2, y2; + Bool projectLeft, projectRight; + LineFaceRec leftFace, rightFace, prevRightFace, firstFace; + int first = TRUE; + Bool somethingDrawn = FALSE; + Bool selfJoin = FALSE; + int xorg = pDrawable->x; + int yorg = pDrawable->y; + Bool hardClip = FALSE; + + if (!RegionNumRects(pGC->pCompositeClip)) + return; + + if (RegionNumRects(pGC->pCompositeClip) != 1) { + miWideLine(pDrawable, pGC, mode, npt, pPts); + return; + } + + x2 = pPts->x; + y2 = pPts->y; + if (npt > 1) { + if (mode == CoordModePrevious) { + int nptTmp; + register DDXPointPtr pPtsTmp; + + x1 = x2; + y1 = y2; + nptTmp = npt; + pPtsTmp = pPts + 1; + while (--nptTmp) { + x1 += pPtsTmp->x; + y1 += pPtsTmp->y; + ++pPtsTmp; + } + if ((x2 == x1) && (y2 == y1)) + selfJoin = TRUE; + } + else if ((x2 == pPts[npt - 1].x) && (y2 == pPts[npt - 1].y)) + selfJoin = TRUE; + } + + projectLeft = ((pGC->capStyle == CapProjecting) && !selfJoin); + projectRight = FALSE; + + (*infoRec->SetupForSolidFill) (infoRec->pScrn, pGC->fgPixel, pGC->alu, + pGC->planemask); + + infoRec->ClipBox = &pGC->pCompositeClip->extents; + + if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_FILL) { + hardClip = TRUE; + (*infoRec->SetClippingRectangle) (infoRec->pScrn, + infoRec->ClipBox->x1, + infoRec->ClipBox->y1, + infoRec->ClipBox->x2 - 1, + infoRec->ClipBox->y2 - 1); + } + + x2 += xorg; + y2 += yorg; + while (--npt) { + x1 = x2; + y1 = y2; + ++pPts; + x2 = pPts->x; + y2 = pPts->y; + if (mode == CoordModePrevious) { + x2 += x1; + y2 += y1; + } + else { + x2 += xorg; + y2 += yorg; + } + if ((x1 != x2) || (y1 != y2)) { + somethingDrawn = TRUE; + if ((npt == 1) && (pGC->capStyle == CapProjecting) && !selfJoin) + projectRight = TRUE; + XAAWideSegment(pGC, x1, y1, x2, y2, + projectLeft, projectRight, &leftFace, &rightFace); + if (first) { + if (selfJoin) + firstFace = leftFace; + else if (pGC->capStyle == CapRound) { + if (pGC->lineWidth == 1) { + DRAW_POINT(infoRec->pScrn, x1, y1); + } + else + XAALineArc(pGC, &leftFace, (LineFacePtr) NULL, + (double) 0.0, (double) 0.0, TRUE); + } + } + else + XAALineJoin(pGC, &leftFace, &prevRightFace); + + prevRightFace = rightFace; + first = FALSE; + projectLeft = FALSE; + } + if (npt == 1 && somethingDrawn) { + if (selfJoin) + XAALineJoin(pGC, &firstFace, &rightFace); + else if (pGC->capStyle == CapRound) { + if (pGC->lineWidth == 1) { + DRAW_POINT(infoRec->pScrn, x2, y2); + } + else + XAALineArc(pGC, (LineFacePtr) NULL, &rightFace, + (double) 0.0, (double) 0.0, TRUE); + } + } + } + /* handle crock where all points are coincedent */ + if (!somethingDrawn) { + projectLeft = (pGC->capStyle == CapProjecting); + XAAWideSegment(pGC, x2, y2, x2, y2, projectLeft, projectLeft, + &leftFace, &rightFace); + if (pGC->capStyle == CapRound) { + XAALineArc(pGC, &leftFace, (LineFacePtr) NULL, + (double) 0.0, (double) 0.0, TRUE); + rightFace.dx = -1; /* sleezy hack to make it work */ + XAALineArc(pGC, (LineFacePtr) NULL, &rightFace, + (double) 0.0, (double) 0.0, TRUE); + } + } + + infoRec->ClipBox = NULL; + if (hardClip) + (*infoRec->DisableClipping) (infoRec->pScrn); + + SET_SYNC_FLAG(infoRec); +} diff --git a/hw/xfree86/xaa/xaacexp.h b/hw/xfree86/xaa/xaacexp.h new file mode 100644 index 000000000..6fde54c65 --- /dev/null +++ b/hw/xfree86/xaa/xaacexp.h @@ -0,0 +1,126 @@ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#ifndef FIXEDBASE +#define CHECKRETURN(b) if(width <= ((b) * 32)) return(base + (b)) +#else +#define CHECKRETURN(b) if(width <= ((b) * 32)) return(base) +#endif + +#if X_BYTE_ORDER == X_BIG_ENDIAN +#define SHIFT_L(value, shift) ((value) >> (shift)) +#define SHIFT_R(value, shift) ((value) << (shift)) +#else +#define SHIFT_L(value, shift) ((value) << (shift)) +#define SHIFT_R(value, shift) ((value) >> (shift)) +#endif + +#ifndef MSBFIRST +#ifdef FIXEDBASE +#define WRITE_IN_BITORDER(dest, offset, data) *(dest) = data; +#else +#define WRITE_IN_BITORDER(dest, offset, data) *(dest + offset) = data; +#endif +#else +#ifdef FIXEDBASE +#define WRITE_IN_BITORDER(dest, offset, data) *(dest) = SWAP_BITS_IN_BYTES(data); +#else +#define WRITE_IN_BITORDER(dest, offset, data) *(dest + offset) = SWAP_BITS_IN_BYTES(data) +#endif +#endif + +#ifdef FIXEDBASE +#ifdef MSBFIRST +#define WRITE_BITS(b) *base = SWAP_BITS_IN_BYTES(b) +#define WRITE_BITS1(b) { \ + *base = byte_reversed_expand3[(b) & 0xFF] | \ + byte_reversed_expand3[((b) & 0xFF00) >> 8] << 24; } +#define WRITE_BITS2(b) { \ + *base = byte_reversed_expand3[(b) & 0xFF] | \ + byte_reversed_expand3[((b) & 0xFF00) >> 8] << 24; \ + *base = byte_reversed_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_reversed_expand3[((b) & 0xFF0000) >> 16] << 16; } +#define WRITE_BITS3(b) { \ + *base = byte_reversed_expand3[(b) & 0xFF] | \ + byte_reversed_expand3[((b) & 0xFF00) >> 8] << 24; \ + *base = byte_reversed_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_reversed_expand3[((b) & 0xFF0000) >> 16] << 16; \ + *base = byte_reversed_expand3[((b) & 0xFF0000) >> 16] >> 16 | \ + byte_reversed_expand3[((b) & 0xFF000000) >> 24] << 8; } +#else +#define WRITE_BITS(b) *base = (b) +#define WRITE_BITS1(b) { \ + *base = byte_expand3[(b) & 0xFF] | \ + byte_expand3[((b) & 0xFF00) >> 8] << 24; } +#define WRITE_BITS2(b) { \ + *base = byte_expand3[(b) & 0xFF] | \ + byte_expand3[((b) & 0xFF00) >> 8] << 24; \ + *base = byte_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_expand3[((b) & 0xFF0000) >> 16] << 16; } +#define WRITE_BITS3(b) { \ + *base = byte_expand3[(b) & 0xFF] | \ + byte_expand3[((b) & 0xFF00) >> 8] << 24; \ + *base = byte_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_expand3[((b) & 0xFF0000) >> 16] << 16; \ + *base = byte_expand3[((b) & 0xFF0000) >> 16] >> 16 | \ + byte_expand3[((b) & 0xFF000000) >> 24] << 8; } +#endif +#else +#ifdef MSBFIRST +#define WRITE_BITS(b) *(base++) = SWAP_BITS_IN_BYTES(b) +#define WRITE_BITS1(b) { \ + *(base++) = byte_reversed_expand3[(b) & 0xFF] | \ + byte_reversed_expand3[((b) & 0xFF00) >> 8] << 24; } +#define WRITE_BITS2(b) { \ + *(base) = byte_reversed_expand3[(b) & 0xFF] | \ + byte_reversed_expand3[((b) & 0xFF00) >> 8] << 24; \ + *(base + 1) = byte_reversed_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_reversed_expand3[((b) & 0xFF0000) >> 16] << 16; \ + base += 2; } +#define WRITE_BITS3(b) { \ + *(base) = byte_reversed_expand3[(b) & 0xFF] | \ + byte_reversed_expand3[((b) & 0xFF00) >> 8] << 24; \ + *(base + 1) = byte_reversed_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_reversed_expand3[((b) & 0xFF0000) >> 16] << 16; \ + *(base + 2) = byte_reversed_expand3[((b) & 0xFF0000) >> 16] >> 16 | \ + byte_reversed_expand3[((b) & 0xFF000000) >> 24] << 8; \ + base += 3; } +#else +#define WRITE_BITS(b) *(base++) = (b) +#define WRITE_BITS1(b) { \ + *(base++) = byte_expand3[(b) & 0xFF] | \ + byte_expand3[((b) & 0xFF00) >> 8] << 24; } +#define WRITE_BITS2(b) { \ + *(base) = byte_expand3[(b) & 0xFF] | \ + byte_expand3[((b) & 0xFF00) >> 8] << 24; \ + *(base + 1) = byte_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_expand3[((b) & 0xFF0000) >> 16] << 16; \ + base += 2; } +#define WRITE_BITS3(b) { \ + *(base) = byte_expand3[(b) & 0xFF] | \ + byte_expand3[((b) & 0xFF00) >> 8] << 24; \ + *(base + 1) = byte_expand3[((b) & 0xFF00) >> 8] >> 8 | \ + byte_expand3[((b) & 0xFF0000) >> 16] << 16; \ + *(base + 2) = byte_expand3[((b) & 0xFF0000) >> 16] >> 16 | \ + byte_expand3[((b) & 0xFF000000) >> 24] << 8; \ + base += 3; } +#endif +#endif + +#ifdef FIXEDBASE +#ifdef MSBFIRST +#define EXPNAME(x) x##MSBFirstFixedBase +#else +#define EXPNAME(x) x##LSBFirstFixedBase +#endif +#else +#ifdef MSBFIRST +#define EXPNAME(x) x##MSBFirst +#else +#define EXPNAME(x) x##LSBFirst +#endif +#endif diff --git a/hw/xfree86/xaa/xaalocal.h b/hw/xfree86/xaa/xaalocal.h new file mode 100644 index 000000000..0817f5354 --- /dev/null +++ b/hw/xfree86/xaa/xaalocal.h @@ -0,0 +1,1437 @@ + +#ifndef _XAALOCAL_H +#define _XAALOCAL_H + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +/* This file is very unorganized ! */ + +#include "gcstruct.h" +#include "regionstr.h" +#include "xf86fbman.h" +#include "xaa.h" +#include "mi.h" +#include "picturestr.h" + +#define GCWhenForced (GCArcMode << 1) + +#define DO_COLOR_8x8 0x00000001 +#define DO_MONO_8x8 0x00000002 +#define DO_CACHE_BLT 0x00000003 +#define DO_COLOR_EXPAND 0x00000004 +#define DO_CACHE_EXPAND 0x00000005 +#define DO_IMAGE_WRITE 0x00000006 +#define DO_PIXMAP_COPY 0x00000007 +#define DO_SOLID 0x00000008 + +typedef CARD32 *(*GlyphScanlineFuncPtr) (CARD32 *base, unsigned int **glyphp, + int line, int nglyph, int width); + +typedef CARD32 *(*StippleScanlineProcPtr) (CARD32 *, CARD32 *, int, int, int); + +typedef void (*RectFuncPtr) (ScrnInfoPtr, int, int, int, int, int, int, + XAACacheInfoPtr); +typedef void (*TrapFuncPtr) (ScrnInfoPtr, int, int, int, int, int, int, + int, int, int, int, int, int, XAACacheInfoPtr); + +typedef struct _XAAScreen { + CreateGCProcPtr CreateGC; + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CopyWindowProcPtr CopyWindow; + WindowExposuresProcPtr WindowExposures; + CreatePixmapProcPtr CreatePixmap; + DestroyPixmapProcPtr DestroyPixmap; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + XAAInfoRecPtr AccelInfoRec; + Bool (*EnterVT) (ScrnInfoPtr); + void (*LeaveVT) (ScrnInfoPtr); + int (*SetDGAMode) (ScrnInfoPtr, int, DGADevicePtr); + void (*EnableDisableFBAccess) (ScrnInfoPtr, Bool); + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; +} XAAScreenRec, *XAAScreenPtr; + +#define OPS_ARE_PIXMAP 0x00000001 +#define OPS_ARE_ACCEL 0x00000002 + +typedef struct _XAAGC { + GCOps *wrapOps; + GCFuncs *wrapFuncs; + GCOps *XAAOps; + int DashLength; + unsigned char *DashPattern; + unsigned long changes; + unsigned long flags; +} XAAGCRec, *XAAGCPtr; + +#define REDUCIBILITY_CHECKED 0x00000001 +#define REDUCIBLE_TO_8x8 0x00000002 +#define REDUCIBLE_TO_2_COLOR 0x00000004 +#define DIRTY 0x00010000 +#define OFFSCREEN 0x00020000 +#define DGA_PIXMAP 0x00040000 +#define SHARED_PIXMAP 0x00080000 +#define LOCKED_PIXMAP 0x00100000 + +#define REDUCIBILITY_MASK \ + (REDUCIBILITY_CHECKED | REDUCIBLE_TO_8x8 | REDUCIBLE_TO_2_COLOR) + +typedef struct _XAAPixmap { + unsigned long flags; + CARD32 pattern0; + CARD32 pattern1; + int fg; + int bg; + FBAreaPtr offscreenArea; + Bool freeData; +} XAAPixmapRec, *XAAPixmapPtr; + +extern _X_EXPORT Bool + XAACreateGC(GCPtr pGC); + +extern _X_EXPORT Bool + XAAInitAccel(ScreenPtr pScreen, XAAInfoRecPtr infoRec); + +extern _X_EXPORT RegionPtr + +XAABitBlt(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC * pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + void (*doBitBlt) (DrawablePtr, DrawablePtr, GCPtr, RegionPtr, + DDXPointPtr)/*, unsigned long bitPlane*/); + +extern _X_EXPORT void + +XAAScreenToScreenBitBlt(ScrnInfoPtr pScrn, + int nbox, + DDXPointPtr pptSrc, + BoxPtr pbox, + int xdir, int ydir, int alu, unsigned int planemask); + +extern _X_EXPORT void + +XAADoBitBlt(DrawablePtr pSrc, + DrawablePtr pDst, GC * pGC, RegionPtr prgnDst, DDXPointPtr pptSrc); + +extern _X_EXPORT void + +XAADoImageWrite(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, RegionPtr prgnDst, DDXPointPtr pptSrc); + +extern _X_EXPORT void + +XAADoImageRead(DrawablePtr pSrc, + DrawablePtr pDst, + GC * pGC, RegionPtr prgnDst, DDXPointPtr pptSrc); + +extern _X_EXPORT void + XAACopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); + +extern _X_EXPORT RegionPtr + +XAACopyArea(DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC * pGC, + int srcx, int srcy, int width, int height, int dstx, int dsty); + +extern _X_EXPORT void + XAAValidateCopyArea(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidatePutImage(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidateCopyPlane(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidatePushPixels(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidateFillSpans(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidatePolyGlyphBlt(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidateImageGlyphBlt(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT void + XAAValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); + +extern _X_EXPORT RegionPtr + +XAACopyPlaneColorExpansion(DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, int dsty, unsigned long bitPlane); + +extern _X_EXPORT void + +XAAPushPixelsSolidColorExpansion(GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, int dy, int xOrg, int yOrg); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpandMSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpand3MSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpandMSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpand3MSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpandLSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpand3LSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpandLSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapColorExpand3LSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpandMSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpand3MSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpandMSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpand3MSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpandLSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpand3LSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpandLSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask); + +extern _X_EXPORT void + +XAAWriteBitmapScanlineColorExpand3LSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask); + +extern _X_EXPORT void + +XAAWritePixmap(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int rop, + unsigned int planemask, + int transparency_color, int bpp, int depth); + +extern _X_EXPORT void + +XAAWritePixmapScanline(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int rop, + unsigned int planemask, + int transparency_color, int bpp, int depth); + +typedef void (*ClipAndRenderRectsFunc) (GCPtr, int, BoxPtr, int, int); + +extern _X_EXPORT void + +XAAClipAndRenderRects(GCPtr pGC, + ClipAndRenderRectsFunc func, + int nrectFill, xRectangle *prectInit, int xorg, int yorg); + +typedef void (*ClipAndRenderSpansFunc) (GCPtr, int, DDXPointPtr, int *, + int, int, int); + +extern _X_EXPORT void + +XAAClipAndRenderSpans(GCPtr pGC, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted, + ClipAndRenderSpansFunc func, int xorg, int yorg); + +extern _X_EXPORT void + +XAAFillSolidRects(ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox); + +extern _X_EXPORT void + +XAAFillMono8x8PatternRects(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int pat0, int pat1, int xorg, int yorg); + +extern _X_EXPORT void + +XAAFillMono8x8PatternRectsScreenOrigin(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int pat0, int pat1, int xorg, int yorg); + +extern _X_EXPORT void + +XAAFillColor8x8PatternRectsScreenOrigin(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorigin, int yorigin, + XAACacheInfoPtr pCache); + +extern _X_EXPORT void + +XAAFillColor8x8PatternRects(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorigin, int yorigin, XAACacheInfoPtr pCache); + +extern _X_EXPORT void + +XAAFillCacheBltRects(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int xorg, int yorg, XAACacheInfoPtr pCache); + +extern _X_EXPORT void + +XAAFillCacheExpandRects(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillImageWriteRects(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAPolyFillRect(DrawablePtr pDraw, + GCPtr pGC, int nrectFill, xRectangle *prectInit); + +extern _X_EXPORT void + +XAATEGlyphRendererMSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRenderer3MSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererMSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRenderer3MSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererLSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRenderer3LSBFirstFixedBase(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererLSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRenderer3LSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererScanlineMSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererScanline3MSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererScanlineLSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT void + +XAATEGlyphRendererScanline3LSBFirst(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, + int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncMSBFirstFixedBase[32]) (CARD32 + *base, + unsigned + int + **glyphp, + int line, + int + nglyph, + int + width); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncMSBFirst[32]) (CARD32 *base, + unsigned int + **glyphp, + int line, + int nglyph, + int width); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncLSBFirstFixedBase[32]) (CARD32 + *base, + unsigned + int + **glyphp, + int line, + int + nglyph, + int + width); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncLSBFirst[32]) (CARD32 *base, + unsigned int + **glyphp, + int line, + int nglyph, + int width); + +extern _X_EXPORT GlyphScanlineFuncPtr + *XAAGetGlyphScanlineFuncMSBFirstFixedBase(void); +extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncMSBFirst(void); +extern _X_EXPORT GlyphScanlineFuncPtr + *XAAGetGlyphScanlineFuncLSBFirstFixedBase(void); +extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncLSBFirst(void); + +extern _X_EXPORT void + +XAAFillColorExpandRectsLSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRects3LSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRectsLSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRects3LSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRectsMSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRects3MSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRectsMSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandRects3MSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandRectsLSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandRects3LSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandRectsMSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandRects3MSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpansLSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpans3LSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpansLSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpans3LSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpansMSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpans3MSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpansMSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillColorExpandSpans3MSBFirstFixedBase(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandSpansLSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandSpans3LSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAPutImage(DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, int leftPad, int format, char *pImage); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandSpansMSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillScanlineColorExpandSpans3MSBFirst(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncMSBFirstFixedBase[6]) (CARD32 + *base, + CARD32 + *src, + int + offset, + int + width, + int + dwords); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncMSBFirst[6]) (CARD32 *base, + CARD32 *src, + int offset, + int width, + int dwords); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncLSBFirstFixedBase[6]) (CARD32 + *base, + CARD32 + *src, + int + offset, + int + width, + int + dwords); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncLSBFirst[6]) (CARD32 *base, + CARD32 *src, + int offset, + int width, + int dwords); + +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFuncMSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFuncMSBFirst(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFuncLSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFuncLSBFirst(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFunc3MSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFunc3MSBFirst(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFunc3LSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr + *XAAGetStippleScanlineFunc3LSBFirst(void); + +extern _X_EXPORT int + +XAAPolyText8TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars); + +extern _X_EXPORT int + +XAAPolyText16TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars); + +extern _X_EXPORT void + +XAAImageText8TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, int x, int y, int count, char *chars); + +extern _X_EXPORT void + +XAAImageText16TEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, unsigned short *chars); + +extern _X_EXPORT void + +XAAImageGlyphBltTEColorExpansion(DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + +extern _X_EXPORT void + +XAAPolyGlyphBltTEColorExpansion(DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + +extern _X_EXPORT int + +XAAPolyText8NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, char *chars); + +extern _X_EXPORT int + +XAAPolyText16NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, unsigned short *chars); + +extern _X_EXPORT void + +XAAImageText8NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, int count, char *chars); + +extern _X_EXPORT void + +XAAImageText16NonTEColorExpansion(DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, unsigned short *chars); + +extern _X_EXPORT void + +XAAImageGlyphBltNonTEColorExpansion(DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + +extern _X_EXPORT void + +XAAPolyGlyphBltNonTEColorExpansion(DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase); + +extern _X_EXPORT void XAANonTEGlyphRenderer(ScrnInfoPtr pScrn, + int x, int y, int n, + NonTEGlyphPtr glyphs, + BoxPtr pbox, + int fg, int rop, + unsigned int planemask); + +extern _X_EXPORT void + +XAAFillSolidSpans(ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int n, DDXPointPtr ppt, int *pwidth, int fSorted); + +extern _X_EXPORT void + +XAAFillMono8x8PatternSpans(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + int patx, int paty, int xorg, int yorg); + +extern _X_EXPORT void + +XAAFillMono8x8PatternSpansScreenOrigin(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + int patx, int paty, int xorg, int yorg); + +extern _X_EXPORT void + +XAAFillColor8x8PatternSpansScreenOrigin(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + XAACacheInfoPtr, + int xorigin, int yorigin); + +extern _X_EXPORT void + +XAAFillColor8x8PatternSpans(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + XAACacheInfoPtr, int xorigin, int yorigin); + +extern _X_EXPORT void + +XAAFillCacheBltSpans(ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr points, + int *widths, + int fSorted, XAACacheInfoPtr pCache, int xorg, int yorg); + +extern _X_EXPORT void + +XAAFillCacheExpandSpans(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, int xorg, int yorg, PixmapPtr pPix); + +extern _X_EXPORT void + +XAAFillSpans(DrawablePtr pDrawable, + GC * pGC, + int nInit, DDXPointPtr pptInit, int *pwidth, int fSorted); + +extern _X_EXPORT void + XAAInitPixmapCache(ScreenPtr pScreen, RegionPtr areas, void * data); + +extern _X_EXPORT void + +XAAWriteBitmapToCache(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, int bg); + +extern _X_EXPORT void + +XAAWriteBitmapToCacheLinear(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, int bg); + +extern _X_EXPORT void + +XAAWritePixmapToCache(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, int srcwidth, int bpp, int depth); + +extern _X_EXPORT void + +XAAWritePixmapToCacheLinear(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, int bpp, int depth); + +extern _X_EXPORT void + XAASolidHorVertLineAsRects(ScrnInfoPtr pScrn, int x, int y, int len, int dir); + +extern _X_EXPORT void + +XAASolidHorVertLineAsTwoPoint(ScrnInfoPtr pScrn, + int x, int y, int len, int dir); + +extern _X_EXPORT void + +XAASolidHorVertLineAsBresenham(ScrnInfoPtr pScrn, + int x, int y, int len, int dir); + +extern _X_EXPORT void + +XAAPolyRectangleThinSolid(DrawablePtr pDrawable, + GCPtr pGC, int nRectsInit, xRectangle *pRectsInit); + +extern _X_EXPORT void + +XAAPolylinesWideSolid(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr pPts); + +extern _X_EXPORT void + +XAAFillPolygonSolid(DrawablePtr pDrawable, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn); + +extern _X_EXPORT void + +XAAFillPolygonStippled(DrawablePtr pDrawable, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn); + +extern _X_EXPORT void + +XAAFillPolygonTiled(DrawablePtr pDrawable, + GCPtr pGC, + int shape, int mode, int count, DDXPointPtr ptsIn); + +extern _X_EXPORT int + +XAAIsEasyPolygon(DDXPointPtr ptsIn, + int count, + BoxPtr extents, + int origin, + DDXPointPtr * topPoint, int *topY, int *bottomY, int shape); + +extern _X_EXPORT void + +XAAFillPolygonHelper(ScrnInfoPtr pScrn, + DDXPointPtr ptsIn, + int count, + DDXPointPtr topPoint, + int y, + int maxy, + int origin, + RectFuncPtr RectFunc, + TrapFuncPtr TrapFunc, + int xorg, int yorg, XAACacheInfoPtr pCache); + +extern _X_EXPORT void + XAAPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg); + +extern _X_EXPORT void + +XAAPolyLines(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr pptInit); + +extern _X_EXPORT void + +XAAPolySegmentDashed(DrawablePtr pDrawable, + GCPtr pGC, int nseg, xSegment * pSeg); + +extern _X_EXPORT void + +XAAPolyLinesDashed(DrawablePtr pDrawable, + GCPtr pGC, int mode, int npt, DDXPointPtr pptInit); + +extern _X_EXPORT void + XAAWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache); + +extern _X_EXPORT void + +XAAWriteColor8x8PatternToCache(ScrnInfoPtr pScrn, + PixmapPtr pPix, XAACacheInfoPtr pCache); + +extern _X_EXPORT void + +XAARotateMonoPattern(int *pat0, int *pat1, + int xoffset, int yoffset, Bool msbfirst); + +extern _X_EXPORT void XAAComputeDash(GCPtr pGC); + +extern _X_EXPORT void XAAMoveDWORDS_FixedBase(register CARD32 *dest, + register CARD32 *src, + register int dwords); + +extern _X_EXPORT void XAAMoveDWORDS_FixedSrc(register CARD32 *dest, + register CARD32 *src, + register int dwords); + +extern _X_EXPORT void XAAMoveDWORDS(register CARD32 *dest, + register CARD32 *src, register int dwords); + +extern _X_EXPORT int + +XAAGetRectClipBoxes(GCPtr pGC, + BoxPtr pboxClippedBase, + int nrectFill, xRectangle *prectInit); + +extern _X_EXPORT void + XAASetupOverlay8_32Planar(ScreenPtr); + +extern _X_EXPORT void + XAAPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs); + +extern _X_EXPORT XAACacheInfoPtr XAACacheTile(ScrnInfoPtr Scrn, PixmapPtr pPix); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheMonoStipple(ScrnInfoPtr Scrn, PixmapPtr pPix); + +extern _X_EXPORT XAACacheInfoPtr +XAACachePlanarMonoStipple(ScrnInfoPtr Scrn, PixmapPtr pPix); + +typedef XAACacheInfoPtr(*XAACachePlanarMonoStippleProc) (ScrnInfoPtr, + PixmapPtr); +extern _X_EXPORT XAACachePlanarMonoStippleProc +XAAGetCachePlanarMonoStipple(void); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheStipple(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, int bg); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheMono8x8Pattern(ScrnInfoPtr Scrn, int pat0, int pat1); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheColor8x8Pattern(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, int bg); + +extern _X_EXPORT void + XAATileCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache, int w, int h); + +extern _X_EXPORT void XAAClosePixmapCache(ScreenPtr pScreen); +void XAAInvalidatePixmapCache(ScreenPtr pScreen); + +extern _X_EXPORT Bool XAACheckStippleReducibility(PixmapPtr pPixmap); +extern _X_EXPORT Bool XAACheckTileReducibility(PixmapPtr pPixmap, + Bool checkMono); + +extern _X_EXPORT int XAAStippledFillChooser(GCPtr pGC); +extern _X_EXPORT int XAAOpaqueStippledFillChooser(GCPtr pGC); +extern _X_EXPORT int XAATiledFillChooser(GCPtr pGC); + +extern _X_EXPORT void XAAMoveInOffscreenPixmaps(ScreenPtr pScreen); +extern _X_EXPORT void XAAMoveOutOffscreenPixmaps(ScreenPtr pScreen); +extern _X_EXPORT void XAARemoveAreaCallback(FBAreaPtr area); +extern _X_EXPORT void XAAMoveOutOffscreenPixmap(PixmapPtr pPix); +extern _X_EXPORT Bool XAAInitStateWrap(ScreenPtr pScreen, + XAAInfoRecPtr infoRec); + +extern _X_EXPORT void + +XAAComposite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +extern _X_EXPORT Bool + +XAADoComposite(CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); + +extern _X_EXPORT void + +XAAGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); + +extern _X_EXPORT Bool + +XAADoGlyphs(CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs); + +/* helpers */ +extern _X_EXPORT void + XAA_888_plus_PICT_a8_to_8888(CARD32 color, CARD8 *alphaPtr, /* in bytes */ + int alphaPitch, CARD32 *dstPtr, int dstPitch, /* in dwords */ + int width, int height); + +extern _X_EXPORT Bool + +XAAGetRGBAFromPixel(CARD32 pixel, + CARD16 *red, + CARD16 *green, CARD16 *blue, CARD16 *alpha, CARD32 format); + +extern _X_EXPORT Bool + +XAAGetPixelFromRGBA(CARD32 *pixel, + CARD16 red, + CARD16 green, CARD16 blue, CARD16 alpha, CARD32 format); + +/* XXX should be static */ +extern _X_EXPORT GCOps XAAFallbackOps; +extern _X_EXPORT GCOps *XAAGetFallbackOps(void); +extern _X_EXPORT GCFuncs XAAGCFuncs; +extern _X_EXPORT DevPrivateKey XAAGetScreenKey(void); +extern _X_EXPORT DevPrivateKey XAAGetGCKey(void); +extern _X_EXPORT DevPrivateKey XAAGetPixmapKey(void); + +extern _X_EXPORT unsigned int XAAShiftMasks[32]; + +extern _X_EXPORT unsigned int byte_expand3[256], byte_reversed_expand3[256]; + +extern _X_EXPORT CARD32 XAAReverseBitOrder(CARD32 data); + +#define GET_XAASCREENPTR_FROM_SCREEN(pScreen)\ + dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()) + +#define GET_XAASCREENPTR_FROM_GC(pGC)\ + dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()) + +#define GET_XAASCREENPTR_FROM_DRAWABLE(pDraw)\ + dixLookupPrivate(&(pDraw)->pScreen->devPrivates, XAAGetScreenKey()) + +#define GET_XAAINFORECPTR_FROM_SCREEN(pScreen)\ +((XAAScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define GET_XAAINFORECPTR_FROM_GC(pGC)\ +((XAAScreenPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define GET_XAAINFORECPTR_FROM_DRAWABLE(pDraw)\ +((XAAScreenPtr)dixLookupPrivate(&(pDraw)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn)\ +((XAAScreenPtr)dixLookupPrivate(&(pScrn)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define XAA_GET_PIXMAP_PRIVATE(pix)\ + (XAAPixmapPtr)dixLookupPrivate(&(pix)->devPrivates, XAAGetPixmapKey()) + +#define CHECK_RGB_EQUAL(c) (!((((c) >> 8) ^ (c)) & 0xffff)) + +#define CHECK_FG(pGC, flags) \ + (!(flags & RGB_EQUAL) || CHECK_RGB_EQUAL(pGC->fgPixel)) + +#define CHECK_BG(pGC, flags) \ + (!(flags & RGB_EQUAL) || CHECK_RGB_EQUAL(pGC->bgPixel)) + +#define CHECK_ROP(pGC, flags) \ + (!(flags & GXCOPY_ONLY) || (pGC->alu == GXcopy)) + +#define CHECK_ROPSRC(pGC, flags) \ + (!(flags & ROP_NEEDS_SOURCE) || ((pGC->alu != GXclear) && \ + (pGC->alu != GXnoop) && (pGC->alu != GXinvert) && \ + (pGC->alu != GXset))) + +#define CHECK_PLANEMASK(pGC, flags) \ + (!(flags & NO_PLANEMASK) || \ + ((pGC->planemask & infoRec->FullPlanemasks[pGC->depth - 1]) == \ + infoRec->FullPlanemasks[pGC->depth - 1])) + +#define CHECK_COLORS(pGC, flags) \ + (!(flags & RGB_EQUAL) || \ + (CHECK_RGB_EQUAL(pGC->fgPixel) && CHECK_RGB_EQUAL(pGC->bgPixel))) + +#define CHECK_NO_GXCOPY(pGC, flags) \ + ((pGC->alu != GXcopy) || !(flags & NO_GXCOPY) || \ + ((pGC->planemask & infoRec->FullPlanemask) != infoRec->FullPlanemask)) + +#define IS_OFFSCREEN_PIXMAP(pPix)\ + ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->offscreenArea) + +#define PIXMAP_IS_SHARED(pPix)\ + ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->flags & SHARED_PIXMAP) + +#define OFFSCREEN_PIXMAP_LOCKED(pPix)\ + ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->flags & LOCKED_PIXMAP) + +#define XAA_DEPTH_BUG(pGC) \ + ((pGC->depth == 32) && (pGC->bgPixel == 0xffffffff)) + +#define DELIST_OFFSCREEN_PIXMAP(pPix) { \ + PixmapLinkPtr _pLink, _prev; \ + _pLink = infoRec->OffscreenPixmaps; \ + _prev = NULL; \ + while(_pLink) { \ + if(_pLink->pPix == pPix) { \ + if(_prev) _prev->next = _pLink->next; \ + else infoRec->OffscreenPixmaps = _pLink->next; \ + free(_pLink); \ + break; \ + } \ + _prev = _pLink; \ + _pLink = _pLink->next; \ + }} + +#define SWAP_BITS_IN_BYTES(v) \ + (((0x01010101 & (v)) << 7) | ((0x02020202 & (v)) << 5) | \ + ((0x04040404 & (v)) << 3) | ((0x08080808 & (v)) << 1) | \ + ((0x10101010 & (v)) >> 1) | ((0x20202020 & (v)) >> 3) | \ + ((0x40404040 & (v)) >> 5) | ((0x80808080 & (v)) >> 7)) + +/* + * Moved XAAPixmapCachePrivate here from xaaPCache.c, since driver + * replacements for CacheMonoStipple need access to it + */ + +typedef struct { + int Num512x512; + int Current512; + XAACacheInfoPtr Info512; + int Num256x256; + int Current256; + XAACacheInfoPtr Info256; + int Num128x128; + int Current128; + XAACacheInfoPtr Info128; + int NumMono; + int CurrentMono; + XAACacheInfoPtr InfoMono; + int NumColor; + int CurrentColor; + XAACacheInfoPtr InfoColor; + int NumPartial; + int CurrentPartial; + XAACacheInfoPtr InfoPartial; + DDXPointRec MonoOffsets[64]; + DDXPointRec ColorOffsets[64]; +} XAAPixmapCachePrivate, *XAAPixmapCachePrivatePtr; + +#endif /* _XAALOCAL_H */ diff --git a/hw/xfree86/common/xaarop.h b/hw/xfree86/xaa/xaarop.h similarity index 79% rename from hw/xfree86/common/xaarop.h rename to hw/xfree86/xaa/xaarop.h index 84aa9baba..f2acde075 100644 --- a/hw/xfree86/common/xaarop.h +++ b/hw/xfree86/xaa/xaarop.h @@ -1,3 +1,30 @@ +/* + + int XAAHelpSolidROP(ScrnInfoPtr pScrn, int *fg, int pm, int *rop) + + For use with solid fills emulated by solid 8x8 patterns. You + give it the foreground, planemask and X rop and it will replace + the foreground with a new one and the rop with the appropriate + MS triadic raster op. The function will return which components + (S-P) need to be enabled. + + int XAAHelpPatternROP(ScrnInfoPtr pScrn, int *fg, int *bg, int pm, int *rop) + + For use with 8x8 opaque pattern fills. You give it the foreground, + and background, planemask and X rop and it will replace the + foreground and background with new ones and the rop with the + appropriate MS triadic raster op. The function will return which + components (S-P) need to be enabled. + + ROP_PAT - Means to enable 8x8 mono patterns (all bits + set for solid patterns). Set the foreground and + background as returned by the function. + + ROP_SRC - Means a source of color == planemask should be used. + + +*/ + #ifndef _XAAROP_H #define _XAAROP_H @@ -265,4 +292,20 @@ #define NO_SRC_ROP(rop) \ ((rop == GXnoop) || (rop == GXset) || (rop == GXclear) || (rop == GXinvert)) +extern _X_EXPORT int XAAHelpSolidROP(ScrnInfoPtr pScrn, int *fg, int pm, + int *rop); +extern _X_EXPORT int XAAHelpPatternROP(ScrnInfoPtr pScrn, int *fg, int *bg, + int pm, int *rop); + +/* XXX These four should be static, but it breaks the 6.7.0 ABI. */ +extern _X_EXPORT int XAACopyROP[16]; +extern _X_EXPORT int XAACopyROP_PM[16]; +extern _X_EXPORT int XAAPatternROP[16]; +extern _X_EXPORT int XAAPatternROP_PM[16]; + +extern _X_EXPORT int XAAGetCopyROP(int i); +extern _X_EXPORT int XAAGetCopyROP_PM(int i); +extern _X_EXPORT int XAAGetPatternROP(int i); +extern _X_EXPORT int XAAGetPatternROP_PM(int i); + #endif /* _XAAROP_H */ diff --git a/hw/xfree86/xaa/xaawrap.h b/hw/xfree86/xaa/xaawrap.h new file mode 100644 index 000000000..2d2d7881a --- /dev/null +++ b/hw/xfree86/xaa/xaawrap.h @@ -0,0 +1,75 @@ + +#define XAA_SCREEN_PROLOGUE(pScreen, field)\ + ((pScreen)->field = \ + ((XAAScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()))->field) + +#define XAA_SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +#define XAA_GC_FUNC_PROLOGUE(pGC)\ + XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&(pGC)->devPrivates, XAAGetGCKey()); \ + (pGC)->funcs = pGCPriv->wrapFuncs;\ + if(pGCPriv->flags)\ + (pGC)->ops = pGCPriv->wrapOps + +#define XAA_GC_FUNC_EPILOGUE(pGC)\ + pGCPriv->wrapFuncs = (pGC)->funcs;\ + (pGC)->funcs = &XAAGCFuncs;\ + if(pGCPriv->flags) {\ + pGCPriv->wrapOps = (pGC)->ops;\ + (pGC)->ops = (pGCPriv->flags & OPS_ARE_ACCEL) ? pGCPriv->XAAOps :\ + &XAAPixmapOps;\ + } + +#define XAA_GC_OP_PROLOGUE(pGC)\ + XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&(pGC)->devPrivates, XAAGetGCKey()); \ + GCFuncs *oldFuncs = pGC->funcs;\ + pGC->funcs = pGCPriv->wrapFuncs;\ + pGC->ops = pGCPriv->wrapOps + +#define XAA_GC_OP_PROLOGUE_WITH_RETURN(pGC)\ + XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&(pGC)->devPrivates, XAAGetGCKey()); \ + GCFuncs *oldFuncs = pGC->funcs;\ + if(!RegionNumRects(pGC->pCompositeClip)) return; \ + pGC->funcs = pGCPriv->wrapFuncs;\ + pGC->ops = pGCPriv->wrapOps + +#define XAA_GC_OP_EPILOGUE(pGC)\ + pGCPriv->wrapOps = pGC->ops;\ + pGC->funcs = oldFuncs;\ + pGC->ops = pGCPriv->XAAOps + +#define XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw)\ + XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&(pGC)->devPrivates, XAAGetGCKey()); \ + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDraw));\ + GCFuncs *oldFuncs = pGC->funcs;\ + pGC->funcs = pGCPriv->wrapFuncs;\ + pGC->ops = pGCPriv->wrapOps; \ + SYNC_CHECK(pGC) + +#define XAA_PIXMAP_OP_EPILOGUE(pGC)\ + pGCPriv->wrapOps = pGC->ops;\ + pGC->funcs = oldFuncs;\ + pGC->ops = &XAAPixmapOps;\ + pixPriv->flags |= DIRTY + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#define XAA_RENDER_PROLOGUE(pScreen,field)\ + (GetPictureScreen(pScreen)->field = \ + ((XAAScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()))->field) + +#define XAA_RENDER_EPILOGUE(pScreen, field, wrapper)\ + (GetPictureScreen(pScreen)->field = wrapper) + +/* This also works fine for drawables */ + +#define SYNC_CHECK(pGC) {\ + XAAInfoRecPtr infoRec =\ +((XAAScreenPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec; \ + if(infoRec->NeedToSync) {\ + (*infoRec->Sync)(infoRec->pScrn);\ + infoRec->NeedToSync = FALSE;\ + }} diff --git a/include/gcstruct.h b/include/gcstruct.h index cb1b56655..f005a6fc0 100644 --- a/include/gcstruct.h +++ b/include/gcstruct.h @@ -276,9 +276,16 @@ typedef struct _GC { unsigned int stateChanges; /* masked with GC_ */ unsigned int serialNumber; const GCFuncs *funcs; - const GCOps *ops; + GCOps *ops; PrivateRec *devPrivates; + /* + * The following were moved here from private storage to allow device- + * independent access to them from screen wrappers. + * --- 1997.11.03 Marc Aurele La France (tsi@xfree86.org) + */ + PixmapPtr pRotatedPixmap; /* tile/stipple rotated for alignment */ RegionPtr pCompositeClip; + /* fExpose & freeCompClip defined above */ } GC; #endif /* GCSTRUCT_H */ diff --git a/mi/Makefile.am b/mi/Makefile.am index 110c3f5dd..0b6a98935 100644 --- a/mi/Makefile.am +++ b/mi/Makefile.am @@ -2,8 +2,8 @@ noinst_LTLIBRARIES = libmi.la if XORG sdk_HEADERS = micmap.h miline.h mipointer.h mi.h \ - migc.h mipointrst.h mizerarc.h micoord.h \ - mistruct.h mioverlay.h + migc.h mipointrst.h mizerarc.h micoord.h mifillarc.h \ + miwideline.h mistruct.h mioverlay.h endif AM_CFLAGS = $(DIX_CFLAGS) diff --git a/mi/mi.h b/mi/mi.h index 8b0a231ca..d3e412a5e 100644 --- a/mi/mi.h +++ b/mi/mi.h @@ -488,6 +488,9 @@ extern _X_EXPORT void miMarkUnrealizedWindow(WindowPtr /*pChild */ , Bool /*fromConfigure */ ); +extern _X_EXPORT void miSegregateChildren(WindowPtr pWin, RegionPtr pReg, + int depth); + extern _X_EXPORT WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y); extern _X_EXPORT WindowPtr miXYToWindow(ScreenPtr pScreen, SpritePtr pSprite, int x, int y); diff --git a/mi/mifillarc.c b/mi/mifillarc.c index 888519edf..19c928361 100644 --- a/mi/mifillarc.c +++ b/mi/mifillarc.c @@ -50,7 +50,7 @@ Author: Bob Scheifler, MIT X Consortium #define Dsin(d) sin((double)d*(M_PI/11520.0)) #define Dcos(d) cos((double)d*(M_PI/11520.0)) -static void +void miFillArcSetup(xArc * arc, miFillArcRec * info) { info->y = arc->height >> 1; @@ -276,7 +276,7 @@ miGetPieEdge(xArc * arc, int angle, miSliceEdgePtr edge, Bool top, Bool left) miGetArcEdge(arc, edge, k, top, left); } -static void +void miFillArcSliceSetup(xArc * arc, miArcSliceRec * slice, GCPtr pGC) { int angle1, angle2; diff --git a/mi/mifillarc.h b/mi/mifillarc.h index 61ab2538d..1478d1850 100644 --- a/mi/mifillarc.h +++ b/mi/mifillarc.h @@ -175,4 +175,13 @@ typedef struct _miArcSlice { #define miFillInArcLower(slw) (((iny + dy) != 0) && \ ((slw > 1) || (ine != inxk))) +extern _X_EXPORT void miFillArcSetup(xArc * /*arc */ , + miFillArcRec * /*info */ + ); + +extern _X_EXPORT void miFillArcSliceSetup(xArc * /*arc */ , + miArcSliceRec * /*slice */ , + GCPtr /*pGC */ + ); + #endif /* __MIFILLARC_H__ */ diff --git a/mi/migc.c b/mi/migc.c index bc2e1aede..8fdd4810c 100644 --- a/mi/migc.c +++ b/mi/migc.c @@ -46,6 +46,8 @@ miChangeGC(GCPtr pGC, unsigned long mask) void miDestroyGC(GCPtr pGC) { + if (pGC->pRotatedPixmap) + (*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap); if (pGC->freeCompClip) RegionDestroy(pGC->pCompositeClip); } diff --git a/mi/mioverlay.c b/mi/mioverlay.c index b8b7a5ba8..9f3ef0725 100644 --- a/mi/mioverlay.c +++ b/mi/mioverlay.c @@ -990,6 +990,7 @@ miOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn) int clientInterested = (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask; if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) { + ScreenPtr pScreen = pWin->drawable.pScreen; miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); BoxRec box; diff --git a/mi/miwideline.c b/mi/miwideline.c index 54de1d3e6..6276c2d8b 100644 --- a/mi/miwideline.c +++ b/mi/miwideline.c @@ -787,7 +787,7 @@ miFillRectPolyHelper(DrawablePtr pDrawable, } } -static int +/* static */ int miPolyBuildEdge(double x0, double y0, double k, /* x0 * dy - y0 * dx */ int dx, int dy, int xi, int yi, int left, PolyEdgePtr edge) { @@ -839,7 +839,7 @@ miPolyBuildEdge(double x0, double y0, double k, /* x0 * dy - y0 * dx */ #define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) -static int +/* static */ int miPolyBuildPoly(PolyVertexPtr vertices, PolySlopePtr slopes, int count, @@ -1379,7 +1379,7 @@ miRoundJoinFace(LineFacePtr face, PolyEdgePtr edge, Bool *leftEdge) return y; } -static void +void miRoundJoinClip(LineFacePtr pLeft, LineFacePtr pRight, PolyEdgePtr edge1, PolyEdgePtr edge2, int *y1, int *y2, Bool *left1, Bool *left2) @@ -1400,7 +1400,7 @@ miRoundJoinClip(LineFacePtr pLeft, LineFacePtr pRight, *y2 = miRoundJoinFace(pRight, edge2, left2); } -static int +int miRoundCapClip(LineFacePtr face, Bool isInt, PolyEdgePtr edge, Bool *leftEdge) { int y; diff --git a/mi/miwideline.h b/mi/miwideline.h index 88bc3d6c8..82822cf45 100644 --- a/mi/miwideline.h +++ b/mi/miwideline.h @@ -91,3 +91,28 @@ typedef struct _LineFace { ValidateGC (pDrawable, pGC); \ } \ } + +extern _X_EXPORT void miRoundJoinClip(LineFacePtr /*pLeft */ , + LineFacePtr /*pRight */ , + PolyEdgePtr /*edge1 */ , + PolyEdgePtr /*edge2 */ , + int * /*y1 */ , + int * /*y2 */ , + Bool * /*left1 */ , + Bool * /*left2 */ + ); + +extern _X_EXPORT int miRoundCapClip(LineFacePtr /*face */ , + Bool /*isInt */ , + PolyEdgePtr /*edge */ , + Bool * /*leftEdge */ + ); + +extern _X_EXPORT int miPolyBuildEdge(double x0, double y0, double k, int dx, + int dy, int xi, int yi, int left, + PolyEdgePtr edge); +extern _X_EXPORT int miPolyBuildPoly(PolyVertexPtr vertices, + PolySlopePtr slopes, int count, int xi, + int yi, PolyEdgePtr left, + PolyEdgePtr right, int *pnleft, + int *pnright, int *h); diff --git a/mi/miwindow.c b/mi/miwindow.c index 39c279e18..af22941f6 100644 --- a/mi/miwindow.c +++ b/mi/miwindow.c @@ -745,6 +745,20 @@ miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure) } } +void +miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth) +{ + WindowPtr pChild; + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + if (pChild->drawable.depth == depth) + RegionUnion(pReg, pReg, &pChild->borderClip); + + if (pChild->firstChild) + miSegregateChildren(pChild, pReg, depth); + } +} + WindowPtr miSpriteTrace(SpritePtr pSprite, int x, int y) { diff --git a/miext/Makefile.am b/miext/Makefile.am index add4d18b0..bb29e8148 100644 --- a/miext/Makefile.am +++ b/miext/Makefile.am @@ -1 +1,4 @@ SUBDIRS = sync damage shadow rootless +if COMPOSITE +SUBDIRS += cw +endif diff --git a/miext/cw/Makefile.am b/miext/cw/Makefile.am new file mode 100644 index 000000000..e056f4279 --- /dev/null +++ b/miext/cw/Makefile.am @@ -0,0 +1,11 @@ +noinst_LTLIBRARIES = libcw.la + +AM_CFLAGS = $(DIX_CFLAGS) + +INCLUDES = -I$(top_srcdir)/hw/xfree86/os-support + +libcw_la_SOURCES = \ + cw.c \ + cw_ops.c \ + cw_render.c \ + cw.h diff --git a/miext/cw/cw.c b/miext/cw/cw.c new file mode 100644 index 000000000..4a1a0c5f9 --- /dev/null +++ b/miext/cw/cw.c @@ -0,0 +1,524 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "gcstruct.h" +#include "windowstr.h" +#include "cw.h" + +#define CW_DEBUG 1 + +#if CW_DEBUG +#define CW_ASSERT(x) do { \ + if (!(x)) { \ + ErrorF("composite wrapper: assertion failed at %s:%d\n", __FUNC__, \ + __LINE__); \ + } \ +} while (0) +#else +#define CW_ASSERT(x) do {} while (0) +#endif + +DevPrivateKeyRec cwGCKeyRec; +DevPrivateKeyRec cwScreenKeyRec; +DevPrivateKeyRec cwWindowKeyRec; +DevPrivateKeyRec cwPictureKeyRec; + +extern GCOps cwGCOps; + +static Bool + cwCloseScreen(ScreenPtr pScreen); + +static void + cwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable); +static void + cwChangeGC(GCPtr pGC, unsigned long mask); +static void + cwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void + cwDestroyGC(GCPtr pGC); +static void + cwChangeClip(GCPtr pGC, int type, void * pvalue, int nrects); +static void + cwCopyClip(GCPtr pgcDst, GCPtr pgcSrc); +static void + cwDestroyClip(GCPtr pGC); + +GCFuncs cwGCFuncs = { + cwValidateGC, + cwChangeGC, + cwCopyGC, + cwDestroyGC, + cwChangeClip, + cwDestroyClip, + cwCopyClip, +}; + +/* Find the real drawable to draw to, and provide offsets that will translate + * window coordinates to backing pixmap coordinates. + */ +DrawablePtr +cwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off) +{ + PixmapPtr pPixmap; + + if (pDrawable->type == DRAWABLE_WINDOW && + (pPixmap = getCwPixmap((WindowPtr) pDrawable))) { + *x_off = pDrawable->x - pPixmap->screen_x; + *y_off = pDrawable->y - pPixmap->screen_y; + return &pPixmap->drawable; + } + else { + *x_off = *y_off = 0; + return pDrawable; + } +} + +#define FUNC_PROLOGUE(pGC, pPriv) do { \ + (pGC)->funcs = (pPriv)->wrapFuncs; \ + (pGC)->ops = (pPriv)->wrapOps; \ +} while (0) + +#define FUNC_EPILOGUE(pGC, pPriv) do { \ + (pPriv)->wrapFuncs = (pGC)->funcs; \ + (pPriv)->wrapOps = (pGC)->ops; \ + (pGC)->funcs = &cwGCFuncs; \ + (pGC)->ops = &cwGCOps; \ +} while (0) + +static Bool +cwCreateBackingGC(GCPtr pGC, DrawablePtr pDrawable) +{ + cwGCRec *pPriv = getCwGC(pGC); + int status, x_off, y_off; + XID noexpose = xFalse; + DrawablePtr pBackingDrawable; + + pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); + pPriv->pBackingGC = CreateGC(pBackingDrawable, GCGraphicsExposures, + &noexpose, &status, (XID) 0, serverClient); + if (status != Success) + return FALSE; + + pPriv->serialNumber = 0; + pPriv->stateChanges = GCAllBits; + + return TRUE; +} + +static void +cwDestroyBackingGC(GCPtr pGC) +{ + cwGCPtr pPriv; + + pPriv = (cwGCPtr) getCwGC(pGC); + + if (pPriv->pBackingGC) { + FreeGC(pPriv->pBackingGC, (XID) 0); + pPriv->pBackingGC = NULL; + } +} + +static void +cwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable) +{ + GCPtr pBackingGC; + cwGCPtr pPriv; + DrawablePtr pBackingDrawable; + int x_off, y_off; + + pPriv = (cwGCPtr) getCwGC(pGC); + + FUNC_PROLOGUE(pGC, pPriv); + + /* + * Must call ValidateGC to ensure pGC->pCompositeClip is valid + */ + (*pGC->funcs->ValidateGC) (pGC, stateChanges, pDrawable); + + if (!cwDrawableIsRedirWindow(pDrawable)) { + cwDestroyBackingGC(pGC); + FUNC_EPILOGUE(pGC, pPriv); + return; + } + else { + if (!pPriv->pBackingGC && !cwCreateBackingGC(pGC, pDrawable)) { + FUNC_EPILOGUE(pGC, pPriv); + return; + } + } + + pBackingGC = pPriv->pBackingGC; + pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); + + pPriv->stateChanges |= stateChanges; + + /* + * Copy the composite clip into the backing GC if either + * the drawable clip list has changed or the client has changed + * the client clip data + */ + if (pDrawable->serialNumber != pPriv->serialNumber || + (pPriv->stateChanges & (GCClipXOrigin | GCClipYOrigin | GCClipMask))) { + ChangeGCVal vals[2]; + RegionPtr pCompositeClip; + + pCompositeClip = RegionCreate(NULL, 0); + RegionCopy(pCompositeClip, pGC->pCompositeClip); + + /* Either the drawable has changed, or the clip list in the drawable has + * changed. Copy the new clip list over and set the new translated + * offset for it. + */ + + (*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION, + (void *) pCompositeClip, 0); + + vals[0].val = x_off - pDrawable->x; + vals[1].val = y_off - pDrawable->y; + ChangeGC(NullClient, pBackingGC, (GCClipXOrigin | GCClipYOrigin), vals); + + pPriv->serialNumber = pDrawable->serialNumber; + /* + * Mask off any client clip changes to make sure + * the clip list set above remains in effect + */ + pPriv->stateChanges &= ~(GCClipXOrigin | GCClipYOrigin | GCClipMask); + } + + if (pPriv->stateChanges) { + CopyGC(pGC, pBackingGC, pPriv->stateChanges); + pPriv->stateChanges = 0; + } + + if ((pGC->patOrg.x + x_off) != pBackingGC->patOrg.x || + (pGC->patOrg.y + y_off) != pBackingGC->patOrg.y) { + ChangeGCVal vals[2]; + + vals[0].val = pGC->patOrg.x + x_off; + vals[1].val = pGC->patOrg.y + y_off; + ChangeGC(NullClient, pBackingGC, + (GCTileStipXOrigin | GCTileStipYOrigin), vals); + } + + ValidateGC(pBackingDrawable, pBackingGC); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwChangeGC(GCPtr pGC, unsigned long mask) +{ + cwGCPtr pPriv = (cwGCPtr) dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pGC, pPriv); + + (*pGC->funcs->ChangeGC) (pGC, mask); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + cwGCPtr pPriv = (cwGCPtr) dixLookupPrivate(&pGCDst->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pGCDst, pPriv); + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + + FUNC_EPILOGUE(pGCDst, pPriv); +} + +static void +cwDestroyGC(GCPtr pGC) +{ + cwGCPtr pPriv = (cwGCPtr) dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pGC, pPriv); + + cwDestroyBackingGC(pGC); + + (*pGC->funcs->DestroyGC) (pGC); + + /* leave it unwrapped */ +} + +static void +cwChangeClip(GCPtr pGC, int type, void * pvalue, int nrects) +{ + cwGCPtr pPriv = (cwGCPtr) dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pGC, pPriv); + + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + + FUNC_EPILOGUE(pGC, pPriv); +} + +static void +cwCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + cwGCPtr pPriv = (cwGCPtr) dixLookupPrivate(&pgcDst->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pgcDst, pPriv); + + (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc); + + FUNC_EPILOGUE(pgcDst, pPriv); +} + +static void +cwDestroyClip(GCPtr pGC) +{ + cwGCPtr pPriv = (cwGCPtr) dixLookupPrivate(&pGC->devPrivates, cwGCKey); + + FUNC_PROLOGUE(pGC, pPriv); + + (*pGC->funcs->DestroyClip) (pGC); + + FUNC_EPILOGUE(pGC, pPriv); +} + +/* + * Screen wrappers. + */ + +#define SCREEN_PROLOGUE(pScreen, field) \ + ((pScreen)->field = getCwScreen(pScreen)->field) + +#define SCREEN_EPILOGUE(pScreen, field, wrapper) do { \ + getCwScreen(pScreen)->field = (pScreen)->field; \ + (pScreen)->field = (wrapper); \ +} while (0) + +static Bool +cwCreateGC(GCPtr pGC) +{ + cwGCPtr pPriv = getCwGC(pGC); + ScreenPtr pScreen = pGC->pScreen; + Bool ret; + + SCREEN_PROLOGUE(pScreen, CreateGC); + + if ((ret = (*pScreen->CreateGC) (pGC))) + FUNC_EPILOGUE(pGC, pPriv); + + SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC); + + return ret; +} + +static void +cwGetImage(DrawablePtr pSrc, int x, int y, int w, int h, unsigned int format, + unsigned long planemask, char *pdstLine) +{ + ScreenPtr pScreen = pSrc->pScreen; + DrawablePtr pBackingDrawable; + int src_off_x, src_off_y; + + SCREEN_PROLOGUE(pScreen, GetImage); + + pBackingDrawable = cwGetBackingDrawable(pSrc, &src_off_x, &src_off_y); + + CW_OFFSET_XY_SRC(x, y); + + (*pScreen->GetImage) (pBackingDrawable, x, y, w, h, format, planemask, + pdstLine); + + SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage); +} + +static void +cwGetSpans(DrawablePtr pSrc, int wMax, DDXPointPtr ppt, int *pwidth, + int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pSrc->pScreen; + DrawablePtr pBackingDrawable; + int i; + int src_off_x, src_off_y; + + SCREEN_PROLOGUE(pScreen, GetSpans); + + pBackingDrawable = cwGetBackingDrawable(pSrc, &src_off_x, &src_off_y); + + for (i = 0; i < nspans; i++) + CW_OFFSET_XY_SRC(ppt[i].x, ppt[i].y); + + (*pScreen->GetSpans) (pBackingDrawable, wMax, ppt, pwidth, nspans, + pdstStart); + + SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans); +} + +static void +cwCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, CopyWindow); + + if (!cwDrawableIsRedirWindow((DrawablePtr) pWin)) { + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + } + else { + GCPtr pGC; + BoxPtr pExtents; + int x_off, y_off; + int dx, dy; + PixmapPtr pBackingPixmap; + RegionPtr pClip; + int src_x, src_y, dst_x, dst_y, w, h; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + + pExtents = RegionExtents(prgnSrc); + + pBackingPixmap = (PixmapPtr) cwGetBackingDrawable((DrawablePtr) pWin, + &x_off, &y_off); + + src_x = pExtents->x1 - pBackingPixmap->screen_x; + src_y = pExtents->y1 - pBackingPixmap->screen_y; + w = pExtents->x2 - pExtents->x1; + h = pExtents->y2 - pExtents->y1; + dst_x = src_x - dx; + dst_y = src_y - dy; + + /* Translate region (as required by API) */ + RegionTranslate(prgnSrc, -dx, -dy); + + pGC = GetScratchGC(pBackingPixmap->drawable.depth, pScreen); + /* + * Copy region to GC as clip, aligning as dest clip + */ + pClip = RegionCreate(NULL, 0); + RegionIntersect(pClip, &pWin->borderClip, prgnSrc); + RegionTranslate(pClip, + -pBackingPixmap->screen_x, -pBackingPixmap->screen_y); + + (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0); + + ValidateGC(&pBackingPixmap->drawable, pGC); + + (*pGC->ops->CopyArea) (&pBackingPixmap->drawable, + &pBackingPixmap->drawable, pGC, + src_x, src_y, w, h, dst_x, dst_y); + + (*pGC->funcs->DestroyClip) (pGC); + + FreeScratchGC(pGC); + } + + SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); +} + +static PixmapPtr +cwGetWindowPixmap(WindowPtr pWin) +{ + PixmapPtr pPixmap = getCwPixmap(pWin); + + if (!pPixmap) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, GetWindowPixmap); + if (pScreen->GetWindowPixmap) + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap); + } + return pPixmap; +} + +static void +cwSetWindowPixmap(WindowPtr pWindow, PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + + if (pPixmap == (*pScreen->GetScreenPixmap) (pScreen)) + pPixmap = NULL; + setCwPixmap(pWindow, pPixmap); +} + +/* Screen initialization/teardown */ +void +miInitializeCompositeWrapper(ScreenPtr pScreen) +{ + cwScreenPtr pScreenPriv; + Bool has_render = GetPictureScreenIfSet(pScreen) != NULL; + + if (!dixRegisterPrivateKey(&cwScreenKeyRec, PRIVATE_SCREEN, 0)) + return; + + if (!dixRegisterPrivateKey(&cwGCKeyRec, PRIVATE_GC, sizeof(cwGCRec))) + return; + + if (!dixRegisterPrivateKey(&cwWindowKeyRec, PRIVATE_WINDOW, 0)) + return; + + if (!dixRegisterPrivateKey(&cwPictureKeyRec, PRIVATE_PICTURE, 0)) + return; + + pScreenPriv = malloc(sizeof(cwScreenRec)); + if (!pScreenPriv) + return; + + dixSetPrivate(&pScreen->devPrivates, cwScreenKey, pScreenPriv); + + SCREEN_EPILOGUE(pScreen, CloseScreen, cwCloseScreen); + SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage); + SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans); + SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC); + SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow); + + SCREEN_EPILOGUE(pScreen, SetWindowPixmap, cwSetWindowPixmap); + SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap); + + if (has_render) + cwInitializeRender(pScreen); +} + +static Bool +cwCloseScreen(ScreenPtr pScreen) +{ + cwScreenPtr pScreenPriv; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + pScreenPriv = (cwScreenPtr) dixLookupPrivate(&pScreen->devPrivates, + cwScreenKey); + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->CreateGC = pScreenPriv->CreateGC; + pScreen->CopyWindow = pScreenPriv->CopyWindow; + + if (ps) + cwFiniRender(pScreen); + + free((void *) pScreenPriv); + + return (*pScreen->CloseScreen) (pScreen); +} diff --git a/miext/cw/cw.h b/miext/cw/cw.h new file mode 100644 index 000000000..9f880f7f5 --- /dev/null +++ b/miext/cw/cw.h @@ -0,0 +1,173 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "gcstruct.h" +#include "picturestr.h" +#include "privates.h" + +/* + * One of these structures is allocated per GC that gets used with a window with + * backing pixmap. + */ + +typedef struct { + GCPtr pBackingGC; /* Copy of the GC but with graphicsExposures + * set FALSE and the clientClip set to + * clip output to the valid regions of the + * backing pixmap. */ + unsigned long serialNumber; /* clientClip computed time */ + unsigned long stateChanges; /* changes in parent gc since last copy */ + GCOps *wrapOps; /* wrapped ops */ + GCFuncs *wrapFuncs; /* wrapped funcs */ +} cwGCRec, *cwGCPtr; + +extern _X_EXPORT DevPrivateKeyRec cwGCKeyRec; + +#define cwGCKey (&cwGCKeyRec) + +#define getCwGC(pGC) ((cwGCPtr)dixLookupPrivate(&(pGC)->devPrivates, cwGCKey)) +#define setCwGC(pGC,p) dixSetPrivate(&(pGC)->devPrivates, cwGCKey, p) + +/* + * One of these structures is allocated per Picture that gets used with a + * window with a backing pixmap + */ + +typedef struct { + PicturePtr pBackingPicture; + unsigned long serialNumber; + unsigned long stateChanges; +} cwPictureRec, *cwPicturePtr; + +extern _X_EXPORT DevPrivateKeyRec cwPictureKeyRec; + +#define cwPictureKey (&cwPictureKeyRec) + +#define getCwPicture(pPicture) (pPicture->pDrawable ? \ + (cwPicturePtr)dixLookupPrivate(&(pPicture)->devPrivates, cwPictureKey) : 0) +#define setCwPicture(pPicture,p) dixSetPrivate(&(pPicture)->devPrivates, cwPictureKey, p) + +extern _X_EXPORT DevPrivateKeyRec cwWindowKeyRec; + +#define cwWindowKey (&cwWindowKeyRec) + +#define cwWindowPrivate(pWin) dixLookupPrivate(&(pWin)->devPrivates, cwWindowKey) +#define getCwPixmap(pWindow) ((PixmapPtr) cwWindowPrivate(pWindow)) +#define setCwPixmap(pWindow,pPixmap) \ + dixSetPrivate(&(pWindow)->devPrivates, cwWindowKey, pPixmap) + +#define cwDrawableIsRedirWindow(pDraw) \ + ((pDraw)->type == DRAWABLE_WINDOW && \ + getCwPixmap((WindowPtr) (pDraw)) != NULL) + +typedef struct { + /* + * screen func wrappers + */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CreateGCProcPtr CreateGC; + + CopyWindowProcPtr CopyWindow; + + GetWindowPixmapProcPtr GetWindowPixmap; + SetWindowPixmapProcPtr SetWindowPixmap; + + DestroyPictureProcPtr DestroyPicture; + ChangePictureClipProcPtr ChangePictureClip; + DestroyPictureClipProcPtr DestroyPictureClip; + + ChangePictureProcPtr ChangePicture; + ValidatePictureProcPtr ValidatePicture; + + CompositeProcPtr Composite; + CompositeRectsProcPtr CompositeRects; + + TrapezoidsProcPtr Trapezoids; + TrianglesProcPtr Triangles; + + RasterizeTrapezoidProcPtr RasterizeTrapezoid; +} cwScreenRec, *cwScreenPtr; + +extern _X_EXPORT DevPrivateKeyRec cwScreenKeyRec; + +#define cwScreenKey (&cwScreenKeyRec) + +#define getCwScreen(pScreen) ((cwScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, cwScreenKey)) +#define setCwScreen(pScreen,p) dixSetPrivate(&(pScreen)->devPrivates, cwScreenKey, p) + +#define CW_OFFSET_XYPOINTS(ppt, npt) do { \ + DDXPointPtr _ppt = (DDXPointPtr)(ppt); \ + int _i; \ + for (_i = 0; _i < npt; _i++) { \ + _ppt[_i].x += dst_off_x; \ + _ppt[_i].y += dst_off_y; \ + } \ +} while (0) + +#define CW_OFFSET_RECTS(prect, nrect) do { \ + int _i; \ + for (_i = 0; _i < nrect; _i++) { \ + (prect)[_i].x += dst_off_x; \ + (prect)[_i].y += dst_off_y; \ + } \ +} while (0) + +#define CW_OFFSET_ARCS(parc, narc) do { \ + int _i; \ + for (_i = 0; _i < narc; _i++) { \ + (parc)[_i].x += dst_off_x; \ + (parc)[_i].y += dst_off_y; \ + } \ +} while (0) + +#define CW_OFFSET_XY_DST(x, y) do { \ + (x) = (x) + dst_off_x; \ + (y) = (y) + dst_off_y; \ +} while (0) + +#define CW_OFFSET_XY_SRC(x, y) do { \ + (x) = (x) + src_off_x; \ + (y) = (y) + src_off_y; \ +} while (0) + +/* cw.c */ +extern _X_EXPORT DrawablePtr + cwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off); + +/* cw_render.c */ + +extern _X_EXPORT void + cwInitializeRender(ScreenPtr pScreen); + +extern _X_EXPORT void + cwFiniRender(ScreenPtr pScreen); + +/* cw.c */ + +extern _X_EXPORT void + miInitializeCompositeWrapper(ScreenPtr pScreen); diff --git a/miext/cw/cw_ops.c b/miext/cw/cw_ops.c new file mode 100644 index 000000000..17e8d6fc6 --- /dev/null +++ b/miext/cw/cw_ops.c @@ -0,0 +1,477 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "gcstruct.h" +#include "pixmapstr.h" +#include "cw.h" +#include "mi.h" + +#define SETUP_BACKING_DST(_pDst, _pGC) \ + cwGCPtr pGCPrivate = getCwGC (_pGC); \ + int dst_off_x, dst_off_y; \ + DrawablePtr pBackingDst = cwGetBackingDrawable(pDst, &dst_off_x, \ + &dst_off_y); \ + GCPtr pBackingGC = pGCPrivate->pBackingGC ? pGCPrivate->pBackingGC : _pGC + +#define SETUP_BACKING_SRC(pSrc, pGC) \ + int src_off_x, src_off_y; \ + DrawablePtr pBackingSrc = cwGetBackingDrawable(pSrc, &src_off_x, \ + &src_off_y) + +#define PROLOGUE(pGC) do { \ + if (pBackingGC->serialNumber != pBackingDst->serialNumber) { \ + ValidateGC(pBackingDst, pBackingGC); \ + } \ + pGC->funcs = pGCPrivate->wrapFuncs;\ + pGC->ops = pGCPrivate->wrapOps;\ +} while (0) + +#define EPILOGUE(pGC) do { \ + pGCPrivate->wrapFuncs = (pGC)->funcs; \ + pGCPrivate->wrapOps = (pGC)->ops; \ + (pGC)->funcs = &cwGCFuncs; \ + (pGC)->ops = &cwGCOps; \ +} while (0) + +extern GCFuncs cwGCFuncs; + +/* + * GC ops -- wrap each GC operation with our own function + */ + +static void cwFillSpans(DrawablePtr pDst, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, int fSorted); +static void cwSetSpans(DrawablePtr pDst, GCPtr pGC, char *psrc, + DDXPointPtr ppt, int *pwidth, int nspans, int fSorted); +static void cwPutImage(DrawablePtr pDst, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, int format, + char *pBits); +static RegionPtr cwCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty); +static RegionPtr cwCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty, unsigned long plane); +static void cwPolyPoint(DrawablePtr pDst, GCPtr pGC, int mode, int npt, + xPoint * pptInit); +static void cwPolylines(DrawablePtr pDst, GCPtr pGC, int mode, int npt, + DDXPointPtr pptInit); +static void cwPolySegment(DrawablePtr pDst, GCPtr pGC, int nseg, + xSegment * pSegs); +static void cwPolyRectangle(DrawablePtr pDst, GCPtr pGC, + int nrects, xRectangle *pRects); +static void cwPolyArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc * parcs); +static void cwFillPolygon(DrawablePtr pDst, GCPtr pGC, int shape, int mode, + int count, DDXPointPtr pPts); +static void cwPolyFillRect(DrawablePtr pDst, GCPtr pGC, + int nrectFill, xRectangle *prectInit); +static void cwPolyFillArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc * parcs); +static int cwPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars); +static int cwPolyText16(DrawablePtr pDst, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void cwImageText8(DrawablePtr pDst, GCPtr pGC, int x, int y, + int count, char *chars); +static void cwImageText16(DrawablePtr pDst, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void cwImageGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, + unsigned int nglyph, CharInfoPtr * ppci, + void * pglyphBase); +static void cwPolyGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, + unsigned int nglyph, CharInfoPtr * ppci, + void * pglyphBase); +static void cwPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, + int w, int h, int x, int y); + +GCOps cwGCOps = { + cwFillSpans, + cwSetSpans, + cwPutImage, + cwCopyArea, + cwCopyPlane, + cwPolyPoint, + cwPolylines, + cwPolySegment, + cwPolyRectangle, + cwPolyArc, + cwFillPolygon, + cwPolyFillRect, + cwPolyFillArc, + cwPolyText8, + cwPolyText16, + cwImageText8, + cwImageText16, + cwImageGlyphBlt, + cwPolyGlyphBlt, + cwPushPixels +}; + +static void +cwFillSpans(DrawablePtr pDst, GCPtr pGC, int nspans, DDXPointPtr ppt, + int *pwidth, int fSorted) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XYPOINTS(ppt, nspans); + + (*pBackingGC->ops->FillSpans) (pBackingDst, pBackingGC, nspans, ppt, + pwidth, fSorted); + + EPILOGUE(pGC); +} + +static void +cwSetSpans(DrawablePtr pDst, GCPtr pGC, char *psrc, DDXPointPtr ppt, + int *pwidth, int nspans, int fSorted) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XYPOINTS(ppt, nspans); + + (*pBackingGC->ops->SetSpans) (pBackingDst, pBackingGC, psrc, ppt, pwidth, + nspans, fSorted); + + EPILOGUE(pGC); +} + +static void +cwPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, int w, int h, + int leftPad, int format, char *pBits) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->PutImage) (pBackingDst, pBackingGC, depth, x, y, w, h, + leftPad, format, pBits); + + EPILOGUE(pGC); +} + +static RegionPtr +cwCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty) +{ + int odstx, odsty; + int osrcx, osrcy; + + SETUP_BACKING_DST(pDst, pGC); + SETUP_BACKING_SRC(pSrc, pGC); + + PROLOGUE(pGC); + + odstx = dstx; + odsty = dsty; + osrcx = srcx; + osrcy = srcy; + CW_OFFSET_XY_DST(dstx, dsty); + CW_OFFSET_XY_SRC(srcx, srcy); + + (*pBackingGC->ops->CopyArea) (pBackingSrc, pBackingDst, + pBackingGC, srcx, srcy, w, h, dstx, dsty); + + EPILOGUE(pGC); + + return miHandleExposures(pSrc, pDst, pGC, + osrcx, osrcy, w, h, odstx, odsty/*, 0*/); +} + +static RegionPtr +cwCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty, unsigned long plane) +{ + int odstx, odsty; + int osrcx, osrcy; + + SETUP_BACKING_DST(pDst, pGC); + SETUP_BACKING_SRC(pSrc, pGC); + + PROLOGUE(pGC); + + odstx = dstx; + odsty = dsty; + osrcx = srcx; + osrcy = srcy; + CW_OFFSET_XY_DST(dstx, dsty); + CW_OFFSET_XY_SRC(srcx, srcy); + + (*pBackingGC->ops->CopyPlane) (pBackingSrc, pBackingDst, + pBackingGC, srcx, srcy, w, h, + dstx, dsty, plane); + + EPILOGUE(pGC); + + return miHandleExposures(pSrc, pDst, pGC, + osrcx, osrcy, w, h, odstx, odsty/*, plane*/); +} + +static void +cwPolyPoint(DrawablePtr pDst, GCPtr pGC, int mode, int npt, xPoint * ppt) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + if (mode == CoordModeOrigin) + CW_OFFSET_XYPOINTS(ppt, npt); + else + CW_OFFSET_XYPOINTS(ppt, 1); + + (*pBackingGC->ops->PolyPoint) (pBackingDst, pBackingGC, mode, npt, ppt); + + EPILOGUE(pGC); +} + +static void +cwPolylines(DrawablePtr pDst, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + if (mode == CoordModeOrigin) + CW_OFFSET_XYPOINTS(ppt, npt); + else + CW_OFFSET_XYPOINTS(ppt, 1); + + (*pBackingGC->ops->Polylines) (pBackingDst, pBackingGC, mode, npt, ppt); + + EPILOGUE(pGC); +} + +static void +cwPolySegment(DrawablePtr pDst, GCPtr pGC, int nseg, xSegment * pSegs) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XYPOINTS(pSegs, nseg * 2); + + (*pBackingGC->ops->PolySegment) (pBackingDst, pBackingGC, nseg, pSegs); + + EPILOGUE(pGC); +} + +static void +cwPolyRectangle(DrawablePtr pDst, GCPtr pGC, int nrects, xRectangle *pRects) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(pRects, nrects); + + (*pBackingGC->ops->PolyRectangle) (pBackingDst, pBackingGC, nrects, pRects); + + EPILOGUE(pGC); +} + +static void +cwPolyArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc * pArcs) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(pArcs, narcs); + + (*pBackingGC->ops->PolyArc) (pBackingDst, pBackingGC, narcs, pArcs); + + EPILOGUE(pGC); +} + +static void +cwFillPolygon(DrawablePtr pDst, GCPtr pGC, int shape, int mode, int npt, + DDXPointPtr ppt) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + if (mode == CoordModeOrigin) + CW_OFFSET_XYPOINTS(ppt, npt); + else + CW_OFFSET_XYPOINTS(ppt, 1); + + (*pBackingGC->ops->FillPolygon) (pBackingDst, pBackingGC, shape, mode, npt, + ppt); + + EPILOGUE(pGC); +} + +static void +cwPolyFillRect(DrawablePtr pDst, GCPtr pGC, int nrects, xRectangle *pRects) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(pRects, nrects); + + (*pBackingGC->ops->PolyFillRect) (pBackingDst, pBackingGC, nrects, pRects); + + EPILOGUE(pGC); +} + +static void +cwPolyFillArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc * parcs) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_RECTS(parcs, narcs); + + (*pBackingGC->ops->PolyFillArc) (pBackingDst, pBackingGC, narcs, parcs); + + EPILOGUE(pGC); +} + +static int +cwPolyText8(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, char *chars) +{ + int result; + + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + result = (*pBackingGC->ops->PolyText8) (pBackingDst, pBackingGC, x, y, + count, chars); + + EPILOGUE(pGC); + + return result; +} + +static int +cwPolyText16(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, + unsigned short *chars) +{ + int result; + + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + result = (*pBackingGC->ops->PolyText16) (pBackingDst, pBackingGC, x, y, + count, chars); + + EPILOGUE(pGC); + return result; +} + +static void +cwImageText8(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, char *chars) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->ImageText8) (pBackingDst, pBackingGC, x, y, count, + chars); + + EPILOGUE(pGC); +} + +static void +cwImageText16(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, + unsigned short *chars) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->ImageText16) (pBackingDst, pBackingGC, x, y, count, + chars); + + EPILOGUE(pGC); +} + +static void +cwImageGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->ImageGlyphBlt) (pBackingDst, pBackingGC, x, y, nglyph, + ppci, pglyphBase); + + EPILOGUE(pGC); +} + +static void +cwPolyGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, void * pglyphBase) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->PolyGlyphBlt) (pBackingDst, pBackingGC, x, y, nglyph, + ppci, pglyphBase); + + EPILOGUE(pGC); +} + +static void +cwPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, int w, int h, + int x, int y) +{ + SETUP_BACKING_DST(pDst, pGC); + + PROLOGUE(pGC); + + CW_OFFSET_XY_DST(x, y); + + (*pBackingGC->ops->PushPixels) (pBackingGC, pBitMap, pBackingDst, w, h, + x, y); + + EPILOGUE(pGC); +} diff --git a/miext/cw/cw_render.c b/miext/cw/cw_render.c new file mode 100644 index 000000000..059d686fb --- /dev/null +++ b/miext/cw/cw_render.c @@ -0,0 +1,383 @@ +/* + * Copyright © 2004 Eric Anholt + * + * 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 Eric Anholt not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Eric Anholt makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "gcstruct.h" +#include "windowstr.h" +#include "cw.h" + +#define cwPsDecl(pScreen) \ + PictureScreenPtr ps = GetPictureScreen (pScreen); \ + cwScreenPtr pCwScreen = getCwScreen (pScreen) + +#define cwPicturePrivate \ + cwPicturePtr pPicturePrivate = getCwPicture(pPicture) + +#define cwSrcPictureDecl \ + int src_picture_x_off, src_picture_y_off; \ + PicturePtr pBackingSrcPicture = cwGetBackingPicture(pSrcPicture, \ + &src_picture_x_off,\ + &src_picture_y_off) + +#define cwDstPictureDecl \ + int dst_picture_x_off, dst_picture_y_off; \ + PicturePtr pBackingDstPicture = cwGetBackingPicture(pDstPicture, \ + &dst_picture_x_off,\ + &dst_picture_y_off) + +#define cwMskPictureDecl \ + int msk_picture_x_off = 0, msk_picture_y_off = 0; \ + PicturePtr pBackingMskPicture = (!pMskPicture ? 0 : \ + cwGetBackingPicture(pMskPicture, \ + &msk_picture_x_off,\ + &msk_picture_y_off)) + +#define cwPsUnwrap(elt) { \ + ps->elt = pCwScreen->elt; \ +} + +#define cwPsWrap(elt,func) { \ + pCwScreen->elt = ps->elt; \ + ps->elt = func; \ +} + +static cwPicturePtr +cwCreatePicturePrivate(PicturePtr pPicture) +{ + WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; + PixmapPtr pPixmap = getCwPixmap(pWindow); + int error; + cwPicturePtr pPicturePrivate; + + pPicturePrivate = malloc(sizeof(cwPictureRec)); + if (!pPicturePrivate) + return NULL; + + pPicturePrivate->pBackingPicture = CreatePicture(0, &pPixmap->drawable, + pPicture->pFormat, + 0, 0, serverClient, + &error); + if (!pPicturePrivate->pBackingPicture) { + free(pPicturePrivate); + return NULL; + } + + /* + * Ensure that this serial number does not match the window's + */ + pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber; + pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1; + + setCwPicture(pPicture, pPicturePrivate); + + return pPicturePrivate; +} + +static void +cwDestroyPicturePrivate(PicturePtr pPicture) +{ + cwPicturePrivate; + + if (pPicturePrivate) { + if (pPicturePrivate->pBackingPicture) + FreePicture(pPicturePrivate->pBackingPicture, 0); + free(pPicturePrivate); + setCwPicture(pPicture, NULL); + } +} + +static PicturePtr +cwGetBackingPicture(PicturePtr pPicture, int *x_off, int *y_off) +{ + cwPicturePrivate; + + if (pPicturePrivate) { + DrawablePtr pDrawable = pPicture->pDrawable; + WindowPtr pWindow = (WindowPtr) pDrawable; + PixmapPtr pPixmap = getCwPixmap(pWindow); + + *x_off = pDrawable->x - pPixmap->screen_x; + *y_off = pDrawable->y - pPixmap->screen_y; + + return pPicturePrivate->pBackingPicture; + } + else { + *x_off = *y_off = 0; + return pPicture; + } +} + +static void +cwDestroyPicture(PicturePtr pPicture) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + + cwPsDecl(pScreen); + + cwPsUnwrap(DestroyPicture); + cwDestroyPicturePrivate(pPicture); + (*ps->DestroyPicture) (pPicture); + cwPsWrap(DestroyPicture, cwDestroyPicture); +} + +static void +cwChangePicture(PicturePtr pPicture, Mask mask) +{ + ScreenPtr pScreen = pPicture->pDrawable->pScreen; + + cwPsDecl(pScreen); + cwPicturePtr pPicturePrivate = getCwPicture(pPicture); + + cwPsUnwrap(ChangePicture); + (*ps->ChangePicture) (pPicture, mask); + if (pPicturePrivate) + pPicturePrivate->stateChanges |= mask; + cwPsWrap(ChangePicture, cwChangePicture); +} + +static void +cwValidatePicture(PicturePtr pPicture, Mask mask) +{ + DrawablePtr pDrawable = pPicture->pDrawable; + ScreenPtr pScreen = pDrawable->pScreen; + + cwPsDecl(pScreen); + cwPicturePrivate; + + cwPsUnwrap(ValidatePicture); + + /* + * Must call ValidatePicture to ensure pPicture->pCompositeClip is valid + */ + (*ps->ValidatePicture) (pPicture, mask); + + if (!cwDrawableIsRedirWindow(pDrawable)) { + if (pPicturePrivate) + cwDestroyPicturePrivate(pPicture); + } + else { + PicturePtr pBackingPicture; + DrawablePtr pBackingDrawable; + int x_off, y_off; + + pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); + + if (pPicturePrivate && + pPicturePrivate->pBackingPicture->pDrawable != pBackingDrawable) { + cwDestroyPicturePrivate(pPicture); + pPicturePrivate = 0; + } + + if (!pPicturePrivate) { + pPicturePrivate = cwCreatePicturePrivate(pPicture); + if (!pPicturePrivate) { + cwPsWrap(ValidatePicture, cwValidatePicture); + return; + } + } + + pBackingPicture = pPicturePrivate->pBackingPicture; + + /* + * Always copy transform and filters because there's no + * indication of when they've changed + */ + SetPictureTransform(pBackingPicture, pPicture->transform); + + if (pBackingPicture->filter != pPicture->filter || + pPicture->filter_nparams > 0) { + char *filter = PictureGetFilterName(pPicture->filter); + + SetPictureFilter(pBackingPicture, + filter, strlen(filter), + pPicture->filter_params, pPicture->filter_nparams); + } + + pPicturePrivate->stateChanges |= mask; + + if (pPicturePrivate->serialNumber != pDrawable->serialNumber || + (pPicturePrivate-> + stateChanges & (CPClipXOrigin | CPClipYOrigin | CPClipMask))) { + SetPictureClipRegion(pBackingPicture, x_off - pDrawable->x, + y_off - pDrawable->y, + pPicture->pCompositeClip); + + pPicturePrivate->serialNumber = pDrawable->serialNumber; + pPicturePrivate->stateChanges &= + ~(CPClipXOrigin | CPClipYOrigin | CPClipMask); + } + + CopyPicture(pPicture, pPicturePrivate->stateChanges, pBackingPicture); + + ValidatePicture(pBackingPicture); + } + cwPsWrap(ValidatePicture, cwValidatePicture); +} + +static void +cwComposite(CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pMskPicture, + PicturePtr pDstPicture, + INT16 xSrc, + INT16 ySrc, + INT16 xMsk, + INT16 yMsk, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwMskPictureDecl; + cwDstPictureDecl; + + cwPsUnwrap(Composite); + (*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, + pBackingDstPicture, xSrc + src_picture_x_off, + ySrc + src_picture_y_off, xMsk + msk_picture_x_off, + yMsk + msk_picture_y_off, xDst + dst_picture_x_off, + yDst + dst_picture_y_off, width, height); + cwPsWrap(Composite, cwComposite); +} + +static void +cwCompositeRects(CARD8 op, + PicturePtr pDstPicture, + xRenderColor * color, int nRect, xRectangle *rects) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + + cwPsDecl(pScreen); + cwDstPictureDecl; + int i; + + cwPsUnwrap(CompositeRects); + for (i = 0; i < nRect; i++) { + rects[i].x += dst_picture_x_off; + rects[i].y += dst_picture_y_off; + } + (*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects); + cwPsWrap(CompositeRects, cwCompositeRects); +} + +static void +cwTrapezoids(CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + int i; + + cwPsUnwrap(Trapezoids); + if (dst_picture_x_off || dst_picture_y_off) { + for (i = 0; i < ntrap; i++) { + traps[i].top += dst_picture_y_off << 16; + traps[i].bottom += dst_picture_y_off << 16; + traps[i].left.p1.x += dst_picture_x_off << 16; + traps[i].left.p1.y += dst_picture_y_off << 16; + traps[i].left.p2.x += dst_picture_x_off << 16; + traps[i].left.p2.y += dst_picture_y_off << 16; + traps[i].right.p1.x += dst_picture_x_off << 16; + traps[i].right.p1.y += dst_picture_y_off << 16; + traps[i].right.p2.x += dst_picture_x_off << 16; + traps[i].right.p2.y += dst_picture_y_off << 16; + } + } + (*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + ntrap, traps); + cwPsWrap(Trapezoids, cwTrapezoids); +} + +static void +cwTriangles(CARD8 op, + PicturePtr pSrcPicture, + PicturePtr pDstPicture, + PictFormatPtr maskFormat, + INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris) +{ + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + + cwPsDecl(pScreen); + cwSrcPictureDecl; + cwDstPictureDecl; + int i; + + cwPsUnwrap(Triangles); + if (dst_picture_x_off || dst_picture_y_off) { + for (i = 0; i < ntri; i++) { + tris[i].p1.x += dst_picture_x_off << 16; + tris[i].p1.y += dst_picture_y_off << 16; + tris[i].p2.x += dst_picture_x_off << 16; + tris[i].p2.y += dst_picture_y_off << 16; + tris[i].p3.x += dst_picture_x_off << 16; + tris[i].p3.y += dst_picture_y_off << 16; + } + } + (*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, + xSrc + src_picture_x_off, ySrc + src_picture_y_off, + ntri, tris); + cwPsWrap(Triangles, cwTriangles); +} + +void +cwInitializeRender(ScreenPtr pScreen) +{ + cwPsDecl(pScreen); + + cwPsWrap(DestroyPicture, cwDestroyPicture); + cwPsWrap(ChangePicture, cwChangePicture); + cwPsWrap(ValidatePicture, cwValidatePicture); + cwPsWrap(Composite, cwComposite); + cwPsWrap(CompositeRects, cwCompositeRects); + cwPsWrap(Trapezoids, cwTrapezoids); + cwPsWrap(Triangles, cwTriangles); + /* There is no need to wrap AddTraps as far as we can tell. AddTraps can + * only be done on alpha-only pictures, and we won't be getting + * alpha-only window pictures, so there's no need to translate. + */ +} + +void +cwFiniRender(ScreenPtr pScreen) +{ + cwPsDecl(pScreen); + + cwPsUnwrap(DestroyPicture); + cwPsUnwrap(ChangePicture); + cwPsUnwrap(ValidatePicture); + cwPsUnwrap(Composite); + cwPsUnwrap(CompositeRects); + cwPsUnwrap(Trapezoids); + cwPsUnwrap(Triangles); +} diff --git a/miext/damage/damage.c b/miext/damage/damage.c index f3ae4ebbc..c2b9d01a6 100644 --- a/miext/damage/damage.c +++ b/miext/damage/damage.c @@ -40,6 +40,9 @@ #include "gcstruct.h" #include "damage.h" #include "damagestr.h" +#ifdef COMPOSITE +#include "cw.h" +#endif #define wrap(priv, real, mem, func) {\ priv->mem = real->mem; \ diff --git a/render/picture.c b/render/picture.c index d08f30a8a..98f7afa3a 100644 --- a/render/picture.c +++ b/render/picture.c @@ -279,6 +279,12 @@ PictureCreateDefaultFormats(ScreenPtr pScreen, int *nformatp) addFormat(formats, &nformats, PICT_a4b4g4r4, pDepth->depth); } break; + case 24: + if (pDepth->depth >= 24) { + addFormat(formats, &nformats, PICT_r8g8b8, pDepth->depth); + addFormat(formats, &nformats, PICT_b8g8r8, pDepth->depth); + } + break; case 32: if (pDepth->depth >= 24) { addFormat(formats, &nformats, PICT_x8r8g8b8, pDepth->depth); @@ -1355,6 +1361,77 @@ SetPictureTransform(PicturePtr pPicture, PictTransform * transform) return Success; } +void +CopyPicture(PicturePtr pSrc, Mask mask, PicturePtr pDst) +{ + PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen); + Mask origMask = mask; + + pDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pDst->stateChanges |= mask; + + while (mask) { + Mask bit = lowbit(mask); + + switch (bit) { + case CPRepeat: + pDst->repeat = pSrc->repeat; + pDst->repeatType = pSrc->repeatType; + break; + case CPAlphaMap: + if (pSrc->alphaMap && + pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP) + pSrc->alphaMap->refcnt++; + if (pDst->alphaMap) + FreePicture((void *) pDst->alphaMap, (XID) 0); + pDst->alphaMap = pSrc->alphaMap; + break; + case CPAlphaXOrigin: + pDst->alphaOrigin.x = pSrc->alphaOrigin.x; + break; + case CPAlphaYOrigin: + pDst->alphaOrigin.y = pSrc->alphaOrigin.y; + break; + case CPClipXOrigin: + pDst->clipOrigin.x = pSrc->clipOrigin.x; + break; + case CPClipYOrigin: + pDst->clipOrigin.y = pSrc->clipOrigin.y; + break; + case CPClipMask: + if (!pSrc->clientClip) { + (*ps->ChangePictureClip) (pDst, CT_NONE, NULL, 0); + } + else { + RegionPtr clientClip; + RegionPtr srcClientClip = (RegionPtr) pSrc->clientClip; + + clientClip = RegionCreate(RegionExtents(srcClientClip), + RegionNumRects(srcClientClip)); + (*ps->ChangePictureClip) (pDst, CT_REGION, clientClip, 0); + } + break; + case CPGraphicsExposure: + pDst->graphicsExposures = pSrc->graphicsExposures; + break; + case CPPolyEdge: + pDst->polyEdge = pSrc->polyEdge; + break; + case CPPolyMode: + pDst->polyMode = pSrc->polyMode; + break; + case CPDither: + break; + case CPComponentAlpha: + pDst->componentAlpha = pSrc->componentAlpha; + break; + } + mask &= ~bit; + } + + (*ps->ChangePicture) (pDst, origMask); +} + static void ValidateOnePicture(PicturePtr pPicture) { diff --git a/render/picturestr.h b/render/picturestr.h index dd25a272d..0076d431d 100644 --- a/render/picturestr.h +++ b/render/picturestr.h @@ -449,6 +449,9 @@ SetPictureClipRegion(PicturePtr pPicture, extern _X_EXPORT int SetPictureTransform(PicturePtr pPicture, PictTransform * transform); +extern _X_EXPORT void + CopyPicture(PicturePtr pSrc, Mask mask, PicturePtr pDst); + extern _X_EXPORT void ValidatePicture(PicturePtr pPicture);