summaryrefslogtreecommitdiff
path: root/src/amd_gx_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/amd_gx_accel.c')
-rw-r--r--src/amd_gx_accel.c2212
1 files changed, 2212 insertions, 0 deletions
diff --git a/src/amd_gx_accel.c b/src/amd_gx_accel.c
new file mode 100644
index 0000000..5f6337e
--- /dev/null
+++ b/src/amd_gx_accel.c
@@ -0,0 +1,2212 @@
+/* Copyright (c) 2003-2005 Advanced Micro Devices, Inc.
+ *
+ * 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 THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * */
+
+/*
+ * File Contents: This file is consists of main Xfree acceleration supported
+ * routines like solid fill used here.
+ *
+ * Project: Geode Xfree Frame buffer device driver.
+ * */
+
+/* #undef OPT_ACCEL */
+
+/* Xfree86 header files */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vgaHW.h"
+#include "xf86.h"
+#include "xf86_ansic.h"
+#include "xaalocal.h"
+#include "xf86fbman.h"
+#include "miline.h"
+#include "xf86_libc.h"
+#include "xaarop.h"
+#include "servermd.h"
+#include "picture.h"
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86_ansic.h"
+#include "xf86Pci.h"
+#include "xf86PciInfo.h"
+#include "amd.h"
+#include "gfx_defs.h"
+#include "gfx_regs.h"
+
+#undef ulong
+typedef unsigned long ulong;
+
+#undef uint
+typedef unsigned int uint;
+
+#undef ushort
+typedef unsigned short ushort;
+
+#undef uchar
+typedef unsigned char uchar;
+
+#if DEBUGLVL>0
+extern FILE *zdfp;
+
+#if DEBUGTIM>0
+#ifdef NO_RDTSC
+#define DBLOG(n,s...) \
+ do { \
+ if((DEBUGLVL)>=(n)) { \
+ long secs,usecs; \
+ getsecs(&secs,&usecs); \
+ fprintf(zdfp,"%d,%d ",secs,usecs); \
+ fprintf(zdfp,s); \
+ } \
+ } while(0)
+#else /* ifdef No_RDTSC */
+#define tsc(n) __asm__ __volatile__ ( \
+ " rdtsc" \
+ : "=a" (((int*)(&(n)))[0]), "=d" (((int*)(&(n)))[1]) \
+ : )
+#define DBLOG(n,s...) \
+ do { \
+ if((DEBUGLVL)>=(n)) { \
+ long long t; \
+ tsc(t); \
+ fprintf(zdfp,"%lld ",t); \
+ fprintf(zdfp,s); \
+ } \
+ } while(0)
+#endif /* ifdef No_RDTSC */
+#else /* if DEBUFTIM */
+#define DBLOG(n,s...) \
+ do { \
+ if((DEBUGLVL)>=(n)) \
+ fprintf(zdfp,s); \
+ } while(0)
+#endif /* if DEBUGTIM */
+#else /* if DEBUGLVL > 0 */
+#define DBLOG(n,s...) \
+ do {} while(0)
+#endif /* if DEBUGLVL > 0 */
+
+#define CALC_FBOFFSET(x, y) \
+ (((ulong)(y) << gu2_yshift) | ((ulong)(x) << gu2_xshift))
+#define FBADDR(x,y) \
+ ((unsigned char *)pGeode->FBBase + CALC_FBOFFSET(x, y))
+
+#define OS_UDELAY 0
+#if OS_UDELAY > 0
+#define OS_USLEEP(usec) usleep(usec);
+#else
+#define OS_USLEEP(usec)
+#endif
+
+#ifdef OPT_ACCEL
+unsigned int BPP;
+unsigned int BLT_MODE, VEC_MODE;
+unsigned int ACCEL_STRIDE;
+
+#define GU2_WAIT_PENDING while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_PENDING)
+#define GU2_WAIT_BUSY while(READ_GP32(MGP_BLT_STATUS) & MGP_BS_BLT_BUSY)
+#endif
+
+#define HOOK(fn) localRecPtr->fn = GX##fn
+
+/* static storage declarations */
+
+typedef struct sGBltBox
+{
+ ulong x, y;
+ ulong w, h;
+ ulong color;
+ int bpp, transparent;
+} GBltBox;
+
+#if GX_SCANLINE_SUPPORT
+static GBltBox giwr;
+#endif
+#if GX_CPU2SCREXP_SUPPORT
+static GBltBox gc2s;
+#endif
+#if GX_CLREXP_8X8_PAT_SUPPORT
+static ulong *gc8x8p;
+#endif
+
+#if GX_DASH_LINE_SUPPORT
+typedef struct sGDashLine
+{
+ ulong pat[2];
+ int len;
+ int fg;
+ int bg;
+} GDashLine;
+
+static GDashLine gdln;
+#endif
+
+static unsigned int gu2_xshift, gu2_yshift;
+static XAAInfoRecPtr localRecPtr;
+
+/* pat 0xF0 */
+/* src 0xCC */
+/* dst 0xAA */
+
+/* (src FUNC dst) */
+
+static const int SDfn[16] = {
+ 0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE,
+ 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF
+};
+
+/* ((src FUNC dst) AND pat-mask) OR (dst AND (NOT pat-mask)) */
+
+static const int SDfn_PM[16] = {
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA
+};
+
+/* (pat FUNC dst) */
+
+static int PDfn[16] = {
+ 0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA,
+ 0x05, 0xA5, 0x55, 0xF5, 0x0F, 0xAF, 0x5F, 0xFF
+};
+
+/* ((pat FUNC dst) AND src-mask) OR (dst AND (NOT src-mask)) */
+
+static int PDfn_SM[16] = {
+ 0x22, 0xA2, 0x62, 0xE2, 0x2A, 0xAA, 0x6A, 0xEA,
+ 0x26, 0xA6, 0x66, 0xE6, 0x2E, 0xAE, 0x6E, 0xEE
+};
+
+#define move0(d,s,n) \
+ __asm__ __volatile__( \
+ " rep; movsl\n" \
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
+ : "0" (n), "1" (s), "2" (d) \
+ : "memory")
+
+#define move1(d,s,n) \
+ __asm__ __volatile__( \
+ " rep; movsl\n" \
+ " movsb\n" \
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
+ : "0" (n), "1" (s), "2" (d) \
+ : "memory")
+
+#define move2(d,s,n) \
+ __asm__ __volatile__( \
+ " rep; movsl\n" \
+ " movsw\n" \
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
+ : "0" (n), "1" (s), "2" (d) \
+ : "memory")
+
+#define move3(d,s,n) \
+ __asm__ __volatile__( \
+ " rep; movsl\n" \
+ " movsw\n" \
+ " movsb\n" \
+ : "=&c" (d0), "=&S" (d1), "=&D" (d2) \
+ : "0" (n), "1" (s), "2" (d) \
+ : "memory")
+
+static void
+amd_memory_to_screen_blt(unsigned long src, unsigned long dst,
+ unsigned long sp, unsigned long dp, long w, long h, int bpp)
+{
+ int d0, d1, d2;
+ int n = w * (bpp >> 3);
+ int m = n >> 2;
+
+ switch (n & 3) {
+ case 0:
+ while (--h >= 0) {
+ move0(dst, src, m);
+ src += sp;
+ dst += dp;
+ }
+ break;
+ case 1:
+ while (--h >= 0) {
+ move1(dst, src, m);
+ src += sp;
+ dst += dp;
+ }
+ break;
+ case 2:
+ while (--h >= 0) {
+ move2(dst, src, m);
+ src += sp;
+ dst += dp;
+ }
+ break;
+ case 3:
+ while (--h >= 0) {
+ move3(dst, src, m);
+ src += sp;
+ dst += dp;
+ }
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ * GXAccelSync.
+ *
+ * Description :This function is called to synchronize with the graphics
+ * engine and it waits the graphic engine is idle. This is
+ * required before allowing direct access to the framebuffer.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+void
+GXAccelSync(ScrnInfoPtr pScrni)
+{
+ DBLOG(3, "GXAccelSync()\n");
+#ifndef OPT_ACCEL
+ gfx_wait_until_idle();
+#else
+ GU2_WAIT_BUSY;
+#endif
+}
+
+#if GX_FILL_RECT_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForSolidFill.
+ *
+ * Description :The SetupFor and Subsequent SolidFill(Rect) provide
+ * filling rectangular areas of the screen with a
+ * foreground color.
+ *
+ * Parameters.
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * color int foreground fill color
+ * rop int unmapped raster op
+ * planemask uint -1 (fill) or pattern data
+ *
+ * Returns :none
+ *--------------------------------------------------------------------------*/
+static void
+GXSetupForSolidFill(ScrnInfoPtr pScrni,
+ int color, int rop, unsigned int planemask)
+{
+ DBLOG(2, "GXSetupForSolidFill(%#x,%#x,%#x)\n", color, rop, planemask);
+ rop &= 0x0F;
+#ifndef OPT_ACCEL
+ gfx_set_solid_pattern(planemask);
+ gfx_set_solid_source(color);
+ gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+#else
+ {
+ unsigned int ROP =
+ BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
+ if (((ROP ^ (ROP >> 1)) & 0x55) != 0)
+ BLT_MODE |= MGP_BM_DST_REQ;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, planemask);
+ WRITE_GP32(MGP_SRC_COLOR_FG, color);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentSolidFillRect.
+ *
+ * Description :see GXSetupForSolidFill.
+ *
+ * Parameters.
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x int destination x offset
+ * y int destination y offset
+ * w int fill area width (pixels)
+ * h int fill area height (pixels)
+ *
+ * Returns :none
+ *
+ * Sample application uses:
+ * - Window backgrounds.
+ * - pull down highlighting.
+ * - x11perf: rectangle tests (-rect500).
+ * - x11perf: fill trapezoid tests (-trap100).
+ * - x11perf: horizontal line segments (-hseg500).
+ *----------------------------------------------------------------------------*/
+static void
+GXSubsequentSolidFillRect(ScrnInfoPtr pScrni, int x, int y, int w, int h)
+{
+ DBLOG(2, "GXSubsequentSolidFillRect() at %d,%d %dx%d\n", x, y, w, h);
+#ifndef OPT_ACCEL
+ gfx_pattern_fill(x, y, w, h);
+#else
+ {
+ unsigned int offset = CALC_FBOFFSET(x, y);
+ unsigned int size = (w << 16) | h;
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, offset);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
+ }
+#endif
+}
+
+#endif /* if GX_FILL_RECT_SUPPORT */
+
+#if GX_CLREXP_8X8_PAT_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForColor8x8PatternFill
+ *
+ * Description :8x8 color pattern data is 64 pixels of full color data
+ * stored linearly in offscreen video memory. These patterns
+ * are useful as a substitute for 8x8 mono patterns when tiling,
+ * doing opaque stipples, or regular stipples.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * patx int x offset to pattern data
+ * paty int y offset to pattern data
+ * rop int unmapped raster operation
+ * planemask uint -1 (copy) or pattern data
+ * trans_color int -1 (copy) or transparent color (not enabled)
+ * trans color only supported on source channel
+ * or in monochrome pattern channel
+ *
+ * Returns :none.
+ *
+ *---------------------------------------------------------------------------*/
+
+static void
+GXSetupForColor8x8PatternFill(ScrnInfoPtr pScrni, int patx, int paty, int rop,
+ uint planemask, int trans_color)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ DBLOG(2, "GXSetupForColor8x8PatternFill() pat %#x,%#x rop %#x %#x %#x\n",
+ patx, paty, rop, planemask, trans_color);
+ rop &= 0x0F;
+ gc8x8p = (unsigned long *)FBADDR(patx, paty);
+ /* gfx_set_solid_pattern is needed to clear src/pat transparency */
+ gfx_set_solid_pattern(0);
+ gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
+ (gfx_set_solid_source(planemask), PDfn_SM[rop]));
+ gfx2_set_source_stride(pGeode->AccelPitch);
+ gfx2_set_destination_stride(pGeode->AccelPitch);
+ if (trans_color == -1)
+ gfx2_set_source_transparency(0, 0);
+ else
+ gfx2_set_source_transparency(trans_color, ~0);
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentColor8x8PatternFillRect
+ *
+ * Description :see GXSetupForColor8x8PatternFill.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * patx int pattern phase x offset
+ * paty int pattern phase y offset
+ * x int destination x offset
+ * y int destination y offset
+ * w int fill area width (pixels)
+ * h int fill area height (pixels)
+ *
+ * Returns :none
+ *
+ * Sample application uses:
+ * - Patterned desktops
+ * - x11perf: stippled rectangle tests (-srect500).
+ * - x11perf: opaque stippled rectangle tests (-osrect500).
+ *--------------------------------------------------------------------------*/
+static void
+GXSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrni, int patx, int paty,
+ int x, int y, int w, int h)
+{
+ DBLOG(2,
+ "GXSubsequentColor8x8PatternFillRect() patxy %d,%d at %d,%d %dsx%d\n",
+ patx, paty, x, y, w, h);
+ gfx2_set_pattern_origin(patx, paty);
+ gfx2_color_pattern_fill(CALC_FBOFFSET(x, y), w, h, gc8x8p);
+}
+
+/* GX_CLREXP_8X8_PAT_SUPPORT */
+#endif
+
+#if GX_MONO_8X8_PAT_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForMono8x8PatternFill
+ *
+ * Description :8x8 mono pattern data is 64 bits of color expansion data
+ * with ones indicating the foreground color and zeros
+ * indicating the background color. These patterns are
+ * useful when tiling, doing opaque stipples, or regular
+ * stipples.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * patx int x offset to pattern data
+ * paty int y offset to pattern data
+ * fg int foreground color
+ * bg int -1 (transparent) or background color
+ * rop int unmapped raster operation
+ * planemask uint -1 (copy) or pattern data
+ *
+ * Returns :none.
+ *
+ * Comments :none.
+ *
+ *--------------------------------------------------------------------------*/
+static void
+GXSetupForMono8x8PatternFill(ScrnInfoPtr pScrni, int patx, int paty,
+ int fg, int bg, int rop, uint planemask)
+{
+ DBLOG(2,
+ "GXSetupForMono8x8PatternFill() pat %#x,%#x fg %#x bg %#x %#x %#x\n",
+ patx, paty, fg, bg, rop, planemask);
+ rop &= 0x0F;
+#ifndef OPT_ACCEL
+ gfx_set_mono_pattern(bg, fg, patx, paty, bg == -1 ? 1 : 0);
+ gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
+ (gfx_set_solid_source(planemask), PDfn_SM[rop]));
+#else
+ {
+ unsigned int ROP = BPP |
+ (bg ==
+ -1 ? MGP_RM_PAT_MONO | MGP_RM_PAT_TRANS : MGP_RM_PAT_MONO) |
+ (planemask == ~0U ? PDfn[rop] : PDfn_SM[rop]);
+ BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
+ if (((ROP ^ (ROP >> 1)) & 0x55) != 0)
+ BLT_MODE |= MGP_BM_DST_REQ;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_SRC_COLOR_FG, planemask);
+ WRITE_GP32(MGP_PAT_COLOR_0, bg);
+ WRITE_GP32(MGP_PAT_COLOR_1, fg);
+ WRITE_GP32(MGP_PAT_DATA_0, patx);
+ WRITE_GP32(MGP_PAT_DATA_1, paty);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentMono8x8PatternFillRect
+ *
+ * Description :see GXSetupForMono8x8PatternFill
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * patx int pattern phase x offset
+ * paty int pattern phase y offset
+ * x int destination x offset
+ * y int destination y offset
+ * w int fill area width (pixels)
+ * h int fill area height (pixels)
+
+ * Returns :none
+ *
+ * Sample application uses:
+ * - Patterned desktops
+ * - x11perf: stippled rectangle tests (-srect500).
+ * - x11perf: opaque stippled rectangle tests (-osrect500).
+ *--------------------------------------------------------------------------*/
+static void
+GXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrni, int patx, int paty,
+ int x, int y, int w, int h)
+{
+ DBLOG(2,
+ "GXSubsequentMono8x8PatternFillRect() pat %#x,%#x at %d,%d %dx%d\n",
+ patx, paty, x, y, w, h);
+#ifndef OPT_ACCEL
+ gfx_pattern_fill(x, y, w, h);
+#else
+ {
+ unsigned int offset =
+ CALC_FBOFFSET(x, y) | ((x & 7) << 26) | ((y & 7) << 29);
+ unsigned int size = (w << 16) | h;
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, offset);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
+ }
+#endif
+}
+
+#endif /* GX_MONO_8X8_PAT_SUPPORT */
+
+#if GX_SCR2SCRCPY_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForScreenToScreenCopy
+ *
+ * Description :SetupFor and Subsequent ScreenToScreenCopy functions
+ * provide an interface for copying rectangular areas from
+ * video memory to video memory.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * xdir int x copy direction (up/dn)
+ * ydir int y copy direction (up/dn)
+ * rop int unmapped raster operation
+ * planemask uint -1 (copy) or pattern data
+ * trans_color int -1 (copy) or transparent color
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+static void
+GXSetupForScreenToScreenCopy(ScrnInfoPtr pScrni, int xdir, int ydir, int rop,
+ uint planemask, int trans_color)
+{
+ DBLOG(2, "GXSetupForScreenToScreenCopy() xd%d yd%d rop %#x %#x %#x\n",
+ xdir, ydir, rop, planemask, trans_color);
+ rop &= 0x0F;
+#ifndef OPT_ACCEL
+ {
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ gfx_set_solid_pattern(planemask);
+ /* transparency is a parameter to set_rop, but set...pattern clears
+ * transparency */
+ if (trans_color == -1)
+ gfx2_set_source_transparency(0, 0);
+ else
+ gfx2_set_source_transparency(trans_color, ~0);
+ gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ gfx2_set_source_stride(pGeode->AccelPitch);
+ gfx2_set_destination_stride(pGeode->AccelPitch);
+ }
+#else
+ {
+ unsigned int ROP =
+ BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ if (trans_color != -1)
+ ROP |= MGP_RM_SRC_TRANS;
+ BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, planemask);
+ WRITE_GP32(MGP_SRC_COLOR_FG, trans_color);
+ WRITE_GP32(MGP_SRC_COLOR_BG, ~0);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsquentScreenToScreenCopy
+ *
+ * Description :see GXSetupForScreenToScreenCopy.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x1 int source x offset
+ * y1 int source y offset
+ * x2 int destination x offset
+ * y2 int destination y offset
+ * w int copy area width (pixels)
+ * h int copy area height (pixels)
+ *
+ * Returns :none
+ *
+ * Sample application uses (non-transparent):
+ * - Moving windows.
+ * - x11perf: scroll tests (-scroll500).
+ * - x11perf: copy from window to window (-copywinwin500).
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentScreenToScreenCopy(ScrnInfoPtr pScrni,
+ int x1, int y1, int x2, int y2, int w, int h)
+{
+ DBLOG(2, "GXSubsequentScreenToScreenCopy() from %d,%d to %d,%d %dx%d\n",
+ x1, y1, x2, y2, w, h);
+#ifndef OPT_ACCEL
+ {
+ int flags = 0;
+
+ if (x2 > x1)
+ flags |= 1;
+ if (y2 > y1)
+ flags |= 2;
+ gfx2_screen_to_screen_blt(CALC_FBOFFSET(x1, y1), CALC_FBOFFSET(x2,
+ y2), w, h, flags);
+ }
+#else
+ {
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ unsigned int src = CALC_FBOFFSET(x1, y1);
+ unsigned int dst = CALC_FBOFFSET(x2, y2);
+ unsigned int size = (w << 16) | h;
+ unsigned int blt_mode = BLT_MODE;
+
+ if (x2 > x1) {
+ int n = (w << gu2_xshift) - 1;
+
+ src += n;
+ dst += n;
+ blt_mode |= MGP_BM_NEG_XDIR;
+ }
+ if (y2 > y1) {
+ int n = (h - 1) * pGeode->AccelPitch;
+
+ src += n;
+ dst += n;
+ blt_mode |= MGP_BM_NEG_YDIR;
+ }
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_SRC_OFFSET, src);
+ WRITE_GP32(MGP_DST_OFFSET, dst);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP16(MGP_BLT_MODE, blt_mode);
+ }
+#endif
+}
+
+#endif /* if GX_SCR2SCRCPY_SUPPORT */
+
+#if GX_SCANLINE_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForScanlineImageWrite
+ *
+ * Description :SetupFor/Subsequent ScanlineImageWrite and ImageWriteScanline
+ * transfer full color pixel data from system memory to video
+ * memory. This is useful for dealing with alignment issues and
+ * performing raster ops on the data.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * rop int unmapped raster operation
+ * planemask uint -1 (copy) or pattern data
+ * bpp int bits per pixel (unused)
+ * depth int color depth (unused)
+ *
+ * Returns :none
+ *
+ * x11perf -putimage10
+ * x11perf -putimage100
+ * x11perf -putimage500
+ *----------------------------------------------------------------------------
+ */
+static void
+GXSetupForScanlineImageWrite(ScrnInfoPtr pScrni, int rop, uint planemask,
+ int trans_color, int bpp, int depth)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ DBLOG(2, "GXSetupForScanlineImageWrite() rop %#x %#x %#x %d %d\n",
+ rop, planemask, trans_color, bpp, depth);
+ rop &= 0x0F;
+ /* transparency is a parameter to set_rop, but set...pattern clears
+ * transparency */
+ gfx_set_solid_pattern(planemask);
+ if (trans_color == -1)
+ gfx2_set_source_transparency(0, 0);
+ else
+ gfx2_set_source_transparency(trans_color, ~0);
+ gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ gfx2_set_source_stride(pGeode->AccelPitch);
+ gfx2_set_destination_stride(pGeode->AccelPitch);
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentScanlineImageWriteRect
+ *
+ * Description : see GXSetupForScanlineImageWrite.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x int destination x offset
+ * y int destination y offset
+ * w int copy area width (pixels)
+ * h int copy area height (pixels)
+ * skipleft int x margin (pixels) to skip (not enabled)
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrni,
+ int x, int y, int w, int h, int skipleft)
+{
+ DBLOG(2, "GXSubsequentScanlineImageWriteRect() rop %d,%d %dx%d %d\n", x,
+ y, w, h, skipleft);
+ giwr.x = x;
+ giwr.y = y;
+ giwr.w = w;
+ giwr.h = h;
+#if !GX_USE_OFFSCRN_MEM
+#if !GX_ONE_LINE_AT_A_TIME
+ GXAccelSync(pScrni);
+#endif
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsquentImageWriteScanline
+ *
+ * Description : see GXSetupForScanlineImageWrite.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * bufno int scanline number in write group
+ *
+ * Returns :none
+ *
+ * Sample application uses (non-transparent):
+ * - Moving windows.
+ * - x11perf: scroll tests (-scroll500).
+ * - x11perf: copy from window to window (-copywinwin500).
+ *
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentImageWriteScanline(ScrnInfoPtr pScrni, int bufno)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+#if !GX_USE_OFFSCRN_MEM
+ unsigned long offset;
+#endif
+
+#if GX_ONE_LINE_AT_A_TIME
+ DBLOG(3, "GXSubsequentImageWriteScanline() %d\n", bufno);
+#if !GX_USE_OFFSCRN_MEM
+ offset = pGeode->AccelImageWriteBuffers[bufno] - pGeode->FBBase;
+ gfx2_screen_to_screen_blt(offset, CALC_FBOFFSET(giwr.x, giwr.y), giwr.w,
+ 1, 0);
+#else /* if !GX_USE_OFFSCRN_MEM */
+ gfx2_color_bitmap_to_screen_blt(0, 0, CALC_FBOFFSET(giwr.x, giwr.y),
+ giwr.w, 1, pGeode->AccelImageWriteBuffers[bufno], pGeode->AccelPitch);
+#endif /* if !GX_USE_OFFSCRN_MEM */
+ ++giwr.y;
+#else /* if GX_ONE_LINE_AT_A_TIME */
+ int blt_height;
+
+ DBLOG(3, "GXSubsequentImageWriteScanline() %d\n", bufno);
+
+ if ((blt_height = pGeode->NoOfImgBuffers) > giwr.h)
+ blt_height = giwr.h;
+ if (++bufno < blt_height)
+ return;
+#if !GX_USE_OFFSCRN_MEM
+ offset = pGeode->AccelImageWriteBuffers[0] - pGeode->FBBase;
+ gfx2_screen_to_screen_blt(offset, CALC_FBOFFSET(giwr.x, giwr.y), giwr.w,
+ blt_height, 0);
+ GXAccelSync(pScrni);
+#else /* if !GX_USE_OFFSCRN_MEM */
+ gfx2_color_bitmap_to_screen_blt(0, 0, CALC_FBOFFSET(giwr.x, giwr.y),
+ giwr.w, blt_height, pGeode->AccelImageWriteBuffers[0],
+ pGeode->AccelPitch);
+#endif /* if !GX_USE_OFFSCRN_MEM */
+ giwr.h -= blt_height;
+ giwr.y += blt_height;
+#endif /* if GX_ONE_LINE_AT_A_TIME */
+}
+#endif /* GX_SCANLINE_SUPPORT */
+
+#if GX_CPU2SCREXP_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForScanlineCPUToScreenColorExpandFill
+ *
+ * Description :SetupFor/Subsequent CPUToScreenColorExpandFill and
+ * ColorExpandScanline routines provide an interface for
+ * doing expansion blits from source patterns stored in
+ * system memory.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * fg int foreground color
+ * bg int -1 (transparent) or background color
+ * rop int unmapped raster operation
+ * planemask uint -1 (copy) or pattern data
+ *
+ * Returns :none.
+ *---------------------------------------------------------------------------*/
+
+static void
+GXSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrni,
+ int fg, int bg, int rop, uint planemask)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ ulong srcpitch;
+
+ DBLOG(2,
+ "GXSetupForScanlineCPUToScreenColorExpandFill() fg %#x bg %#x "
+ "rop %#x %#x\n", fg, bg, rop, planemask);
+ rop &= 0x0F;
+ srcpitch = ((pGeode->AccelPitch + 31) >> 5) << 2;
+#ifndef OPT_ACCEL
+ gfx_set_solid_pattern(planemask);
+ gfx_set_mono_source(bg, fg, bg == -1 ? 1 : 0);
+ gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ gfx2_set_source_stride(srcpitch);
+ gfx2_set_destination_stride(pGeode->AccelPitch);
+#else
+ {
+ unsigned int stride = (srcpitch << 16) | pGeode->AccelPitch;
+ unsigned int ROP =
+ BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ if (bg == -1)
+ ROP |= MGP_RM_SRC_TRANS;
+ BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
+ MGP_BM_SRC_MONO | MGP_BM_SRC_FB | MGP_BM_DST_REQ :
+ MGP_BM_SRC_MONO | MGP_BM_SRC_FB;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, planemask);
+ WRITE_GP32(MGP_SRC_COLOR_BG, bg);
+ WRITE_GP32(MGP_SRC_COLOR_FG, fg);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, stride);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentScanlineCPUToScreenColorExpandFill
+ *
+ Description :see GXSetupForScanlineCPUToScreenColorExpandFill
+ *
+ * Parameters:
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x int destination x offset
+ * y int destination y offset
+ * w int fill area width (pixels)
+ * h int fill area height (pixels)
+ *
+ * Returns :none
+ *
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrni,
+ int x, int y, int w, int h, int skipleft)
+{
+ DBLOG(2,
+ "GXSubsequentScanlineCPUToScreenColorExpandFill() %d,%d %dx%d %d\n",
+ x, y, w, h, skipleft);
+ gc2s.x = x;
+ gc2s.y = y;
+ gc2s.w = w;
+ gc2s.h = h;
+#ifdef OPT_ACCEL
+ {
+#if GX_ONE_LINE_AT_A_TIME
+ unsigned int size = (gc2s.w << 16) | 1;
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+#else
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+ unsigned int src =
+ pGeode->AccelColorExpandBuffers[0] - pGeode->FBBase;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_SRC_OFFSET, src);
+#endif
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentColorExpandScanline
+ *
+ * Description :see GXSetupForScanlineCPUToScreenColorExpandFill
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * bufno int scanline number in write group
+ *
+ * Returns :none
+ *----------------------------------------------------------------------------
+ */
+static void
+GXSubsequentColorExpandScanline(ScrnInfoPtr pScrni, int bufno)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ DBLOG(3, "GXSubsequentColorExpandScanline() %d\n", bufno);
+#ifndef OPT_ACCEL
+ {
+#if GX_ONE_LINE_AT_A_TIME
+ ulong offset =
+ pGeode->AccelColorExpandBuffers[bufno] - pGeode->FBBase;
+ gfx2_mono_expand_blt(offset, 0, 0, CALC_FBOFFSET(gc2s.x, gc2s.y),
+ gc2s.w, 1, 0);
+ ++gc2s.y;
+#else /* if GX_ONE_LINE_AT_A_TIME */
+ ulong srcpitch;
+ int blt_height;
+
+ if ((blt_height = pGeode->NoOfImgBuffers) > gc2s.h)
+ blt_height = gc2s.h;
+ if (++bufno < blt_height)
+ return;
+
+ /* convert from bits to dwords */
+ srcpitch = ((pGeode->AccelPitch + 31) >> 5) << 2;
+ gfx2_mono_bitmap_to_screen_blt(0, 0, CALC_FBOFFSET(gc2s.x, gc2s.y),
+ gc2s.w, blt_height, pGeode->AccelColorExpandBuffers[0], srcpitch);
+ gc2s.h -= blt_height;
+ gc2s.y += blt_height;
+#endif /* if GX_ONE_LINE_AT_A_TIME */
+ }
+#else /* ifndef OPT_ACCEL */
+ {
+#if GX_ONE_LINE_AT_A_TIME
+ unsigned int src =
+ pGeode->AccelColorExpandBuffers[bufno] - pGeode->FBBase;
+ unsigned int dst = CALC_FBOFFSET(gc2s.x, gc2s.y);
+
+ ++gc2s.y;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_SRC_OFFSET, src);
+ WRITE_GP32(MGP_DST_OFFSET, dst);
+ WRITE_GP16(MGP_BLT_MODE, BLT_MODE);
+#else /* if GX_ONE_LINE_AT_A_TIME */
+ unsigned int dst, size;
+ int blt_height;
+
+ GU2_WAIT_BUSY;
+ if ((blt_height = pGeode->NoOfImgBuffers) > gc2s.h)
+ blt_height = gc2s.h;
+ if (++bufno < blt_height)
+ return;
+ dst = CALC_FBOFFSET(gc2s.x, gc2s.y);
+ size = (gc2s.w << 16) | blt_height;
+ gc2s.h -= blt_height;
+ gc2s.y += blt_height;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, dst);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP16(MGP_BLT_MODE, BLT_MODE);
+#endif /* if GX_ONE_LINE_AT_A_TIME */
+ }
+#endif /* ifndef OPT_ACCEL */
+}
+#endif /* GX_CPU2SCREXP_SUPPORT */
+
+#if GX_SCR2SCREXP_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForScreenToScreenColorExpandFill
+ *
+ * Description :SetupFor/Subsequent ScreenToScreenColorExpandFill and
+ * ColorExpandScanline routines provide an interface for
+ * doing expansion blits from source patterns stored in
+ * video memory.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * fg int foreground color
+ * bg int -1 (transparent) or background color
+ * rop int unmapped raster operation
+ * planemask uint -1 (copy) or pattern data
+ *
+ * Returns :none.
+ *---------------------------------------------------------------------------*/
+
+static void
+GXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrni, int fg, int bg,
+ int rop, uint planemask)
+{
+ DBLOG(2,
+ "GXSetupForScreenToScreenColorExpandFill() fg %#x bg %#x "
+ "rop %#x %#x\n", fg, bg, rop, planemask);
+ rop &= 0x0F;
+#ifndef OPT_ACCEL
+ {
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ gfx_set_solid_pattern(planemask);
+ gfx_set_mono_source(bg, fg, bg == -1 ? 1 : 0);
+ gfx_set_raster_operation(planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ gfx2_set_source_stride(pGeode->AccelPitch);
+ gfx2_set_destination_stride(pGeode->AccelPitch);
+ }
+#else
+ {
+ unsigned int ROP =
+ BPP | (planemask == ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ if (bg == -1)
+ ROP |= MGP_RM_SRC_TRANS;
+ BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
+ MGP_BM_SRC_MONO | MGP_BM_SRC_FB | MGP_BM_DST_REQ :
+ MGP_BM_SRC_MONO | MGP_BM_SRC_FB;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, planemask);
+ WRITE_GP32(MGP_SRC_COLOR_BG, bg);
+ WRITE_GP32(MGP_SRC_COLOR_FG, fg);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * GXSubsequentScreenToScreenColorExpandFill
+ *
+ * Description :see GXSetupForScreenToScreenColorExpandFill
+ *
+ * Parameters:
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x int destination x offset
+ * y int destination y offset
+ * w int fill area width (pixels)
+ * h int fill area height (pixels)
+ * offset int initial x offset
+ *
+ * Returns :none
+ *
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrni,
+ int x, int y, int w, int h, int srcx, int srcy, int offset)
+{
+ DBLOG(2,
+ "GXSubsequentScreenToScreenColorExpandFill() %d,%d %dx%d %d,%d %d\n",
+ x, y, w, h, srcx, srcy, offset);
+#ifndef OPT_ACCEL
+ gfx2_mono_expand_blt(CALC_FBOFFSET(srcx, srcy), offset, 0,
+ CALC_FBOFFSET(x, y), w, h, 0);
+#else
+ {
+ unsigned int src = (CALC_FBOFFSET(srcx,
+ srcy) + (offset >> 3)) | ((offset & 7) << 26);
+ unsigned int dst = CALC_FBOFFSET(x, y);
+ unsigned int size = (w << 16) | h;
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_SRC_OFFSET, src);
+ WRITE_GP32(MGP_DST_OFFSET, dst);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP16(MGP_BLT_MODE, BLT_MODE);
+ }
+#endif
+}
+#endif /* GX_SCR2SCREXP_SUPPORT */
+
+#define VM_MAJOR_DEC 0
+#define VM_MINOR_DEC 0
+
+static unsigned short vmode[] = {
+ VM_X_MAJOR | VM_MAJOR_INC | VM_MINOR_INC,
+ /* !XDECREASING !YDECREASING !YMAJOR */
+ VM_Y_MAJOR | VM_MAJOR_INC | VM_MINOR_INC,
+ /* !XDECREASING !YDECREASING YMAJOR */
+ VM_X_MAJOR | VM_MAJOR_INC | VM_MINOR_DEC,
+ /* !XDECREASING YDECREASING !YMAJOR */
+ VM_Y_MAJOR | VM_MAJOR_DEC | VM_MINOR_INC,
+ /* !XDECREASING YDECREASING YMAJOR */
+ VM_X_MAJOR | VM_MAJOR_DEC | VM_MINOR_INC,
+ /* XDECREASING !YDECREASING !YMAJOR */
+ VM_Y_MAJOR | VM_MAJOR_INC | VM_MINOR_DEC,
+ /* XDECREASING !YDECREASING YMAJOR */
+ VM_X_MAJOR | VM_MAJOR_DEC | VM_MINOR_DEC,
+ /* XDECREASING YDECREASING !YMAJOR */
+ VM_Y_MAJOR | VM_MAJOR_DEC | VM_MINOR_DEC,
+ /* XDECREASING YDECREASING YMAJOR */
+};
+
+#if GX_BRES_LINE_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForSolidLine
+ *
+ * Description :SetupForSolidLine and Subsequent HorVertLine TwoPointLine
+ * BresenhamLine provides an interface for drawing thin
+ * solid lines.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * color int foreground fill color
+ * rop int unmapped raster op
+ * planemask uint -1 (fill) or pattern data (not enabled)
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+static void
+GXSetupForSolidLine(ScrnInfoPtr pScrni, int color, int rop, uint planemask)
+{
+ DBLOG(2, "GXSetupForSolidLine() %#x %#x %#x\n", color, rop, planemask);
+ rop &= 0x0F;
+#ifndef OPT_ACCEL
+ gfx_set_solid_pattern(color);
+ gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
+ (gfx_set_solid_source(planemask), PDfn_SM[rop]));
+#else
+ {
+ unsigned int ROP =
+ BPP | (planemask == ~0U ? PDfn[rop] : PDfn_SM[rop]);
+ BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
+ VEC_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ? ((BLT_MODE |=
+ MGP_BM_DST_REQ), MGP_VM_DST_REQ) : 0;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, color);
+ WRITE_GP32(MGP_SRC_COLOR_FG, planemask);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, ACCEL_STRIDE);
+ }
+#endif
+}
+
+/*---------------------------------------------------------------------------
+ * GXSubsequentSolidBresenhamLine
+ *
+ * Description :see GXSetupForSolidLine
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x1 int destination x offset
+ * y1 int destination y offset
+ * absmaj int Bresenman absolute major
+ * absmin int Bresenman absolute minor
+ * err int Bresenman initial error term
+ * len int length of the vector (pixels)
+ * octant int specifies sign and magnitude relationships
+ * used to determine axis of magor rendering
+ * and direction of vector progress.
+ *
+ * Returns :none
+ *
+ * - Window outlines on window move.
+ * - x11perf: line segments (-line500).
+ * - x11perf: line segments (-seg500).
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentSolidBresenhamLine(ScrnInfoPtr pScrni, int x1, int y1,
+ int absmaj, int absmin, int err, int len, int octant)
+{
+ long axial, diagn;
+
+ DBLOG(2, "GXSubsequentSolidBresenhamLine() %d,%d %d %d, %d %d, %d\n",
+ x1, y1, absmaj, absmin, err, len, octant);
+ if (len <= 0)
+ return;
+ axial = absmin;
+ err += axial;
+ diagn = absmin - absmaj;
+#ifndef OPT_ACCEL
+ gfx_bresenham_line(x1, y1, len, err, axial, diagn, vmode[octant]);
+#else
+ {
+ unsigned int offset = CALC_FBOFFSET(x1, y1);
+ unsigned int vec_err = (axial << 16) | (unsigned short)diagn;
+ unsigned int vec_len = (len << 16) | (unsigned short)err;
+ unsigned int vec_mode = VEC_MODE | vmode[octant];
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, offset);
+ WRITE_GP32(MGP_VEC_ERR, vec_err);
+ WRITE_GP32(MGP_VEC_LEN, vec_len);
+ WRITE_GP32(MGP_VECTOR_MODE, vec_mode);
+ }
+#endif
+}
+
+/*---------------------------------------------------------------------------
+ * GXSubsequentSolidTwoPointLine
+ *
+ * Description :see GXSetupForSolidLine
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x0 int destination x start offset
+ * y0 int destination y start offset
+ * x1 int destination x end offset
+ * y1 int destination y end offset
+ * flags int OMIT_LAST, dont draw last pixel (not used)
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrni, int x0, int y0,
+ int x1, int y1, int flags)
+{
+ long dx, dy, dmaj, dmin, octant, bias;
+ long axial, diagn, err, len;
+
+ DBLOG(2, "GXSubsequentSolidTwoPointLine() %d,%d %d,%d, %#x\n",
+ x0, y0, x1, y1, flags);
+
+ if ((dx = x1 - x0) < 0)
+ dx = -dx;
+ if ((dy = y1 - y0) < 0)
+ dy = -dy;
+ if (dy >= dx) {
+ dmaj = dy;
+ dmin = dx;
+ octant = YMAJOR;
+ } else {
+ dmaj = dx;
+ dmin = dy;
+ octant = 0;
+ }
+ len = dmaj;
+ if ((flags & OMIT_LAST) == 0)
+ ++len;
+ if (len <= 0)
+ return;
+ if (x1 < x0)
+ octant |= XDECREASING;
+ if (y1 < y0)
+ octant |= YDECREASING;
+
+ axial = dmin << 1;
+ bias = miGetZeroLineBias(pScrni->pScreen);
+ err = axial - dmaj - ((bias >> octant) & 1);
+ diagn = (dmin - dmaj) << 1;
+
+#ifndef OPT_ACCEL
+ gfx_bresenham_line(x0, y0, len, err, axial, diagn, vmode[octant]);
+#else
+ {
+ unsigned int offset = CALC_FBOFFSET(x0, y0);
+ unsigned int vec_err = (axial << 16) | (unsigned short)diagn;
+ unsigned int vec_len = (len << 16) | (unsigned short)err;
+ unsigned int vec_mode = VEC_MODE | vmode[octant];
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, offset);
+ WRITE_GP32(MGP_VEC_ERR, vec_err);
+ WRITE_GP32(MGP_VEC_LEN, vec_len);
+ WRITE_GP32(MGP_VECTOR_MODE, vec_mode);
+ }
+#endif
+}
+
+/*---------------------------------------------------------------------------
+ * GXSubsequentSolidHorVertLine
+ *
+ * Description :see GXSetupForSolidLine
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x int destination x offset
+ * y int destination y offset
+ * len int length of the vector (pixels)
+ * dir int DEGREES_270 or DEGREES_0 line direction
+ *
+ * Sample application uses:
+ * - Window outlines on window move.
+ * - x11perf: line segments (-hseg500).
+ * - x11perf: line segments (-vseg500).
+ *---------------------------------------------------------------------------
+ */
+static void
+GXSubsequentSolidHorVertLine(ScrnInfoPtr pScrni,
+ int x, int y, int len, int dir)
+{
+ DBLOG(2, "GXSubsequentHorVertLine() %d,%d %d %d\n", x, y, len, dir);
+#ifndef OPT_ACCEL
+ if (dir == DEGREES_0)
+ gfx_pattern_fill(x, y, len, 1);
+ else
+ gfx_pattern_fill(x, y, 1, len);
+#else
+ {
+ unsigned int offset = CALC_FBOFFSET(x, y);
+ unsigned int size =
+ dir == DEGREES_0 ? (len << 16) | 1 : (1 << 16) | len;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, offset);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
+ }
+#endif
+}
+#endif /* GX_BRES_LINE_SUPPORT */
+
+#if GX_DASH_LINE_SUPPORT
+/*----------------------------------------------------------------------------
+ * GXSetupForDashedLine
+ *
+ * Description :SetupForDashedLine and Subsequent TwoPointLine
+ * BresenhamLine provides an interface for drawing thin
+ * dashed lines.
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * fg int foreground fill color
+ * bg int -1 (transp) or background fill color
+ * rop int unmapped raster op
+ * planemask uint -1 (fill) or pattern data (not enabled)
+ * length int pattern length (bits)
+ * pattern uchar* dash pattern mask
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+static void
+GXSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
+ unsigned int planemask, int length, unsigned char *pattern)
+{
+ int i, l, n, m;
+ CARD32 pat = *pattern;
+ CARD32 pat8x8[2];
+
+ if (length <= 0)
+ return;
+ i = l = m = 0;
+ while (i < 2) {
+ m |= pat >> l;
+ l += length;
+ if ((n = l - 32) >= 0) {
+ pat8x8[i++] = m;
+ m = pat << (length - n);
+ l = n;
+ }
+ }
+ gdln.pat[0] = pat8x8[0];
+ gdln.pat[1] = pat8x8[1];
+ gdln.len = length;
+ gdln.fg = fg;
+ gdln.bg = bg;
+ rop &= 0x0F;
+ gfx_set_solid_pattern(0);
+ gfx_set_raster_operation(planemask == ~0U ? PDfn[rop] :
+ (gfx_set_solid_source(planemask), PDfn_SM[rop]));
+}
+
+/*---------------------------------------------------------------------------
+ * GXSubsequentDashedBresenhamLine
+ *
+ * Description: This function is used to render a vector using the
+ * specified bresenham parameters.
+ *
+ * Parameters:
+ * pScrni: Screen handler pointer having screen information.
+ * x1: Specifies the starting x position
+ * y1: Specifies starting y possition
+ * absmaj: Specfies the Bresenman absolute major.
+ * absmin: Specfies the Bresenman absolute minor.
+ * err: Specifies the bresenham err term.
+ * len: Specifies the length of the vector interms of pixels.
+ * octant: not used in this function,may be added for standard
+ * interface.
+ *
+ * Returns: none
+ *
+ * Comments: none
+ *
+ * Sample application uses:
+ * - Window outlines on window move.
+ * - x11perf: line segments (-line500).
+ * - x11perf: line segments (-seg500).
+ *----------------------------------------------------------------------------
+ */
+static void
+GXSubsequentDashedBresenhamLine(ScrnInfoPtr pScrni,
+ int x1, int y1, int absmaj, int absmin,
+ int err, int len, int octant, int phase)
+{
+ int i, n;
+ int axial, diagn;
+ int trans = (gdln.bg == -1);
+ unsigned long pat8x8[2];
+
+ DEBUGMSG(0, (0, 0, "BLine %d, %d, %d, %d, %d, %d, %d\n",
+ x1, y1, absmaj, absmin, err, len, octant));
+ i = phase >= 32 ? (phase -= 32, 1) : 0;
+ n = 32 - phase;
+ pat8x8[0] =
+ ((gdln.pat[i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[1 - i] << n);
+ pat8x8[1] =
+ ((gdln.pat[1 - i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[i] << n);
+ axial = absmin;
+ err += axial;
+ diagn = absmin - absmaj;
+ gfx_set_mono_pattern(gdln.bg, gdln.fg, pat8x8[0], pat8x8[1], trans);
+ gfx2_set_pattern_origin(x1, y1);
+ gfx2_bresenham_line(CALC_FBOFFSET(x1, y1), len, err, axial, diagn,
+ vmode[octant]);
+}
+
+/*---------------------------------------------------------------------------
+ * GXSubsequentDashedTwoPointLine
+ *
+ * Description :see GXSetupForDashedLine
+ *
+ * Arg Type Comment
+ * pScrni ScrnInfoPtr pointer to Screeen info
+ * x0 int destination x start offset
+ * y0 int destination y start offset
+ * x1 int destination x end offset
+ * y1 int destination y end offset
+ * flags int OMIT_LAST, dont draw last pixel (not used)
+ * phase int initial pattern offset at x1,y1
+ *
+ * Returns :none
+ *---------------------------------------------------------------------------*/
+static void
+GXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrni, int x0, int y0,
+ int x1, int y1, int flags, int phase)
+{
+ int i, n;
+ long dx, dy, dmaj, dmin, octant, bias;
+ long axial, diagn, err, len, pat8x8[2];
+
+ DBLOG(2, "GXSubsequentDashedTwoPointLine() %d,%d %d,%d, %#x %d\n",
+ x0, y0, x1, y1, flags, phase);
+
+ i = phase >= 32 ? (phase -= 32, 1) : 0;
+ n = 32 - phase;
+ pat8x8[0] =
+ ((gdln.pat[i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[1 - i] << n);
+ pat8x8[1] =
+ ((gdln.pat[1 - i] >> phase) & ((1UL << n) - 1)) | (gdln.pat[i] << n);
+
+ if ((dx = x1 - x0) < 0)
+ dx = -dx;
+ if ((dy = y1 - y0) < 0)
+ dy = -dy;
+ if (dy >= dx) {
+ dmaj = dy;
+ dmin = dx;
+ octant = YMAJOR;
+ } else {
+ dmaj = dx;
+ dmin = dy;
+ octant = 0;
+ }
+ len = dmaj;
+ if ((flags & OMIT_LAST) == 0)
+ ++len;
+ if (len <= 0)
+ return;
+ if (x1 < x0)
+ octant |= XDECREASING;
+ if (y1 < y0)
+ octant |= YDECREASING;
+
+ axial = dmin << 1;
+ bias = miGetZeroLineBias(pScrni->pScreen);
+ err = axial - dmaj - ((bias >> octant) & 1);
+ diagn = (dmin - dmaj) << 1;
+
+ gfx2_set_pattern_origin(x0, y0);
+ gfx2_bresenham_line(CALC_FBOFFSET(x0, y0), len, err, axial, diagn,
+ vmode[octant]);
+
+}
+#endif /* GX_DASH_LINE_SUPPORT */
+
+#if GX_WRITE_PIXMAP_SUPPORT
+static void
+GXWritePixmap(ScrnInfoPtr pScrni, int x, int y, int w, int h,
+ unsigned char *src, int srcwidth, int rop, unsigned int planemask,
+ int trans, int bpp, int depth)
+{
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+ DBLOG(2, "GXWritePixmap() %d,%d %dx%d, s%#x sp%d %#x %#x %#x %d %d\n",
+ x, y, w, h, src, srcwidth, rop, planemask, trans, bpp, depth);
+ if (bpp == pScrni->bitsPerPixel) {
+ rop &= 0x0F;
+ if (rop == GXcopy && trans == -1) {
+ gfx_wait_until_idle();
+ amd_memory_to_screen_blt((unsigned long)src,
+ (unsigned long)FBADDR(x, y), srcwidth, pGeode->AccelPitch, w,
+ h, bpp);
+ } else {
+ gfx_set_solid_pattern(planemask);
+ gfx_set_raster_operation(planemask ==
+ ~0U ? SDfn[rop] : SDfn_PM[rop]);
+ if (trans != -1)
+ gfx_color_bitmap_to_screen_xblt(0, 0, x, y, w, h, src,
+ srcwidth, trans);
+ else
+ gfx_color_bitmap_to_screen_blt(0, 0, x, y, w, h, src,
+ srcwidth);
+ SET_SYNC_FLAG(pGeode->AccelInfoRec);
+ }
+ } else
+ pGeode->WritePixmap(pScrni, x, y, w, h, src, srcwidth, rop, planemask,
+ trans, bpp, depth);
+}
+#endif /* if GX_WRITE_PIXMAP_SUPPORT */
+
+#if XF86EXA
+#define GEODEPTR_FROM_PIXMAP(x) \
+ GEODEPTR(xf86Screens[(x)->drawable.pScreen->myNum])
+#define GEODEPTR_FROM_SCREEN(x) \
+ GEODEPTR(xf86Screens[(x)->myNum])
+#define GEODEPTR_FROM_PICTURE(x) \
+ GEODEPTR(xf86Screens[(x)->pDrawable->pScreen->myNum])
+
+static void
+amd_gx_exa_WaitMarker(ScreenPtr pScreen, int Marker)
+{
+ GU2_WAIT_BUSY;
+}
+
+static void
+amd_gx_exa_Done(PixmapPtr p)
+{
+}
+
+static Bool
+amd_gx_exa_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
+ char *src, int src_pitch)
+{
+ char *dst = pDst->devPrivate.ptr;
+ int dst_pitch = exaGetPixmapPitch(pDst);
+ int bpp = pDst->drawable.bitsPerPixel;
+
+ dst += y * dst_pitch + x * (bpp >> 3);
+ GU2_WAIT_BUSY;
+ amd_memory_to_screen_blt((unsigned long)src, (unsigned long)dst,
+ src_pitch, dst_pitch, w, h, bpp);
+ return TRUE;
+}
+
+static Bool
+amd_gx_exa_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
+ char *dst, int dst_pitch)
+{
+ char *src = pSrc->devPrivate.ptr;
+ int src_pitch = exaGetPixmapPitch(pSrc);
+ int bpp = pSrc->drawable.bitsPerPixel;
+
+ src += y * src_pitch + x * (bpp >> 3);
+ GU2_WAIT_BUSY;
+ amd_memory_to_screen_blt((unsigned long)src, (unsigned long)dst,
+ src_pitch, dst_pitch, w, h, bpp);
+ return TRUE;
+}
+
+/* Solid */
+
+static Bool
+amd_gx_exa_PrepareSolid(PixmapPtr pxMap, int alu, Pixel planemask, Pixel fg)
+{
+ DBLOG(2, "amd_gx_exa_PrepareSolid(%#x,%#x,%#x)\n", alu, planemask, fg);
+ int dstPitch = exaGetPixmapPitch(pxMap);
+ unsigned int ROP = BPP | (planemask == ~0U ? SDfn[alu] : SDfn_PM[alu]);
+
+ BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0;
+ if (((ROP ^ (ROP >> 1)) & 0x55) != 0)
+ BLT_MODE |= MGP_BM_DST_REQ;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, planemask);
+ WRITE_GP32(MGP_SRC_COLOR_FG, fg);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, dstPitch);
+ return TRUE;
+}
+
+static void
+amd_gx_exa_Solid(PixmapPtr pxMap, int x1, int y1, int x2, int y2)
+{
+ DBLOG(2, "amd_gx_exa_Solid() at %d,%d %d,%d\n", x1, y1, x2, y2);
+ int bpp = (pxMap->drawable.bitsPerPixel + 7) / 8;
+ int pitch = exaGetPixmapPitch(pxMap);
+ unsigned int offset = exaGetPixmapOffset(pxMap) + pitch * y1 + bpp * x1;
+ unsigned int size = ((x2 - x1) << 16) | (y2 - y1);
+
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_DST_OFFSET, offset);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP32(MGP_BLT_MODE, BLT_MODE);
+}
+
+/* Copy */
+
+static Bool
+amd_gx_exa_PrepareCopy(PixmapPtr pxSrc, PixmapPtr pxDst, int dx, int dy,
+ int alu, Pixel planemask)
+{
+ DBLOG(2, "amd_gx_exa_PrepareCopy() dx%d dy%d alu %#x %#x\n",
+ dx, dy, alu, planemask);
+ GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
+ int dstPitch = exaGetPixmapPitch(pxDst);
+
+ pGeode->cpySrcOffset = exaGetPixmapOffset(pxSrc);
+ pGeode->cpySrcPitch = exaGetPixmapPitch(pxSrc);
+ pGeode->cpySrcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8;
+ pGeode->cpyDx = dx;
+ pGeode->cpyDy = dy;
+ unsigned int ROP = BPP | (planemask == ~0U ? SDfn[alu] : SDfn_PM[alu]);
+
+ BLT_MODE = ((ROP ^ (ROP >> 1)) & 0x55) != 0 ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_PAT_COLOR_0, planemask);
+ WRITE_GP32(MGP_SRC_COLOR_FG, ~0);
+ WRITE_GP32(MGP_SRC_COLOR_BG, ~0);
+ WRITE_GP32(MGP_RASTER_MODE, ROP);
+ WRITE_GP32(MGP_STRIDE, (pGeode->cpySrcPitch << 16) | dstPitch);
+ return TRUE;
+}
+
+static void
+amd_gx_exa_Copy(PixmapPtr pxDst, int srcX, int srcY, int dstX, int dstY,
+ int w, int h)
+{
+ DBLOG(2, "amd_gx_exa_Copy() from %d,%d to %d,%d %dx%d\n", srcX, srcY,
+ dstX, dstY, w, h);
+ GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
+ int dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8;
+ int dstPitch = exaGetPixmapPitch(pxDst);
+ unsigned int srcOffset =
+ pGeode->cpySrcOffset + pGeode->cpySrcPitch * srcY +
+ pGeode->cpySrcBpp * srcX;
+ unsigned int dstOffset =
+ exaGetPixmapOffset(pxDst) + dstPitch * dstY + dstBpp * dstX;
+ unsigned int size = (w << 16) | h;
+ unsigned int blt_mode = BLT_MODE;
+
+ if (pGeode->cpyDx < 0) {
+ srcOffset += w * pGeode->cpySrcBpp - 1;
+ dstOffset += w * dstBpp - 1;
+ blt_mode |= MGP_BM_NEG_XDIR;
+ }
+ if (pGeode->cpyDy < 0) {
+ srcOffset += (h - 1) * pGeode->cpySrcPitch;
+ dstOffset += (h - 1) * dstPitch;
+ blt_mode |= MGP_BM_NEG_YDIR;
+ }
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_SRC_OFFSET, srcOffset);
+ WRITE_GP32(MGP_DST_OFFSET, dstOffset);
+ WRITE_GP32(MGP_WID_HEIGHT, size);
+ WRITE_GP16(MGP_BLT_MODE, blt_mode);
+}
+
+/* A=SRC, B=DST */
+#define SRC_DST 0
+/* B=SRC, A=DST */
+#define DST_SRC MGP_RM_DEST_FROM_CHAN_A
+/* A*alpha + B*0 */
+#define Aa_B0 MGP_RM_ALPHA_TIMES_A
+/* A*0 + B*(1-alpha) */
+#define A0_B1a MGP_RM_BETA_TIMES_B
+/* A*1 + B*(1-alpha) */
+#define A1_B1a MGP_RM_A_PLUS_BETA_B
+/* A*alpha + B*(1-alpha) */
+#define Aa_B1a MGP_RM_ALPHA_A_PLUS_BETA_B
+/* alpha from A */
+#define a_A MGP_RM_SELECT_ALPHA_A
+/* alpha from B */
+#define a_B MGP_RM_SELECT_ALPHA_B
+/* alpha from const */
+#define a_C MGP_RM_SELECT_ALPHA_R
+/* alpha = 1 */
+#define a_1 MGP_RM_SELECT_ALPHA_1
+
+#define MGP_RM_ALPHA_TO_ARGB (MGP_RM_ALPHA_TO_ALPHA | MGP_RM_ALPHA_TO_RGB)
+#define gxPictOpMAX PictOpAdd /* highest accelerated op */
+
+unsigned int amd_gx_exa_alpha_ops[] =
+/* A B OP AS const = 0 */
+{
+ (SRC_DST | Aa_B0 | a_C), 0, /* clear (src*0) */
+ (SRC_DST | Aa_B0 | a_1), 0, /* src (src*1) */
+ (DST_SRC | Aa_B0 | a_1), 0, /* dst (dst*1) */
+ (SRC_DST | A1_B1a | a_A), 0, /* src-over (src*1 + dst(1-A)) */
+ (DST_SRC | A1_B1a | a_A), 0, /* dst-over (dst*1 + src(1-B)) */
+ (SRC_DST | Aa_B0 | a_B), 0, /* src-in (src*B) */
+ (DST_SRC | Aa_B0 | a_B), 0, /* dst-in (dst*A) */
+ (DST_SRC | A0_B1a | a_A), 0, /* src-out (src*(1-B)) */
+ (SRC_DST | A0_B1a | a_A), 0, /* dst-out (dst*(1-A)) */
+/* pass1 (SRC=dst DST=scr=src), pass2 (SRC=src, DST=dst) */
+ (DST_SRC | Aa_B0 | a_B), /* srcatop (src*B) */
+ (SRC_DST | A0_B1a | a_A), /* + (dst(1-A)) */
+ (SRC_DST | Aa_B0 | a_B), /* dstatop (dst*A) */
+ (DST_SRC | A0_B1a | a_A), /* + (src(1-B) */
+ (SRC_DST | A0_B1a | a_A), /* xor (src*(1-B) */
+ (SRC_DST | A0_B1a | a_A), /* + (dst(1-A) */
+ (SRC_DST | A1_B1a | a_C), 0, /* add (src*1 + dst*1) */
+};
+
+#define usesPasses(op) ((( \
+ ( 1 << PictOpAtop ) | \
+ ( 1 << PictOpAtopReverse ) | \
+ ( 1 << PictOpXor ) | \
+ 0 ) >> (op)) & 1)
+
+/* pass1 or pass2 */
+#define usesSrcAlpha(op) ((( \
+ ( 1 << PictOpOver ) | \
+ ( 1 << PictOpInReverse ) | \
+ ( 1 << PictOpOutReverse ) | \
+ ( 1 << PictOpAtop ) | \
+ ( 1 << PictOpAtopReverse ) | \
+ ( 1 << PictOpXor ) | \
+ 0 ) >> (op)) & 1)
+
+/* pass1 or pass2 */
+#define usesDstAlpha(op) ((( \
+ ( 1 << PictOpOverReverse ) | \
+ ( 1 << PictOpIn ) | \
+ ( 1 << PictOpOut ) | \
+ ( 1 << PictOpAtop ) | \
+ ( 1 << PictOpAtopReverse ) | \
+ ( 1 << PictOpXor ) | \
+ 0 ) >> (op)) & 1)
+
+/* non 2 pass ops */
+#define usesChanB0(op) ((( \
+ ( 1 << PictOpOver ) | \
+ ( 1 << PictOpOverReverse ) | \
+ ( 1 << PictOpIn ) | \
+ ( 1 << PictOpInReverse ) | \
+ ( 1 << PictOpOut ) | \
+ ( 1 << PictOpOutReverse ) | \
+ ( 1 << PictOpAdd ) | \
+ 0 ) >> (op)) & 1)
+
+/* pass 1 ops */
+#define usesChanB1(op) ((( \
+ ( 1 << PictOpAtop ) | \
+ ( 1 << PictOpAtopReverse ) | \
+ ( 1 << PictOpXor ) | \
+ 0 ) >> (op)) & 1)
+
+/* pass 2 ops */
+#define usesChanB2(op) ((( \
+ ( 1 << PictOpAtop ) | \
+ ( 1 << PictOpAtopReverse ) | \
+ ( 1 << PictOpXor ) | \
+ 0 ) >> (op)) & 1)
+
+typedef struct
+{
+ int exa_fmt;
+ int bpp;
+ int gx_fmt;
+ int alpha_bits;
+} amd_gx_exa_fmt_t;
+
+amd_gx_exa_fmt_t amd_gx_exa_fmts[] = {
+ {PICT_a8r8g8b8, 32, MGP_RM_BPPFMT_8888, 8},
+ {PICT_x8r8g8b8, 32, MGP_RM_BPPFMT_8888, 0},
+ {PICT_a4r4g4b4, 16, MGP_RM_BPPFMT_4444, 4},
+ {PICT_a1r5g5b5, 16, MGP_RM_BPPFMT_1555, 1},
+ {PICT_r5g6b5, 16, MGP_RM_BPPFMT_565, 0},
+ {PICT_r3g3b2, 8, MGP_RM_BPPFMT_332, 0},
+};
+
+static amd_gx_exa_fmt_t *
+amd_gx_exa_check_format(PicturePtr p)
+{
+ int i;
+ int bpp = p->pDrawable ? p->pDrawable->bitsPerPixel : 0;
+ amd_gx_exa_fmt_t *fp = &amd_gx_exa_fmts[0];
+
+ for (i = sizeof(amd_gx_exa_fmts) / sizeof(amd_gx_exa_fmts[0]); --i >= 0;
+ ++fp) {
+ if (fp->bpp < bpp)
+ return NULL;
+ if (fp->bpp != bpp)
+ continue;
+ if (fp->exa_fmt == p->format)
+ break;
+ }
+ return i < 0 ? NULL : fp;
+}
+
+/* Composite */
+
+static Bool
+amd_gx_exa_CheckComposite(int op, PicturePtr pSrc, PicturePtr pMsk,
+ PicturePtr pDst)
+{
+ amd_gx_exa_fmt_t *sfp, *dfp;
+ GeodeRec *pGeode = GEODEPTR_FROM_PICTURE(pDst);
+
+ if (op > gxPictOpMAX)
+ return FALSE;
+ if (pMsk)
+ return FALSE;
+ if (usesPasses(op) && pGeode->exaBfrSz == 0)
+ return FALSE;
+ if (pSrc->filter != PictFilterNearest &&
+ pSrc->filter != PictFilterFast &&
+ pSrc->filter != PictFilterGood && pSrc->filter != PictFilterBest)
+ return FALSE;
+ if (pSrc->repeat)
+ return FALSE;
+ if (pSrc->transform)
+ return FALSE;
+ return TRUE;
+}
+
+static Bool
+amd_gx_exa_PrepareComposite(int op, PicturePtr pSrc, PicturePtr pMsk,
+ PicturePtr pDst, PixmapPtr pxSrc, PixmapPtr pxMsk, PixmapPtr pxDst)
+{
+ int srcPitch;
+
+ DBLOG(2, "amd_gx_exa_PrepareComposite()\n");
+ GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
+ amd_gx_exa_fmt_t *sfp, *dfp;
+
+ if ((sfp = amd_gx_exa_check_format(pSrc)) == NULL)
+ return FALSE;
+ if (sfp->alpha_bits == 0 && usesSrcAlpha(op))
+ return FALSE;
+ if ((dfp = amd_gx_exa_check_format(pDst)) == NULL)
+ return FALSE;
+ if (dfp->alpha_bits == 0 && usesDstAlpha(op))
+ return FALSE;
+ if (sfp->gx_fmt != dfp->gx_fmt)
+ return FALSE;
+ srcPitch = exaGetPixmapPitch(pxSrc);
+ if (usesPasses(op) && srcPitch > pGeode->exaBfrSz)
+ return FALSE;
+ pGeode->cmpSrcPitch = srcPitch;
+ pGeode->cmpOp = op;
+ pGeode->cmpSrcOffset = exaGetPixmapOffset(pxSrc);
+ pGeode->cmpSrcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8;
+ pGeode->cmpSrcFmt = sfp->gx_fmt;
+ pGeode->cmpDstFmt = dfp->gx_fmt | (dfp->alpha_bits == 0 ?
+ MGP_RM_ALPHA_TO_RGB : MGP_RM_ALPHA_TO_ARGB);
+ return TRUE;
+}
+
+static void
+amd_gx_exa_Composite(PixmapPtr pxDst, int srcX, int srcY, int maskX,
+ int maskY, int dstX, int dstY, int width, int height)
+{
+ int op, current_line, max_lines, lines, pass, scratchPitch;
+ unsigned int srcOffset, srcOfs, srcPitch, srcPch, srcBpp;
+ unsigned int dstOffset, dstOfs, dstPitch, dstPch, dstBpp;
+ unsigned int sizes, strides, blt_mode, rop, pitch;
+ GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst);
+
+ DBLOG(2, "amd_gx_exa_Composite() from %d,%d to %d,%d %dx%d\n",
+ srcX, srcY, dstX, dstY, width, height);
+
+ op = pGeode->cmpOp;
+ if (usesPasses(op)) {
+ int cacheLineSz = 32;
+ int cachelines =
+ (width * pGeode->cmpSrcBpp + cacheLineSz - 1) / cacheLineSz;
+ scratchPitch = cachelines * cacheLineSz;
+ if (scratchPitch > pGeode->cmpSrcPitch)
+ scratchPitch = pGeode->cmpSrcPitch;
+ max_lines = pGeode->exaBfrSz / scratchPitch;
+ } else {
+ scratchPitch = 0;
+ max_lines = height;
+ }
+
+ dstBpp = (pxDst->drawable.bitsPerPixel + 7) / 8;
+ dstPitch = exaGetPixmapPitch(pxDst);
+ dstOffset = exaGetPixmapOffset(pxDst) + dstPitch * dstY + dstBpp * dstX;
+ srcBpp = pGeode->cmpSrcBpp;
+ srcPitch = pGeode->cmpSrcPitch;
+ srcOffset = pGeode->cmpSrcOffset + srcPitch * srcY + srcBpp * srcX;
+
+ current_line = pass = 0;
+ while (current_line < height) {
+ if (usesPasses(op)) {
+ lines = height - current_line;
+ if (lines > max_lines)
+ lines = max_lines;
+ switch (pass) {
+ case 0: /* copy src to scratch */
+ srcPch = srcPitch;
+ srcOfs = srcOffset + current_line * srcPch;
+ dstPch = scratchPitch;
+ dstOfs = pGeode->exaBfrOffset;
+ rop = pGeode->cmpSrcFmt | MGP_RM_ALPHA_TO_ARGB;
+ rop |= amd_gx_exa_alpha_ops[PictOpSrc * 2];
+ blt_mode = usesChanB0(PictOpSrc) ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ ++pass;
+ break;
+ case 1: /* pass1 */
+ srcPch = dstPitch;
+ srcOfs = dstOffset + current_line * srcPch;
+ dstPch = scratchPitch;
+ dstOfs = pGeode->exaBfrOffset;
+ rop = pGeode->cmpSrcFmt | MGP_RM_ALPHA_TO_ARGB;
+ rop |= amd_gx_exa_alpha_ops[op * 2];
+ blt_mode = usesChanB1(op) ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ ++pass;
+ break;
+ case 2: /* pass2 */
+ srcPch = srcPitch;
+ srcOfs = srcOffset + current_line * srcPch;
+ dstPch = dstPitch;
+ dstOfs = dstOffset + current_line * dstPch;
+ rop = pGeode->cmpSrcFmt | MGP_RM_ALPHA_TO_ARGB;
+ rop |= amd_gx_exa_alpha_ops[op * 2 + 1];
+ blt_mode = usesChanB2(op) ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ ++pass;
+ break;
+ case 3: /* add */
+ srcPch = scratchPitch;
+ srcOfs = pGeode->exaBfrOffset;
+ dstPch = dstPitch;
+ dstOfs = dstOffset + current_line * dstPch;
+ rop = pGeode->cmpDstFmt;
+ rop |= amd_gx_exa_alpha_ops[PictOpAdd * 2];
+ blt_mode = usesChanB0(PictOpAdd) ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ current_line += lines;
+ pass = 0;
+ break;
+ }
+ strides = (srcPch << 16) | dstPch;
+ } else { /* not multi pass */
+ srcOfs = srcOffset;
+ dstOfs = dstOffset;
+ current_line = lines = height;
+ strides = (srcPitch << 16) | dstPitch;
+ rop = pGeode->cmpDstFmt | amd_gx_exa_alpha_ops[op * 2];
+ blt_mode = usesChanB0(op) ?
+ MGP_BM_SRC_FB | MGP_BM_DST_REQ : MGP_BM_SRC_FB;
+ }
+ sizes = (width << 16) | lines;
+ if (srcOfs < dstOfs) {
+ srcOfs += (lines - 1) * srcPitch + width * srcBpp - 1;
+ dstOfs += (lines - 1) * dstPitch + width * dstBpp - 1;
+ blt_mode |= MGP_BM_NEG_XDIR | MGP_BM_NEG_YDIR;
+ }
+ GU2_WAIT_PENDING;
+ WRITE_GP32(MGP_RASTER_MODE, rop);
+ WRITE_GP32(MGP_SRC_OFFSET, srcOfs);
+ WRITE_GP32(MGP_DST_OFFSET, dstOfs);
+ WRITE_GP32(MGP_WID_HEIGHT, sizes);
+ WRITE_GP32(MGP_STRIDE, strides);
+ WRITE_GP16(MGP_BLT_MODE, blt_mode);
+ }
+}
+#endif /* #if XF86EXA */
+
+/*----------------------------------------------------------------------------
+ * GXAccelInit.
+ *
+ * Description: This function sets up the supported acceleration routines and
+ * appropriate flags.
+ *
+ * Parameters:
+ * pScrn: Screeen pointer structure.
+ *
+ * Returns: TRUE on success and FALSE on Failure
+ *
+ * Comments: This function is called in GXScreenInit in
+ * geode_driver.c to set * the acceleration.
+ *----------------------------------------------------------------------------
+ */
+Bool
+GXAccelInit(ScreenPtr pScrn)
+{
+ ScrnInfoPtr pScrni = xf86Screens[pScrn->myNum];
+ GeodeRec *pGeode = GEODEPTR(pScrni);
+
+#if XF86EXA
+ ExaDriverPtr pExa = pGeode->pExa;
+#endif
+
+ gu2_xshift = pScrni->bitsPerPixel >> 4;
+
+ switch (pGeode->AccelPitch) {
+ case 1024:
+ gu2_yshift = 10;
+ break;
+ case 2048:
+ gu2_yshift = 11;
+ break;
+ case 4096:
+ gu2_yshift = 12;
+ break;
+ default:
+ gu2_yshift = 13;
+ break;
+ }
+
+#ifdef OPT_ACCEL
+ ACCEL_STRIDE = (pGeode->AccelPitch << 16) | pGeode->AccelPitch;
+ switch (pScrni->bitsPerPixel) {
+ case 16:
+ BPP = MGP_RM_BPPFMT_565;
+ break;
+ case 32:
+ BPP = MGP_RM_BPPFMT_8888;
+ break;
+ default:
+ BPP = MGP_RM_BPPFMT_332;
+ break;
+ }
+#endif
+
+#if XF86EXA
+ if (pExa && pGeode->useEXA) {
+
+ xf86DrvMsg(pScrni->scrnIndex, X_INFO, "Init EXA\n");
+ if (exaGetVersion() < EXA_MAKE_VERSION(0, 2, 0)) {
+ xf86DrvMsg(pScrni->scrnIndex, X_ERROR, "EXA version is too old "
+ "(got 0x%3x, need >= 0x020)\n", exaGetVersion());
+ return FALSE;
+ }
+
+ /* Sync */
+ pExa->WaitMarker = amd_gx_exa_WaitMarker;
+ /* UploadToScreen */
+ pExa->UploadToScreen = amd_gx_exa_UploadToScreen;
+ pExa->DownloadFromScreen = amd_gx_exa_DownloadFromScreen;
+
+ /* Solid fill */
+ pExa->PrepareSolid = amd_gx_exa_PrepareSolid;
+ pExa->Solid = amd_gx_exa_Solid;
+ pExa->DoneSolid = amd_gx_exa_Done;
+
+ /* Copy */
+ pExa->PrepareCopy = amd_gx_exa_PrepareCopy;
+ pExa->Copy = amd_gx_exa_Copy;
+ pExa->DoneCopy = amd_gx_exa_Done;
+
+ /* Composite */
+ pExa->CheckComposite = amd_gx_exa_CheckComposite;
+ pExa->PrepareComposite = amd_gx_exa_PrepareComposite;
+ pExa->Composite = amd_gx_exa_Composite;
+ pExa->DoneComposite = amd_gx_exa_Done;
+
+ return exaDriverInit(pScrn, pGeode->pExa);
+ }
+#endif
+
+ /* Getting the pointer for acceleration Inforecord */
+ pGeode->AccelInfoRec = localRecPtr = XAACreateInfoRec();
+ if (!pGeode->AccelInfoRec)
+ return FALSE;
+
+ /* SET ACCELERATION FLAGS */
+ localRecPtr->Flags =
+ PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
+
+ /* HOOK SYNCRONIZARION ROUTINE */
+ localRecPtr->Sync = GXAccelSync;
+
+#if GX_FILL_RECT_SUPPORT
+ /* HOOK FILLED RECTANGLES */
+ HOOK(SetupForSolidFill);
+ HOOK(SubsequentSolidFillRect);
+ localRecPtr->SolidFillFlags = 0;
+#endif
+
+#if GX_MONO_8X8_PAT_SUPPORT
+ /* Color expansion */
+ HOOK(SetupForMono8x8PatternFill);
+ HOOK(SubsequentMono8x8PatternFillRect);
+/* BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY | */
+ localRecPtr->Mono8x8PatternFillFlags = BIT_ORDER_IN_BYTE_MSBFIRST |
+ HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN;
+#endif
+
+#if GX_CLREXP_8X8_PAT_SUPPORT
+ /* Color expansion */
+ HOOK(SetupForColor8x8PatternFill);
+ HOOK(SubsequentColor8x8PatternFillRect);
+/* BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY | */
+ localRecPtr->Color8x8PatternFillFlags =
+ BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD |
+ HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_PROGRAMMED_ORIGIN;
+#endif
+
+#if GX_SCR2SCRCPY_SUPPORT
+ /* HOOK SCREEN TO SCREEN COPIES
+ * Set flag to only allow copy if transparency is enabled.
+ */
+ HOOK(SetupForScreenToScreenCopy);
+ HOOK(SubsequentScreenToScreenCopy);
+ localRecPtr->ScreenToScreenCopyFlags =
+ BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
+#endif
+
+#if GX_BRES_LINE_SUPPORT
+ /* HOOK BRESENHAM SOLID LINES */
+ localRecPtr->SolidLineFlags = NO_PLANEMASK;
+ HOOK(SetupForSolidLine);
+ HOOK(SubsequentSolidBresenhamLine);
+ HOOK(SubsequentSolidHorVertLine);
+ HOOK(SubsequentSolidTwoPointLine);
+ localRecPtr->SolidBresenhamLineErrorTermBits = 15;
+#endif
+
+#if GX_DASH_LINE_SUPPORT
+ /* HOOK BRESENHAM DASHED LINES */
+ HOOK(SetupForDashedLine);
+ HOOK(SubsequentDashedBresenhamLine);
+ HOOK(SubsequentDashedTwoPointLine);
+ localRecPtr->DashedBresenhamLineErrorTermBits = 15;
+ localRecPtr->DashPatternMaxLength = 64;
+ localRecPtr->DashedLineFlags = NO_PLANEMASK | /* TRANSPARENCY_ONLY | */
+ LINE_PATTERN_POWER_OF_2_ONLY | LINE_PATTERN_MSBFIRST_MSBJUSTIFIED;
+#endif
+
+#if GX_SCR2SCREXP_SUPPORT
+ /* Color expansion */
+ HOOK(SetupForScreenToScreenColorExpandFill);
+ HOOK(SubsequentScreenToScreenColorExpandFill);
+ localRecPtr->ScreenToScreenColorExpandFillFlags =
+ BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY;
+#endif
+
+ if (pGeode->AccelImageWriteBuffers) {
+#if GX_SCANLINE_SUPPORT
+ localRecPtr->ScanlineImageWriteBuffers =
+ pGeode->AccelImageWriteBuffers;
+ localRecPtr->NumScanlineImageWriteBuffers = pGeode->NoOfImgBuffers;
+ HOOK(SetupForScanlineImageWrite);
+ HOOK(SubsequentScanlineImageWriteRect);
+ HOOK(SubsequentImageWriteScanline);
+ localRecPtr->ScanlineImageWriteFlags = NO_PLANEMASK | NO_GXCOPY |
+ BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
+#endif
+
+ } else {
+ localRecPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES;
+ }
+
+ if (pGeode->AccelColorExpandBuffers) {
+#if GX_CPU2SCREXP_SUPPORT
+ /* Color expansion */
+ localRecPtr->ScanlineColorExpandBuffers =
+ pGeode->AccelColorExpandBuffers;
+ localRecPtr->NumScanlineColorExpandBuffers =
+ pGeode->NoOfColorExpandLines;
+ HOOK(SetupForScanlineCPUToScreenColorExpandFill);
+ HOOK(SubsequentScanlineCPUToScreenColorExpandFill);
+ HOOK(SubsequentColorExpandScanline);
+ localRecPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
+ BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
+#endif
+ }
+#if GX_WRITE_PIXMAP_SUPPORT
+ pGeode->WritePixmap = localRecPtr->WritePixmap;
+ HOOK(WritePixmap);
+#endif
+
+ return (XAAInit(pScrn, localRecPtr));
+}
+
+/* END OF FILE */