v3dv: check the render area against the clip window

And flag dirty scissor state if the render area is constraining the
current clip window, so that we emit a new clip window with the next
draw call.

Also, remove the early emission of a clip window for the render area
if we didn't have any scissor state. TLB clears ignore the clip
window, so this was doing nothing for us.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index 9af49c2..95b5690 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -883,6 +883,22 @@
     */
    state->render_area = pRenderPassBegin->renderArea;
 
+   /* If our render area is smaller than the current clip window we will have
+    * to emit a new clip window.
+    */
+   uint32_t min_render_x = state->render_area.offset.x;
+   uint32_t min_render_y = state->render_area.offset.x;
+   uint32_t max_render_x = min_render_x + state->render_area.extent.width - 1;
+   uint32_t max_render_y = min_render_y + state->render_area.extent.height - 1;
+   uint32_t min_clip_x = state->clip_window.offset.x;
+   uint32_t min_clip_y = state->clip_window.offset.y;
+   uint32_t max_clip_x = min_clip_x + state->clip_window.extent.width - 1;
+   uint32_t max_clip_y = min_clip_y + state->clip_window.extent.height - 1;
+   if (min_render_x > min_clip_x || min_render_y > min_clip_y ||
+       max_render_x < max_clip_x || max_render_y < max_clip_y) {
+      state->dirty |= V3DV_CMD_DIRTY_SCISSOR;
+   }
+
    /* Setup for first subpass */
    v3dv_cmd_buffer_subpass_start(cmd_buffer, 0);
 }
@@ -1549,20 +1565,6 @@
                            internal_bpp);
    }
 
-   /* If we don't have a scissor or viewport defined let's just use the render
-    * area as clip_window, as that would be required for a clear in any
-    * case. If we have that, it would be emitted as part of the pipeline
-    * dynamic state flush
-    *
-    * FIXME: this is mostly just needed for clear. radv has dedicated paths
-    * for them, so we could get that idea. In any case, need to revisit if
-    * this is the place to emit the clip window.
-    */
-   if (cmd_buffer->state.dynamic.scissor.count == 0 &&
-       cmd_buffer->state.dynamic.viewport.count == 0) {
-      emit_clip_window(job, &state->render_area);
-   }
-
    return job;
 }