aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/kdrive/ati/ati_draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/kdrive/ati/ati_draw.c')
-rw-r--r--xorg-server/hw/kdrive/ati/ati_draw.c918
1 files changed, 918 insertions, 0 deletions
diff --git a/xorg-server/hw/kdrive/ati/ati_draw.c b/xorg-server/hw/kdrive/ati/ati_draw.c
new file mode 100644
index 000000000..c10fea471
--- /dev/null
+++ b/xorg-server/hw/kdrive/ati/ati_draw.c
@@ -0,0 +1,918 @@
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "ati.h"
+#include "ati_reg.h"
+#include "ati_dma.h"
+#include "ati_draw.h"
+#include "kaa.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;
+
+int sample_count;
+float sample_offsets_x[255];
+float sample_offsets_y[255];
+
+#define DRAW_USING_PACKET3 0
+
+void
+ATIDrawSetup(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ATIScreenInfo(pScreenPriv);
+ ATICardInfo(pScreenPriv);
+ RING_LOCALS;
+
+ /* XXX: this shouldn't be necessary, but fixes some R128 composite
+ * issues.
+ */
+ /*if (!atic->is_radeon) {
+ char *mmio = atic->reg_base;
+ 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 if (!atic->is_r300) {
+ /* 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(6);
+ 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);
+ OUT_REG(RADEON_REG_RB3D_DSTCACHE_MODE,
+ RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH |
+ RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH);
+ END_DMA();
+ } else {
+ BEGIN_DMA(18);
+ /* XXX: The 0 below should be RADEON_TCL_BYPASS on
+ * RS300s.
+ */
+ OUT_REG(R200_REG_SE_VAP_CNTL_STATUS, 0);
+ OUT_REG(R200_REG_PP_CNTL_X, 0);
+ OUT_REG(R200_REG_PP_TXMULTI_CTL_0, 0);
+ OUT_REG(R200_REG_SE_VTX_STATE_CNTL, 0);
+ OUT_REG(R200_REG_RE_CNTL, 0);
+ /* XXX: VTX_ST_DENORMALIZED is illegal for the case of
+ * repeating textures.
+ */
+ OUT_REG(R200_REG_SE_VTE_CNTL, R200_VTX_ST_DENORMALIZED);
+ OUT_REG(R200_REG_SE_VAP_CNTL,
+ R200_VAP_FORCE_W_TO_ONE |
+ R200_VAP_VF_MAX_VTX_NUM);
+ OUT_REG(R200_REG_RE_AUX_SCISSOR_CNTL, 0);
+ OUT_REG(RADEON_REG_RB3D_DSTCACHE_MODE,
+ RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH |
+ RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH |
+ R200_RB3D_DC_2D_CACHE_AUTOFREE |
+ R200_RB3D_DC_3D_CACHE_AUTOFREE);
+ END_DMA();
+ }
+ }
+}
+
+static void
+ATIWaitMarker(ScreenPtr pScreen, int marker)
+{
+ KdScreenPriv(pScreen);
+ ATIScreenInfo(pScreenPriv);
+
+ ENTER_DRAW(0);
+ ATIWaitIdle(atis);
+ LEAVE_DRAW(0);
+}
+
+void
+RadeonSwitchTo2D(ATIScreenInfo *atis)
+{
+ RING_LOCALS;
+
+ ENTER_DRAW(0);
+ BEGIN_DMA(4);
+ OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
+ OUT_REG(ATI_REG_WAIT_UNTIL,
+ RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+ END_DMA();
+ LEAVE_DRAW(0);
+}
+
+void
+RadeonSwitchTo3D(ATIScreenInfo *atis)
+{
+ RING_LOCALS;
+
+ ENTER_DRAW(0);
+ BEGIN_DMA(4);
+ OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH);
+ /* We must wait for 3d to idle, in case source was just written as a dest. */
+ OUT_REG(ATI_REG_WAIT_UNTIL,
+ RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
+ END_DMA();
+ LEAVE_DRAW(0);
+}
+
+#if ATI_TRACE_DRAW
+void
+ATIEnterDraw (PixmapPtr pPix, char *function)
+{
+ if (pPix != NULL) {
+ KdScreenPriv(pPix->drawable.pScreen);
+ CARD32 offset;
+
+ offset = ((CARD8 *)pPix->devPrivate.ptr -
+ pScreenPriv->screen->memory_base);
+
+ ErrorF ("Enter %s 0x%x (%dx%dx%d/%d)\n", function, offset,
+ pPix->drawable.width, pPix->drawable.height, pPix->drawable.depth,
+ pPix->drawable.bitsPerPixel);
+ } else
+ ErrorF ("Enter %s\n", function);
+}
+
+void
+ATILeaveDraw (PixmapPtr pPix, char *function)
+{
+ if (pPix != NULL) {
+ KdScreenPriv(pPix->drawable.pScreen);
+ CARD32 offset;
+
+ offset = ((CARD8 *)pPix->devPrivate.ptr -
+ pScreenPriv->screen->memory_base);
+
+ ErrorF ("Leave %s 0x%x\n", function, offset);
+ } else
+ ErrorF ("Leave %s\n", function);
+}
+#endif
+
+/* 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 pitchAlign 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.pitchAlign != 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.offsetAlign != 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;
+
+ ENTER_DRAW(pPix);
+
+ 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
+
+ LEAVE_DRAW(pPix);
+ return TRUE;
+}
+
+static void
+ATISolid(int x1, int y1, int x2, int y2)
+{
+ ENTER_DRAW(0);
+ 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_REG(ATI_REG_DST_Y_X, (y1 << 16) | x1);
+ OUT_RING_REG(ATI_REG_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1));
+ END_DMA();
+#endif
+ LEAVE_DRAW(0);
+}
+
+static void
+ATIDoneSolid(void)
+{
+ ENTER_DRAW(0);
+ LEAVE_DRAW(0);
+}
+
+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;
+
+ ENTER_DRAW (pDst);
+ 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
+ LEAVE_DRAW(pDst);
+
+ 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_REG(ATI_REG_SRC_Y_X, (srcY << 16) | srcX);
+ OUT_RING_REG(ATI_REG_DST_Y_X, (dstY << 16) | dstX);
+ OUT_RING_REG(ATI_REG_DST_HEIGHT_WIDTH, (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;
+
+ ENTER_DRAW (pDst);
+
+ LEAVE_DRAW (pDst);
+ /* XXX: Hostdata uploads aren't working yet. */
+ return FALSE;
+
+ 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;
+
+ 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_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_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_RB3D_DSTCACHE_CTLSTAT,
+ RADEON_RB3D_DC_FLUSH_ALL);
+ 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();
+ }
+
+ kaaMarkSync(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;
+
+ ENTER_DRAW(pSrc);
+ /* 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 = pSrc->drawable.width;
+ if (atis->kaa.flags & KAA_OFFSCREEN_ALIGN_POT)
+ w = 1 << (ATILog2(w - 1) + 1);
+ dst_pitch = (w * pSrc->drawable.bitsPerPixel / 8 +
+ atis->kaa.pitchAlign - 1) & ~(atis->kaa.pitchAlign - 1);
+
+ size = dst_pitch * pSrc->drawable.height;
+ if (size > atis->scratch_area->size)
+ ATI_FALLBACK(("Pixmap too large for scratch (%d,%d)\n",
+ pSrc->drawable.width, pSrc->drawable.height));
+
+ atis->scratch_next = (atis->scratch_next + atis->kaa.offsetAlign - 1) &
+ ~(atis->kaa.offsetAlign - 1);
+ if (atis->scratch_next + size > atis->scratch_area->offset +
+ atis->scratch_area->size) {
+ /* Only sync when we've used all of the scratch area. */
+ kaaWaitSync(pSrc->drawable.pScreen);
+ atis->scratch_next = atis->scratch_area->offset;
+ }
+ memcpy(pDst, pSrc, sizeof(*pDst));
+ pDst->devKind = dst_pitch;
+ pDst->devPrivate.ptr = pScreenPriv->screen->memory_base +
+ atis->scratch_next;
+ 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(4);
+ OUT_REG(RADEON_REG_RB3D_DSTCACHE_CTLSTAT,
+ RADEON_RB3D_DC_FLUSH_ALL);
+ OUT_REG(ATI_REG_WAIT_UNTIL, RADEON_WAIT_HOST_IDLECLEAN);
+ END_DMA();
+ } else {
+ BEGIN_DMA(2);
+ OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_ALL);
+ END_DMA();
+ }
+
+ LEAVE_DRAW(pSrc);
+ return TRUE;
+}
+
+static void
+ATIBlockHandler(pointer blockData, OSTimePtr timeout, pointer readmask)
+{
+ ScreenPtr pScreen = (ScreenPtr) blockData;
+ KdScreenPriv(pScreen);
+ ATIScreenInfo(pScreenPriv);
+
+ /* When the server is going to sleep, make sure that all DMA data has
+ * been flushed.
+ */
+ if (atis->indirectBuffer)
+ ATIFlushIndirect(atis, 1);
+}
+
+static void
+ATIWakeupHandler(pointer blockData, int result, pointer readmask)
+{
+}
+
+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);
+
+ RegisterBlockAndWakeupHandlers(ATIBlockHandler, ATIWakeupHandler,
+ pScreen);
+
+#ifdef USE_DRI
+ atis->using_dri = ATIDRIScreenInit(pScreen);
+#endif /* USE_DRI */
+
+ memset(&atis->kaa, 0, sizeof(KaaScreenInfoRec));
+ atis->kaa.waitMarker = ATIWaitMarker;
+ 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.offsetAlign = 1024;
+ atis->kaa.pitchAlign = 64;
+ } else {
+ /* Rage 128 compositing wants power-of-two pitches. */
+ atis->kaa.flags |= KAA_OFFSCREEN_ALIGN_POT;
+ atis->kaa.offsetAlign = 32;
+ /* Pitch alignment is in sets of 8 pixels, and we need to cover
+ * 32bpp, so 32 bytes.
+ */
+ atis->kaa.pitchAlign = 32;
+ }
+
+ kaaInitTrapOffsets(8, sample_offsets_x, sample_offsets_y, 0.0, 0.0);
+ sample_count = (1 << 8) - 1;
+
+ if (!kaaDrawInit(pScreen, &atis->kaa))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+ATIScratchSave(ScreenPtr pScreen, KdOffscreenArea *area)
+{
+ KdScreenPriv(pScreen);
+ ATIScreenInfo(pScreenPriv);
+
+ atis->scratch_area = NULL;
+}
+
+void
+ATIDrawEnable(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ATIScreenInfo(pScreenPriv);
+ ATICardInfo(pScreenPriv);
+
+ ATIDMASetup(pScreen);
+ ATIDrawSetup(pScreen);
+
+ atis->scratch_area = NULL;
+ 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;
+ atis->kaa.UploadToScreen = NULL;
+ atis->kaa.UploadToScratch = NULL;
+
+ /* We can't dispatch 3d commands in PIO mode. */
+ if (!atis->using_pio) {
+ if (!atic->is_radeon) {
+ atis->kaa.CheckComposite = R128CheckComposite;
+ atis->kaa.PrepareComposite = R128PrepareComposite;
+ atis->kaa.Composite = R128Composite;
+ atis->kaa.DoneComposite = R128DoneComposite;
+ } else if (atic->is_r100) {
+ atis->kaa.CheckComposite = R100CheckComposite;
+ atis->kaa.PrepareComposite = R100PrepareComposite;
+ atis->kaa.Composite = RadeonComposite;
+ atis->kaa.DoneComposite = RadeonDoneComposite;
+ } else if (atic->is_r200) {
+ atis->kaa.CheckComposite = R200CheckComposite;
+ atis->kaa.PrepareComposite = R200PrepareComposite;
+ atis->kaa.Composite = RadeonComposite;
+ atis->kaa.DoneComposite = RadeonDoneComposite;
+ }
+ }
+#ifdef USE_DRI
+ if (atis->using_dri) {
+ if (!atic->is_radeon) {
+ /*atis->kaa.PrepareTrapezoids = R128PrepareTrapezoids;
+ atis->kaa.Trapezoids = R128Trapezoids;
+ atis->kaa.DoneTrapezoids = R128DoneTrapezoids;*/
+ } else if (atic->is_r100 || atic->is_r200) {
+ atis->kaa.PrepareTrapezoids = RadeonPrepareTrapezoids;
+ atis->kaa.Trapezoids = RadeonTrapezoids;
+ atis->kaa.DoneTrapezoids = RadeonDoneTrapezoids;
+ }
+ }
+#endif /* USE_DRI */
+
+ atis->kaa.UploadToScreen = ATIUploadToScreen;
+
+ /* Reserve a scratch area. It'll be used for storing glyph data during
+ * Composite operations, because glyphs aren't in real pixmaps and thus
+ * can't be migrated.
+ */
+ atis->scratch_area = KdOffscreenAlloc(pScreen, 131072,
+ atis->kaa.offsetAlign, TRUE, ATIScratchSave, atis);
+ if (atis->scratch_area != NULL) {
+ atis->scratch_next = atis->scratch_area->offset;
+ atis->kaa.UploadToScratch = ATIUploadToScratch;
+ }
+
+ kaaMarkSync(pScreen);
+}
+
+void
+ATIDrawDisable(ScreenPtr pScreen)
+{
+ kaaWaitSync(pScreen);
+ ATIDMATeardown(pScreen);
+}
+
+void
+ATIDrawFini(ScreenPtr pScreen)
+{
+#ifdef USE_DRI
+ KdScreenPriv(pScreen);
+ ATIScreenInfo(pScreenPriv);
+ if (atis->using_dri) {
+ ATIDRICloseScreen(pScreen);
+ atis->using_dri = FALSE;
+ }
+#endif /* USE_DRI */
+
+ RemoveBlockAndWakeupHandlers(ATIBlockHandler, ATIWakeupHandler,
+ pScreen);
+
+ kaaDrawFini(pScreen);
+}
+