summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi/si_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeonsi/si_state.c')
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c52
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)