241 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * $Id$
 | 
						|
 *
 | 
						|
 * Copyright © 2003 Eric Anholt
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice appear in all copies and that both that
 | 
						|
 * copyright notice and this permission notice appear in supporting
 | 
						|
 * documentation, and that the name of Eric Anholt not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission.  Eric Anholt makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | 
						|
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
						|
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
 * PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 */
 | 
						|
/* $Header$ */
 | 
						|
 | 
						|
#ifdef USE_DMA
 | 
						|
#define TAG(x)		x##DMA
 | 
						|
#define LOCALS		RING_LOCALS; \
 | 
						|
			(void)atic
 | 
						|
#define BEGIN(x)	BEGIN_RING(x * 2)
 | 
						|
#define OUT_REG(reg, val) OUT_RING_REG(reg, val)
 | 
						|
#define END()		ADVANCE_RING()
 | 
						|
#else
 | 
						|
#define TAG(x)		x##MMIO
 | 
						|
#define LOCALS		char *mmio = atic->reg_base; \
 | 
						|
			(void)atis
 | 
						|
#define BEGIN(x)	ATIWaitAvailMMIO(x)
 | 
						|
#define OUT_REG(reg, val) MMIO_OUT32((mmio), (reg), (val))
 | 
						|
#define END()
 | 
						|
#endif
 | 
						|
 | 
						|
static Bool
 | 
						|
