panfrost: Improve viewport (clipping) robustness
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 14 Jun 2019 19:25:26 +0000 (12:25 -0700)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 17 Jun 2019 14:59:14 +0000 (07:59 -0700)
On more complex apps (possibly using desktop GL specific extensions?),
our viewport code was getting wacky results for unclear reasons. Let's
be a little less wacky.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/pan_context.c

index de8da320b02d2308b2e4096c778b4fd2ec700e67..bce57625163fae73e0016c304478b94afa35bc99 100644 (file)
@@ -1287,28 +1287,57 @@ panfrost_emit_for_draw(struct panfrost_context *ctx, bool with_vertex_data)
         };
 
         /* Always scissor to the viewport by default. */
-        view.viewport0[0] = (int) (vp->translate[0] - vp->scale[0]);
-        view.viewport1[0] = MALI_POSITIVE((int) (vp->translate[0] + vp->scale[0]));
+        int minx = (int) (vp->translate[0] - vp->scale[0]);
+        int maxx = (int) (vp->translate[0] + vp->scale[0]);
 
         int miny = (int) (vp->translate[1] - vp->scale[1]);
         int maxy = (int) (vp->translate[1] + vp->scale[1]);
 
-        if (ss && ctx->rasterizer && ctx->rasterizer->base.scissor) {
-                view.viewport0[0] = ss->minx;
-                view.viewport1[0] = MALI_POSITIVE(ss->maxx);
+        /* Apply the scissor test */
 
+        if (ss && ctx->rasterizer && ctx->rasterizer->base.scissor) {
+                minx = ss->minx;
+                maxx = ss->maxx;
                 miny = ss->miny;
                 maxy = ss->maxy;
         } 
 
         /* Hardware needs the min/max to be strictly ordered, so flip if we
-         * need to */
+         * need to. The viewport transformation in the vertex shader will
+         * handle the negatives if we don't */
+
         if (miny > maxy) {
                 int temp = miny;
                 miny = maxy;
                 maxy = temp;
         }
 
+        if (minx > maxx) {
+                int temp = minx;
+                minx = maxx;
+                maxx = temp;
+        }
+
+        /* Clamp everything positive, just in case */
+
+        maxx = MAX2(0, maxx);
+        maxy = MAX2(0, maxy);
+        minx = MAX2(0, minx);
+        miny = MAX2(0, miny);
+
+        /* Clamp to the framebuffer size as a last check */
+
+        minx = MIN2(ctx->pipe_framebuffer.width, minx);
+        maxx = MIN2(ctx->pipe_framebuffer.width, maxx);
+
+        miny = MIN2(ctx->pipe_framebuffer.height, miny);
+        maxy = MIN2(ctx->pipe_framebuffer.height, maxy);
+
+        /* Upload */
+
+        view.viewport0[0] = minx;
+        view.viewport1[0] = MALI_POSITIVE(maxx);
+
         view.viewport0[1] = miny;
         view.viewport1[1] = MALI_POSITIVE(maxy);