radeonsi: update copyrights
[mesa.git] / src / gallium / drivers / radeonsi / si_state_viewport.c
index 8e08a61f2f61b2fb1ce1f642b4598fb55a084407..d02542e4c10e2f34a2b13169c70bff6a40e49db8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2012 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -40,7 +41,8 @@ static void si_set_scissor_states(struct pipe_context *pctx,
        for (i = 0; i < num_scissors; i++)
                ctx->scissors.states[start_slot + i] = state[i];
 
-       if (!ctx->scissor_enabled)
+       if (!ctx->queued.named.rasterizer ||
+           !ctx->queued.named.rasterizer->scissor_enable)
                return;
 
        ctx->scissors.dirty_mask |= ((1 << num_scissors) - 1) << start_slot;
@@ -62,13 +64,6 @@ static void si_get_scissor_from_viewport(struct si_context *ctx,
        maxx = vp->scale[0] + vp->translate[0];
        maxy = vp->scale[1] + vp->translate[1];
 
-       /* r600_draw_rectangle sets this. Disable the scissor. */
-       if (minx == -1 && miny == -1 && maxx == 1 && maxy == 1) {
-               scissor->minx = scissor->miny = 0;
-               scissor->maxx = scissor->maxy = SI_MAX_SCISSOR;
-               return;
-       }
-
        /* Handle inverted viewports. */
        if (minx > maxx) {
                tmp = minx;
@@ -146,7 +141,7 @@ static void si_emit_one_scissor(struct si_context *ctx,
 static void si_emit_guardband(struct si_context *ctx,
                              struct si_signed_scissor *vp_as_scissor)
 {
-       struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
+       struct radeon_winsys_cs *cs = ctx->b.gfx_cs;
        struct pipe_viewport_state vp;
        float left, top, right, bottom, max_range, guardband_x, guardband_y;
        float discard_x, discard_y;
@@ -186,17 +181,26 @@ static void si_emit_guardband(struct si_context *ctx,
        discard_x = 1.0;
        discard_y = 1.0;
 
-       if (ctx->current_rast_prim < PIPE_PRIM_TRIANGLES) {
+       if (unlikely(ctx->current_rast_prim < PIPE_PRIM_TRIANGLES) &&
+           ctx->queued.named.rasterizer) {
                /* When rendering wide points or lines, we need to be more
-                * conservative about when to discard them entirely. Since
-                * point size can be determined by the VS output, we basically
-                * disable discard completely completely here.
-                *
-                * TODO: This can hurt performance when rendering lines and
-                * points with fixed size, and could be improved.
-                */
-               discard_x = guardband_x;
-               discard_y = guardband_y;
+                * conservative about when to discard them entirely. */
+               const struct si_state_rasterizer *rs = ctx->queued.named.rasterizer;
+               float pixels;
+
+               if (ctx->current_rast_prim == PIPE_PRIM_POINTS)
+                       pixels = rs->max_point_size;
+               else
+                       pixels = rs->line_width;
+
+               /* Add half the point size / line width */
+               discard_x += pixels / (2.0 * vp.scale[0]);
+               discard_y += pixels / (2.0 * vp.scale[1]);
+
+               /* Discard primitives that would lie entirely outside the clip
+                * region. */
+               discard_x = MIN2(discard_x, guardband_x);
+               discard_y = MIN2(discard_y, guardband_y);
        }
 
        /* If any of the GB registers is updated, all of them must be updated. */
@@ -208,16 +212,18 @@ static void si_emit_guardband(struct si_context *ctx,
        radeon_emit(cs, fui(discard_x));   /* R_028BF4_PA_CL_GB_HORZ_DISC_ADJ */
 }
 
-static void si_emit_scissors(struct r600_common_context *rctx, struct r600_atom *atom)
+static void si_emit_scissors(struct si_context *ctx, struct r600_atom *atom)
 {
-       struct si_context *ctx = (struct si_context *)rctx;
-       struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
+       struct radeon_winsys_cs *cs = ctx->b.gfx_cs;
        struct pipe_scissor_state *states = ctx->scissors.states;
        unsigned mask = ctx->scissors.dirty_mask;
-       bool scissor_enabled = ctx->scissor_enabled;
+       bool scissor_enabled = false;
        struct si_signed_scissor max_vp_scissor;
        int i;
 
+       if (ctx->queued.named.rasterizer)
+               scissor_enabled = ctx->queued.named.rasterizer->scissor_enable;
+
        /* The simple case: Only 1 viewport is active. */
        if (!ctx->vs_writes_viewport_index) {
                struct si_signed_scissor *vp = &ctx->viewports.as_scissor[0];
@@ -282,7 +288,7 @@ static void si_set_viewport_states(struct pipe_context *pctx,
 static void si_emit_one_viewport(struct si_context *ctx,
                                 struct pipe_viewport_state *state)
 {
-       struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
+       struct radeon_winsys_cs *cs = ctx->b.gfx_cs;
 
        radeon_emit(cs, fui(state->scale[0]));
        radeon_emit(cs, fui(state->translate[0]));
@@ -294,7 +300,7 @@ static void si_emit_one_viewport(struct si_context *ctx,
 
 static void si_emit_viewports(struct si_context *ctx)
 {
-       struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
+       struct radeon_winsys_cs *cs = ctx->b.gfx_cs;
        struct pipe_viewport_state *states = ctx->viewports.states;
        unsigned mask = ctx->viewports.dirty_mask;
 
@@ -322,19 +328,37 @@ static void si_emit_viewports(struct si_context *ctx)
        ctx->viewports.dirty_mask = 0;
 }
 
+static inline void
+si_viewport_zmin_zmax(const struct pipe_viewport_state *vp, bool halfz,
+                     bool window_space_position, float *zmin, float *zmax)
+{
+       if (window_space_position) {
+               *zmin = 0;
+               *zmax = 1;
+               return;
+       }
+       util_viewport_zmin_zmax(vp, halfz, zmin, zmax);
+}
+
 static void si_emit_depth_ranges(struct si_context *ctx)
 {
-       struct radeon_winsys_cs *cs = ctx->b.gfx.cs;
+       struct radeon_winsys_cs *cs = ctx->b.gfx_cs;
        struct pipe_viewport_state *states = ctx->viewports.states;
        unsigned mask = ctx->viewports.depth_range_dirty_mask;
+       bool clip_halfz = false;
+       bool window_space = ctx->vs_disables_clipping_viewport;
        float zmin, zmax;
 
+       if (ctx->queued.named.rasterizer)
+               clip_halfz = ctx->queued.named.rasterizer->clip_halfz;
+
        /* The simple case: Only 1 viewport is active. */
        if (!ctx->vs_writes_viewport_index) {
                if (!(mask & 1))
                        return;
 
-               util_viewport_zmin_zmax(&states[0], ctx->clip_halfz, &zmin, &zmax);
+               si_viewport_zmin_zmax(&states[0], clip_halfz, window_space,
+                                     &zmin, &zmax);
 
                radeon_set_context_reg_seq(cs, R_0282D0_PA_SC_VPORT_ZMIN_0, 2);
                radeon_emit(cs, fui(zmin));
@@ -351,7 +375,8 @@ static void si_emit_depth_ranges(struct si_context *ctx)
                radeon_set_context_reg_seq(cs, R_0282D0_PA_SC_VPORT_ZMIN_0 +
                                           start * 4 * 2, count * 2);
                for (i = start; i < start+count; i++) {
-                       util_viewport_zmin_zmax(&states[i], ctx->clip_halfz, &zmin, &zmax);
+                       si_viewport_zmin_zmax(&states[i], clip_halfz, window_space,
+                                             &zmin, &zmax);
                        radeon_emit(cs, fui(zmin));
                        radeon_emit(cs, fui(zmax));
                }
@@ -359,37 +384,24 @@ static void si_emit_depth_ranges(struct si_context *ctx)
        ctx->viewports.depth_range_dirty_mask = 0;
 }
 
-static void si_emit_viewport_states(struct r600_common_context *rctx,
+static void si_emit_viewport_states(struct si_context *ctx,
                                    struct r600_atom *atom)
 {
-       struct si_context *ctx = (struct si_context *)rctx;
        si_emit_viewports(ctx);
        si_emit_depth_ranges(ctx);
 }
 
-/* Set viewport dependencies on pipe_rasterizer_state. */
-void si_viewport_set_rast_deps(struct si_context *ctx,
-                              bool scissor_enable, bool clip_halfz)
-{
-       if (ctx->scissor_enabled != scissor_enable) {
-               ctx->scissor_enabled = scissor_enable;
-               ctx->scissors.dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1;
-               si_mark_atom_dirty(ctx, &ctx->scissors.atom);
-       }
-       if (ctx->clip_halfz != clip_halfz) {
-               ctx->clip_halfz = clip_halfz;
-               ctx->viewports.depth_range_dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1;
-               si_mark_atom_dirty(ctx, &ctx->viewports.atom);
-       }
-}
-
 /**
+ * This reacts to 2 state changes:
+ * - VS.writes_viewport_index
+ * - VS output position in window space (enable/disable)
+ *
  * Normally, we only emit 1 viewport and 1 scissor if no shader is using
  * the VIEWPORT_INDEX output, and emitting the other viewports and scissors
  * is delayed. When a shader with VIEWPORT_INDEX appears, this should be
  * called to emit the rest.
  */
-void si_update_vs_writes_viewport_index(struct si_context *ctx)
+void si_update_vs_viewport_state(struct si_context *ctx)
 {
        struct tgsi_shader_info *info = si_get_vs_info(ctx);
        bool vs_window_space;
@@ -404,7 +416,9 @@ void si_update_vs_writes_viewport_index(struct si_context *ctx)
        if (ctx->vs_disables_clipping_viewport != vs_window_space) {
                ctx->vs_disables_clipping_viewport = vs_window_space;
                ctx->scissors.dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1;
+               ctx->viewports.depth_range_dirty_mask = (1 << SI_MAX_VIEWPORTS) - 1;
                si_mark_atom_dirty(ctx, &ctx->scissors.atom);
+               si_mark_atom_dirty(ctx, &ctx->viewports.atom);
        }
 
        /* Viewport index handling. */
@@ -425,9 +439,6 @@ void si_init_viewport_functions(struct si_context *ctx)
        ctx->scissors.atom.emit = si_emit_scissors;
        ctx->viewports.atom.emit = si_emit_viewport_states;
 
-       ctx->scissors.atom.num_dw = (2 + 16 * 2) + 6;
-       ctx->viewports.atom.num_dw = 2 + 16 * 6;
-
        ctx->b.b.set_scissor_states = si_set_scissor_states;
        ctx->b.b.set_viewport_states = si_set_viewport_states;
 }