/* * Copyright © 2004 Ralph Thomas * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Ralph Thomas not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Ralph Thomas makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * RALPH THOMAS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL RALPH THOMAS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* ** VIA CLE266 driver ** Copyright 2004 (C) Ralph Thomas ** ** http://www.viatech.com.tw/ ** ** This code is for accelerated drawing of solids and accelerated ** copies. Note that there is currently no software FIFO implemented, ** and no documentation on any hardware FIFO. */ #include "via.h" #include "viadraw.h" #include "via_regs.h" #include #include "kdrive.h" #include "kaa.h" /* ** A global to contain card information between calls into this file. ** XXX: This is totally brain-damaged. Why don't I get the information ** I want in viaSolid/viaCopy/viaDoneXXX? */ static ViaCardInfo* card; /* ** Translation table from GC raster operation values into ROP3 values ** that the VIA chip understands. ** ** viaPatternRop is used by viaPrepareSolid. ** viaCopyRop is used by viaPrepareCopy. */ CARD8 viaPatternRop[16] = { /* GXclear */ 0x00, /* ROP_0 0 */ /* GXand */ 0xA0, /* ROP_DPa src AND dst */ /* GXandReverse */ 0x50, /* ROP_PDna src AND NOT dst */ /* GXcopy */ 0xF0, /* ROP_P src */ /* GXandInverted*/ 0x0A, /* ROP_DPna NOT src AND dst */ /* GXnoop */ 0xAA, /* ROP_D dst */ /* GXxor */ 0x5A, /* ROP_DPx src XOR dst */ /* GXor */ 0xFA, /* ROP_DPo src OR dst */ /* GXnor */ 0x05, /* ROP_DPon NOT src AND NOT dst */ /* GXequiv */ 0xA5, /* ROP_PDxn NOT src XOR dst */ /* GXinvert */ 0x55, /* ROP_Dn NOT dst */ /* GXorReverse */ 0xF5, /* ROP_PDno src OR NOT dst */ /* GXcopyInverted*/ 0x0F, /* ROP_Pn NOT src */ /* GXorInverted */ 0xAF, /* ROP_DPno NOT src OR dst */ /* GXnand */ 0x5F, /* ROP_DPan NOT src OR NOT dst */ /* GXset */ 0xFF, /* ROP_1 1 */ }; CARD8 viaCopyRop[16] = { /* GXclear */ 0x00, /* ROP_0 0 */ /* GXand */ 0x88, /* ROP_DSa src AND dst */ /* GXandReverse */ 0x44, /* ROP_SDna src AND NOT dst */ /* GXcopy */ 0xCC, /* ROP_S src */ /* GXandInverted*/ 0x22, /* ROP_DSna NOT src AND dst */ /* GXnoop */ 0xAA, /* ROP_D dst */ /* GXxor */ 0x66, /* ROP_DSx src XOR dst */ /* GXor */ 0xEE, /* ROP_DSo src OR dst */ /* GXnor */ 0x11, /* ROP_DSon NOT src AND NOT dst */ /* GXequiv */ 0x99, /* ROP_DSxn NOT src XOR dst */ /* GXinvert */ 0x55, /* ROP_Dn NOT dst */ /* GXorReverse */ 0xDD, /* ROP_SDno src OR NOT dst */ /* GXcopyInverted*/ 0x33, /* ROP_Sn NOT src */ /* GXorInverted */ 0xBB, /* ROP_DSno NOT src OR dst */ /* GXnand */ 0x77, /* ROP_DSan NOT src OR NOT dst */ /* GXset */ 0xFF, /* ROP_1 1 */ }; /* ** void viaWaitIdle( ViaCardInfo* viac ) ** ** Description: ** Block up the CPU while waiting for the last command sent to ** the chip to complete. As an experiment I'm going to try to ** yield my process to others instead of just tight looping. ** ** Arguments: ** viac VIA-driver specific chip information ** ** Return: ** None. */ void viaWaitIdle( ViaCardInfo* viac ) { while( INREG32( VIA_REG_STATUS ) & VIA_BUSY ) sched_yield(); } /* ** void viaDrawSync( ScreenPtr pScreen, int marker ) ** ** Description: ** Block until the graphics chip has finished all outstanding drawing ** operations and the framebuffer contents is static. ** ** Arguments: ** pScreen Pointer to screen strucutre for the screen we're ** waiting for drawing to end on. ** ** Return: ** None. */ static void viaWaitMarker( ScreenPtr pScreen, int marker ) { KdScreenPriv( pScreen ); ViaCardInfo* viac = pScreenPriv->card->driver; viaWaitIdle( viac ); } /* ** Bool viaPrepareSolid( PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg ) ** ** Description: ** Decide if the specified solid fill operation can be accelerated or not, ** and if the fill can be accelerated, prepare the hardware for doing it. ** ** Arguments: ** pPixmap Pixmap to draw solid into. ** alu Raster operation to draw using, these are the same ** values which get set by XSetFunction(3X). See the ** Xlib PM p. 140 for a list of raster operations as ** well as descriptions. ** planemask This is the GC plane mask. We only copy bits which ** match the plane mask. ** fg The foreground pixel of the GC, the pixel to draw in. ** ** Return: ** TRUE This operation can be accelerated, call viaSolid to actually ** have it drawn. ** FALSE This operation cannot be accelerated, fall back to software. ** ** See Also: ** viaSolid - the function which actually draws the solid. */ static Bool viaPrepareSolid( PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg ) { ScreenPtr pScreen = pPixmap->drawable.pScreen; KdScreenPriv( pScreen ); ViaCardInfo* viac = pScreenPriv->card->driver; /* ** We don't accelerate when the plane mask is not everything. */ if( ~planeMask & FbFullMask( pPixmap->drawable.depth ) ) return FALSE; /* ** Compose the command, then store the composed command and color ** in the viac structure so that when viaSolid gets called we can ** write them out. */ viac->savedCommand = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (viaPatternRop[alu] << 24); viac->savedFgColor = fg; /* ** Store pointer to chip information, due to brain-damaged KAA. */ card = viac; return TRUE; } /* ** void viaSolid( int x1, int y1, int x2, int y2 ) ** ** Description: ** Perform a solid fill, using the data that was stored by viaPrepareSolid. ** ** Arguments: ** x1 x-coordinate of fill origin ** y1 y-coordinate of fill origin ** x2 x-coordinate of fill end point ** y2 y-coordinate of fill end point ** ** Return: ** None. ** ** See Also: ** viaPrepareSolid - the function that composes the GE command and saves ** the color for us. */ static void viaSolid( int x1, int y1, int x2, int y2 ) { ViaCardInfo* viac = card; int w = x2 - x1; int h = y2 - y1; if( !viac ) return; if( !w || !h ) return; /* ** Wait for the card to finish the current draw. */ viaWaitIdle( viac ); /* ** Do the draw. */ OUTREG32( VIA_REG_DSTPOS, ((y1 << 16) | x1) ); OUTREG32( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)) ); OUTREG32( VIA_REG_FGCOLOR, viac->savedFgColor ); OUTREG32( VIA_REG_GECMD, viac->savedCommand ); } /* ** void viaDoneSolid ** ** Description: ** Finish up drawing of the solid. ** ** Arguments: ** None. ** ** Return: ** None. */ static void viaDoneSolid(void) { } /* ** Bool viaPrepareCopy( PixmapPtr pSrcPixmap, PixmapPtr pDestPixmap, int dx, ** int dy, int alu, Pixel planeMask ) ** ** Description: ** Set up the VIA chip for a BitBlt. ** ** Arguments: ** pSrcPixmap the source pixmap to copy from ** pDestPixmap the destination pixmap to copy to ** dx direction of copy in x ** dy direction of copy in y ** alu Raster operation to draw using, these are the same ** values which get set by XSetFunction(3X). See the ** Xlib PM p. 140 for a list of raster operations as ** well as descriptions. ** planeMask This is the GC plane mask. We only copy bits which ** match the plane mask. ** ** Return: ** TRUE the requested copy operation can be accelerated using hardware, ** call viaCopy next. ** FALSE the requested copy operation cannot be accelerated using ** hardware - fallback to software. ** ** See Also: ** viaCopy - the function which does the actual copy. */ static Bool viaPrepareCopy( PixmapPtr pSrcPixmap, PixmapPtr pDestPixmap, int dx, int dy, int alu, Pixel planeMask ) { ScreenPtr pScreen = pDestPixmap->drawable.pScreen; KdScreenPriv( pScreen ); ViaCardInfo* viac = pScreenPriv->card->driver; /* ** Don't accelerate when the plane mask is set. */ if( ~planeMask & FbFullMask( pDestPixmap->drawable.depth ) ) return FALSE; viac->savedCommand = VIA_GEC_BLT | (viaCopyRop[alu] << 24); if( dx < 0 ) viac->savedCommand |= VIA_GEC_DECX; if( dy < 0 ) viac->savedCommand |= VIA_GEC_DECY; /* ** Store pointer to chip structure, due to brain-damaged KAA. */ card = viac; return TRUE; } /* ** void viaCopy( int srcX, int srcY, int dstX, int dstY, int w, int h ) ** ** Description: ** Perform a BitBlt from one screen area to another. ** ** Arguments: ** srcX source x-coordinate ** srcY source y-coordinate ** dstX destination x-coordinate ** dstY destination y-coordinate ** w width of area to copy (pixels) ** h height of area to copy (pixels) ** ** Return: ** None. ** ** See Also: ** viaPrepareCopy - the function which sets up for the copy. */ static void viaCopy( int srcX, int srcY, int dstX, int dstY, int w, int h ) { ViaCardInfo* viac = card; if( !viac ) return; if( !w | !h ) return; /* ** XXX: Check these two "if"s out. */ if( viac->savedCommand & VIA_GEC_DECX ) { srcX += ( w - 1 ); dstX += ( w - 1 ); } if( viac->savedCommand & VIA_GEC_DECY ) { srcY += ( h - 1 ); dstY += ( h - 1 ); } OUTREG32( VIA_REG_SRCPOS, ((srcY << 16) | srcX) ); OUTREG32( VIA_REG_DSTPOS, ((dstY << 16) | dstX) ); OUTREG32( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)) ); OUTREG32( VIA_REG_GECMD, viac->savedCommand ); } /* ** void viaDoneCopy() ** ** Description: ** Finish up the copy. ** ** Arguments: ** None. ** ** Return: ** None. */ static void viaDoneCopy(void) { } /* ** Bool viaDrawInit( ScreenPtr pScreen ) ** ** Description: ** Initialize the 2D acceleration hardware and register the KAA ** acceleration layer with the VIA acceleration functions (above). ** ** Arguments: ** pScreen Pointer to screen structure for the screen we're ** enabling acceleration on. ** ** Return: ** TRUE initialization and setup of KAA acceleration was successful. ** FALSE initialization and setup of KAA acceleration failed. */ Bool viaDrawInit( ScreenPtr pScreen ) { KdScreenPriv( pScreen ); ViaCardInfo* viac = pScreenPriv->card->driver; ViaScreenInfo* vias = pScreenPriv->card->driver; CARD32 geMode = 0; if( !viac ) return FALSE; DebugF( "viac->mapBase = 0x%x\n", viac->mapBase ); /* ** We reset the 2D engine to a known state by setting all of it's ** registers to zero. */ OUTREG32( VIA_REG_GEMODE, 0x0 ); OUTREG32( VIA_REG_SRCPOS, 0x0 ); OUTREG32( VIA_REG_DSTPOS, 0x0 ); OUTREG32( VIA_REG_DIMENSION, 0x0 ); OUTREG32( VIA_REG_PATADDR, 0x0 ); OUTREG32( VIA_REG_FGCOLOR, 0x0 ); OUTREG32( VIA_REG_BGCOLOR, 0x0 ); OUTREG32( VIA_REG_CLIPTL, 0x0 ); OUTREG32( VIA_REG_CLIPBR, 0x0 ); OUTREG32( VIA_REG_OFFSET, 0x0 ); OUTREG32( VIA_REG_KEYCONTROL, 0x0 ); OUTREG32( VIA_REG_SRCBASE, 0x0 ); OUTREG32( VIA_REG_DSTBASE, 0x0 ); OUTREG32( VIA_REG_PITCH, 0x0 ); OUTREG32( VIA_REG_MONOPAT0, 0x0 ); OUTREG32( VIA_REG_MONOPAT1, 0x0 ); /* ** Set the GE mode up. ** XXX: What happens in 24bpp mode? */ switch( pScreenPriv->screen->fb[0].bitsPerPixel ) { case 16: geMode = VIA_GEM_16bpp; break; case 32: geMode = VIA_GEM_32bpp; break; default: geMode = VIA_GEM_8bpp; break; } OUTREG32( VIA_REG_GEMODE, geMode ); /* ** Set the source and destination base addresses, and set pitch. */ OUTREG32( VIA_REG_SRCBASE, 0x0 ); OUTREG32( VIA_REG_DSTBASE, 0x0 ); OUTREG32( VIA_REG_PITCH, VIA_PITCH_ENABLE | ((pScreen->width * pScreenPriv->screen->fb[0].bitsPerPixel >> 3) >> 3) | (((pScreen->width * pScreenPriv->screen->fb[0].bitsPerPixel >> 3) >> 3) << 16)); DebugF( "Initialized 2D engine!\n" ); memset(&vias->kaa, 0, sizeof(KaaScreenInfoRec)); vias->kaa.waitMarker = viaWaitMarker; vias->kaa.PrepareSolid = viaPrepareSolid; vias->kaa.Solid = viaSolid; vias->kaa.DoneSolid = viaDoneSolid; vias->kaa.PrepareCopy = viaPrepareCopy; vias->kaa.Copy = viaCopy; vias->kaa.DoneCopy = viaDoneCopy; return kaaDrawInit( pScreen, &vias->kaa ); } /* ** void viaDrawEnable( ScreenPtr pScreen ) ** ** Description: ** Enable accelerated drawing on the specified screen. ** ** Arguments: ** pScreen Pointer to screen structure for the screen we're ** enabling acceleration on. ** ** Return: ** None. */ void viaDrawEnable( ScreenPtr pScreen ) { kaaMarkSync( pScreen ); } /* ** void viaDrawDisable( ScreenPtr pScreen ) ** ** Description: ** Disable accelerated drawing to the specified screen. ** ** Arguments: ** pScreen Pointer to screen structure for the screen we're ** disabling acceleration on. ** ** Return: ** None */ void viaDrawDisable( ScreenPtr pScreen ) { } /* ** void viaDrawFini( ScreenPtr pScreen ) ** ** Description: ** Shutdown accelerated drawing and free associated strucures and ** resources. ** ** Arguments: ** pScreen Pointer to screen structure for the screen we're ** disabling acceleration on. ** ** Return: ** None. */ void viaDrawFini( ScreenPtr pScreen ) { }