TAG(ATISetup)(PixmapPtr pDst, PixmapPtr pSrc)
 | 
						|
{
 | 
						|
	KdScreenPriv(pDst->drawable.pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	int dst_offset, dst_pitch;
 | 
						|
	int bpp = pDst->drawable.bitsPerPixel;
 | 
						|
	LOCALS;
 | 
						|
 | 
						|
	accel_atis = atis;
 | 
						|
 | 
						|
	dst_pitch = pDst->devKind;
 | 
						|
	dst_offset = ((CARD8 *)pDst->devPrivate.ptr -
 | 
						|
	    pScreenPriv->screen->memory_base);
 | 
						|
	if ((dst_pitch & (atis->kaa.offscreenPitch - 1)) != 0)
 | 
						|
		ATI_FALLBACK(("Bad dst pitch 0x%x\n", dst_pitch));
 | 
						|
	if ((dst_offset & (atis->kaa.offscreenByteAlign - 1)) != 0)
 | 
						|
		ATI_FALLBACK(("Bad dst offset 0x%x\n", dst_offset));
 | 
						|
 | 
						|
	if (pSrc != NULL) {
 | 
						|
		src_pitch = pSrc->devKind;
 | 
						|
		src_offset = ((CARD8 *)pSrc->devPrivate.ptr -
 | 
						|
		    pScreenPriv->screen->memory_base);
 | 
						|
		if ((src_pitch & (atis->kaa.offscreenPitch - 1)) != 0)
 | 
						|
			ATI_FALLBACK(("Bad src pitch 0x%x\n", src_pitch));
 | 
						|
		if ((src_offset & (atis->kaa.offscreenByteAlign - 1)) != 0)
 | 
						|
			ATI_FALLBACK(("Bad src offset 0x%x\n", src_offset));
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef USE_DMA
 | 
						|
	if (atic->is_radeon && !atic->is_r200)
 | 
						|
		RadeonSwitchTo2D();
 | 
						|
#endif
 | 
						|
	BEGIN((pSrc != NULL) ? 3 : 2);
 | 
						|
	if (atic->is_radeon) {
 | 
						|
		OUT_REG(RADEON_REG_DST_PITCH_OFFSET,
 | 
						|
		    ((dst_pitch >> 6) << 22) | (dst_offset >> 10));
 | 
						|
		if (pSrc != NULL) {
 | 
						|
			OUT_REG(RADEON_REG_SRC_PITCH_OFFSET,
 | 
						|
			    ((src_pitch >> 6) << 22) | (src_offset >> 10));
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (is_24bpp) {
 | 
						|
			dst_pitch *= 3;
 | 
						|
			src_pitch *= 3;
 | 
						|
		}
 | 
						|
		/* R128 pitch is in units of 8 pixels, offset in 32 bytes */
 | 
						|
		OUT_REG(RADEON_REG_DST_PITCH_OFFSET,
 | 
						|
		    ((dst_pitch/bpp) << 21) | (dst_offset >> 5));
 | 
						|
		if (pSrc != NULL) {
 | 
						|
			OUT_REG(RADEON_REG_SRC_PITCH_OFFSET,
 | 
						|
			    ((src_pitch/bpp) << 21) | (src_offset >> 5));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	OUT_REG(RADEON_REG_DEFAULT_SC_BOTTOM_RIGHT,
 | 
						|
	    (RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX));
 | 
						|
	END();
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
TAG(ATIPrepareSolid)(PixmapPtr pPixmap, int alu, Pixel pm, Pixel fg)
 | 
						|
{
 | 
						|
	KdScreenPriv(pPixmap->drawable.pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	CARD32 datatype;
 | 
						|
	LOCALS;
 | 
						|
 | 
						|
	if (is_24bpp) {
 | 
						|
		/* Solid fills in fake-24bpp mode only work if the pixel color
 | 
						|
		 * and planemask are all the same byte.
 | 
						|
		 */
 | 
						|
		if ((fg & 0xffffff) != (((fg & 0xff) << 16) | ((fg >> 8) &
 | 
						|
		    0xffff)))
 | 
						|
			ATI_FALLBACK(("Can't do solid color %d in 24bpp\n"));
 | 
						|
		if ((pm & 0xffffff) != (((pm & 0xff) << 16) | ((pm >> 8) &
 | 
						|
		    0xffff)))
 | 
						|
			ATI_FALLBACK(("Can't do planemask %d in 24bpp\n"));
 | 
						|
	}
 | 
						|
 | 
						|
	if (!ATIGetDatatypeBpp(pPixmap->drawable.bitsPerPixel, &datatype))
 | 
						|
		return FALSE;
 | 
						|
	if (!TAG(ATISetup)(pPixmap, NULL))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	BEGIN(4);
 | 
						|
	OUT_REG(RADEON_REG_DP_GUI_MASTER_CNTL,
 | 
						|
	    (datatype << 8) |
 | 
						|
	    RADEON_GMC_CLR_CMP_CNTL_DIS |
 | 
						|
	    RADEON_GMC_AUX_CLIP_DIS |
 | 
						|
	    RADEON_GMC_BRUSH_SOLID_COLOR |
 | 
						|
	    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
 | 
						|
	    RADEON_GMC_SRC_DATATYPE_COLOR |
 | 
						|
	    (ATISolidRop[alu] << 16));
 | 
						|
	OUT_REG(RADEON_REG_DP_BRUSH_FRGD_CLR, fg);
 | 
						|
	OUT_REG(RADEON_REG_DP_WRITE_MASK, pm);
 | 
						|
	OUT_REG(RADEON_REG_DP_CNTL, RADEON_DST_X_LEFT_TO_RIGHT |
 | 
						|
	    RADEON_DST_Y_TOP_TO_BOTTOM);
 | 
						|
	END();
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
TAG(ATISolid)(int x1, int y1, int x2, int y2)
 | 
						|
{
 | 
						|
	ATIScreenInfo *atis = accel_atis;
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	LOCALS;
 | 
						|
	
 | 
						|
	if (is_24bpp) {
 | 
						|
		x1 *= 3;
 | 
						|
		x2 *= 3;
 | 
						|
	}
 | 
						|
	BEGIN(2);
 | 
						|
	OUT_REG(RADEON_REG_DST_Y_X, (y1 << 16) | x1);
 | 
						|
	OUT_REG(RADEON_REG_DST_WIDTH_HEIGHT, ((x2 - x1) << 16) | (y2 - y1));
 | 
						|
	END();
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
TAG(ATIPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, Pixel pm)
 | 
						|
{
 | 
						|
	KdScreenPriv(pDst->drawable.pScreen);
 | 
						|
	ATIScreenInfo(pScreenPriv);
 | 
						|
	ATICardInfo(pScreenPriv);
 | 
						|
	CARD32 datatype;
 | 
						|
	LOCALS;
 | 
						|
 | 
						|
	copydx = dx;
 | 
						|
	copydy = dy;
 | 
						|
 | 
						|
	if (is_24bpp && ((pm & 0xffffff) != (((pm & 0xff) << 16) | ((pm >> 8) &
 | 
						|
	    0xffff))))
 | 
						|
		ATI_FALLBACK(("Can't do planemask %d in 24bpp\n"));
 | 
						|
 | 
						|
	if (!ATIGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
 | 
						|
		return FALSE;
 | 
						|
	if (!TAG(ATISetup)(pDst, pSrc))
 | 
						|
		return FALSE;
 | 
						|
 | 
						|
	BEGIN(3);
 | 
						|
	OUT_REG(RADEON_REG_DP_GUI_MASTER_CNTL,
 | 
						|
	    (datatype << 8) |
 | 
						|
	    RADEON_GMC_CLR_CMP_CNTL_DIS |
 | 
						|
	    RADEON_GMC_AUX_CLIP_DIS |
 | 
						|
	    RADEON_GMC_BRUSH_SOLID_COLOR |
 | 
						|
	    RADEON_GMC_SRC_DATATYPE_COLOR |
 | 
						|
	    (ATIBltRop[alu] << 16) |
 | 
						|
	    RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
 | 
						|
	    RADEON_GMC_DST_PITCH_OFFSET_CNTL |
 | 
						|
	    RADEON_DP_SRC_SOURCE_MEMORY);
 | 
						|
	OUT_REG(RADEON_REG_DP_WRITE_MASK, pm);
 | 
						|
	OUT_REG(RADEON_REG_DP_CNTL, 
 | 
						|
	    (dx >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) |
 | 
						|
	    (dy >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0));
 | 
						|
	END();
 | 
						|
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
TAG(ATICopy)(int srcX, int srcY, int dstX, int dstY, int w, int h)
 | 
						|
{
 | 
						|
	ATIScreenInfo *atis = accel_atis;
 | 
						|
	ATICardInfo *atic = atis->atic;
 | 
						|
	LOCALS;
 | 
						|
 | 
						|
	if (is_24bpp) {
 | 
						|
		srcX *= 3;
 | 
						|
		dstX *= 3;
 | 
						|
		w *= 3;
 | 
						|
	}
 | 
						|
 | 
						|
	if (copydx < 0) {
 | 
						|
		srcX += w - 1;
 | 
						|
		dstX += w - 1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (copydy < 0)  {
 | 
						|
		srcY += h - 1;
 | 
						|
		dstY += h - 1;
 | 
						|
	}
 | 
						|
 | 
						|
	BEGIN(3);
 | 
						|
	OUT_REG(RADEON_REG_SRC_Y_X, (srcY << 16) | srcX);
 | 
						|
	OUT_REG(RADEON_REG_DST_Y_X, (dstY << 16) | dstX);
 | 
						|
	OUT_REG(RADEON_REG_DST_HEIGHT_WIDTH, (h << 16) | w);
 | 
						|
	END();
 | 
						|
}
 | 
						|
 | 
						|
#undef TAG
 | 
						|
#undef LOCALS
 | 
						|
#undef BEGIN
 | 
						|
#undef OUT_REG
 | 
						|
#undef END
 |