mirror of
https://github.com/X11Libre/xserver.git
synced 2026-10-16 00:19:55 +00:00
- Add monochrome hardware cursor support.
- Try to auto-detect AGP support for DRI on Radeons. And fail. Detect it
properly on R128.
- Set up card for pseudo-DMA if possible. Convert 2D rendering code to
prepare DMA packets only. Use generic code to decode DMA packets to
MMIO if PDMA is unavailable. Add WIP code to support "real" DMA without
DRM support.
- Dispatch pending DMA commands when the server sleeps. Otherwise some
things, such as typing in an xterm, wouldn't show up for a time.
- Fix Radeon Composite acceleration in many ways, and add Rage 128
Composite acceleration. Disable them both due to still-not-understood
issues they have. They fail with In, Out, AtopReverse, and Xor, and
text rendering is strange.
- Add textured XV support for R100 and Rage 128. No brightness/sat
controls, but it does support multiple ports, and cooperates with
Composite.
- Add WIP code for hostdata uploads.
- Many cleanups and fixes.
805 lines
21 KiB
C
805 lines
21 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 HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
#include "ati.h"
|
|
#include "ati_reg.h"
|
|
#include "ati_dma.h"
|
|
#include "ati_draw.h"
|
|
|
|
CARD8 ATISolidRop[16] = {
|
|
/* GXclear */ 0x00, /* 0 */
|
|
/* GXand */ 0xa0, /* src AND dst */
|
|
/* GXandReverse */ 0x50, /* src AND NOT dst */
|
|
/* GXcopy */ 0xf0, /* src */
|
|
/* GXandInverted*/ 0x0a, /* NOT src AND dst */
|
|
/* GXnoop */ 0xaa, /* dst */
|
|
/* GXxor */ 0x5a, /* src XOR dst */
|
|
/* GXor */ 0xfa, /* src OR dst */
|
|
/* GXnor */ 0x05, /* NOT src AND NOT dst */
|
|
/* GXequiv */ 0xa5, /* NOT src XOR dst */
|
|
/* GXinvert */ 0x55, /* NOT dst */
|
|
/* GXorReverse */ 0xf5, /* src OR NOT dst */
|
|
/* GXcopyInverted*/ 0x0f, /* NOT src */
|
|
/* GXorInverted */ 0xaf, /* NOT src OR dst */
|
|
/* GXnand */ 0x5f, /* NOT src OR NOT dst */
|
|
/* GXset */ 0xff, /* 1 */
|
|
};
|
|
|
|
CARD8 ATIBltRop[16] = {
|
|
/* GXclear */ 0x00, /* 0 */
|
|
/* GXand */ 0x88, /* src AND dst */
|
|
/* GXandReverse */ 0x44, /* src AND NOT dst */
|
|
/* GXcopy */ 0xcc, /* src */
|
|
/* GXandInverted*/ 0x22, /* NOT src AND dst */
|
|
/* GXnoop */ 0xaa, /* dst */
|
|
/* GXxor */ 0x66, /* src XOR dst */
|
|
/* GXor */ 0xee, /* src OR dst */
|
|
/* GXnor */ 0x11, /* NOT src AND NOT dst */
|
|
/* GXequiv */ 0x99, /* NOT src XOR dst */
|
|
/* GXinvert */ 0x55, /* NOT dst */
|
|
/* GXorReverse */ 0xdd, /* src OR NOT dst */
|
|
/* GXcopyInverted*/ 0x33, /* NOT src */
|
|
/* GXorInverted */ 0xbb, /* NOT src OR dst */
|
|
/* GXnand */ 0x77, /* NOT src OR NOT dst */
|
|
/* GXset */ 0xff, /* 1 */
|
|
};
|
|
|
|
int copydx, copydy;
|
|
ATIScreenInfo *accel_atis;
|
|
/* If is_24bpp is set, then we are using the accelerator in 8-bit mode due
|
|
* to it being broken for 24bpp, so coordinates have to be multiplied by 3.
|
|
*/
|
|
Bool is_24bpp;
|
|
CARD32 settings, color, src_pitch_offset, dst_pitch_offset;
|
|
|
|
#define DRAW_USING_PACKET3 0
|
|
|
|
void
|
|
ATIDrawSetup(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
ATICardInfo(pScreenPriv);
|
|
char *mmio = atic->reg_base;
|
|
RING_LOCALS;
|
|
|
|
/* XXX: this shouldn't be necessary, but fixes some R128 composite
|
|
* issues.
|
|
*/
|
|
/*if (!atic->is_radeon) {
|
|
ATIWaitIdle(atis);
|
|
MMIO_OUT32(mmio, R128_REG_PC_GUI_MODE,
|
|
R128_PC_BYPASS_EN);
|
|
}*/
|
|
|
|
BEGIN_DMA(2);
|
|
OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
|
|
ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
|
|
END_DMA();
|
|
|
|
if (!atic->is_radeon) {
|
|
/* Setup for R128 Composite */
|
|
BEGIN_DMA(12);
|
|
OUT_REG(R128_REG_SCALE_3D_CNTL,
|
|
R128_SCALE_3D_TEXMAP_SHADE |
|
|
R128_SCALE_PIX_REPLICATE |
|
|
R128_TEX_CACHE_SPLIT |
|
|
R128_TEX_MAP_ALPHA_IN_TEXTURE |
|
|
R128_TEX_CACHE_LINE_SIZE_4QW);
|
|
OUT_REG(R128_REG_SETUP_CNTL,
|
|
R128_COLOR_SOLID_COLOR |
|
|
R128_PRIM_TYPE_TRI |
|
|
R128_TEXTURE_ST_MULT_W |
|
|
R128_STARTING_VERTEX_1 |
|
|
R128_ENDING_VERTEX_3 |
|
|
R128_SUB_PIX_4BITS);
|
|
OUT_REG(R128_REG_PM4_VC_FPU_SETUP,
|
|
R128_FRONT_DIR_CCW |
|
|
R128_BACKFACE_CULL |
|
|
R128_FRONTFACE_SOLID |
|
|
R128_FPU_COLOR_SOLID |
|
|
R128_FPU_SUB_PIX_4BITS |
|
|
R128_FPU_MODE_3D |
|
|
R128_TRAP_BITS_DISABLE |
|
|
R128_XFACTOR_2 |
|
|
R128_YFACTOR_2 |
|
|
R128_FLAT_SHADE_VERTEX_OGL |
|
|
R128_FPU_ROUND_TRUNCATE |
|
|
R128_WM_SEL_8DW);
|
|
OUT_REG(R128_REG_PLANE_3D_MASK_C, 0xffffffff);
|
|
OUT_REG(R128_REG_CONSTANT_COLOR_C, 0xff000000);
|
|
OUT_REG(R128_REG_WINDOW_XY_OFFSET, 0x00000000);
|
|
END_DMA();
|
|
} else {
|
|
/* Setup for R100/R200 Composite */
|
|
BEGIN_DMA(8);
|
|
OUT_REG(RADEON_REG_RE_TOP_LEFT, 0);
|
|
OUT_REG(RADEON_REG_RE_WIDTH_HEIGHT, 0xffffffff);
|
|
OUT_REG(RADEON_REG_RB3D_PLANEMASK, 0xffffffff);
|
|
OUT_REG(RADEON_REG_SE_CNTL,
|
|
RADEON_FFACE_CULL_CCW |
|
|
RADEON_FFACE_SOLID |
|
|
RADEON_VTX_PIX_CENTER_OGL);
|
|
END_DMA();
|
|
|
|
if (atic->is_r100) {
|
|
BEGIN_DMA(4);
|
|
OUT_REG(RADEON_REG_SE_CNTL_STATUS, RADEON_TCL_BYPASS);
|
|
OUT_REG(RADEON_REG_SE_COORD_FMT,
|
|
RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
|
|
RADEON_VTX_ST0_NONPARAMETRIC |
|
|
RADEON_VTX_ST1_NONPARAMETRIC |
|
|
RADEON_TEX1_W_ROUTING_USE_W0);
|
|
END_DMA();
|
|
} else {
|
|
BEGIN_DMA(12);
|
|
OUT_REG(R200_REG_RE_CNTL, 0);
|
|
OUT_REG(R200_REG_SE_VTE_CNTL, R200_VTX_XY_FMT);
|
|
OUT_REG(R200_REG_SE_VTX_FMT_0, R200_VTX_XY);
|
|
OUT_REG(R200_REG_SE_VTX_FMT_1,
|
|
(4 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
|
|
(4 << R200_VTX_TEX1_COMP_CNT_SHIFT));
|
|
OUT_REG(R200_REG_SE_VAP_CNTL, 0);
|
|
OUT_REG(R200_REG_RE_AUX_SCISSOR_CNTL, 0);
|
|
END_DMA();
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
RadeonSwitchTo2D(ATIScreenInfo *atis)
|
|
{
|
|
RING_LOCALS;
|
|
|
|
BEGIN_DMA(2);
|
|
OUT_REG(ATI_REG_WAIT_UNTIL,
|
|
RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
|
|
END_DMA();
|
|
}
|
|
|
|
void
|
|
RadeonSwitchTo3D(ATIScreenInfo *atis)
|
|
{
|
|
RING_LOCALS;
|
|
|
|
BEGIN_DMA(2);
|
|
OUT_REG(ATI_REG_WAIT_UNTIL,
|
|
RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
|
|
END_DMA();
|
|
}
|
|
|
|
/* Assumes that depth 15 and 16 can be used as depth 16, which is okay since we
|
|
* require src and dest datatypes to be equal.
|
|
*/
|
|
static Bool
|
|
ATIGetDatatypeBpp(int bpp, CARD32 *type)
|
|
{
|
|
switch (bpp) {
|
|
case 8:
|
|
*type = R128_DATATYPE_CI8;
|
|
return TRUE;
|
|
case 16:
|
|
*type = R128_DATATYPE_RGB565;
|
|
return TRUE;
|
|
case 24:
|
|
*type = R128_DATATYPE_CI8;
|
|
return TRUE;
|
|
case 32:
|
|
*type = R128_DATATYPE_ARGB8888;
|
|
return TRUE;
|
|
default:
|
|
ATI_FALLBACK(("Unsupported bpp: %d\n", bpp));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
Bool
|
|
ATIGetOffsetPitch(ATIScreenInfo *atis, int bpp, CARD32 *pitch_offset,
|
|
int offset, int pitch)
|
|
{
|
|
ATICardInfo *atic = atis->atic;
|
|
|
|
/* On the R128, depending on the bpp the screen can be set up so that it
|
|
* doesn't meet the offscreenPitch requirement but can still be
|
|
* accelerated, so we check the specific pitch requirement of alignment
|
|
* to 8 pixels.
|
|
*/
|
|
if (atic->is_radeon) {
|
|
if (pitch % atis->kaa.offscreenPitch != 0)
|
|
ATI_FALLBACK(("Bad pitch 0x%08x\n", pitch));
|
|
*pitch_offset = ((pitch >> 6) << 22) | (offset >> 10);
|
|
|
|
} else {
|
|
if (pitch % bpp != 0)
|
|
ATI_FALLBACK(("Bad pitch 0x%08x\n", pitch));
|
|
*pitch_offset = ((pitch / bpp) << 21) | (offset >> 5);
|
|
}
|
|
|
|
if (offset % atis->kaa.offscreenByteAlign != 0)
|
|
ATI_FALLBACK(("Bad offset 0x%08x\n", offset));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
ATIGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset)
|
|
{
|
|
KdScreenPriv(pPix->drawable.pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
CARD32 pitch, offset;
|
|
int bpp;
|
|
|
|
bpp = pPix->drawable.bitsPerPixel;
|
|
if (bpp == 24)
|
|
bpp = 8;
|
|
|
|
offset = ((CARD8 *)pPix->devPrivate.ptr -
|
|
pScreenPriv->screen->memory_base);
|
|
pitch = pPix->devKind;
|
|
|
|
return ATIGetOffsetPitch(atis, bpp, pitch_offset, offset, pitch);
|
|
}
|
|
|
|
static Bool
|
|
ATIPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
|
|
{
|
|
KdScreenPriv(pPix->drawable.pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
ATICardInfo(pScreenPriv);
|
|
CARD32 datatype;
|
|
RING_LOCALS;
|
|
|
|
is_24bpp = (pPix->drawable.bitsPerPixel == 24);
|
|
accel_atis = atis;
|
|
|
|
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 0x%08x in 24bpp\n",
|
|
fg));
|
|
if ((pm & 0xffffff) != (((pm & 0xff) << 16) | ((pm >> 8) &
|
|
0xffff)))
|
|
ATI_FALLBACK(("Can't do planemask 0x%08x in 24bpp\n",
|
|
pm));
|
|
}
|
|
|
|
if (!ATIGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype))
|
|
return FALSE;
|
|
if (!ATIGetPixmapOffsetPitch(pPix, &dst_pitch_offset))
|
|
return FALSE;
|
|
|
|
if (atic->is_radeon)
|
|
RadeonSwitchTo2D(atis);
|
|
|
|
settings =
|
|
ATI_GMC_DST_PITCH_OFFSET_CNTL |
|
|
ATI_GMC_BRUSH_SOLID_COLOR |
|
|
(datatype << 8) |
|
|
ATI_GMC_SRC_DATATYPE_COLOR |
|
|
(ATISolidRop[alu] << 16) |
|
|
ATI_GMC_CLR_CMP_CNTL_DIS |
|
|
R128_GMC_AUX_CLIP_DIS;
|
|
color = fg;
|
|
|
|
#if DRAW_USING_PACKET3
|
|
BEGIN_DMA(6);
|
|
OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
|
|
ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
|
|
OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
|
|
OUT_REG(ATI_REG_DP_CNTL, ATI_DST_X_LEFT_TO_RIGHT |
|
|
ATI_DST_Y_TOP_TO_BOTTOM);
|
|
END_DMA();
|
|
#else
|
|
BEGIN_DMA(12);
|
|
OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
|
|
ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
|
|
OUT_REG(ATI_REG_DST_PITCH_OFFSET, dst_pitch_offset);
|
|
OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, settings);
|
|
OUT_REG(ATI_REG_DP_BRUSH_FRGD_CLR, fg);
|
|
OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
|
|
OUT_REG(ATI_REG_DP_CNTL, ATI_DST_X_LEFT_TO_RIGHT |
|
|
ATI_DST_Y_TOP_TO_BOTTOM);
|
|
END_DMA();
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
ATISolid(int x1, int y1, int x2, int y2)
|
|
{
|
|
ATIScreenInfo *atis = accel_atis;
|
|
RING_LOCALS;
|
|
|
|
if (is_24bpp) {
|
|
x1 *= 3;
|
|
x2 *= 3;
|
|
}
|
|
#if DRAW_USING_PACKET3
|
|
BEGIN_DMA(6);
|
|
OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_PAINT_MULTI, 5));
|
|
OUT_RING(settings);
|
|
OUT_RING(dst_pitch_offset);
|
|
OUT_RING(color);
|
|
OUT_RING((x1 << 16) | y1);
|
|
OUT_RING(((x2 - x1) << 16) | (y2 - y1));
|
|
END_DMA();
|
|
#else
|
|
BEGIN_DMA(3);
|
|
OUT_RING(DMA_PACKET0(ATI_REG_DST_Y_X, 2));
|
|
OUT_RING((y1 << 16) | x1);
|
|
OUT_RING(((y2 - y1) << 16) | (x2 - x1));
|
|
END_DMA();
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ATIDoneSolid(void)
|
|
{
|
|
}
|
|
|
|
static Bool
|
|
ATIPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, Pixel pm)
|
|
{
|
|
KdScreenPriv(pDst->drawable.pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
ATICardInfo(pScreenPriv);
|
|
CARD32 datatype;
|
|
RING_LOCALS;
|
|
|
|
copydx = dx;
|
|
copydy = dy;
|
|
is_24bpp = pDst->drawable.bitsPerPixel == 24;
|
|
accel_atis = atis;
|
|
|
|
if (is_24bpp && ((pm & 0xffffff) != (((pm & 0xff) << 16) | ((pm >> 8) &
|
|
0xffff))))
|
|
ATI_FALLBACK(("Can't do planemask 0x%08x in 24bpp\n", pm));
|
|
|
|
if (!ATIGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype))
|
|
return FALSE;
|
|
if (!ATIGetPixmapOffsetPitch(pSrc, &src_pitch_offset))
|
|
return FALSE;
|
|
if (!ATIGetPixmapOffsetPitch(pDst, &dst_pitch_offset))
|
|
return FALSE;
|
|
|
|
if (atic->is_radeon)
|
|
RadeonSwitchTo2D(atis);
|
|
|
|
settings =
|
|
ATI_GMC_SRC_PITCH_OFFSET_CNTL |
|
|
ATI_GMC_DST_PITCH_OFFSET_CNTL |
|
|
ATI_GMC_BRUSH_NONE |
|
|
(datatype << 8) |
|
|
ATI_GMC_SRC_DATATYPE_COLOR |
|
|
(ATIBltRop[alu] << 16) |
|
|
ATI_DP_SRC_SOURCE_MEMORY |
|
|
ATI_GMC_CLR_CMP_CNTL_DIS |
|
|
R128_GMC_AUX_CLIP_DIS;
|
|
|
|
#if DRAW_USING_PACKET3
|
|
BEGIN_DMA(6);
|
|
OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
|
|
ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
|
|
OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
|
|
OUT_REG(ATI_REG_DP_CNTL,
|
|
(dx >= 0 ? ATI_DST_X_LEFT_TO_RIGHT : 0) |
|
|
(dy >= 0 ? ATI_DST_Y_TOP_TO_BOTTOM : 0));
|
|
END_DMA();
|
|
|
|
#else
|
|
BEGIN_DMA(12);
|
|
OUT_REG(ATI_REG_DEFAULT_SC_BOTTOM_RIGHT,
|
|
ATI_DEFAULT_SC_RIGHT_MAX | ATI_DEFAULT_SC_BOTTOM_MAX);
|
|
OUT_REG(ATI_REG_SRC_PITCH_OFFSET, src_pitch_offset);
|
|
OUT_REG(ATI_REG_DST_PITCH_OFFSET, dst_pitch_offset);
|
|
OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, settings);
|
|
OUT_REG(ATI_REG_DP_WRITE_MASK, pm);
|
|
OUT_REG(ATI_REG_DP_CNTL,
|
|
(dx >= 0 ? ATI_DST_X_LEFT_TO_RIGHT : 0) |
|
|
(dy >= 0 ? ATI_DST_Y_TOP_TO_BOTTOM : 0));
|
|
END_DMA();
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
ATICopy(int srcX, int srcY, int dstX, int dstY, int w, int h)
|
|
{
|
|
ATIScreenInfo *atis = accel_atis;
|
|
RING_LOCALS;
|
|
|
|
if (is_24bpp) {
|
|
srcX *= 3;
|
|
dstX *= 3;
|
|
w *= 3;
|
|
}
|
|
|
|
#if !DRAW_USING_PACKET3
|
|
if (copydx < 0) {
|
|
srcX += w - 1;
|
|
dstX += w - 1;
|
|
}
|
|
|
|
if (copydy < 0) {
|
|
srcY += h - 1;
|
|
dstY += h - 1;
|
|
}
|
|
#endif
|
|
|
|
#if DRAW_USING_PACKET3
|
|
BEGIN_DMA(7);
|
|
OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_BITBLT_MULTI, 6));
|
|
OUT_RING(settings);
|
|
OUT_RING(src_pitch_offset);
|
|
OUT_RING(dst_pitch_offset);
|
|
OUT_RING((srcX << 16) | srcY);
|
|
OUT_RING((dstX << 16) | dstY);
|
|
OUT_RING((w << 16) | h);
|
|
END_DMA();
|
|
#else
|
|
BEGIN_DMA(4);
|
|
OUT_RING(DMA_PACKET0(ATI_REG_SRC_Y_X, 3));
|
|
OUT_RING((srcY << 16) | srcX);
|
|
OUT_RING((dstY << 16) | dstX);
|
|
OUT_RING((h << 16) | w);
|
|
END_DMA();
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
ATIDoneCopy(void)
|
|
{
|
|
}
|
|
|
|
static Bool
|
|
ATIUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
|
|
{
|
|
ScreenPtr pScreen = pDst->drawable.pScreen;
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
ATICardInfo(pScreenPriv);
|
|
int width, height, bpp, i, dwords;
|
|
int dst_pitch, dst_offset;
|
|
CARD32 dst_pitch_offset, datatype;
|
|
Bool success;
|
|
RING_LOCALS;
|
|
|
|
dst_offset = ((CARD8 *)pDst->devPrivate.ptr -
|
|
pScreenPriv->screen->memory_base);
|
|
dst_pitch = pDst->devKind;
|
|
width = pDst->drawable.width;
|
|
height = pDst->drawable.height;
|
|
bpp = pDst->drawable.bitsPerPixel;
|
|
|
|
success = ATIGetDatatypeBpp(bpp, &datatype);
|
|
|
|
if (bpp == 24) {
|
|
is_24bpp = TRUE;
|
|
bpp = 8;
|
|
} else
|
|
is_24bpp = FALSE;
|
|
|
|
if (!ATIGetOffsetPitch(atis, bpp, &dst_pitch_offset, dst_offset,
|
|
dst_pitch))
|
|
return FALSE;
|
|
|
|
if (src_pitch != (width * bpp / 8))
|
|
return FALSE;
|
|
|
|
/* No PACKET3 packets when in PIO mode. */
|
|
if (atis->using_pio)
|
|
return FALSE;
|
|
|
|
/* XXX: Hostdata uploads aren't working yet. */
|
|
return FALSE;
|
|
|
|
dwords = (width * height * (bpp / 8) + 3) / 4;
|
|
|
|
/* Flush pixel cache so nothing being written to the destination
|
|
* previously gets mixed up with the hostdata blit.
|
|
*/
|
|
if (atic->is_radeon) {
|
|
BEGIN_DMA(4);
|
|
OUT_REG(RADEON_REG_RB2D_DSTCACHE_CTLSTAT,
|
|
RADEON_RB2D_DC_FLUSH);
|
|
OUT_REG(ATI_REG_WAIT_UNTIL,
|
|
RADEON_WAIT_2D_IDLECLEAN |
|
|
RADEON_WAIT_3D_IDLECLEAN |
|
|
RADEON_WAIT_HOST_IDLECLEAN);
|
|
END_DMA();
|
|
} else {
|
|
BEGIN_DMA(2);
|
|
OUT_REG(R128_REG_PC_GUI_CTLSTAT,
|
|
R128_PC_FLUSH_GUI | R128_PC_RI_GUI);
|
|
END_DMA();
|
|
}
|
|
|
|
BEGIN_DMA(8);
|
|
OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_HOSTDATA_BLT, 7 + dwords));
|
|
OUT_RING(ATI_GMC_DST_PITCH_OFFSET_CNTL |
|
|
ATI_GMC_BRUSH_NONE |
|
|
(datatype << 8) |
|
|
ATI_GMC_SRC_DATATYPE_COLOR |
|
|
(ATISolidRop[GXcopy] << 16) |
|
|
ATI_DP_SRC_SOURCE_HOST_DATA |
|
|
ATI_GMC_CLR_CMP_CNTL_DIS |
|
|
R128_GMC_AUX_CLIP_DIS |
|
|
ATI_GMC_WR_MSK_DIS);
|
|
OUT_RING(dst_pitch_offset);
|
|
OUT_RING(0xffffffff);
|
|
OUT_RING(0xffffffff);
|
|
OUT_RING((0 << 16) | 0);
|
|
OUT_RING((height << 16) | width);
|
|
OUT_RING(dwords);
|
|
END_DMA();
|
|
|
|
for (i = 0; i < dwords; i++) {
|
|
BEGIN_DMA(1);
|
|
OUT_RING(((CARD32 *)src)[i]);
|
|
END_DMA();
|
|
}
|
|
|
|
if (atic->is_radeon) {
|
|
BEGIN_DMA(4);
|
|
OUT_REG(RADEON_REG_RB2D_DSTCACHE_CTLSTAT,
|
|
RADEON_RB2D_DC_FLUSH);
|
|
OUT_REG(ATI_REG_WAIT_UNTIL,
|
|
RADEON_WAIT_2D_IDLECLEAN |
|
|
RADEON_WAIT_HOST_IDLECLEAN);
|
|
END_DMA();
|
|
} else {
|
|
BEGIN_DMA(2);
|
|
OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_GUI);
|
|
END_DMA();
|
|
}
|
|
|
|
KdMarkSync(pScreen);
|
|
|
|
ErrorF("hostdata upload %d,%d %dbpp\n", width, height, bpp);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static Bool
|
|
ATIUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst)
|
|
{
|
|
KdScreenPriv(pSrc->drawable.pScreen);
|
|
ATICardInfo(pScreenPriv);
|
|
ATIScreenInfo(pScreenPriv);
|
|
int dst_pitch, src_pitch, w, i, size, bytes;
|
|
unsigned char *dst, *src;
|
|
RING_LOCALS;
|
|
|
|
/* Align width to log 2, useful for R128 composite. This should be a
|
|
* KAA flag we check for (and supported in kaa.c in general) since many
|
|
* older bits of hardware are going to want POT pitches.
|
|
*/
|
|
w = 1 << (ATILog2(pSrc->drawable.width - 1) + 1);
|
|
dst_pitch = (w * pSrc->drawable.bitsPerPixel / 8 +
|
|
atis->kaa.offscreenPitch - 1) & ~(atis->kaa.offscreenPitch - 1);
|
|
|
|
size = dst_pitch * pSrc->drawable.height;
|
|
if (size > atis->scratch_size)
|
|
ATI_FALLBACK(("Pixmap too large for scratch (%d,%d)\n",
|
|
pSrc->drawable.width, pSrc->drawable.height));
|
|
|
|
if (atis->scratch_next + size > atis->scratch_offset +
|
|
atis->scratch_size) {
|
|
/* Only sync when we've used all of the scratch area. */
|
|
KdCheckSync(pSrc->drawable.pScreen);
|
|
atis->scratch_next = atis->scratch_offset;
|
|
}
|
|
memcpy(pDst, pSrc, sizeof(*pDst));
|
|
pDst->devKind = dst_pitch;
|
|
pDst->devPrivate.ptr = atis->scratch_next +
|
|
pScreenPriv->screen->memory_base;
|
|
atis->scratch_next += size;
|
|
|
|
src = pSrc->devPrivate.ptr;
|
|
src_pitch = pSrc->devKind;
|
|
dst = pDst->devPrivate.ptr;
|
|
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
|
|
|
i = pSrc->drawable.height;
|
|
while (i--) {
|
|
memcpy(dst, src, bytes);
|
|
dst += dst_pitch;
|
|
src += src_pitch;
|
|
}
|
|
|
|
/* Flush the pixel cache */
|
|
if (atic->is_radeon) {
|
|
BEGIN_DMA(2);
|
|
OUT_REG(RADEON_REG_RB2D_DSTCACHE_CTLSTAT,
|
|
RADEON_RB2D_DC_FLUSH_ALL);
|
|
END_DMA();
|
|
} else {
|
|
BEGIN_DMA(2);
|
|
OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_ALL);
|
|
END_DMA();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
ATIBlockHandler (int screen, pointer blockData, pointer timeout,
|
|
pointer readmask)
|
|
{
|
|
ScreenPtr pScreen = screenInfo.screens[screen];
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
|
|
/* When the server is going to sleep, make sure that all DMA data has
|
|
* been flushed.
|
|
*/
|
|
ATIFlushIndirect(atis, 1);
|
|
}
|
|
|
|
Bool
|
|
ATIDrawInit(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
ATICardInfo(pScreenPriv);
|
|
|
|
ErrorF("Screen: %d/%d depth/bpp\n", pScreenPriv->screen->fb[0].depth,
|
|
pScreenPriv->screen->fb[0].bitsPerPixel);
|
|
|
|
#ifdef USE_DRI
|
|
atis->using_dri = ATIDRIScreenInit(pScreen);
|
|
#endif /* USE_DRI */
|
|
|
|
memset(&atis->kaa, 0, sizeof(KaaScreenInfoRec));
|
|
atis->kaa.PrepareSolid = ATIPrepareSolid;
|
|
atis->kaa.Solid = ATISolid;
|
|
atis->kaa.DoneSolid = ATIDoneSolid;
|
|
atis->kaa.PrepareCopy = ATIPrepareCopy;
|
|
atis->kaa.Copy = ATICopy;
|
|
atis->kaa.DoneCopy = ATIDoneCopy;
|
|
/* Other acceleration will be hooked in in DrawEnable depending on
|
|
* what type of DMA gets initialized.
|
|
*/
|
|
|
|
atis->kaa.flags = KAA_OFFSCREEN_PIXMAPS;
|
|
if (atic->is_radeon) {
|
|
atis->kaa.offscreenByteAlign = 1024;
|
|
atis->kaa.offscreenPitch = 64;
|
|
} else {
|
|
/* Rage 128 compositing wants power-of-two pitches. */
|
|
atis->kaa.flags |= KAA_OFFSCREEN_ALIGN_POT;
|
|
atis->kaa.offscreenByteAlign = 32;
|
|
/* Pitch alignment is in sets of 8 pixels, and we need to cover
|
|
* 32bpp, so 32 bytes.
|
|
*/
|
|
atis->kaa.offscreenPitch = 32;
|
|
}
|
|
|
|
if (!kaaDrawInit(pScreen, &atis->kaa))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
ATIDrawEnable(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
ATICardInfo(pScreenPriv);
|
|
|
|
ATIDMASetup(pScreen);
|
|
ATIDrawSetup(pScreen);
|
|
|
|
atis->kaa.PrepareBlend = NULL;
|
|
atis->kaa.Blend = NULL;
|
|
atis->kaa.DoneBlend = NULL;
|
|
atis->kaa.CheckComposite = NULL;
|
|
atis->kaa.PrepareComposite = NULL;
|
|
atis->kaa.Composite = NULL;
|
|
atis->kaa.DoneComposite = NULL;
|
|
/* XXX: The R128 Blend code has several issues, according to
|
|
* rendercheck. Source coordinates are sometimes wrong it appears, and
|
|
* in some cases the blending results are wrong.
|
|
*/
|
|
if (0 && !atic->is_radeon) {
|
|
atis->kaa.PrepareBlend = R128PrepareBlend;
|
|
atis->kaa.Blend = R128Blend;
|
|
atis->kaa.DoneBlend = R128DoneBlend;
|
|
}
|
|
|
|
/* We can't dispatch 3d commands in PIO mode. */
|
|
if (!atis->using_pio) {
|
|
if (0 && !atic->is_radeon) { /* XXX */
|
|
atis->kaa.CheckComposite = R128CheckComposite;
|
|
atis->kaa.PrepareComposite = R128PrepareComposite;
|
|
atis->kaa.Composite = R128Composite;
|
|
atis->kaa.DoneComposite = R128DoneComposite;
|
|
} else if (0 && atic->is_r100) { /* XXX */
|
|
atis->kaa.CheckComposite = R100CheckComposite;
|
|
atis->kaa.PrepareComposite = R100PrepareComposite;
|
|
atis->kaa.Composite = RadeonComposite;
|
|
atis->kaa.DoneComposite = RadeonDoneComposite;
|
|
} else if (0 && atic->is_r200) { /* XXX */
|
|
atis->kaa.CheckComposite = R200CheckComposite;
|
|
atis->kaa.PrepareComposite = R200PrepareComposite;
|
|
atis->kaa.Composite = RadeonComposite;
|
|
atis->kaa.DoneComposite = RadeonDoneComposite;
|
|
}
|
|
}
|
|
|
|
atis->kaa.UploadToScreen = ATIUploadToScreen;
|
|
atis->kaa.UploadToScratch = ATIUploadToScratch;
|
|
|
|
atis->save_blockhandler = pScreen->BlockHandler;
|
|
pScreen->BlockHandler = ATIBlockHandler;
|
|
|
|
KdMarkSync(pScreen);
|
|
}
|
|
|
|
void
|
|
ATIDrawDisable(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
|
|
ATIDMATeardown(pScreen);
|
|
|
|
pScreen->BlockHandler = atis->save_blockhandler;
|
|
}
|
|
|
|
void
|
|
ATIDrawFini(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
|
|
#ifdef USE_DRI
|
|
if (atis->using_dri) {
|
|
ATIDRICloseScreen(pScreen);
|
|
atis->using_dri = FALSE;
|
|
}
|
|
#endif /* USE_DRI */
|
|
|
|
kaaDrawFini(pScreen);
|
|
}
|
|
|
|
void
|
|
ATIDrawSync(ScreenPtr pScreen)
|
|
{
|
|
KdScreenPriv(pScreen);
|
|
ATIScreenInfo(pScreenPriv);
|
|
|
|
ATIWaitIdle(atis);
|
|
}
|