summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r600/r600_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r600/r600_state.c')
-rw-r--r--src/gallium/drivers/r600/r600_state.c277
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 84a13e4ef7a..6503c3740e8 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,