diff --git a/hw/kdrive/ati/Makefile.am b/hw/kdrive/ati/Makefile.am index bb7607113..2a268122c 100644 --- a/hw/kdrive/ati/Makefile.am +++ b/hw/kdrive/ati/Makefile.am @@ -9,7 +9,6 @@ DRI_SOURCES = ati_dri.c \ r128_common.h \ r128_sarea.h \ radeon_common.h \ - radeon_composite.c \ radeon_sarea.h endif @@ -39,13 +38,18 @@ endif noinst_LIBRARIES = libati.a libati_a_SOURCES = \ + ati_cursor.c \ + ati_dma.c \ + ati_dma.h \ ati_draw.c \ ati_draw.h \ - ati_drawtmp.h \ + ati_microcode.c \ ati.c \ ati.h \ ati_reg.h \ - r128_blendtmp.h \ + r128_composite.c \ + ati_video.c \ + radeon_composite.c \ $(DRI_SOURCES) Xati_SOURCES = \ diff --git a/hw/kdrive/ati/ati.c b/hw/kdrive/ati/ati.c index 69d0ef6d5..06c3d7ded 100644 --- a/hw/kdrive/ati/ati.c +++ b/hw/kdrive/ati/ati.c @@ -32,10 +32,16 @@ #include "ati_sarea.h" #endif -#define CAP_R128 0x1 /* If it's a Rage 128 */ -#define CAP_R100 0x2 /* If it's an r100 series radeon. */ -#define CAP_R200 0x3 /* If it's an r200 series radeon. */ -#define CAP_R300 0x4 /* If it's an r300 series radeon. */ +static Bool ATIIsAGP(ATICardInfo *atic); + +#define CAP_SERIESMASK 0xf +#define CAP_R128 0x1 /* If it's a Rage 128 */ +#define CAP_R100 0x2 /* If it's an r100 series radeon. */ +#define CAP_R200 0x3 /* If it's an r200 series radeon. */ +#define CAP_R300 0x4 /* If it's an r300 series radeon. */ + +#define CAP_FEATURESMASK 0xf0 +#define CAP_NOAGP 0x10 /* If it's a PCI-only card. */ struct pci_id_entry ati_pci_ids[] = { {0x1002, 0x4136, 0x2, "ATI Radeon RS100"}, @@ -63,13 +69,13 @@ struct pci_id_entry ati_pci_ids[] = { {0x1002, 0x4964, 0x2, "ATI Radeon RV250 Id"}, {0x1002, 0x4965, 0x2, "ATI Radeon RV250 Ie"}, {0x1002, 0x4966, 0x2, "ATI Radeon RV250 If"}, - {0x1002, 0x4967, 0x2, "ATI Radeon RV250 Ig"}, - {0x1002, 0x4c45, 0x1, "ATI Rage 128 LE"}, + {0x1002, 0x4967, 0x2, "ATI Radeon R250 Ig"}, + {0x1002, 0x4c45, 0x11, "ATI Rage 128 LE"}, {0x1002, 0x4c46, 0x1, "ATI Rage 128 LF"}, - {0x1002, 0x4c57, 0x2, "ATI Radeon RV200 LW"}, - {0x1002, 0x4c58, 0x2, "ATI Radeon RV200 LX"}, + {0x1002, 0x4c57, 0x2, "ATI Radeon Mobiliy M7 RV200 LW (7500)"}, + {0x1002, 0x4c58, 0x2, "ATI Radeon Mobiliy M7 RV200 LX (7500)"}, {0x1002, 0x4c59, 0x2, "ATI Radeon Mobility M6 LY"}, - {0x1002, 0x4c5a, 0x2, "ATI Radeon Mobility LZ"}, + {0x1002, 0x4c5a, 0x2, "ATI Radeon Mobility M6 LZ"}, {0x1002, 0x4c64, 0x3, "ATI Radeon RV250 Ld"}, {0x1002, 0x4c65, 0x3, "ATI Radeon RV250 Le"}, {0x1002, 0x4c66, 0x3, "ATI Radeon Mobility M9 RV250 Lf"}, @@ -93,7 +99,7 @@ struct pci_id_entry ati_pci_ids[] = { {0x1002, 0x5041, 0x1, "ATI Rage 128 PA"}, {0x1002, 0x5042, 0x1, "ATI Rage 128 PB"}, {0x1002, 0x5043, 0x1, "ATI Rage 128 PC"}, - {0x1002, 0x5044, 0x1, "ATI Rage 128 PD"}, + {0x1002, 0x5044, 0x11, "ATI Rage 128 PD"}, {0x1002, 0x5045, 0x1, "ATI Rage 128 PE"}, {0x1002, 0x5046, 0x1, "ATI Rage 128 PF"}, {0x1002, 0x5047, 0x1, "ATI Rage 128 PG"}, @@ -105,9 +111,9 @@ struct pci_id_entry ati_pci_ids[] = { {0x1002, 0x504d, 0x1, "ATI Rage 128 PM"}, {0x1002, 0x504e, 0x1, "ATI Rage 128 PN"}, {0x1002, 0x504f, 0x1, "ATI Rage 128 PO"}, - {0x1002, 0x5050, 0x1, "ATI Rage 128 PP"}, + {0x1002, 0x5050, 0x11, "ATI Rage 128 PP"}, {0x1002, 0x5051, 0x1, "ATI Rage 128 PQ"}, - {0x1002, 0x5052, 0x1, "ATI Rage 128 PR"}, + {0x1002, 0x5052, 0x11, "ATI Rage 128 PR"}, {0x1002, 0x5053, 0x1, "ATI Rage 128 PS"}, {0x1002, 0x5054, 0x1, "ATI Rage 128 PT"}, {0x1002, 0x5055, 0x1, "ATI Rage 128 PU"}, @@ -121,14 +127,14 @@ struct pci_id_entry ati_pci_ids[] = { {0x1002, 0x5148, 0x3, "ATI Radeon R200 QH"}, {0x1002, 0x514c, 0x3, "ATI Radeon R200 QL"}, {0x1002, 0x514d, 0x3, "ATI Radeon R200 QM"}, - {0x1002, 0x5157, 0x2, "ATI Radeon RV200 QW"}, - {0x1002, 0x5158, 0x2, "ATI Radeon RV200 QX"}, + {0x1002, 0x5157, 0x2, "ATI Radeon RV200 QW (7500)"}, + {0x1002, 0x5158, 0x2, "ATI Radeon RV200 QX (7500)"}, {0x1002, 0x5159, 0x2, "ATI Radeon RV100 QY"}, {0x1002, 0x515a, 0x2, "ATI Radeon RV100 QZ"}, - {0x1002, 0x5245, 0x1, "ATI Rage 128 RE"}, + {0x1002, 0x5245, 0x11, "ATI Rage 128 RE"}, {0x1002, 0x5246, 0x1, "ATI Rage 128 RF"}, {0x1002, 0x5247, 0x1, "ATI Rage 128 RG"}, - {0x1002, 0x524b, 0x1, "ATI Rage 128 RK"}, + {0x1002, 0x524b, 0x11, "ATI Rage 128 RK"}, {0x1002, 0x524c, 0x1, "ATI Rage 128 RL"}, {0x1002, 0x5345, 0x1, "ATI Rage 128 SE"}, {0x1002, 0x5346, 0x1, "ATI Rage 128 SF"}, @@ -233,7 +239,7 @@ ATICardInit(KdCardInfo *card) /* We demand identification by busid, not driver name */ atic->drmFd = drmOpen(NULL, atic->busid); if (atic->drmFd < 0) - ErrorF("Failed to open DRM. DMA won't be used.\n"); + ErrorF("Failed to open DRM, DRI disabled.\n"); #endif /* USE_DRI */ card->driver = atic; @@ -244,17 +250,20 @@ ATICardInit(KdCardInfo *card) break; } } - - if (atic->pci_id->caps != CAP_R128) + + if ((atic->pci_id->caps & CAP_SERIESMASK) != CAP_R128) atic->is_radeon = TRUE; - if (atic->pci_id->caps == CAP_R100) + if ((atic->pci_id->caps & CAP_SERIESMASK) == CAP_R100) atic->is_r100 = TRUE; - if (atic->pci_id->caps == CAP_R200) + if ((atic->pci_id->caps & CAP_SERIESMASK) == CAP_R200) atic->is_r200 = TRUE; - if (atic->pci_id->caps == CAP_R300) + if ((atic->pci_id->caps & CAP_SERIESMASK) == CAP_R300) atic->is_r300 = TRUE; - ErrorF("Using ATI card: %s at %s\n", atic->pci_id->name, atic->busid); + atic->is_agp = ATIIsAGP(atic); + + ErrorF("Using ATI card: %s (%s) at %s\n", atic->pci_id->name, + atic->is_agp ? "AGP" : "PCI", atic->busid); return TRUE; } @@ -284,7 +293,7 @@ ATIScreenInit(KdScreenInfo *screen) return FALSE; atis->atic = atic; - + atis->screen = screen; screen->driver = atis; #ifdef KDRIVEFBDEV @@ -313,11 +322,20 @@ ATIScreenInit(KdScreenInfo *screen) } screen->off_screen_base = screen_size; + + /* Reserve the area for the monochrome cursor. */ + if (screen->off_screen_base + + ATI_CURSOR_HEIGHT * ATI_CURSOR_PITCH * 3 <= screen->memory_size) { + atis->cursor.offset = screen->off_screen_base; + screen->off_screen_base += ATI_CURSOR_HEIGHT * ATI_CURSOR_PITCH * 2; + } + #if defined(USE_DRI) && defined(GLXEXT) /* Reserve a static area for the back buffer the same size as the * visible screen. XXX: This would be better initialized in ati_dri.c - * when GLX is set up, but I'm not sure when the offscreen memory - * manager gets set up. + * when GLX is set up, but the offscreen memory manager's allocations + * don't last through VT switches, while the kernel's understanding of + * offscreen locations does. */ atis->frontOffset = 0; atis->frontPitch = screen->fb[0].byteStride; @@ -365,11 +383,12 @@ ATIScreenInit(KdScreenInfo *screen) * Composite operations, because glyphs aren't in real pixmaps and thus * can't be migrated. */ - atis->scratch_size = 65536; /* big enough for 128x128@32bpp */ + atis->scratch_size = 131072; /* big enough for 128x128@32bpp */ if (screen->off_screen_base + atis->scratch_size <= screen->memory_size) { atis->scratch_offset = screen->off_screen_base; screen->off_screen_base += atis->scratch_size; + atis->scratch_next = atis->scratch_offset; } else { atis->scratch_size = 0; } @@ -383,6 +402,10 @@ ATIScreenFini(KdScreenInfo *screen) ATIScreenInfo *atis = (ATIScreenInfo *)screen->driver; ATICardInfo *atic = screen->card->driver; +#ifdef XV + ATIFiniVideo(screen->pScreen); +#endif + atic->backend_funcs.scrfini(screen); xfree(atis); screen->driver = 0; @@ -391,13 +414,13 @@ ATIScreenFini(KdScreenInfo *screen) Bool ATIMapReg(KdCardInfo *card, ATICardInfo *atic) { - atic->reg_base = (CARD8 *)KdMapDevice(RADEON_REG_BASE(card), - RADEON_REG_SIZE(card)); + atic->reg_base = (CARD8 *)KdMapDevice(ATI_REG_BASE(card), + ATI_REG_SIZE(card)); if (atic->reg_base == NULL) return FALSE; - KdSetMappedMode(RADEON_REG_BASE(card), RADEON_REG_SIZE(card), + KdSetMappedMode(ATI_REG_BASE(card), ATI_REG_SIZE(card), KD_MAPPED_MODE_REGISTERS); return TRUE; @@ -407,9 +430,9 @@ void ATIUnmapReg(KdCardInfo *card, ATICardInfo *atic) { if (atic->reg_base) { - KdResetMappedMode(RADEON_REG_BASE(card), RADEON_REG_SIZE(card), + KdResetMappedMode(ATI_REG_BASE(card), ATI_REG_SIZE(card), KD_MAPPED_MODE_REGISTERS); - KdUnmapDevice((void *)atic->reg_base, RADEON_REG_SIZE(card)); + KdUnmapDevice((void *)atic->reg_base, ATI_REG_SIZE(card)); atic->reg_base = 0; } } @@ -420,6 +443,9 @@ ATIInitScreen(ScreenPtr pScreen) KdScreenPriv(pScreen); ATICardInfo(pScreenPriv); +#ifdef XV + ATIInitVideo(pScreen); +#endif return atic->backend_funcs.initScreen(pScreen); } @@ -525,7 +551,55 @@ ATILog2(int val) return 1; for (bits = 0; val != 0; val >>= 1, ++bits) ; - return bits; + return bits - 1; +} + +static Bool +ATIIsAGP(ATICardInfo *atic) +{ + char *mmio = atic->reg_base; + CARD32 agp_command; + Bool is_agp = FALSE; + + if (mmio == NULL) + return FALSE; + + if (atic->is_radeon) { + /* XXX: Apparently this doesn't work. Maybe it needs to be done + * through the PCI config aperture then. + */ + agp_command = MMIO_IN32(mmio, RADEON_REG_AGP_COMMAND); + MMIO_OUT32(mmio, RADEON_REG_AGP_COMMAND, agp_command | + RADEON_AGP_ENABLE); + if (MMIO_IN32(mmio, RADEON_REG_AGP_COMMAND) & RADEON_AGP_ENABLE) + is_agp = TRUE; + MMIO_OUT32(mmio, RADEON_REG_AGP_COMMAND, agp_command); + } else { + /* Don't know any way to detect R128 AGP automatically, so + * assume AGP for all cards not marked as PCI-only by XFree86. + */ + if ((atic->pci_id->caps & CAP_FEATURESMASK) != CAP_NOAGP) + is_agp = TRUE; + } + + return is_agp; +} + +/* This function is required to work around a hardware bug in some (all?) + * revisions of the R300. This workaround should be called after every + * CLOCK_CNTL_INDEX register access. If not, register reads afterward + * may not be correct. + */ +void R300CGWorkaround(ATIScreenInfo *atis) { + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + CARD32 save; + + save = MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_INDEX); + MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, save & ~(0x3f | + ATI_PLL_WR_EN)); + MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_INDEX); + MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, save); } KdCardFuncs ATIFuncs = { @@ -542,11 +616,11 @@ KdCardFuncs ATIFuncs = { ATIScreenFini, /* scrfini */ ATICardFini, /* cardfini */ - 0, /* initCursor */ - 0, /* enableCursor */ - 0, /* disableCursor */ - 0, /* finiCursor */ - 0, /* recolorCursor */ + ATICursorInit, /* initCursor */ + ATICursorEnable, /* enableCursor */ + ATICursorDisable, /* disableCursor */ + ATICursorFini, /* finiCursor */ + ATIRecolorCursor, /* recolorCursor */ ATIDrawInit, /* initAccel */ ATIDrawEnable, /* enableAccel */ diff --git a/hw/kdrive/ati/ati.h b/hw/kdrive/ati/ati.h index 9270f080b..a8ca47fd6 100644 --- a/hw/kdrive/ati/ati.h +++ b/hw/kdrive/ati/ati.h @@ -26,7 +26,9 @@ #ifndef _ATI_H_ #define _ATI_H_ -#include "config.h" +#ifdef HAVE_CONFIG_H +#include +#endif #ifdef KDRIVEFBDEV #include @@ -35,6 +37,8 @@ #include #endif +#include "kxv.h" + #ifdef XF86DRI #define USE_DRI #include "libdrm.h" @@ -46,8 +50,8 @@ #endif #endif -#define RADEON_REG_BASE(c) ((c)->attr.address[1]) -#define RADEON_REG_SIZE(c) (0x4000) +#define ATI_REG_BASE(c) ((c)->attr.address[1]) +#define ATI_REG_SIZE(c) (0x4000) #ifdef __powerpc__ @@ -82,6 +86,18 @@ MMIO_IN32(__volatile__ void *base, const unsigned long offset) #endif +#define MMIO_OUT8(mmio, a, v) (*(VOL8 *)((mmio) + (a)) = (v)) +#define MMIO_IN8(mmio, a, v) (*(VOL8 *)((mmio) + (a))) + +#define INPLL(mmio, addr) \ + (MMIO_OUT8(mmio, ATI_REG_CLOCK_CNTL_INDEX, addr), \ + MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_DATA)) + +#define OUTPLL(mmio, addr, val) do { \ + MMIO_OUT8(mmio, ATI_REG_CLOCK_CNTL_INDEX, (addr) | ATI_PLL_WR_EN); \ + MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_DATA, val); \ +} while (0) + typedef volatile CARD8 VOL8; typedef volatile CARD16 VOL16; typedef volatile CARD32 VOL32; @@ -125,6 +141,7 @@ typedef struct _ATICardInfo { Bool is_r100; Bool is_r200; Bool is_r300; + Bool is_agp; char *busid; #ifdef USE_DRI int drmFd; @@ -135,6 +152,48 @@ typedef struct _ATICardInfo { #define getATICardInfo(kd) ((ATICardInfo *) ((kd)->card->driver)) #define ATICardInfo(kd) ATICardInfo *atic = getATICardInfo(kd) +typedef struct _ATICursor { + int width, height; + int xhot, yhot; + + Bool has_cursor; + CursorPtr pCursor; + Pixel source, mask; + KdOffscreenArea *area; + CARD32 offset; +} ATICursor; + +typedef struct _ATIPortPriv { + int brightness; + int saturation; + RegionRec clip; + Bool videoOn; + Time offTime; + Time freeTime; + CARD32 size; + KdOffscreenArea *off_screen; + DrawablePtr pDraw; + PixmapPtr pPixmap; + + CARD32 src_offset; + CARD32 src_pitch; + CARD8 *src_addr; + + int id; + int src_x1, src_y1, src_x2, src_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; + int src_w, src_h, dst_w, dst_h; +} ATIPortPrivRec, *ATIPortPrivPtr; + +typedef struct _dmaBuf { + int size; + int used; + void *address; +#ifdef USE_DRI + drmBufPtr drmBuf; +#endif +} dmaBuf; + typedef struct _ATIScreenInfo { union { #ifdef KDRIVEFBDEV @@ -145,20 +204,52 @@ typedef struct _ATIScreenInfo { #endif } backend_priv; KaaScreenInfoRec kaa; + ATICardInfo *atic; + KdScreenInfo *screen; - Bool using_dri; - Bool using_dma; + void (*save_blockhandler)(int screen, pointer blockData, + pointer timeout, pointer readmask); - int scratch_offset; - int scratch_size; + int scratch_offset; + int scratch_next; + int scratch_size; + + ATICursor cursor; + + KdVideoAdaptorPtr pAdaptor; + int num_texture_ports; + + Bool using_pio; /* If we use decode DMA packets to MMIO. */ + Bool using_pseudo; /* If we use MMIO to submit DMA packets. */ + Bool using_dma; /* If we use non-DRI DMA to submit packets. */ + Bool using_dri; /* If we use the DRM for DMA. */ + Bool using_agp; /* If we are using AGP or not for DMA. */ + + KdOffscreenArea *dma_space; /* For "DMA" from framebuffer. */ + void *agp_addr; /* Mapped AGP aperture */ + int agp_size; + int agp_key; /* Key of AGP memory for DMA */ + CARD32 *ring_addr; /* Beginning of ring buffer. */ + int ring_write; /* Index of write ptr in ring. */ + int ring_read; /* Index of read ptr in ring. */ + int ring_len; + + + dmaBuf *indirectBuffer; + int indirectStart; + + int mmio_avail; + int cce_pri_size; + int cce_pri_avail; #ifdef USE_DRI + Bool dma_started; + drmSize registerSize; drmHandle registerHandle; drmHandle fbHandle; - int IsAGP; drmSize gartSize; drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long gartOffset; @@ -196,23 +287,9 @@ typedef struct _ATIScreenInfo { unsigned char *gartTex; /* Map */ int log2GARTTexGran; - int CCEMode; /* CCE mode that server/clients use */ - int CPMode; /* CP mode that server/clients use */ - int CCEFifoSize; /* Size of the CCE command FIFO */ int DMAusecTimeout; /* CCE timeout in usecs */ - /* DMA 2D accleration */ - drmBufPtr indirectBuffer; - int indirectStart; - - /* DRI screen private data */ - int fbX; - int fbY; - int backX; - int backY; - int depthX; - int depthY; - + /* DRI screen private data */ int frontOffset; int frontPitch; int backOffset; @@ -240,13 +317,18 @@ typedef struct _ATIScreenInfo { #define getATIScreenInfo(kd) ((ATIScreenInfo *) ((kd)->screen->driver)) #define ATIScreenInfo(kd) ATIScreenInfo *atis = getATIScreenInfo(kd) +/* ati.c */ Bool ATIMapReg(KdCardInfo *card, ATICardInfo *atic); void ATIUnmapReg(KdCardInfo *card, ATICardInfo *atic); -Bool +void +R300CGWorkaround(ATIScreenInfo *atis); + +/* ati_draw.c */ +void ATIDrawSetup(ScreenPtr pScreen); Bool @@ -264,17 +346,54 @@ ATIDrawDisable(ScreenPtr pScreen); void ATIDrawFini(ScreenPtr pScreen); +/* ati_dri.c */ #ifdef USE_DRI Bool ATIDRIScreenInit(ScreenPtr pScreen); void ATIDRICloseScreen(ScreenPtr pScreen); + +void +ATIDRIDMAStart(ScreenPtr pScreen); + +void +ATIDRIDMAStop(ScreenPtr pScreen); + +void +ATIDRIDispatchIndirect(ATIScreenInfo *atis, Bool discard); + +drmBufPtr +ATIDRIGetBuffer(ATIScreenInfo *atis); + #endif /* USE_DRI */ +/* ati_cursor.c */ +Bool +ATICursorInit(ScreenPtr pScreen); + +void +ATICursorEnable(ScreenPtr pScreen); + +void +ATICursorDisable(ScreenPtr pScreen); + +void +ATICursorFini(ScreenPtr pScreen); + +void +ATIRecolorCursor(ScreenPtr pScreen, int ndef, xColorItem *pdef); + int ATILog2(int val); +/* ati_video.c */ +Bool +ATIInitVideo(ScreenPtr pScreen); + +void +ATIFiniVideo(ScreenPtr pScreen); + extern KdCardFuncs ATIFuncs; #endif /* _ATI_H_ */ diff --git a/hw/kdrive/ati/ati_cursor.c b/hw/kdrive/ati/ati_cursor.c new file mode 100644 index 000000000..e62e926ed --- /dev/null +++ b/hw/kdrive/ati/ati_cursor.c @@ -0,0 +1,392 @@ +/* + * Copyright © 2004 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. + */ +/* $RCSId$ */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "ati.h" +#include "ati_reg.h" +#include "cursorstr.h" +#include "ati_draw.h" + +static void +ATIMoveCursor(ScreenPtr pScreen, int x, int y) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + CARD16 xoff, yoff; + CARD8 *mmio = atic->reg_base; + + if (!pCurPriv->has_cursor) + return; + + if (!pScreenPriv->enabled) + return; + + x -= pCurPriv->xhot; + xoff = 0; + if (x < 0) { + xoff = -x; + x = 0; + } + y -= pCurPriv->yhot; + yoff = 0; + if (y < 0) { + yoff = -y; + y = 0; + } + + MMIO_OUT32(mmio, ATI_REG_CUR_HORZ_VERT_OFF, ATI_CUR_LOCK | + (xoff << 16) | yoff); + MMIO_OUT32(mmio, ATI_REG_CUR_HORZ_VERT_POSN, ATI_CUR_LOCK | + (x << 16) | y); + MMIO_OUT32(mmio, ATI_REG_CUR_OFFSET, (pCurPriv->offset + yoff * 16)); +} + +static void +ATIAllocCursorColors(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + CursorPtr pCursor = pCurPriv->pCursor; + + KdAllocateCursorPixels(pScreen, 0, pCursor, &pCurPriv->source, + &pCurPriv->mask); + switch (pScreenPriv->screen->fb[0].bitsPerPixel) { + case 4: + pCurPriv->source |= pCurPriv->source << 4; + pCurPriv->mask |= pCurPriv->mask << 4; + /* FALLTHROUGH */ + case 8: + pCurPriv->source |= pCurPriv->source << 8; + pCurPriv->mask |= pCurPriv->mask << 8; + /* FALLTHROUGH */ + case 16: + pCurPriv->source |= pCurPriv->source << 16; + pCurPriv->mask |= pCurPriv->mask << 16; + } +} + +static void +ATISetCursorColors(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + CARD8 *mmio = atic->reg_base; + + MMIO_OUT32(mmio, ATI_REG_CUR_CLR0, pCurPriv->mask); + MMIO_OUT32(mmio, ATI_REG_CUR_CLR1, pCurPriv->source); +} + +void +ATIRecolorCursor(ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + CursorPtr pCursor = pCurPriv->pCursor; + + if (!pCurPriv->has_cursor || !pCursor) + return; + + if (!pScreenPriv->enabled) + return; + + if (pdef) { + while (ndef != 0) { + if (pdef->pixel == pCurPriv->source || + pdef->pixel == pCurPriv->mask) + break; + ndef--; + } + + if (ndef == 0) + return; + } + ATIAllocCursorColors(pScreen); + ATISetCursorColors(pScreen); +} + +#define InvertBits32(v) do { \ + v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); \ + v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); \ + v = ((v & 0x0f0f0f0f) << 4) | ((v >> 4) & 0x0f0f0f0f); \ +} while (0) + +static void +ATILoadCursor(ScreenPtr pScreen, int x, int y) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + CursorPtr pCursor = pCurPriv->pCursor; + CursorBitsPtr bits = pCursor->bits; + int h; + CARD32 *ram, *msk, *mskLine, *src, *srcLine; + int i; + int lwsrc; + CARD32 tmp; + CARD8 *mmio = atic->reg_base; + + ATIAllocCursorColors(pScreen); + + pCurPriv->pCursor = pCursor; + pCurPriv->xhot = pCursor->bits->xhot; + pCurPriv->yhot = pCursor->bits->yhot; + + /* Stick new image into cursor memory */ + ram = (CARD32 *)(pScreenPriv->screen->memory_base + + pCurPriv->offset); + mskLine = (CARD32 *)bits->mask; + srcLine = (CARD32 *)bits->source; + + h = bits->height; + if (h > ATI_CURSOR_HEIGHT) + h = ATI_CURSOR_HEIGHT; + + lwsrc = BitmapBytePad(bits->width) / 4; /* words per line */ + + tmp = MMIO_IN32(mmio, ATI_REG_GEN_CNTL); + MMIO_OUT32(mmio, ATI_REG_GEN_CNTL, tmp & ~ATI_CRTC_CUR_EN); + + for (i = 0; i < ATI_CURSOR_HEIGHT; i++) { + CARD32 m1, m2, s1, s2; + + msk = mskLine; + src = srcLine; + mskLine += lwsrc; + srcLine += lwsrc; + + if (i < h && 0 < lwsrc) { + m1 = ~*msk++; + s1 = *src++; + InvertBits32(m1); + InvertBits32(s1); + } else { + m1 = 0xffffffff; + s1 = 0x0; + } + if (i < h && 1 < lwsrc) { + m2 = ~*msk++; + s2 = *src++; + InvertBits32(m2); + InvertBits32(s2); + } else { + m2 = 0xffffffff; + s2 = 0x0; + } + + *ram++ = m1; + *ram++ = m2; + *ram++ = s1; + *ram++ = s2; + } + + /* Not sure why this is necessary, but it prevents some cursor + * corruption. Not even all of it. + */ + for (i = 0; i < ATI_CURSOR_HEIGHT; i++) { + *ram++ = 0xffffffff; + *ram++ = 0xffffffff; + *ram++ = 0x0; + *ram++ = 0x0; + } + + /* Enable the cursor */ + tmp = MMIO_IN32(mmio, ATI_REG_GEN_CNTL); + MMIO_OUT32(mmio, ATI_REG_GEN_CNTL, tmp | ATI_CRTC_CUR_EN); + + /* Set new color */ + ATISetCursorColors(pScreen); + + /* Move to new position */ + ATIMoveCursor(pScreen, x, y); +} + +static void +ATIUnloadCursor(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + CARD8 *mmio = atic->reg_base; + CARD32 tmp; + + tmp = MMIO_IN32(mmio, ATI_REG_GEN_CNTL) & ~ATI_CRTC_CUR_EN; + MMIO_OUT32(mmio, ATI_REG_GEN_CNTL, tmp); +} + +static Bool +ATIRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + if (!pScreenPriv->enabled) + return TRUE; + + /* miRecolorCursor does this */ + if (pCursor && pCurPriv->pCursor == pCursor) + { + int x, y; + + miPointerPosition(&x, &y); + ATILoadCursor(pScreen, x, y); + } + + return TRUE; +} + +static Bool +ATIUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + +static void +ATISetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + pCurPriv->pCursor = pCursor; + + if (!pScreenPriv->enabled) + return; + + if (pCursor) + ATILoadCursor(pScreen, x, y); + else + ATIUnloadCursor(pScreen); +} + +miPointerSpriteFuncRec ATIPointerSpriteFuncs = { + ATIRealizeCursor, + ATIUnrealizeCursor, + ATISetCursor, + ATIMoveCursor, +}; + +static void +ATIQueryBestSize(int class, unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + switch (class) + { + case CursorShape: + if (*pwidth > pCurPriv->width) + *pwidth = pCurPriv->width; + if (*pheight > pCurPriv->height) + *pheight = pCurPriv->height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + fbQueryBestSize(class, pwidth, pheight, pScreen); + break; + } +} + +void +ATICursorEnable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + if (!pCurPriv->has_cursor) + return; + + if (pCurPriv->pCursor) { + int x, y; + + miPointerPosition(&x, &y); + ATILoadCursor(pScreen, x, y); + } + else + ATIUnloadCursor(pScreen); +} + +void +ATICursorDisable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + if (!pScreenPriv->enabled || !pCurPriv->has_cursor) + return; + + if (pCurPriv->pCursor) + ATIUnloadCursor(pScreen); +} + +Bool +ATICursorInit(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + pCurPriv->has_cursor = FALSE; + + if (pCurPriv->offset == 0) + return FALSE; + + if (atic->reg_base == NULL) + return FALSE; + + pCurPriv->width = ATI_CURSOR_WIDTH; + pCurPriv->height= ATI_CURSOR_HEIGHT; + pScreen->QueryBestSize = ATIQueryBestSize; + miPointerInitialize(pScreen, &ATIPointerSpriteFuncs, + &kdPointerScreenFuncs, FALSE); + pCurPriv->has_cursor = TRUE; + pCurPriv->pCursor = NULL; + return TRUE; +} + +void +ATICursorFini(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICursor *pCurPriv = &atis->cursor; + + pCurPriv->has_cursor = FALSE; + pCurPriv->pCursor = NULL; +} diff --git a/hw/kdrive/ati/ati_dma.c b/hw/kdrive/ati/ati_dma.c new file mode 100644 index 000000000..8f94ee06f --- /dev/null +++ b/hw/kdrive/ati/ati_dma.c @@ -0,0 +1,992 @@ +/* + * Copyright © 2004 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$ */ + +#include "ati.h" +#include "ati_reg.h" +#include "ati_dma.h" +#include "ati_draw.h" + +#ifdef USE_DRI +#include "radeon_common.h" +#include "r128_common.h" +#include "ati_sarea.h" +#endif /* USE_DRI */ + +#include "agp.h" + +#define DEBUG_FIFO 0 + +extern CARD32 r128_cce_microcode[]; +extern CARD32 radeon_cp_microcode[][2]; +extern CARD32 r200_cp_microcode[][2]; + +#if DEBUG_FIFO +static void +ATIDebugFifo(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + + if (atic->is_radeon) { + ErrorF("RADEON_REG_CP_CSQ_CNTL: 0x%08x\n", + MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL)); + ErrorF("RADEON_REG_CP_CSQ_STAT: 0x%08x\n", + MMIO_IN32(mmio, RADEON_REG_CP_CSQ_STAT)); + ErrorF("RADEON_REG_RBBM_STATUS: 0x%08x\n", + MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS)); + ErrorF("RADEON_REG_RB2D_DSTCACHE_CTLSTAT: 0x%08x\n", + MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT)); + } else { + ErrorF("R128_REG_PM4_BUFFER_CNTL: 0x%08x\n", + MMIO_IN32(mmio, R128_REG_PM4_BUFFER_CNTL)); + ErrorF("R128_REG_PM4_STAT: 0x%08x\n", + MMIO_IN32(mmio, R128_REG_PM4_STAT)); + ErrorF("R128_REG_GUI_STAT: 0x%08x\n", + MMIO_IN32(mmio, R128_REG_GUI_STAT)); + ErrorF("R128_REG_PC_NGUI_CTLSTAT: 0x%08x\n", + MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT)); + } +} +#endif + +static void +ATIUploadMicrocode(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + int i; + + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_ADDR, 0); + if (atic->is_radeon && atic->is_r200) { + for (i = 0; i < 256; i++) { + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH, + r200_cp_microcode[i][1]); + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL, + r200_cp_microcode[i][0]); + } + } else if (atic->is_radeon && atic->is_r100) { + for (i = 0; i < 256; i++) { + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH, + radeon_cp_microcode[i][1]); + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL, + radeon_cp_microcode[i][0]); + } + } else { + for (i = 0; i < 256; i++) { + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAH, + r128_cce_microcode[i * 2]); + MMIO_OUT32(mmio, ATI_REG_MICROCODE_RAM_DATAL, + r128_cce_microcode[i * 2 + 1]); + } + } +} +/* Required when reading from video memory after acceleration to make sure all + * data has been flushed to video memory from the pixel cache. + */ +static void +ATIFlushPixelCache(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + int tries; + CARD32 temp; + + if (atic->is_radeon) { + temp = MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT); + temp |= RADEON_RB2D_DC_FLUSH_ALL; + MMIO_OUT32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT, temp); + + for (tries = 1000000; tries != 0; tries--) { + if ((MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT) & + RADEON_RB2D_DC_BUSY) == 0) + break; + } + } else { + temp = MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT); + temp |= R128_PC_FLUSH_ALL; + MMIO_OUT32(mmio, R128_REG_PC_NGUI_CTLSTAT, temp); + + for (tries = 1000000; tries != 0; tries--) { + if ((MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT) & + R128_PC_BUSY) != R128_PC_BUSY) + break; + } + } + if (tries == 0) + ErrorF("Timeout flushing pixel cache.\n"); +} + +static void +ATIEngineReset(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + CARD32 clockcntlindex, mclkcntl; + +#if DEBUG_FIFO + ErrorF("Engine Reset!\n"); + ATIDebugFifo(atis); +#endif + + ATIFlushPixelCache(atis); + + clockcntlindex = MMIO_IN32(mmio, ATI_REG_CLOCK_CNTL_INDEX); + if (atic->is_r300) + R300CGWorkaround(atis); + + if (atic->is_radeon) { + CARD32 host_path_cntl; + + mclkcntl = INPLL(mmio, RADEON_REG_MCLK_CNTL); + + OUTPLL(mmio, RADEON_REG_MCLK_CNTL, mclkcntl | + RADEON_FORCEON_MCLKA | + RADEON_FORCEON_MCLKB | + RADEON_FORCEON_YCLKA | + RADEON_FORCEON_YCLKB | + RADEON_FORCEON_MC | + RADEON_FORCEON_AIC); + + host_path_cntl = MMIO_IN32(mmio, RADEON_REG_HOST_PATH_CNTL); + + if (atic->is_r300) { + MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET, + RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_E2); + } else { + MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET, + RADEON_SOFT_RESET_CP | + RADEON_SOFT_RESET_HI | + RADEON_SOFT_RESET_SE | + RADEON_SOFT_RESET_RE | + RADEON_SOFT_RESET_PP | + RADEON_SOFT_RESET_E2 | + RADEON_SOFT_RESET_RB); + } + MMIO_IN32(mmio, RADEON_REG_RBBM_SOFT_RESET); + MMIO_OUT32(mmio, RADEON_REG_RBBM_SOFT_RESET, 0); + + MMIO_OUT32(mmio, RADEON_REG_HOST_PATH_CNTL, host_path_cntl | + RADEON_HDP_SOFT_RESET); + MMIO_IN32(mmio, RADEON_REG_HOST_PATH_CNTL); + MMIO_OUT32(mmio, RADEON_REG_HOST_PATH_CNTL, host_path_cntl); + + MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, clockcntlindex); + OUTPLL(mmio, RADEON_REG_MCLK_CNTL, mclkcntl); + if (atic->is_r300) + R300CGWorkaround(atis); + } else { + CARD32 temp; + + mclkcntl = INPLL(mmio, R128_REG_MCLK_CNTL); + + OUTPLL(mmio, R128_REG_MCLK_CNTL, + mclkcntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP); + + temp = MMIO_IN32(mmio, R128_REG_GEN_RESET_CNTL); + MMIO_OUT32(mmio, R128_REG_GEN_RESET_CNTL, + temp | R128_SOFT_RESET_GUI); + temp = MMIO_IN32(mmio, R128_REG_GEN_RESET_CNTL); + MMIO_OUT32(mmio, R128_REG_GEN_RESET_CNTL, + temp & ~R128_SOFT_RESET_GUI); + temp = MMIO_IN32(mmio, R128_REG_GEN_RESET_CNTL); + + OUTPLL(mmio, R128_REG_MCLK_CNTL, mclkcntl); + MMIO_OUT32(mmio, ATI_REG_CLOCK_CNTL_INDEX, clockcntlindex); + } +} + +static void +ATIWaitAvailMMIO(ATIScreenInfo *atis, int n) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + int tries; + + if (atis->mmio_avail >= n) { + atis->mmio_avail -= n; + return; + } + if (atic->is_radeon) { + for (tries = 1000000; tries != 0 && atis->mmio_avail < n; tries--) + { + atis->mmio_avail = MMIO_IN32(mmio, + RADEON_REG_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; + } + } else { + for (tries = 1000000; tries != 0 && atis->mmio_avail < n; tries--) + { + atis->mmio_avail = MMIO_IN32(mmio, R128_REG_GUI_STAT) & + 0xfff; + } + } + if (tries == 0) { + ErrorF("Timeout waiting for %d MMIO slots.\n", n); + ATIEngineReset(atis); + } + atis->mmio_avail -= n; +} + +static int +ATIGetAvailPrimary(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + + if (atic->is_radeon) { + int csq_stat, diff; + + csq_stat = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_STAT); + diff = ((csq_stat & RADEON_CSQ_WPTR_PRIMARY_MASK) >> 8) - + (csq_stat & RADEON_CSQ_RPTR_PRIMARY_MASK); + + if (diff < 0) + return -diff; + else + return atis->cce_pri_size - diff; + } else { + return MMIO_IN32(mmio, R128_REG_PM4_STAT) & + R128_PM4_FIFOCNT_MASK; + } +} + +static void +ATIWaitAvailPrimary(ATIScreenInfo *atis, int n) +{ + int tries; + + if (atis->cce_pri_avail >= n) { + atis->cce_pri_avail -= n; + return; + } + + for (tries = 1000000; tries != 0 && atis->cce_pri_avail < n; tries--) + { + atis->cce_pri_avail = ATIGetAvailPrimary(atis); + if (atis->cce_pri_avail >= n) + break; + } + if (tries == 0) { + ErrorF("Timeout waiting for %d CCE slots (%d avail).\n", n, + atis->cce_pri_avail); + ATIEngineReset(atis); + } + atis->cce_pri_avail -= n; +} + +void +ATIWaitIdle(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + int tries; + char *mmio = atic->reg_base; + RING_LOCALS; + + if (atis->indirectBuffer != NULL) + ATIFlushIndirect(atis, 0); + +#ifdef USE_DRI + if (atis->using_dri) { + int ret; + int cmd = (atic->is_radeon ? DRM_RADEON_CP_IDLE : + DRM_R128_CCE_IDLE); + do { + ret = drmCommandNone(atic->drmFd, cmd); + } while (ret == -EBUSY); + if (ret != 0) + ErrorF("Failed to idle DMA, returned %d\n", ret); + return; + } +#endif + + if (atic->is_radeon && (atis->using_pseudo || atis->using_dma)) { + BEGIN_DMA(4); + OUT_REG(RADEON_REG_RB2D_DSTCACHE_CTLSTAT, + RADEON_RB2D_DC_FLUSH_ALL); + OUT_REG(ATI_REG_WAIT_UNTIL, + RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_3D_IDLECLEAN); + END_DMA(); + } + + if (!atic->is_radeon && (atis->using_pseudo || atis->using_dma)) { + ATIWaitAvailPrimary(atis, atis->cce_pri_size); + + for (tries = 1000000; tries != 0; tries--) { + if ((MMIO_IN32(mmio, R128_REG_PM4_STAT) & + (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE)) == 0) + break; + } + if (tries == 0) { + ErrorF("Timeout idling CCE, resetting...\n"); + ATIEngineReset(atis); + } + } + + /* Radeon CP idle is the same as MMIO idle. */ + if (atis->using_pio || atic->is_radeon) { + /* Empty the fifo */ + ATIWaitAvailMMIO(atis, 64); + + if (atic->is_radeon) { + for (tries = 1000000; tries != 0; tries--) { + if ((MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS) & + RADEON_RBBM_ACTIVE) == 0) + break; + } + } else { + for (tries = 1000000; tries != 0; tries--) { + if ((MMIO_IN32(mmio, R128_REG_GUI_STAT) & + R128_GUI_ACTIVE) == 0) + break; + } + } + if (tries == 0) { + ErrorF("Timeout idling accelerator, resetting...\n"); + ATIEngineReset(atis); + } + } + + ATIFlushPixelCache(atis); + +#if DEBUG_FIFO + ErrorF("Idle?\n"); + ATIDebugFifo(atis); +#endif +} + +dmaBuf * +ATIGetDMABuffer(ATIScreenInfo *atis) +{ + dmaBuf *buf; + + buf = (dmaBuf *)xalloc(sizeof(dmaBuf)); + if (buf == NULL) + return NULL; + +#ifdef USE_DRI + if (atis->using_dri) { + buf->drmBuf = ATIDRIGetBuffer(atis); + if (buf->drmBuf == NULL) { + xfree(buf); + return NULL; + } + buf->size = buf->drmBuf->total; + buf->used = buf->drmBuf->used; + buf->address = buf->drmBuf->address; + return buf; + } +#endif /* USE_DRI */ + + if (atis->using_dma) + buf->size = atis->ring_len / 2; + else + buf->size = 512 * 1024; + buf->address = xalloc(buf->size); + if (buf->address == NULL) { + xfree(buf); + return NULL; + } + buf->used = 0; + + return buf; +} + +/* Decode a type-3 packet into MMIO register writes. Only some type-3 packets + * supported, and only partially. + */ +static void +ATIDispatchPacket3MMIO(ATIScreenInfo *atis, CARD32 header, CARD32 *addr, + int count) +{ + ATICardInfo *atic = atis->atic; + char *mmio = atic->reg_base; + CARD32 settings; + int i = 0; + + settings = addr[i++]; + + if ((settings & ATI_GMC_SRC_PITCH_OFFSET_CNTL) != 0) + MMIO_OUT32(mmio, ATI_REG_SRC_PITCH_OFFSET, addr[i++]); + if ((settings & ATI_GMC_DST_PITCH_OFFSET_CNTL) != 0) + MMIO_OUT32(mmio, ATI_REG_DST_PITCH_OFFSET, addr[i++]); + if ((settings & ATI_GMC_BRUSH_MASK) == ATI_GMC_BRUSH_SOLID_COLOR) + MMIO_OUT32(mmio, ATI_REG_DP_BRUSH_FRGD_CLR, addr[i++]); + + switch (header & (ATI_CCE_PACKETTYPE_MASK | + ATI_CCE_PACKET3_IT_OPCODE_MASK)) + { + case ATI_CCE_PACKET3_PAINT_MULTI: + while (i < count) { + MMIO_OUT32(mmio, ATI_REG_DST_Y_X, + (addr[i] >> 16) | (addr[i] << 16)); + i++; + MMIO_OUT32(mmio, ATI_REG_DST_HEIGHT_WIDTH, + (addr[i] >> 16) | (addr[i] << 16)); + i++; + } + break; + case ATI_CCE_PACKET3_BITBLT_MULTI: + while (i < count) { + MMIO_OUT32(mmio, ATI_REG_SRC_Y_X, + (addr[i] >> 16) | (addr[i] << 16)); + i++; + MMIO_OUT32(mmio, ATI_REG_DST_Y_X, + (addr[i] >> 16) | (addr[i] << 16)); + i++; + MMIO_OUT32(mmio, ATI_REG_DST_HEIGHT_WIDTH, + (addr[i] >> 16) | (addr[i] << 16)); + i++; + } + break; + default: + ErrorF("Unsupported packet: 0x%x\n", header); + } +} + +/* Dispatch packets by decoding them and writing to registers. Doesn't support + * the type 3 packets. + */ +static void +ATIDispatchIndirectMMIO(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + dmaBuf *buf = atis->indirectBuffer; + char *mmio = atic->reg_base; + CARD32 *addr; + CARD32 reg; + int i, n, count; + + addr = (CARD32 *)((char *)buf->address + atis->indirectStart); + count = (buf->used - atis->indirectStart) / 4; + + for (i = 0; i < count; i++) { + CARD32 header = addr[i]; + + switch (header & ATI_CCE_PACKETTYPE_MASK) + { + case ATI_CCE_PACKET0: + n = ((header & ATI_CCE_PACKET0_COUNT_MASK) >> 16) + 1; + reg = (header & ATI_CCE_PACKET0_REG_MASK) << 2; + ATIWaitAvailMMIO(atis, n); + while (n > 0) { + i++; + MMIO_OUT32(mmio, reg, addr[i]); + if ((header & ATI_CCE_PACKET0_ONE_REG_WR) == 0) + reg += 4; + n--; + } + break; + case ATI_CCE_PACKET1: + reg = (header & ATI_CCE_PACKET1_REG_1) << 2; + MMIO_OUT32(mmio, reg, addr[++i]); + reg = ((header & ATI_CCE_PACKET1_REG_2) >> + ATI_CCE_PACKET1_REG_2_SHIFT) << 2; + MMIO_OUT32(mmio, reg, addr[++i]); + break; + case ATI_CCE_PACKET2: + /* PACKET2 is a no-op packet. */ + break; + case ATI_CCE_PACKET3: + n = ((header & ATI_CCE_PACKET3_COUNT_MASK) >> 16) + 1; + ATIDispatchPacket3MMIO(atis, header, &addr[i], n); + i += n; + break; + default: + ErrorF("Unsupported packet: 0x%x\n", addr[i]); + } + } +} + +/* Dispatch packets by sending them through the MMIO aperture. */ +static void +R128DispatchIndirectPDMA(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + dmaBuf *buf = atis->indirectBuffer; + char *mmio = atic->reg_base; + CARD32 *addr; + int count; + + addr = (CARD32 *)((char *)buf->address + atis->indirectStart); + count = (buf->used - atis->indirectStart) / 4; + + while (count > 1) { + ATIWaitAvailPrimary(atis, 2); + MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_EVEN, *addr++); + MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_ODD, *addr++); + count -= 2; + } + + /* Submit last DWORD if necessary. */ + if (count != 0) { + ATIWaitAvailPrimary(atis, 2); + MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_EVEN, *addr++); + MMIO_OUT32(mmio, R128_REG_PM4_FIFO_DATA_ODD, ATI_CCE_PACKET2); + } +} + +/* Dispatch packets by sending them through the MMIO aperture, using the + * primary CCE ring. */ +static void +RadeonDispatchIndirectPDMA(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + dmaBuf *buf = atis->indirectBuffer; + char *mmio = atic->reg_base; + CARD32 *addr; + int count, avail, reg, i; + + addr = (CARD32 *)((char *)buf->address + atis->indirectStart); + count = (buf->used - atis->indirectStart) / 4; + + reg = RADEON_REG_CSQ_APER_PRIMARY; + while (count > 0) { + avail = ATIGetAvailPrimary(atis); + for (i = 0; i < min(count, avail); i++) { + MMIO_OUT32(mmio, reg, *addr++); + if (reg == RADEON_REG_CSQ_APER_PRIMARY_END) + reg = RADEON_REG_CSQ_APER_PRIMARY; + else + reg += 4; + } + count -= i; + } +} + + +/* Dispatch packets by writing them to the (primary) ring buffer, which happens + * to be in framebuffer memory. + */ +static void +R128DispatchIndirectDMA(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + dmaBuf *buf = atis->indirectBuffer; + char *mmio = atic->reg_base; + CARD32 *addr; + int count, ring_count; + + addr = (CARD32 *)((char *)buf->address + atis->indirectStart); + count = (buf->used - atis->indirectStart) / 4; + ring_count = atis->ring_len / 4; + + while (count > 0) { + int tries = 0; + + atis->ring_addr[atis->ring_write++] = *addr++; + if (atis->ring_write >= ring_count) + atis->ring_write = 0; + while (atis->ring_write == atis->ring_read) { + atis->ring_read = MMIO_IN32(mmio, ATI_REG_CCE_RPTR); + if (tries++ == 1000000) { + ErrorF("Timeout submitting packets, resetting...\n"); + ATIEngineReset(atis); + } + } + count--; + } + /* Workaround for some early Rage 128 ASIC spins where the CCE parser + * may read up to 32 DWORDS beyond the end of the ring buffer memory + * before wrapping around, if the ring buffer was empty and a <32 DWORD + * packet that wraps around the end of the ring buffer is submitted. + * To work around that, copy the beginning of the ring buffer past the + * end if that may happen. + */ + if (atis->ring_write < 32) + memcpy(atis->ring_addr + ring_count, atis->ring_addr, 32 * 4); + + /* Update write pointer */ + MMIO_OUT32(mmio, ATI_REG_CCE_WPTR, atis->ring_write); +} + +void +ATIFlushIndirect(ATIScreenInfo *atis, Bool discard) +{ + ATICardInfo *atic = atis->atic; + dmaBuf *buf = atis->indirectBuffer; + + if ((atis->indirectStart == buf->used) && !discard) + return; + +#if DEBUG_FIFO + ErrorF("Dispatching %d DWORDS\n", (buf->used - atis->indirectStart) / + 4); +#endif + +#ifdef USE_DRI + if (atis->using_dri) { + buf->drmBuf->used = buf->used; + ATIDRIDispatchIndirect(atis, discard); + if (discard) { + buf->drmBuf = ATIDRIGetBuffer(atis); + buf->size = buf->drmBuf->total; + buf->used = buf->drmBuf->used; + buf->address = buf->drmBuf->address; + atis->indirectStart = 0; + } else { + /* Start on a double word boundary */ + atis->indirectStart = buf->used = (buf->used + 7) & ~7; + } + return; + } +#endif /* USE_DRI */ + + if (atis->using_dma && !atic->is_radeon) + R128DispatchIndirectDMA(atis); + else if (atis->using_pseudo) { + if (atic->is_radeon) + RadeonDispatchIndirectPDMA(atis); + else + R128DispatchIndirectPDMA(atis); + } else + ATIDispatchIndirectMMIO(atis); + + buf->used = 0; + atis->indirectStart = 0; +} + +static Bool +ATIInitAGP(ScreenPtr pScreen, int size) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + AgpInfoPtr agp_info; + int screennum = atis->screen->mynum; + + if (atic->is_radeon) + return FALSE; + + if (!KdAgpGARTSupported()) + return FALSE; + + if (!KdAcquireGART(screennum)) + return FALSE; + + atis->agp_key = KdAllocateGARTMemory(screennum, size, 0, NULL); + if (atis->agp_key == -1) { + ErrorF("Failed to allocate %dKB GART memory\n", size/1024); + KdReleaseGART(screennum); + return FALSE; + } + + if (!KdBindGARTMemory(screennum, atis->agp_key, 0)) { + ErrorF("Failed to bind GART memory\n"); + KdReleaseGART(screennum); + return FALSE; + } + + agp_info = KdGetAGPInfo(screennum); + if (agp_info == NULL) { + KdUnbindGARTMemory(screennum, atis->agp_key); + KdReleaseGART(screennum); + return FALSE; + } + + atis->agp_addr = KdMapDevice(agp_info->base, agp_info->size); + if (atis->agp_addr == NULL) { + ErrorF("Failed to map GART memory\n"); + KdUnbindGARTMemory(screennum, atis->agp_key); + KdReleaseGART(screennum); + free(agp_info); + return FALSE; + } + KdSetMappedMode(agp_info->base, agp_info->size, + KD_MAPPED_MODE_FRAMEBUFFER); + + atis->agp_size = size; + free(agp_info); + + return TRUE; +} + +static void +ATIFiniAGP(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + int screennum = atis->screen->mynum; + + KdUnbindGARTMemory(screennum, atis->agp_key); + KdReleaseGART(screennum); + atis->agp_addr = NULL; + atis->agp_size = 0; +} + +static Bool +ATIPseudoDMAInit(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + char *mmio = atic->reg_base; + + /* XXX: The Radeon pseudo-dma code is untested. */ + if (0 && atic->is_radeon) + return FALSE; + + ATIUploadMicrocode(atis); + ATIEngineReset(atis); + + if (atic->is_radeon) { + MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL, + RADEON_CSQ_PRIPIO_INDDIS); + atis->cce_pri_size = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL) & + RADEON_CSQ_CNT_PRIMARY_MASK; + MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, RADEON_ME_MODE_FREE_RUN); + } else { + MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL, R128_PM4_192PIO | + R128_PM4_BUFFER_CNTL_NOUPDATE); + atis->cce_pri_size = 192; + MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL, + R128_PM4_MICRO_FREERUN); + } + + return TRUE; +} + +static Bool +ATIPseudoDMAFini(ScreenPtr pScreen) +{ KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + char *mmio = atic->reg_base; + + if (atic->is_radeon) { + MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, 0); + MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL, + RADEON_CSQ_PRIDIS_INDDIS); + } else { + MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL, 0); + MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL, + R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE); + } + atis->cce_pri_size = 0; + + ATIEngineReset(atis); + + return TRUE; +} + +static Bool +ATIDMAInit(ScreenPtr pScreen, Bool use_agp) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + char *mmio = atic->reg_base; + int dma_offset; + CARD32 tmp; + + /* XXX: Not for radeons. Yet? */ + if (atic->is_radeon) + return FALSE; + + if (use_agp) { + if (1) + return FALSE; /* XXX */ + /* Allocate a 1MB AGP space, but only use 128k + 128 for DMA. + * XXX: Should use the rest for things like scratch space. + */ + if (!ATIInitAGP(pScreen, 1024 * 1024)) + return FALSE; + atis->ring_addr = atis->agp_addr; + atis->ring_len = 128 * 1024; + dma_offset = R128_AGP_OFFSET; + } else { + if (1) + return FALSE; /* XXX */ + /* Allocate a 128K buffer, plus 32 DWORDS to give space for the + * R128 ASIC bug workaround. + */ + atis->dma_space = KdOffscreenAlloc(pScreen, 128 * 1024 + 128, + 128, TRUE, NULL, NULL); + if (atis->dma_space == NULL) + return FALSE; + atis->ring_addr = (CARD32 *)(atis->dma_space->offset + + pScreenPriv->screen->memory_base); + atis->ring_len = 128 * 1024; + dma_offset = atis->dma_space->offset; + } + + ATIUploadMicrocode(atis); + ATIEngineReset(atis); + + atis->ring_read = 0; + atis->ring_write = 0; + + tmp = MMIO_IN32(mmio, ATI_REG_BUS_CNTL); + MMIO_OUT32(mmio, ATI_REG_BUS_CNTL, tmp & ~ATI_BUS_MASTER_DIS); + + MMIO_OUT32(mmio, ATI_REG_CCE_RB_BASE, dma_offset); + MMIO_OUT32(mmio, ATI_REG_CCE_WPTR, atis->ring_write); + MMIO_OUT32(mmio, ATI_REG_CCE_RPTR, atis->ring_read); + MMIO_OUT32(mmio, ATI_REG_CCE_RPTR_ADDR, 0 /* XXX? */); + + if (atic->is_radeon) { + MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL, + RADEON_CSQ_PRIBM_INDBM); + atis->cce_pri_size = MMIO_IN32(mmio, RADEON_REG_CP_CSQ_CNTL) & + RADEON_CSQ_CNT_PRIMARY_MASK; + MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, RADEON_ME_MODE_FREE_RUN); + } else { + MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_WM_CNTL, + ((R128_WATERMARK_L/4) << R128_WMA_SHIFT) | + ((R128_WATERMARK_M/4) << R128_WMB_SHIFT) | + ((R128_WATERMARK_N/4) << R128_WMC_SHIFT) | + ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT)); + /* The sample code reads from an undocumneted register + * (PM4_BUFFER_ADDR). Perhaps it's a write posting thing? Do + * a read in case that's it. + */ + MMIO_IN32(mmio, R128_REG_PM4_BUFFER_CNTL); + if (use_agp) { + /* XXX Magic num */ + MMIO_OUT32(mmio, R128_REG_PCI_GART_PAGE, 1); + MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL, + ATILog2(atis->ring_len) | + R128_PM4_192BM | + R128_PM4_BUFFER_CNTL_NOUPDATE); + } else { + MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL, + ATILog2(atis->ring_len) | + R128_PM4_192BM | + R128_PM4_BUFFER_CNTL_NOUPDATE | + R128_PM4_IN_FRAME_BUFFER); + } + atis->cce_pri_size = 192; + MMIO_IN32(mmio, R128_REG_PM4_BUFFER_CNTL); + MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL, + R128_PM4_MICRO_FREERUN); + } + + return TRUE; +} + +static Bool +ATIDMAFini(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + char *mmio = atic->reg_base; + + if (atic->is_radeon) { + MMIO_OUT32(mmio, RADEON_REG_ME_CNTL, 0); + MMIO_OUT32(mmio, RADEON_REG_CP_CSQ_CNTL, + RADEON_CSQ_PRIDIS_INDDIS); + } else { + MMIO_OUT32(mmio, ATI_REG_CCE_WPTR, + atis->ring_write | R128_PM4_BUFFER_DL_DONE); + MMIO_OUT32(mmio, R128_REG_PM4_MICRO_CNTL, 0); + MMIO_OUT32(mmio, R128_REG_PM4_BUFFER_CNTL, + R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE); + } + atis->cce_pri_size = 0; + + ATIEngineReset(atis); + + if (atis->using_agp) + ATIFiniAGP(pScreen); + else + KdOffscreenFree(pScreen, atis->dma_space); + + return TRUE; +} + +void +ATIDMASetup(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + +#ifdef USE_DRI + if (atis->using_dri) + ATIDRIDMAStart(pScreen); +#endif /* USE_DRI */ + + if (!atis->using_dri) { + atis->using_agp = FALSE; + if (atic->is_agp && ATIDMAInit(pScreen, TRUE)) { + atis->using_agp = TRUE; + atis->using_dma = TRUE; + } else if (ATIDMAInit(pScreen, FALSE)) { + atis->using_agp = FALSE; + atis->using_dma = TRUE; + } else if (ATIPseudoDMAInit(pScreen)) + atis->using_pseudo = TRUE; + else + atis->using_pio = TRUE; + } + + atis->indirectBuffer = ATIGetDMABuffer(atis); + if (atis->indirectBuffer == FALSE) + FatalError("Failed to allocate DMA buffer.\n"); + + if (atis->using_dri) + ErrorF("Initialized %s DRI DMA\n", + atis->using_agp ? "AGP" : "PCI"); + else if (atis->using_dma && atis->using_agp) + ErrorF("Initialized AGP DMA\n"); + else if (atis->using_dma) + ErrorF("Initialized framebuffer pseudo-DMA\n"); + else if (atis->using_pseudo) + ErrorF("Initialized pseudo-DMA\n"); + else if (atis->using_pio) + ErrorF("Initialized PIO\n"); +} + +void +ATIDMATeardown(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + + ATIWaitIdle(atis); + +#ifdef USE_DRI + if (atis->using_dri) + ATIDRIDMAStop(pScreen); +#endif /* USE_DRI */ + + if (atis->using_dma) + ATIDMAFini(pScreen); + + if (atis->using_pseudo) + ATIPseudoDMAFini(pScreen); + + if (atis->using_pio || atis->using_pseudo || atis->using_dma) { + xfree(atis->indirectBuffer->address); + xfree(atis->indirectBuffer); + } + atis->indirectBuffer = NULL; + + atis->using_pio = FALSE; + atis->using_pseudo = FALSE; + atis->using_dma = FALSE; + atis->using_agp = FALSE; +} + diff --git a/hw/kdrive/ati/ati_dma.h b/hw/kdrive/ati/ati_dma.h new file mode 100644 index 000000000..69910301e --- /dev/null +++ b/hw/kdrive/ati/ati_dma.h @@ -0,0 +1,97 @@ +/* + * Copyright © 2004 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$ */ + +#ifndef _ATI_DMA_H_ +#define _ATI_DMA_H_ + +#define DMA_PACKET0(reg, count) \ + (ATI_CCE_PACKET0 | (((count) - 1) << 16) | ((reg) >> 2)) +#define DMA_PACKET1(reg1, reg2) \ + (ATI_CCE_PACKET1 | \ + (((reg2) >> 2) << ATI_CCE_PACKET1_REG_2_SHIFT) | ((reg1) >> 2)) +#define DMA_PACKET3(type, count) \ + ((type) | (((count) - 1) << 16)) + +#if 0 /* CCE non-debug */ + +#define RING_LOCALS CARD32 *__head; int __count +#define BEGIN_DMA(n) \ +do { \ + if ((atis->indirectBuffer->used + 4*(n)) > \ + atis->indirectBuffer->size) { \ + ATIFlushIndirect(atis, 1); \ + } \ + __head = (CARD32 *)((char *)atis->indirectBuffer->address + \ + atis->indirectBuffer->used); \ + __count = 0; \ +} while (0) +#define END_DMA() do { \ + atis->indirectBuffer->used += __count * 4; \ +} while (0) + +#else + +#define RING_LOCALS CARD32 *__head; int __count; int __total +#define BEGIN_DMA(n) \ +do { \ + if ((atis->indirectBuffer->used + 4*(n)) > \ + atis->indirectBuffer->size) { \ + ATIFlushIndirect(atis, 1); \ + } \ + __head = (CARD32 *)((char *)atis->indirectBuffer->address + \ + atis->indirectBuffer->used); \ + __count = 0; \ + __total = n; \ +} while (0) +#define END_DMA() do { \ + if (__count != __total) \ + ErrorF("count != total (%d vs %d) at %s:%d\n", __count, \ + __total, __FILE__, __LINE__); \ + atis->indirectBuffer->used += __count * 4; \ +} while (0) + +#endif + +#define OUT_RING(x) do { \ + __head[__count++] = (x); \ +} while (0) + +#define OUT_REG(reg, val) \ +do { \ + OUT_RING(DMA_PACKET0(reg, 1)); \ + OUT_RING(val); \ +} while (0) + +dmaBuf * +ATIGetDMABuffer(ATIScreenInfo *atis); + +void +ATIFlushIndirect(ATIScreenInfo *atis, Bool discard); + +void +ATIDMASetup(ScreenPtr pScreen); + +void +ATIDMATeardown(ScreenPtr pScreen); + +#endif /* _ATI_DMA_H_ */ diff --git a/hw/kdrive/ati/ati_draw.c b/hw/kdrive/ati/ati_draw.c index 8a79bf27c..dd9a1f4db 100644 --- a/hw/kdrive/ati/ati_draw.c +++ b/hw/kdrive/ati/ati_draw.c @@ -28,12 +28,8 @@ #endif #include "ati.h" #include "ati_reg.h" +#include "ati_dma.h" #include "ati_draw.h" -#ifdef USE_DRI -#include "radeon_common.h" -#include "r128_common.h" -#include "ati_sarea.h" -#endif /* USE_DRI */ CARD8 ATISolidRop[16] = { /* GXclear */ 0x00, /* 0 */ @@ -73,335 +69,524 @@ CARD8 ATIBltRop[16] = { /* GXset */ 0xff, /* 1 */ }; -static CARD32 R128BlendOp[] = { - /* Clear */ - R128_ALPHA_BLEND_SRC_ZERO | R128_ALPHA_BLEND_DST_ZERO, - /* Src */ - R128_ALPHA_BLEND_SRC_ONE | R128_ALPHA_BLEND_DST_ZERO, - /* Dst */ - R128_ALPHA_BLEND_SRC_ZERO | R128_ALPHA_BLEND_DST_ONE, - /* Over */ - R128_ALPHA_BLEND_SRC_ONE | R128_ALPHA_BLEND_DST_INVSRCALPHA, - /* OverReverse */ - R128_ALPHA_BLEND_SRC_INVDSTALPHA | R128_ALPHA_BLEND_DST_ONE, - /* In */ - R128_ALPHA_BLEND_SRC_DSTALPHA | R128_ALPHA_BLEND_DST_ZERO, - /* InReverse */ - R128_ALPHA_BLEND_SRC_ZERO | R128_ALPHA_BLEND_DST_SRCALPHA, - /* Out */ - R128_ALPHA_BLEND_SRC_INVDSTALPHA | R128_ALPHA_BLEND_DST_ZERO, - /* OutReverse */ - R128_ALPHA_BLEND_SRC_ZERO | R128_ALPHA_BLEND_DST_INVSRCALPHA, - /* Atop */ - R128_ALPHA_BLEND_SRC_DSTALPHA | R128_ALPHA_BLEND_DST_INVSRCALPHA, - /* AtopReverse */ - R128_ALPHA_BLEND_SRC_INVDSTALPHA | R128_ALPHA_BLEND_DST_SRCALPHA, - /* Xor */ - R128_ALPHA_BLEND_SRC_INVDSTALPHA | R128_ALPHA_BLEND_DST_INVSRCALPHA, - /* Add */ - R128_ALPHA_BLEND_SRC_ONE | R128_ALPHA_BLEND_DST_ONE, -}; - int copydx, copydy; -int fifo_size; ATIScreenInfo *accel_atis; -int src_pitch; -int src_offset; -int src_bpp; /* 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; -/* For r128 Blend, tells whether to force src x/y offset to (0,0). */ -Bool is_repeat; +CARD32 settings, color, src_pitch_offset, dst_pitch_offset; -static void -ATIWaitAvailMMIO(int n) +#define DRAW_USING_PACKET3 0 + +void +ATIDrawSetup(ScreenPtr pScreen) { - ATICardInfo *atic = accel_atis->atic; + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); char *mmio = atic->reg_base; + RING_LOCALS; - if (fifo_size >= n) { - fifo_size -= n; - return; + /* 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) { - do { - fifo_size = MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS) & - RADEON_RBBM_FIFOCNT_MASK; - } while (fifo_size < n); + if (pitch % atis->kaa.offscreenPitch != 0) + ATI_FALLBACK(("Bad pitch 0x%08x\n", pitch)); + *pitch_offset = ((pitch >> 6) << 22) | (offset >> 10); + } else { - do { - fifo_size = MMIO_IN32(mmio, R128_REG_GUI_STAT) & 0xfff; - } while (fifo_size < n); + if (pitch % bpp != 0) + ATI_FALLBACK(("Bad pitch 0x%08x\n", pitch)); + *pitch_offset = ((pitch / bpp) << 21) | (offset >> 5); } - fifo_size -= n; + + 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 -RadeonWaitIdle(void) +ATISolid(int x1, int y1, int x2, int y2) { ATIScreenInfo *atis = accel_atis; - ATICardInfo *atic = atis->atic; - char *mmio = atic->reg_base; - CARD32 temp; - -#ifdef USE_DRI - if (atis->using_dma) { - int ret; - - do { - ret = drmCommandNone(atic->drmFd, DRM_RADEON_CP_IDLE); - } while (ret == -EBUSY); - if (ret != 0) - ErrorF("Failed to idle DMA, returned %d\n", ret); + RING_LOCALS; + + if (is_24bpp) { + x1 *= 3; + x2 *= 3; } -#endif /* USE_DRI */ - - /* Wait for the engine to go idle */ - ATIWaitAvailMMIO(64); - - while ((MMIO_IN32(mmio, RADEON_REG_RBBM_STATUS) & - RADEON_RBBM_ACTIVE) != 0) - ; - - /* Flush pixel cache */ - temp = MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT); - temp |= RADEON_RB2D_DC_FLUSH_ALL; - MMIO_OUT32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT, temp); - - while ((MMIO_IN32(mmio, RADEON_REG_RB2D_DSTCACHE_CTLSTAT) & - RADEON_RB2D_DC_BUSY) != 0) - ; +#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 -R128WaitIdle(void) +ATIDoneSolid(void) { - ATIScreenInfo *atis = accel_atis; - ATICardInfo *atic = atis->atic; - char *mmio = atic->reg_base; - CARD32 temp; - int tries; - -#ifdef USE_DRI - if (atis->using_dma) { - int ret; - - do { - ret = drmCommandNone(atic->drmFd, DRM_R128_CCE_IDLE); - } while (ret == -EBUSY); - if (ret != 0) - ErrorF("Failed to idle DMA, returned %d\n", ret); - } -#endif /* USE_DRI */ - - ATIWaitAvailMMIO(64); - - tries = 1000000; - while (tries--) { - if ((MMIO_IN32(mmio, R128_REG_GUI_STAT) & R128_GUI_ACTIVE) == 0) - break; - } - - temp = MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT); - MMIO_OUT32(mmio, R128_REG_PC_NGUI_CTLSTAT, temp | 0xff); - - tries = 1000000; - while (tries--) { - if ((MMIO_IN32(mmio, R128_REG_PC_NGUI_CTLSTAT) & R128_PC_BUSY) != - R128_PC_BUSY) - break; - } } -void -ATIWaitIdle(void) +static Bool +ATIPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, Pixel pm) { - ATIScreenInfo *atis = accel_atis; - ATICardInfo *atic = atis->atic; + KdScreenPriv(pDst->drawable.pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + CARD32 datatype; + RING_LOCALS; -#ifdef USE_DRI - /* Dispatch any accumulated commands first. */ - if (atis->using_dma && atis->indirectBuffer != NULL) - ATIDMAFlushIndirect(0); -#endif /* USE_DRI */ + 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) - RadeonWaitIdle(); - else - R128WaitIdle(); + 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; } -#ifdef USE_DRI -void ATIDMAStart(ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - ATICardInfo(pScreenPriv); - ATIScreenInfo(pScreenPriv); - int ret; - - if (atic->is_radeon) - ret = drmCommandNone(atic->drmFd, DRM_RADEON_CP_START); - else - ret = drmCommandNone(atic->drmFd, DRM_R128_CCE_START); - - if (ret == 0) - atis->using_dma = TRUE; - else - ErrorF("%s: DMA start returned %d\n", __FUNCTION__, ret); -} - -/* Attempts to idle the DMA engine, and stops it. Note that the ioctl is the - * same for both R128 and Radeon, so we can just use the name of one of them. - */ -void ATIDMAStop(ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - ATICardInfo(pScreenPriv); - ATIScreenInfo(pScreenPriv); - drmRadeonCPStop stop; - int ret; - - stop.flush = 1; - stop.idle = 1; - ret = drmCommandWrite(atic->drmFd, DRM_RADEON_CP_STOP, &stop, - sizeof(drmRadeonCPStop)); - - if (ret != 0 && errno == EBUSY) { - ErrorF("Failed to idle the DMA engine\n"); - - stop.idle = 0; - ret = drmCommandWrite(atic->drmFd, DRM_RADEON_CP_STOP, &stop, - sizeof(drmRadeonCPStop)); - } - atis->using_dma = FALSE; -} - -/* The R128 and Radeon Indirect ioctls differ only in the ioctl number */ -void ATIDMADispatchIndirect(Bool discard) -{ - ATIScreenInfo *atis = accel_atis; - ATICardInfo *atic = atis->atic; - drmBufPtr buffer = atis->indirectBuffer; - drmR128Indirect indirect; - int cmd; - - indirect.idx = buffer->idx; - indirect.start = atis->indirectStart; - indirect.end = buffer->used; - indirect.discard = discard; - cmd = atic->is_radeon ? DRM_RADEON_INDIRECT : DRM_R128_INDIRECT; - drmCommandWriteRead(atic->drmFd, cmd, &indirect, - sizeof(drmR128Indirect)); -} - -/* Flush the indirect buffer to the kernel for submission to the card */ -void ATIDMAFlushIndirect(Bool discard) -{ - ATIScreenInfo *atis = accel_atis; - drmBufPtr buffer = atis->indirectBuffer; - - if (buffer == NULL) - return; - if ((atis->indirectStart == buffer->used) && !discard) - return; - - ATIDMADispatchIndirect(discard); - - if (discard) { - atis->indirectBuffer = ATIDMAGetBuffer(); - atis->indirectStart = 0; - } else { - /* Start on a double word boundary */ - atis->indirectStart = buffer->used = (buffer->used + 7) & ~7; - } -} - -/* Get an indirect buffer for the DMA 2D acceleration commands */ -drmBufPtr ATIDMAGetBuffer() -{ - ATIScreenInfo *atis = accel_atis; - ATICardInfo *atic = atis->atic; - drmDMAReq dma; - drmBufPtr buf = NULL; - int indx = 0; - int size = 0; - int ret; - - dma.context = atis->serverContext; - dma.send_count = 0; - dma.send_list = NULL; - dma.send_sizes = NULL; - dma.flags = 0; - dma.request_count = 1; - if (atis->atic->is_radeon) - dma.request_size = RADEON_BUFFER_SIZE; - else - dma.request_size = R128_BUFFER_SIZE; - dma.request_list = &indx; - dma.request_sizes = &size; - dma.granted_count = 0; - - do { - ret = drmDMA(atic->drmFd, &dma); - } while (ret != 0); - - buf = &atis->buffers->list[indx]; - buf->used = 0; - return buf; -} - -/* The hardware has a cache on the memory controller for writes to the - * destination, which I guess is separate for 2d and 3d. So, when switching - * between 2d and 3d you need to wait for idle and for the cache to clean. - */ -void -RadeonSwitchTo2D(void) +static void +ATICopy(int srcX, int srcY, int dstX, int dstY, int w, int h) { ATIScreenInfo *atis = accel_atis; RING_LOCALS; - BEGIN_RING(2); - OUT_RING(DMA_PACKET0(RADEON_REG_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); + 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 } -void -RadeonSwitchTo3D(void) +static void +ATIDoneCopy(void) { - ATIScreenInfo *atis = accel_atis; - RING_LOCALS; - - BEGIN_RING(2); - OUT_RING(DMA_PACKET0(RADEON_REG_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN); - ADVANCE_RING(); } -#endif /* USE_DRI */ - static Bool ATIUploadToScreen(PixmapPtr pDst, char *src, int src_pitch) { - int i; - char *dst; - int dst_pitch; - int bytes; + 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 = pDst->devPrivate.ptr; + dst_offset = ((CARD8 *)pDst->devPrivate.ptr - + pScreenPriv->screen->memory_base); dst_pitch = pDst->devKind; - bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch; + width = pDst->drawable.width; + height = pDst->drawable.height; + bpp = pDst->drawable.bitsPerPixel; - KdCheckSync(pDst->drawable.pScreen); + success = ATIGetDatatypeBpp(bpp, &datatype); - for (i = 0; i < pDst->drawable.height; i++) { - memcpy(dst, src, bytes); - dst += dst_pitch; - src += src_pitch; + 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; } @@ -410,87 +595,76 @@ static Bool ATIUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst) { KdScreenPriv(pSrc->drawable.pScreen); + ATICardInfo(pScreenPriv); ATIScreenInfo(pScreenPriv); - int dst_pitch; + int dst_pitch, src_pitch, w, i, size, bytes; + unsigned char *dst, *src; + RING_LOCALS; - dst_pitch = (pSrc->drawable.width * pSrc->drawable.bitsPerPixel / 8 + + /* 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); - - if (dst_pitch * pSrc->drawable.height > atis->scratch_size) + + 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_offset + + pDst->devPrivate.ptr = atis->scratch_next + pScreenPriv->screen->memory_base; + atis->scratch_next += size; - return ATIUploadToScreen(pDst, pSrc->devPrivate.ptr, pSrc->devKind); -} + src = pSrc->devPrivate.ptr; + src_pitch = pSrc->devKind; + dst = pDst->devPrivate.ptr; + bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch; -static Bool -R128GetDatatypePict(CARD32 format, CARD32 *type) -{ - switch (format) { - case PICT_a8r8g8b8: - *type = R128_DATATYPE_ARGB_8888; - return TRUE; - case PICT_r5g6b5: - *type = R128_DATATYPE_RGB_565; - return TRUE; + i = pSrc->drawable.height; + while (i--) { + memcpy(dst, src, bytes); + dst += dst_pitch; + src += src_pitch; } - ATI_FALLBACK(("Unsupported format: %x\n", format)); - - return FALSE; -} - -/* 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) -{ - is_24bpp = FALSE; - - switch (bpp) { - case 8: - *type = R128_DATATYPE_C8; - return TRUE; - case 16: - *type = R128_DATATYPE_RGB_565; - return TRUE; - case 24: - *type = R128_DATATYPE_C8; - is_24bpp = TRUE; - return TRUE; - case 32: - *type = R128_DATATYPE_ARGB_8888; - return TRUE; - default: - ATI_FALLBACK(("Unsupported bpp: %x\n", bpp)); - return FALSE; + /* 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(); } -} -#ifdef USE_DRI -#define USE_DMA -#include "ati_drawtmp.h" -#include "r128_blendtmp.h" -#endif /* USE_DRI */ - -#undef USE_DMA -#include "ati_drawtmp.h" -#include "r128_blendtmp.h" - -static void -ATIDoneSolid(void) -{ + return TRUE; } static void -ATIDoneCopy(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 @@ -502,64 +676,36 @@ ATIDrawInit(ScreenPtr pScreen) ErrorF("Screen: %d/%d depth/bpp\n", pScreenPriv->screen->fb[0].depth, pScreenPriv->screen->fb[0].bitsPerPixel); + #ifdef USE_DRI - if (atis->using_dri) - ATIDMAStart(pScreen); - else { - if (!atic->is_r300 && ATIDRIScreenInit(pScreen)) - atis->using_dri = TRUE; - } + atis->using_dri = ATIDRIScreenInit(pScreen); #endif /* USE_DRI */ memset(&atis->kaa, 0, sizeof(KaaScreenInfoRec)); -#ifdef USE_DRI - if (atis->using_dma) { - atis->kaa.PrepareSolid = ATIPrepareSolidDMA; - atis->kaa.Solid = ATISolidDMA; - atis->kaa.PrepareCopy = ATIPrepareCopyDMA; - atis->kaa.Copy = ATICopyDMA; - if (!atic->is_radeon) { - atis->kaa.PrepareBlend = R128PrepareBlendDMA; - atis->kaa.Blend = R128BlendDMA; - atis->kaa.DoneBlend = R128DoneBlendDMA; - } else if (!atic->is_r200) { - atis->kaa.PrepareBlend = RadeonPrepareBlend; - atis->kaa.Blend = RadeonBlend; - atis->kaa.DoneBlend = RadeonDoneBlend; - atis->kaa.PrepareComposite = RadeonPrepareComposite; - atis->kaa.Composite = RadeonComposite; - atis->kaa.DoneComposite = RadeonDoneComposite; - } - } else { -#else - { -#endif /* USE_DRI */ - atis->kaa.PrepareSolid = ATIPrepareSolidMMIO; - atis->kaa.Solid = ATISolidMMIO; - atis->kaa.PrepareCopy = ATIPrepareCopyMMIO; - atis->kaa.Copy = ATICopyMMIO; - if (!atic->is_radeon) { - atis->kaa.PrepareBlend = R128PrepareBlendMMIO; - atis->kaa.Blend = R128BlendMMIO; - atis->kaa.DoneBlend = R128DoneBlendMMIO; - } - } - atis->kaa.UploadToScreen = ATIUploadToScreen; - if (atis->scratch_size != 0) - atis->kaa.UploadToScratch = ATIUploadToScratch; + 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; @@ -569,26 +715,81 @@ ATIDrawInit(ScreenPtr pScreen) 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) { -#ifdef USE_DRI KdScreenPriv(pScreen); ATIScreenInfo(pScreenPriv); - if (atis->using_dma) - ATIDMAStop(pScreen); - - if (atis->using_dri) +#ifdef USE_DRI + if (atis->using_dri) { ATIDRICloseScreen(pScreen); + atis->using_dri = FALSE; + } #endif /* USE_DRI */ kaaDrawFini(pScreen); @@ -600,7 +801,5 @@ ATIDrawSync(ScreenPtr pScreen) KdScreenPriv(pScreen); ATIScreenInfo(pScreenPriv); - accel_atis = atis; - - ATIWaitIdle(); + ATIWaitIdle(atis); } diff --git a/hw/kdrive/ati/ati_draw.h b/hw/kdrive/ati/ati_draw.h index af2a95ce4..2131681d5 100644 --- a/hw/kdrive/ati/ati_draw.h +++ b/hw/kdrive/ati/ati_draw.h @@ -1,7 +1,5 @@ /* - * $Id$ - * - * Copyright © 2003 Eric Anholt + * Copyright © 2004 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 @@ -26,63 +24,69 @@ #ifndef _ATI_DRAW_H_ #define _ATI_DRAW_H_ -#ifdef USE_DRI +Bool +ATIGetOffsetPitch(ATIScreenInfo *atis, int bpp, CARD32 *pitch_offset, + int offset, int pitch); -#define DMA_PACKET0( reg, n ) \ - (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) +Bool +ATIGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset); -#define RING_LOCALS CARD32 *__head; int __count; - -#define BEGIN_RING( n ) \ -do { \ - if (atis->indirectBuffer == NULL) { \ - atis->indirectBuffer = ATIDMAGetBuffer(); \ - atis->indirectStart = 0; \ - } else if ((atis->indirectBuffer->used + 4*(n)) > \ - atis->indirectBuffer->total) { \ - ATIDMAFlushIndirect(1); \ - } \ - __head = (pointer)((char *)atis->indirectBuffer->address + \ - atis->indirectBuffer->used); \ - __count = 0; \ -} while (0) - -#define ADVANCE_RING() do { \ - atis->indirectBuffer->used += __count * (int)sizeof(CARD32); \ -} while (0) - -#define OUT_RING(x) do { \ - MMIO_OUT32(&__head[__count++], 0, (x)); \ -} while (0) - -#define OUT_RING_REG(reg, val) \ -do { \ - OUT_RING(DMA_PACKET0(reg, 0)); \ - OUT_RING(val); \ -} while (0) - -drmBufPtr ATIDMAGetBuffer(void); -void ATIDMAFlushIndirect(Bool discard); -void ATIDMADispatchIndirect(Bool discard); -void ATIDMAStart(ScreenPtr pScreen); -void ATIDMAStop(ScreenPtr pScreen); - -Bool RadeonPrepareBlend(int op, PicturePtr pSrcPicture, PicturePtr pDstPicture, +Bool +R128PrepareBlend(int op, PicturePtr pSrcPicture, PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pDst); -void RadeonBlend(int srcX, int srcY, int dstX, int dstY, int width, int height); -Bool RadeonPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, - PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); -void RadeonDoneBlend(void); -void RadeonComposite(int srcX, int srcY, int maskX, int maskY, int dstX, - int dstY, int w, int h); -void RadeonDoneComposite(void); -void RadeonSwitchTo2D(void); -void RadeonSwitchTo3D(void); - -#endif /* USE_DRI */ void -ATIWaitIdle(void); +R128Blend(int srcX, int srcY, int dstX, int dstY, int width, int height); + +void +R128DoneBlend(void); + +Bool +R128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +Bool +R128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); + +void +R128Composite(int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, + int w, int h); + +void +R128DoneComposite(void); + +Bool +R100CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +Bool +R100PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); + +Bool +R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +Bool +R200PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst); + +void +RadeonComposite(int srcX, int srcY, int maskX, int maskY, int dstX, + int dstY, int w, int h); + +void +RadeonDoneComposite(void); + +void +RadeonSwitchTo2D(ATIScreenInfo *atis); + +void +RadeonSwitchTo3D(ATIScreenInfo *atis); + +void +ATIWaitIdle(ATIScreenInfo *atis); #if 0 #define ATI_FALLBACK(x) \ diff --git a/hw/kdrive/ati/ati_dri.c b/hw/kdrive/ati/ati_dri.c index 5bd07916a..d86802550 100644 --- a/hw/kdrive/ati/ati_dri.c +++ b/hw/kdrive/ati/ati_dri.c @@ -28,6 +28,7 @@ #endif #include "ati.h" #include "ati_reg.h" +#include "ati_dma.h" #include "ati_dri.h" #include "ati_dripriv.h" #include "sarea.h" @@ -67,8 +68,6 @@ static Bool ATIInitVisualConfigs(ScreenPtr pScreen) if (depth != 16 && (depth != 24 || bpp != 32)) ErrorF("DRI GLX unsupported at %d/%d depth/bpp\n", depth, bpp); - /* Same number of configs for 16 and 24bpp, so I factored this part out. - */ if (atis->depthOffset != 0) use_db = 1; else @@ -89,15 +88,15 @@ static Bool ATIInitVisualConfigs(ScreenPtr pScreen) } i = 0; - if (depth == 16) { - for (db = 0; db <= use_db; db++) { - for (accum = 0; accum <= 1; accum++) { - for (stencil = 0; stencil <= 1; stencil++) { - pATIConfigPtrs[i] = &pATIConfigs[i]; - - pConfigs[i].vid = (VisualID)(-1); - pConfigs[i].class = -1; - pConfigs[i].rgba = TRUE; + for (db = 0; db <= use_db; db++) { + for (accum = 0; accum <= 1; accum++) { + for (stencil = 0; stencil <= 1; stencil++) { + pATIConfigPtrs[i] = &pATIConfigs[i]; + + pConfigs[i].vid = (VisualID)(-1); + pConfigs[i].class = -1; + pConfigs[i].rgba = TRUE; + if (depth == 16) { pConfigs[i].redSize = 5; pConfigs[i].greenSize = 6; pConfigs[i].blueSize = 5; @@ -106,54 +105,7 @@ static Bool ATIInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].greenMask = 0x000007E0; pConfigs[i].blueMask = 0x0000001F; pConfigs[i].alphaMask = 0x00000000; - if (accum) { /* Simulated in software */ - pConfigs[i].accumRedSize = 16; - pConfigs[i].accumGreenSize = 16; - pConfigs[i].accumBlueSize = 16; - pConfigs[i].accumAlphaSize = 0; - } else { - pConfigs[i].accumRedSize = 0; - pConfigs[i].accumGreenSize = 0; - pConfigs[i].accumBlueSize = 0; - pConfigs[i].accumAlphaSize = 0; - } - if (db) - pConfigs[i].doubleBuffer = TRUE; - else - pConfigs[i].doubleBuffer = FALSE; - pConfigs[i].stereo = FALSE; - pConfigs[i].bufferSize = 16; - pConfigs[i].depthSize = 16; - if (stencil) - pConfigs[i].stencilSize = 8; - else - pConfigs[i].stencilSize = 0; - pConfigs[i].auxBuffers = 0; - pConfigs[i].level = 0; - if (accum) { - pConfigs[i].visualRating = GLX_SLOW_CONFIG; - } else { - pConfigs[i].visualRating = GLX_NONE; - } - pConfigs[i].transparentPixel = GLX_NONE; - pConfigs[i].transparentRed = 0; - pConfigs[i].transparentGreen = 0; - pConfigs[i].transparentBlue = 0; - pConfigs[i].transparentAlpha = 0; - pConfigs[i].transparentIndex = 0; - i++; - } - } - } - } else { - for (db = 0; db <= use_db; db++) { - for (accum = 0; accum <= 1; accum++) { - for (stencil = 0; stencil <= 1; stencil++) { - pATIConfigPtrs[i] = &pATIConfigs[i]; - - pConfigs[i].vid = (VisualID)(-1); - pConfigs[i].class = -1; - pConfigs[i].rgba = TRUE; + } else { pConfigs[i].redSize = 8; pConfigs[i].greenSize = 8; pConfigs[i].blueSize = 8; @@ -162,22 +114,34 @@ static Bool ATIInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].greenMask = 0x0000FF00; pConfigs[i].blueMask = 0x000000FF; pConfigs[i].alphaMask = 0xFF000000; - if (accum) { /* Simulated in software */ - pConfigs[i].accumRedSize = 16; - pConfigs[i].accumGreenSize = 16; - pConfigs[i].accumBlueSize = 16; - pConfigs[i].accumAlphaSize = 16; - } else { - pConfigs[i].accumRedSize = 0; - pConfigs[i].accumGreenSize = 0; - pConfigs[i].accumBlueSize = 0; - pConfigs[i].accumAlphaSize = 0; - } - if (db) - pConfigs[i].doubleBuffer = TRUE; + } + if (accum) { /* Simulated in software */ + pConfigs[i].accumRedSize = 16; + pConfigs[i].accumGreenSize = 16; + pConfigs[i].accumBlueSize = 16; + if (depth == 16) + pConfigs[i].accumAlphaSize = 0; else - pConfigs[i].doubleBuffer = FALSE; - pConfigs[i].stereo = FALSE; + pConfigs[i].accumAlphaSize = 16; + } else { + pConfigs[i].accumRedSize = 0; + pConfigs[i].accumGreenSize = 0; + pConfigs[i].accumBlueSize = 0; + pConfigs[i].accumAlphaSize = 0; + } + if (db) + pConfigs[i].doubleBuffer = TRUE; + else + pConfigs[i].doubleBuffer = FALSE; + pConfigs[i].stereo = FALSE; + if (depth == 16) { + pConfigs[i].bufferSize = 16; + pConfigs[i].depthSize = 16; + if (stencil) + pConfigs[i].stencilSize = 8; + else + pConfigs[i].stencilSize = 0; + } else { pConfigs[i].bufferSize = 32; if (stencil) { pConfigs[i].depthSize = 24; @@ -186,23 +150,23 @@ static Bool ATIInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].depthSize = 24; pConfigs[i].stencilSize = 0; } - pConfigs[i].auxBuffers = 0; - pConfigs[i].level = 0; - if (accum) { - pConfigs[i].visualRating = GLX_SLOW_CONFIG; - } else { - pConfigs[i].visualRating = GLX_NONE; - } - pConfigs[i].transparentPixel = GLX_NONE; - pConfigs[i].transparentRed = 0; - pConfigs[i].transparentGreen = 0; - pConfigs[i].transparentBlue = 0; - pConfigs[i].transparentAlpha = 0; - pConfigs[i].transparentIndex = 0; - i++; - } - } } + pConfigs[i].auxBuffers = 0; + pConfigs[i].level = 0; + if (accum) { + pConfigs[i].visualRating = GLX_SLOW_CONFIG; + } else { + pConfigs[i].visualRating = GLX_NONE; + } + pConfigs[i].transparentPixel = GLX_NONE; + pConfigs[i].transparentRed = 0; + pConfigs[i].transparentGreen = 0; + pConfigs[i].transparentBlue = 0; + pConfigs[i].transparentAlpha = 0; + pConfigs[i].transparentIndex = 0; + i++; + } + } } atis->numVisualConfigs = numConfigs; @@ -224,18 +188,18 @@ ATIDRIInitGARTValues(ScreenPtr pScreen) /* Initialize the ring buffer data */ atis->ringStart = atis->gartOffset; - atis->ringMapSize = atis->ringSize*1024*1024 + DRM_PAGE_SIZE; + atis->ringMapSize = atis->ringSize * 1024 * 1024 + DRM_PAGE_SIZE; atis->ringReadOffset = atis->ringStart + atis->ringMapSize; atis->ringReadMapSize = DRM_PAGE_SIZE; /* Reserve space for vertex/indirect buffers */ atis->bufStart = atis->ringReadOffset + atis->ringReadMapSize; - atis->bufMapSize = atis->bufSize*1024*1024; + atis->bufMapSize = atis->bufSize * 1024 * 1024; /* Reserve the rest for GART textures */ atis->gartTexStart = atis->bufStart + atis->bufMapSize; - s = (atis->gartSize*1024*1024 - atis->gartTexStart); + s = (atis->gartSize * 1024 * 1024 - atis->gartTexStart); l = ATILog2((s-1) / ATI_NR_TEX_REGIONS); if (l < ATI_LOG_TEX_GRANULARITY) l = ATI_LOG_TEX_GRANULARITY; atis->gartTexMapSize = (s >> l) << l; @@ -258,10 +222,10 @@ ATIDRIAddAndMap(int fd, drmHandle offset, drmSize size, ErrorF("[%s] %s handle = 0x%08lx\n", name, desc, *handle); if (drmMap(fd, *handle, size, address) < 0) { - ErrorF("[agp] Could not map %s\n", name, desc); + ErrorF("[%s] Could not map %s\n", name, desc); return FALSE; } - ErrorF("[%s] %s mapped at 0x%08lx\n", name, desc, address); + ErrorF("[%s] %s mapped at 0x%08lx\n", name, desc, *address); return TRUE; } @@ -280,6 +244,10 @@ ATIDRIAgpInit(ScreenPtr pScreen) unsigned long agpBase; CARD32 cntl, chunk; + /* AGP DRI seems broken on my R128, not sure why. */ + if (!atic->is_radeon) + return FALSE; + if (drmAgpAcquire(atic->drmFd) < 0) { ErrorF("[agp] AGP not available\n"); return FALSE; @@ -306,20 +274,20 @@ ATIDRIAgpInit(ScreenPtr pScreen) } /* Workaround for some hardware bugs */ - /* XXX: Magic numbers */ - if (!atic->is_r200) { - cntl = MMIO_IN32(mmio, RADEON_REG_AGP_CNTL) | 0x000e0000; - MMIO_OUT32(mmio, RADEON_REG_AGP_CNTL, cntl); + if (atic->is_r100) { + cntl = MMIO_IN32(mmio, ATI_REG_AGP_CNTL); + MMIO_OUT32(mmio, ATI_REG_AGP_CNTL, cntl | + RADEON_PENDING_SLOTS_VAL | RADEON_PENDING_SLOTS_SEL); } - if ((ret = drmAgpAlloc(atic->drmFd, atis->gartSize*1024*1024, 0, NULL, - &atis->agpMemHandle)) < 0) { + if ((ret = drmAgpAlloc(atic->drmFd, atis->gartSize * 1024 * 1024, 0, + NULL, &atis->agpMemHandle)) < 0) { ErrorF("[agp] Out of memory (%d)\n", ret); drmAgpRelease(atic->drmFd); return FALSE; } ErrorF("[agp] %d kB allocated with handle 0x%08lx\n", - atis->gartSize*1024, (long)atis->agpMemHandle); + atis->gartSize * 1024, (long)atis->agpMemHandle); if (drmAgpBind(atic->drmFd, atis->agpMemHandle, atis->gartOffset) < 0) { ErrorF("[agp] Could not bind\n"); @@ -350,30 +318,31 @@ ATIDRIAgpInit(ScreenPtr pScreen) return FALSE; /* Initialize radeon/r128 AGP registers */ - cntl = MMIO_IN32(mmio, RADEON_REG_AGP_CNTL); - cntl &= ~RADEON_AGP_APER_SIZE_MASK; + cntl = MMIO_IN32(mmio, ATI_REG_AGP_CNTL); + cntl &= ~ATI_AGP_APER_SIZE_MASK; switch (atis->gartSize) { - case 256: cntl |= RADEON_AGP_APER_SIZE_256MB; break; - case 128: cntl |= RADEON_AGP_APER_SIZE_128MB; break; - case 64: cntl |= RADEON_AGP_APER_SIZE_64MB; break; - case 32: cntl |= RADEON_AGP_APER_SIZE_32MB; break; - case 16: cntl |= RADEON_AGP_APER_SIZE_16MB; break; - case 8: cntl |= RADEON_AGP_APER_SIZE_8MB; break; - case 4: cntl |= RADEON_AGP_APER_SIZE_4MB; break; + case 256: cntl |= ATI_AGP_APER_SIZE_256MB; break; + case 128: cntl |= ATI_AGP_APER_SIZE_128MB; break; + case 64: cntl |= ATI_AGP_APER_SIZE_64MB; break; + case 32: cntl |= ATI_AGP_APER_SIZE_32MB; break; + case 16: cntl |= ATI_AGP_APER_SIZE_16MB; break; + case 8: cntl |= ATI_AGP_APER_SIZE_8MB; break; + case 4: cntl |= ATI_AGP_APER_SIZE_4MB; break; default: - ErrorF("[agp] Illegal aperture size %d kB\n", atis->gartSize*1024); + ErrorF("[agp] Illegal aperture size %d kB\n", atis->gartSize * + 1024); return FALSE; } agpBase = drmAgpBase(atic->drmFd); - MMIO_OUT32(mmio, RADEON_REG_AGP_BASE, agpBase); - MMIO_OUT32(mmio, RADEON_REG_AGP_CNTL, cntl); + MMIO_OUT32(mmio, ATI_REG_AGP_BASE, agpBase); + MMIO_OUT32(mmio, ATI_REG_AGP_CNTL, cntl); if (!atic->is_radeon) { /* Disable Rage 128 PCIGART registers */ chunk = MMIO_IN32(mmio, R128_REG_BM_CHUNK_0_VAL); chunk &= ~(R128_BM_PTR_FORCE_TO_PCI | - R128_BM_PM4_RD_FORCE_TO_PCI | - R128_BM_GLOBAL_FORCE_TO_PCI); + R128_BM_PM4_RD_FORCE_TO_PCI | + R128_BM_GLOBAL_FORCE_TO_PCI); MMIO_OUT32(mmio, R128_REG_BM_CHUNK_0_VAL, chunk); /* Ensure AGP GART is used (for now) */ @@ -395,14 +364,14 @@ ATIDRIPciInit(ScreenPtr pScreen) ATIDRIInitGARTValues(pScreen); - ret = drmScatterGatherAlloc(atic->drmFd, atis->gartSize*1024*1024, + ret = drmScatterGatherAlloc(atic->drmFd, atis->gartSize * 1024 * 1024, &atis->pciMemHandle); if (ret < 0) { ErrorF("[pci] Out of memory (%d)\n", ret); return FALSE; } ErrorF("[pci] %d kB allocated with handle 0x%08lx\n", - atis->gartSize*1024, (long)atis->pciMemHandle); + atis->gartSize * 1024, (long)atis->pciMemHandle); if (!ATIDRIAddAndMap(atic->drmFd, atis->ringStart, atis->ringMapSize, DRM_SCATTER_GATHER, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL, @@ -432,7 +401,8 @@ ATIDRIPciInit(ScreenPtr pScreen) chunk |= (R128_BM_PTR_FORCE_TO_PCI | R128_BM_PM4_RD_FORCE_TO_PCI | R128_BM_GLOBAL_FORCE_TO_PCI); MMIO_OUT32(mmio, R128_REG_BM_CHUNK_0_VAL, chunk); - MMIO_OUT32(mmio, R128_REG_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */ + /* Ensure PCI GART is used */ + MMIO_OUT32(mmio, R128_REG_PCI_GART_PAGE, 0); } return TRUE; } @@ -446,29 +416,28 @@ R128DRIKernelInit(ScreenPtr pScreen) ATIScreenInfo(pScreenPriv); ATICardInfo(pScreenPriv); drmR128Init drmInfo; + int bpp = pScreenPriv->screen->fb[0].bitsPerPixel; memset(&drmInfo, 0, sizeof(drmR128Init) ); drmInfo.func = DRM_R128_INIT_CCE; drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); - drmInfo.is_pci = !atis->IsAGP; - drmInfo.cce_mode = atis->CCEMode; + drmInfo.is_pci = !atic->is_agp; + drmInfo.cce_mode = R128_PM4_64BM_64VCBM_64INDBM; drmInfo.cce_secure = TRUE; - drmInfo.ring_size = atis->ringSize*1024*1024; + drmInfo.ring_size = atis->ringSize * 1024 * 1024; drmInfo.usec_timeout = atis->DMAusecTimeout; - drmInfo.fb_bpp = pScreenPriv->screen->fb[0].bitsPerPixel; - drmInfo.depth_bpp = pScreenPriv->screen->fb[0].bitsPerPixel; - - /* XXX: pitches are in pixels on r128. */ drmInfo.front_offset = atis->frontOffset; - drmInfo.front_pitch = atis->frontPitch; - + drmInfo.front_pitch = atis->frontPitch / (bpp / 8); drmInfo.back_offset = atis->backOffset; - drmInfo.back_pitch = atis->backPitch; + drmInfo.back_pitch = atis->backPitch / (bpp / 8); + drmInfo.fb_bpp = bpp; drmInfo.depth_offset = atis->depthOffset; - drmInfo.depth_pitch = atis->depthPitch; + drmInfo.depth_pitch = atis->depthPitch / (bpp / 8); + drmInfo.depth_bpp = bpp; + drmInfo.span_offset = atis->spanOffset; drmInfo.fb_offset = atis->fbHandle; @@ -502,21 +471,20 @@ RadeonDRIKernelInit(ScreenPtr pScreen) drmInfo.func = DRM_RADEON_INIT_CP; drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); - drmInfo.is_pci = !atis->IsAGP; - drmInfo.cp_mode = atis->CPMode; - drmInfo.gart_size = atis->gartSize*1024*1024; - drmInfo.ring_size = atis->ringSize*1024*1024; + drmInfo.is_pci = !atic->is_agp; + drmInfo.cp_mode = RADEON_CSQ_PRIBM_INDBM; + drmInfo.gart_size = atis->gartSize * 1024 * 1024; + drmInfo.ring_size = atis->ringSize * 1024 * 1024; drmInfo.usec_timeout = atis->DMAusecTimeout; - drmInfo.fb_bpp = pScreenPriv->screen->fb[0].bitsPerPixel; - drmInfo.depth_bpp = pScreenPriv->screen->fb[0].bitsPerPixel; - drmInfo.front_offset = atis->frontOffset; drmInfo.front_pitch = atis->frontPitch; drmInfo.back_offset = atis->backOffset; drmInfo.back_pitch = atis->backPitch; + drmInfo.fb_bpp = pScreenPriv->screen->fb[0].bitsPerPixel; drmInfo.depth_offset = atis->depthOffset; drmInfo.depth_pitch = atis->depthPitch; + drmInfo.depth_bpp = pScreenPriv->screen->fb[0].bitsPerPixel; drmInfo.fb_offset = atis->fbHandle; drmInfo.mmio_offset = atis->registerHandle; @@ -547,7 +515,7 @@ ATIDRIBufInit(ScreenPtr pScreen) else size = R128_BUFFER_SIZE; - if (atis->IsAGP) + if (atic->is_agp) type = DRM_AGP_BUFFER; else type = DRM_SG_BUFFER; @@ -607,14 +575,14 @@ static void ATIDRISwapContext(ScreenPtr pScreen, DRISyncType syncType, if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ - if (atis->using_dma) - ATIDMAFlushIndirect(1); + if (atis->dma_started) + ATIFlushIndirect(atis, 1); } } static Bool ATIDRIFinishScreenInit(ScreenPtr pScreen); -/* Initialize the screen-specific data structures for the DRI and the +/* Initialize the screen-specific data structures for the Radeon or Rage 128. This is the main entry point to the device-specific initialization code. It calls device-independent DRI functions to create the DRI data structures and initialize the DRI state. */ @@ -630,17 +598,12 @@ ATIDRIScreenInit(ScreenPtr pScreen) int devSareaSize; drmSetVersion sv; - /* XXX: Disable DRI clients for unsupported depths */ - - if (atic->is_radeon) { - atis->CPMode = RADEON_CSQ_PRIBM_INDBM; - } - else { - atis->CCEMode = R128_PM4_64BM_64VCBM_64INDBM; - atis->CCEFifoSize = 64; + if (pScreenPriv->screen->fb[0].depth < 16 || + pScreenPriv->screen->fb[0].bitsPerPixel == 24) { + ErrorF("DRI unsupported at this depth/bpp, disabling.\n"); + return FALSE; } - atis->IsAGP = FALSE; /* XXX */ atis->agpMode = 1; atis->gartSize = 8; atis->ringSize = 1; @@ -674,7 +637,7 @@ ATIDRIScreenInit(ScreenPtr pScreen) * DRIScreenInit(). */ pDRIInfo = DRICreateInfoRec(); - if (!pDRIInfo) + if (pDRIInfo == NULL) return FALSE; atis->pDRIInfo = pDRIInfo; @@ -692,9 +655,8 @@ ATIDRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverMajorVersion = 4; pDRIInfo->ddxDriverMinorVersion = 0; pDRIInfo->ddxDriverPatchVersion = 0; - /* XXX: RADEON_FB_BASE(pScreenPriv->card); */ pDRIInfo->frameBufferPhysicalAddress = - (unsigned long)pScreenPriv->screen->memory_base; + pScreenPriv->card->attr.address[0] & 0xfc000000; pDRIInfo->frameBufferSize = pScreenPriv->screen->memory_size; pDRIInfo->frameBufferStride = pScreenPriv->screen->fb[0].byteStride; pDRIInfo->ddxDrawableTableEntry = SAREA_MAX_DRAWABLES; @@ -705,12 +667,12 @@ ATIDRIScreenInit(ScreenPtr pScreen) */ pDRIInfo->SAREASize = SAREA_MAX; - if (!atic->is_radeon) { - pDRIInfo->devPrivateSize = sizeof(R128DRIRec); - devSareaSize = sizeof(R128SAREAPriv); - } else { + if (atic->is_radeon) { pDRIInfo->devPrivateSize = sizeof(RADEONDRIRec); devSareaSize = sizeof(RADEONSAREAPriv); + } else { + pDRIInfo->devPrivateSize = sizeof(R128DRIRec); + devSareaSize = sizeof(R128SAREAPriv); } if (sizeof(XF86DRISAREARec) + devSareaSize > SAREA_MAX) { @@ -751,8 +713,8 @@ ATIDRIScreenInit(ScreenPtr pScreen) /* Add a map for the MMIO registers that will be accessed by any * DRI-based clients. */ - atis->registerSize = RADEON_REG_SIZE(atic); - if (drmAddMap(atic->drmFd, RADEON_REG_BASE(pScreenPriv->screen->card), + atis->registerSize = ATI_REG_SIZE(pScreenPriv->screen->card); + if (drmAddMap(atic->drmFd, ATI_REG_BASE(pScreenPriv->screen->card), atis->registerSize, DRM_REGISTERS, DRM_READ_ONLY, &atis->registerHandle) < 0) { ATIDRICloseScreen(pScreen); @@ -765,14 +727,14 @@ ATIDRIScreenInit(ScreenPtr pScreen) &scratch_int, &scratch_int, &scratch_ptr); /* Initialize AGP */ - if (atis->IsAGP && !ATIDRIAgpInit(pScreen)) { - atis->IsAGP = FALSE; + if (atic->is_agp && !ATIDRIAgpInit(pScreen)) { + atic->is_agp = FALSE; ErrorF("[agp] AGP failed to initialize; falling back to PCI mode.\n"); - ErrorF("[agp] Make sure your kernel's AGP support is loaded and functioning."); + ErrorF("[agp] Make sure your kernel's AGP support is loaded and functioning.\n"); } /* Initialize PCIGART */ - if (!atis->IsAGP && !ATIDRIPciInit(pScreen)) { + if (!atic->is_agp && !ATIDRIPciInit(pScreen)) { ATIDRICloseScreen(pScreen); return FALSE; } @@ -797,9 +759,11 @@ static Bool R128DRIFinishScreenInit(ScreenPtr pScreen) { KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); ATIScreenInfo(pScreenPriv); R128SAREAPrivPtr pSAREAPriv; R128DRIPtr pR128DRI; + int bpp = pScreenPriv->screen->fb[0].bitsPerPixel; /* Initialize the kernel data structures */ if (!R128DRIKernelInit(pScreen)) { @@ -816,9 +780,6 @@ R128DRIFinishScreenInit(ScreenPtr pScreen) /* Initialize IRQ */ ATIDRIIrqInit(pScreen); - /* Initialize and start the CCE if required */ - ATIDMAStart(pScreen); - pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen); memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); @@ -830,15 +791,15 @@ R128DRIFinishScreenInit(ScreenPtr pScreen) pR128DRI->depth = pScreenPriv->screen->fb[0].depth; pR128DRI->bpp = pScreenPriv->screen->fb[0].bitsPerPixel; - pR128DRI->IsPCI = !atis->IsAGP; + pR128DRI->IsPCI = !atic->is_agp; pR128DRI->AGPMode = atis->agpMode; pR128DRI->frontOffset = atis->frontOffset; - pR128DRI->frontPitch = atis->frontPitch; + pR128DRI->frontPitch = atis->frontPitch / (bpp / 8); pR128DRI->backOffset = atis->backOffset; - pR128DRI->backPitch = atis->backPitch; + pR128DRI->backPitch = atis->backPitch / (bpp / 8); pR128DRI->depthOffset = atis->depthOffset; - pR128DRI->depthPitch = atis->depthPitch; + pR128DRI->depthPitch = atis->depthPitch / (bpp / 8); pR128DRI->spanOffset = atis->spanOffset; pR128DRI->textureOffset = atis->textureOffset; pR128DRI->textureSize = atis->textureSize; @@ -894,8 +855,6 @@ RadeonDRIFinishScreenInit(ScreenPtr pScreen) ErrorF("[drm] Failed to initialize GART heap manager\n"); } - ATIDMAStart(pScreen); - /* Initialize the SAREA private data structure */ pSAREAPriv = (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScreen); memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); @@ -908,7 +867,7 @@ RadeonDRIFinishScreenInit(ScreenPtr pScreen) pRADEONDRI->depth = pScreenPriv->screen->fb[0].depth; pRADEONDRI->bpp = pScreenPriv->screen->fb[0].bitsPerPixel; - pRADEONDRI->IsPCI = !atis->IsAGP; + pRADEONDRI->IsPCI = !atic->is_agp; pRADEONDRI->AGPMode = atis->agpMode; pRADEONDRI->frontOffset = atis->frontOffset; @@ -968,8 +927,6 @@ ATIDRIFinishScreenInit(ScreenPtr pScreen) } } - atis->using_dri = TRUE; - return TRUE; } @@ -985,11 +942,17 @@ ATIDRICloseScreen(ScreenPtr pScreen) drmRadeonInit drmRadeonInfo; if (atis->indirectBuffer != NULL) { - ATIDMADispatchIndirect(1); + /* Flush any remaining commands and free indirect buffers. + * Two steps are used because ATIFlushIndirect gets a + * new buffer after discarding. + */ + ATIFlushIndirect(atis, 1); + ATIDRIDispatchIndirect(atis, 1); + xfree(atis->indirectBuffer); atis->indirectBuffer = NULL; atis->indirectStart = 0; } - ATIDMAStop(pScreen); + ATIDRIDMAStop(pScreen); if (atis->irqEnabled) { drmCtlUninstHandler(atic->drmFd); @@ -1055,7 +1018,7 @@ ATIDRICloseScreen(ScreenPtr pScreen) DRIDestroyInfoRec(atis->pDRIInfo); atis->pDRIInfo = NULL; } - atis->using_dri = FALSE; + #ifdef GLXEXT if (atis->pVisualConfigs) { xfree(atis->pVisualConfigs); @@ -1068,3 +1031,101 @@ ATIDRICloseScreen(ScreenPtr pScreen) #endif /* GLXEXT */ atic->drmFd = -1; } + +void +ATIDRIDMAStart(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + int ret; + + if (atic->is_radeon) + ret = drmCommandNone(atic->drmFd, DRM_RADEON_CP_START); + else + ret = drmCommandNone(atic->drmFd, DRM_R128_CCE_START); + + if (ret == 0) + atis->dma_started = TRUE; + else + ErrorF("%s: DMA start returned %d\n", __FUNCTION__, ret); +} + +/* Attempts to idle the DMA engine and stops it. Note that the ioctl is the + * same for both R128 and Radeon, so we can just use the name of one of them. + */ +void +ATIDRIDMAStop(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + drmRadeonCPStop stop; + int ret; + + stop.flush = 1; + stop.idle = 1; + ret = drmCommandWrite(atic->drmFd, DRM_RADEON_CP_STOP, &stop, + sizeof(drmRadeonCPStop)); + + if (ret != 0 && errno == EBUSY) { + ErrorF("Failed to idle the DMA engine\n"); + + stop.idle = 0; + ret = drmCommandWrite(atic->drmFd, DRM_RADEON_CP_STOP, &stop, + sizeof(drmRadeonCPStop)); + } + atis->dma_started = FALSE; +} + +/* The R128 and Radeon Indirect ioctls differ only in the ioctl number */ +void +ATIDRIDispatchIndirect(ATIScreenInfo *atis, Bool discard) +{ + ATICardInfo *atic = atis->atic; + drmBufPtr buffer = atis->indirectBuffer->drmBuf; + drmR128Indirect indirect; + int cmd; + + indirect.idx = buffer->idx; + indirect.start = atis->indirectStart; + indirect.end = buffer->used; + indirect.discard = discard; + cmd = atic->is_radeon ? DRM_RADEON_INDIRECT : DRM_R128_INDIRECT; + drmCommandWriteRead(atic->drmFd, cmd, &indirect, + sizeof(drmR128Indirect)); +} + +/* Get an indirect buffer for the DMA 2D acceleration commands */ +drmBufPtr +ATIDRIGetBuffer(ATIScreenInfo *atis) +{ + ATICardInfo *atic = atis->atic; + drmDMAReq dma; + drmBufPtr buf = NULL; + int indx = 0; + int size = 0; + int ret; + + dma.context = atis->serverContext; + dma.send_count = 0; + dma.send_list = NULL; + dma.send_sizes = NULL; + dma.flags = 0; + dma.request_count = 1; + if (atis->atic->is_radeon) + dma.request_size = RADEON_BUFFER_SIZE; + else + dma.request_size = R128_BUFFER_SIZE; + dma.request_list = &indx; + dma.request_sizes = &size; + dma.granted_count = 0; + + do { + ret = drmDMA(atic->drmFd, &dma); + } while (ret != 0); + + buf = &atis->buffers->list[indx]; + buf->used = 0; + return buf; +} diff --git a/hw/kdrive/ati/ati_microcode.c b/hw/kdrive/ati/ati_microcode.c new file mode 100644 index 000000000..2a27195cc --- /dev/null +++ b/hw/kdrive/ati/ati_microcode.c @@ -0,0 +1,597 @@ +/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- + * radeon_cp.c -- CP support for Radeon -*- linux-c -*- + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Fremont, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Kevin E. Martin + * Gareth Hughes + */ + +/* CCE microcode (from ATI) */ + +#include "ati.h" + +CARD32 r128_cce_microcode[] = { + 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, + 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, + 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, + 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11, + 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28, + 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, + 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, + 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, + 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071, + 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2, + 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1, + 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, + 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, + 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, + 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1, + 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82, + 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729, + 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008, + 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, + 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, + 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, + 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0, + 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370, + 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1, + 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793, + 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, + 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, + 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1, + 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1, + 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894, + 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14, + 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1, + 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, + 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, + 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +CARD32 radeon_cp_microcode[][2] = { + { 0x21007000, 0000000000 }, + { 0x20007000, 0000000000 }, + { 0x000000b4, 0x00000004 }, + { 0x000000b8, 0x00000004 }, + { 0x6f5b4d4c, 0000000000 }, + { 0x4c4c427f, 0000000000 }, + { 0x5b568a92, 0000000000 }, + { 0x4ca09c6d, 0000000000 }, + { 0xad4c4c4c, 0000000000 }, + { 0x4ce1af3d, 0000000000 }, + { 0xd8afafaf, 0000000000 }, + { 0xd64c4cdc, 0000000000 }, + { 0x4cd10d10, 0000000000 }, + { 0x000f0000, 0x00000016 }, + { 0x362f242d, 0000000000 }, + { 0x00000012, 0x00000004 }, + { 0x000f0000, 0x00000016 }, + { 0x362f282d, 0000000000 }, + { 0x000380e7, 0x00000002 }, + { 0x04002c97, 0x00000002 }, + { 0x000f0001, 0x00000016 }, + { 0x333a3730, 0000000000 }, + { 0x000077ef, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000021, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000021, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000021, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00000017, 0x00000004 }, + { 0x0003802b, 0x00000002 }, + { 0x040067e0, 0x00000002 }, + { 0x00000017, 0x00000004 }, + { 0x000077e0, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x000037e1, 0x00000002 }, + { 0x040067e1, 0x00000006 }, + { 0x000077e0, 0x00000002 }, + { 0x000077e1, 0x00000002 }, + { 0x000077e1, 0x00000006 }, + { 0xffffffff, 0000000000 }, + { 0x10000000, 0000000000 }, + { 0x0003802b, 0x00000002 }, + { 0x040067e0, 0x00000006 }, + { 0x00007675, 0x00000002 }, + { 0x00007676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0003802c, 0x00000002 }, + { 0x04002676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0000002f, 0x00000018 }, + { 0x0000002f, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x00000030, 0x00000018 }, + { 0x00000030, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x01605000, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00098000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x64c0603e, 0x00000004 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00080000, 0x00000016 }, + { 0000000000, 0000000000 }, + { 0x0400251d, 0x00000002 }, + { 0x00007580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x04002580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x00000049, 0x00000004 }, + { 0x00005000, 0000000000 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x00019000, 0x00000002 }, + { 0x00011055, 0x00000014 }, + { 0x00000055, 0x00000012 }, + { 0x0400250f, 0x00000002 }, + { 0x0000504f, 0x00000004 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00007565, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000058, 0x00000004 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x01e655b4, 0x00000002 }, + { 0x4401b0e4, 0x00000002 }, + { 0x01c110e4, 0x00000002 }, + { 0x26667066, 0x00000018 }, + { 0x040c2565, 0x00000002 }, + { 0x00000066, 0x00000018 }, + { 0x04002564, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x0000005d, 0x00000004 }, + { 0x00401069, 0x00000008 }, + { 0x00101000, 0x00000002 }, + { 0x000d80ff, 0x00000002 }, + { 0x0080006c, 0x00000008 }, + { 0x000f9000, 0x00000002 }, + { 0x000e00ff, 0x00000002 }, + { 0000000000, 0x00000006 }, + { 0x0000008f, 0x00000018 }, + { 0x0000005b, 0x00000004 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00007576, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00009000, 0x00000002 }, + { 0x00041000, 0x00000002 }, + { 0x0c00350e, 0x00000002 }, + { 0x00049000, 0x00000002 }, + { 0x00051000, 0x00000002 }, + { 0x01e785f8, 0x00000002 }, + { 0x00200000, 0x00000002 }, + { 0x0060007e, 0x0000000c }, + { 0x00007563, 0x00000002 }, + { 0x006075f0, 0x00000021 }, + { 0x20007073, 0x00000004 }, + { 0x00005073, 0x00000004 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00007576, 0x00000002 }, + { 0x00007577, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x0000750f, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00600083, 0x0000000c }, + { 0x006075f0, 0x00000021 }, + { 0x000075f8, 0x00000002 }, + { 0x00000083, 0x00000004 }, + { 0x000a750e, 0x00000002 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x0020750f, 0x00000002 }, + { 0x00600086, 0x00000004 }, + { 0x00007570, 0x00000002 }, + { 0x00007571, 0x00000002 }, + { 0x00007572, 0x00000006 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00005000, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00007568, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000095, 0x0000000c }, + { 0x00058000, 0x00000002 }, + { 0x0c607562, 0x00000002 }, + { 0x00000097, 0x00000004 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x00600096, 0x00000004 }, + { 0x400070e5, 0000000000 }, + { 0x000380e6, 0x00000002 }, + { 0x040025c5, 0x00000002 }, + { 0x000380e5, 0x00000002 }, + { 0x000000a8, 0x0000001c }, + { 0x000650aa, 0x00000018 }, + { 0x040025bb, 0x00000002 }, + { 0x000610ab, 0x00000018 }, + { 0x040075bc, 0000000000 }, + { 0x000075bb, 0x00000002 }, + { 0x000075bc, 0000000000 }, + { 0x00090000, 0x00000006 }, + { 0x00090000, 0x00000002 }, + { 0x000d8002, 0x00000006 }, + { 0x00007832, 0x00000002 }, + { 0x00005000, 0x00000002 }, + { 0x000380e7, 0x00000002 }, + { 0x04002c97, 0x00000002 }, + { 0x00007820, 0x00000002 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x01200000, 0x00000002 }, + { 0x20077000, 0x00000002 }, + { 0x01200000, 0x00000002 }, + { 0x20007000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x0120751b, 0x00000002 }, + { 0x8040750a, 0x00000002 }, + { 0x8040750b, 0x00000002 }, + { 0x00110000, 0x00000002 }, + { 0x000380e5, 0x00000002 }, + { 0x000000c6, 0x0000001c }, + { 0x000610ab, 0x00000018 }, + { 0x844075bd, 0x00000002 }, + { 0x000610aa, 0x00000018 }, + { 0x840075bb, 0x00000002 }, + { 0x000610ab, 0x00000018 }, + { 0x844075bc, 0x00000002 }, + { 0x000000c9, 0x00000004 }, + { 0x804075bd, 0x00000002 }, + { 0x800075bb, 0x00000002 }, + { 0x804075bc, 0x00000002 }, + { 0x00108000, 0x00000002 }, + { 0x01400000, 0x00000002 }, + { 0x006000cd, 0x0000000c }, + { 0x20c07000, 0x00000020 }, + { 0x000000cf, 0x00000012 }, + { 0x00800000, 0x00000006 }, + { 0x0080751d, 0x00000006 }, + { 0000000000, 0000000000 }, + { 0x0000775c, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460275d, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x01e00830, 0x00000002 }, + { 0x21007000, 0000000000 }, + { 0x6464614d, 0000000000 }, + { 0x69687420, 0000000000 }, + { 0x00000073, 0000000000 }, + { 0000000000, 0000000000 }, + { 0x00005000, 0x00000002 }, + { 0x000380d0, 0x00000002 }, + { 0x040025e0, 0x00000002 }, + { 0x000075e1, 0000000000 }, + { 0x00000001, 0000000000 }, + { 0x000380e0, 0x00000002 }, + { 0x04002394, 0x00000002 }, + { 0x00005000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0x00000008, 0000000000 }, + { 0x00000004, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, +}; + +CARD32 r200_cp_microcode[][2] = { + { 0x21007000, 0000000000 }, + { 0x20007000, 0000000000 }, + { 0x000000ab, 0x00000004 }, + { 0x000000af, 0x00000004 }, + { 0x66544a49, 0000000000 }, + { 0x49494174, 0000000000 }, + { 0x54517d83, 0000000000 }, + { 0x498d8b64, 0000000000 }, + { 0x49494949, 0000000000 }, + { 0x49da493c, 0000000000 }, + { 0x49989898, 0000000000 }, + { 0xd34949d5, 0000000000 }, + { 0x9dc90e11, 0000000000 }, + { 0xce9b9b9b, 0000000000 }, + { 0x000f0000, 0x00000016 }, + { 0x352e232c, 0000000000 }, + { 0x00000013, 0x00000004 }, + { 0x000f0000, 0x00000016 }, + { 0x352e272c, 0000000000 }, + { 0x000f0001, 0x00000016 }, + { 0x3239362f, 0000000000 }, + { 0x000077ef, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00061000, 0x00000002 }, + { 0x00000020, 0x0000001a }, + { 0x00004000, 0x0000001e }, + { 0x00000016, 0x00000004 }, + { 0x0003802a, 0x00000002 }, + { 0x040067e0, 0x00000002 }, + { 0x00000016, 0x00000004 }, + { 0x000077e0, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x000037e1, 0x00000002 }, + { 0x040067e1, 0x00000006 }, + { 0x000077e0, 0x00000002 }, + { 0x000077e1, 0x00000002 }, + { 0x000077e1, 0x00000006 }, + { 0xffffffff, 0000000000 }, + { 0x10000000, 0000000000 }, + { 0x0003802a, 0x00000002 }, + { 0x040067e0, 0x00000006 }, + { 0x00007675, 0x00000002 }, + { 0x00007676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0003802b, 0x00000002 }, + { 0x04002676, 0x00000002 }, + { 0x00007677, 0x00000002 }, + { 0x00007678, 0x00000006 }, + { 0x0000002e, 0x00000018 }, + { 0x0000002e, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x0000002f, 0x00000018 }, + { 0x0000002f, 0x00000018 }, + { 0000000000, 0x00000006 }, + { 0x01605000, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00098000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x64c0603d, 0x00000004 }, + { 0x00080000, 0x00000016 }, + { 0000000000, 0000000000 }, + { 0x0400251d, 0x00000002 }, + { 0x00007580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x04002580, 0x00000002 }, + { 0x00067581, 0x00000002 }, + { 0x00000046, 0x00000004 }, + { 0x00005000, 0000000000 }, + { 0x00061000, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x00019000, 0x00000002 }, + { 0x00011055, 0x00000014 }, + { 0x00000055, 0x00000012 }, + { 0x0400250f, 0x00000002 }, + { 0x0000504a, 0x00000004 }, + { 0x00007565, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000051, 0x00000004 }, + { 0x01e655b4, 0x00000002 }, + { 0x4401b0dc, 0x00000002 }, + { 0x01c110dc, 0x00000002 }, + { 0x2666705d, 0x00000018 }, + { 0x040c2565, 0x00000002 }, + { 0x0000005d, 0x00000018 }, + { 0x04002564, 0x00000002 }, + { 0x00007566, 0x00000002 }, + { 0x00000054, 0x00000004 }, + { 0x00401060, 0x00000008 }, + { 0x00101000, 0x00000002 }, + { 0x000d80ff, 0x00000002 }, + { 0x00800063, 0x00000008 }, + { 0x000f9000, 0x00000002 }, + { 0x000e00ff, 0x00000002 }, + { 0000000000, 0x00000006 }, + { 0x00000080, 0x00000018 }, + { 0x00000054, 0x00000004 }, + { 0x00007576, 0x00000002 }, + { 0x00065000, 0x00000002 }, + { 0x00009000, 0x00000002 }, + { 0x00041000, 0x00000002 }, + { 0x0c00350e, 0x00000002 }, + { 0x00049000, 0x00000002 }, + { 0x00051000, 0x00000002 }, + { 0x01e785f8, 0x00000002 }, + { 0x00200000, 0x00000002 }, + { 0x00600073, 0x0000000c }, + { 0x00007563, 0x00000002 }, + { 0x006075f0, 0x00000021 }, + { 0x20007068, 0x00000004 }, + { 0x00005068, 0x00000004 }, + { 0x00007576, 0x00000002 }, + { 0x00007577, 0x00000002 }, + { 0x0000750e, 0x00000002 }, + { 0x0000750f, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00600076, 0x0000000c }, + { 0x006075f0, 0x00000021 }, + { 0x000075f8, 0x00000002 }, + { 0x00000076, 0x00000004 }, + { 0x000a750e, 0x00000002 }, + { 0x0020750f, 0x00000002 }, + { 0x00600079, 0x00000004 }, + { 0x00007570, 0x00000002 }, + { 0x00007571, 0x00000002 }, + { 0x00007572, 0x00000006 }, + { 0x00005000, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00007568, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x00000084, 0x0000000c }, + { 0x00058000, 0x00000002 }, + { 0x0c607562, 0x00000002 }, + { 0x00000086, 0x00000004 }, + { 0x00600085, 0x00000004 }, + { 0x400070dd, 0000000000 }, + { 0x000380dd, 0x00000002 }, + { 0x00000093, 0x0000001c }, + { 0x00065095, 0x00000018 }, + { 0x040025bb, 0x00000002 }, + { 0x00061096, 0x00000018 }, + { 0x040075bc, 0000000000 }, + { 0x000075bb, 0x00000002 }, + { 0x000075bc, 0000000000 }, + { 0x00090000, 0x00000006 }, + { 0x00090000, 0x00000002 }, + { 0x000d8002, 0x00000006 }, + { 0x00005000, 0x00000002 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x00007821, 0x00000002 }, + { 0x00007800, 0000000000 }, + { 0x01665000, 0x00000002 }, + { 0x000a0000, 0x00000002 }, + { 0x000671cc, 0x00000002 }, + { 0x0286f1cd, 0x00000002 }, + { 0x000000a3, 0x00000010 }, + { 0x21007000, 0000000000 }, + { 0x000000aa, 0x0000001c }, + { 0x00065000, 0x00000002 }, + { 0x000a0000, 0x00000002 }, + { 0x00061000, 0x00000002 }, + { 0x000b0000, 0x00000002 }, + { 0x38067000, 0x00000002 }, + { 0x000a00a6, 0x00000004 }, + { 0x20007000, 0000000000 }, + { 0x01200000, 0x00000002 }, + { 0x20077000, 0x00000002 }, + { 0x01200000, 0x00000002 }, + { 0x20007000, 0000000000 }, + { 0x00061000, 0x00000002 }, + { 0x0120751b, 0x00000002 }, + { 0x8040750a, 0x00000002 }, + { 0x8040750b, 0x00000002 }, + { 0x00110000, 0x00000002 }, + { 0x000380dd, 0x00000002 }, + { 0x000000bd, 0x0000001c }, + { 0x00061096, 0x00000018 }, + { 0x844075bd, 0x00000002 }, + { 0x00061095, 0x00000018 }, + { 0x840075bb, 0x00000002 }, + { 0x00061096, 0x00000018 }, + { 0x844075bc, 0x00000002 }, + { 0x000000c0, 0x00000004 }, + { 0x804075bd, 0x00000002 }, + { 0x800075bb, 0x00000002 }, + { 0x804075bc, 0x00000002 }, + { 0x00108000, 0x00000002 }, + { 0x01400000, 0x00000002 }, + { 0x006000c4, 0x0000000c }, + { 0x20c07000, 0x00000020 }, + { 0x000000c6, 0x00000012 }, + { 0x00800000, 0x00000006 }, + { 0x0080751d, 0x00000006 }, + { 0x000025bb, 0x00000002 }, + { 0x000040c0, 0x00000004 }, + { 0x0000775c, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460275d, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x00007999, 0x00000002 }, + { 0x00a05000, 0x00000002 }, + { 0x00661000, 0x00000002 }, + { 0x0460299b, 0x00000020 }, + { 0x00004000, 0000000000 }, + { 0x01e00830, 0x00000002 }, + { 0x21007000, 0000000000 }, + { 0x00005000, 0x00000002 }, + { 0x00038042, 0x00000002 }, + { 0x040025e0, 0x00000002 }, + { 0x000075e1, 0000000000 }, + { 0x00000001, 0000000000 }, + { 0x000380d9, 0x00000002 }, + { 0x04007394, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, + { 0000000000, 0000000000 }, +}; + diff --git a/hw/kdrive/ati/ati_reg.h b/hw/kdrive/ati/ati_reg.h index 477e67f14..36eba9a0e 100644 --- a/hw/kdrive/ati/ati_reg.h +++ b/hw/kdrive/ati/ati_reg.h @@ -1,6 +1,4 @@ /* - * $Id$ - * * Copyright © 2003 Eric Anholt * * Permission to use, copy, modify, distribute, and sell this software and its @@ -23,104 +21,489 @@ */ /* $Header$ */ -/* Many of the Radeon register defines are the same for the r128 */ +/* Many of the Radeon and Rage 128 registers are the same. + * ATI_ should denote registers and values that are common for R128 and Radeon. + * + * The information in this file comes from many sources, including the Rage 128 + * DDK, Rage 128 register reference, the XFree86 and kernel Rage 128 and Radeon + * register definition headers, and bits from the Radeon DDK and RV200 register + * specs supplied by others. + */ -#define RADEON_REG_BUS_CNTL 0x0030 -# define RADEON_BUS_MASTER_DIS (1 << 6) +#define ATI_REG_CLOCK_CNTL_INDEX 0x0008 +# define ATI_PLL_WR_EN (1 << 7) +# define ATI_PLL_DIV_SEL (3 << 8) -#define RADEON_GEN_INT_CNTL 0x0040 -#define RADEON_REG_AGP_BASE 0x0170 +#define ATI_REG_CLOCK_CNTL_DATA 0x000c -#define RADEON_REG_AGP_CNTL 0x0174 -# define RADEON_AGP_APER_SIZE_256MB (0x00 << 0) -# define RADEON_AGP_APER_SIZE_128MB (0x20 << 0) -# define RADEON_AGP_APER_SIZE_64MB (0x30 << 0) -# define RADEON_AGP_APER_SIZE_32MB (0x38 << 0) -# define RADEON_AGP_APER_SIZE_16MB (0x3c << 0) -# define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) -# define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) -# define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) +#define ATI_REG_BUS_CNTL 0x0030 +# define ATI_BUS_MASTER_DIS (1 << 6) + +#define ATI_REG_GEN_INT_CNTL 0x0040 + +#define ATI_REG_GEN_CNTL 0x0050 +# define ATI_CRTC_DBL_SCAN_EN (1 << 0) +# define ATI_CRTC_INTERLACE_EN (1 << 1) +# define ATI_CRTC_CSYNC_EN (1 << 4) +# define ATI_CRTC_PIX_WIDTH_MASK (7 << 8) +# define ATI_CRTC_CUR_EN (1 << 16) +# define ATI_CRTC_CUR_MODE_MASK (7 << 17) +# define ATI_CRTC_ICON_EN (1 << 20) +# define ATI_CRTC_EXT_DISP_EN (1 << 24) +# define ATI_CRTC_EN (1 << 25) +# define ATI_CRTC_DISP_REQ_EN_B (1 << 26) + +#define ATI_REG_CRTC_EXT_CNTL 0x0054 +# define ATI_CRTC_EN (1 << 25) +# define ATI_CRTC_VGA_XOVERSCAN (1 << 0) +# define ATI_VGA_ATI_LINEAR (1 << 3) +# define ATI_XCRT_CNT_EN (1 << 6) +# define ATI_CRTC_HSYNC_DIS (1 << 8) +# define ATI_CRTC_VSYNC_DIS (1 << 9) +# define ATI_CRTC_DISPLAY_DIS (1 << 10) +# define RADEON_CRTC_SYNC_TRISTAT (1 << 11) +# define ATI_CRTC_CRT_ON (1 << 15) +# define R128_FP_OUT_EN (1 << 22) +# define R128_FP_ACTIVE (1 << 23) + +#define ATI_REG_DAC_CNTL 0x0058 +# define ATI_DAC_RANGE_CNTL (3 << 0) +# define ATI_DAC_BLANKING (1 << 2) +# define R128_DAC_CRT_SEL_CRTC2 (1 << 4) +# define ATI_DAC_CMP_EN (1 << 3) +# define R128_DAC_PALETTE_ACC_CTL (1 << 5) +# define ATI_DAC_CMP_OUTPUT (1 << 7) +# define ATI_DAC_8BIT_EN (1 << 8) +# define ATI_DAC_VGA_ADR_EN (1 << 13) +# define ATI_DAC_PDWN (1 << 15) +# define ATI_DAC_MASK_ALL (0xff << 24) + +#define ATI_REG_I2C_CNTL_1 0x0094 + +#define R128_REG_GEN_RESET_CNTL 0x00f0 +# define R128_SOFT_RESET_GUI (1 << 0) +# define R128_SOFT_RESET_VCLK (1 << 8) +# define R128_SOFT_RESET_PCLK (1 << 9) +# define R128_SOFT_RESET_DISPENG_XCLK (1 << 11) +# define R128_SOFT_RESET_MEMCTLR_XCLK (1 << 12) + +#define RADEON_REG_RBBM_SOFT_RESET 0x00f0 +# define RADEON_SOFT_RESET_CP (1 << 0) +# define RADEON_SOFT_RESET_HI (1 << 1) +# define RADEON_SOFT_RESET_SE (1 << 2) +# define RADEON_SOFT_RESET_RE (1 << 3) +# define RADEON_SOFT_RESET_PP (1 << 4) +# define RADEON_SOFT_RESET_E2 (1 << 5) +# define RADEON_SOFT_RESET_RB (1 << 6) +# define RADEON_SOFT_RESET_HDP (1 << 7) + +#define RADEON_REG_HOST_PATH_CNTL 0x0130 +# define RADEON_HDP_SOFT_RESET (1 << 26) + +#define ATI_REG_AGP_BASE 0x0170 + +#define ATI_REG_AGP_CNTL 0x0174 +# define ATI_AGP_APER_SIZE_256MB (0x00 << 0) +# define ATI_AGP_APER_SIZE_128MB (0x20 << 0) +# define ATI_AGP_APER_SIZE_64MB (0x30 << 0) +# define ATI_AGP_APER_SIZE_32MB (0x38 << 0) +# define ATI_AGP_APER_SIZE_16MB (0x3c << 0) +# define ATI_AGP_APER_SIZE_8MB (0x3e << 0) +# define ATI_AGP_APER_SIZE_4MB (0x3f << 0) +# define ATI_AGP_APER_SIZE_MASK (0x3f << 0) +#define RADEON_PENDING_SLOTS_VAL 0x00060000 +#define RADEON_PENDING_SLOTS_SEL 0x00080000 + +#define R128_REG_PCI_GART_PAGE 0x017c + +#define R128_REG_PC_NGUI_CTLSTAT 0x0184 +# define R128_PC_FLUSH_GUI (3 << 0) +# define R128_PC_RI_GUI (1 << 2) +# define R128_PC_FLUSH_ALL 0x00ff +# define R128_PC_BUSY (1 << 31) + +#define R128_REG_VIPH_CONTROL 0x01d0 + +#define ATI_REG_CRTC_H_TOTAL_DISP 0x0200 +#define ATI_REG_CRTC2_H_TOTAL_DISP 0x0300 +# define ATI_CRTC_H_TOTAL (0x01ff << 0) +# define ATI_CRTC_H_TOTAL_SHIFT 0 +# define ATI_CRTC_H_DISP (0x00ff << 16) +# define ATI_CRTC_H_DISP_SHIFT 16 + +#define ATI_REG_CRTC_H_SYNC_STRT_WID 0x0204 +#define ATI_REG_CRTC2_H_SYNC_STRT_WID 0x0304 +# define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) +# define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3) +# define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3 +# define RADEON_CRTC_H_SYNC_WID (0x3f << 16) +# define RADEON_CRTC_H_SYNC_WID_SHIFT 16 +# define RADEON_CRTC_H_SYNC_POL (1 << 23) + +#define ATI_REG_CRTC_OFFSET 0x0224 +#define ATI_REG_CRTC2_OFFSET 0x0324 +#define ATI_REG_CRTC_OFFSET_CNTL 0x0228 +#define ATI_REG_CRTC2_OFFSET_CNTL 0x0328 +#define ATI_REG_CRTC_PITCH 0x022c +#define ATI_REG_CRTC2_PITCH 0x032c + +#define ATI_REG_OVR_CLR 0x0230 +#define ATI_REG_OVR_WID_LEFT_RIGHT 0x0234 +#define ATI_REG_OVR_WID_TOP_BOTTOM 0x0238 + +#define ATI_REG_CUR_OFFSET 0x0260 +#define ATI_REG_CUR_HORZ_VERT_POSN 0x0264 +#define ATI_REG_CUR_HORZ_VERT_OFF 0x0268 +# define ATI_CUR_LOCK (1 << 31) +# define ATI_CURSOR_WIDTH 64 +# define ATI_CURSOR_HEIGHT 64 +# define ATI_CURSOR_PITCH 16 + +#define ATI_REG_CUR_CLR0 0x026c +#define ATI_REG_CUR_CLR1 0x0270 +#define ATI_REG_OV0_SCALE_CNTL 0x0420 +#define ATI_REG_SUBPIC_CNTL 0x0540 +#define ATI_REG_CAP0_TRIG_CNTL 0x0950 +#define RADEON_REG_VIPH_CONTROL 0x0c50 #define RADEON_REG_RBBM_STATUS 0x0e40 # define RADEON_RBBM_FIFOCNT_MASK 0x007f # define RADEON_RBBM_ACTIVE (1 << 31) +#define ATI_REG_CCE_RB_BASE 0x0700 + +#define R128_REG_PM4_BUFFER_CNTL 0x0704 +# define R128_PM4_IN_FRAME_BUFFER (1 << 26) +# define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27) +# define R128_PM4_NONPM4 (0 << 28) +# define R128_PM4_192PIO (1 << 28) +# define R128_PM4_192BM (2 << 28) +# define R128_PM4_128PIO_64INDBM (3 << 28) +# define R128_PM4_128BM_64INDBM (4 << 28) +# define R128_PM4_64PIO_128INDBM (5 << 28) +# define R128_PM4_64BM_128INDBM (6 << 28) +# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) + +#define RADEON_REG_CP_RB_CNTL 0x0704 + +#define R128_REG_PM4_BUFFER_WM_CNTL 0x0708 +# define R128_WMA_SHIFT 0 +# define R128_WMB_SHIFT 8 +# define R128_WMC_SHIFT 16 +# define R128_WB_WM_SHIFT 24 + +#define ATI_REG_CCE_RPTR_ADDR 0x070c +#define ATI_REG_CCE_RPTR 0x0710 +#define ATI_REG_CCE_WPTR 0x0714 +# define R128_PM4_BUFFER_DL_DONE (1 << 31) + +#define R128_REG_PM4_VC_FPU_SETUP 0x071c +# define R128_FRONT_DIR_CW (0 << 0) +# define R128_FRONT_DIR_CCW (1 << 0) +# define R128_FRONT_DIR_MASK (1 << 0) +# define R128_BACKFACE_CULL (0 << 1) +# define R128_BACKFACE_POINTS (1 << 1) +# define R128_BACKFACE_LINES (2 << 1) +# define R128_BACKFACE_SOLID (3 << 1) +# define R128_BACKFACE_MASK (3 << 1) +# define R128_FRONTFACE_CULL (0 << 3) +# define R128_FRONTFACE_POINTS (1 << 3) +# define R128_FRONTFACE_LINES (2 << 3) +# define R128_FRONTFACE_SOLID (3 << 3) +# define R128_FRONTFACE_MASK (3 << 3) +# define R128_FPU_COLOR_SOLID (0 << 5) +# define R128_FPU_COLOR_FLAT (1 << 5) +# define R128_FPU_COLOR_GOURAUD (2 << 5) +# define R128_FPU_COLOR_GOURAUD2 (3 << 5) +# define R128_FPU_COLOR_MASK (3 << 5) +# define R128_FPU_SUB_PIX_2BITS (0 << 7) +# define R128_FPU_SUB_PIX_4BITS (1 << 7) +# define R128_FPU_MODE_2D (0 << 8) +# define R128_FPU_MODE_3D (1 << 8) +# define R128_TRAP_BITS_DISABLE (1 << 9) +# define R128_EDGE_ANTIALIAS (1 << 10) +# define R128_SUPERSAMPLE (1 << 11) +# define R128_XFACTOR_2 (0 << 12) +# define R128_XFACTOR_4 (1 << 12) +# define R128_YFACTOR_2 (0 << 13) +# define R128_YFACTOR_4 (1 << 13) +# define R128_FLAT_SHADE_VERTEX_D3D (0 << 14) +# define R128_FLAT_SHADE_VERTEX_OGL (1 << 14) +# define R128_FPU_ROUND_TRUNCATE (0 << 15) +# define R128_FPU_ROUND_NEAREST (1 << 15) +# define R128_WM_SEL_8DW (0 << 16) +# define R128_WM_SEL_16DW (1 << 16) +# define R128_WM_SEL_32DW (2 << 16) + +#define R128_REG_PM4_IW_INDOFF 0x0738 +#define R128_REG_PM4_IW_INDSIZE 0x073c + #define RADEON_REG_CP_CSQ_CNTL 0x0740 -# define RADEON_CSQ_PRIBM_INDBM (4 << 28) +# define RADEON_CSQ_CNT_PRIMARY_MASK 0x000000ff +# define RADEON_CSQ_CNT_INDIRECT_MASK 0x0000ff00 +# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) +# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) +# define RADEON_CSQ_PRIBM_INDDIS (2 << 28) +# define RADEON_CSQ_PRIPIO_INDBM (3 << 28) +# define RADEON_CSQ_PRIBM_INDBM (4 << 28) +# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) -#define RADEON_REG_SRC_PITCH_OFFSET 0x1428 -#define RADEON_REG_DST_PITCH_OFFSET 0x142c -#define RADEON_REG_SRC_Y_X 0x1434 -#define RADEON_REG_DST_Y_X 0x1438 -#define RADEON_REG_DST_HEIGHT_WIDTH 0x143c +#define R128_REG_PM4_STAT 0x07b8 +# define R128_PM4_FIFOCNT_MASK 0x00000fff +# define R128_PM4_BUSY (1 << 16) +# define R128_PM4_GUI_ACTIVE (1 << 31) -#define RADEON_REG_DP_GUI_MASTER_CNTL 0x146c -# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) -# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) -# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) -# define RADEON_GMC_BRUSH_NONE (15 << 4) -# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) -# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) -# define RADEON_GMC_3D_FCN_EN (1 << 27) -# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) -# define RADEON_GMC_AUX_CLIP_DIS (1 << 29) +#define RADEON_REG_CP_STAT 0x07c0 +# define RADEON_CSQ_PRIMARY_BUSY (1 << 10) +# define RADEON_CSQ_INDIRECT_BUSY (1 << 11) -#define RADEON_REG_DP_BRUSH_FRGD_CLR 0x147c -#define RADEON_REG_DST_WIDTH_HEIGHT 0x1598 -#define RADEON_REG_CLR_CMP_CNTL 0x15c0 -#define RADEON_REG_AUX_SC_CNTL 0x1660 +#define RADEON_REG_ME_CNTL 0x07d0 +# define RADEON_ME_MODE_FREE_RUN (1 << 30) -#define RADEON_REG_DP_CNTL 0x16c0 -# define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) -# define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) +#define ATI_REG_MICROCODE_RAM_ADDR 0x07d4 +#define ATI_REG_MICROCODE_RAM_RADDR 0x07d8 +#define ATI_REG_MICROCODE_RAM_DATAH 0x07dc +#define ATI_REG_MICROCODE_RAM_DATAL 0x07e0 +#define R128_REG_PM4_BUFFER_ADDR 0x07f0 -#define RADEON_REG_DP_MIX 0x16c8 -#define RADEON_REG_DP_WRITE_MASK 0x16cc -#define RADEON_REG_DEFAULT_OFFSET 0x16e0 -#define RADEON_REG_DEFAULT_PITCH 0x16e4 +#define RADEON_REG_CP_CSQ_STAT 0x07f8 +# define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0) +# define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8) +# define RADEON_CSQ_RPTR_INDIRECT_MASK (0xff << 16) +# define RADEON_CSQ_WPTR_INDIRECT_MASK (0xff << 24) -#define RADEON_REG_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 -# define RADEON_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) -# define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) +#define R128_REG_PM4_MICRO_CNTL 0x07fc +# define R128_PM4_MICRO_FREERUN (1 << 30) -#define RADEON_REG_SC_TOP_LEFT 0x16ec -#define RADEON_REG_SC_BOTTOM_RIGHT 0x16f0 +#define R128_REG_BM_CHUNK_0_VAL 0x0a18 +# define R128_BM_PTR_FORCE_TO_PCI (1 << 21) +# define R128_BM_PM4_RD_FORCE_TO_PCI (1 << 22) +# define R128_BM_GLOBAL_FORCE_TO_PCI (1 << 23) -#define RADEON_REG_WAIT_UNTIL 0x1720 -# define RADEON_WAIT_CRTC_PFLIP (1 << 0) +#define R128_REG_AGP_COMMAND 0x0f58 +# define R128_AGP_ENABLE (1 << 8) + +#define RADEON_REG_AGP_COMMAND 0x0f60 +# define RADEON_AGP_ENABLE (1 << 8) + +#define R128_REG_PM4_FIFO_DATA_EVEN 0x1000 +#define R128_REG_PM4_FIFO_DATA_ODD 0x1004 + +#define RADEON_REG_CSQ_APER_PRIMARY 0x1000 +#define RADEON_REG_CSQ_APER_PRIMARY_END 0x11fc +#define RADEON_REG_CSQ_APER_INDIRECT 0x1300 +#define RADEON_REG_CSQ_APER_INDIRECT_END 0x13fc +#define ATI_REG_SRC_PITCH_OFFSET 0x1428 +#define ATI_REG_DST_PITCH_OFFSET 0x142c +#define ATI_REG_SRC_Y_X 0x1434 +#define ATI_REG_DST_Y_X 0x1438 +#define ATI_REG_DST_HEIGHT_WIDTH 0x143c + +#define ATI_REG_DP_GUI_MASTER_CNTL 0x146c +# define ATI_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) +# define ATI_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) +# define ATI_GMC_SRC_CLIPPING (1 << 2) +# define ATI_GMC_DST_CLIPPING (1 << 3) +# define ATI_GMC_BRUSH_SOLID_COLOR (13 << 4) +# define ATI_GMC_BRUSH_NONE (15 << 4) +# define ATI_GMC_BRUSH_MASK (15 << 4) +# define ATI_GMC_DST_DATATYPE_MASK (0xf << 8) +# define ATI_GMC_SRC_DATATYPE_COLOR (3 << 12) +# define R128_GMC_CONVERSION_TEMP (1 << 15) +# define R128_GMC_CONVERSION_TEMP_6500 (0 << 15) +# define R128_GMC_CONVERSION_TEMP_9300 (1 << 15) +# define ATI_GMC_ROP3_MASK (0xff << 16) +# define ATI_DP_SRC_SOURCE_MEMORY (2 << 24) +# define ATI_DP_SRC_SOURCE_HOST_DATA (3 << 24) +# define R128_GMC_3D_FCN_EN (1 << 27) +# define ATI_GMC_CLR_CMP_CNTL_DIS (1 << 28) +# define R128_GMC_AUX_CLIP_DIS (1 << 29) +# define ATI_GMC_WR_MSK_DIS (1 << 30) +# define R128_GMC_LD_BRUSH_Y_X (1 << 31) + +#define ATI_REG_DP_BRUSH_FRGD_CLR 0x147c +#define ATI_REG_DST_WIDTH_HEIGHT 0x1598 +#define ATI_REG_CLR_CMP_CNTL 0x15c0 +#define ATI_REG_AUX_SC_CNTL 0x1660 + +#define ATI_REG_DP_CNTL 0x16c0 +# define ATI_DST_X_LEFT_TO_RIGHT (1 << 0) +# define ATI_DST_Y_TOP_TO_BOTTOM (1 << 1) + +#define ATI_REG_DP_MIX 0x16c8 +#define ATI_REG_DP_WRITE_MASK 0x16cc +#define ATI_REG_DEFAULT_OFFSET 0x16e0 +#define ATI_REG_DEFAULT_PITCH 0x16e4 + +#define ATI_REG_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 +# define ATI_DEFAULT_SC_RIGHT_MAX 0x00001fff +# define ATI_DEFAULT_SC_BOTTOM_MAX 0x1fff0000 + +#define ATI_REG_SC_TOP_LEFT 0x16ec +#define ATI_REG_SC_BOTTOM_RIGHT 0x16f0 + +#define ATI_REG_WAIT_UNTIL 0x1720 +# define ATI_WAIT_CRTC_PFLIP (1 << 0) +# define ATI_WAIT_RE_CRTC_VLINE (1 << 1) +# define ATI_WAIT_FE_CRTC_VLINE (1 << 2) +# define ATI_WAIT_CRTC_VLINE (1 << 3) +# define ATI_WAIT_DMA_VIPH0_IDLE (1 << 4) +# define ATI_WAIT_DMA_VIPH1_IDLE (1 << 5) +# define ATI_WAIT_DMA_VIPH2_IDLE (1 << 6) +# define ATI_WAIT_DMA_VIPH3_IDLE (1 << 7) +# define ATI_WAIT_DMA_VID_IDLE (1 << 8) +# define ATI_WAIT_DMA_GUI_IDLE (1 << 9) +# define ATI_WAIT_CMDFIFO (1 << 10) +# define ATI_WAIT_OV0_FLIP (1 << 11) +# define RADEON_WAIT_OV0_SLICEDONE (1 << 12) +# define RADEON_WAIT_2D_IDLE (1 << 14) +# define RADEON_WAIT_3D_IDLE (1 << 15) # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) +# define ATI_WAIT_CMDFIFO_ENTRIES (0x07f00000) +# define RADEON_WAIT_BOTH_CRTC_PFLIP (1 << 30) +# define RADEON_ENG_DISPLAY_SELECT (1 << 31) -#define RADEON_RB3D_BLENDCNTL 0x1c20 +#define R128_REG_GUI_STAT 0x1740 +# define R128_GUI_ACTIVE (1 << 31) + +#define R128_REG_PC_GUI_MODE 0x1744 +#define R128_PC_GUI_PRIORITY (1 << 0) +#define R128_PC_RISE_DF_EN (1 << 1) +#define R128_PC_FALL_DF_EN (1 << 2) +#define R128_PC_BYPASS_EN (1 << 3) +#define R128_PC_CACHE_SIZE (1 << 4) +#define R128_PC_IGNORE_UNIFY (1 << 5) +#define R128_PC_IGNORE_WRHINT (1 << 6) +#define R128_PC_IGNORE_RDHINT (1 << 7) +#define R128_PC_RISE_DP_EN (1 << 8) + +#define R128_REG_PC_GUI_CTLSTAT 0x1748 +/* bits match R128_REG_PC_NGUI_CTLSTAT */ + +#define R128_REG_TEX_CNTL 0x1800 +#define R128_REG_SECONDARY_SCALE_OFFSET 0x1980 +#define R128_REG_SECONDARY_SCALE_PITCH 0x1980 +#define R128_REG_SECONDARY_SCALE_X_INC 0x1984 +#define R128_REG_SECONDARY_SCALE_Y_INC 0x1988 +#define R128_REG_SECONDARY_SCALE_HACC 0x198c +#define R128_REG_SECONDARY_SCALE_VACC 0x1990 +#define R128_REG_SCALE_SRC_HEIGHT_WIDTH 0x1994 +#define R128_REG_SCALE_OFFSET_0 0x1998 +#define R128_REG_SCALE_PITCH 0x199c +#define R128_REG_SCALE_X_INC 0x19a0 +#define R128_REG_SCALE_Y_INC 0x19a4 +#define R128_REG_SCALE_HACC 0x19a8 +#define R128_REG_SCALE_VACC 0x19ac +#define R128_REG_SCALE_DST_X_Y 0x19b0 +#define R128_REG_SCALE_DST_HEIGHT_WIDTH 0x19b4 + +#define R128_REG_SCALE_3D_CNTL 0x1a00 +# define R128_SCALE_DITHER_ERR_DIFF (0 << 1) +# define R128_SCALE_DITHER_TABLE (1 << 1) +# define R128_TEX_CACHE_SIZE_FULL (0 << 2) +# define R128_TEX_CACHE_SIZE_HALF (1 << 2) +# define R128_DITHER_INIT_CURR (0 << 3) +# define R128_DITHER_INIT_RESET (1 << 3) +# define R128_ROUND_24BIT (1 << 4) +# define R128_TEX_CACHE_DISABLE (1 << 5) +# define R128_SCALE_3D_NOOP (0 << 6) +# define R128_SCALE_3D_SCALE (1 << 6) +# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6) +# define R128_SCALE_PIX_BLEND (0 << 8) +# define R128_SCALE_PIX_REPLICATE (1 << 8) +# define R128_TEX_CACHE_SPLIT (1 << 9) +# define R128_APPLE_YUV_MODE (1 << 10) +# define R128_TEX_CACHE_PALLETE_MODE (1 << 11) +# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) +# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12) +# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12) +# define R128_FOG_TABLE (1 << 14) +# define R128_SIGNED_DST_CLAMP (1 << 15) +/* Alpha bits from R128_REG_MISC_3D_CNTL */ +# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28) +# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28) +# define R128_COMPOSITE_SHADOW (1 << 29) +# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30) +# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31) +# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31) + +#define R128_REG_SCALE_3D_DATATYPE 0x1a20 + +#define R128_REG_SETUP_CNTL 0x1bc4 +# define R128_DONT_START_TRIANGLE (1 << 0) +# define R128_Z_BIAS (0 << 1) +# define R128_DONT_START_ANY_ON (1 << 2) +# define R128_COLOR_SOLID_COLOR (0 << 3) +# define R128_COLOR_FLAT_VERT_1 (1 << 3) +# define R128_COLOR_FLAT_VERT_2 (2 << 3) +# define R128_COLOR_FLAT_VERT_3 (3 << 3) +# define R128_COLOR_GOURAUD (4 << 3) +# define R128_PRIM_TYPE_TRI (0 << 7) +# define R128_PRIM_TYPE_LINE (1 << 7) +# define R128_PRIM_TYPE_POINT (2 << 7) +# define R128_PRIM_TYPE_POLY_EDGE (3 << 7) +# define R128_TEXTURE_ST_MULT_W (0 << 9) +# define R128_TEXTURE_ST_DIRECT (1 << 9) +# define R128_STARTING_VERTEX_1 (1 << 14) +# define R128_STARTING_VERTEX_2 (2 << 14) +# define R128_STARTING_VERTEX_3 (3 << 14) +# define R128_ENDING_VERTEX_1 (1 << 16) +# define R128_ENDING_VERTEX_2 (2 << 16) +# define R128_ENDING_VERTEX_3 (3 << 16) +# define R128_SU_POLY_LINE_LAST (0 << 18) +# define R128_SU_POLY_LINE_NOT_LAST (1 << 18) +# define R128_SUB_PIX_2BITS (0 << 19) +# define R128_SUB_PIX_4BITS (1 << 19) +# define R128_SET_UP_CONTINUE (1 << 31) + +#define R128_REG_WINDOW_XY_OFFSET 0x1bcc + +#define RADEON_REG_RB3D_BLENDCNTL 0x1c20 # define RADEON_COMB_FCN_MASK (3 << 12) # define RADEON_COMB_FCN_ADD_CLAMP (0 << 12) # define RADEON_COMB_FCN_ADD_NOCLAMP (1 << 12) # define RADEON_COMB_FCN_SUB_CLAMP (2 << 12) # define RADEON_COMB_FCN_SUB_NOCLAMP (3 << 12) -# define RADEON_SRC_BLEND_GL_ZERO (32 << 16) -# define RADEON_SRC_BLEND_GL_ONE (33 << 16) -# define RADEON_SRC_BLEND_GL_SRC_COLOR (34 << 16) -# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) -# define RADEON_SRC_BLEND_GL_DST_COLOR (36 << 16) -# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) -# define RADEON_SRC_BLEND_GL_SRC_ALPHA (38 << 16) -# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) -# define RADEON_SRC_BLEND_GL_DST_ALPHA (40 << 16) -# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) -# define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) -# define RADEON_SRC_BLEND_MASK (63 << 16) -# define RADEON_DST_BLEND_GL_ZERO (32 << 24) -# define RADEON_DST_BLEND_GL_ONE (33 << 24) -# define RADEON_DST_BLEND_GL_SRC_COLOR (34 << 24) -# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) -# define RADEON_DST_BLEND_GL_DST_COLOR (36 << 24) -# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) -# define RADEON_DST_BLEND_GL_SRC_ALPHA (38 << 24) -# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) -# define RADEON_DST_BLEND_GL_DST_ALPHA (40 << 24) -# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) -# define RADEON_DST_BLEND_MASK (63 << 24) +# define R200_COMB_FCN_MIN (4 << 12) +# define R200_COMB_FCN_MAX (5 << 12) +# define R200_COMB_FCN_RSUB_CLAMP (6 << 12) +# define R200_COMB_FCN_RSUB_NOCLAMP (7 << 12) +# define RADEON_SBLEND_GL_ZERO (32 << 16) +# define RADEON_SBLEND_GL_ONE (33 << 16) +# define RADEON_SBLEND_GL_SRC_COLOR (34 << 16) +# define RADEON_SBLEND_GL_INV_SRC_COLOR (35 << 16) +# define RADEON_SBLEND_GL_DST_COLOR (36 << 16) +# define RADEON_SBLEND_GL_INV_DST_COLOR (37 << 16) +# define RADEON_SBLEND_GL_SRC_ALPHA (38 << 16) +# define RADEON_SBLEND_GL_INV_SRC_ALPHA (39 << 16) +# define RADEON_SBLEND_GL_DST_ALPHA (40 << 16) +# define RADEON_SBLEND_GL_INV_DST_ALPHA (41 << 16) +# define RADEON_SBLEND_GL_SRC_ALPHA_SATURATE (42 << 16) +# define R200_SBLEND_GL_CONST_COLOR (43 << 16) +# define R200_SBLEND_GL_ONE_MINUS_CONST_COLOR (44 << 16) +# define R200_SBLEND_GL_CONST_ALPHA (45 << 16) +# define R200_SBLEND_GL_ONE_MINUS_CONST_ALPHA (46 << 16) +# define RADEON_SBLEND_MASK (63 << 16) +# define RADEON_DBLEND_GL_ZERO (32 << 24) +# define RADEON_DBLEND_GL_ONE (33 << 24) +# define RADEON_DBLEND_GL_SRC_COLOR (34 << 24) +# define RADEON_DBLEND_GL_INV_SRC_COLOR (35 << 24) +# define RADEON_DBLEND_GL_DST_COLOR (36 << 24) +# define RADEON_DBLEND_GL_INV_DST_COLOR (37 << 24) +# define RADEON_DBLEND_GL_SRC_ALPHA (38 << 24) +# define RADEON_DBLEND_GL_INV_SRC_ALPHA (39 << 24) +# define RADEON_DBLEND_GL_DST_ALPHA (40 << 24) +# define RADEON_DBLEND_GL_INV_DST_ALPHA (41 << 24) +# define R200_DBLEND_GL_CONST_COLOR (43 << 24) +# define R200_DBLEND_GL_ONE_MINUS_CONST_COLOR (44 << 24) +# define R200_DBLEND_GL_CONST_ALPHA (45 << 24) +# define R200_DBLEND_GL_ONE_MINUS_CONST_ALPHA (46 << 24) +# define RADEON_DBLEND_MASK (63 << 24) #define RADEON_REG_PP_CNTL 0x1c38 # define RADEON_STIPPLE_ENABLE (1 << 0) @@ -132,11 +515,16 @@ # define RADEON_TEX_1_ENABLE (1 << 5) # define RADEON_TEX_2_ENABLE (1 << 6) # define RADEON_TEX_3_ENABLE (1 << 7) +# define R200_TEX_4_ENABLE (1 << 8) +# define R200_TEX_5_ENABLE (1 << 9) # define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12) # define RADEON_TEX_BLEND_0_ENABLE (1 << 12) # define RADEON_TEX_BLEND_1_ENABLE (1 << 13) # define RADEON_TEX_BLEND_2_ENABLE (1 << 14) # define RADEON_TEX_BLEND_3_ENABLE (1 << 15) +# define R200_TEX_BLEND_4_ENABLE (1 << 16) +# define R200_TEX_BLEND_5_ENABLE (1 << 17) +# define R200_TEX_BLEND_6_ENABLE (1 << 18) # define RADEON_PLANAR_YUV_ENABLE (1 << 20) # define RADEON_SPECULAR_ENABLE (1 << 21) # define RADEON_FOG_ENABLE (1 << 22) @@ -236,6 +624,8 @@ # define RADEON_ROUND_PREC_4TH_PIX (2 << 30) # define RADEON_ROUND_PREC_HALF_PIX (3 << 30) +#define R200_REG_RE_CNTL 0x1c50 + #define RADEON_REG_SE_COORD_FMT 0x1c50 # define RADEON_VTX_XY_PRE_MULT_1_OVER_W0 (1 << 0) # define RADEON_VTX_Z_PRE_MULT_1_OVER_W0 (1 << 1) @@ -318,6 +708,7 @@ # define RADEON_TXFORMAT_ARGB8888 (6 << 0) # define RADEON_TXFORMAT_RGBA8888 (7 << 0) # define RADEON_TXFORMAT_Y8 (8 << 0) +# define RADEON_TXFORMAT_AYUV444 (9 << 0) # define RADEON_TXFORMAT_VYUY422 (10 << 0) # define RADEON_TXFORMAT_YVYU422 (11 << 0) # define RADEON_TXFORMAT_DXT1 (12 << 0) @@ -337,9 +728,9 @@ # define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20) # define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20 # define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) -# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) # define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) # define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) # define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) # define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) # define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) @@ -486,15 +877,240 @@ # define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8) # define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8) # define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 9) +/* COMP_ARG, BLEND_CNTL, CLAMP_TX same as for CBLEND, T*_EQ_TCUR */ # define RADEON_ALPHA_ARG_MASK 0xf #define RADEON_REG_PP_TFACTOR_0 0x1c68 #define RADEON_REG_PP_TFACTOR_1 0x1c80 #define RADEON_REG_PP_TFACTOR_2 0x1c98 +#define R128_REG_TEX_CNTL_C 0x1c9c +# define R128_Z_ENABLE (1 << 0) +# define R128_Z_WRITE_ENABLE (1 << 1) +# define R128_STENCIL_ENABLE (1 << 3) +# define R128_SHADE_ENABLE (0 << 4) +# define R128_TEXMAP_ENABLE (1 << 4) +# define R128_SEC_TEXMAP_ENABLE (1 << 5) +# define R128_FOG_ENABLE (1 << 7) +# define R128_DITHER_ENABLE (1 << 8) +# define R128_ALPHA_ENABLE (1 << 9) +# define R128_ALPHA_TEST_ENABLE (1 << 10) +# define R128_SPEC_LIGHT_ENABLE (1 << 11) +# define R128_TEX_CHROMA_KEY_ENABLE (1 << 12) +# define R128_ALPHA_IN_TEX_COMPLETE_A (0 << 13) +# define R128_ALPHA_IN_TEX_LSB_A (1 << 13) +# define R128_LIGHT_DIS (0 << 14) +# define R128_LIGHT_COPY (1 << 14) +# define R128_LIGHT_MODULATE (2 << 14) +# define R128_LIGHT_ADD (3 << 14) +# define R128_LIGHT_BLEND_CONSTANT (4 << 14) +# define R128_LIGHT_BLEND_TEXTURE (5 << 14) +# define R128_LIGHT_BLEND_VERTEX (6 << 14) +# define R128_LIGHT_BLEND_CONST_COLOR (7 << 14) +# define R128_ALPHA_LIGHT_DIS (0 << 18) +# define R128_ALPHA_LIGHT_COPY (1 << 18) +# define R128_ALPHA_LIGHT_MODULATE (2 << 18) +# define R128_ALPHA_LIGHT_ADD (3 << 18) +# define R128_ANTI_ALIAS (1 << 21) +# define R128_TEX_CACHE_FLUSH (1 << 23) +# define R128_LOD_BIAS_SHIFT 24 +# define R128_LOD_BIAS_MASK (0xff << 24) + +#define R128_REG_MISC_3D_STATE_CNTL 0x1ca0 +# define R128_REF_ALPHA_MASK 0xff +# define R128_MISC_SCALE_3D_NOOP (0 << 8) +# define R128_MISC_SCALE_3D_SCALE (1 << 8) +# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8) +# define R128_MISC_SCALE_PIX_BLEND (0 << 10) +# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10) +# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) +# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12) +# define R128_FOG_VERTEX (0 << 14) +# define R128_FOG_TABLE (1 << 14) +# define R128_SBLEND_ZERO (0 << 16) +# define R128_SBLEND_ONE (1 << 16) +# define R128_SBLEND_SRCCOLOR (2 << 16) +# define R128_SBLEND_INVSRCCOLOR (3 << 16) +# define R128_SBLEND_SRC_ALPHA (4 << 16) +# define R128_SBLEND_INV_SRC_ALPHA (5 << 16) +# define R128_SBLEND_DST_ALPHA (6 << 16) +# define R128_SBLEND_INV_DST_ALPHA (7 << 16) +# define R128_SBLEND_DSTCOLOR (8 << 16) +# define R128_SBLEND_INVDSTCOLOR (9 << 16) +# define R128_SBLEND_SRC_ALPHASAT (10 << 16) +# define R128_SBLEND_BOTHSRC_ALPHA (11 << 16) +# define R128_SBLEND_BOTHINV_SRC_ALPHA (12 << 16) +# define R128_SBLEND_MASK (15 << 16) +# define R128_DBLEND_ZERO (0 << 20) +# define R128_DBLEND_ONE (1 << 20) +# define R128_DBLEND_SRCCOLOR (2 << 20) +# define R128_DBLEND_INVSRCCOLOR (3 << 20) +# define R128_DBLEND_SRC_ALPHA (4 << 20) +# define R128_DBLEND_INV_SRC_ALPHA (5 << 20) +# define R128_DBLEND_DST_ALPHA (6 << 20) +# define R128_DBLEND_INV_DST_ALPHA (7 << 20) +# define R128_DBLEND_DSTCOLOR (8 << 20) +# define R128_DBLEND_INVDSTCOLOR (9 << 20) +# define R128_DBLEND_SRC_ALPHASAT (10 << 20) +# define R128_DBLEND_MASK (15 << 20) +# define R128_ALPHA_TEST_NEVER (0 << 24) +# define R128_ALPHA_TEST_LESS (1 << 24) +# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) +# define R128_ALPHA_TEST_EQUAL (3 << 24) +# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) +# define R128_ALPHA_TEST_GREATER (5 << 24) +# define R128_ALPHA_TEST_NEQUAL (6 << 24) +# define R128_ALPHA_TEST_ALWAYS (7 << 24) +# define R128_ALPHA_TEST_MASK (7 << 24) + +#define R128_REG_PRIM_TEX_CNTL_C 0x1cb0 +#define R128_REG_SEC_TEX_CNTL_C 0x1d00 +# define R128_SEC_SELECT_PRIM_ST (0 << 0) +# define R128_SEC_SELECT_SEC_ST (1 << 0) +# define R128_MIN_BLEND_NEAREST (0 << 1) +# define R128_MIN_BLEND_LINEAR (1 << 1) +# define R128_MIN_BLEND_MIPNEAREST (2 << 1) +# define R128_MIN_BLEND_MIPLINEAR (3 << 1) +# define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1) +# define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1) +# define R128_MIN_BLEND_MASK (7 << 1) +# define R128_MAG_BLEND_NEAREST (0 << 4) +# define R128_MAG_BLEND_LINEAR (1 << 4) +# define R128_MAG_BLEND_MASK (7 << 4) +# define R128_MIP_MAP_DISABLE (1 << 7) +# define R128_TEX_CLAMP_S_WRAP (0 << 8) +# define R128_TEX_CLAMP_S_MIRROR (1 << 8) +# define R128_TEX_CLAMP_S_CLAMP (2 << 8) +# define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8) +# define R128_TEX_CLAMP_S_MASK (3 << 8) +# define R128_TEX_WRAP_S (1 << 10) +# define R128_TEX_CLAMP_T_WRAP (0 << 11) +# define R128_TEX_CLAMP_T_MIRROR (1 << 11) +# define R128_TEX_CLAMP_T_CLAMP (2 << 11) +# define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11) +# define R128_TEX_CLAMP_T_MASK (3 << 11) +# define R128_TEX_WRAP_T (1 << 13) +# define R128_TEX_PERSPECTIVE_DISABLE (1 << 14) +# define R128_TEX_DATATYPE_SHIFT 16 +# define R128_PALLETE_EITHER (0 << 20) +# define R128_PALLETE_1 (1 << 20) +# define R128_PALLETE_2 (2 << 20) +# define R128_PSEUDOCOLOR_DT_RGB565 (0 << 24) +# define R128_PSEUDOCOLOR_DT_ARGB1555 (1 << 24) +# define R128_PSEUDOCOLOR_DT_ARGB4444 (2 << 24) + +#define R128_REG_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4 +#define R128_REG_SEC_TEXTURE_COMBINE_CNTL_C 0x1d04 +# define R128_COMB_DIS (0 << 0) +# define R128_COMB_COPY (1 << 0) +# define R128_COMB_COPY_INP (2 << 0) +# define R128_COMB_MODULATE (3 << 0) +# define R128_COMB_MODULATE2X (4 << 0) +# define R128_COMB_MODULATE4X (5 << 0) +# define R128_COMB_ADD (6 << 0) +# define R128_COMB_ADD_SIGNED (7 << 0) +# define R128_COMB_BLEND_VERTEX (8 << 0) +# define R128_COMB_BLEND_TEXTURE (9 << 0) +# define R128_COMB_BLEND_CONST (10 << 0) +# define R128_COMB_BLEND_PREMULT (11 << 0) +# define R128_COMB_BLEND_PREV (12 << 0) +# define R128_COMB_BLEND_PREMULT_INV (13 << 0) +# define R128_COMB_ADD_SIGNED2X (14 << 0) +# define R128_COMB_BLEND_CONST_COLOR (15 << 0) +# define R128_COMB_MASK (15 << 0) +# define R128_COLOR_FACTOR_CONST_COLOR (0 << 4) +# define R128_COLOR_FACTOR_NCONST_COLOR (1 << 4) +# define R128_COLOR_FACTOR_TEX (4 << 4) +# define R128_COLOR_FACTOR_NTEX (5 << 4) +# define R128_COLOR_FACTOR_ALPHA (6 << 4) +# define R128_COLOR_FACTOR_NALPHA (7 << 4) +# define R128_COLOR_FACTOR_PREV_COLOR (8 << 4) +# define R128_COLOR_FACTOR_MASK (15 << 4) +# define R128_COMB_FCN_MSB (1 << 8) +# define R128_INPUT_FACTOR_CONST_COLOR (2 << 10) +# define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10) +# define R128_INPUT_FACTOR_INT_COLOR (4 << 10) +# define R128_INPUT_FACTOR_INT_ALPHA (5 << 10) +# define R128_INPUT_FACTOR_PREV_COLOR (8 << 10) /* SEC only */ +# define R128_INPUT_FACTOR_PREV_ALPHA (9 << 10) /* SEC only */ +# define R128_INPUT_FACTOR_MASK (15 << 10) +# define R128_COMB_ALPHA_DIS (0 << 14) +# define R128_COMB_ALPHA_COPY (1 << 14) +# define R128_COMB_ALPHA_COPY_INP (2 << 14) +# define R128_COMB_ALPHA_MODULATE (3 << 14) +# define R128_COMB_ALPHA_MODULATE2X (4 << 14) +# define R128_COMB_ALPHA_MODULATE4X (5 << 14) +# define R128_COMB_ALPHA_ADD (6 << 14) +# define R128_COMB_ALPHA_ADD_SIGNED (7 << 14) +# define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14) +# define R128_COMB_ALPHA_MASK (15 << 14) +# define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18) +# define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18) +# define R128_ALPHA_FACTOR_MASK (15 << 18) +# define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25) +# define R128_INP_FACTOR_A_INT_ALPHA (2 << 25) +# define R128_INP_FACTOR_A_PREV_ALPHA (4 << 25) /* SEC only */ +# define R128_INP_FACTOR_A_MASK (7 << 25) + +#define R128_REG_TEX_SIZE_PITCH_C 0x1cb8 +# define R128_TEX_PITCH_SHIFT 0 +# define R128_TEX_SIZE_SHIFT 4 +# define R128_TEX_HEIGHT_SHIFT 8 +# define R128_TEX_MIN_SIZE_SHIFT 12 +# define R128_SEC_TEX_PITCH_SHIFT 16 +# define R128_SEC_TEX_SIZE_SHIFT 20 +# define R128_SEC_TEX_HEIGHT_SHIFT 24 +# define R128_SEC_TEX_MIN_SIZE_SHIFT 28 +# define R128_TEX_PITCH_MASK (0x0f << 0) +# define R128_TEX_SIZE_MASK (0x0f << 4) +# define R128_TEX_HEIGHT_MASK (0x0f << 8) +# define R128_TEX_MIN_SIZE_MASK (0x0f << 12) +# define R128_SEC_TEX_PITCH_MASK (0x0f << 16) +# define R128_SEC_TEX_SIZE_MASK (0x0f << 20) +# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24) +# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28) +# define R128_TEX_SIZE_PITCH_SHIFT 0 +# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16 +# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0) +# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16) + +#define R128_REG_PRIM_TEX_0_OFFSET_C 0x1cbc +#define R128_REG_PRIM_TEX_1_OFFSET_C 0x1cc0 +#define R128_REG_PRIM_TEX_2_OFFSET_C 0x1cc4 +#define R128_REG_PRIM_TEX_3_OFFSET_C 0x1cc8 +#define R128_REG_PRIM_TEX_4_OFFSET_C 0x1ccc +#define R128_REG_PRIM_TEX_5_OFFSET_C 0x1cd0 +#define R128_REG_PRIM_TEX_6_OFFSET_C 0x1cd4 +#define R128_REG_PRIM_TEX_7_OFFSET_C 0x1cd8 +#define R128_REG_PRIM_TEX_8_OFFSET_C 0x1cdc +#define R128_REG_PRIM_TEX_9_OFFSET_C 0x1ce0 +#define R128_REG_PRIM_TEX_10_OFFSET_C 0x1ce4 +#define R128_REG_SEC_TEX_0_OFFSET_C 0x1d08 +#define R128_REG_SEC_TEX_1_OFFSET_C 0x1d0c +#define R128_REG_SEC_TEX_2_OFFSET_C 0x1d10 +#define R128_REG_SEC_TEX_3_OFFSET_C 0x1d14 +#define R128_REG_SEC_TEX_4_OFFSET_C 0x1d18 +#define R128_REG_SEC_TEX_5_OFFSET_C 0x1d1c +#define R128_REG_SEC_TEX_6_OFFSET_C 0x1d20 +#define R128_REG_SEC_TEX_7_OFFSET_C 0x1d24 +#define R128_REG_SEC_TEX_8_OFFSET_C 0x1d28 +#define R128_REG_SEC_TEX_9_OFFSET_C 0x1d2c +#define R128_REG_SEC_TEX_10_OFFSET_C 0x1d30 +# define R128_TEX_NO_TILE (0 << 30) +# define R128_TEX_TILED_BY_HOST (1 << 30) +# define R128_TEX_TILED_BY_STORAGE (2 << 30) +# define R128_TEX_TILED_BY_STORAGE2 (3 << 30) +#define R128_REG_CONSTANT_COLOR_C 0x1d34 +# define R128_CONSTANT_BLUE_SHIFT 0 +# define R128_CONSTANT_GREEN_SHIFT 8 +# define R128_CONSTANT_RED_SHIFT 16 +# define R128_CONSTANT_ALPHA_SHIFT 24 + #define RADEON_REG_PP_TEX_SIZE_0 0x1d04 /* NPOT */ -#define RADEON_REG_PP_TEX_SIZE_1 0x1d0c -#define RADEON_REG_PP_TEX_SIZE_2 0x1d14 +#define RADEON_REG_PP_TEX_SIZE_1 0x1d0c /* NPOT */ +#define RADEON_REG_PP_TEX_SIZE_2 0x1d14 /* NPOT */ # define RADEON_TEX_USIZE_MASK (0x7ff << 0) # define RADEON_TEX_USIZE_SHIFT 0 # define RADEON_TEX_VSIZE_MASK (0x7ff << 16) @@ -509,8 +1125,68 @@ #define RADEON_REG_PP_TEX_PITCH_2 0x1d18 /* NPOT */ /* note: bits 13-5: 32 byte aligned stride of texture map */ +#define R128_REG_PLANE_3D_MASK_C 0x1d44 + #define RADEON_REG_RB3D_PLANEMASK 0x1d84 +#define R200_REG_SE_VAP_CNTL 0x2080 +# define R200_VAP_TCL_ENABLE 0x00000001 +# define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 +# define R200_VAP_FORCE_W_TO_ONE 0x00010000 +# define R200_VAP_D3D_TEX_DEFAULT 0x00020000 +# define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 +# define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 + +#define R200_REG_SE_VTX_FMT_0 0x2088 +# define R200_VTX_XY 0 /* always have xy */ +# define R200_VTX_Z0 (1 << 0) +# define R200_VTX_W0 (1 << 1) +# define R200_VTX_WEIGHT_COUNT_SHIFT (2) +# define R200_VTX_PV_MATRIX_SEL (1 << 5) +# define R200_VTX_N0 (1 << 6) +# define R200_VTX_POINT_SIZE (1 << 7) +# define R200_VTX_DISCRETE_FOG (1 << 8) +# define R200_VTX_SHININESS_0 (1 << 9) +# define R200_VTX_SHININESS_1 (1 << 10) +# define R200_VTX_COLOR_NOT_PRESENT 0 +# define R200_VTX_PK_RGBA 1 +# define R200_VTX_FP_RGB 2 +# define R200_VTX_FP_RGBA 3 +# define R200_VTX_COLOR_MASK 3 +# define R200_VTX_COLOR_0_SHIFT 11 +# define R200_VTX_COLOR_1_SHIFT 13 +# define R200_VTX_COLOR_2_SHIFT 15 +# define R200_VTX_COLOR_3_SHIFT 17 +# define R200_VTX_COLOR_4_SHIFT 19 +# define R200_VTX_COLOR_5_SHIFT 21 +# define R200_VTX_COLOR_6_SHIFT 23 +# define R200_VTX_COLOR_7_SHIFT 25 +# define R200_VTX_XY1 (1 << 28) +# define R200_VTX_Z1 (1 << 29) +# define R200_VTX_W1 (1 << 30) +# define R200_VTX_N1 (1 << 31) + +#define R200_REG_SE_VTX_FMT_1 0x208c +# define R200_VTX_TEX0_COMP_CNT_SHIFT 0 +# define R200_VTX_TEX1_COMP_CNT_SHIFT 3 +# define R200_VTX_TEX2_COMP_CNT_SHIFT 6 +# define R200_VTX_TEX3_COMP_CNT_SHIFT 9 +# define R200_VTX_TEX4_COMP_CNT_SHIFT 12 +# define R200_VTX_TEX5_COMP_CNT_SHIFT 15 + +#define R200_REG_SE_VTE_CNTL 0x20b0 +# define R200_VPORT_X_SCALE_ENA 0x00000001 +# define R200_VPORT_X_OFFSET_ENA 0x00000002 +# define R200_VPORT_Y_SCALE_ENA 0x00000004 +# define R200_VPORT_Y_OFFSET_ENA 0x00000008 +# define R200_VPORT_Z_SCALE_ENA 0x00000010 +# define R200_VPORT_Z_OFFSET_ENA 0x00000020 +# define R200_VTX_XY_FMT 0x00000100 +# define R200_VTX_Z_FMT 0x00000200 +# define R200_VTX_W0_FMT 0x00000400 +# define R200_VTX_W0_NORMALIZE 0x00000800 +# define R200_VTX_ST_DENORMALIZED 0x00001000 + #define RADEON_REG_SE_CNTL_STATUS 0x2140 # define RADEON_VC_NO_SWAP (0 << 0) # define RADEON_VC_16BIT_SWAP (1 << 0) @@ -520,36 +1196,530 @@ #define RADEON_REG_RE_TOP_LEFT 0x26c0 +#define R200_REG_RE_AUX_SCISSOR_CNTL 0x26f0 + +#define R200_REG_PP_TXFILTER_0 0x2c00 +#define R200_REG_PP_TXFILTER_1 0x2c20 +#define R200_REG_PP_TXFILTER_2 0x2c40 +#define R200_REG_PP_TXFILTER_3 0x2c60 +#define R200_REG_PP_TXFILTER_4 0x2c80 +#define R200_REG_PP_TXFILTER_5 0x2ca0 +# define R200_MAG_FILTER_NEAREST (0 << 0) +# define R200_MAG_FILTER_LINEAR (1 << 0) +# define R200_MAG_FILTER_MASK (1 << 0) +# define R200_MIN_FILTER_NEAREST (0 << 1) +# define R200_MIN_FILTER_LINEAR (1 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) +# define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) +# define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) +# define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) +# define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) +# define R200_MIN_FILTER_MASK (15 << 1) +# define R200_MAX_ANISO_1_TO_1 (0 << 5) +# define R200_MAX_ANISO_2_TO_1 (1 << 5) +# define R200_MAX_ANISO_4_TO_1 (2 << 5) +# define R200_MAX_ANISO_8_TO_1 (3 << 5) +# define R200_MAX_ANISO_16_TO_1 (4 << 5) +# define R200_MAX_ANISO_MASK (7 << 5) +# define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) +# define R200_MAX_MIP_LEVEL_SHIFT 16 +# define R200_YUV_TO_RGB (1 << 20) +# define R200_YUV_TEMPERATURE_COOL (0 << 21) +# define R200_YUV_TEMPERATURE_HOT (1 << 21) +# define R200_YUV_TEMPERATURE_MASK (1 << 21) +# define R200_WRAPEN_S (1 << 22) +# define R200_CLAMP_S_WRAP (0 << 23) +# define R200_CLAMP_S_MIRROR (1 << 23) +# define R200_CLAMP_S_CLAMP_LAST (2 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) +# define R200_CLAMP_S_CLAMP_BORDER (4 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) +# define R200_CLAMP_S_CLAMP_GL (6 << 23) +# define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) +# define R200_CLAMP_S_MASK (7 << 23) +# define R200_WRAPEN_T (1 << 26) +# define R200_CLAMP_T_WRAP (0 << 27) +# define R200_CLAMP_T_MIRROR (1 << 27) +# define R200_CLAMP_T_CLAMP_LAST (2 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) +# define R200_CLAMP_T_CLAMP_BORDER (4 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) +# define R200_CLAMP_T_CLAMP_GL (6 << 27) +# define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) +# define R200_CLAMP_T_MASK (7 << 27) +# define R200_KILL_LT_ZERO (1 << 30) +# define R200_BORDER_MODE_OGL (0 << 31) +# define R200_BORDER_MODE_D3D (1 << 31) + +#define R200_REG_PP_TXFORMAT_0 0x2c04 +# define R200_TXFORMAT_I8 (0 << 0) +# define R200_TXFORMAT_AI88 (1 << 0) +# define R200_TXFORMAT_RGB332 (2 << 0) +# define R200_TXFORMAT_ARGB1555 (3 << 0) +# define R200_TXFORMAT_RGB565 (4 << 0) +# define R200_TXFORMAT_ARGB4444 (5 << 0) +# define R200_TXFORMAT_ARGB8888 (6 << 0) +# define R200_TXFORMAT_RGBA8888 (7 << 0) +# define R200_TXFORMAT_Y8 (8 << 0) +# define R200_TXFORMAT_AVYU4444 (9 << 0) +# define R200_TXFORMAT_VYUY422 (10 << 0) +# define R200_TXFORMAT_YVYU422 (11 << 0) +# define R200_TXFORMAT_DXT1 (12 << 0) +# define R200_TXFORMAT_DXT23 (14 << 0) +# define R200_TXFORMAT_DXT45 (15 << 0) +# define R200_TXFORMAT_FORMAT_MASK (31 << 0) +# define R200_TXFORMAT_FORMAT_SHIFT 0 +# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define R200_TXFORMAT_NON_POWER2 (1 << 7) +# define R200_TXFORMAT_WIDTH_MASK (15 << 8) +# define R200_TXFORMAT_WIDTH_SHIFT 8 +# define R200_TXFORMAT_HEIGHT_MASK (15 << 12) +# define R200_TXFORMAT_HEIGHT_SHIFT 12 +# define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ +# define R200_TXFORMAT_F5_WIDTH_SHIFT 16 +# define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) +# define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 +# define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) +# define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) +# define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) +# define R200_TXFORMAT_ST_ROUTE_SHIFT 24 +# define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) + +#define R200_REG_PP_TXFORMAT_X_0 0x2c08 +# define R200_DEPTH_LOG2_MASK (0xf << 0) +# define R200_DEPTH_LOG2_SHIFT 0 +# define R200_VOLUME_FILTER_SHIFT 4 +# define R200_VOLUME_FILTER_MASK (1 << 4) +# define R200_VOLUME_FILTER_NEAREST (0 << 4) +# define R200_VOLUME_FILTER_LINEAR (1 << 4) +# define R200_WRAPEN_Q (1 << 8) +# define R200_CLAMP_Q_WRAP (0 << 9) +# define R200_CLAMP_Q_MIRROR (1 << 9) +# define R200_CLAMP_Q_CLAMP_LAST (2 << 9) +# define R200_CLAMP_Q_MIRROR_CLAMP_LAST (3 << 9) +# define R200_CLAMP_Q_CLAMP_BORDER (4 << 9) +# define R200_CLAMP_Q_MIRROR_CLAMP_BORDER (5 << 9) +# define R200_CLAMP_Q_CLAMP_GL (6 << 9) +# define R200_CLAMP_Q_MIRROR_CLAMP_GL (7 << 9) +# define R200_CLAMP_Q_MASK (7 << 9) +# define R200_MIN_MIP_LEVEL_MASK (0xff << 12) +# define R200_MIN_MIP_LEVEL_SHIFT 12 +# define R200_TEXCOORD_NONPROJ (0 << 16) +# define R200_TEXCOORD_CUBIC_ENV (1 << 16) +# define R200_TEXCOORD_VOLUME (2 << 16) +# define R200_TEXCOORD_PROJ (3 << 16) +# define R200_TEXCOORD_DEPTH (4 << 16) +# define R200_TEXCOORD_1D_PROJ (5 << 16) +# define R200_TEXCOORD_1D (6 << 16) +# define R200_TEXCOORD_ZERO (7 << 16) +# define R200_TEXCOORD_MASK (7 << 16) +# define R200_LOD_BIAS_MASK (0xfff80000) +# define R200_LOD_BIAS_SHIFT 19 + +#define R200_REG_PP_TXSIZE_0 0x2c0c /* NPOT only */ +#define R200_REG_PP_TXPITCH_0 0x2c10 /* NPOT only */ +#define R200_REG_PP_BORDER_COLOR_0 0x2c14 + +#define R200_PP_TXOFFSET_0 0x2d00 +#define R200_PP_TXOFFSET_1 0x2d18 +#define R200_PP_TXOFFSET_2 0x2d30 +#define R200_PP_TXOFFSET_3 0x2d48 +#define R200_PP_TXOFFSET_4 0x2d60 +#define R200_PP_TXOFFSET_5 0x2d78 +# define R200_TXO_ENDIAN_NO_SWAP (0 << 0) +# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) +# define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) +# define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R200_TXO_OFFSET_MASK 0xffffffe0 +# define R200_TXO_OFFSET_SHIFT 5 + +#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 +#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 +#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c +#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 +#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 +#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c +#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 +#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 +#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 +#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c +#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 +#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 +#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c +#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 +#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 +#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c +#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 +#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 +#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 +#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c +#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 +#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 +#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c +#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 +#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 +#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c +#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 +#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 +#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 +#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c + +#define R200_REG_PP_TXCBLEND_0 0x2f00 +# define R200_TXC_ARG_A_ZERO (0) +# define R200_TXC_ARG_A_CURRENT_COLOR (2) +# define R200_TXC_ARG_A_CURRENT_ALPHA (3) +# define R200_TXC_ARG_A_DIFFUSE_COLOR (4) +# define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) +# define R200_TXC_ARG_A_SPECULAR_COLOR (6) +# define R200_TXC_ARG_A_SPECULAR_ALPHA (7) +# define R200_TXC_ARG_A_TFACTOR_COLOR (8) +# define R200_TXC_ARG_A_TFACTOR_ALPHA (9) +# define R200_TXC_ARG_A_R0_COLOR (10) +# define R200_TXC_ARG_A_R0_ALPHA (11) +# define R200_TXC_ARG_A_R1_COLOR (12) +# define R200_TXC_ARG_A_R1_ALPHA (13) +# define R200_TXC_ARG_A_R2_COLOR (14) +# define R200_TXC_ARG_A_R2_ALPHA (15) +# define R200_TXC_ARG_A_R3_COLOR (16) +# define R200_TXC_ARG_A_R3_ALPHA (17) +# define R200_TXC_ARG_A_R4_COLOR (18) +# define R200_TXC_ARG_A_R4_ALPHA (19) +# define R200_TXC_ARG_A_R5_COLOR (20) +# define R200_TXC_ARG_A_R5_ALPHA (21) +# define R200_TXC_ARG_A_TFACTOR1_COLOR (26) +# define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) +# define R200_TXC_ARG_A_MASK (31 << 0) +# define R200_TXC_ARG_A_SHIFT 0 +# define R200_TXC_ARG_B_ZERO (0 << 5) +# define R200_TXC_ARG_B_CURRENT_COLOR (2 << 5) +# define R200_TXC_ARG_B_CURRENT_ALPHA (3 << 5) +# define R200_TXC_ARG_B_DIFFUSE_COLOR (4 << 5) +# define R200_TXC_ARG_B_DIFFUSE_ALPHA (5 << 5) +# define R200_TXC_ARG_B_SPECULAR_COLOR (6 << 5) +# define R200_TXC_ARG_B_SPECULAR_ALPHA (7 << 5) +# define R200_TXC_ARG_B_TFACTOR_COLOR (8 << 5) +# define R200_TXC_ARG_B_TFACTOR_ALPHA (9 << 5) +# define R200_TXC_ARG_B_R0_COLOR (10 << 5) +# define R200_TXC_ARG_B_R0_ALPHA (11 << 5) +# define R200_TXC_ARG_B_R1_COLOR (12 << 5) +# define R200_TXC_ARG_B_R1_ALPHA (13 << 5) +# define R200_TXC_ARG_B_R2_COLOR (14 << 5) +# define R200_TXC_ARG_B_R2_ALPHA (15 << 5) +# define R200_TXC_ARG_B_R3_COLOR (16 << 5) +# define R200_TXC_ARG_B_R3_ALPHA (17 << 5) +# define R200_TXC_ARG_B_R4_COLOR (18 << 5) +# define R200_TXC_ARG_B_R4_ALPHA (19 << 5) +# define R200_TXC_ARG_B_R5_COLOR (20 << 5) +# define R200_TXC_ARG_B_R5_ALPHA (21 << 5) +# define R200_TXC_ARG_B_TFACTOR1_COLOR (26 << 5) +# define R200_TXC_ARG_B_TFACTOR1_ALPHA (27 << 5) +# define R200_TXC_ARG_B_MASK (31 << 5) +# define R200_TXC_ARG_B_SHIFT 5 +# define R200_TXC_ARG_C_ZERO (0 << 10) +# define R200_TXC_ARG_C_CURRENT_COLOR (2 << 10) +# define R200_TXC_ARG_C_CURRENT_ALPHA (3 << 10) +# define R200_TXC_ARG_C_DIFFUSE_COLOR (4 << 10) +# define R200_TXC_ARG_C_DIFFUSE_ALPHA (5 << 10) +# define R200_TXC_ARG_C_SPECULAR_COLOR (6 << 10) +# define R200_TXC_ARG_C_SPECULAR_ALPHA (7 << 10) +# define R200_TXC_ARG_C_TFACTOR_COLOR (8 << 10) +# define R200_TXC_ARG_C_TFACTOR_ALPHA (9 << 10) +# define R200_TXC_ARG_C_R0_COLOR (10 << 10) +# define R200_TXC_ARG_C_R0_ALPHA (11 << 10) +# define R200_TXC_ARG_C_R1_COLOR (12 << 10) +# define R200_TXC_ARG_C_R1_ALPHA (13 << 10) +# define R200_TXC_ARG_C_R2_COLOR (14 << 10) +# define R200_TXC_ARG_C_R2_ALPHA (15 << 10) +# define R200_TXC_ARG_C_R3_COLOR (16 << 10) +# define R200_TXC_ARG_C_R3_ALPHA (17 << 10) +# define R200_TXC_ARG_C_R4_COLOR (18 << 10) +# define R200_TXC_ARG_C_R4_ALPHA (19 << 10) +# define R200_TXC_ARG_C_R5_COLOR (20 << 10) +# define R200_TXC_ARG_C_R5_ALPHA (21 << 10) +# define R200_TXC_ARG_C_TFACTOR1_COLOR (26 << 10) +# define R200_TXC_ARG_C_TFACTOR1_ALPHA (27 << 10) +# define R200_TXC_ARG_C_MASK (31 << 10) +# define R200_TXC_ARG_C_SHIFT 10 +# define R200_TXC_COMP_ARG_A (1 << 16) +# define R200_TXC_COMP_ARG_A_SHIFT (16) +# define R200_TXC_BIAS_ARG_A (1 << 17) +# define R200_TXC_SCALE_ARG_A (1 << 18) +# define R200_TXC_NEG_ARG_A (1 << 19) +# define R200_TXC_COMP_ARG_B (1 << 20) +# define R200_TXC_COMP_ARG_B_SHIFT (20) +# define R200_TXC_BIAS_ARG_B (1 << 21) +# define R200_TXC_SCALE_ARG_B (1 << 22) +# define R200_TXC_NEG_ARG_B (1 << 23) +# define R200_TXC_COMP_ARG_C (1 << 24) +# define R200_TXC_COMP_ARG_C_SHIFT (24) +# define R200_TXC_BIAS_ARG_C (1 << 25) +# define R200_TXC_SCALE_ARG_C (1 << 26) +# define R200_TXC_NEG_ARG_C (1 << 27) +# define R200_TXC_OP_MADD (0 << 28) +# define R200_TXC_OP_CND0 (2 << 28) +# define R200_TXC_OP_LERP (3 << 28) +# define R200_TXC_OP_DOT3 (4 << 28) +# define R200_TXC_OP_DOT4 (5 << 28) +# define R200_TXC_OP_CONDITIONAL (6 << 28) +# define R200_TXC_OP_DOT2_ADD (7 << 28) +# define R200_TXC_OP_MASK (7 << 28) + +#define R200_REG_PP_TXCBLEND2_0 0x2f04 +# define R200_TXC_TFACTOR_SEL_SHIFT 0 +# define R200_TXC_TFACTOR_SEL_MASK 0x7 +# define R200_TXC_TFACTOR1_SEL_SHIFT 4 +# define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXC_SCALE_SHIFT 8 +# define R200_TXC_SCALE_MASK (7 << 8) +# define R200_TXC_SCALE_1X (0 << 8) +# define R200_TXC_SCALE_2X (1 << 8) +# define R200_TXC_SCALE_4X (2 << 8) +# define R200_TXC_SCALE_8X (3 << 8) +# define R200_TXC_SCALE_INV2 (5 << 8) +# define R200_TXC_SCALE_INV4 (6 << 8) +# define R200_TXC_SCALE_INV8 (7 << 8) +# define R200_TXC_CLAMP_SHIFT 12 +# define R200_TXC_CLAMP_MASK (3 << 12) +# define R200_TXC_CLAMP_WRAP (0 << 12) +# define R200_TXC_CLAMP_0_1 (1 << 12) +# define R200_TXC_CLAMP_8_8 (2 << 12) +# define R200_TXC_OUTPUT_REG_MASK (7 << 16) +# define R200_TXC_OUTPUT_REG_NONE (0 << 16) +# define R200_TXC_OUTPUT_REG_R0 (1 << 16) +# define R200_TXC_OUTPUT_REG_R1 (2 << 16) +# define R200_TXC_OUTPUT_REG_R2 (3 << 16) +# define R200_TXC_OUTPUT_REG_R3 (4 << 16) +# define R200_TXC_OUTPUT_REG_R4 (5 << 16) +# define R200_TXC_OUTPUT_REG_R5 (6 << 16) +# define R200_TXC_OUTPUT_MASK_MASK (7 << 20) +# define R200_TXC_OUTPUT_MASK_RGB (0 << 20) +# define R200_TXC_OUTPUT_MASK_RG (1 << 20) +# define R200_TXC_OUTPUT_MASK_RB (2 << 20) +# define R200_TXC_OUTPUT_MASK_R (3 << 20) +# define R200_TXC_OUTPUT_MASK_GB (4 << 20) +# define R200_TXC_OUTPUT_MASK_G (5 << 20) +# define R200_TXC_OUTPUT_MASK_B (6 << 20) +# define R200_TXC_OUTPUT_MASK_NONE (7 << 20) +# define R200_TXC_REPL_NORMAL 0 +# define R200_TXC_REPL_RED 1 +# define R200_TXC_REPL_GREEN 2 +# define R200_TXC_REPL_BLUE 3 +# define R200_TXC_REPL_ARG_A_SHIFT 26 +# define R200_TXC_REPL_ARG_A_MASK (3 << 26) +# define R200_TXC_REPL_ARG_B_SHIFT 28 +# define R200_TXC_REPL_ARG_B_MASK (3 << 28) +# define R200_TXC_REPL_ARG_C_SHIFT 30 +# define R200_TXC_REPL_ARG_C_MASK (3 << 30) + +#define R200_REG_PP_TXABLEND_0 0x2f08 +# define R200_TXA_ARG_A_ZERO (0) +# define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ +# define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ +# define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) +# define R200_TXA_ARG_A_DIFFUSE_BLUE (5) +# define R200_TXA_ARG_A_SPECULAR_ALPHA (6) +# define R200_TXA_ARG_A_SPECULAR_BLUE (7) +# define R200_TXA_ARG_A_TFACTOR_ALPHA (8) +# define R200_TXA_ARG_A_TFACTOR_BLUE (9) +# define R200_TXA_ARG_A_R0_ALPHA (10) +# define R200_TXA_ARG_A_R0_BLUE (11) +# define R200_TXA_ARG_A_R1_ALPHA (12) +# define R200_TXA_ARG_A_R1_BLUE (13) +# define R200_TXA_ARG_A_R2_ALPHA (14) +# define R200_TXA_ARG_A_R2_BLUE (15) +# define R200_TXA_ARG_A_R3_ALPHA (16) +# define R200_TXA_ARG_A_R3_BLUE (17) +# define R200_TXA_ARG_A_R4_ALPHA (18) +# define R200_TXA_ARG_A_R4_BLUE (19) +# define R200_TXA_ARG_A_R5_ALPHA (20) +# define R200_TXA_ARG_A_R5_BLUE (21) +# define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) +# define R200_TXA_ARG_A_TFACTOR1_BLUE (27) +# define R200_TXA_ARG_A_MASK (31 << 0) +# define R200_TXA_ARG_A_SHIFT 0 +# define R200_TXA_ARG_B_ZERO (0 << 5) +# define R200_TXA_ARG_B_CURRENT_ALPHA (2 << 5) /* guess */ +# define R200_TXA_ARG_B_CURRENT_BLUE (3 << 5) /* guess */ +# define R200_TXA_ARG_B_DIFFUSE_ALPHA (4 << 5) +# define R200_TXA_ARG_B_DIFFUSE_BLUE (5 << 5) +# define R200_TXA_ARG_B_SPECULAR_ALPHA (6 << 5) +# define R200_TXA_ARG_B_SPECULAR_BLUE (7 << 5) +# define R200_TXA_ARG_B_TFACTOR_ALPHA (8 << 5) +# define R200_TXA_ARG_B_TFACTOR_BLUE (9 << 5) +# define R200_TXA_ARG_B_R0_ALPHA (10 << 5) +# define R200_TXA_ARG_B_R0_BLUE (11 << 5) +# define R200_TXA_ARG_B_R1_ALPHA (12 << 5) +# define R200_TXA_ARG_B_R1_BLUE (13 << 5) +# define R200_TXA_ARG_B_R2_ALPHA (14 << 5) +# define R200_TXA_ARG_B_R2_BLUE (15 << 5) +# define R200_TXA_ARG_B_R3_ALPHA (16 << 5) +# define R200_TXA_ARG_B_R3_BLUE (17 << 5) +# define R200_TXA_ARG_B_R4_ALPHA (18 << 5) +# define R200_TXA_ARG_B_R4_BLUE (19 << 5) +# define R200_TXA_ARG_B_R5_ALPHA (20 << 5) +# define R200_TXA_ARG_B_R5_BLUE (21 << 5) +# define R200_TXA_ARG_B_TFACTOR1_ALPHA (26 << 5) +# define R200_TXA_ARG_B_TFACTOR1_BLUE (27 << 5) +# define R200_TXA_ARG_B_MASK (31 << 5) +# define R200_TXA_ARG_B_SHIFT 5 +# define R200_TXA_ARG_C_ZERO (0 << 10) +# define R200_TXA_ARG_C_CURRENT_ALPHA (2 << 10) /* guess */ +# define R200_TXA_ARG_C_CURRENT_BLUE (3 << 10) /* guess */ +# define R200_TXA_ARG_C_DIFFUSE_ALPHA (4 << 10) +# define R200_TXA_ARG_C_DIFFUSE_BLUE (5 << 10) +# define R200_TXA_ARG_C_SPECULAR_ALPHA (6 << 10) +# define R200_TXA_ARG_C_SPECULAR_BLUE (7 << 10) +# define R200_TXA_ARG_C_TFACTOR_ALPHA (8 << 10) +# define R200_TXA_ARG_C_TFACTOR_BLUE (9 << 10) +# define R200_TXA_ARG_C_R0_ALPHA (10 << 10) +# define R200_TXA_ARG_C_R0_BLUE (11 << 10) +# define R200_TXA_ARG_C_R1_ALPHA (12 << 10) +# define R200_TXA_ARG_C_R1_BLUE (13 << 10) +# define R200_TXA_ARG_C_R2_ALPHA (14 << 10) +# define R200_TXA_ARG_C_R2_BLUE (15 << 10) +# define R200_TXA_ARG_C_R3_ALPHA (16 << 10) +# define R200_TXA_ARG_C_R3_BLUE (17 << 10) +# define R200_TXA_ARG_C_R4_ALPHA (18 << 10) +# define R200_TXA_ARG_C_R4_BLUE (19 << 10) +# define R200_TXA_ARG_C_R5_ALPHA (20 << 10) +# define R200_TXA_ARG_C_R5_BLUE (21 << 10) +# define R200_TXA_ARG_C_TFACTOR1_ALPHA (26 << 10) +# define R200_TXA_ARG_C_TFACTOR1_BLUE (27 << 10) +# define R200_TXA_ARG_C_MASK (31 << 10) +# define R200_TXA_ARG_C_SHIFT 10 +# define R200_TXA_COMP_ARG_A (1 << 16) +# define R200_TXA_COMP_ARG_A_SHIFT (16) +# define R200_TXA_BIAS_ARG_A (1 << 17) +# define R200_TXA_SCALE_ARG_A (1 << 18) +# define R200_TXA_NEG_ARG_A (1 << 19) +# define R200_TXA_COMP_ARG_B (1 << 20) +# define R200_TXA_COMP_ARG_B_SHIFT (20) +# define R200_TXA_BIAS_ARG_B (1 << 21) +# define R200_TXA_SCALE_ARG_B (1 << 22) +# define R200_TXA_NEG_ARG_B (1 << 23) +# define R200_TXA_COMP_ARG_C (1 << 24) +# define R200_TXA_COMP_ARG_C_SHIFT (24) +# define R200_TXA_BIAS_ARG_C (1 << 25) +# define R200_TXA_SCALE_ARG_C (1 << 26) +# define R200_TXA_NEG_ARG_C (1 << 27) +# define R200_TXA_OP_MADD (0 << 28) +# define R200_TXA_OP_CND0 (2 << 28) +# define R200_TXA_OP_LERP (3 << 28) +# define R200_TXA_OP_CONDITIONAL (6 << 28) +# define R200_TXA_OP_MASK (7 << 28) + +#define R200_REG_PP_TXABLEND2_0 0x2f0c +# define R200_TXA_TFACTOR_SEL_SHIFT 0 +# define R200_TXA_TFACTOR_SEL_MASK 0x7 +# define R200_TXA_TFACTOR1_SEL_SHIFT 4 +# define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) +# define R200_TXA_SCALE_SHIFT 8 +# define R200_TXA_SCALE_MASK (7 << 8) +# define R200_TXA_SCALE_1X (0 << 8) +# define R200_TXA_SCALE_2X (1 << 8) +# define R200_TXA_SCALE_4X (2 << 8) +# define R200_TXA_SCALE_8X (3 << 8) +# define R200_TXA_SCALE_INV2 (5 << 8) +# define R200_TXA_SCALE_INV4 (6 << 8) +# define R200_TXA_SCALE_INV8 (7 << 8) +# define R200_TXA_CLAMP_SHIFT 12 +# define R200_TXA_CLAMP_MASK (3 << 12) +# define R200_TXA_CLAMP_WRAP (0 << 12) +# define R200_TXA_CLAMP_0_1 (1 << 12) +# define R200_TXA_CLAMP_8_8 (2 << 12) +# define R200_TXA_OUTPUT_REG_MASK (7 << 16) +# define R200_TXA_OUTPUT_REG_NONE (0 << 16) +# define R200_TXA_OUTPUT_REG_R0 (1 << 16) +# define R200_TXA_OUTPUT_REG_R1 (2 << 16) +# define R200_TXA_OUTPUT_REG_R2 (3 << 16) +# define R200_TXA_OUTPUT_REG_R3 (4 << 16) +# define R200_TXA_OUTPUT_REG_R4 (5 << 16) +# define R200_TXA_OUTPUT_REG_R5 (6 << 16) +# define R200_TXA_DOT_ALPHA (1 << 20) +# define R200_TXA_REPL_NORMAL 0 +# define R200_TXA_REPL_RED 1 +# define R200_TXA_REPL_GREEN 2 +# define R200_TXA_REPL_ARG_A_SHIFT 26 +# define R200_TXA_REPL_ARG_A_MASK (3 << 26) +# define R200_TXA_REPL_ARG_B_SHIFT 28 +# define R200_TXA_REPL_ARG_B_MASK (3 << 28) +# define R200_TXA_REPL_ARG_C_SHIFT 30 +# define R200_TXA_REPL_ARG_C_MASK (3 << 30) + #define RADEON_REG_RB2D_DSTCACHE_CTLSTAT 0x342c # define RADEON_RB2D_DC_FLUSH (3 << 0) # define RADEON_RB2D_DC_FREE (3 << 2) # define RADEON_RB2D_DC_FLUSH_ALL 0xf # define RADEON_RB2D_DC_BUSY (1 << 31) -#define RADEON_CP_PACKET0 0x00000000 -#define RADEON_CP_PACKET1 0x40000000 -#define RADEON_CP_PACKET2 0x80000000 -#define RADEON_CP_PACKET3_NOP 0xC0001000 -#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900 -#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00 -#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00 -#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 -#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400 -#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600 -#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800 -#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 -#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 -#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 -#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 -#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 -#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 -#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300 -#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 -#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500 -#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800 -#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 -#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 -#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 +/* PLL register defines */ +#define R128_REG_MCLK_CNTL 0x000f +# define R128_FORCE_GCP (1 << 16) +# define R128_FORCE_PIPE3D_CP (1 << 17) +# define R128_FORCE_RCP (1 << 18) +#define RADEON_REG_MCLK_CNTL 0x0012 +# define RADEON_FORCEON_MCLKA (1 << 16) +# define RADEON_FORCEON_MCLKB (1 << 17) +# define RADEON_FORCEON_YCLKA (1 << 18) +# define RADEON_FORCEON_YCLKB (1 << 19) +# define RADEON_FORCEON_MC (1 << 20) +# define RADEON_FORCEON_AIC (1 << 21) + +/* CCE packet defines */ + +#define ATI_CCE_PACKETTYPE_MASK 0xc0000000 +#define ATI_CCE_PACKET0 0x00000000 +#define ATI_CCE_PACKET0_COUNT_MASK 0x3fff0000 +#define ATI_CCE_PACKET0_ONE_REG_WR 0x00008000 +#define ATI_CCE_PACKET0_REG_MASK 0x000007ff +#define ATI_CCE_PACKET1 0x40000000 +#define ATI_CCE_PACKET1_REG_1 0x000007ff +#define ATI_CCE_PACKET1_REG_2 0x003ff800 +#define ATI_CCE_PACKET1_REG_2_SHIFT 10 +#define ATI_CCE_PACKET2 0x80000000 +#define ATI_CCE_PACKET3 0xc0000000 +#define ATI_CCE_PACKET3_COUNT_MASK 0x3fff0000 +#define ATI_CCE_PACKET3_IT_OPCODE_MASK 0x0000ff00 +#define ATI_CCE_PACKET3_NOP 0xc0001000 +#define ATI_CCE_PACKET3_NEXT_CHAR 0xc0001900 +#define ATI_CCE_PACKET3_PLY_NEXTSCAN 0xc0001d00 +#define ATI_CCE_PACKET3_SET_SCISSORS 0xc0001e00 +#define R128_CCE_PACKET3_SET_MODE_24BPP 0xc0001f00 +#define R128_CCE_PACKET3_3D_SAVE_CONTEXT 0xc0002000 +#define R128_CCE_PACKET3_3D_PLAY_CONTEXT 0xc0002100 +#define ATI_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xc0002300 +#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xc0002400 +#define ATI_CCE_PACKET3_3D_RNDR_GEN_PRIM 0xc0002500 +#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xc0002600 +#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xc0002800 +#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xc0002900 +#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xc0002a00 +#define ATI_CCE_PACKET3_LOAD_PALETTE 0xc0002c00 +#define R128_CCE_PACKET3_PURGE 0xc0002d00 +#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE 0xc0002e00 +#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xc0002f00 +#define RADEON_CP_PACKET3_3D_CLEAR_ZMASK 0xc0003200 +#define R200_CP_PACKET3_3D_DRAW_IMMD_2 0xc0003500 +#define ATI_CCE_PACKET3_CNTL_PAINT 0xc0009100 +#define ATI_CCE_PACKET3_CNTL_BITBLT 0xc0009200 +#define ATI_CCE_PACKET3_CNTL_SMALLTEXT 0xc0009300 +#define ATI_CCE_PACKET3_HOSTDATA_BLT 0xc0009400 +#define ATI_CCE_PACKET3_CNTL_POLYLINE 0xc0009500 +#define R128_CCE_PACKET3_SCALE 0xc0009600 +#define R128_CCE_PACKET3_TRANS_SCALE 0xc0009700 +#define ATI_CCE_PACKET3_CNTL_POLYSCANLINES 0xc0009800 +#define ATI_CCE_PACKET3_PAINT_MULTI 0xc0009a00 +#define ATI_CCE_PACKET3_BITBLT_MULTI 0xc0009b00 +#define ATI_CCE_PACKET3_CNTL_TRANS_BITBLT 0xc0009c00 #define RADEON_CP_VC_FRMT_XY 0x00000000 #define RADEON_CP_VC_FRMT_W0 0x00000001 @@ -598,117 +1768,49 @@ #define RADEON_CP_VC_CNTL_TCL_ENABLE 0x00000200 #define RADEON_CP_VC_CNTL_NUM_SHIFT 16 -#define R128_REG_PC_NGUI_CTLSTAT 0x0184 -# define R128_PC_BUSY (1 << 31) -#define R128_REG_PCI_GART_PAGE 0x017c -#define R128_REG_PC_NGUI_CTLSTAT 0x0184 -#define R128_REG_BM_CHUNK_0_VAL 0x0a18 -# define R128_BM_PTR_FORCE_TO_PCI (1 << 21) -# define R128_BM_PM4_RD_FORCE_TO_PCI (1 << 22) -# define R128_BM_GLOBAL_FORCE_TO_PCI (1 << 23) -#define R128_REG_GUI_STAT 0x1740 -# define R128_GUI_ACTIVE (1 << 31) +#define R128_CCE_VC_FRMT_RHW 0x00000001 +#define R128_CCE_VC_FRMT_DIFFUSE_BGR 0x00000002 +#define R128_CCE_VC_FRMT_DIFFUSE_A 0x00000004 +#define R128_CCE_VC_FRMT_DIFFUSE_ARGB 0x00000008 +#define R128_CCE_VC_FRMT_SPEC_BGR 0x00000010 +#define R128_CCE_VC_FRMT_SPEC_F 0x00000020 +#define R128_CCE_VC_FRMT_SPEC_FRGB 0x00000040 +#define R128_CCE_VC_FRMT_S_T 0x00000080 +#define R128_CCE_VC_FRMT_S2_T2 0x00000100 +#define R128_CCE_VC_FRMT_RHW2 0x00000200 -#define R128_REG_TEX_CNTL 0x1800 -#define R128_REG_SCALE_SRC_HEIGHT_WIDTH 0x1994 -#define R128_REG_SCALE_OFFSET_0 0x1998 -#define R128_REG_SCALE_PITCH 0x199c -#define R128_REG_SCALE_X_INC 0x19a0 -#define R128_REG_SCALE_Y_INC 0x19a4 -#define R128_REG_SCALE_HACC 0x19a8 -#define R128_REG_SCALE_VACC 0x19ac -#define R128_REG_SCALE_DST_X_Y 0x19b0 -#define R128_REG_SCALE_DST_HEIGHT_WIDTH 0x19b4 +#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000 +#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001 +#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002 +#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 +#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007 +#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010 +#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020 +#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 +#define R128_CCE_VC_CNTL_NUM_SHIFT 16 -#define R128_REG_SCALE_3D_CNTL 0x1a00 -# define R128_SCALE_DITHER_ERR_DIFF (0 << 1) -# define R128_SCALE_DITHER_TABLE (1 << 1) -# define R128_TEX_CACHE_SIZE_FULL (0 << 2) -# define R128_TEX_CACHE_SIZE_HALF (1 << 2) -# define R128_DITHER_INIT_CURR (0 << 3) -# define R128_DITHER_INIT_RESET (1 << 3) -# define R128_ROUND_24BIT (1 << 4) -# define R128_TEX_CACHE_DISABLE (1 << 5) -# define R128_SCALE_3D_NOOP (0 << 6) -# define R128_SCALE_3D_SCALE (1 << 6) -# define R128_SCALE_3D_TEXMAP_SHADE (2 << 6) -# define R128_SCALE_PIX_BLEND (0 << 8) -# define R128_SCALE_PIX_REPLICATE (1 << 8) -# define R128_TEX_CACHE_SPLIT (1 << 9) -# define R128_APPLE_YUV_MODE (1 << 10) -# define R128_TEX_CACHE_PALLETE_MODE (1 << 11) -# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) -# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12) -# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12) -# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12) -# define R128_FOG_TABLE (1 << 14) -# define R128_SIGNED_DST_CLAMP (1 << 15) -# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) -# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) -# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) -# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) -# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) -# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) -# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16) -# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16) -# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16) -# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16) -# define R128_ALPHA_BLEND_SRC_SAT (10 << 16) -# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16) -# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16) -# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) -# define R128_ALPHA_BLEND_DST_ONE (1 << 20) -# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) -# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) -# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) -# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) -# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20) -# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20) -# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20) -# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20) -# define R128_ALPHA_TEST_NEVER (0 << 24) -# define R128_ALPHA_TEST_LESS (1 << 24) -# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) -# define R128_ALPHA_TEST_EQUAL (3 << 24) -# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) -# define R128_ALPHA_TEST_GREATER (5 << 24) -# define R128_ALPHA_TEST_NEQUAL (6 << 24) -# define R128_ALPHA_TEST_ALWAYS (7 << 24) -# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28) -# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28) -# define R128_COMPOSITE_SHADOW (1 << 29) -# define R128_TEX_MAP_ALPHA_IN_TEXTURE (1 << 30) -# define R128_TEX_CACHE_LINE_SIZE_8QW (0 << 31) -# define R128_TEX_CACHE_LINE_SIZE_4QW (1 << 31) - -#define R128_REG_SCALE_3D_DATATYPE 0x1a20 - -#define R128_REG_TEX_CNTL_C 0x1c9c -# define R128_TEX_ALPHA_EN (1 << 9) -# define R128_TEX_CACHE_FLUSH (1 << 23) - -#define R128_REG_PRIM_TEX_CNTL_C 0x1cb0 -#define R128_REG_PRIM_TEXTURE_COMBINE_CNTL_C 0x1cb4 - -#define R128_DATATYPE_C8 2 -#define R128_DATATYPE_ARGB_1555 3 -#define R128_DATATYPE_RGB_565 4 -#define R128_DATATYPE_ARGB_8888 6 -#define R128_DATATYPE_RGB_332 7 +#define R128_DATATYPE_VQ 0 +#define R128_DATATYPE_CI4 1 +#define R128_DATATYPE_CI8 2 +#define R128_DATATYPE_ARGB1555 3 +#define R128_DATATYPE_RGB565 4 +#define R128_DATATYPE_RGB888 5 +#define R128_DATATYPE_ARGB8888 6 +#define R128_DATATYPE_RGB332 7 #define R128_DATATYPE_Y8 8 -#define R128_DATATYPE_RGB_8 9 +#define R128_DATATYPE_RGB8 9 +#define R128_DATATYPE_CI16 10 #define R128_DATATYPE_VYUY_422 11 #define R128_DATATYPE_YVYU_422 12 #define R128_DATATYPE_AYUV_444 14 -#define R128_DATATYPE_ARGB_4444 15 +#define R128_DATATYPE_ARGB4444 15 -#define R128_PM4_NONPM4 (0 << 28) -#define R128_PM4_192PIO (1 << 28) -#define R128_PM4_192BM (2 << 28) -#define R128_PM4_128PIO_64INDBM (3 << 28) -#define R128_PM4_128BM_64INDBM (4 << 28) -#define R128_PM4_64PIO_128INDBM (5 << 28) -#define R128_PM4_64BM_128INDBM (6 << 28) -#define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) -#define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) -#define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) +#define R128_AGP_OFFSET 0x02000000 + +#define R128_WATERMARK_L 16 +#define R128_WATERMARK_M 8 +#define R128_WATERMARK_N 8 +#define R128_WATERMARK_K 128 diff --git a/hw/kdrive/ati/ati_video.c b/hw/kdrive/ati/ati_video.c new file mode 100644 index 000000000..3106eeb07 --- /dev/null +++ b/hw/kdrive/ati/ati_video.c @@ -0,0 +1,950 @@ +/* + * Copyright © 2004 Keith Packard + * + * 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. + * + * Based on mach64video.c by Keith Packard. + */ +/* $RCSId$ */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "ati.h" +#include "ati_dma.h" +#include "ati_draw.h" +#include "ati_reg.h" +#include "kaa.h" + +#include +#include "fourcc.h" + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvSaturation; + +extern CARD8 ATIBltRop[16]; + +#define IMAGE_MAX_WIDTH 2048 +#define IMAGE_MAX_HEIGHT 2048 + +static void +ATIStopVideo(KdScreenInfo *screen, pointer data, Bool exit) +{ + ScreenPtr pScreen = screen->pScreen; + ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data; + + REGION_EMPTY(screen->pScreen, &pPortPriv->clip); + + if (pPortPriv->off_screen) { + KdOffscreenFree (pScreen, pPortPriv->off_screen); + pPortPriv->off_screen = 0; + } +} + +static int +ATISetPortAttribute(KdScreenInfo *screen, Atom attribute, int value, + pointer data) +{ + return BadMatch; +} + +static int +ATIGetPortAttribute(KdScreenInfo *screen, Atom attribute, int *value, + pointer data) +{ + return BadMatch; +} + +static void +ATIQueryBestSize(KdScreenInfo *screen, Bool motion, short vid_w, short vid_h, + short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, + pointer data) +{ + *p_w = drw_w; + *p_h = drw_h; +} + +/* ATIClipVideo - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +static void +ATIClipVideo(BoxPtr dst, INT32 *x1, INT32 *x2, INT32 *y1, INT32 *y2, + BoxPtr extents, INT32 width, INT32 height) +{ + INT32 vscale, hscale, delta; + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if (diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if (diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if (diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if (diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if (*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if (delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if (*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if (delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } +} + +static void +R128DisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + CARD32 dstDatatype, srcDatatype; + CARD32 dst_offset, dst_pitch; + int dstxoff, dstyoff; + PixmapPtr pPixmap = pPortPriv->pPixmap; + int bpp = pPixmap->drawable.bitsPerPixel; + RING_LOCALS; + + BoxPtr pBox = REGION_RECTS(&pPortPriv->clip); + int nBox = REGION_NUM_RECTS(&pPortPriv->clip); + + if (pPortPriv->id == FOURCC_UYVY) + srcDatatype = R128_DATATYPE_YVYU_422; + else + srcDatatype = R128_DATATYPE_VYUY_422; + + switch (bpp) + { + case 16: + if (pPixmap->drawable.depth == 15) + dstDatatype = R128_DATATYPE_ARGB1555; + else + dstDatatype = R128_DATATYPE_RGB565; + break; + case 32: + dstDatatype = R128_DATATYPE_ARGB8888; + break; + default: + return; + } + + dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr - + pScreenPriv->screen->memory_base); + dst_pitch = pPixmap->devKind; +#ifdef COMPOSITE + dstxoff = -pPixmap->screen_x + pPixmap->drawable.x; + dstyoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + dstxoff = 0; + dstyoff = 0; +#endif + + BEGIN_DMA(18); + OUT_REG(ATI_REG_DST_PITCH_OFFSET, + ((dst_pitch / bpp) << 21) | (dst_offset >> 5)); + OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, + ATI_GMC_DST_PITCH_OFFSET_CNTL | + ATI_GMC_BRUSH_NONE | + (dstDatatype << 8) | + ATI_GMC_SRC_DATATYPE_COLOR | + (ATIBltRop[GXcopy] << 16) | + R128_GMC_3D_FCN_EN | + ATI_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS); + OUT_REG(ATI_REG_DP_CNTL, + ATI_DST_X_LEFT_TO_RIGHT | ATI_DST_Y_TOP_TO_BOTTOM ); + OUT_REG(R128_REG_SCALE_3D_CNTL, + R128_SCALE_3D_SCALE | + R128_SBLEND_ONE | + R128_DBLEND_ZERO); + OUT_REG(R128_REG_TEX_CNTL_C, R128_TEX_CACHE_FLUSH); + OUT_REG(R128_REG_SCALE_3D_DATATYPE, srcDatatype); + + OUT_RING(DMA_PACKET0(R128_REG_SCALE_PITCH, 5)); + OUT_RING(pPortPriv->src_pitch / 16); + OUT_RING((pPortPriv->src_w << 16) / pPortPriv->dst_w); + OUT_RING((pPortPriv->src_h << 16) / pPortPriv->dst_h); + OUT_RING(0x0); + OUT_RING(0x0); + + END_DMA(); + + while (nBox--) { + int srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth; + + dstX = pBox->x1 + dstxoff; + dstY = pBox->y1 + dstyoff; + dstw = pBox->x2 - pBox->x1; + dsth = pBox->y2 - pBox->y1; + srcX = (pBox->x1 - pPortPriv->dst_x1) * + pPortPriv->src_w / pPortPriv->dst_w; + srcY = (pBox->y1 - pPortPriv->dst_y1) * + pPortPriv->src_h / pPortPriv->dst_h; + srcw = pPortPriv->src_w - srcX; + srch = pPortPriv->src_h - srcY; + + BEGIN_DMA(6); + /* R128_REG_SCALE_SRC_HEIGHT_WIDTH, + * R128_REG_SCALE_OFFSET_0 + */ + OUT_RING(DMA_PACKET0(R128_REG_SCALE_SRC_HEIGHT_WIDTH, 2)); + OUT_RING((srch << 16) | srcw); + OUT_RING(pPortPriv->src_offset + srcY * pPortPriv->src_pitch + + srcX * 2); + /* R128_REG_SCALE_DST_X_Y + * R128_REG_SCALE_DST_HEIGHT_WIDTH + */ + OUT_RING(DMA_PACKET0(R128_REG_SCALE_DST_X_Y, 2)); + OUT_RING((dstX << 16) | dstY); + OUT_RING((dsth << 16) | dstw); + END_DMA(); + pBox++; + } +#ifdef DAMAGEEXT + /* XXX: Shouldn't this be in kxv.c instead? */ + DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip); +#endif + KdMarkSync(pScreen); +} + +union intfloat { + float f; + CARD32 i; +}; + +struct blend_vertex { + union intfloat x, y; + union intfloat s0, t0; +}; + +#define VTX_DWORD_COUNT 4 + +#define VTX_OUT(vtx) \ +do { \ + OUT_RING(vtx.x.i); \ + OUT_RING(vtx.y.i); \ + OUT_RING(vtx.s0.i); \ + OUT_RING(vtx.t0.i); \ +} while (0) + +static void +RadeonDisplayVideo(KdScreenInfo *screen, ATIPortPrivPtr pPortPriv) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + struct blend_vertex vtx[4]; + PixmapPtr pPixmap = pPortPriv->pPixmap; + CARD32 txformat; + CARD32 dst_offset, dst_pitch, dst_format; + int dstxoff, dstyoff, pixel_shift; + RING_LOCALS; + + BoxPtr pBox = REGION_RECTS(&pPortPriv->clip); + int nBox = REGION_NUM_RECTS(&pPortPriv->clip); + + switch (pPixmap->drawable.bitsPerPixel) + { + case 16: + if (pPixmap->drawable.depth == 15) + dst_format = RADEON_COLOR_FORMAT_ARGB1555; + else + dst_format = RADEON_COLOR_FORMAT_RGB565; + pixel_shift = 1; + break; + case 32: + dst_format = RADEON_COLOR_FORMAT_ARGB8888; + pixel_shift = 2; + break; + default: + return; + } + + dst_offset = ((CARD8 *)pPixmap->devPrivate.ptr - + pScreenPriv->screen->memory_base); + dst_pitch = pPixmap->devKind; + +#ifdef COMPOSITE + dstxoff = -pPixmap->screen_x + pPixmap->drawable.x; + dstyoff = -pPixmap->screen_y + pPixmap->drawable.y; +#else + dstxoff = 0; + dstyoff = 0; +#endif + + if (pPortPriv->id == FOURCC_UYVY) + txformat = RADEON_TXFORMAT_YVYU422; + else + txformat = RADEON_TXFORMAT_VYUY422; + + txformat |= RADEON_TXFORMAT_NON_POWER2; + + /* RADEON_REG_PP_TXFILTER_0, + * RADEON_REG_PP_TXFORMAT_0, + * RADEON_REG_PP_TXOFFSET_0 + */ + BEGIN_DMA(4); + OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0, 3)); + OUT_RING(RADEON_YUV_TO_RGB); + OUT_RING(txformat); + OUT_RING(pPortPriv->src_offset); + END_DMA(); + + /* RADEON_REG_PP_TEX_SIZE_0, + * RADEON_REG_PP_TEX_PITCH_0 + */ + BEGIN_DMA(3); + OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0, 2)); + OUT_RING((pPixmap->drawable.width - 1) | + ((pPixmap->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); + OUT_RING(pPortPriv->src_pitch - 32); + END_DMA(); + + BEGIN_DMA(14); + OUT_REG(ATI_REG_WAIT_UNTIL, + RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN); + + /* RADEON_REG_PP_CNTL, + * RADEON_REG_RB3D_CNTL, + * RADEON_REG_RB3D_COLOROFFSET + */ + OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3)); + OUT_RING(RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); + OUT_RING(dst_format | RADEON_ALPHA_BLEND_ENABLE); + OUT_RING(dst_offset); + + OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift); + + OUT_REG(RADEON_REG_PP_TXCBLEND_0, + RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_T0_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + OUT_REG(RADEON_REG_PP_TXABLEND_0, + RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_T0_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_CLAMP_TX); + + OUT_REG(RADEON_REG_RB3D_BLENDCNTL, + RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ZERO); + + END_DMA(); + + while (nBox--) { + float srcX, srcY, dstX, dstY, srcw, srch, dstw, dsth; + + dstX = pBox->x1 + dstxoff; + dstY = pBox->y1 + dstyoff; + dstw = pBox->x2 - pBox->x1; + dsth = pBox->y2 - pBox->y1; + srcX = (pBox->x1 - pPortPriv->dst_x1) * + pPortPriv->src_w / pPortPriv->dst_w; + srcY = (pBox->y1 - pPortPriv->dst_y1) * + pPortPriv->src_h / pPortPriv->dst_h; + srcw = pPortPriv->src_w * (dstw / pPortPriv->dst_w); + srch = pPortPriv->src_h * (dsth / pPortPriv->dst_h); + + vtx[0].x.f = dstX; + vtx[0].y.f = dstY; + vtx[0].s0.f = srcX; + vtx[0].t0.f = srcY; + + vtx[1].x.f = dstX; + vtx[1].y.f = dstY + dsth; + vtx[1].s0.f = srcX; + vtx[1].t0.f = srcY + srch; + + vtx[2].x.f = dstX + dstw; + vtx[2].y.f = dstY + dsth; + vtx[2].s0.f = srcX + srcw; + vtx[2].t0.f = srcY + srch; + + vtx[3].x.f = dstX + dstw; + vtx[3].y.f = dstY; + vtx[3].s0.f = srcX + srcw; + vtx[3].t0.f = srcY; + + if (atic->is_r100) { + BEGIN_DMA(4 * VTX_DWORD_COUNT + 3); + OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, + 4 * VTX_DWORD_COUNT + 2)); + OUT_RING(RADEON_CP_VC_FRMT_XY | + RADEON_CP_VC_FRMT_ST0); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + RADEON_CP_VC_CNTL_MAOS_ENABLE | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + } else { + BEGIN_DMA(4 * VTX_DWORD_COUNT + 2); + OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, + 4 * VTX_DWORD_COUNT + 1)); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + } + + VTX_OUT(vtx[0]); + VTX_OUT(vtx[1]); + VTX_OUT(vtx[2]); + VTX_OUT(vtx[3]); + + END_DMA(); + + pBox++; + } +#ifdef DAMAGEEXT + /* XXX: Shouldn't this be in kxv.c instead? */ + DamageDamageRegion(pPortPriv->pDraw, &pPortPriv->clip); +#endif + KdMarkSync(pScreen); +} + +static void +ATIVideoSave(ScreenPtr pScreen, KdOffscreenArea *area) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATIPortPrivPtr pPortPriv = atis->pAdaptor->pPortPrivates[0].ptr; + + if (pPortPriv->off_screen == area) + pPortPriv->off_screen = 0; +} + +static int +ATIPutImage(KdScreenInfo *screen, DrawablePtr pDraw, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, + unsigned char *buf, + short width, + short height, + Bool sync, + RegionPtr clipBoxes, + pointer data) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIScreenInfo(pScreenPriv); + ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data; + char *mmio = atic->reg_base; + INT32 x1, x2, y1, y2; + int randr = RR_Rotate_0 /* XXX */; + int srcPitch, srcPitch2, dstPitch; + int top, left, npixels, nlines, size; + BoxRec dstBox; + int dst_width = width, dst_height = height; + int rot_x1, rot_y1, rot_x2, rot_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; + int rot_src_w, rot_src_h, rot_drw_w, rot_drw_h; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + ATIClipVideo(&dstBox, &x1, &x2, &y1, &y2, + REGION_EXTENTS(pScreen, clipBoxes), width, height); + + src_w = (x2 - x1) >> 16; + src_h = (y2 - y1) >> 16; + drw_w = dstBox.x2 - dstBox.x1; + drw_h = dstBox.y2 - dstBox.y1; + + if ((x1 >= x2) || (y1 >= y2)) + return Success; + + if (mmio == NULL) + return BadAlloc; + + if (randr & (RR_Rotate_0|RR_Rotate_180)) { + dst_width = width; + dst_height = height; + rot_src_w = src_w; + rot_src_h = src_h; + rot_drw_w = drw_w; + rot_drw_h = drw_h; + } else { + dst_width = height; + dst_height = width; + rot_src_w = src_h; + rot_src_h = src_w; + rot_drw_w = drw_h; + rot_drw_h = drw_w; + } + + switch (randr & RR_Rotate_All) { + case RR_Rotate_0: + default: + dst_x1 = dstBox.x1; + dst_y1 = dstBox.y1; + dst_x2 = dstBox.x2; + dst_y2 = dstBox.y2; + rot_x1 = x1; + rot_y1 = y1; + rot_x2 = x2; + rot_y2 = y2; + break; + case RR_Rotate_90: + dst_x1 = dstBox.y1; + dst_y1 = screen->height - dstBox.x2; + dst_x2 = dstBox.y2; + dst_y2 = screen->height - dstBox.x1; + rot_x1 = y1; + rot_y1 = (src_w << 16) - x2; + rot_x2 = y2; + rot_y2 = (src_w << 16) - x1; + break; + case RR_Rotate_180: + dst_x1 = screen->width - dstBox.x2; + dst_y1 = screen->height - dstBox.y2; + dst_x2 = screen->width - dstBox.x1; + dst_y2 = screen->height - dstBox.y1; + rot_x1 = (src_w << 16) - x2; + rot_y1 = (src_h << 16) - y2; + rot_x2 = (src_w << 16) - x1; + rot_y2 = (src_h << 16) - y1; + break; + case RR_Rotate_270: + dst_x1 = screen->width - dstBox.y2; + dst_y1 = dstBox.x1; + dst_x2 = screen->width - dstBox.y1; + dst_y2 = dstBox.x2; + rot_x1 = (src_h << 16) - y2; + rot_y1 = x1; + rot_x2 = (src_h << 16) - y1; + rot_y2 = x2; + break; + } + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + dstPitch = ((dst_width << 1) + 15) & ~15; + srcPitch = (width + 3) & ~3; + srcPitch2 = ((width >> 1) + 3) & ~3; + size = dstPitch * dst_height; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + dstPitch = ((dst_width << 1) + 15) & ~15; + srcPitch = (width << 1); + srcPitch2 = 0; + size = dstPitch * dst_height; + break; + } + + if (pPortPriv->off_screen != NULL && size != pPortPriv->size) { + KdOffscreenFree(screen->pScreen, pPortPriv->off_screen); + pPortPriv->off_screen = 0; + } + + if (pPortPriv->off_screen == NULL) { + pPortPriv->off_screen = KdOffscreenAlloc(screen->pScreen, + size * 2, 64, TRUE, ATIVideoSave, pPortPriv); + if (pPortPriv->off_screen == NULL) + return BadAlloc; + } + + + if (pDraw->type == DRAWABLE_WINDOW) + pPortPriv->pPixmap = + (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); + else + pPortPriv->pPixmap = (PixmapPtr)pDraw; + + /* Migrate the pixmap to offscreen if necessary. */ + if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) + kaaMoveInPixmap(pPortPriv->pPixmap); + + if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) { + return BadAlloc; + } + + pPortPriv->src_offset = pPortPriv->off_screen->offset; + pPortPriv->src_addr = (CARD8 *)(pScreenPriv->screen->memory_base + + pPortPriv->src_offset); + pPortPriv->src_pitch = dstPitch; + pPortPriv->size = size; + pPortPriv->pDraw = pDraw; + + /* copy data */ + top = rot_y1 >> 16; + left = (rot_x1 >> 16) & ~1; + npixels = ((((rot_x2 + 0xffff) >> 16) + 1) & ~1) - left; + + /* Since we're probably overwriting the area that might still be used + * for the last PutImage request, wait for idle. + */ + ATIWaitIdle(atis); + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + nlines = ((((rot_y2 + 0xffff) >> 16) + 1) & ~1) - top; + KdXVCopyPlanarData(screen, buf, pPortPriv->src_addr, randr, + srcPitch, srcPitch2, dstPitch, rot_src_w, rot_src_h, + height, top, left, nlines, npixels, id); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + nlines = ((rot_y2 + 0xffff) >> 16) - top; + KdXVCopyPackedData(screen, buf, pPortPriv->src_addr, randr, + srcPitch, dstPitch, rot_src_w, rot_src_h, top, left, + nlines, npixels); + break; + } + + /* update cliplist */ + if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) { + REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes); + } + + pPortPriv->id = id; + pPortPriv->src_x1 = rot_x1; + pPortPriv->src_y1 = rot_y1; + pPortPriv->src_x2 = rot_x2; + pPortPriv->src_y2 = rot_y2; + pPortPriv->src_w = rot_src_w; + pPortPriv->src_h = rot_src_h; + pPortPriv->dst_x1 = dst_x1; + pPortPriv->dst_y1 = dst_y1; + pPortPriv->dst_x2 = dst_x2; + pPortPriv->dst_y2 = dst_y2; + pPortPriv->dst_w = rot_drw_w; + pPortPriv->dst_h = rot_drw_h; + + if (atic->is_radeon) + RadeonDisplayVideo(screen, pPortPriv); + else + R128DisplayVideo(screen, pPortPriv); + + return Success; +} + +static int +ATIReputImage(KdScreenInfo *screen, DrawablePtr pDraw, short drw_x, short drw_y, + RegionPtr clipBoxes, pointer data) +{ + ScreenPtr pScreen = screen->pScreen; + KdScreenPriv(pScreen); + ATICardInfo(pScreenPriv); + ATIPortPrivPtr pPortPriv = (ATIPortPrivPtr)data; + BoxPtr pOldExtents = REGION_EXTENTS(screen->pScreen, &pPortPriv->clip); + BoxPtr pNewExtents = REGION_EXTENTS(screen->pScreen, clipBoxes); + + if (pOldExtents->x1 != pNewExtents->x1 || + pOldExtents->x2 != pNewExtents->x2 || + pOldExtents->y1 != pNewExtents->y1 || + pOldExtents->y2 != pNewExtents->y2) + return BadMatch; + + if (pDraw->type == DRAWABLE_WINDOW) + pPortPriv->pPixmap = + (*pScreen->GetWindowPixmap)((WindowPtr)pDraw); + else + pPortPriv->pPixmap = (PixmapPtr)pDraw; + + if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) + kaaMoveInPixmap(pPortPriv->pPixmap); + + if (!kaaPixmapIsOffscreen(pPortPriv->pPixmap)) { + ErrorF("err\n"); + return BadAlloc; + } + + + /* update cliplist */ + if (!REGION_EQUAL(screen->pScreen, &pPortPriv->clip, clipBoxes)) + REGION_COPY(screen->pScreen, &pPortPriv->clip, clipBoxes); + + /* XXX: What do the drw_x and drw_y here mean for us? */ + + if (atic->is_radeon) + RadeonDisplayVideo(screen, pPortPriv); + else + R128DisplayVideo(screen, pPortPriv); + + return Success; +} + +static int +ATIQueryImageAttributes(KdScreenInfo *screen, int id, unsigned short *w, + unsigned short *h, int *pitches, int *offsets) +{ + int size, tmp; + + if (*w > IMAGE_MAX_WIDTH) + *w = IMAGE_MAX_WIDTH; + if (*h > IMAGE_MAX_HEIGHT) + *h = IMAGE_MAX_HEIGHT; + + *w = (*w + 1) & ~1; + if (offsets) + offsets[0] = 0; + + switch (id) + { + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if (pitches) + pitches[0] = size; + size *= *h; + if (offsets) + offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if (pitches) + pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if (offsets) + offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if (pitches) + pitches[0] = size; + size *= *h; + break; + } + + return size; +} + + +/* client libraries expect an encoding */ +static KdVideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} + } +}; + +#define NUM_FORMATS 3 + +static KdVideoFormatRec Formats[NUM_FORMATS] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 0 + +static KdAttributeRec Attributes[NUM_ATTRIBUTES] = +{ +}; + +#define NUM_IMAGES 4 + +static KdImageRec Images[NUM_IMAGES] = +{ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_UYVY +}; + +static KdVideoAdaptorPtr +ATISetupImageVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + KdVideoAdaptorPtr adapt; + ATIPortPrivPtr pPortPriv; + int i; + + atis->num_texture_ports = 16; + + adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) + atis->num_texture_ports * + (sizeof(ATIPortPrivRec) + sizeof(DevUnion))); + if (adapt == NULL) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "ATI Texture Video"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = atis->num_texture_ports; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + pPortPriv = + (ATIPortPrivPtr)(&adapt->pPortPrivates[atis->num_texture_ports]); + + for (i = 0; i < atis->num_texture_ports; i++) + adapt->pPortPrivates[i].ptr = &pPortPriv[i]; + + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pAttributes = Attributes; + adapt->pImages = Images; + adapt->nImages = NUM_IMAGES; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = ATIStopVideo; + adapt->SetPortAttribute = ATISetPortAttribute; + adapt->GetPortAttribute = ATIGetPortAttribute; + adapt->QueryBestSize = ATIQueryBestSize; + adapt->PutImage = ATIPutImage; + adapt->ReputImage = ATIReputImage; + adapt->QueryImageAttributes = ATIQueryImageAttributes; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0); + + atis->pAdaptor = adapt; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvSaturation = MAKE_ATOM("XV_SATURATION"); + + return adapt; +} + +Bool ATIInitVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + ATICardInfo(pScreenPriv); + KdScreenInfo *screen = pScreenPriv->screen; + KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL; + KdVideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + + atis->pAdaptor = NULL; + + if (atic->reg_base == NULL) + return FALSE; + if (atic->is_r200 || atic->is_r300) + return FALSE; + + num_adaptors = KdXVListGenericAdaptors(screen, &adaptors); + + newAdaptor = ATISetupImageVideo(pScreen); + + if (newAdaptor) { + if (!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = xalloc((num_adaptors + 1) * + sizeof(KdVideoAdaptorPtr *)); + if (newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(KdVideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if (num_adaptors) + KdXVScreenInit(pScreen, adaptors, num_adaptors); + + if (newAdaptors) + xfree(newAdaptors); + + return TRUE; +} + +void +ATIFiniVideo(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ATIScreenInfo(pScreenPriv); + KdVideoAdaptorPtr adapt = atis->pAdaptor; + ATIPortPrivPtr pPortPriv; + int i; + + if (!adapt) + return; + + for (i = 0; i < atis->num_texture_ports; i++) { + pPortPriv = (ATIPortPrivPtr)(&adapt->pPortPrivates[i].ptr); + REGION_UNINIT(pScreen, &pPortPriv->clip); + } + xfree(adapt); + atis->pAdaptor = NULL; +} diff --git a/hw/kdrive/ati/r128_composite.c b/hw/kdrive/ati/r128_composite.c new file mode 100644 index 000000000..0245e2081 --- /dev/null +++ b/hw/kdrive/ati/r128_composite.c @@ -0,0 +1,589 @@ +/* + * Copyright © 2003 Eric Anholt, Anders Carlsson + * + * 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$ */ + +#include "ati.h" +#include "ati_reg.h" +#include "ati_dma.h" +#include "ati_draw.h" + +extern ATIScreenInfo *accel_atis; +extern CARD8 ATIBltRop[16]; + +static int src_pitch; +static int src_offset; +static int src_bpp; +int widths[2] = {1,1}; +int heights[2] = {1,1}; +Bool is_repeat; + +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 blendctl; +}; + +static struct blendinfo R128BlendOp[] = { + /* Clear */ + {0, 0, R128_SBLEND_ZERO | R128_DBLEND_ZERO}, + /* Src */ + {0, 0, R128_SBLEND_ONE | R128_DBLEND_ZERO}, + /* Dst */ + {0, 0, R128_SBLEND_ZERO | R128_DBLEND_ONE}, + /* Over */ + {0, 1, R128_SBLEND_ONE | R128_DBLEND_INV_SRC_ALPHA}, + /* OverReverse */ + {1, 0, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_ONE}, + /* In */ + {1, 0, R128_SBLEND_DST_ALPHA | R128_DBLEND_ZERO}, + /* InReverse */ + {0, 1, R128_SBLEND_ZERO | R128_DBLEND_SRC_ALPHA}, + /* Out */ + {1, 0, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_ZERO}, + /* OutReverse */ + {0, 1, R128_SBLEND_ZERO | R128_DBLEND_INV_SRC_ALPHA}, + /* Atop */ + {1, 1, R128_SBLEND_DST_ALPHA | R128_DBLEND_INV_SRC_ALPHA}, + /* AtopReverse */ + {1, 1, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_SRC_ALPHA}, + /* Xor */ + {1, 1, R128_SBLEND_INV_DST_ALPHA | R128_DBLEND_INV_SRC_ALPHA}, + /* Add */ + {0, 0, R128_SBLEND_ONE | R128_DBLEND_ONE}, +}; + +static Bool +R128GetDatatypePict(CARD32 format, CARD32 *type) +{ + switch (format) { + case PICT_a1r5g5b5: + *type = R128_DATATYPE_ARGB1555; + return TRUE; + case PICT_r5g6b5: + *type = R128_DATATYPE_RGB565; + return TRUE; + case PICT_a8r8g8b8: + *type = R128_DATATYPE_ARGB8888; + return TRUE; + default: + return FALSE; + } + +} + +Bool +R128PrepareBlend(int op, PicturePtr pSrcPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + ATIScreenInfo(pScreenPriv); + CARD32 dstDatatype, srcDatatype; + RING_LOCALS; + CARD32 xinc, yinc, dst_pitch_offset; + + accel_atis = atis; + + src_offset = (CARD8 *)pSrc->devPrivate.ptr - + pScreenPriv->screen->memory_base; + src_pitch = pSrc->devKind; + src_bpp = pSrc->drawable.bitsPerPixel; + is_repeat = pSrcPicture->repeat; + + if (op >= sizeof(R128BlendOp)/sizeof(R128BlendOp[0])) + ATI_FALLBACK(("Unsupported op 0x%x\n", op)); + if (pSrcPicture->repeat && (pSrc->drawable.width != 1 || + pSrc->drawable.height != 1)) + ATI_FALLBACK(("repeat unsupported\n")); + if (pSrcPicture->transform != NULL) + ATI_FALLBACK(("transform unsupported\n")); + if (!R128GetDatatypePict(pDstPicture->format, &dstDatatype)) + ATI_FALLBACK(("Unsupported dest format 0x%x\n", + pDstPicture->format)); + if (!R128GetDatatypePict(pSrcPicture->format, &srcDatatype)) + ATI_FALLBACK(("Unsupported src format 0x%x\n", + pSrcPicture->format)); + if (src_pitch % src_bpp != 0) + ATI_FALLBACK(("Bad src pitch 0x%x\n", src_pitch)); + if (!ATIGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) + return FALSE; + + if (is_repeat) { + xinc = 0; + yinc = 0; + } else { + xinc = 65536; + yinc = 65536; + } + + BEGIN_DMA(18); + OUT_REG(ATI_REG_DST_PITCH_OFFSET, dst_pitch_offset); + OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, + ATI_GMC_DST_PITCH_OFFSET_CNTL | + ATI_GMC_BRUSH_SOLID_COLOR | + (dstDatatype << 8) | + ATI_GMC_SRC_DATATYPE_COLOR | + (ATIBltRop[GXcopy] << 16) | + ATI_DP_SRC_SOURCE_MEMORY | + R128_GMC_3D_FCN_EN | + ATI_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS); + OUT_REG(ATI_REG_DP_CNTL, + ATI_DST_X_LEFT_TO_RIGHT | ATI_DST_Y_TOP_TO_BOTTOM ); + OUT_REG(R128_REG_SCALE_3D_CNTL, + R128_SCALE_3D_SCALE | + R128_SCALE_PIX_REPLICATE | + R128BlendOp[op].blendctl | + R128_TEX_MAP_ALPHA_IN_TEXTURE); + OUT_REG(R128_REG_TEX_CNTL_C, R128_ALPHA_ENABLE | R128_TEX_CACHE_FLUSH); + OUT_REG(R128_REG_SCALE_3D_DATATYPE, srcDatatype); + + /* R128_REG_SCALE_PITCH, + * R128_REG_SCALE_X_INC, + * R128_REG_SCALE_Y_INC, + * R128_REG_SCALE_HACC + * R128_REG_SCALE_VACC */ + OUT_RING(DMA_PACKET0(R128_REG_SCALE_PITCH, 5)); + OUT_RING(src_pitch / src_bpp); + OUT_RING(xinc); + OUT_RING(yinc); + OUT_RING(0x0); + OUT_RING(0x0); + END_DMA(); + + return TRUE; +} + +void +R128Blend(int srcX, int srcY, int dstX, int dstY, int width, int height) +{ + ATIScreenInfo *atis = accel_atis; + RING_LOCALS; + + if (is_repeat) { + srcX = 0; + srcY = 0; + } + + BEGIN_DMA(6); + /* R128_REG_SCALE_SRC_HEIGHT_WIDTH, + * R128_REG_SCALE_OFFSET_0 + */ + OUT_RING(DMA_PACKET0(R128_REG_SCALE_SRC_HEIGHT_WIDTH, 2)); + OUT_RING((height << 16) | width); + OUT_RING(src_offset + srcY * src_pitch + srcX * (src_bpp >> 3)); + /* R128_REG_SCALE_DST_X_Y + * R128_REG_SCALE_DST_HEIGHT_WIDTH + */ + OUT_RING(DMA_PACKET0(R128_REG_SCALE_DST_X_Y, 2)); + OUT_RING((dstX << 16) | dstY); + OUT_RING((height << 16) | width); + END_DMA(); +} + +void +R128DoneBlend(void) +{ +} + +static Bool +R128CheckCompositeTexture(PicturePtr pPict) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + + if (w > (1 << 10) || h > (1 << 10)) + ATI_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + ATI_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + switch (pPict->format) { + case PICT_a8: + case PICT_a1r5g5b5: + case PICT_a4r4g4b4: + case PICT_r5g6b5: + case PICT_a8r8g8b8: + break; + default: + ATI_FALLBACK(("Unsupported picture format 0x%x\n", + pPict->format)); + } + + return TRUE; +} + +Bool +R128CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + CARD32 dstDatatype; + + if (op >= sizeof(R128BlendOp)/sizeof(R128BlendOp[0])) + ATI_FALLBACK(("Unsupported op 0x%x\n", op)); + if (op == PictOpIn || op == PictOpOut || op == PictOpAtopReverse || + op == PictOpXor) + if (op != PictOpOver) + ATI_FALLBACK(("Something's wacky with these ops\n")); + if (pSrcPicture->transform) + ATI_FALLBACK(("Source transform unsupported.\n")); + if (pMaskPicture && pMaskPicture->transform) + ATI_FALLBACK(("Mask transform unsupported.\n")); + if (pDstPicture->format == PICT_a8) { + if (R128BlendOp[op].src_alpha || R128BlendOp[op].dst_alpha || + pMaskPicture != NULL) + ATI_FALLBACK(("alpha blending unsupported with " + "A8 dst?\n")); + } else if (!R128GetDatatypePict(pDstPicture->format, &dstDatatype)) { + ATI_FALLBACK(("Unsupported dest format 0x%x\n", + pDstPicture->format)); + } + if (pMaskPicture != NULL && pMaskPicture->componentAlpha && + R128BlendOp[op].src_alpha) + ATI_FALLBACK(("Component alpha not supported with source alpha " + "blending.\n")); + + if (!R128CheckCompositeTexture(pSrcPicture)) + return FALSE; + if (pMaskPicture != NULL && !R128CheckCompositeTexture(pMaskPicture)) + return FALSE; + + return TRUE; +} + +static Bool +R128TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit, CARD32 *txsize, + CARD32 *tex_cntl_c) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int bytepp, shift, l2w, l2h, l2p; + int pitch; + + pitch = pPix->devKind; + if ((pitch & (pitch - 1)) != 0) + ATI_FALLBACK(("NPOT pitch 0x%x unsupported\n", pitch)); + + switch (pPict->format) { + case PICT_a8: + /* DATATYPE_RGB8 appears to expand the value into the alpha + * channel like we want. We then blank out the R,G,B channels + * as necessary using the combiners. + */ + *tex_cntl_c = R128_DATATYPE_RGB8 << R128_TEX_DATATYPE_SHIFT; + bytepp = 1; + break; + case PICT_a1r5g5b5: + *tex_cntl_c = R128_DATATYPE_ARGB1555 << R128_TEX_DATATYPE_SHIFT; + bytepp = 2; + break; + case PICT_a4r4g4b4: + *tex_cntl_c = R128_DATATYPE_ARGB4444 << R128_TEX_DATATYPE_SHIFT; + bytepp = 2; + break; + case PICT_r5g6b5: + *tex_cntl_c = R128_DATATYPE_RGB565 << R128_TEX_DATATYPE_SHIFT; + bytepp = 2; + break; + case PICT_a8r8g8b8: + *tex_cntl_c = R128_DATATYPE_ARGB8888 << R128_TEX_DATATYPE_SHIFT; + bytepp = 4; + break; + default: + return FALSE; + } + + *tex_cntl_c |= R128_MIP_MAP_DISABLE; + + if (unit == 0) + shift = 0; + else { + shift = 16; + *tex_cntl_c |= R128_SEC_SELECT_SEC_ST; + } + + if (w == 1) + l2w = 0; + else + l2w = ATILog2(w - 1) + 1; + if (h == 1) + l2h = 0; + else + l2h = ATILog2(h - 1) + 1; + l2p = ATILog2(pPix->devKind / bytepp); + + if (pPict->repeat && w == 1 && h == 1) + l2p = 0; + else if (pPict->repeat && l2p != l2w) + ATI_FALLBACK(("Repeat not supported for pitch != width\n")); + l2w = l2p; + + widths[unit] = 1 << l2w; + heights[unit] = 1 << l2h; + *txsize |= l2p << (R128_TEX_PITCH_SHIFT + shift); + *txsize |= ((l2w > l2h) ? l2w : l2h) << (R128_TEX_SIZE_SHIFT + shift); + *txsize |= l2h << (R128_TEX_HEIGHT_SHIFT + shift); + + return TRUE; +} + +Bool +R128PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + ATIScreenInfo(pScreenPriv); + CARD32 txsize = 0, prim_tex_cntl_c, sec_tex_cntl_c = 0, dstDatatype; + CARD32 dst_pitch_offset, color_factor, in_color_factor; + int i; + RING_LOCALS; + + accel_atis = atis; + + if (pDstPicture->format == PICT_a8) + dstDatatype = R128_DATATYPE_Y8; + else + R128GetDatatypePict(pDstPicture->format, &dstDatatype); + + if (!R128TextureSetup(pSrcPicture, pSrc, 0, &txsize, &prim_tex_cntl_c)) + return FALSE; + if (pMask != NULL && !R128TextureSetup(pMaskPicture, pMask, 1, &txsize, + &sec_tex_cntl_c)) + return FALSE; + + if (!ATIGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) + return FALSE; + + 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(ATI_REG_DST_PITCH_OFFSET, dst_pitch_offset); + OUT_REG(ATI_REG_DP_GUI_MASTER_CNTL, + ATI_GMC_DST_PITCH_OFFSET_CNTL | + ATI_GMC_BRUSH_SOLID_COLOR | + (dstDatatype << 8) | + ATI_GMC_SRC_DATATYPE_COLOR | + (ATIBltRop[GXcopy] << 16) | + ATI_DP_SRC_SOURCE_MEMORY | + R128_GMC_3D_FCN_EN | + ATI_GMC_CLR_CMP_CNTL_DIS | + R128_GMC_AUX_CLIP_DIS | + ATI_GMC_WR_MSK_DIS); + OUT_REG(R128_REG_MISC_3D_STATE_CNTL, + R128_MISC_SCALE_3D_TEXMAP_SHADE | + R128_MISC_SCALE_PIX_REPLICATE | + R128_ALPHA_COMB_ADD_CLAMP | + R128BlendOp[op].blendctl); + OUT_REG(R128_REG_TEX_CNTL_C, + R128_TEXMAP_ENABLE | + ((pMask != NULL) ? R128_SEC_TEXMAP_ENABLE : 0) | + R128_ALPHA_ENABLE | + R128_TEX_CACHE_FLUSH); + OUT_REG(R128_REG_PC_GUI_CTLSTAT, R128_PC_FLUSH_GUI); + END_DMA(); + + /* IN operator: Without a mask, only the first texture unit is enabled. + * With a mask, we put the source in the first unit and have it pass + * through as input to the 2nd. The 2nd unit takes the incoming source + * pixel and modulates it with either the alpha or each of the channels + * in the mask, depending on componentAlpha. + */ + BEGIN_DMA(15); + /* R128_REG_PRIM_TEX_CNTL_C, + * R128_REG_PRIM_TEXTURE_COMBINE_CNTL_C, + * R128_REG_TEX_SIZE_PITCH_C, + * R128_REG_PRIM_TEX_0_OFFSET_C - R128_REG_PRIM_TEX_10_OFFSET_C + */ + OUT_RING(DMA_PACKET0(R128_REG_PRIM_TEX_CNTL_C, 14)); + OUT_RING(prim_tex_cntl_c); + + /* If this is the only stage and the dest is a8, route the alpha result + * to the color (red channel, in particular), too. Otherwise, be sure + * to zero out color channels of an a8 source. + */ + if (pMaskPicture == NULL && pDstPicture->format == PICT_a8) + color_factor = R128_COLOR_FACTOR_ALPHA; + else if (pSrcPicture->format == PICT_a8) + color_factor = R128_COLOR_FACTOR_CONST_COLOR; + else + color_factor = R128_COLOR_FACTOR_TEX; + + OUT_RING(R128_COMB_COPY | + color_factor | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + OUT_RING(txsize); + /* We could save some output by only writing the offset register that + * will actually be used. On the other hand, this is easy. + */ + for (i = 0; i <= 10; i++) + OUT_RING(((CARD8 *)pSrc->devPrivate.ptr - + pScreenPriv->screen->memory_base)); + END_DMA(); + + if (pMask != NULL) { + BEGIN_DMA(14); + /* R128_REG_SEC_TEX_CNTL_C, + * R128_REG_SEC_TEXTURE_COMBINE_CNTL_C, + * R128_REG_SEC_TEX_0_OFFSET_C - R128_REG_SEC_TEX_10_OFFSET_C + */ + OUT_RING(DMA_PACKET0(R128_REG_SEC_TEX_CNTL_C, 13)); + OUT_RING(sec_tex_cntl_c); + + /* XXX: Need to check with keithp to see if component alpha a8 + * masks should act as non-CA, or if they should expand the RGB + * channels as 0. + */ + if (pDstPicture->format == PICT_a8) { + color_factor = R128_COLOR_FACTOR_ALPHA; + in_color_factor = R128_INPUT_FACTOR_PREV_ALPHA; + } else if (pMaskPicture->componentAlpha) { + color_factor = R128_COLOR_FACTOR_TEX; + in_color_factor = R128_INPUT_FACTOR_PREV_COLOR; + } else { + color_factor = R128_COLOR_FACTOR_ALPHA; + in_color_factor = R128_INPUT_FACTOR_PREV_COLOR; + } + + OUT_RING(R128_COMB_MODULATE | + color_factor | + in_color_factor | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + for (i = 0; i <= 10; i++) + OUT_RING(((CARD8 *)pMask->devPrivate.ptr - + pScreenPriv->screen->memory_base)); + END_DMA(); + } + + return TRUE; +} + +union intfloat { + float f; + CARD32 i; +}; + +struct blend_vertex { + union intfloat x, y, z, w; + union intfloat s0, t0; + union intfloat s1, t1; +}; + +#define VTX_RING_COUNT 8 + +#define VTX_OUT(vtx) \ +do { \ + OUT_RING(vtx.x.i); \ + OUT_RING(vtx.y.i); \ + OUT_RING(vtx.z.i); \ + OUT_RING(vtx.w.i); \ + OUT_RING(vtx.s0.i); \ + OUT_RING(vtx.t0.i); \ + OUT_RING(vtx.s1.i); \ + OUT_RING(vtx.t1.i); \ +} while (0) + +void +R128Composite(int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, + int w, int h) +{ + ATIScreenInfo *atis = accel_atis; + struct blend_vertex vtx[4]; + int i; + RING_LOCALS; + + /*ErrorF("R128Composite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n", + srcX, srcY, maskX, maskY,dstX, dstY, w, h);*/ + + vtx[0].x.f = dstX; + vtx[0].y.f = dstY; + vtx[0].z.f = 0.0; + vtx[0].w.f = 1.0; + vtx[0].s0.f = srcX; + vtx[0].t0.f = srcY; + vtx[0].s1.f = maskX; + vtx[0].t1.f = maskY; + + vtx[1].x.f = dstX; + vtx[1].y.f = dstY + h; + vtx[1].z.f = 0.0; + vtx[1].w.f = 1.0; + vtx[1].s0.f = srcX; + vtx[1].t0.f = srcY + h; + vtx[1].s1.f = maskX; + vtx[1].t1.f = maskY + h; + + vtx[2].x.f = dstX + w; + vtx[2].y.f = dstY + h; + vtx[2].z.f = 0.0; + vtx[2].w.f = 1.0; + vtx[2].s0.f = srcX + w; + vtx[2].t0.f = srcY + h; + vtx[2].s1.f = maskX + w; + vtx[2].t1.f = maskY + h; + + vtx[3].x.f = dstX + w; + vtx[3].y.f = dstY; + vtx[3].z.f = 0.0; + vtx[3].w.f = 1.0; + vtx[3].s0.f = srcX + w; + vtx[3].t0.f = srcY; + vtx[3].s1.f = maskX + w; + vtx[3].t1.f = maskY; + + for (i = 0; i < 4; i++) { + vtx[i].x.f += 0.0; + vtx[i].y.f += 0.125; + vtx[i].s0.f /= widths[0]; + vtx[i].t0.f /= heights[0]; + vtx[i].s1.f /= widths[1]; + vtx[i].t1.f /= heights[1]; + } + + BEGIN_DMA(3 + 4 * VTX_RING_COUNT); + OUT_RING(DMA_PACKET3(ATI_CCE_PACKET3_3D_RNDR_GEN_PRIM, + 2 + 4 * VTX_RING_COUNT)); + OUT_RING(R128_CCE_VC_FRMT_RHW | + R128_CCE_VC_FRMT_S_T | + R128_CCE_VC_FRMT_S2_T2); + OUT_RING(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (4 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + VTX_OUT(vtx[0]); + VTX_OUT(vtx[1]); + VTX_OUT(vtx[2]); + VTX_OUT(vtx[3]); + + END_DMA(); +} + +void +R128DoneComposite(void) +{ +} diff --git a/hw/kdrive/ati/radeon_composite.c b/hw/kdrive/ati/radeon_composite.c index 94f43e2a1..bcdedd8da 100644 --- a/hw/kdrive/ati/radeon_composite.c +++ b/hw/kdrive/ati/radeon_composite.c @@ -28,100 +28,369 @@ #endif #include "ati.h" #include "ati_reg.h" +#include "ati_dma.h" #include "ati_draw.h" -#include "radeon_common.h" -#include "r128_common.h" -#include "ati_sarea.h" - -#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() extern ATIScreenInfo *accel_atis; -static CARD32 RadeonBlendOp[] = { - /* Clear */ - RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ZERO, - /* Src */ - RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO, - /* Dst */ - RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ONE, - /* Over */ - RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA, - /* OverReverse */ - RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_ONE, - /* In */ - RADEON_SRC_BLEND_GL_DST_ALPHA | RADEON_DST_BLEND_GL_ZERO, - /* InReverse */ - RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_SRC_ALPHA, - /* Out */ - RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_ZERO, - /* OutReverse */ - RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA, - /* Atop */ - RADEON_SRC_BLEND_GL_DST_ALPHA | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA, - /* AtopReverse */ - RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_SRC_ALPHA, - /* Xor */ - RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA | RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA, - /* Add */ - RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ONE, - /* Saturate */ - RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE | RADEON_DST_BLEND_GL_ONE, - /* DisjointClear */ - RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ZERO, - /* DisjointSrc */ - RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO, - /* DisjointDst */ - RADEON_SRC_BLEND_GL_ZERO | RADEON_DST_BLEND_GL_ONE, +struct blendinfo { + Bool dst_alpha; + Bool src_alpha; + CARD32 blend_cntl; }; +static struct blendinfo RadeonBlendOp[] = { + /* Clear */ + {0, 0, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_ZERO}, + /* Src */ + {0, 0, RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ZERO}, + /* Dst */ + {0, 0, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_ONE}, + /* Over */ + {0, 1, RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_INV_SRC_ALPHA}, + /* OverReverse */ + {1, 0, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_ONE}, + /* In */ + {1, 0, RADEON_SBLEND_GL_DST_ALPHA | RADEON_DBLEND_GL_ZERO}, + /* InReverse */ + {0, 1, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_SRC_ALPHA}, + /* Out */ + {1, 0, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_ZERO}, + /* OutReverse */ + {0, 1, RADEON_SBLEND_GL_ZERO | RADEON_DBLEND_GL_INV_SRC_ALPHA}, + /* Atop */ + {1, 1, RADEON_SBLEND_GL_DST_ALPHA | RADEON_DBLEND_GL_INV_SRC_ALPHA}, + /* AtopReverse */ + {1, 1, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_SRC_ALPHA}, + /* Xor */ + {1, 1, RADEON_SBLEND_GL_INV_DST_ALPHA | RADEON_DBLEND_GL_INV_SRC_ALPHA}, + /* Add */ + {0, 0, RADEON_SBLEND_GL_ONE | RADEON_DBLEND_GL_ONE}, +}; + +struct formatinfo { + int fmt; + CARD32 card_fmt; +}; + +/* Note on texture formats: + * TXFORMAT_Y8 expands to (Y,Y,Y,1). TXFORMAT_I8 expands to (I,I,I,I) + */ +static struct formatinfo R100TexFormats[] = { + {PICT_a8r8g8b8, RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x8r8g8b8, RADEON_TXFORMAT_ARGB8888}, + {PICT_r5g6b5, RADEON_TXFORMAT_RGB565}, + {PICT_a1r5g5b5, RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x1r5g5b5, RADEON_TXFORMAT_ARGB1555}, + {PICT_a8, RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP}, +}; + +static struct formatinfo R200TexFormats[] = { + {PICT_a8r8g8b8, R200_TXFORMAT_ARGB8888 | R200_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x8r8g8b8, R200_TXFORMAT_ARGB8888}, + {PICT_r5g6b5, R200_TXFORMAT_RGB565}, + {PICT_a1r5g5b5, R200_TXFORMAT_ARGB1555 | R200_TXFORMAT_ALPHA_IN_MAP}, + {PICT_x1r5g5b5, R200_TXFORMAT_ARGB1555}, + {PICT_a8, R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP}, +}; + +/* Common Radeon setup code */ + static Bool -RadeonTextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit) +RadeonGetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) +{ + switch (pDstPicture->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + *dst_format = RADEON_COLOR_FORMAT_ARGB8888; + break; + case PICT_r5g6b5: + *dst_format = RADEON_COLOR_FORMAT_RGB565; + break; + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *dst_format = RADEON_COLOR_FORMAT_ARGB1555; + break; + case PICT_a8: + *dst_format = RADEON_COLOR_FORMAT_RGB8; + break; + default: + ATI_FALLBACK(("Unsupported dest format 0x%x\n", + pDstPicture->format)); + } + + return TRUE; +} + +/* R100-specific code */ + +static Bool +R100CheckCompositeTexture(PicturePtr pPict, int unit) { - ATIScreenInfo *atis = accel_atis; - ATICardInfo *atic = atis->atic; - KdScreenPriv(pPix->drawable.pScreen); - CARD32 txformat, txoffset, txpitch; int w = pPict->pDrawable->width; int h = pPict->pDrawable->height; - LOCALS; + int i; if ((w > 0x7ff) || (h > 0x7ff)) ATI_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); - switch (pPict->format) { - case PICT_a8r8g8b8: - txformat = RADEON_TXFORMAT_ARGB8888 | - RADEON_TXFORMAT_ALPHA_IN_MAP; - break; - case PICT_x8r8g8b8: - txformat = RADEON_TXFORMAT_ARGB8888; - break; - case PICT_r5g6b5: - txformat = RADEON_TXFORMAT_RGB565; - break; - case PICT_a8: - txformat = RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP; - break; - default: + for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++) + { + if (R100TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(R100TexFormats) / sizeof(R100TexFormats[0])) ATI_FALLBACK(("Unsupported picture format 0x%x\n", pPict->format)); - } - if (pPict->repeat) { - if ((w & (w - 1)) != 0 || (h & (h - 1)) != 0) - ATI_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, - h)); - txformat |= (ATILog2(w) - 1) << RADEON_TXFORMAT_WIDTH_SHIFT; - txformat |= (ATILog2(h) - 1) << RADEON_TXFORMAT_HEIGHT_SHIFT; + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + ATI_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + return TRUE; +} + +static Bool +R100TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit) +{ + ATIScreenInfo *atis = accel_atis; + KdScreenPriv(pPix->drawable.pScreen); + CARD32 txformat, txoffset, txpitch; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + RING_LOCALS; + + for (i = 0; i < sizeof(R100TexFormats) / sizeof(R100TexFormats[0]); i++) + { + if (R100TexFormats[i].fmt == pPict->format) + break; + } + txformat = R100TexFormats[i].card_fmt; + + if (pPict->repeat) { + txformat |= ATILog2(w) << RADEON_TXFORMAT_WIDTH_SHIFT; + txformat |= ATILog2(h) << RADEON_TXFORMAT_HEIGHT_SHIFT; } else txformat |= RADEON_TXFORMAT_NON_POWER2; txformat |= unit << 24; /* RADEON_TXFORMAT_ST_ROUTE_STQX */ + txpitch = pPix->devKind; + txoffset = ((CARD8 *)pPix->devPrivate.ptr - + pScreenPriv->screen->memory_base); + + if ((txoffset & 0x1f) != 0) + ATI_FALLBACK(("Bad texture offset 0x%x\n", txoffset)); + if ((txpitch & 0x1f) != 0) + ATI_FALLBACK(("Bad texture pitch 0x%x\n", txpitch)); + + /* RADEON_REG_PP_TXFILTER_0, + * RADEON_REG_PP_TXFORMAT_0, + * RADEON_REG_PP_TXOFFSET_0 + */ + BEGIN_DMA(4); + OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0 + 0x18 * unit, 3)); + OUT_RING(0); + OUT_RING(txformat); + OUT_RING(txoffset); + END_DMA(); + + /* RADEON_REG_PP_TEX_SIZE_0, + * RADEON_REG_PP_TEX_PITCH_0 + */ + BEGIN_DMA(3); + OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0 + 0x8 * unit, 2)); + OUT_RING((pPix->drawable.width - 1) | + ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); + OUT_RING(txpitch - 32); + END_DMA(); + + return TRUE; +} + +Bool +R100CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + CARD32 tmp1; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0])) + ATI_FALLBACK(("Unsupported Composite op 0x%x\n", op)); + if (pSrcPicture->transform) + ATI_FALLBACK(("Source transform unsupported.\n")); + if (pMaskPicture != NULL && pMaskPicture->transform) + ATI_FALLBACK(("Mask transform unsupported.\n")); + if (pMaskPicture != NULL && pMaskPicture->componentAlpha && + RadeonBlendOp[op].src_alpha) + ATI_FALLBACK(("Component alpha not supported with source " + "alpha blending.\n")); + if (pDstPicture->pDrawable->width >= (1 << 11) || + pDstPicture->pDrawable->height >= (1 << 11)) + ATI_FALLBACK(("Dest w/h too large (%d,%d).\n", + pDstPicture->pDrawable->width, + pDstPicture->pDrawable->height)); + + if (!R100CheckCompositeTexture(pSrcPicture, 0)) + return FALSE; + if (pMaskPicture != NULL && !R100CheckCompositeTexture(pMaskPicture, 1)) + return FALSE; + + if (!RadeonGetDestFormat(pDstPicture, &tmp1)) + return FALSE; + + return TRUE; +} + +Bool +R100PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + ATIScreenInfo(pScreenPriv); + CARD32 dst_format, dst_offset, dst_pitch; + CARD32 pp_cntl, blendcntl, cblend, ablend; + int pixel_shift; + RING_LOCALS; + + accel_atis = atis; + + RadeonGetDestFormat(pDstPicture, &dst_format); + pixel_shift = pDst->drawable.bitsPerPixel >> 4; + + dst_offset = ((CARD8 *)pDst->devPrivate.ptr - + pScreenPriv->screen->memory_base); + dst_pitch = pDst->devKind; + if ((dst_offset & 0x0f) != 0) + ATI_FALLBACK(("Bad destination offset 0x%x\n", dst_offset)); + if (((dst_pitch >> pixel_shift) & 0x7) != 0) + ATI_FALLBACK(("Bad destination pitch 0x%x\n", dst_pitch)); + + if (!R100TextureSetup(pSrcPicture, pSrc, 0)) + return FALSE; + pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE; + + if (pMask != NULL) { + if (!R100TextureSetup(pMaskPicture, pMask, 1)) + return FALSE; + pp_cntl |= RADEON_TEX_1_ENABLE; + } + + BEGIN_DMA(14); + OUT_REG(ATI_REG_WAIT_UNTIL, + RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN); + + /* RADEON_REG_PP_CNTL, + * RADEON_REG_RB3D_CNTL, + * RADEON_REG_RB3D_COLOROFFSET + */ + OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3)); + OUT_RING(pp_cntl); + OUT_RING(dst_format | RADEON_ALPHA_BLEND_ENABLE); + OUT_RING(dst_offset); + + OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift); + + /* IN operator: Multiply src by mask components or mask alpha. + * BLEND_CTL_ADD is A * B + C. + * If a picture is a8, we have to explicitly zero its color values. + * If the destination is a8, we have to route the alpha to red, I think. + */ + cblend = RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX | + RADEON_COLOR_ARG_C_ZERO; + ablend = RADEON_BLEND_CTL_ADD | RADEON_CLAMP_TX | + RADEON_ALPHA_ARG_C_ZERO; + + if (pDstPicture->format == PICT_a8) + cblend |= RADEON_COLOR_ARG_A_T0_ALPHA; + else if (pSrcPicture->format == PICT_a8) + cblend |= RADEON_COLOR_ARG_A_ZERO; + else + cblend |= RADEON_COLOR_ARG_A_T0_COLOR; + ablend |= RADEON_ALPHA_ARG_A_T0_ALPHA; + + if (pMask) { + if (pMaskPicture->componentAlpha && + pDstPicture->format != PICT_a8) + cblend |= RADEON_COLOR_ARG_B_T1_COLOR; + else + cblend |= RADEON_COLOR_ARG_B_T1_ALPHA; + ablend |= RADEON_ALPHA_ARG_B_T1_ALPHA; + } else { + cblend |= RADEON_COLOR_ARG_B_ZERO | RADEON_COMP_ARG_B; + ablend |= RADEON_ALPHA_ARG_B_ZERO | RADEON_COMP_ARG_B; + } + + OUT_REG(RADEON_REG_PP_TXCBLEND_0, cblend); + OUT_REG(RADEON_REG_PP_TXABLEND_0, ablend); + + /* Op operator. */ + blendcntl = RadeonBlendOp[op].blend_cntl; + if (PICT_FORMAT_A(pDstPicture->format) == 0 && + RadeonBlendOp[op].dst_alpha) { + if ((blendcntl & RADEON_SBLEND_MASK) == + RADEON_SBLEND_GL_DST_ALPHA) + blendcntl = (blendcntl & ~RADEON_SBLEND_MASK) | + RADEON_SBLEND_GL_ONE; + else if ((blendcntl & RADEON_SBLEND_MASK) == + RADEON_SBLEND_GL_INV_DST_ALPHA) + blendcntl = (blendcntl & ~RADEON_SBLEND_MASK) | + RADEON_SBLEND_GL_ZERO; + } + OUT_REG(RADEON_REG_RB3D_BLENDCNTL, blendcntl); + END_DMA(); + + return TRUE; +} + +static Bool +R200CheckCompositeTexture(PicturePtr pPict, int unit) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + + if ((w > 0x7ff) || (h > 0x7ff)) + ATI_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); + + for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++) + { + if (R200TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(R200TexFormats) / sizeof(R200TexFormats[0])) + ATI_FALLBACK(("Unsupported picture format 0x%x\n", + pPict->format)); + + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + ATI_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + return TRUE; +} +static Bool +R200TextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit) +{ + ATIScreenInfo *atis = accel_atis; + KdScreenPriv(pPix->drawable.pScreen); + CARD32 txformat, txoffset, txpitch; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + RING_LOCALS; + + for (i = 0; i < sizeof(R200TexFormats) / sizeof(R200TexFormats[0]); i++) + { + if (R200TexFormats[i].fmt == pPict->format) + break; + } + txformat = R200TexFormats[i].card_fmt; + + if (pPict->repeat) { + txformat |= ATILog2(w) << R200_TXFORMAT_WIDTH_SHIFT; + txformat |= ATILog2(h) << R200_TXFORMAT_HEIGHT_SHIFT; + } else + txformat |= R200_TXFORMAT_NON_POWER2; + txformat |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; + txpitch = pPix->devKind; txoffset = ((CARD8 *)pPix->devPrivate.ptr - pScreenPriv->screen->memory_base); @@ -131,149 +400,154 @@ RadeonTextureSetup(PicturePtr pPict, PixmapPtr pPix, int unit) if ((txpitch & 0x1f) != 0) ATI_FALLBACK(("Bad texture pitch 0x%x\n", txpitch)); - /* RADEON_REG_PP_TXFILTER_0, RADEON_REG_PP_TXFORMAT_0, - * RADEON_REG_PP_TXOFFSET_0 + /* R200_REG_PP_TXFILTER_0, + * R200_REG_PP_TXFORMAT_0, + * R200_REG_PP_TXFORMAT_X_0, + * R200_REG_PP_TXSIZE_0, + * R200_REG_PP_TXPITCH_0 */ - BEGIN_RING(4); - OUT_RING(DMA_PACKET0(RADEON_REG_PP_TXFILTER_0 + 0x18 * unit, 2)); + BEGIN_DMA(6); + OUT_RING(DMA_PACKET0(R200_REG_PP_TXFILTER_0 + 0x20 * unit, 5)); OUT_RING(0); OUT_RING(txformat); - OUT_RING(txoffset); - ADVANCE_RING(); - - /* RADEON_REG_PP_TEX_SIZE_0, RADEON_REG_PP_TEX_PITCH_0 */ - BEGIN_RING(3); - OUT_RING(DMA_PACKET0(RADEON_REG_PP_TEX_SIZE_0 + 0x8 * unit, 1)); + OUT_RING(0); OUT_RING((pPix->drawable.width - 1) | - ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); - OUT_RING(txpitch - 32); - ADVANCE_RING(); + ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); /* XXX */ + OUT_RING(txpitch - 32); /* XXX */ + END_DMA(); + + BEGIN_DMA(2); + OUT_REG(R200_PP_TXOFFSET_0 + 0x18 * unit, txoffset); + END_DMA(); return TRUE; } Bool -RadeonPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, - PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +R200CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) { - KdScreenPriv(pDst->drawable.pScreen); - ATIScreenInfo(pScreenPriv); - ATICardInfo(pScreenPriv); - CARD32 dst_format, dst_offset, dst_pitch; - CARD32 pp_cntl; - int pixel_shift; - LOCALS; + CARD32 tmp1; - /*ErrorF("RadeonPrepareComposite\n");*/ - /* Check for unsupported compositing operations. */ if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0])) ATI_FALLBACK(("Unsupported Composite op 0x%x\n", op)); if (pSrcPicture->transform) ATI_FALLBACK(("Source transform unsupported.\n")); - if (pMaskPicture && pMaskPicture->transform) + if (pMaskPicture != NULL && pMaskPicture->transform) ATI_FALLBACK(("Mask transform unsupported.\n")); + if (pMaskPicture != NULL && pMaskPicture->componentAlpha && + RadeonBlendOp[op].src_alpha) + ATI_FALLBACK(("Component alpha not supported with source " + "alpha blending.\n")); + + if (!R200CheckCompositeTexture(pSrcPicture, 0)) + return FALSE; + if (pMaskPicture != NULL && !R200CheckCompositeTexture(pMaskPicture, 1)) + return FALSE; + + if (!RadeonGetDestFormat(pDstPicture, &tmp1)) + return FALSE; + + return TRUE; +} + +Bool +R200PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + ATIScreenInfo(pScreenPriv); + CARD32 dst_format, dst_offset, dst_pitch; + CARD32 pp_cntl, blendcntl, cblend, ablend; + int pixel_shift; + RING_LOCALS; + + RadeonGetDestFormat(pDstPicture, &dst_format); + pixel_shift = pDst->drawable.bitsPerPixel >> 4; accel_atis = atis; - switch (pDstPicture->format) { - case PICT_r5g6b5: - dst_format = RADEON_COLOR_FORMAT_RGB565; - pixel_shift = 1; - break; - case PICT_a1r5g5b5: - dst_format = RADEON_COLOR_FORMAT_ARGB1555; - pixel_shift = 1; - break; - case PICT_a8r8g8b8: - case PICT_x8r8g8b8: - dst_format = RADEON_COLOR_FORMAT_ARGB8888; - pixel_shift = 2; - break; - default: - ATI_FALLBACK(("Unsupported dest format 0x%x\n", - pDstPicture->format)); - } - dst_offset = ((CARD8 *)pDst->devPrivate.ptr - pScreenPriv->screen->memory_base); dst_pitch = pDst->devKind; - if ((dst_offset & 0xff) != 0) + if ((dst_offset & 0x0f) != 0) ATI_FALLBACK(("Bad destination offset 0x%x\n", dst_offset)); if (((dst_pitch >> pixel_shift) & 0x7) != 0) ATI_FALLBACK(("Bad destination pitch 0x%x\n", dst_pitch)); - if (!RadeonTextureSetup(pSrcPicture, pSrc, 0)) + if (!R200TextureSetup(pSrcPicture, pSrc, 0)) return FALSE; pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE; if (pMask != NULL) { - if (!RadeonTextureSetup(pMaskPicture, pMask, 1)) + if (!R200TextureSetup(pMaskPicture, pMask, 1)) return FALSE; pp_cntl |= RADEON_TEX_1_ENABLE; } - BEGIN(2); - OUT_REG(RADEON_REG_RE_TOP_LEFT, 0); - OUT_REG(RADEON_REG_RE_WIDTH_HEIGHT, 0xffffffff); - END(); + BEGIN_DMA(34); + OUT_REG(ATI_REG_WAIT_UNTIL, + RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN); - BEGIN(11); - OUT_REG(RADEON_REG_PP_CNTL, pp_cntl); - OUT_REG(RADEON_REG_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); - /* COLORPITCH is multiples of 8 pixels, but located at the 3rd bit */ - OUT_REG(RADEON_REG_RB3D_COLORPITCH, (dst_pitch >> pixel_shift)); - OUT_REG(RADEON_REG_RB3D_COLOROFFSET, dst_offset); - 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); - 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); - if (pMask != NULL) { - /* IN operator: Multiply src by mask components or mask alpha. - * BLEND_CTL_ADD is A * B + C - */ - if (pMaskPicture->componentAlpha) - OUT_REG(RADEON_REG_PP_TXCBLEND_0, - RADEON_COLOR_ARG_A_T0_COLOR | - RADEON_COLOR_ARG_B_T1_COLOR | - RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); + /* RADEON_REG_PP_CNTL, + * RADEON_REG_RB3D_CNTL, + * RADEON_REG_RB3D_COLOROFFSET + */ + OUT_RING(DMA_PACKET0(RADEON_REG_PP_CNTL, 3)); + OUT_RING(pp_cntl); + OUT_RING(dst_format | RADEON_ALPHA_BLEND_ENABLE); + OUT_RING(dst_offset); + + OUT_REG(RADEON_REG_RB3D_COLORPITCH, dst_pitch >> pixel_shift); + + /* IN operator: Multiply src by mask components or mask alpha. + * BLEND_CTL_ADD is A * B + C. + * If a picture is a8, we have to explicitly zero its color values. + * If the destination is a8, we have to route the alpha to red, I think. + */ + cblend = R200_TXC_OP_MADD | R200_TXC_ARG_C_ZERO; + ablend = R200_TXA_OP_MADD | R200_TXA_ARG_C_ZERO; + + if (pDstPicture->format == PICT_a8) + cblend |= R200_TXC_ARG_A_R0_ALPHA; + else if (pSrcPicture->format == PICT_a8) + cblend |= R200_TXC_ARG_A_ZERO; + else + cblend |= R200_TXC_ARG_A_R0_COLOR; + ablend |= R200_TXA_ARG_B_R0_ALPHA; + + if (pMask) { + if (pMaskPicture->componentAlpha && + pDstPicture->format != PICT_a8) + cblend |= R200_TXC_ARG_B_R1_COLOR; else - OUT_REG(RADEON_REG_PP_TXCBLEND_0, - RADEON_COLOR_ARG_A_T0_COLOR | - RADEON_COLOR_ARG_B_T1_ALPHA | - RADEON_COLOR_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - OUT_REG(RADEON_REG_PP_TXABLEND_0, - RADEON_ALPHA_ARG_A_T0_ALPHA | - RADEON_ALPHA_ARG_B_T1_ALPHA | - RADEON_ALPHA_ARG_C_ZERO | - RADEON_BLEND_CTL_ADD); + cblend |= R200_TXC_ARG_B_R1_ALPHA; + ablend |= R200_TXA_ARG_B_R1_ALPHA; } else { - OUT_REG(RADEON_REG_PP_TXCBLEND_0, - RADEON_COLOR_ARG_A_ZERO | - RADEON_COLOR_ARG_B_ZERO | - RADEON_COLOR_ARG_C_T0_COLOR | - RADEON_BLEND_CTL_ADD | - RADEON_CLAMP_TX); - OUT_REG(RADEON_REG_PP_TXABLEND_0, - RADEON_ALPHA_ARG_A_ZERO | - RADEON_ALPHA_ARG_B_ZERO | - RADEON_ALPHA_ARG_C_T0_ALPHA | - RADEON_BLEND_CTL_ADD); + cblend |= R200_TXC_ARG_B_ZERO | R200_TXC_COMP_ARG_B; + ablend |= R200_TXA_ARG_B_ZERO | R200_TXA_COMP_ARG_B; } - /* Op operator. */ - OUT_REG(RADEON_RB3D_BLENDCNTL, RadeonBlendOp[op]); - END(); - RadeonSwitchTo3D(); + OUT_REG(R200_REG_PP_TXCBLEND_0, cblend); + OUT_REG(R200_REG_PP_TXABLEND_0, ablend); + OUT_REG(R200_REG_PP_TXCBLEND2_0, 0); + OUT_REG(R200_REG_PP_TXABLEND2_0, 0); + + /* Op operator. */ + blendcntl = RadeonBlendOp[op].blend_cntl; + if (PICT_FORMAT_A(pDstPicture->format) == 0 && + RadeonBlendOp[op].dst_alpha) { + blendcntl &= ~RADEON_SBLEND_MASK; + if ((blendcntl & RADEON_SBLEND_MASK) == + RADEON_SBLEND_GL_DST_ALPHA) + blendcntl |= RADEON_SBLEND_GL_ONE; + else if ((blendcntl & RADEON_SBLEND_MASK) == + RADEON_SBLEND_GL_INV_DST_ALPHA) + blendcntl |= RADEON_SBLEND_GL_ZERO; + } + OUT_REG(RADEON_REG_RB3D_BLENDCNTL, blendcntl); + END_DMA(); return TRUE; } @@ -289,7 +563,7 @@ struct blend_vertex { union intfloat s1, t1; }; -#define VTX_REG_COUNT 6 +#define VTX_DWORD_COUNT 6 #define VTX_OUT(vtx) \ do { \ @@ -299,8 +573,6 @@ do { \ OUT_RING(vtx.t0.i); \ OUT_RING(vtx.s1.i); \ OUT_RING(vtx.t1.i); \ - /*ErrorF("%f,%f %f,%f %f,%f\n", vtx.x.f, vtx.y.f, vtx.s0.f, \ - vtx.t0.f, vtx.s1.f, vtx.t1.f);*/ \ } while (0) void @@ -310,21 +582,10 @@ RadeonComposite(int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, ATIScreenInfo *atis = accel_atis; ATICardInfo *atic = atis->atic; struct blend_vertex vtx[4]; - LOCALS; + RING_LOCALS; - /*ErrorF("RadeonComposite %d %d %d %d %d %d\n", srcX, srcY, maskX, maskY, - dstX, dstY, w, h);*/ - BEGIN_RING(3 + 4 * VTX_REG_COUNT); - OUT_RING(RADEON_CP_PACKET3_3D_DRAW_IMMD | - ((4 * VTX_REG_COUNT + 1) << 16)); - OUT_RING(RADEON_CP_VC_FRMT_XY | - RADEON_CP_VC_FRMT_ST0 | - RADEON_CP_VC_FRMT_ST1); - OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | - RADEON_CP_VC_CNTL_PRIM_WALK_RING | - RADEON_CP_VC_CNTL_MAOS_ENABLE | - RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | - (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + /*ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n", + srcX, srcY, maskX, maskY,dstX, dstY, w, h);*/ vtx[0].x.f = dstX; vtx[0].y.f = dstY; @@ -354,36 +615,36 @@ RadeonComposite(int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, vtx[3].s1.f = maskX + w; vtx[3].t1.f = maskY; + if (atic->is_r100) { + BEGIN_DMA(4 * VTX_DWORD_COUNT + 3); + OUT_RING(DMA_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, + 4 * VTX_DWORD_COUNT + 2)); + OUT_RING(RADEON_CP_VC_FRMT_XY | + RADEON_CP_VC_FRMT_ST0 | + RADEON_CP_VC_FRMT_ST1); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + RADEON_CP_VC_CNTL_MAOS_ENABLE | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + } else { + BEGIN_DMA(4 * VTX_DWORD_COUNT + 2); + OUT_RING(DMA_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, + 4 * VTX_DWORD_COUNT + 1)); + OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | + RADEON_CP_VC_CNTL_PRIM_WALK_RING | + (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); + } + VTX_OUT(vtx[0]); VTX_OUT(vtx[1]); VTX_OUT(vtx[2]); VTX_OUT(vtx[3]); - ADVANCE_RING(); + END_DMA(); } void RadeonDoneComposite(void) { - /*ErrorF("RadeonDoneComposite\n");*/ -} - -Bool -RadeonPrepareBlend(int op, PicturePtr pSrcPicture, PicturePtr pDstPicture, - PixmapPtr pSrc, PixmapPtr pDst) -{ - return RadeonPrepareComposite(op, pSrcPicture, NULL, pDstPicture, pSrc, - NULL, pDst); -} - -void -RadeonBlend(int srcX, int srcY, int dstX, int dstY, int width, int height) -{ - RadeonComposite(srcX, srcY, 0, 0, dstX, dstY, width, height); -} - -void -RadeonDoneBlend(void) -{ - RadeonDoneComposite(); }