diff options
Diffstat (limited to 'src/gallium/drivers/radeonsi/si_state.c')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 2deee4516d9..fb353ad419d 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -32,6 +32,7 @@ #include "util/u_format.h" #include "util/u_format_s3tc.h" #include "util/u_memory.h" +#include "util/u_pstipple.h" static void si_init_atom(struct r600_atom *atom, struct r600_atom **list_elem, void (*emit)(struct si_context *ctx, struct r600_atom *state), @@ -616,6 +617,7 @@ static void *si_create_rs_state(struct pipe_context *ctx, rs->multisample_enable = state->multisample; rs->clip_plane_enable = state->clip_plane_enable; rs->line_stipple_enable = state->line_stipple_enable; + rs->poly_stipple_enable = state->poly_stipple_enable; polygon_dual_mode = (state->fill_front != PIPE_POLYGON_MODE_FILL || state->fill_back != PIPE_POLYGON_MODE_FILL); @@ -2760,6 +2762,56 @@ static void si_set_index_buffer(struct pipe_context *ctx, static void si_set_polygon_stipple(struct pipe_context *ctx, const struct pipe_poly_stipple *state) { + struct si_context *sctx = (struct si_context *)ctx; + struct pipe_resource *tex; + struct pipe_sampler_view *view; + bool is_zero = true; + bool is_one = true; + int i; + + /* The hardware obeys 0 and 1 swizzles in the descriptor even if + * the resource is NULL/invalid. Take advantage of this fact and skip + * texture allocation if the stipple pattern is constant. + * + * This is an optimization for the common case when stippling isn't + * used but set_polygon_stipple is still called by st/mesa. + */ + for (i = 0; i < Elements(state->stipple); i++) { + is_zero = is_zero && state->stipple[i] == 0; + is_one = is_one && state->stipple[i] == 0xffffffff; + } + + if (is_zero || is_one) { + struct pipe_sampler_view templ = {{0}}; + + templ.swizzle_r = PIPE_SWIZZLE_ZERO; + templ.swizzle_g = PIPE_SWIZZLE_ZERO; + templ.swizzle_b = PIPE_SWIZZLE_ZERO; + /* The pattern should be inverted in the texture. */ + templ.swizzle_a = is_zero ? PIPE_SWIZZLE_ONE : PIPE_SWIZZLE_ZERO; + + view = ctx->create_sampler_view(ctx, NULL, &templ); + } else { + /* Create a new texture. */ + tex = util_pstipple_create_stipple_texture(ctx, state->stipple); + if (!tex) + return; + + view = util_pstipple_create_sampler_view(ctx, tex); + pipe_resource_reference(&tex, NULL); + } + + ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, + SI_POLY_STIPPLE_SAMPLER, 1, &view); + pipe_sampler_view_reference(&view, NULL); + + /* Bind the sampler state if needed. */ + if (!sctx->pstipple_sampler_state) { + sctx->pstipple_sampler_state = util_pstipple_create_sampler(ctx); + ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, + SI_POLY_STIPPLE_SAMPLER, 1, + &sctx->pstipple_sampler_state); + } } static void si_texture_barrier(struct pipe_context *ctx) |