From c0c979eebc076b95cc8d18a013ce2968fe6311ad Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Mon, 30 Jan 2012 17:22:13 -0500 Subject: [PATCH] r600g: add support for common surface allocator for tiling v13 Tiled surface have all kind of alignment constraint that needs to be met. Instead of having all this code duplicated btw ddx and mesa use common code in libdrm_radeon this also ensure that both ddx and mesa compute those alignment in the same way. v2 fix evergreen v3 fix compressed texture and workaround cube texture issue by disabling 2D array mode for cubemap (need to check if r7xx and newer are also affected by the issue) v4 fix texture array v5 fix evergreen and newer, split surface values computation from mipmap tree generation so that we can get them directly from the ddx v6 final fix to evergreen tile split value v7 fix mipmap offset to avoid to use random value, use color view depth view to address different layer as hardware is doing some magic rotation depending on the layer v8 fix COLOR_VIEW on r6xx for linear array mode, use COLOR_VIEW on evergreen, align bytes per pixel to a multiple of a dword v9 fix handling of stencil on evergreen, half fix for compressed texture v10 fix evergreen compressed texture proper support for stencil tile split. Fix stencil issue when array mode was clear by the kernel, always program stencil bo. On evergreen depth buffer bo need to be big enough to hold depth buffer + stencil buffer as even with stencil disabled things get written there. v11 rebase on top of mesa, fix pitch issue with 1d surface on evergreen, old ddx overestimate those. Fix linear case when pitch*height < 64. Fix r300g. v12 Fix linear case when pitch*height < 64 for old path, adapt to libdrm API change v13 add libdrm check Signed-off-by: Jerome Glisse --- configure.ac | 4 +- src/gallium/drivers/r300/r300_texture.c | 2 +- src/gallium/drivers/r600/evergreen_state.c | 352 +++++++++++++++--- src/gallium/drivers/r600/evergreend.h | 22 ++ src/gallium/drivers/r600/r600_blit.c | 27 +- src/gallium/drivers/r600/r600_hw_context.c | 3 + src/gallium/drivers/r600/r600_pipe.h | 1 + src/gallium/drivers/r600/r600_resource.h | 1 + src/gallium/drivers/r600/r600_state.c | 258 ++++++++++--- src/gallium/drivers/r600/r600_texture.c | 198 +++++++++- src/gallium/targets/dri-r300/Makefile | 2 + src/gallium/targets/dri-r600/Makefile | 2 +- src/gallium/targets/egl-static/Makefile | 2 + src/gallium/targets/va-r300/Makefile | 2 +- src/gallium/targets/va-r600/Makefile | 2 +- src/gallium/targets/vdpau-r300/Makefile | 2 +- src/gallium/targets/vdpau-r600/Makefile | 2 +- src/gallium/targets/xorg-r300/Makefile | 2 +- src/gallium/targets/xorg-r600/Makefile | 2 +- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 29 +- .../winsys/radeon/drm/radeon_drm_winsys.c | 26 ++ .../winsys/radeon/drm/radeon_drm_winsys.h | 1 + src/gallium/winsys/radeon/drm/radeon_winsys.h | 25 +- 23 files changed, 833 insertions(+), 134 deletions(-) diff --git a/configure.ac b/configure.ac index af1e914f35a..b2b1ab8f41a 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ USER_CXXFLAGS="$CXXFLAGS" dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.24 -LIBDRM_RADEON_REQUIRED=2.4.24 +LIBDRM_RADEON_REQUIRED=2.4.31 LIBDRM_INTEL_REQUIRED=2.4.30 LIBDRM_NOUVEAU_REQUIRED=0.6 DRI2PROTO_REQUIRED=2.6 @@ -1864,11 +1864,13 @@ if test "x$with_gallium_drivers" != x; then gallium_check_st "i915/drm" "dri-i915" "xorg-i915" ;; xr300) + PKG_CHECK_MODULES([RADEON], [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED]) gallium_require_llvm "Gallium R300" GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" gallium_check_st "radeon/drm" "dri-r300" "xorg-r300" "" "xvmc-r300" "vdpau-r300" "va-r300" ;; xr600) + PKG_CHECK_MODULES([RADEON], [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED]) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600" gallium_check_st "radeon/drm" "dri-r600" "xorg-r600" "" "xvmc-r600" "vdpau-r600" "va-r600" ;; diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 0b352e9daca..99678bc89a8 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -963,7 +963,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, if (!buffer) return NULL; - rws->buffer_get_tiling(buffer, µtile, ¯otile); + rws->buffer_get_tiling(buffer, µtile, ¯otile, NULL, NULL, NULL, NULL, NULL); /* Enforce a microtiled zbuffer. */ if (util_format_is_depth_or_stencil(base->format) && diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 89f22153a7e..dd67e4bf1d8 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -48,6 +48,61 @@ #include "r600_pipe.h" #include "r600_formats.h" +static uint32_t eg_num_banks(uint32_t nbanks) +{ + switch (nbanks) { + case 2: + return 0; + case 4: + return 1; + case 8: + default: + return 2; + case 16: + return 3; + } +} + + +static unsigned eg_tile_split(unsigned tile_split) +{ + switch (tile_split) { + case 64: tile_split = 0; break; + case 128: tile_split = 1; break; + case 256: tile_split = 2; break; + case 512: tile_split = 3; break; + default: + case 1024: tile_split = 4; break; + case 2048: tile_split = 5; break; + case 4096: tile_split = 6; break; + } + return tile_split; +} + +static unsigned eg_macro_tile_aspect(unsigned macro_tile_aspect) +{ + switch (macro_tile_aspect) { + default: + case 1: macro_tile_aspect = 0; break; + case 2: macro_tile_aspect = 1; break; + case 4: macro_tile_aspect = 2; break; + case 8: macro_tile_aspect = 3; break; + } + return macro_tile_aspect; +} + +static unsigned eg_bank_wh(unsigned bankwh) +{ + switch (bankwh) { + default: + case 1: bankwh = 0; break; + case 2: bankwh = 1; break; + case 4: bankwh = 2; break; + case 8: bankwh = 3; break; + } + return bankwh; +} + static uint32_t r600_translate_blend_function(int blend_func) { switch (blend_func) { @@ -1035,13 +1090,15 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte struct pipe_resource *texture, const struct pipe_sampler_view *state) { + struct r600_screen *rscreen = (struct r600_screen*)ctx->screen; struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view); struct r600_pipe_resource_state *rstate; struct r600_resource_texture *tmp = (struct r600_resource_texture*)texture; unsigned format, endian; uint32_t word4 = 0, yuv_format = 0, pitch = 0; unsigned char swizzle[4], array_mode = 0, tile_type = 0; - unsigned height, depth; + unsigned height, depth, width; + unsigned macro_aspect, tile_split, bankh, bankw, nbanks; if (view == NULL) return NULL; @@ -1074,13 +1131,50 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte endian = r600_colorformat_endian_swap(format); - height = texture->height0; - depth = texture->depth0; - - pitch = align(tmp->pitch_in_blocks[0] * - util_format_get_blockwidth(state->format), 8); - array_mode = tmp->array_mode[0]; - tile_type = tmp->tile_type; + if (!rscreen->use_surface) { + height = texture->height0; + depth = texture->depth0; + width = texture->width0; + pitch = align(tmp->pitch_in_blocks[0] * + util_format_get_blockwidth(state->format), 8); + array_mode = tmp->array_mode[0]; + tile_type = tmp->tile_type; + tile_split = 0; + macro_aspect = 0; + bankw = 0; + bankh = 0; + } else { + width = tmp->surface.level[0].npix_x; + height = tmp->surface.level[0].npix_y; + depth = tmp->surface.level[0].npix_z; + pitch = tmp->surface.level[0].nblk_x * util_format_get_blockwidth(state->format); + tile_type = tmp->tile_type; + + switch (tmp->surface.level[0].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + array_mode = V_028C70_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_2D: + array_mode = V_028C70_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_1D: + array_mode = V_028C70_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_028C70_ARRAY_LINEAR_GENERAL; + break; + } + tile_split = tmp->surface.tile_split; + macro_aspect = tmp->surface.mtilea; + bankw = tmp->surface.bankw; + bankh = tmp->surface.bankh; + tile_split = eg_tile_split(tile_split); + macro_aspect = eg_macro_tile_aspect(macro_aspect); + bankw = eg_bank_wh(bankw); + bankh = eg_bank_wh(bankh); + } + nbanks = eg_num_banks(rscreen->tiling_info.num_banks); if (texture->target == PIPE_TEXTURE_1D_ARRAY) { height = 1; @@ -1097,12 +1191,16 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte rstate->val[0] = (S_030000_DIM(r600_tex_dim(texture->target)) | S_030000_PITCH((pitch / 8) - 1) | S_030000_NON_DISP_TILING_ORDER(tile_type) | - S_030000_TEX_WIDTH(texture->width0 - 1)); + S_030000_TEX_WIDTH(width - 1)); rstate->val[1] = (S_030004_TEX_HEIGHT(height - 1) | S_030004_TEX_DEPTH(depth - 1) | S_030004_ARRAY_MODE(array_mode)); rstate->val[2] = (tmp->offset[0] + r600_resource_va(ctx->screen, texture)) >> 8; - rstate->val[3] = (tmp->offset[1] + r600_resource_va(ctx->screen, texture)) >> 8; + if (state->u.tex.last_level) { + rstate->val[3] = (tmp->offset[1] + r600_resource_va(ctx->screen, texture)) >> 8; + } else { + rstate->val[3] = (tmp->offset[0] + r600_resource_va(ctx->screen, texture)) >> 8; + } rstate->val[4] = (word4 | S_030010_SRF_MODE_ALL(V_030010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | S_030010_ENDIAN_SWAP(endian) | @@ -1110,9 +1208,15 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte rstate->val[5] = (S_030014_LAST_LEVEL(state->u.tex.last_level) | S_030014_BASE_ARRAY(state->u.tex.first_layer) | S_030014_LAST_ARRAY(state->u.tex.last_layer)); - rstate->val[6] = (S_030018_MAX_ANISO(4 /* max 16 samples */)); - rstate->val[7] = (S_03001C_DATA_FORMAT(format) | - S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_TEXTURE)); + /* aniso max 16 samples */ + rstate->val[6] = (S_030018_MAX_ANISO(4)) | + (S_030018_TILE_SPLIT(tile_split)); + rstate->val[7] = S_03001C_DATA_FORMAT(format) | + S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_TEXTURE) | + S_03001C_BANK_WIDTH(bankw) | + S_03001C_BANK_HEIGHT(bankh) | + S_03001C_MACRO_TILE_ASPECT(macro_aspect) | + S_03001C_NUM_BANKS(nbanks); return &view->base; } @@ -1318,16 +1422,17 @@ static void evergreen_set_viewport_state(struct pipe_context *ctx, } static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, - const struct pipe_framebuffer_state *state, int cb) + const struct pipe_framebuffer_state *state, int cb) { + struct r600_screen *rscreen = rctx->screen; struct r600_resource_texture *rtex; struct r600_surface *surf; unsigned level = state->cbufs[cb]->u.tex.level; unsigned pitch, slice; - unsigned color_info; + unsigned color_info, color_attrib; unsigned format, swap, ntype, endian; uint64_t offset; - unsigned tile_type; + unsigned tile_type, macro_aspect, tile_split, bankh, bankw, nbanks; const struct util_format_description *desc; int i; unsigned blend_clamp = 0, blend_bypass = 0; @@ -1344,10 +1449,66 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta } /* XXX quite sure for dx10+ hw don't need any offset hacks */ - offset = r600_texture_get_offset(rtex, - level, state->cbufs[cb]->u.tex.first_layer); - pitch = rtex->pitch_in_blocks[level] / 8 - 1; - slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; + if (!rscreen->use_surface) { + offset = r600_texture_get_offset(rtex, + level, state->cbufs[cb]->u.tex.first_layer); + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64; + if (slice) { + slice = slice - 1; + } + color_info = S_028C70_ARRAY_MODE(rtex->array_mode[level]); + tile_split = 0; + macro_aspect = 0; + bankw = 0; + bankh = 0; + if (rtex->array_mode[level] > V_028C70_ARRAY_LINEAR_ALIGNED) { + tile_type = rtex->tile_type; + } else { + /* workaround for linear buffers */ + tile_type = 1; + } + } else { + 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_info = 0; + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_LINEAR_ALIGNED); + tile_type = 1; + break; + case RADEON_SURF_MODE_1D: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_1D_TILED_THIN1); + tile_type = rtex->tile_type; + break; + case RADEON_SURF_MODE_2D: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_2D_TILED_THIN1); + tile_type = rtex->tile_type; + break; + case RADEON_SURF_MODE_LINEAR: + default: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_LINEAR_GENERAL); + tile_type = 1; + break; + } + tile_split = rtex->surface.tile_split; + macro_aspect = rtex->surface.mtilea; + bankw = rtex->surface.bankw; + bankh = rtex->surface.bankh; + tile_split = eg_tile_split(tile_split); + macro_aspect = eg_macro_tile_aspect(macro_aspect); + bankw = eg_bank_wh(bankw); + bankh = eg_bank_wh(bankh); + } + nbanks = eg_num_banks(rscreen->tiling_info.num_banks); desc = util_format_description(surf->base.format); for (i = 0; i < 4; i++) { if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { @@ -1355,6 +1516,13 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta } } + color_attrib = S_028C74_TILE_SPLIT(tile_split)| + S_028C74_NUM_BANKS(nbanks) | + S_028C74_BANK_WIDTH(bankw) | + S_028C74_BANK_HEIGHT(bankh) | + S_028C74_MACRO_TILE_ASPECT(macro_aspect) | + S_028C74_NON_DISP_TILING_ORDER(tile_type); + ntype = V_028C70_NUMBER_UNORM; if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) ntype = V_028C70_NUMBER_SRGB; @@ -1392,9 +1560,8 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta blend_bypass = 1; } - color_info = S_028C70_FORMAT(format) | + color_info |= S_028C70_FORMAT(format) | S_028C70_COMP_SWAP(swap) | - S_028C70_ARRAY_MODE(rtex->array_mode[level]) | S_028C70_BLEND_CLAMP(blend_clamp) | S_028C70_BLEND_BYPASS(blend_bypass) | S_028C70_NUMBER_TYPE(ntype) | @@ -1421,10 +1588,6 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta } rctx->alpha_ref_dirty = true; - if (rtex->array_mode[level] > V_028C70_ARRAY_LINEAR_ALIGNED) { - tile_type = rtex->tile_type; - } else /* workaround for linear buffers */ - tile_type = 1; offset += r600_resource_va(rctx->context.screen, state->cbufs[cb]->texture); offset >>= 8; @@ -1447,22 +1610,38 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta R_028C68_CB_COLOR0_SLICE + cb * 0x3C, S_028C68_SLICE_TILE_MAX(slice), NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, - 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, + R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, + 0x00000000, NULL, 0); + } else { + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + r600_pipe_state_add_reg(rstate, + R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, + 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, + 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), + NULL, 0); + } + } r600_pipe_state_add_reg(rstate, R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C, - S_028C74_NON_DISP_TILING_ORDER(tile_type), + color_attrib, &rtex->resource, RADEON_USAGE_READWRITE); } static void evergreen_db(struct r600_context *rctx, struct r600_pipe_state *rstate, const struct pipe_framebuffer_state *state) { + struct r600_screen *rscreen = rctx->screen; struct r600_resource_texture *rtex; struct r600_surface *surf; - unsigned level, first_layer, pitch, slice, format, array_mode; uint64_t offset; + unsigned level, first_layer, pitch, slice, format, array_mode; + unsigned macro_aspect, tile_split, bankh, bankw, z_info, nbanks; if (state->zsbuf == NULL) return; @@ -1470,30 +1649,84 @@ static void evergreen_db(struct r600_context *rctx, struct r600_pipe_state *rsta surf = (struct r600_surface *)state->zsbuf; level = surf->base.u.tex.level; rtex = (struct r600_resource_texture*)surf->base.texture; - - /* XXX remove this once tiling is properly supported */ - array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : - V_028C70_ARRAY_1D_TILED_THIN1; - first_layer = surf->base.u.tex.first_layer; - offset = r600_texture_get_offset(rtex, level, first_layer); - pitch = rtex->pitch_in_blocks[level] / 8 - 1; - slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(rtex->real_format); - offset += r600_resource_va(rctx->context.screen, surf->base.texture); + offset = r600_resource_va(rctx->context.screen, surf->base.texture); + /* XXX remove this once tiling is properly supported */ + if (!rscreen->use_surface) { + /* XXX remove this once tiling is properly supported */ + array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : + V_028C70_ARRAY_1D_TILED_THIN1; + + offset += r600_texture_get_offset(rtex, level, first_layer); + pitch = (rtex->pitch_in_blocks[level] / 8) - 1; + slice = ((rtex->pitch_in_blocks[level] * surf->aligned_height) / 64); + if (slice) { + slice = slice - 1; + } + tile_split = 0; + macro_aspect = 0; + bankw = 0; + bankh = 0; + } else { + 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; + } + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_2D: + array_mode = V_028C70_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_1D: + case RADEON_SURF_MODE_LINEAR_ALIGNED: + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_028C70_ARRAY_1D_TILED_THIN1; + break; + } + tile_split = rtex->surface.tile_split; + macro_aspect = rtex->surface.mtilea; + bankw = rtex->surface.bankw; + bankh = rtex->surface.bankh; + tile_split = eg_tile_split(tile_split); + macro_aspect = eg_macro_tile_aspect(macro_aspect); + bankw = eg_bank_wh(bankw); + bankh = eg_bank_wh(bankh); + } + nbanks = eg_num_banks(rscreen->tiling_info.num_banks); offset >>= 8; + z_info = S_028040_ARRAY_MODE(array_mode) | + S_028040_FORMAT(format) | + S_028040_TILE_SPLIT(tile_split)| + S_028040_NUM_BANKS(nbanks) | + S_028040_BANK_WIDTH(bankw) | + S_028040_BANK_HEIGHT(bankh) | + S_028040_MACRO_TILE_ASPECT(macro_aspect); + r600_pipe_state_add_reg(rstate, R_028048_DB_Z_READ_BASE, offset, &rtex->resource, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg(rstate, R_028050_DB_Z_WRITE_BASE, offset, &rtex->resource, RADEON_USAGE_READWRITE); - r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, + 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, 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), + NULL, 0); + } if (rtex->stencil) { uint64_t stencil_offset = r600_texture_get_offset(rtex->stencil, level, first_layer); + unsigned stile_split; + stile_split = eg_tile_split(rtex->stencil->surface.tile_split); stencil_offset += r600_resource_va(rctx->context.screen, (void*)rtex->stencil); stencil_offset >>= 8; @@ -1502,14 +1735,41 @@ static void evergreen_db(struct r600_context *rctx, struct r600_pipe_state *rsta r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, stencil_offset, &rtex->stencil->resource, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, - 1, &rtex->stencil->resource, RADEON_USAGE_READWRITE); + 1 | S_028044_TILE_SPLIT(stile_split), + &rtex->stencil->resource, RADEON_USAGE_READWRITE); } else { - r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, - 0, NULL, RADEON_USAGE_READWRITE); + if (rscreen->use_surface && rtex->surface.flags & RADEON_SURF_SBUFFER) { + uint64_t stencil_offset = rtex->surface.stencil_offset; + unsigned stile_split = rtex->surface.stencil_tile_split; + + stile_split = eg_tile_split(stile_split); + stencil_offset += r600_resource_va(rctx->context.screen, surf->base.texture); + stencil_offset += rtex->surface.level[level].offset / 4; + stencil_offset >>= 8; + + r600_pipe_state_add_reg(rstate, R_02804C_DB_STENCIL_READ_BASE, + stencil_offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, + stencil_offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, + 1 | S_028044_TILE_SPLIT(stile_split), + &rtex->resource, + RADEON_USAGE_READWRITE); + } else { + r600_pipe_state_add_reg(rstate, R_02804C_DB_STENCIL_READ_BASE, + offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, + offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, + 0, NULL, RADEON_USAGE_READWRITE); + } } - r600_pipe_state_add_reg(rstate, R_028040_DB_Z_INFO, - S_028040_ARRAY_MODE(array_mode) | S_028040_FORMAT(format), + r600_pipe_state_add_reg(rstate, R_028040_DB_Z_INFO, z_info, &rtex->resource, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg(rstate, R_028058_DB_DEPTH_SIZE, S_028058_PITCH_TILE_MAX(pitch), diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index 3345ebf9310..1d870760f61 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -366,6 +366,11 @@ #define S_028C74_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 4) #define G_028C74_NON_DISP_TILING_ORDER(x) (((x) >> 4) & 0x1) #define C_028C74_NON_DISP_TILING_ORDER 0xFFFFFFEF +#define S_028C74_TILE_SPLIT(x) (((x) & 0xf) << 5) +#define S_028C74_NUM_BANKS(x) (((x) & 0x3) << 10) +#define S_028C74_BANK_WIDTH(x) (((x) & 0x3) << 13) +#define S_028C74_BANK_HEIGHT(x) (((x) & 0x3) << 16) +#define S_028C74_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 19) #define R_028C78_CB_COLOR0_DIM 0x028C78 #define S_028C78_WIDTH_MAX(x) (((x) & 0xFFFF) << 0) @@ -540,11 +545,17 @@ #define S_028040_ZRANGE_PRECISION(x) (((x) & 0x1) << 31) #define G_028040_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1) #define C_028040_ZRANGE_PRECISION 0x7FFFFFFF +#define S_028040_TILE_SPLIT(x) (((x) & 0x7) << 8) +#define S_028040_NUM_BANKS(x) (((x) & 0x3) << 12) +#define S_028040_BANK_WIDTH(x) (((x) & 0x3) << 16) +#define S_028040_BANK_HEIGHT(x) (((x) & 0x3) << 20) +#define S_028040_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 24) #define R_028044_DB_STENCIL_INFO 0x028044 #define S_028044_FORMAT(x) (((x) & 0x1) << 0) #define G_028044_FORMAT(x) (((x) >> 0) & 0x1) #define C_028044_FORMAT 0xFFFFFFFE +#define S_028044_TILE_SPLIT(x) (((x) & 0x7) << 8) #define R_028058_DB_DEPTH_SIZE 0x028058 #define S_028058_PITCH_TILE_MAX(x) (((x) & 0x7FF) << 0) @@ -1053,7 +1064,12 @@ #define S_030018_INTERLACED(x) (((x) & 0x1) << 6) #define G_030018_INTERLACED(x) (((x) >> 6) & 0x1) #define C_030018_INTERLACED 0xFFFFFFBF +#define S_030018_TILE_SPLIT(x) (((x) & 0x7) << 29) #define R_03001C_SQ_TEX_RESOURCE_WORD7_0 0x03001C +#define S_03001C_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 6) +#define S_03001C_BANK_WIDTH(x) (((x) & 0x3) << 8) +#define S_03001C_BANK_HEIGHT(x) (((x) & 0x3) << 10) +#define S_03001C_NUM_BANKS(x) (((x) & 0x3) << 16) #define S_03001C_TYPE(x) (((x) & 0x3) << 30) #define G_03001C_TYPE(x) (((x) >> 30) & 0x3) #define C_03001C_TYPE 0x3FFFFFFF @@ -1841,6 +1857,12 @@ #define R_028C3C_PA_SC_AA_MASK 0x00028C3C #define R_028C60_CB_COLOR0_BASE 0x00028C60 #define R_028C6C_CB_COLOR0_VIEW 0x00028C6C +#define S_028C6C_SLICE_START(x) (((x) & 0x7FF) << 0) +#define G_028C6C_SLICE_START(x) (((x) >> 0) & 0x7FF) +#define C_028C6C_SLICE_START 0xFFFFF800 +#define S_028C6C_SLICE_MAX(x) (((x) & 0x7FF) << 13) +#define G_028C6C_SLICE_MAX(x) (((x) >> 13) & 0x7FF) +#define C_028C6C_SLICE_MAX 0xFF001FFF #define R_028C9C_CB_COLOR1_BASE 0x00028C9C #define R_028CA0_CB_COLOR1_PITCH 0x00028CA0 #define R_028CA4_CB_COLOR1_SLICE 0x00028CA4 diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 93df1a2911d..ff720c9a028 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -202,7 +202,7 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers, { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_framebuffer_state *fb = &rctx->framebuffer; - + r600_blitter_begin(ctx, R600_CLEAR); util_blitter_clear(rctx->blitter, fb->width, fb->height, fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, @@ -263,6 +263,10 @@ struct texture_orig_info { unsigned format; unsigned width0; unsigned height0; + unsigned npix_x; + unsigned npix_y; + unsigned npix0_x; + unsigned npix0_y; }; static void r600_compressed_to_blittable(struct pipe_resource *tex, @@ -270,6 +274,7 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex, struct texture_orig_info *orig) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; + struct r600_screen *rscreen = (struct r600_screen *)tex->screen; unsigned pixsize = util_format_get_blocksize(rtex->real_format); int new_format; int new_height, new_width; @@ -277,6 +282,10 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex, orig->format = tex->format; orig->width0 = tex->width0; orig->height0 = tex->height0; + orig->npix0_x = rtex->surface.level[0].npix_x; + orig->npix0_y = rtex->surface.level[0].npix_y; + orig->npix_x = rtex->surface.level[level].npix_x; + orig->npix_y = rtex->surface.level[level].npix_y; if (pixsize == 8) new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ @@ -289,14 +298,26 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex, tex->width0 = new_width; tex->height0 = new_height; tex->format = new_format; + rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); + rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); + rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); + rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); } static void r600_reset_blittable_to_compressed(struct pipe_resource *tex, + unsigned level, struct texture_orig_info *orig) { + struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; + struct r600_screen *rscreen = (struct r600_screen *)tex->screen; + tex->format = orig->format; tex->width0 = orig->width0; tex->height0 = orig->height0; + rtex->surface.level[0].npix_x = orig->npix0_x; + rtex->surface.level[0].npix_y = orig->npix0_y; + rtex->surface.level[level].npix_x = orig->npix_x; + rtex->surface.level[level].npix_y = orig->npix_y; } static void r600_resource_copy_region(struct pipe_context *ctx, @@ -352,10 +373,10 @@ static void r600_resource_copy_region(struct pipe_context *ctx, src, src_level, psbox); if (restore_orig[0]) - r600_reset_blittable_to_compressed(src, &orig_info[0]); + r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]); if (restore_orig[1]) - r600_reset_blittable_to_compressed(dst, &orig_info[1]); + r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]); } void r600_init_blit_functions(struct r600_context *rctx) diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index ea15530e927..ab51b3e4c43 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -1439,6 +1439,9 @@ void r600_context_flush(struct r600_context *ctx, unsigned flags) cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 0, 0); cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_PS_PARTIAL_FLUSH) | EVENT_INDEX(4); + /* force to keep tiling flags */ + flags |= RADEON_FLUSH_KEEP_TILING_FLAGS; + /* Flush the CS. */ ctx->ws->cs_flush(ctx->cs, flags); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index f11539a9875..f1306176b94 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -117,6 +117,7 @@ struct r600_screen { struct r600_pipe_fences fences; unsigned num_contexts; + unsigned use_surface; /* for thread-safe write accessing to num_contexts */ pipe_mutex mutex_num_contexts; diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h index 1a32c056dd4..8b90b12e957 100644 --- a/src/gallium/drivers/r600/r600_resource.h +++ b/src/gallium/drivers/r600/r600_resource.h @@ -60,6 +60,7 @@ struct r600_resource_texture { struct r600_resource_texture *stencil; /* Stencil is in a separate buffer on Evergreen. */ struct r600_resource_texture *flushed_depth_texture; boolean is_flushing_texture; + struct radeon_surface surface; }; #define R600_TEX_IS_TILED(tex, level) ((tex)->array_mode[level] != V_038000_ARRAY_LINEAR_GENERAL && (tex)->array_mode[level] != V_038000_ARRAY_LINEAR_ALIGNED) diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index e6362f93536..0d83fa608fb 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -1081,6 +1081,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c struct pipe_resource *texture, const struct pipe_sampler_view *state) { + struct r600_screen *rscreen = (struct r600_screen*)ctx->screen; struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view); struct r600_pipe_resource_state *rstate; struct r600_resource_texture *tmp = (struct r600_resource_texture*)texture; @@ -1122,48 +1123,107 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c offset_level = state->u.tex.first_level; last_level = state->u.tex.last_level - offset_level; - width = u_minify(texture->width0, offset_level); - height = u_minify(texture->height0, offset_level); - depth = u_minify(texture->depth0, offset_level); - - pitch = align(tmp->pitch_in_blocks[offset_level] * - util_format_get_blockwidth(state->format), 8); - array_mode = tmp->array_mode[offset_level]; - tile_type = tmp->tile_type; - - if (texture->target == PIPE_TEXTURE_1D_ARRAY) { - height = 1; - depth = texture->array_size; - } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { - depth = texture->array_size; - } - - rstate->bo[0] = &tmp->resource; - rstate->bo[1] = &tmp->resource; - rstate->bo_usage[0] = RADEON_USAGE_READ; - rstate->bo_usage[1] = RADEON_USAGE_READ; - - rstate->val[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | - S_038000_TILE_MODE(array_mode) | - S_038000_TILE_TYPE(tile_type) | - S_038000_PITCH((pitch / 8) - 1) | - S_038000_TEX_WIDTH(width - 1)); - rstate->val[1] = (S_038004_TEX_HEIGHT(height - 1) | - S_038004_TEX_DEPTH(depth - 1) | - S_038004_DATA_FORMAT(format)); - rstate->val[2] = tmp->offset[offset_level] >> 8; - rstate->val[3] = tmp->offset[offset_level+1] >> 8; - rstate->val[4] = (word4 | - S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | - S_038010_REQUEST_SIZE(1) | - S_038010_ENDIAN_SWAP(endian) | - S_038010_BASE_LEVEL(0)); - rstate->val[5] = (S_038014_LAST_LEVEL(last_level) | - S_038014_BASE_ARRAY(state->u.tex.first_layer) | - S_038014_LAST_ARRAY(state->u.tex.last_layer)); - rstate->val[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | - S_038018_MAX_ANISO(4 /* max 16 samples */)); + if (!rscreen->use_surface) { + width = u_minify(texture->width0, offset_level); + height = u_minify(texture->height0, offset_level); + depth = u_minify(texture->depth0, offset_level); + + pitch = align(tmp->pitch_in_blocks[offset_level] * + util_format_get_blockwidth(state->format), 8); + array_mode = tmp->array_mode[offset_level]; + tile_type = tmp->tile_type; + + if (texture->target == PIPE_TEXTURE_1D_ARRAY) { + height = 1; + depth = texture->array_size; + } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { + depth = texture->array_size; + } + rstate->bo[0] = &tmp->resource; + rstate->bo[1] = &tmp->resource; + rstate->bo_usage[0] = RADEON_USAGE_READ; + rstate->bo_usage[1] = RADEON_USAGE_READ; + + rstate->val[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | + S_038000_TILE_MODE(array_mode) | + S_038000_TILE_TYPE(tile_type) | + S_038000_PITCH((pitch / 8) - 1) | + S_038000_TEX_WIDTH(width - 1)); + rstate->val[1] = (S_038004_TEX_HEIGHT(height - 1) | + S_038004_TEX_DEPTH(depth - 1) | + S_038004_DATA_FORMAT(format)); + rstate->val[2] = tmp->offset[offset_level] >> 8; + rstate->val[3] = tmp->offset[offset_level+1] >> 8; + rstate->val[4] = (word4 | + S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | + S_038010_REQUEST_SIZE(1) | + S_038010_ENDIAN_SWAP(endian) | + S_038010_BASE_LEVEL(0)); + rstate->val[5] = (S_038014_LAST_LEVEL(last_level) | + S_038014_BASE_ARRAY(state->u.tex.first_layer) | + S_038014_LAST_ARRAY(state->u.tex.last_layer)); + rstate->val[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | + S_038018_MAX_ANISO(4 /* max 16 samples */)); + } else { + width = tmp->surface.level[offset_level].npix_x; + height = tmp->surface.level[offset_level].npix_y; + depth = tmp->surface.level[offset_level].npix_z; + pitch = tmp->surface.level[offset_level].nblk_x * util_format_get_blockwidth(state->format); + tile_type = tmp->tile_type; + + if (texture->target == PIPE_TEXTURE_1D_ARRAY) { + height = 1; + depth = texture->array_size; + } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { + depth = texture->array_size; + } + switch (tmp->surface.level[offset_level].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + array_mode = V_038000_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + array_mode = V_038000_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + array_mode = V_038000_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_038000_ARRAY_LINEAR_GENERAL; + break; + } + + rstate->bo[0] = &tmp->resource; + rstate->bo[1] = &tmp->resource; + rstate->bo_usage[0] = RADEON_USAGE_READ; + rstate->bo_usage[1] = RADEON_USAGE_READ; + + rstate->val[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | + S_038000_TILE_MODE(array_mode) | + S_038000_TILE_TYPE(tile_type) | + S_038000_PITCH((pitch / 8) - 1) | + S_038000_TEX_WIDTH(width - 1)); + rstate->val[1] = (S_038004_TEX_HEIGHT(height - 1) | + S_038004_TEX_DEPTH(depth - 1) | + S_038004_DATA_FORMAT(format)); + rstate->val[2] = tmp->surface.level[offset_level].offset >> 8; + if (offset_level >= tmp->surface.last_level) { + rstate->val[3] = tmp->surface.level[offset_level].offset >> 8; + } else { + rstate->val[3] = tmp->surface.level[offset_level + 1].offset >> 8; + } + rstate->val[4] = (word4 | + S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | + S_038010_REQUEST_SIZE(1) | + S_038010_ENDIAN_SWAP(endian) | + S_038010_BASE_LEVEL(0)); + rstate->val[5] = (S_038014_LAST_LEVEL(last_level) | + S_038014_BASE_ARRAY(state->u.tex.first_layer) | + S_038014_LAST_ARRAY(state->u.tex.last_layer)); + rstate->val[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | + S_038018_MAX_ANISO(4 /* max 16 samples */)); + } return &view->base; } @@ -1433,6 +1493,7 @@ static void r600_set_viewport_state(struct pipe_context *ctx, static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, const struct pipe_framebuffer_state *state, int cb) { + struct r600_screen *rscreen = rctx->screen; struct r600_resource_texture *rtex; struct r600_surface *surf; unsigned level = state->cbufs[cb]->u.tex.level; @@ -1451,15 +1512,47 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, 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; } /* XXX quite sure for dx10+ hw don't need any offset hacks */ - offset = r600_texture_get_offset(rtex, - level, state->cbufs[cb]->u.tex.first_layer); - pitch = rtex->pitch_in_blocks[level] / 8 - 1; - slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; + if (!rscreen->use_surface) { + offset = r600_texture_get_offset(rtex, + level, state->cbufs[cb]->u.tex.first_layer); + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64; + if (slice) { + slice = slice - 1; + } + color_info = S_0280A0_ARRAY_MODE(rtex->array_mode[level]); + } else { + 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_info = 0; + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_LINEAR_ALIGNED); + break; + case RADEON_SURF_MODE_1D: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_1D_TILED_THIN1); + break; + case RADEON_SURF_MODE_2D: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_2D_TILED_THIN1); + break; + case RADEON_SURF_MODE_LINEAR: + default: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_LINEAR_GENERAL); + break; + } + } desc = util_format_description(surf->base.format); for (i = 0; i < 4; i++) { @@ -1500,9 +1593,8 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, blend_bypass = 1; } - color_info = S_0280A0_FORMAT(format) | + color_info |= S_0280A0_FORMAT(format) | S_0280A0_COMP_SWAP(swap) | - S_0280A0_ARRAY_MODE(rtex->array_mode[level]) | S_0280A0_BLEND_BYPASS(blend_bypass) | S_0280A0_BLEND_CLAMP(blend_clamp) | S_0280A0_NUMBER_TYPE(ntype) | @@ -1550,9 +1642,23 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, S_028060_PITCH_TILE_MAX(pitch) | S_028060_SLICE_TILE_MAX(slice), NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028080_CB_COLOR0_VIEW + cb * 4, - 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, + R_028080_CB_COLOR0_VIEW + cb * 4, + 0x00000000, NULL, 0); + } else { + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + r600_pipe_state_add_reg(rstate, + R_028080_CB_COLOR0_VIEW + cb * 4, + 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, + R_028080_CB_COLOR0_VIEW + cb * 4, + S_028080_SLICE_START(state->cbufs[cb]->u.tex.first_layer) | + S_028080_SLICE_MAX(state->cbufs[cb]->u.tex.last_layer), + NULL, 0); + } + } r600_pipe_state_add_reg(rstate, R_0280E0_CB_COLOR0_FRAG + cb * 4, 0, &rtex->resource, RADEON_USAGE_READWRITE); @@ -1567,6 +1673,7 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, static void r600_db(struct r600_context *rctx, struct r600_pipe_state *rstate, const struct pipe_framebuffer_state *state) { + struct r600_screen *rscreen = rctx->screen; struct r600_resource_texture *rtex; struct r600_surface *surf; unsigned level, pitch, slice, format, offset, array_mode; @@ -1579,15 +1686,39 @@ static void r600_db(struct r600_context *rctx, struct r600_pipe_state *rstate, surf = (struct r600_surface *)state->zsbuf; rtex = (struct r600_resource_texture*)state->zsbuf->texture; - /* XXX remove this once tiling is properly supported */ - array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : - V_0280A0_ARRAY_1D_TILED_THIN1; + if (!rscreen->use_surface) { + /* XXX remove this once tiling is properly supported */ + array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : + V_0280A0_ARRAY_1D_TILED_THIN1; + + /* XXX quite sure for dx10+ hw don't need any offset hacks */ + offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, + level, state->zsbuf->u.tex.first_layer); + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64; + if (slice) { + slice = slice - 1; + } + } else { + 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; + } + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_2D: + array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_1D: + case RADEON_SURF_MODE_LINEAR_ALIGNED: + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_0280A0_ARRAY_1D_TILED_THIN1; + break; + } + } - /* XXX quite sure for dx10+ hw don't need any offset hacks */ - offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, - level, state->zsbuf->u.tex.first_layer); - pitch = rtex->pitch_in_blocks[level] / 8 - 1; - slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(state->zsbuf->texture->format); r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE, @@ -1595,7 +1726,14 @@ static void r600_db(struct r600_context *rctx, struct r600_pipe_state *rstate, r600_pipe_state_add_reg(rstate, R_028000_DB_DEPTH_SIZE, S_028000_PITCH_TILE_MAX(pitch) | S_028000_SLICE_TILE_MAX(slice), NULL, 0); - r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, + S_028004_SLICE_START(state->zsbuf->u.tex.first_layer) | + S_028004_SLICE_MAX(state->zsbuf->u.tex.last_layer), + NULL, 0); + } r600_pipe_state_add_reg(rstate, R_028010_DB_DEPTH_INFO, S_028010_ARRAY_MODE(array_mode) | S_028010_FORMAT(format), &rtex->resource, RADEON_USAGE_READWRITE); diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 47b440d7027..4e2e600acc0 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -241,6 +241,131 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen, } } +static int r600_init_surface(struct radeon_surface *surface, + const struct pipe_resource *ptex, + unsigned array_mode) +{ + surface->npix_x = ptex->width0; + surface->npix_y = ptex->height0; + surface->npix_z = ptex->depth0; + surface->blk_w = util_format_get_blockwidth(ptex->format); + surface->blk_h = util_format_get_blockheight(ptex->format); + surface->blk_d = 1; + surface->array_size = 1; + surface->last_level = ptex->last_level; + surface->bpe = util_format_get_blocksize(ptex->format); + /* align byte per element on dword */ + if (surface->bpe == 3) { + surface->bpe = 4; + } + surface->nsamples = 1; + surface->flags = 0; + switch (array_mode) { + case V_038000_ARRAY_1D_TILED_THIN1: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + break; + case V_038000_ARRAY_2D_TILED_THIN1: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); + break; + case V_038000_ARRAY_LINEAR_ALIGNED: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); + break; + case V_038000_ARRAY_LINEAR_GENERAL: + default: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + break; + } + switch (ptex->target) { + case PIPE_TEXTURE_1D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE); + break; + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + break; + case PIPE_TEXTURE_3D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE); + break; + case PIPE_TEXTURE_1D_ARRAY: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE); + surface->array_size = ptex->array_size; + break; + case PIPE_TEXTURE_2D_ARRAY: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE); + surface->array_size = ptex->array_size; + break; + case PIPE_TEXTURE_CUBE: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE); + break; + case PIPE_BUFFER: + default: + return -EINVAL; + } + if (ptex->bind & PIPE_BIND_SCANOUT) { + surface->flags |= RADEON_SURF_SCANOUT; + } + if (util_format_is_depth_and_stencil(ptex->format)) { + surface->flags |= RADEON_SURF_ZBUFFER; + surface->flags |= RADEON_SURF_SBUFFER; + } + + return 0; +} + +static int r600_setup_surface(struct pipe_screen *screen, + struct r600_resource_texture *rtex, + unsigned array_mode, + unsigned pitch_in_bytes_override) +{ + struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct r600_screen *rscreen = (struct r600_screen*)screen; + unsigned i; + int r; + + if (util_format_is_depth_or_stencil(rtex->real_format)) { + rtex->surface.flags |= RADEON_SURF_ZBUFFER; + rtex->surface.flags |= RADEON_SURF_SBUFFER; + } + + r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface); + if (r) { + return r; + } + rtex->size = rtex->surface.bo_size; + if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) { + /* old ddx on evergreen over estimate alignment for 1d, only 1 level + * for those + */ + rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe; + rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override; + rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y; + if (rtex->surface.flags & RADEON_SURF_SBUFFER) { + rtex->surface.stencil_offset = rtex->surface.level[0].slice_size; + } + } + for (i = 0; i <= ptex->last_level; i++) { + rtex->offset[i] = rtex->surface.level[i].offset; + rtex->layer_size[i] = rtex->surface.level[i].slice_size; + rtex->pitch_in_bytes[i] = rtex->surface.level[i].pitch_bytes; + switch (rtex->surface.level[i].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + rtex->array_mode[i] = V_038000_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + rtex->array_mode[i] = V_038000_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + rtex->array_mode[i] = V_038000_ARRAY_2D_TILED_THIN1; + break; + default: + case RADEON_SURF_MODE_LINEAR: + rtex->array_mode[i] = 0; + break; + } + } + return 0; +} + static void r600_setup_miptree(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode) @@ -304,7 +429,7 @@ static boolean permit_hardware_blit(struct pipe_screen *screen, /* hackaround for S3TC */ if (util_format_is_compressed(res->format)) return TRUE; - + if (!screen->is_format_supported(screen, res->format, res->target, @@ -369,6 +494,8 @@ static const struct u_resource_vtbl r600_texture_vtbl = u_default_transfer_inline_write /* transfer_inline_write */ }; +DEBUG_GET_ONCE_BOOL_OPTION(use_surface, "R600_SURF", TRUE); + static struct r600_resource_texture * r600_texture_create_object(struct pipe_screen *screen, const struct pipe_resource *base, @@ -376,11 +503,20 @@ r600_texture_create_object(struct pipe_screen *screen, unsigned pitch_in_bytes_override, unsigned max_buffer_size, struct pb_buffer *buf, - boolean alloc_bo) + boolean alloc_bo, + struct radeon_surface *surface) { struct r600_resource_texture *rtex; struct r600_resource *resource; struct r600_screen *rscreen = (struct r600_screen*)screen; + int r; + + /* FIXME ugly temporary hack to allow to switch btw current code + * and common surface allocator code + */ + if (debug_get_option_use_surface()) { + rscreen->use_surface = 1; + } rtex = CALLOC_STRUCT(r600_resource_texture); if (rtex == NULL) @@ -397,7 +533,8 @@ r600_texture_create_object(struct pipe_screen *screen, /* We must split depth and stencil into two separate buffers on Evergreen. */ if (!(base->flags & R600_RESOURCE_FLAG_TRANSFER) && ((struct r600_screen*)screen)->chip_class >= EVERGREEN && - util_format_is_depth_and_stencil(base->format)) { + util_format_is_depth_and_stencil(base->format) && + !rscreen->use_surface) { struct pipe_resource stencil; unsigned stencil_pitch_override = 0; @@ -429,7 +566,7 @@ r600_texture_create_object(struct pipe_screen *screen, stencil.format = PIPE_FORMAT_S8_UINT; rtex->stencil = r600_texture_create_object(screen, &stencil, array_mode, stencil_pitch_override, - max_buffer_size, NULL, FALSE); + max_buffer_size, NULL, FALSE, surface); if (!rtex->stencil) { FREE(rtex); return NULL; @@ -442,6 +579,14 @@ r600_texture_create_object(struct pipe_screen *screen, rtex->depth = 1; r600_setup_miptree(screen, rtex, array_mode); + if (rscreen->use_surface) { + rtex->surface = *surface; + r = r600_setup_surface(screen, rtex, array_mode, pitch_in_bytes_override); + if (r) { + FREE(rtex); + return NULL; + } + } /* If we initialized separate stencil for Evergreen. place it after depth. */ if (rtex->stencil) { @@ -461,6 +606,12 @@ r600_texture_create_object(struct pipe_screen *screen, struct pipe_resource *ptex = &rtex->resource.b.b.b; unsigned base_align = r600_get_base_alignment(screen, ptex->format, array_mode); + if (rscreen->use_surface) { + base_align = rtex->surface.bo_alignment; + } else if (util_format_is_depth_or_stencil(rtex->real_format)) { + /* ugly work around depth buffer need stencil room at end of bo */ + rtex->size += ptex->width0 * ptex->height0; + } if (!r600_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) { pipe_resource_reference((struct pipe_resource**)&rtex->stencil, NULL); FREE(rtex); @@ -480,28 +631,37 @@ r600_texture_create_object(struct pipe_screen *screen, return rtex; } -DEBUG_GET_ONCE_BOOL_OPTION(tiling_enabled, "R600_TILING", FALSE); +DEBUG_GET_ONCE_BOOL_OPTION(tiling_enabled, "R600_TILING", TRUE); struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { struct r600_screen *rscreen = (struct r600_screen*)screen; + struct radeon_surface surface; unsigned array_mode = 0; + int r; if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) && !(templ->bind & PIPE_BIND_SCANOUT)) { - if (util_format_is_compressed(templ->format)) { + if (rscreen->use_surface) { + if (permit_hardware_blit(screen, templ)) { + array_mode = V_038000_ARRAY_2D_TILED_THIN1; + } + } else if (util_format_is_compressed(templ->format)) { array_mode = V_038000_ARRAY_1D_TILED_THIN1; } - else if (debug_get_option_tiling_enabled() && - rscreen->info.drm_minor >= 9 && - permit_hardware_blit(screen, templ)) { - array_mode = V_038000_ARRAY_2D_TILED_THIN1; - } } + r = r600_init_surface(&surface, templ, array_mode); + if (r) { + return NULL; + } + r = rscreen->ws->surface_best(rscreen->ws, &surface); + if (r) { + return NULL; + } return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, - 0, 0, NULL, TRUE); + 0, 0, NULL, TRUE, &surface); } static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, @@ -550,6 +710,8 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, unsigned stride = 0; unsigned array_mode = 0; enum radeon_bo_layout micro, macro; + struct radeon_surface surface; + int r; /* Support only 2D textures without mipmaps */ if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) || @@ -560,7 +722,11 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, if (!buf) return NULL; - rscreen->ws->buffer_get_tiling(buf, µ, ¯o); + rscreen->ws->buffer_get_tiling(buf, µ, ¯o, + &surface.bankw, &surface.bankh, + &surface.tile_split, + &surface.stencil_tile_split, + &surface.mtilea); if (macro == RADEON_LAYOUT_TILED) array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; @@ -569,8 +735,12 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, else array_mode = 0; + r = r600_init_surface(&surface, templ, array_mode); + if (r) { + return NULL; + } return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, - stride, 0, buf, FALSE); + stride, 0, buf, FALSE, &surface); } int r600_texture_depth_flush(struct pipe_context *ctx, diff --git a/src/gallium/targets/dri-r300/Makefile b/src/gallium/targets/dri-r300/Makefile index a1bb753f859..6a8bf6635f7 100644 --- a/src/gallium/targets/dri-r300/Makefile +++ b/src/gallium/targets/dri-r300/Makefile @@ -21,4 +21,6 @@ DRIVER_DEFINES = \ include ../Makefile.dri +DRI_LIB_DEPS += -ldrm_radeon + symlinks: diff --git a/src/gallium/targets/dri-r600/Makefile b/src/gallium/targets/dri-r600/Makefile index 2995b58876b..9cc9cb9f63b 100644 --- a/src/gallium/targets/dri-r600/Makefile +++ b/src/gallium/targets/dri-r600/Makefile @@ -21,6 +21,6 @@ DRIVER_DEFINES = \ include ../Makefile.dri -DRI_LIB_DEPS += +DRI_LIB_DEPS += -ldrm_radeon symlinks: diff --git a/src/gallium/targets/egl-static/Makefile b/src/gallium/targets/egl-static/Makefile index 70e4362ef1f..02a55eef160 100644 --- a/src/gallium/targets/egl-static/Makefile +++ b/src/gallium/targets/egl-static/Makefile @@ -115,6 +115,7 @@ egl_CPPFLAGS += -D_EGL_PIPE_R300=1 egl_LIBS += \ $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/r300/libr300.a +egl_SYS += -ldrm_radeon endif endif @@ -125,6 +126,7 @@ egl_CPPFLAGS += -D_EGL_PIPE_R600=1 egl_LIBS += \ $(TOP)/src/gallium/winsys/radeon/drm/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/r600/libr600.a +egl_SYS += -ldrm_radeon endif endif diff --git a/src/gallium/targets/va-r300/Makefile b/src/gallium/targets/va-r300/Makefile index 3e0797b65a0..a270dfa7c99 100644 --- a/src/gallium/targets/va-r300/Makefile +++ b/src/gallium/targets/va-r300/Makefile @@ -19,7 +19,7 @@ C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ $(DRIVER_SOURCES) -DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes +DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes -ldrm_radeon include ../Makefile.va diff --git a/src/gallium/targets/va-r600/Makefile b/src/gallium/targets/va-r600/Makefile index bab18fea2ac..afead84391b 100644 --- a/src/gallium/targets/va-r600/Makefile +++ b/src/gallium/targets/va-r600/Makefile @@ -19,7 +19,7 @@ C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ $(DRIVER_SOURCES) -DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes +DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes -ldrm_radeon include ../Makefile.va diff --git a/src/gallium/targets/vdpau-r300/Makefile b/src/gallium/targets/vdpau-r300/Makefile index 95988bdc652..849f72e03e8 100644 --- a/src/gallium/targets/vdpau-r300/Makefile +++ b/src/gallium/targets/vdpau-r300/Makefile @@ -20,7 +20,7 @@ C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ $(DRIVER_SOURCES) -DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes +DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes -ldrm_radeon include ../Makefile.vdpau diff --git a/src/gallium/targets/vdpau-r600/Makefile b/src/gallium/targets/vdpau-r600/Makefile index 466e80eadf9..ef27b6572c2 100644 --- a/src/gallium/targets/vdpau-r600/Makefile +++ b/src/gallium/targets/vdpau-r600/Makefile @@ -15,7 +15,7 @@ C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ $(DRIVER_SOURCES) -DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes +DRIVER_LIBS = $(shell $(PKG_CONFIG) libdrm --libs) -lXfixes -ldrm_radeon include ../Makefile.vdpau diff --git a/src/gallium/targets/xorg-r300/Makefile b/src/gallium/targets/xorg-r300/Makefile index 26cc5590d7d..45bb3d7e701 100644 --- a/src/gallium/targets/xorg-r300/Makefile +++ b/src/gallium/targets/xorg-r300/Makefile @@ -19,6 +19,6 @@ DRIVER_PIPES = \ $(TOP)/src/gallium/drivers/rbug/librbug.a DRIVER_LINKS = \ - $(shell $(PKG_CONFIG) --libs libdrm) + $(shell $(PKG_CONFIG) --libs libdrm libdrm_radeon) include ../Makefile.xorg diff --git a/src/gallium/targets/xorg-r600/Makefile b/src/gallium/targets/xorg-r600/Makefile index 3c0cc83711c..fd973304f2c 100644 --- a/src/gallium/targets/xorg-r600/Makefile +++ b/src/gallium/targets/xorg-r600/Makefile @@ -19,6 +19,6 @@ DRIVER_PIPES = \ $(TOP)/src/gallium/drivers/rbug/librbug.a DRIVER_LINKS = \ - $(shell $(PKG_CONFIG) --libs libdrm) + $(shell $(PKG_CONFIG) --libs libdrm libdrm_radeon) include ../Makefile.xorg diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index de2906faef9..adee7b20dbc 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -620,9 +620,28 @@ static void *radeon_bo_map(struct pb_buffer *buf, return pb_map(buf, get_pb_usage_from_transfer_flags(usage), cs); } +static unsigned eg_tile_split(unsigned tile_split) +{ + switch (tile_split) { + case 0: tile_split = 64; break; + case 1: tile_split = 128; break; + case 2: tile_split = 256; break; + case 3: tile_split = 512; break; + default: + case 4: tile_split = 1024; break; + case 5: tile_split = 2048; break; + case 6: tile_split = 4096; break; + } + return tile_split; +} + static void radeon_bo_get_tiling(struct pb_buffer *_buf, enum radeon_bo_layout *microtiled, - enum radeon_bo_layout *macrotiled) + enum radeon_bo_layout *macrotiled, + unsigned *bankw, unsigned *bankh, + unsigned *tile_split, + unsigned *stencil_tile_split, + unsigned *mtilea) { struct radeon_bo *bo = get_radeon_bo(_buf); struct drm_radeon_gem_set_tiling args; @@ -643,6 +662,14 @@ static void radeon_bo_get_tiling(struct pb_buffer *_buf, if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE) *macrotiled = RADEON_LAYOUT_TILED; + if (bankw && tile_split && stencil_tile_split && mtilea && tile_split) { + *bankw = (args.tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; + *bankh = (args.tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; + *tile_split = (args.tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK; + *stencil_tile_split = (args.tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; + *mtilea = (args.tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; + *tile_split = eg_tile_split(*tile_split); + } } static void radeon_bo_set_tiling(struct pb_buffer *_buf, diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index 051a390ed22..dbec259d7f3 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -302,6 +302,7 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) ws->cman->destroy(ws->cman); ws->kman->destroy(ws->kman); + radeon_surface_manager_free(ws->surf_man); FREE(rws); } @@ -339,6 +340,22 @@ static boolean radeon_cs_request_feature(struct radeon_winsys_cs *rcs, return FALSE; } +static int radeon_drm_winsys_surface_init(struct radeon_winsys *rws, + struct radeon_surface *surf) +{ + struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; + + return radeon_surface_init(ws->surf_man, surf); +} + +static int radeon_drm_winsys_surface_best(struct radeon_winsys *rws, + struct radeon_surface *surf) +{ + struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws; + + return radeon_surface_best(ws->surf_man, surf); +} + struct radeon_winsys *radeon_drm_winsys_create(int fd) { struct radeon_drm_winsys *ws = CALLOC_STRUCT(radeon_drm_winsys); @@ -359,10 +376,17 @@ struct radeon_winsys *radeon_drm_winsys_create(int fd) if (!ws->cman) goto fail; + /* FIXME check for libdrm version ?? */ + ws->surf_man = radeon_surface_manager_new(fd); + if (!ws->surf_man) + goto fail; + /* Set functions. */ ws->base.destroy = radeon_winsys_destroy; ws->base.query_info = radeon_query_info; ws->base.cs_request_feature = radeon_cs_request_feature; + ws->base.surface_init = radeon_drm_winsys_surface_init; + ws->base.surface_best = radeon_drm_winsys_surface_best; radeon_bomgr_init_functions(ws); radeon_drm_cs_init_functions(ws); @@ -377,6 +401,8 @@ fail: ws->cman->destroy(ws->cman); if (ws->kman) ws->kman->destroy(ws->kman); + if (ws->surf_man) + radeon_surface_manager_free(ws->surf_man); FREE(ws); return NULL; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h index 69216448496..6ac86bcfabb 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h @@ -49,6 +49,7 @@ struct radeon_drm_winsys { struct pb_manager *kman; struct pb_manager *cman; + struct radeon_surface_manager *surf_man; uint32_t num_cpus; /* Number of CPUs. */ diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index 9afd7f8ac82..6fbe765d6b1 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -43,6 +43,7 @@ #include "pipebuffer/pb_bufmgr.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "libdrm/radeon_surface.h" #define RADEON_MAX_CMDBUF_DWORDS (16 * 1024) @@ -200,7 +201,11 @@ struct radeon_winsys { */ void (*buffer_get_tiling)(struct pb_buffer *buf, enum radeon_bo_layout *microtile, - enum radeon_bo_layout *macrotile); + enum radeon_bo_layout *macrotile, + unsigned *bankw, unsigned *bankh, + unsigned *tile_split, + unsigned *stencil_tile_split, + unsigned *mtilea); /** * Set tiling flags describing a memory layout of a buffer object. @@ -347,6 +352,24 @@ struct radeon_winsys { boolean (*cs_request_feature)(struct radeon_winsys_cs *cs, enum radeon_feature_id fid, boolean enable); + + /** + * Initialize surface + * + * \param ws The winsys this function is called from. + * \param surf Surface structure ptr + */ + int (*surface_init)(struct radeon_winsys *ws, + struct radeon_surface *surf); + + /** + * Find best values for a surface + * + * \param ws The winsys this function is called from. + * \param surf Surface structure ptr + */ + int (*surface_best)(struct radeon_winsys *ws, + struct radeon_surface *surf); }; #endif -- 2.30.2