diff options
author | Alex Deucher <alex@samba.(none)> | 2008-01-16 16:55:42 -0500 |
---|---|---|
committer | Alex Deucher <alex@samba.(none)> | 2008-01-16 16:55:42 -0500 |
commit | 3c72b100bcfacee600644669b586e86cfd32754e (patch) | |
tree | fe298f56e0f2e10383c63adb085c005739700256 | |
parent | 2ba3562d2af911fdd90881049599e239d27260bc (diff) |
R300: First pass at render accel
This first pass is pretty limited. All it currently supports
is transforms for rotation. No blending yet.
Based on inital implementation from Wolke Liu with
additional lock-up fixes by Dave Airlie.
-rw-r--r-- | src/radeon_commonfuncs.c | 134 | ||||
-rw-r--r-- | src/radeon_crtc.c | 2 | ||||
-rw-r--r-- | src/radeon_exa.c | 17 | ||||
-rw-r--r-- | src/radeon_exa_funcs.c | 9 | ||||
-rw-r--r-- | src/radeon_exa_render.c | 404 | ||||
-rw-r--r-- | src/radeon_reg.h | 203 |
6 files changed, 755 insertions, 14 deletions
diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c index a1802f86..23a849b7 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -58,7 +58,139 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) info->texW[0] = info->texH[0] = info->texW[1] = info->texH[1] = 1; if (info->ChipFamily >= CHIP_FAMILY_R300) { - /* Unimplemented */ + BEGIN_ACCEL(3); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); + OUT_ACCEL_REG(R300_WAIT_UNTIL, 0x30000); + FINISH_ACCEL(); + + BEGIN_ACCEL(3); + OUT_ACCEL_REG(R300_GB_TILE_CONFIG, 0x10011); + OUT_ACCEL_REG(R300_GB_SELECT,0x0); + OUT_ACCEL_REG(R300_GB_ENABLE, 0x0); + FINISH_ACCEL(); + + BEGIN_ACCEL(3); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); + OUT_ACCEL_REG(R300_WAIT_UNTIL, 0x30000); + FINISH_ACCEL(); + + BEGIN_ACCEL(5); + OUT_ACCEL_REG(R300_GB_AA_CONFIG, 0x0); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); + OUT_ACCEL_REG(R300_GB_MSPOS0, 0x78888888); + OUT_ACCEL_REG(R300_GB_MSPOS1, 0x08888888); + FINISH_ACCEL(); + + BEGIN_ACCEL(4); + OUT_ACCEL_REG(R300_GA_POLY_MODE, 0x120); + OUT_ACCEL_REG(R300_GA_ROUND_MODE, 0x5); + OUT_ACCEL_REG(R300_GA_COLOR_CONTROL, 0xAAAA); + OUT_ACCEL_REG(R300_GA_OFFSET, 0x0); + FINISH_ACCEL(); + + BEGIN_ACCEL(26); + OUT_ACCEL_REG(R300_VAP_CNTL_STATUS, 0x0); + OUT_ACCEL_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); + OUT_ACCEL_REG(R300_VAP_CNTL, 0x300456); + OUT_ACCEL_REG(R300_VAP_VTE_CNTL, 0x300); + OUT_ACCEL_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0x0); + OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_0, 0x6a014001); + OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0xf688f688); + OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_0, 0x100400); + OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_1, 0x1); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f00203); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10001); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f02203); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10141); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141); + OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141); + + OUT_ACCEL_REG(R300_VAP_PVS_FLOW_CNTL_OPC, 0x0); + OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_0, 0x1); + OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_1, 0x2); + + OUT_ACCEL_REG(R300_VAP_GB_VERT_CLIP_ADJ, 0x3f800000); + OUT_ACCEL_REG(R300_VAP_GB_VERT_DISC_ADJ, 0x3f800000); + OUT_ACCEL_REG(R300_VAP_GB_HORZ_CLIP_ADJ, 0x3f800000); + OUT_ACCEL_REG(R300_VAP_GB_HORZ_DISC_ADJ, 0x3f800000); + OUT_ACCEL_REG(R300_VAP_CLIP_CNTL, 0x10000); + FINISH_ACCEL(); + + BEGIN_ACCEL(7); + OUT_ACCEL_REG(R300_SU_TEX_WRAP, 0x0); + OUT_ACCEL_REG(R300_SU_POLY_OFFSET_ENABLE, 0x0); + OUT_ACCEL_REG(R300_SU_CULL_MODE, 0x4); + OUT_ACCEL_REG(R300_SU_DEPTH_SCALE, 0x4b7fffff); + OUT_ACCEL_REG(R300_SU_DEPTH_OFFSET, 0x0); + OUT_ACCEL_REG(R300_RS_COUNT, 0x40002); + OUT_ACCEL_REG(R300_RS_IP_0, 0x1610000); + FINISH_ACCEL(); + + BEGIN_ACCEL(5); + OUT_ACCEL_REG(R300_US_W_FMT, 0x0); + OUT_ACCEL_REG(R300_US_OUT_FMT_1, 0x1B0F); + OUT_ACCEL_REG(R300_US_OUT_FMT_2, 0x1B0F); + OUT_ACCEL_REG(R300_US_OUT_FMT_3, 0x1B0F); + OUT_ACCEL_REG(R300_US_OUT_FMT_0, 0x1B01); + FINISH_ACCEL(); + + BEGIN_ACCEL(2); + OUT_ACCEL_REG(R300_RS_INST_COUNT, 0xC0); + OUT_ACCEL_REG(R300_RS_INST_0, 0x8); + FINISH_ACCEL(); + + BEGIN_ACCEL(12); + OUT_ACCEL_REG(R300_US_CONFIG, 0x8); + OUT_ACCEL_REG(R300_US_PIXSIZE, 0x0); + OUT_ACCEL_REG(R300_US_CODE_OFFSET, 0x40040); + OUT_ACCEL_REG(R300_US_CODE_ADDR_0, 0x0); + OUT_ACCEL_REG(R300_US_CODE_ADDR_1, 0x0); + OUT_ACCEL_REG(R300_US_CODE_ADDR_2, 0x0); + OUT_ACCEL_REG(R300_US_CODE_ADDR_3, 0x400000); + OUT_ACCEL_REG(R300_US_TEX_INST_0, 0x8000); + OUT_ACCEL_REG(R300_US_ALU_RGB_ADDR_0, 0x1f800000); + OUT_ACCEL_REG(R300_US_ALU_RGB_INST_0, 0x50a80); + OUT_ACCEL_REG(R300_US_ALU_ALPHA_ADDR_0, 0x1800000); + OUT_ACCEL_REG(R300_US_ALU_ALPHA_INST_0, 0x00040889); + FINISH_ACCEL(); + + BEGIN_ACCEL(3); + OUT_ACCEL_REG(R300_FG_DEPTH_SRC, 0x0); + OUT_ACCEL_REG(R300_FG_FOG_BLEND, 0x0); + OUT_ACCEL_REG(R300_FG_ALPHA_FUNC, 0x0); + FINISH_ACCEL(); + + BEGIN_ACCEL(12); + OUT_ACCEL_REG(R300_RB3D_ZSTENCILCNTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); + OUT_ACCEL_REG(R300_RB3D_BW_CNTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_ZCNTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_ZTOP, 0x0); + OUT_ACCEL_REG(R300_RB3D_ROPCNTL, 0x0); + + OUT_ACCEL_REG(R300_RB3D_AARESOLVE_CTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_COLOR_CHANNEL_MASK, 0xf); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + OUT_ACCEL_REG(R300_RB3D_CCTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_DITHER_CTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + FINISH_ACCEL(); + + BEGIN_ACCEL(7); + OUT_ACCEL_REG(R300_SC_EDGERULE, 0xA5294A5); + OUT_ACCEL_REG(R300_SC_SCISSOR0, 0x0); + OUT_ACCEL_REG(R300_SC_SCISSOR1, 0x3ffffff); + OUT_ACCEL_REG(R300_SC_CLIP_0_A, 0x880440); + OUT_ACCEL_REG(R300_SC_CLIP_0_B, 0xff0ff0); + OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA); + OUT_ACCEL_REG(R300_SC_SCREENDOOR, 0xffffff); + FINISH_ACCEL(); } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || (info->ChipFamily == CHIP_FAMILY_RV280) || (info->ChipFamily == CHIP_FAMILY_RS300) || diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c index 585b452e..e1e45502 100644 --- a/src/radeon_crtc.c +++ b/src/radeon_crtc.c @@ -356,7 +356,7 @@ radeon_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length, * Allocates memory for a locked-in-framebuffer shadow of the given * width and height for this CRTC's rotated shadow framebuffer. */ - + static void * radeon_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) { diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 4da4841a..3b0c734d 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -105,6 +105,23 @@ RADEONLog2(int val) return bits - 1; } +static __inline__ int +RADEONPow2(int num) +{ + int pot = 2; + + if (num <= 2) + return num; + + while (pot < num) { + pot *= 2; + } + + return pot; +} + + + static __inline__ CARD32 F_TO_DW(float val) { union { diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index 67c31478..b27a2666 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -534,8 +534,13 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) #ifdef RENDER if (info->RenderAccel) { if (info->ChipFamily >= CHIP_FAMILY_R300) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " - "unsupported on R300 type cards and newer.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " + "enabled for R300 type cards.\n"); + info->exa->CheckComposite = R300CheckComposite; + info->exa->PrepareComposite = + FUNC_NAME(R300PrepareComposite); + info->exa->Composite = FUNC_NAME(RadeonComposite); + info->exa->DoneComposite = RadeonDoneComposite; } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || (info->ChipFamily == CHIP_FAMILY_RV280) || (info->ChipFamily == CHIP_FAMILY_RS300) || diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c index eae69c49..c642aff3 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -121,6 +121,17 @@ static struct formatinfo R200TexFormats[] = { {PICT_a8, R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP}, }; +static struct formatinfo R300TexFormats[] = { + {PICT_a8r8g8b8, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)}, + {PICT_x8r8g8b8, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)}, + {PICT_a8b8g8r8, R300_EASY_TX_FORMAT(Z, Y, X, W, W8Z8Y8X8)}, + {PICT_x8b8g8r8, R300_EASY_TX_FORMAT(Z, Y, X, ONE, W8Z8Y8X8)}, + {PICT_r5g6b5, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)}, + {PICT_a1r5g5b5, R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5)}, + {PICT_x1r5g5b5, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W1Z5Y5X5)}, + {PICT_a8, R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8)}, +}; + /* Common Radeon setup code */ static Bool RADEONGetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) @@ -148,6 +159,31 @@ static Bool RADEONGetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) return TRUE; } +static Bool R300GetDestFormat(PicturePtr pDstPicture, CARD32 *dst_format) +{ + switch (pDstPicture->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + *dst_format = R300_COLORFORMAT_ARGB8888; + break; + case PICT_r5g6b5: + *dst_format = R300_COLORFORMAT_RGB565; + break; + case PICT_a1r5g5b5: + case PICT_x1r5g5b5: + *dst_format = R300_COLORFORMAT_ARGB1555; + break; + case PICT_a8: + *dst_format = R300_COLORFORMAT_I8; + break; + default: + ErrorF("Unsupported dest format 0x%x\n", + (int)pDstPicture->format); + return FALSE; + } + return TRUE; +} + static CARD32 RADEONGetBlendCntl(int op, PicturePtr pMask, CARD32 dst_format) { CARD32 sblend, dblend; @@ -706,9 +742,304 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture, return TRUE; } -#ifdef ACCEL_CP +#ifdef ONLY_ONCE + +static Bool R300CheckCompositeTexture(PicturePtr pPict, int unit) +{ + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i; + + if ((w > 0x7ff) || (h > 0x7ff)) + RADEON_FALLBACK(("Picture w/h too large (%dx%d)\n", w, h)); + + for (i = 0; i < sizeof(R300TexFormats) / sizeof(R300TexFormats[0]); i++) + { + if (R300TexFormats[i].fmt == pPict->format) + break; + } + if (i == sizeof(R300TexFormats) / sizeof(R300TexFormats[0])) + RADEON_FALLBACK(("Unsupported picture format 0x%x\n", + (int)pPict->format)); + + if (pPict->repeat && ((w & (w - 1)) != 0 || (h & (h - 1)) != 0)) + RADEON_FALLBACK(("NPOT repeat unsupported (%dx%d)\n", w, h)); + + if (pPict->filter != PictFilterNearest && + pPict->filter != PictFilterBilinear) + RADEON_FALLBACK(("Unsupported filter 0x%x\n", pPict->filter)); + + return TRUE; +} + +#endif /* ONLY_ONCE */ + +static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix, + int unit) +{ + RINFO_FROM_SCREEN(pPix->drawable.pScreen); + CARD32 txfilter, txformat0, txformat1, txoffset, txpitch; + int w = pPict->pDrawable->width; + int h = pPict->pDrawable->height; + int i, pixel_shift; + ACCEL_PREAMBLE(); + + TRACE; + + txpitch = exaGetPixmapPitch(pPix); + txoffset = exaGetPixmapOffset(pPix) + info->fbLocation; + + if ((txoffset & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + if ((txpitch & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); + + pixel_shift = pPix->drawable.bitsPerPixel >> 4; + txpitch >>= pixel_shift; + txpitch -= 1; + + if (RADEONPixmapIsColortiled(pPix)) + txoffset |= R300_MACRO_TILE; + + for (i = 0; i < sizeof(R300TexFormats) / sizeof(R300TexFormats[0]); i++) + { + if (R300TexFormats[i].fmt == pPict->format) + break; + } + + txformat1 = R300TexFormats[i].card_fmt; + + txformat0 = (((RADEONPow2(w) - 1) << R300_TXWIDTH_SHIFT) | + ((RADEONPow2(h) - 1) << R300_TXHEIGHT_SHIFT)); + + if (pPict->repeat) { + ErrorF("repeat\n"); + if ((h != 1) && + (((w * pPix->drawable.bitsPerPixel / 8 + 31) & ~31) != txpitch)) + RADEON_FALLBACK(("Width %d and pitch %u not compatible for repeat\n", + w, (unsigned)txpitch)); + } else + txformat0 |= R300_TXPITCH_EN; + + + info->texW[unit] = RADEONPow2(w); + info->texH[unit] = RADEONPow2(h); + + switch (pPict->filter) { + case PictFilterNearest: + txfilter = (R300_TX_MAG_FILTER_NEAREST | R300_TX_MIN_FILTER_NEAREST); + break; + case PictFilterBilinear: + txfilter = (R300_TX_MAG_FILTER_LINEAR | R300_TX_MIN_FILTER_LINEAR); + break; + default: + RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); + } + + BEGIN_ACCEL(6); + OUT_ACCEL_REG(R300_TX_FILTER0_0 + (unit * 4), txfilter); + OUT_ACCEL_REG(R300_TX_FILTER1_0 + (unit * 4), 0x0); + OUT_ACCEL_REG(R300_TX_FORMAT0_0 + (unit * 4), txformat0); + OUT_ACCEL_REG(R300_TX_FORMAT1_0 + (unit * 4), txformat1); + OUT_ACCEL_REG(R300_TX_FORMAT2_0 + (unit * 4), txpitch); + OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset); + FINISH_ACCEL(); + + if (pPict->transform != 0) { + is_transform[unit] = TRUE; + transform[unit] = pPict->transform; + } else { + is_transform[unit] = FALSE; + } + + return TRUE; +} + +#ifdef ONLY_ONCE + +static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + CARD32 tmp1; + ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; + PixmapPtr pSrcPixmap, pDstPixmap; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + TRACE; + + /* Check for unsupported compositing operations. */ + if (op >= sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0])) + RADEON_FALLBACK(("Unsupported Composite op 0x%x\n", op)); + +#if 1 + /* Throw out cases that aren't going to be our rotation first */ + if (pMaskPicture != NULL || op != PictOpSrc || pSrcPicture->pDrawable == NULL) + RADEON_FALLBACK(("Junk driver\n")); + + if (pSrcPicture->pDrawable->type != DRAWABLE_WINDOW || + pDstPicture->pDrawable->type != DRAWABLE_PIXMAP) { + RADEON_FALLBACK(("bad drawable\n")); + } + + pSrcPixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) pSrcPicture->pDrawable); + pDstPixmap = (PixmapPtr)pDstPicture->pDrawable; + + /* Check if the dest is one of our shadow pixmaps */ + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if (crtc->rotatedPixmap == pDstPixmap) + break; + } + if (i == xf86_config->num_crtc) + RADEON_FALLBACK(("no rotated pixmap\n")); + + if (pSrcPixmap != pScreen->GetScreenPixmap(pScreen)) + RADEON_FALLBACK(("src not screen\n")); +#endif + + + if (pMaskPicture != NULL && pMaskPicture->componentAlpha) { + /* Check if it's component alpha that relies on a source alpha and on + * the source value. We can only get one of those into the single + * source value that we get to blend with. + */ + if (RadeonBlendOp[op].src_alpha && + (RadeonBlendOp[op].blend_cntl & RADEON_SRC_BLEND_MASK) != + RADEON_SRC_BLEND_GL_ZERO) + { + RADEON_FALLBACK(("Component alpha not supported with source " + "alpha and source value blending.\n")); + } + } + + if (!R300CheckCompositeTexture(pSrcPicture, 0)) + return FALSE; + if (pMaskPicture != NULL && !R300CheckCompositeTexture(pMaskPicture, 1)) + return FALSE; + + if (!R300GetDestFormat(pDstPicture, &tmp1)) + return FALSE; + + return TRUE; + +} +#endif /* ONLY_ONCE */ + +static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, + PicturePtr pMaskPicture, PicturePtr pDstPicture, + PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) +{ + RINFO_FROM_SCREEN(pDst->drawable.pScreen); + CARD32 dst_format, dst_offset, dst_pitch; + CARD32 txenable, colorpitch; + /*CARD32 blendcntl, cblend, ablend;*/ + int pixel_shift; + ACCEL_PREAMBLE(); + + TRACE; + + if (!info->XInited3D) + RADEONInit3DEngine(pScrn); + + R300GetDestFormat(pDstPicture, &dst_format); + pixel_shift = pDst->drawable.bitsPerPixel >> 4; + + dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation; + dst_pitch = exaGetPixmapPitch(pDst); + colorpitch = dst_pitch >> pixel_shift; + + if (RADEONPixmapIsColortiled(pDst)) + colorpitch |= R300_COLORTILE; + + colorpitch |= dst_format; + + if ((dst_offset & 0x0f) != 0) + RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); + if (((dst_pitch >> pixel_shift) & 0x7) != 0) + RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); + + if (!FUNC_NAME(R300TextureSetup)(pSrcPicture, pSrc, 0)) + return FALSE; + txenable = R300_TEX_0_ENABLE; + + if (pMask != NULL) { + if (!FUNC_NAME(R300TextureSetup)(pMaskPicture, pMask, 1)) + return FALSE; + txenable |= R300_TEX_1_ENABLE; + } else { + is_transform[1] = FALSE; + } -#define VTX_DWORD_COUNT 6 + RADEON_SWITCH_TO_3D(); + + BEGIN_ACCEL(6); + OUT_ACCEL_REG(R300_TX_INVALTAGS, 0x0); + OUT_ACCEL_REG(R300_TX_ENABLE, txenable); + + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch); + + OUT_ACCEL_REG(R300_RB3D_BLENDCNTL, 0x0); + OUT_ACCEL_REG(R300_RB3D_ABLENDCNTL, 0x0); + +#if 0 + /* 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. + * If we're doing component alpha where the source for blending is going to + * be the source alpha (and there's no source value used), we have to zero + * the source's color values. + */ + 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 || + (pMask && pMaskPicture->componentAlpha && RadeonBlendOp[op].src_alpha)) + { + 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_A_R0_ALPHA; + + if (pMask) { + if (pMaskPicture->componentAlpha && + pDstPicture->format != PICT_a8) + cblend |= R200_TXC_ARG_B_R1_COLOR; + else + cblend |= R200_TXC_ARG_B_R1_ALPHA; + ablend |= R200_TXA_ARG_B_R1_ALPHA; + } else { + cblend |= R200_TXC_ARG_B_ZERO | R200_TXC_COMP_ARG_B; + ablend |= R200_TXA_ARG_B_ZERO | R200_TXA_COMP_ARG_B; + } + + OUT_ACCEL_REG(R200_PP_TXCBLEND_0, cblend); + OUT_ACCEL_REG(R200_PP_TXCBLEND2_0, + R200_TXC_CLAMP_0_1 | R200_TXC_OUTPUT_REG_R0); + OUT_ACCEL_REG(R200_PP_TXABLEND_0, ablend); + OUT_ACCEL_REG(R200_PP_TXABLEND2_0, + R200_TXA_CLAMP_0_1 | R200_TXA_OUTPUT_REG_R0); + + /* Op operator. */ + blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format); + OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blendcntl); +#endif + + FINISH_ACCEL(); + + return TRUE; +} + +#define VTX_COUNT 6 +#define R300_VTX_COUNT 4 + +#ifdef ACCEL_CP #define VTX_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \ do { \ @@ -720,9 +1051,15 @@ do { \ OUT_RING_F(_maskY); \ } while (0) -#else /* ACCEL_CP */ +#define VTX_OUT4(_dstX, _dstY, _srcX, _srcY) \ +do { \ + OUT_RING_F(_dstX); \ + OUT_RING_F(_dstY); \ + OUT_RING_F(_srcX); \ + OUT_RING_F(_srcY); \ +} while (0) -#define VTX_REG_COUNT 6 +#else /* ACCEL_CP */ #define VTX_OUT(_dstX, _dstY, _srcX, _srcY, _maskX, _maskY) \ do { \ @@ -734,6 +1071,14 @@ do { \ OUT_ACCEL_REG_F(RADEON_SE_PORT_DATA0, _maskY); \ } while (0) +#define VTX_OUT4(_dstX, _dstY, _srcX, _srcY) \ +do { \ + OUT_ACCEL_REG_F(RADEON_SE_PORT_DATA0, _dstX); \ + OUT_ACCEL_REG_F(RADEON_SE_PORT_DATA0, _dstY); \ + OUT_ACCEL_REG_F(RADEON_SE_PORT_DATA0, _srcX); \ + OUT_ACCEL_REG_F(RADEON_SE_PORT_DATA0, _srcY); \ +} while (0) + #endif /* !ACCEL_CP */ #ifdef ONLY_ONCE @@ -759,6 +1104,7 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, { RINFO_FROM_SCREEN(pDst->drawable.pScreen); int srcXend, srcYend, maskXend, maskYend; + int vtx_count; xPointFixed srcTopLeft, srcTopRight, srcBottomLeft, srcBottomRight; xPointFixed maskTopLeft, maskTopRight, maskBottomLeft, maskBottomRight; ACCEL_PREAMBLE(); @@ -766,7 +1112,7 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, ENTER_DRAW(0); /*ErrorF("RadeonComposite (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n", - srcX, srcY, maskX, maskY,dstX, dstY, w, h);*/ + srcX, srcY, maskX, maskY,dstX, dstY, w, h);*/ srcXend = srcX + w; srcYend = srcY + h; @@ -804,11 +1150,19 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, transformPoint(transform[1], &maskBottomRight); } + vtx_count = (info->ChipFamily >= CHIP_FAMILY_R300) ? R300_VTX_COUNT : VTX_COUNT; + + if (IS_R300_VARIANT) { + BEGIN_ACCEL(1); + OUT_ACCEL_REG(R300_VAP_VTX_SIZE, vtx_count); + FINISH_ACCEL(); + } + #ifdef ACCEL_CP if (info->ChipFamily < CHIP_FAMILY_R200) { - BEGIN_RING(4 * VTX_DWORD_COUNT + 3); + BEGIN_RING(4 * vtx_count + 3); OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, - 4 * VTX_DWORD_COUNT + 1)); + 4 * vtx_count + 1)); OUT_RING(RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_ST0 | RADEON_CP_VC_FRMT_ST1); @@ -818,16 +1172,24 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); } else { - BEGIN_RING(4 * VTX_DWORD_COUNT + 2); + if (IS_R300_VARIANT) + BEGIN_RING(4 * vtx_count + 6); + else + BEGIN_RING(4 * vtx_count + 2); + OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, - 4 * VTX_DWORD_COUNT)); + 4 * vtx_count)); OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN | RADEON_CP_VC_CNTL_PRIM_WALK_RING | (4 << RADEON_CP_VC_CNTL_NUM_SHIFT)); } #else /* ACCEL_CP */ - BEGIN_ACCEL(1 + VTX_REG_COUNT * 4); + if (IS_R300_VARIANT) + BEGIN_ACCEL(3 + vtx_count * 4); + else + BEGIN_ACCEL(1 + vtx_count * 4); + if (info->ChipFamily < CHIP_FAMILY_R200) { OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_TRIANGLE_FAN | RADEON_VF_PRIM_WALK_DATA | @@ -846,6 +1208,22 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, VTX_OUT(dstX, dstY + h, srcX, srcYend, maskX, maskYend); VTX_OUT(dstX + w, dstY + h, srcXend, srcYend, maskXend, maskYend); VTX_OUT(dstX + w, dstY, srcXend, srcY, maskXend, maskY); + } else if (IS_R300_VARIANT) { + VTX_OUT4((float)dstX, (float)dstY, + xFixedToFloat(srcTopLeft.x) / info->texW[0], + xFixedToFloat(srcTopLeft.y) / info->texH[0]); + + VTX_OUT4((float)dstX, (float)(dstY + h), + xFixedToFloat(srcBottomLeft.x) / info->texW[0], + xFixedToFloat(srcBottomLeft.y) / info->texH[0]); + + VTX_OUT4((float)(dstX + w), (float)(dstY + h), + xFixedToFloat(srcBottomRight.x) / info->texW[0], + xFixedToFloat(srcBottomRight.y) / info->texH[0]); + + VTX_OUT4((float)(dstX + w), (float)dstY, + xFixedToFloat(srcTopRight.x) / info->texW[0], + xFixedToFloat(srcTopRight.y) / info->texH[0]); } else { VTX_OUT((float)dstX, (float)dstY, xFixedToFloat(srcTopLeft.x) / info->texW[0], xFixedToFloat(srcTopLeft.y) / info->texH[0], @@ -861,6 +1239,11 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, xFixedToFloat(maskTopRight.x) / info->texW[1], xFixedToFloat(maskTopRight.y) / info->texH[1]); } + if (IS_R300_VARIANT) { + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); + } + #ifdef ACCEL_CP ADVANCE_RING(); #else @@ -870,6 +1253,7 @@ static void FUNC_NAME(RadeonComposite)(PixmapPtr pDst, LEAVE_DRAW(0); } #undef VTX_OUT +#undef VTX_OUT4 #ifdef ONLY_ONCE static void RadeonDoneComposite(PixmapPtr pDst) diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 09be2295..174fda4a 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -3741,4 +3741,207 @@ #define R600_CONFIG_MEMSIZE 0x5428 #define R600_CONFIG_F0_BASE 0x542C #define R600_CONFIG_APER_SIZE 0x5430 + +#define R300_GB_TILE_CONFIG 0x4018 +#define R300_GB_SELECT 0x401c +#define R300_GB_ENABLE 0x4008 +#define R300_GB_AA_CONFIG 0x4020 +#define R300_GB_MSPOS0 0x4010 +#define R300_GB_MSPOS1 0x4014 + +#define R300_GA_POLY_MODE 0x4288 +#define R300_GA_ROUND_MODE 0x428c +#define R300_GA_COLOR_CONTROL 0x4278 +#define R300_GA_OFFSET 0x4290 + +#define R300_VAP_CNTL_STATUS 0x2140 +#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284 +#define R300_VAP_CNTL 0x2080 +#define R300_VAP_VTE_CNTL 0x20B0 +#define R300_VAP_PSC_SGN_NORM_CNTL 0x21DC +#define R300_VAP_PROG_STREAM_CNTL_0 0x2150 +#define R300_VAP_PROG_STREAM_CNTL_EXT_0 0x21e0 +#define R300_VAP_PVS_CODE_CNTL_0 0x22D0 +#define R300_VAP_PVS_CODE_CNTL_1 0x22D8 +#define R300_VAP_PVS_VECTOR_INDX_REG 0x2200 +#define R300_VAP_PVS_VECTOR_DATA_REG 0x2204 +#define R300_VAP_PVS_FLOW_CNTL_OPC 0x22DC +#define R300_VAP_OUT_VTX_FMT_0 0x2090 +#define R300_VAP_OUT_VTX_FMT_1 0x2094 +#define R300_VAP_VTX_SIZE 0x20b4 +#define R300_VAP_GB_VERT_CLIP_ADJ 0x2220 +#define R300_VAP_GB_VERT_DISC_ADJ 0x2224 +#define R300_VAP_GB_HORZ_CLIP_ADJ 0x2228 +#define R300_VAP_GB_HORZ_DISC_ADJ 0x222c +#define R300_VAP_CLIP_CNTL 0x221c + +#define R300_SU_TEX_WRAP 0x42a0 +#define R300_SU_POLY_OFFSET_ENABLE 0x42b4 +#define R300_SU_CULL_MODE 0x42b8 +#define R300_SU_DEPTH_SCALE 0x42c0 +#define R300_SU_DEPTH_OFFSET 0x42c4 + +#define R300_RS_COUNT 0x4300 +#define R300_RS_IP_0 0x4310 +#define R300_RS_INST_COUNT 0x4304 +#define R300_RS_INST_0 0x4330 + +#define R300_TX_INVALTAGS 0x4100 +#define R300_TX_FILTER0_0 0x4400 +# define R300_TX_MAG_FILTER_NEAREST (1 << 9) +# define R300_TX_MIN_FILTER_NEAREST (1 << 11) +# define R300_TX_MAG_FILTER_LINEAR (2 << 9) +# define R300_TX_MIN_FILTER_LINEAR (2 << 11) +#define R300_TX_FILTER1_0 0x4440 +#define R300_TX_FORMAT0_0 0x4480 +# define R300_TXWIDTH_SHIFT 0 +# define R300_TXHEIGHT_SHIFT 11 +# define R300_NUM_LEVELS_SHIFT 26 +# define R300_NUM_LEVELS_MASK 0x +# define R300_TXPROJECTED (1 << 30) +# define R300_TXPITCH_EN (1 << 31) +#define R300_TX_FORMAT1_0 0x44c0 +# define R300_TX_FORMAT_X8 0x0 +# define R300_TX_FORMAT_X16 0x1 +# define R300_TX_FORMAT_Y4X4 0x2 +# define R300_TX_FORMAT_Y8X8 0x3 +# define R300_TX_FORMAT_Y16X16 0x4 +# define R300_TX_FORMAT_Z3Y3X2 0x5 +# define R300_TX_FORMAT_Z5Y6X5 0x6 +# define R300_TX_FORMAT_Z6Y5X5 0x7 +# define R300_TX_FORMAT_Z11Y11X10 0x8 +# define R300_TX_FORMAT_Z10Y11X11 0x9 +# define R300_TX_FORMAT_W4Z4Y4X4 0xA +# define R300_TX_FORMAT_W1Z5Y5X5 0xB +# define R300_TX_FORMAT_W8Z8Y8X8 0xC +# define R300_TX_FORMAT_W2Z10Y10X10 0xD +# define R300_TX_FORMAT_W16Z16Y16X16 0xE +# define R300_TX_FORMAT_DXT1 0xF +# define R300_TX_FORMAT_DXT3 0x10 +# define R300_TX_FORMAT_DXT5 0x11 +# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ +# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ +# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ +# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ +# define R300_TX_FORMAT_X24_Y8 0x1e +# define R300_TX_FORMAT_X32 0x1e + /* Floating point formats */ + /* Note - hardware supports both 16 and 32 bit floating point */ +# define R300_TX_FORMAT_FL_I16 0x18 +# define R300_TX_FORMAT_FL_I16A16 0x19 +# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A +# define R300_TX_FORMAT_FL_I32 0x1B +# define R300_TX_FORMAT_FL_I32A32 0x1C +# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D + /* alpha modes, convenience mostly */ + /* if you have alpha, pick constant appropriate to the + number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ +# define R300_TX_FORMAT_ALPHA_1CH 0x000 +# define R300_TX_FORMAT_ALPHA_2CH 0x200 +# define R300_TX_FORMAT_ALPHA_4CH 0x600 +# define R300_TX_FORMAT_ALPHA_NONE 0xA00 + /* Swizzling */ + /* constants */ +# define R300_TX_FORMAT_X 0 +# define R300_TX_FORMAT_Y 1 +# define R300_TX_FORMAT_Z 2 +# define R300_TX_FORMAT_W 3 +# define R300_TX_FORMAT_ZERO 4 +# define R300_TX_FORMAT_ONE 5 + /* 2.0*Z, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_Z 6 + /* 2.0*W, everything above 1.0 is set to 0.0 */ +# define R300_TX_FORMAT_CUT_W 7 + +# define R300_TX_FORMAT_B_SHIFT 18 +# define R300_TX_FORMAT_G_SHIFT 15 +# define R300_TX_FORMAT_R_SHIFT 12 +# define R300_TX_FORMAT_A_SHIFT 9 + + /* Convenience macro to take care of layout and swizzling */ +# define R300_EASY_TX_FORMAT(B, G, R, A, FMT) ( \ + ((R300_TX_FORMAT_##B)<<R300_TX_FORMAT_B_SHIFT) \ + | ((R300_TX_FORMAT_##G)<<R300_TX_FORMAT_G_SHIFT) \ + | ((R300_TX_FORMAT_##R)<<R300_TX_FORMAT_R_SHIFT) \ + | ((R300_TX_FORMAT_##A)<<R300_TX_FORMAT_A_SHIFT) \ + | (R300_TX_FORMAT_##FMT) \ + ) + +#define R300_TX_FORMAT2_0 0x4500 +#define R300_TX_OFFSET_0 0x4540 +# define R300_ENDIAN_SWAP_16_BIT (1 << 0) +# define R300_ENDIAN_SWAP_32_BIT (2 << 0) +# define R300_ENDIAN_SWAP_HALF_DWORD (3 << 0) +# define R300_MACRO_TILE (1 << 2); + +#define R300_TX_ENABLE 0x4104 +# define R300_TEX_0_ENABLE (1 << 0) +# define R300_TEX_1_ENABLE (1 << 1) + +#define R300_US_W_FMT 0x46b4 +#define R300_US_OUT_FMT_1 0x46a8 +#define R300_US_OUT_FMT_2 0x46ac +#define R300_US_OUT_FMT_3 0x46b0 +#define R300_US_OUT_FMT_0 0x46a4 +#define R300_US_CONFIG 0x4600 +#define R300_US_PIXSIZE 0x4604 +#define R300_US_CODE_OFFSET 0x4608 +#define R300_US_CODE_ADDR_0 0x4610 +#define R300_US_CODE_ADDR_1 0x4614 +#define R300_US_CODE_ADDR_2 0x4618 +#define R300_US_CODE_ADDR_3 0x461c +#define R300_US_TEX_INST_0 0x4620 +#define R300_US_ALU_RGB_ADDR_0 0x46c0 +#define R300_US_ALU_RGB_INST_0 0x48c0 +#define R300_US_ALU_ALPHA_ADDR_0 0x47c0 +#define R300_US_ALU_ALPHA_INST_0 0x49c0 + +#define R300_FG_DEPTH_SRC 0x4bd8 +#define R300_FG_FOG_BLEND 0x4bc0 +#define R300_FG_ALPHA_FUNC 0x4bd4 + +#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c +#define R300_RB3D_ZCACHE_CTLSTAT 0x4f18 +#define R300_WAIT_UNTIL 0x1720 +#define R300_RB3D_ZSTENCILCNTL 0x4f04 +#define R300_RB3D_ZCACHE_CTLSTAT 0x4f18 +#define R300_RB3D_BW_CNTL 0x4f1c +#define R300_RB3D_ZCNTL 0x4f00 +#define R300_RB3D_ZTOP 0x4f14 +#define R300_RB3D_ROPCNTL 0x4e18 +#define R300_RB3D_BLENDCNTL 0x4e04 +#define R300_RB3D_ABLENDCNTL 0x4e08 +#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c +#define R300_RB3D_COLOROFFSET0 0x4e28 +#define R300_RB3D_COLORPITCH0 0x4e38 +# define R300_COLORTILE (1 << 16) +# define R300_COLORENDIAN_WORD (1 << 19) +# define R300_COLORENDIAN_DWORD (2 << 19) +# define R300_COLORENDIAN_HALF_DWORD (3 << 19) +# define R300_COLORFORMAT_ARGB1555 (3 << 21) +# define R300_COLORFORMAT_RGB565 (4 << 21) +# define R300_COLORFORMAT_ARGB8888 (6 << 21) +# define R300_COLORFORMAT_ARGB32323232 (7 << 21) +# define R300_COLORFORMAT_I8 (9 << 21) +# define R300_COLORFORMAT_ARGB16161616 (10 << 21) +# define R300_COLORFORMAT_VYUY (11 << 21) +# define R300_COLORFORMAT_YVYU (12 << 21) +# define R300_COLORFORMAT_UV88 (13 << 21) +# define R300_COLORFORMAT_ARGB4444 (15 << 21) + +#define R300_RB3D_AARESOLVE_CTL 0x4e88 +#define R300_RB3D_COLOR_CHANNEL_MASK 0x4e0c +#define R300_RB3D_COLOR_CLEAR_VALUE 0x4e14 +#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c +#define R300_RB3D_CCTL 0x4e00 +#define R300_RB3D_DITHER_CTL 0x4e50 + +#define R300_SC_EDGERULE 0x43a8 +#define R300_SC_SCISSOR0 0x43e0 +#define R300_SC_SCISSOR1 0x43e4 +#define R300_SC_CLIP_0_A 0x43b0 +#define R300_SC_CLIP_0_B 0x43b4 +#define R300_SC_CLIP_RULE 0x43d0 +#define R300_SC_SCREENDOOR 0x43e8 + #endif |