radeonsi: Texture border colour fixes.
authorMichel Dänzer <michel.daenzer@amd.com>
Fri, 7 Sep 2012 14:09:08 +0000 (16:09 +0200)
committerMichel Dänzer <michel@daenzer.net>
Tue, 11 Sep 2012 09:06:56 +0000 (11:06 +0200)
* Handle arbitrary border colours.
* Use correct packing format for detecting special border colours.

Fixes piglit tex-border-1 and probably many other tests using border colours.

Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/radeonsi/radeonsi_pipe.c
src/gallium/drivers/radeonsi/radeonsi_pipe.h
src/gallium/drivers/radeonsi/si_state.c

index 9d7ac51..03fe88d 100644 (file)
@@ -172,6 +172,8 @@ static void r600_destroy_context(struct pipe_context *context)
 {
        struct r600_context *rctx = (struct r600_context *)context;
 
+       si_resource_reference(&rctx->border_color_table, NULL);
+
        if (rctx->dummy_pixel_shader) {
                rctx->context.delete_fs_state(&rctx->context, rctx->dummy_pixel_shader);
        }
index a23f34f..4253dbb 100644 (file)
@@ -76,6 +76,7 @@ struct si_pipe_sampler_view {
 
 struct si_pipe_sampler_state {
        uint32_t                        val[4];
+       float                           border_color[4];
 };
 
 /* needed for blitter save */
@@ -137,6 +138,8 @@ struct r600_context {
        boolean                         alpha_ref_dirty;
        struct r600_textures_info       vs_samplers;
        struct r600_textures_info       ps_samplers;
+       struct si_resource              *border_color_table;
+       unsigned                        border_color_offset;
        boolean                         shader_dirty;
 
        struct u_upload_mgr             *uploader;
index 5240036..80da068 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/u_memory.h"
 #include "util/u_framebuffer.h"
 #include "util/u_blitter.h"
+#include "util/u_math.h"
 #include "util/u_pack_color.h"
 #include "tgsi/tgsi_parse.h"
 #include "radeonsi_pipe.h"
@@ -2198,7 +2199,7 @@ static void *si_create_sampler_state(struct pipe_context *ctx,
                return NULL;
        }
 
-       util_pack_color(state->border_color.f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
+       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;
@@ -2229,14 +2230,11 @@ static void *si_create_sampler_state(struct pipe_context *ctx,
                          S_008F38_MIP_FILTER(si_tex_mipfilter(state->min_mip_filter)));
        rstate->val[3] = S_008F3C_BORDER_COLOR_TYPE(border_color_type);
 
-#if 0
-       if (border_color_type == 3) {
-               si_pm4_set_reg(pm4, R_00A404_TD_PS_SAMPLER0_BORDER_RED, fui(state->border_color.f[0]));
-               si_pm4_set_reg(pm4, R_00A408_TD_PS_SAMPLER0_BORDER_GREEN, fui(state->border_color.f[1]));
-               si_pm4_set_reg(pm4, R_00A40C_TD_PS_SAMPLER0_BORDER_BLUE, fui(state->border_color.f[2]));
-               si_pm4_set_reg(pm4, R_00A410_TD_PS_SAMPLER0_BORDER_ALPHA, fui(state->border_color.f[3]));
+       if (border_color_type == V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER) {
+               memcpy(rstate->border_color, state->border_color.f,
+                      sizeof(rstate->border_color));
        }
-#endif
+
        return rstate;
 }
 
@@ -2300,6 +2298,7 @@ static void si_bind_ps_sampler(struct pipe_context *ctx, unsigned count, void **
        struct r600_context *rctx = (struct r600_context *)ctx;
        struct si_pipe_sampler_state **rstates = (struct si_pipe_sampler_state **)states;
        struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state);
+       uint32_t *border_color_table = NULL;
        int i, j;
 
        if (!count)
@@ -2309,12 +2308,56 @@ static void si_bind_ps_sampler(struct pipe_context *ctx, unsigned count, void **
 
        si_pm4_sh_data_begin(pm4);
        for (i = 0; i < count; i++) {
+               if (rstates[i] &&
+                   G_008F3C_BORDER_COLOR_TYPE(rstates[i]->val[3]) ==
+                   V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER) {
+                       if (!rctx->border_color_table ||
+                           ((rctx->border_color_offset + count - i) &
+                            C_008F3C_BORDER_COLOR_PTR)) {
+                               si_resource_reference(&rctx->border_color_table, NULL);
+                               rctx->border_color_offset = 0;
+
+                               rctx->border_color_table =
+                                       si_resource_create_custom(ctx->screen,
+                                                                 PIPE_USAGE_STAGING,
+                                                                 4096 * 4 * 4);
+                       }
+
+                       if (!border_color_table) {
+                               border_color_table =
+                                       rctx->ws->buffer_map(rctx->border_color_table->cs_buf,
+                                                            rctx->cs,
+                                                            PIPE_TRANSFER_WRITE |
+                                                            PIPE_TRANSFER_UNSYNCHRONIZED);
+                       }
+
+                       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);
+                       }
+
+                       rstates[i]->val[3] &= C_008F3C_BORDER_COLOR_PTR;
+                       rstates[i]->val[3] |= S_008F3C_BORDER_COLOR_PTR(rctx->border_color_offset++);
+               }
+
                for (j = 0; j < Elements(rstates[i]->val); ++j) {
                        si_pm4_sh_data_add(pm4, rstates[i] ? rstates[i]->val[j] : 0);
                }
        }
        si_pm4_sh_data_end(pm4, R_00B038_SPI_SHADER_USER_DATA_PS_2);
 
+       if (border_color_table) {
+               uint64_t va_offset =
+                       r600_resource_va(ctx->screen, (void*)rctx->border_color_table);
+
+               si_pm4_set_reg(pm4, R_028080_TA_BC_BASE_ADDR, va_offset >> 8);
+               rctx->ws->buffer_unmap(rctx->border_color_table->cs_buf);
+               si_pm4_add_bo(pm4, rctx->border_color_table, RADEON_USAGE_READ);
+       }
+
        memcpy(rctx->ps_samplers.samplers, states, sizeof(void*) * count);
 
 out: