/* 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 "xf86fbman.h" #include "miline.h" #include "xaarop.h" #include "servermd.h" #include "picture.h" #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Pci.h" #include "xf86PciInfo.h" #include "geode.h" #include "gfx_defs.h" #include "gfx_regs.h" /* Common macros for blend operations are here */ #include "geode_blend.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; #define CALC_FBOFFSET(x, y) \ (((ulong)(y) * gu2_pitch + ((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 static unsigned int BPP; static unsigned int BLT_MODE, VEC_MODE; static 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 #define DLOG(l, fmt, args...) ErrorF(fmt, ##args) /* 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 unsigned int gu2_pitch; /* 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 const 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 const int PDfn_SM[16] = { 0x22, 0xA2, 0x62, 0xE2, 0x2A, 0xAA, 0x6A, 0xEA, 0x26, 0xA6, 0x66, 0xE6, 0x2E, 0xAE, 0x6E, 0xEE }; #ifdef OPT_ACCEL static inline CARD32 amd_gx_BppToRasterMode(int bpp) { switch (bpp) { case 16: return MGP_RM_BPPFMT_565; case 32: return MGP_RM_BPPFMT_8888; case 8: return MGP_RM_BPPFMT_332; default: return 0; } } #endif /* OPT_ACCEL */ /*---------------------------------------------------------------------------- * 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) { //ErrorF("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) { //ErrorF("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_RASTER_MODE, ROP); WRITE_GP32(MGP_PAT_COLOR_0, planemask); WRITE_GP32(MGP_SRC_COLOR_FG, color); 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) { //ErrorF("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); //ErrorF("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->Pitch); gfx2_set_destination_stride(pGeode->Pitch); 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) { //ErrorF( // "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) { //ErrorF( //"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_RASTER_MODE, ROP); 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_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) { DEBUGMSG(1, (0, X_INFO, "%s() pat %#x,%#x at %d,%d %dx%d\n", __func__, 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) { DEBUGMSG(1, (0, X_INFO, "%s() xd%d yd%d rop %#x %#x %#x\n", __func__, 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->Pitch); gfx2_set_destination_stride(pGeode->Pitch); } #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_RASTER_MODE, ROP); 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_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) { DEBUGMSG(1, (0, X_INFO, "%s() from %d,%d to %d,%d %dx%d\n", __func__, 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->Pitch; 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); DEBUGMSG(1, (0, X_INFO, "%s() rop %#x %#x %#x %d %d\n", __func__, 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->Pitch); gfx2_set_destination_stride(pGeode->Pitch); } /*---------------------------------------------------------------------------- * 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) { DEBUGMSG(1, (0, X_INFO, "%s() rop %d,%d %dx%d %d\n", __func__, 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 DEBUGMSG(1, (0, X_INFO, "%s() %d\n", __func__, 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->Pitch); #endif /* if !GX_USE_OFFSCRN_MEM */ ++giwr.y; #else /* if GX_ONE_LINE_AT_A_TIME */ int blt_height; DEBUGMSG(1, (0, X_INFO, "%s() %d\n", __func__, 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->Pitch); #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; DEBUGMSG(1, (0, X_INFO, "%s() fg %#x bg %#x rop %#x %#x\n", __func__, fg, bg, rop, planemask)); rop &= 0x0F; srcpitch = ((pGeode->Pitch + 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->Pitch); #else { unsigned int stride = (srcpitch << 16) | pGeode->Pitch; 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_RASTER_MODE, ROP); WRITE_GP32(MGP_PAT_COLOR_0, planemask); WRITE_GP32(MGP_SRC_COLOR_BG, bg); WRITE_GP32(MGP_SRC_COLOR_FG, fg); 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) { DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %dx%d %d\n", __func__, 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); DEBUGMSG(1, (0, X_INFO, "%s() %d\n", __func__, 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->Pitch + 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) { DEBUGMSG(1, (0, X_INFO, "%s() fg %#x bg %#x rop %#x %#x\n", __func__, 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->Pitch); gfx2_set_destination_stride(pGeode->Pitch); } #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_RASTER_MODE, ROP); WRITE_GP32(MGP_PAT_COLOR_0, planemask); WRITE_GP32(MGP_SRC_COLOR_BG, bg); WRITE_GP32(MGP_SRC_COLOR_FG, fg); 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) { DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %dx%d %d,%d %d\n", __func__, 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) { DEBUGMSG(1, (0, X_INFO, "%s() %#x %#x %#x\n", __func__, 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_RASTER_MODE, ROP); WRITE_GP32(MGP_PAT_COLOR_0, color); WRITE_GP32(MGP_SRC_COLOR_FG, planemask); 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; DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %d %d, %d %d, %d\n", __func__, 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, don't 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; DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %d,%d, %#x\n", __func__, 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) { DEBUGMSG(1, (0, X_INFO, "%s() %d,%d %d %d\n", __func__, 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 position * absmaj: Specifies the Bresenman absolute major. * absmin: Specifies 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]; //ErrorF("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, don't 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]; //ErrorF("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); //ErrorF("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(); geode_memory_to_screen_blt((unsigned long) src, (unsigned long) FBADDR(x, y), srcwidth, pGeode->Pitch, 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 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) { GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pDst); char *dst = pGeode->pExa->memoryBase + exaGetPixmapOffset(pDst); int dst_pitch = exaGetPixmapPitch(pDst); int bpp = pDst->drawable.bitsPerPixel; dst += y * dst_pitch + x * (bpp >> 3); GU2_WAIT_BUSY; geode_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) { GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pSrc); char *src = pGeode->pExa->memoryBase + exaGetPixmapOffset(pSrc); int src_pitch = exaGetPixmapPitch(pSrc); int bpp = pSrc->drawable.bitsPerPixel; src += (y * src_pitch) + (x * (bpp >> 3)); GU2_WAIT_BUSY; geode_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) { int dstPitch = exaGetPixmapPitch(pxMap); unsigned int ROP = amd_gx_BppToRasterMode(pxMap->drawable.bitsPerPixel) | (planemask == ~0U ? SDfn[alu] : SDfn_PM[alu]); // FIXME: this should go away -- workaround for the blockparty icon corruption //if (pxMap->drawable.bitsPerPixel == 32) // return FALSE; BLT_MODE = ((ROP ^ (ROP >> 2)) & 0x33) == 0 ? MGP_BM_SRC_MONO : 0; if (((ROP ^ (ROP >> 1)) & 0x55) != 0) BLT_MODE |= MGP_BM_DST_REQ; //ErrorF("amd_gx_exa_PrepareSolid(%#x,%#x,%#x - ROP=%x,BLT_MODE=%x)\n", alu, planemask, fg, ROP, BLT_MODE); GU2_WAIT_PENDING; WRITE_GP32(MGP_RASTER_MODE, ROP); WRITE_GP32(MGP_PAT_COLOR_0, planemask); WRITE_GP32(MGP_SRC_COLOR_FG, fg); WRITE_GP32(MGP_STRIDE, dstPitch); return TRUE; } static void amd_gx_exa_Solid(PixmapPtr pxMap, int x1, int y1, int x2, int 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); //ErrorF("amd_gx_exa_Solid() at %d,%d %d,%d - offset=%d, bpp=%d\n", x1, y1, x2, y2, offset, bpp); 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) { GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); int dstPitch = exaGetPixmapPitch(pxDst); unsigned int ROP; /* Punt if the color formats aren't the same */ if (pxSrc->drawable.bitsPerPixel != pxDst->drawable.bitsPerPixel) return FALSE; //ErrorF("amd_gx_exa_PrepareCopy() dx%d dy%d alu %#x %#x\n", // dx, dy, alu, planemask); pGeode->cpySrcOffset = exaGetPixmapOffset(pxSrc); pGeode->cpySrcPitch = exaGetPixmapPitch(pxSrc); pGeode->cpySrcBpp = (pxSrc->drawable.bitsPerPixel + 7) / 8; pGeode->cpyDx = dx; pGeode->cpyDy = dy; ROP = amd_gx_BppToRasterMode(pxSrc->drawable.bitsPerPixel) | (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_RASTER_MODE, ROP); WRITE_GP32(MGP_PAT_COLOR_0, planemask); WRITE_GP32(MGP_SRC_COLOR_FG, ~0); WRITE_GP32(MGP_SRC_COLOR_BG, ~0); 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) { 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; //ErrorF("amd_gx_exa_Copy() from %d,%d to %d,%d %dx%d\n", srcX, srcY, // dstX, dstY, w, h); 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) */ }; 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) { 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; if (!pxSrc || !pSrc->pDrawable) return FALSE; GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); amd_gx_exa_fmt_t *sfp, *dfp; //ErrorF("amd_gx_exa_PrepareComposite()\n"); 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 = 0, srcPitch, srcPch = 0, srcBpp; unsigned int dstOffset, dstOfs = 0, dstPitch, dstPch = 0, dstBpp; unsigned int sizes, strides, blt_mode = 0, rop = 0; GeodeRec *pGeode = GEODEPTR_FROM_PIXMAP(pxDst); //ErrorF("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 = xf86ScreenToScrn(pScrn); GeodeRec *pGeode = GEODEPTR(pScrni); #if XF86EXA ExaDriverPtr pExa = pGeode->pExa; #endif gu2_xshift = pScrni->bitsPerPixel >> 4; /* XXX - fixme - this will change - we'll need to update it */ gu2_pitch = pGeode->Pitch; switch (pGeode->Pitch) { 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->Pitch << 16) | pGeode->Pitch; BPP = amd_gx_BppToRasterMode(pScrni->bitsPerPixel); #endif #if XF86EXA if (pExa && pGeode->useEXA) { pExa->exa_major = EXA_VERSION_MAJOR; pExa->exa_minor = EXA_VERSION_MINOR; /* 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 return FALSE; }