diff options
author | Jerome Glisse <jglisse@redhat.com> | 2010-07-27 20:15:17 -0400 |
---|---|---|
committer | Jerome Glisse <jglisse@redhat.com> | 2010-07-27 20:18:32 -0400 |
commit | 641c9adb09e8707f659d42be600d16902ebf8895 (patch) | |
tree | db9200b3266bbc931c2b2636ca31fe5c158b80a5 /src/gallium/drivers/r600/r600_state.c | |
parent | 25472942c9640f6c0d252de2f013d04ac2355b1d (diff) |
r600g: texture support
Add texture mapping support, redbook/texbind works if
you comment out glClear and second checkboard. Need to
fix :
- texture overwritting
- lod & mip/map handling
- unormalized coordinate handling
- texture view with first leve > 0
- and many other things
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Diffstat (limited to 'src/gallium/drivers/r600/r600_state.c')
-rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 277 |
1 files changed, 271 insertions, 6 deletions
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 84a13e4ef7..6503c3740e 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -187,6 +187,8 @@ static void *r600_create_rs_state(struct pipe_context *ctx, struct radeon_state *rstate; rctx->flat_shade = state->flatshade; + rctx->flat_shade = 0; +R600_ERR("flat shade with texture broke tex coord interp\n"); rstate = radeon_state(rscreen->rw, R600_RASTERIZER_TYPE, R600_RASTERIZER); if (rstate == NULL) return NULL; @@ -224,43 +226,306 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state) radeon_draw_set(rctx->draw, state); } +static inline unsigned r600_tex_wrap(unsigned wrap) +{ + switch (wrap) { + default: + case PIPE_TEX_WRAP_REPEAT: + return V_03C000_SQ_TEX_WRAP; + case PIPE_TEX_WRAP_CLAMP: + return V_03C000_SQ_TEX_CLAMP_LAST_TEXEL; + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + return V_03C000_SQ_TEX_CLAMP_HALF_BORDER; + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + return V_03C000_SQ_TEX_CLAMP_BORDER; + case PIPE_TEX_WRAP_MIRROR_REPEAT: + return V_03C000_SQ_TEX_MIRROR; + case PIPE_TEX_WRAP_MIRROR_CLAMP: + return V_03C000_SQ_TEX_MIRROR_ONCE_LAST_TEXEL; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + return V_03C000_SQ_TEX_MIRROR_ONCE_HALF_BORDER; + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + return V_03C000_SQ_TEX_MIRROR_ONCE_BORDER; + } +} + +static inline unsigned r600_tex_filter(unsigned filter) +{ + switch (filter) { + default: + case PIPE_TEX_FILTER_NEAREST: + return V_03C000_SQ_TEX_XY_FILTER_POINT; + case PIPE_TEX_FILTER_LINEAR: + return V_03C000_SQ_TEX_XY_FILTER_BILINEAR; + } +} + +static inline unsigned r600_tex_mipfilter(unsigned filter) +{ + switch (filter) { + case PIPE_TEX_MIPFILTER_NEAREST: + return V_03C000_SQ_TEX_Z_FILTER_POINT; + case PIPE_TEX_MIPFILTER_LINEAR: + return V_03C000_SQ_TEX_Z_FILTER_LINEAR; + default: + case PIPE_TEX_MIPFILTER_NONE: + return V_03C000_SQ_TEX_Z_FILTER_NONE; + } +} + +static inline unsigned r600_tex_compare(unsigned compare) +{ + switch (compare) { + default: + case PIPE_FUNC_NEVER: + return V_03C000_SQ_TEX_DEPTH_COMPARE_NEVER; + case PIPE_FUNC_LESS: + return V_03C000_SQ_TEX_DEPTH_COMPARE_LESS; + case PIPE_FUNC_EQUAL: + return V_03C000_SQ_TEX_DEPTH_COMPARE_EQUAL; + case PIPE_FUNC_LEQUAL: + return V_03C000_SQ_TEX_DEPTH_COMPARE_LESSEQUAL; + case PIPE_FUNC_GREATER: + return V_03C000_SQ_TEX_DEPTH_COMPARE_GREATER; + case PIPE_FUNC_NOTEQUAL: + return V_03C000_SQ_TEX_DEPTH_COMPARE_NOTEQUAL; + case PIPE_FUNC_GEQUAL: + return V_03C000_SQ_TEX_DEPTH_COMPARE_GREATEREQUAL; + case PIPE_FUNC_ALWAYS: + return V_03C000_SQ_TEX_DEPTH_COMPARE_ALWAYS; + } +} + static void *r600_create_sampler_state(struct pipe_context *ctx, const struct pipe_sampler_state *state) { - return NULL; + struct r600_screen *rscreen = r600_screen(ctx->screen); + struct radeon_state *rstate; + + rstate = radeon_state(rscreen->rw, R600_PS_SAMPLER_TYPE, R600_PS_SAMPLER); + if (rstate == NULL) + return NULL; + rstate->states[R600_PS_SAMPLER__SQ_TEX_SAMPLER_WORD0_0] = + S_03C000_CLAMP_X(r600_tex_wrap(state->wrap_s)) | + S_03C000_CLAMP_Y(r600_tex_wrap(state->wrap_t)) | + S_03C000_CLAMP_Z(r600_tex_wrap(state->wrap_r)) | + S_03C000_XY_MAG_FILTER(r600_tex_filter(state->mag_img_filter)) | + S_03C000_XY_MIN_FILTER(r600_tex_filter(state->min_img_filter)) | + S_03C000_MIP_FILTER(r600_tex_mipfilter(state->min_mip_filter)) | + S_03C000_DEPTH_COMPARE_FUNCTION(r600_tex_compare(state->compare_func)); + /* FIXME LOD it depends on texture base level ... */ + rstate->states[R600_PS_SAMPLER__SQ_TEX_SAMPLER_WORD1_0] = + S_03C004_MIN_LOD(0) | + S_03C004_MAX_LOD(0) | + S_03C004_LOD_BIAS(0); + rstate->states[R600_PS_SAMPLER__SQ_TEX_SAMPLER_WORD2_0] = S_03C008_TYPE(1); + if (radeon_state_pm4(rstate)) { + radeon_state_decref(rstate); + return NULL; + } + return rstate; } static void r600_bind_sampler_states(struct pipe_context *ctx, unsigned count, void **states) { + struct r600_context *rctx = r600_context(ctx); + unsigned i; + + /* FIXME split VS/PS/GS sampler */ + for (i = 0; i < count; i++) { + rctx->ps_sampler[i] = radeon_state_decref(rctx->ps_sampler[i]); + } + rctx->nps_sampler = count; + for (i = 0; i < count; i++) { + rctx->ps_sampler[i] = radeon_state_incref(states[i]); + rctx->ps_sampler[i]->id = R600_PS_SAMPLER + i; + } +} + +static inline unsigned r600_tex_swizzle(unsigned swizzle) +{ + switch (swizzle) { + case PIPE_SWIZZLE_RED: + return V_038010_SQ_SEL_X; + case PIPE_SWIZZLE_GREEN: + return V_038010_SQ_SEL_Y; + case PIPE_SWIZZLE_BLUE: + return V_038010_SQ_SEL_Z; + case PIPE_SWIZZLE_ALPHA: + return V_038010_SQ_SEL_W; + case PIPE_SWIZZLE_ZERO: + return V_038010_SQ_SEL_0; + default: + case PIPE_SWIZZLE_ONE: + return V_038010_SQ_SEL_1; + } +} + +static inline unsigned r600_format_type(unsigned format_type) +{ + switch (format_type) { + default: + case UTIL_FORMAT_TYPE_UNSIGNED: + return V_038010_SQ_FORMAT_COMP_UNSIGNED; + case UTIL_FORMAT_TYPE_SIGNED: + return V_038010_SQ_FORMAT_COMP_SIGNED; + case UTIL_FORMAT_TYPE_FIXED: + return V_038010_SQ_FORMAT_COMP_UNSIGNED_BIASED; + } +} + +static inline unsigned r600_tex_dim(unsigned dim) +{ + switch (dim) { + default: + case PIPE_TEXTURE_1D: + return V_038000_SQ_TEX_DIM_1D; + case PIPE_TEXTURE_2D: + return V_038000_SQ_TEX_DIM_2D; + case PIPE_TEXTURE_3D: + return V_038000_SQ_TEX_DIM_3D; + case PIPE_TEXTURE_CUBE: + return V_038000_SQ_TEX_DIM_CUBEMAP; + } } static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *ctx, struct pipe_resource *texture, - const struct pipe_sampler_view *templ) + const struct pipe_sampler_view *view) { - struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); + struct r600_screen *rscreen = r600_screen(ctx->screen); + struct r600_texture_resource *rtexture; + const struct util_format_description *desc; + struct r600_texture *tmp; + struct r600_buffer *rbuffer; + unsigned format; - *view = *templ; - return view; + if (r600_conv_pipe_format(texture->format, &format)) + return NULL; + rtexture = CALLOC_STRUCT(r600_texture_resource); + if (rtexture == NULL) + return NULL; + desc = util_format_description(texture->format); + assert(desc == NULL); + rtexture->state = radeon_state(rscreen->rw, R600_PS_RESOURCE_TYPE, R600_PS_RESOURCE); + if (rtexture->state == NULL) { + FREE(rtexture); + return NULL; + } + rtexture->view = *view; + rtexture->view.reference.count = 1; + rtexture->view.texture = NULL; + pipe_resource_reference(&rtexture->view.texture, texture); + rtexture->view.context = ctx; + + tmp = (struct r600_texture*)texture; + rbuffer = (struct r600_buffer*)tmp->buffer; + rtexture->state->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo); + rtexture->state->bo[1] = radeon_bo_incref(rscreen->rw, rbuffer->bo); + rtexture->state->nbo = 2; + rtexture->state->placement[0] = RADEON_GEM_DOMAIN_GTT; + rtexture->state->placement[1] = RADEON_GEM_DOMAIN_GTT; + rtexture->state->placement[2] = RADEON_GEM_DOMAIN_GTT; + rtexture->state->placement[3] = RADEON_GEM_DOMAIN_GTT; + + /* FIXME properly handle first level != 0 */ + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD0] = + S_038000_DIM(r600_tex_dim(texture->target)) | + S_038000_PITCH((tmp->pitch[0] / 8) - 1) | + S_038000_TEX_WIDTH(texture->width0 - 1); + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD1] = + S_038004_TEX_HEIGHT(texture->height0 - 1) | + S_038004_TEX_DEPTH(texture->depth0 - 1) | + S_038004_DATA_FORMAT(format); + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD2] = 0; + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD3] = tmp->offset[1] >> 8; + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD4] = + S_038010_FORMAT_COMP_X(r600_format_type(UTIL_FORMAT_TYPE_UNSIGNED)) | + S_038010_FORMAT_COMP_Y(r600_format_type(UTIL_FORMAT_TYPE_UNSIGNED)) | + S_038010_FORMAT_COMP_Z(r600_format_type(UTIL_FORMAT_TYPE_UNSIGNED)) | + S_038010_FORMAT_COMP_W(r600_format_type(UTIL_FORMAT_TYPE_UNSIGNED)) | + S_038010_NUM_FORMAT_ALL(V_038010_SQ_NUM_FORMAT_NORM) | + S_038010_SRF_MODE_ALL(V_038010_SFR_MODE_NO_ZERO) | + S_038010_REQUEST_SIZE(1) | + S_038010_DST_SEL_X(r600_tex_swizzle(view->swizzle_r)) | + S_038010_DST_SEL_Y(r600_tex_swizzle(view->swizzle_g)) | + S_038010_DST_SEL_Z(r600_tex_swizzle(view->swizzle_b)) | + S_038010_DST_SEL_W(r600_tex_swizzle(view->swizzle_a)) | + S_038010_BASE_LEVEL(view->first_level); + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD5] = + S_038014_LAST_LEVEL(view->last_level) | + S_038014_BASE_ARRAY(0) | + S_038014_LAST_ARRAY(0); + rtexture->state->states[R600_PS_RESOURCE__RESOURCE0_WORD6] = + S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE); + return &rtexture->view; } static void r600_sampler_view_destroy(struct pipe_context *ctx, struct pipe_sampler_view *view) { - FREE(view); + struct r600_texture_resource *texture; + + if (view == NULL) + return; + texture = LIST_ENTRY(struct r600_texture_resource, view, view); + radeon_state_decref(texture->state); + FREE(texture); } static void r600_set_fragment_sampler_views(struct pipe_context *ctx, unsigned count, struct pipe_sampler_view **views) { + struct r600_texture_resource *rtexture; + struct r600_context *rctx = r600_context(ctx); + struct pipe_sampler_view *tmp; + unsigned i; + + if (views == NULL) + return; + + for (i = 0; i < rctx->nps_view; i++) { + tmp = &rctx->ps_view[i]->view; + pipe_sampler_view_reference(&tmp, NULL); + rctx->ps_view[i] = NULL; + } + rctx->nps_view = count; + for (i = 0; i < count; i++) { + rtexture = LIST_ENTRY(struct r600_texture_resource, views[i], view); + rctx->ps_view[i] = rtexture; + tmp = NULL; + pipe_sampler_view_reference(&tmp, views[i]); + rtexture->state->id = R600_PS_RESOURCE + i; + } } static void r600_set_vertex_sampler_views(struct pipe_context *ctx, unsigned count, struct pipe_sampler_view **views) { + struct r600_texture_resource *rtexture; + struct r600_context *rctx = r600_context(ctx); + struct pipe_sampler_view *tmp; + unsigned i; + + if (views == NULL) + return; + + for (i = 0; i < rctx->nvs_view; i++) { + tmp = &rctx->vs_view[i]->view; + pipe_sampler_view_reference(&tmp, NULL); + rctx->vs_view[i] = NULL; + } + rctx->nps_view = count; + for (i = 0; i < count; i++) { + rtexture = LIST_ENTRY(struct r600_texture_resource, views[i], view); + rctx->vs_view[i] = rtexture; + tmp = NULL; + pipe_sampler_view_reference(&tmp, views[i]); + rtexture->state->id = R600_VS_RESOURCE + i; + } } static void r600_set_scissor_state(struct pipe_context *ctx, |