diff options
Diffstat (limited to 'src/gallium/drivers/radeonsi/si_state.c')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state.c | 663 |
1 files changed, 663 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 3e3a915457a..3141f36a4e5 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -25,6 +25,7 @@ */ #include "util/u_memory.h" +#include "util/u_framebuffer.h" #include "radeonsi_pipe.h" #include "si_state.h" #include "sid.h" @@ -193,6 +194,10 @@ static void si_set_blend_color(struct pipe_context *ctx, si_pm4_set_state(rctx, blend_color, pm4); } +/* + * Clipping, scissors and viewport + */ + static void si_set_clip_state(struct pipe_context *ctx, const struct pipe_clip_state *state) { @@ -265,6 +270,662 @@ static void si_set_viewport_state(struct pipe_context *ctx, si_pm4_set_state(rctx, viewport, viewport); } +/* + * format translation + */ +static uint32_t si_translate_colorformat(enum pipe_format format) +{ + switch (format) { + /* 8-bit buffers. */ + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_A8_UINT: + case PIPE_FORMAT_A8_SINT: + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_I8_UINT: + case PIPE_FORMAT_I8_SINT: + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_UINT: + case PIPE_FORMAT_L8_SINT: + case PIPE_FORMAT_L8_SRGB: + case PIPE_FORMAT_R8_UNORM: + case PIPE_FORMAT_R8_SNORM: + case PIPE_FORMAT_R8_UINT: + case PIPE_FORMAT_R8_SINT: + return V_028C70_COLOR_8; + + /* 16-bit buffers. */ + case PIPE_FORMAT_B5G6R5_UNORM: + return V_028C70_COLOR_5_6_5; + + case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: + return V_028C70_COLOR_1_5_5_5; + + case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B4G4R4X4_UNORM: + return V_028C70_COLOR_4_4_4_4; + + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_UINT: + case PIPE_FORMAT_L8A8_SINT: + case PIPE_FORMAT_L8A8_SRGB: + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8_UINT: + case PIPE_FORMAT_R8G8_SINT: + return V_028C70_COLOR_8_8; + + case PIPE_FORMAT_Z16_UNORM: + case PIPE_FORMAT_R16_UNORM: + case PIPE_FORMAT_R16_UINT: + case PIPE_FORMAT_R16_SINT: + case PIPE_FORMAT_R16_FLOAT: + case PIPE_FORMAT_R16G16_FLOAT: + return V_028C70_COLOR_16; + + /* 32-bit buffers. */ + case PIPE_FORMAT_A8B8G8R8_SRGB: + case PIPE_FORMAT_A8B8G8R8_UNORM: + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_B8G8R8A8_SRGB: + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_R8G8B8A8_SNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_R8G8B8X8_UNORM: + case PIPE_FORMAT_R8SG8SB8UX8U_NORM: + case PIPE_FORMAT_X8B8G8R8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8A8_SSCALED: + case PIPE_FORMAT_R8G8B8A8_USCALED: + case PIPE_FORMAT_R8G8B8A8_SINT: + case PIPE_FORMAT_R8G8B8A8_UINT: + return V_028C70_COLOR_8_8_8_8; + + case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_R10G10B10X2_SNORM: + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_B10G10R10A2_UINT: + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: + return V_028C70_COLOR_2_10_10_10; + + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return V_028C70_COLOR_8_24; + + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return V_028C70_COLOR_24_8; + + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + return V_028C70_COLOR_X24_8_32_FLOAT; + + case PIPE_FORMAT_R32_FLOAT: + case PIPE_FORMAT_Z32_FLOAT: + return V_028C70_COLOR_32; + + case PIPE_FORMAT_R16G16_SSCALED: + case PIPE_FORMAT_R16G16_UNORM: + case PIPE_FORMAT_R16G16_UINT: + case PIPE_FORMAT_R16G16_SINT: + return V_028C70_COLOR_16_16; + + case PIPE_FORMAT_R11G11B10_FLOAT: + return V_028C70_COLOR_10_11_11; + + /* 64-bit buffers. */ + case PIPE_FORMAT_R16G16B16_USCALED: + case PIPE_FORMAT_R16G16B16_SSCALED: + case PIPE_FORMAT_R16G16B16A16_UINT: + case PIPE_FORMAT_R16G16B16A16_SINT: + case PIPE_FORMAT_R16G16B16A16_USCALED: + case PIPE_FORMAT_R16G16B16A16_SSCALED: + case PIPE_FORMAT_R16G16B16A16_UNORM: + case PIPE_FORMAT_R16G16B16A16_SNORM: + case PIPE_FORMAT_R16G16B16_FLOAT: + case PIPE_FORMAT_R16G16B16A16_FLOAT: + return V_028C70_COLOR_16_16_16_16; + + case PIPE_FORMAT_R32G32_FLOAT: + case PIPE_FORMAT_R32G32_USCALED: + case PIPE_FORMAT_R32G32_SSCALED: + case PIPE_FORMAT_R32G32_SINT: + case PIPE_FORMAT_R32G32_UINT: + return V_028C70_COLOR_32_32; + + /* 128-bit buffers. */ + case PIPE_FORMAT_R32G32B32A32_SNORM: + case PIPE_FORMAT_R32G32B32A32_UNORM: + case PIPE_FORMAT_R32G32B32A32_SSCALED: + case PIPE_FORMAT_R32G32B32A32_USCALED: + case PIPE_FORMAT_R32G32B32A32_SINT: + case PIPE_FORMAT_R32G32B32A32_UINT: + case PIPE_FORMAT_R32G32B32A32_FLOAT: + return V_028C70_COLOR_32_32_32_32; + + /* YUV buffers. */ + case PIPE_FORMAT_UYVY: + case PIPE_FORMAT_YUYV: + /* 96-bit buffers. */ + case PIPE_FORMAT_R32G32B32_FLOAT: + /* 8-bit buffers. */ + case PIPE_FORMAT_L4A4_UNORM: + case PIPE_FORMAT_R4A4_UNORM: + case PIPE_FORMAT_A4R4_UNORM: + default: + return ~0U; /* Unsupported. */ + } +} + +static uint32_t si_translate_colorswap(enum pipe_format format) +{ + switch (format) { + /* 8-bit buffers. */ + case PIPE_FORMAT_L4A4_UNORM: + case PIPE_FORMAT_A4R4_UNORM: + return V_028C70_SWAP_ALT; + + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_A8_UINT: + case PIPE_FORMAT_A8_SINT: + case PIPE_FORMAT_R4A4_UNORM: + return V_028C70_SWAP_ALT_REV; + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UINT: + case PIPE_FORMAT_I8_SINT: + case PIPE_FORMAT_L8_UINT: + case PIPE_FORMAT_L8_SINT: + case PIPE_FORMAT_L8_SRGB: + case PIPE_FORMAT_R8_UNORM: + case PIPE_FORMAT_R8_SNORM: + case PIPE_FORMAT_R8_UINT: + case PIPE_FORMAT_R8_SINT: + return V_028C70_SWAP_STD; + + /* 16-bit buffers. */ + case PIPE_FORMAT_B5G6R5_UNORM: + return V_028C70_SWAP_STD_REV; + + case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: + return V_028C70_SWAP_ALT; + + case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B4G4R4X4_UNORM: + return V_028C70_SWAP_ALT; + + case PIPE_FORMAT_Z16_UNORM: + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_L8A8_UNORM: + case PIPE_FORMAT_L8A8_UINT: + case PIPE_FORMAT_L8A8_SINT: + case PIPE_FORMAT_L8A8_SRGB: + return V_028C70_SWAP_ALT; + case PIPE_FORMAT_R8G8_UNORM: + case PIPE_FORMAT_R8G8_UINT: + case PIPE_FORMAT_R8G8_SINT: + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_R16_UNORM: + case PIPE_FORMAT_R16_UINT: + case PIPE_FORMAT_R16_SINT: + case PIPE_FORMAT_R16_FLOAT: + return V_028C70_SWAP_STD; + + /* 32-bit buffers. */ + case PIPE_FORMAT_A8B8G8R8_SRGB: + return V_028C70_SWAP_STD_REV; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return V_028C70_SWAP_ALT; + + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + return V_028C70_SWAP_ALT; + + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + return V_028C70_SWAP_ALT_REV; + case PIPE_FORMAT_R8G8B8A8_SNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_R8G8B8A8_SSCALED: + case PIPE_FORMAT_R8G8B8A8_USCALED: + case PIPE_FORMAT_R8G8B8A8_SINT: + case PIPE_FORMAT_R8G8B8A8_UINT: + case PIPE_FORMAT_R8G8B8X8_UNORM: + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_A8B8G8R8_UNORM: + case PIPE_FORMAT_X8B8G8R8_UNORM: + /* case PIPE_FORMAT_R8SG8SB8UX8U_NORM: */ + return V_028C70_SWAP_STD_REV; + + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_R10G10B10X2_SNORM: + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: + return V_028C70_SWAP_STD; + + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_B10G10R10A2_UINT: + return V_028C70_SWAP_ALT; + + case PIPE_FORMAT_R11G11B10_FLOAT: + case PIPE_FORMAT_R32_FLOAT: + case PIPE_FORMAT_R32_UINT: + case PIPE_FORMAT_R32_SINT: + case PIPE_FORMAT_Z32_FLOAT: + case PIPE_FORMAT_R16G16_FLOAT: + case PIPE_FORMAT_R16G16_UNORM: + case PIPE_FORMAT_R16G16_UINT: + case PIPE_FORMAT_R16G16_SINT: + return V_028C70_SWAP_STD; + + /* 64-bit buffers. */ + case PIPE_FORMAT_R32G32_FLOAT: + case PIPE_FORMAT_R32G32_UINT: + case PIPE_FORMAT_R32G32_SINT: + case PIPE_FORMAT_R16G16B16A16_UNORM: + case PIPE_FORMAT_R16G16B16A16_SNORM: + case PIPE_FORMAT_R16G16B16A16_USCALED: + case PIPE_FORMAT_R16G16B16A16_SSCALED: + case PIPE_FORMAT_R16G16B16A16_UINT: + case PIPE_FORMAT_R16G16B16A16_SINT: + case PIPE_FORMAT_R16G16B16A16_FLOAT: + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + + /* 128-bit buffers. */ + case PIPE_FORMAT_R32G32B32A32_FLOAT: + case PIPE_FORMAT_R32G32B32A32_SNORM: + case PIPE_FORMAT_R32G32B32A32_UNORM: + case PIPE_FORMAT_R32G32B32A32_SSCALED: + case PIPE_FORMAT_R32G32B32A32_USCALED: + case PIPE_FORMAT_R32G32B32A32_SINT: + case PIPE_FORMAT_R32G32B32A32_UINT: + return V_028C70_SWAP_STD; + default: + R600_ERR("unsupported colorswap format %d\n", format); + return ~0U; + } + return ~0U; +} + +static uint32_t si_colorformat_endian_swap(uint32_t colorformat) +{ + if (R600_BIG_ENDIAN) { + switch(colorformat) { + /* 8-bit buffers. */ + case V_028C70_COLOR_8: + return V_028C70_ENDIAN_NONE; + + /* 16-bit buffers. */ + case V_028C70_COLOR_5_6_5: + case V_028C70_COLOR_1_5_5_5: + case V_028C70_COLOR_4_4_4_4: + case V_028C70_COLOR_16: + case V_028C70_COLOR_8_8: + return V_028C70_ENDIAN_8IN16; + + /* 32-bit buffers. */ + case V_028C70_COLOR_8_8_8_8: + case V_028C70_COLOR_2_10_10_10: + case V_028C70_COLOR_8_24: + case V_028C70_COLOR_24_8: + case V_028C70_COLOR_16_16: + return V_028C70_ENDIAN_8IN32; + + /* 64-bit buffers. */ + case V_028C70_COLOR_16_16_16_16: + return V_028C70_ENDIAN_8IN16; + + case V_028C70_COLOR_32_32: + return V_028C70_ENDIAN_8IN32; + + /* 128-bit buffers. */ + case V_028C70_COLOR_32_32_32_32: + return V_028C70_ENDIAN_8IN32; + default: + return V_028C70_ENDIAN_NONE; /* Unsupported. */ + } + } else { + return V_028C70_ENDIAN_NONE; + } +} + +static uint32_t si_translate_dbformat(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + return V_028040_Z_16; + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return V_028040_Z_24; /* XXX no longer supported on SI */ + case PIPE_FORMAT_Z32_FLOAT: + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + return V_028040_Z_32_FLOAT; + default: + return ~0U; + } +} + +/* + * framebuffer handling + */ + +static void si_cb(struct r600_context *rctx, struct si_pm4_state *pm4, + const struct pipe_framebuffer_state *state, int cb) +{ + struct r600_resource_texture *rtex; + struct r600_surface *surf; + unsigned level = state->cbufs[cb]->u.tex.level; + unsigned pitch, slice; + unsigned color_info, color_attrib; + unsigned format, swap, ntype, endian; + uint64_t offset; + unsigned blocksize; + const struct util_format_description *desc; + int i; + unsigned blend_clamp = 0, blend_bypass = 0; + + surf = (struct r600_surface *)state->cbufs[cb]; + rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture; + blocksize = util_format_get_blocksize(rtex->real_format); + + if (rtex->depth) + rctx->have_depth_fb = TRUE; + + if (rtex->depth && !rtex->is_flushing_texture) { + r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE); + rtex = rtex->flushed_depth_texture; + } + + offset = rtex->surface.level[level].offset; + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + offset += rtex->surface.level[level].slice_size * + state->cbufs[cb]->u.tex.first_layer; + } + pitch = (rtex->surface.level[level].nblk_x) / 8 - 1; + slice = (rtex->surface.level[level].nblk_x * rtex->surface.level[level].nblk_y) / 64; + if (slice) { + slice = slice - 1; + } + + color_attrib = S_028C74_TILE_MODE_INDEX(8); + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + color_attrib = S_028C74_TILE_MODE_INDEX(8); + break; + case RADEON_SURF_MODE_1D: + color_attrib = S_028C74_TILE_MODE_INDEX(9); + break; + case RADEON_SURF_MODE_2D: + if (rtex->resource.b.b.bind & PIPE_BIND_SCANOUT) { + switch (blocksize) { + case 1: + color_attrib = S_028C74_TILE_MODE_INDEX(10); + break; + case 2: + color_attrib = S_028C74_TILE_MODE_INDEX(11); + break; + case 4: + color_attrib = S_028C74_TILE_MODE_INDEX(12); + break; + } + break; + } else switch (blocksize) { + case 1: + color_attrib = S_028C74_TILE_MODE_INDEX(14); + break; + case 2: + color_attrib = S_028C74_TILE_MODE_INDEX(15); + break; + case 4: + color_attrib = S_028C74_TILE_MODE_INDEX(16); + break; + case 8: + color_attrib = S_028C74_TILE_MODE_INDEX(17); + break; + default: + color_attrib = S_028C74_TILE_MODE_INDEX(13); + } + break; + } + + desc = util_format_description(surf->base.format); + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) { + ntype = V_028C70_NUMBER_FLOAT; + } else { + ntype = V_028C70_NUMBER_UNORM; + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) + ntype = V_028C70_NUMBER_SRGB; + else if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) { + if (desc->channel[i].normalized) + ntype = V_028C70_NUMBER_SNORM; + else if (desc->channel[i].pure_integer) + ntype = V_028C70_NUMBER_SINT; + } else if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) { + if (desc->channel[i].normalized) + ntype = V_028C70_NUMBER_UNORM; + else if (desc->channel[i].pure_integer) + ntype = V_028C70_NUMBER_UINT; + } + } + + format = si_translate_colorformat(surf->base.format); + swap = si_translate_colorswap(surf->base.format); + if (rtex->resource.b.b.usage == PIPE_USAGE_STAGING) { + endian = V_028C70_ENDIAN_NONE; + } else { + endian = si_colorformat_endian_swap(format); + } + + /* blend clamp should be set for all NORM/SRGB types */ + if (ntype == V_028C70_NUMBER_UNORM || + ntype == V_028C70_NUMBER_SNORM || + ntype == V_028C70_NUMBER_SRGB) + blend_clamp = 1; + + /* set blend bypass according to docs if SINT/UINT or + 8/24 COLOR variants */ + if (ntype == V_028C70_NUMBER_UINT || ntype == V_028C70_NUMBER_SINT || + format == V_028C70_COLOR_8_24 || format == V_028C70_COLOR_24_8 || + format == V_028C70_COLOR_X24_8_32_FLOAT) { + blend_clamp = 0; + blend_bypass = 1; + } + + color_info = S_028C70_FORMAT(format) | + S_028C70_COMP_SWAP(swap) | + S_028C70_BLEND_CLAMP(blend_clamp) | + S_028C70_BLEND_BYPASS(blend_bypass) | + S_028C70_NUMBER_TYPE(ntype) | + S_028C70_ENDIAN(endian); + + rctx->alpha_ref_dirty = true; + + offset += r600_resource_va(rctx->context.screen, state->cbufs[cb]->texture); + offset >>= 8; + + /* FIXME handle enabling of CB beyond BASE8 which has different offset */ + si_pm4_add_bo(pm4, &rtex->resource, RADEON_USAGE_READWRITE); + si_pm4_set_reg(pm4, R_028C60_CB_COLOR0_BASE + cb * 0x3C, offset); + si_pm4_set_reg(pm4, R_028C64_CB_COLOR0_PITCH + cb * 0x3C, S_028C64_TILE_MAX(pitch)); + si_pm4_set_reg(pm4, R_028C68_CB_COLOR0_SLICE + cb * 0x3C, S_028C68_TILE_MAX(slice)); + + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + si_pm4_set_reg(pm4, R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, 0x00000000); + } else { + si_pm4_set_reg(pm4, R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, + S_028C6C_SLICE_START(state->cbufs[cb]->u.tex.first_layer) | + S_028C6C_SLICE_MAX(state->cbufs[cb]->u.tex.last_layer)); + } + si_pm4_set_reg(pm4, R_028C70_CB_COLOR0_INFO + cb * 0x3C, color_info); + si_pm4_set_reg(pm4, R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C, color_attrib); +} + +static void si_db(struct r600_context *rctx, struct si_pm4_state *pm4, + const struct pipe_framebuffer_state *state) +{ + struct r600_resource_texture *rtex; + struct r600_surface *surf; + unsigned level, first_layer, pitch, slice, format; + uint32_t db_z_info, stencil_info; + uint64_t offset; + + if (state->zsbuf == NULL) { + si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, 0); + si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, 0); + return; + } + + surf = (struct r600_surface *)state->zsbuf; + level = surf->base.u.tex.level; + rtex = (struct r600_resource_texture*)surf->base.texture; + + first_layer = surf->base.u.tex.first_layer; + format = si_translate_dbformat(rtex->real_format); + + offset = r600_resource_va(rctx->context.screen, surf->base.texture); + offset += rtex->surface.level[level].offset; + pitch = (rtex->surface.level[level].nblk_x / 8) - 1; + slice = (rtex->surface.level[level].nblk_x * rtex->surface.level[level].nblk_y) / 64; + if (slice) { + slice = slice - 1; + } + offset >>= 8; + + si_pm4_add_bo(pm4, &rtex->resource, RADEON_USAGE_READWRITE); + si_pm4_set_reg(pm4, R_028048_DB_Z_READ_BASE, offset); + si_pm4_set_reg(pm4, R_028050_DB_Z_WRITE_BASE, offset); + si_pm4_set_reg(pm4, R_028008_DB_DEPTH_VIEW, + S_028008_SLICE_START(state->zsbuf->u.tex.first_layer) | + S_028008_SLICE_MAX(state->zsbuf->u.tex.last_layer)); + + db_z_info = S_028040_FORMAT(format); + stencil_info = S_028044_FORMAT(rtex->stencil != 0); + + switch (format) { + case V_028040_Z_16: + db_z_info |= S_028040_TILE_MODE_INDEX(5); + stencil_info |= S_028044_TILE_MODE_INDEX(5); + break; + case V_028040_Z_24: + case V_028040_Z_32_FLOAT: + db_z_info |= S_028040_TILE_MODE_INDEX(6); + stencil_info |= S_028044_TILE_MODE_INDEX(6); + break; + default: + db_z_info |= S_028040_TILE_MODE_INDEX(7); + stencil_info |= S_028044_TILE_MODE_INDEX(7); + } + + if (rtex->stencil) { + uint64_t stencil_offset = + r600_texture_get_offset(rtex->stencil, level, first_layer); + + stencil_offset += r600_resource_va(rctx->context.screen, (void*)rtex->stencil); + stencil_offset >>= 8; + + si_pm4_add_bo(pm4, &rtex->stencil->resource, RADEON_USAGE_READWRITE); + si_pm4_set_reg(pm4, R_02804C_DB_STENCIL_READ_BASE, stencil_offset); + si_pm4_set_reg(pm4, R_028054_DB_STENCIL_WRITE_BASE, stencil_offset); + si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, stencil_info); + } else { + si_pm4_set_reg(pm4, R_028044_DB_STENCIL_INFO, 0); + } + + if (format != ~0U) { + si_pm4_set_reg(pm4, R_02803C_DB_DEPTH_INFO, 0x1); + si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, db_z_info); + si_pm4_set_reg(pm4, R_028058_DB_DEPTH_SIZE, S_028058_PITCH_TILE_MAX(pitch)); + si_pm4_set_reg(pm4, R_02805C_DB_DEPTH_SLICE, S_02805C_SLICE_TILE_MAX(slice)); + + } else { + si_pm4_set_reg(pm4, R_028040_DB_Z_INFO, 0); + } +} + +static void si_set_framebuffer_state(struct pipe_context *ctx, + const struct pipe_framebuffer_state *state) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state); + uint32_t shader_mask, tl, br; + int tl_x, tl_y, br_x, br_y; + + if (pm4 == NULL) + return; + + si_pm4_inval_fb_cache(pm4, state->nr_cbufs); + + if (state->zsbuf) + si_pm4_inval_zsbuf_cache(pm4); + + util_copy_framebuffer_state(&rctx->framebuffer, state); + + /* build states */ + rctx->have_depth_fb = 0; + for (int i = 0; i < state->nr_cbufs; i++) { + si_cb(rctx, pm4, state, i); + } + si_db(rctx, pm4, state); + + shader_mask = 0; + for (int i = 0; i < state->nr_cbufs; i++) { + shader_mask |= 0xf << (i * 4); + } + tl_x = 0; + tl_y = 0; + br_x = state->width; + br_y = state->height; +#if 0 /* These shouldn't be necessary on SI, see PA_SC_ENHANCE register */ + /* EG hw workaround */ + if (br_x == 0) + tl_x = 1; + if (br_y == 0) + tl_y = 1; + /* cayman hw workaround */ + if (rctx->chip_class == CAYMAN) { + if (br_x == 1 && br_y == 1) + br_x = 2; + } +#endif + tl = S_028240_TL_X(tl_x) | S_028240_TL_Y(tl_y); + br = S_028244_BR_X(br_x) | S_028244_BR_Y(br_y); + + si_pm4_set_reg(pm4, R_028240_PA_SC_GENERIC_SCISSOR_TL, tl); + si_pm4_set_reg(pm4, R_028244_PA_SC_GENERIC_SCISSOR_BR, br); + si_pm4_set_reg(pm4, R_028250_PA_SC_VPORT_SCISSOR_0_TL, tl); + si_pm4_set_reg(pm4, R_028254_PA_SC_VPORT_SCISSOR_0_BR, br); + si_pm4_set_reg(pm4, R_028030_PA_SC_SCREEN_SCISSOR_TL, tl); + si_pm4_set_reg(pm4, R_028034_PA_SC_SCREEN_SCISSOR_BR, br); + si_pm4_set_reg(pm4, R_028204_PA_SC_WINDOW_SCISSOR_TL, tl); + si_pm4_set_reg(pm4, R_028208_PA_SC_WINDOW_SCISSOR_BR, br); + si_pm4_set_reg(pm4, R_028200_PA_SC_WINDOW_OFFSET, 0x00000000); + si_pm4_set_reg(pm4, R_028230_PA_SC_EDGERULE, 0xAAAAAAAA); + si_pm4_set_reg(pm4, R_02823C_CB_SHADER_MASK, shader_mask); + si_pm4_set_reg(pm4, R_028BE0_PA_SC_AA_CONFIG, 0x00000000); + + si_pm4_set_state(rctx, framebuffer, pm4); + + if (state->zsbuf) { + cayman_polygon_offset_update(rctx); + } +} + void si_init_state_functions(struct r600_context *rctx) { rctx->context.create_blend_state = si_create_blend_state; @@ -275,4 +936,6 @@ void si_init_state_functions(struct r600_context *rctx) rctx->context.set_clip_state = si_set_clip_state; rctx->context.set_scissor_state = si_set_scissor_state; rctx->context.set_viewport_state = si_set_viewport_state; + + rctx->context.set_framebuffer_state = si_set_framebuffer_state; } |