xserver-multidpi/hw/kdrive/via/viadraw.c
Eric Anholt 545c082cf9 - Replace the syncAccel hook in the kdrive structure with a pair of hooks
in the kaa structure: markSync and waitMarker. The first, if set,
    returns a hardware-dependent marker number which can then be waited for
    with waitMarker. If markSync is absent (which is the case on all
    drivers currently), waitMarker must wait for idle on any given marker
    number. The intention is to allow for more parallelism when we get
    downloading from framebuffer, or more fine-grained idling.
- Replace the KdMarkSync/KdCheckSync functions with kaaMarkSync and
    kaaWaitSync. These will need to be refined when KAA starts being smart
    about using them. Merge kpict.c into kasync.c since kasyn.c has all the
    rest of these fallback funcs.
- Restructure all drivers to initialize a KaaInfo structure by hand rather
    than statically in dubious order.
- Whack the i810 driver into shape in hopes that it'll work after this
    change (it certainly wouldn't have before this). Doesn't support my
    i845 though.
- Make a new KXV helper to avoid duplicated code to fill the region with
    the necessary color key. Use it in i810 and mach64 (tested).
2005-06-09 10:44:45 +00:00

500 lines
13 KiB
C

/*
* 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 <ralpht@gmail.com>
**
** 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 <sched.h>
#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 ) {
}