radeonsi: Make border colour state handling safe for integer textures
authorMichel Dänzer <michel.daenzer@amd.com>
Wed, 1 May 2013 16:15:36 +0000 (18:15 +0200)
committerMichel Dänzer <michel@daenzer.net>
Tue, 28 May 2013 07:55:46 +0000 (09:55 +0200)
src/gallium/drivers/radeonsi/radeonsi_pipe.h
src/gallium/drivers/radeonsi/si_state.c

index 32740498b11ea15b15f8cc892149ddea6923ef88..67cb14b7cc0db19b7ffb7c9cd6e85d92964b4e97 100644 (file)
@@ -87,7 +87,7 @@ struct si_pipe_sampler_view {
 
 struct si_pipe_sampler_state {
        uint32_t                        val[4];
-       float                           border_color[4];
+       uint32_t                        border_color[4];
 };
 
 struct si_cs_shader_state {
index e7dc792b93cc8bdbfd06c1a52f2b583f7b0081ab..4556be699cb6100291ade0711634b193afac06b8 100644 (file)
@@ -2273,11 +2273,31 @@ static void si_sampler_view_destroy(struct pipe_context *ctx,
        FREE(resource);
 }
 
+static bool wrap_mode_uses_border_color(unsigned wrap, bool linear_filter)
+{
+       return wrap == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
+              wrap == PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER ||
+              (linear_filter &&
+               (wrap == PIPE_TEX_WRAP_CLAMP ||
+                wrap == PIPE_TEX_WRAP_MIRROR_CLAMP));
+}
+
+static bool sampler_state_needs_border_color(const struct pipe_sampler_state *state)
+{
+       bool linear_filter = state->min_img_filter != PIPE_TEX_FILTER_NEAREST ||
+                            state->mag_img_filter != PIPE_TEX_FILTER_NEAREST;
+
+       return (state->border_color.ui[0] || state->border_color.ui[1] ||
+               state->border_color.ui[2] || state->border_color.ui[3]) &&
+              (wrap_mode_uses_border_color(state->wrap_s, linear_filter) ||
+               wrap_mode_uses_border_color(state->wrap_t, linear_filter) ||
+               wrap_mode_uses_border_color(state->wrap_r, linear_filter));
+}
+
 static void *si_create_sampler_state(struct pipe_context *ctx,
                                     const struct pipe_sampler_state *state)
 {
        struct si_pipe_sampler_state *rstate = CALLOC_STRUCT(si_pipe_sampler_state);
-       union util_color uc;
        unsigned aniso_flag_offset = state->max_anisotropy > 1 ? 2 : 0;
        unsigned border_color_type;
 
@@ -2285,20 +2305,10 @@ static void *si_create_sampler_state(struct pipe_context *ctx,
                return NULL;
        }
 
-       util_pack_color(state->border_color.f, PIPE_FORMAT_A8R8G8B8_UNORM, &uc);
-       switch (uc.ui) {
-       case 0x000000FF:
-               border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK;
-               break;
-       case 0x00000000:
-               border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK;
-               break;
-       case 0xFFFFFFFF:
-               border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE;
-               break;
-       default: /* Use border color pointer */
+       if (sampler_state_needs_border_color(state))
                border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER;
-       }
+       else
+               border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK;
 
        rstate->val[0] = (S_008F30_CLAMP_X(si_tex_wrap(state->wrap_s)) |
                          S_008F30_CLAMP_Y(si_tex_wrap(state->wrap_t)) |
@@ -2317,7 +2327,7 @@ static void *si_create_sampler_state(struct pipe_context *ctx,
        rstate->val[3] = S_008F3C_BORDER_COLOR_TYPE(border_color_type);
 
        if (border_color_type == V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER) {
-               memcpy(rstate->border_color, state->border_color.f,
+               memcpy(rstate->border_color, state->border_color.ui,
                       sizeof(rstate->border_color));
        }
 
@@ -2440,11 +2450,8 @@ static struct si_pm4_state *si_bind_sampler(struct r600_context *rctx, unsigned
                        }
 
                        for (j = 0; j < 4; j++) {
-                               union fi border_color;
-
-                               border_color.f = rstates[i]->border_color[j];
                                border_color_table[4 * rctx->border_color_offset + j] =
-                                       util_le32_to_cpu(border_color.i);
+                                       util_le32_to_cpu(rstates[i]->border_color[j]);
                        }
 
                        rstates[i]->val[3] &= C_008F3C_BORDER_COLOR_PTR;