+ if (depth_size == 0) {
+ depth_clear = (uint32_t)(0xffff * depth);
+ depth_clear |= depth_clear << 16;
+ } else if (depth_size == 1) {
+ depth_clear = (((uint32_t)(0xffffff * depth)) << 8);
+ depth_clear |= (stencil & 0xff);
+ }
+
+ /* disable "window" scissor.. */
+ OUT_PKT3(ring, CP_SET_CONSTANT, 3);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
+ OUT_RING(ring, xy2d(0, 0));
+ OUT_RING(ring, xy2d(0x7fff, 0x7fff));
+
+ /* make sure we fill all "pixels" (in SCREEN_SCISSOR) */
+ OUT_PKT3(ring, CP_SET_CONSTANT, 5);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
+ OUT_RING(ring, fui(4096.0));
+ OUT_RING(ring, fui(4096.0));
+ OUT_RING(ring, fui(4096.0));
+ OUT_RING(ring, fui(4096.0));
+
+ clear_state(batch, ring, ~0u, true);
+
+ if (color_size >= 0 && depth_size != color_size)
+ clear_fast(batch, ring, color_clear, color_clear, GMEM_PATCH_FASTCLEAR_COLOR);
+
+ if (depth_size >= 0 && depth_size != color_size)
+ clear_fast(batch, ring, depth_clear, depth_clear, GMEM_PATCH_FASTCLEAR_DEPTH);
+
+ if (depth_size == color_size)
+ clear_fast(batch, ring, color_clear, depth_clear, GMEM_PATCH_FASTCLEAR_COLOR_DEPTH);
+
+ clear_state_restore(ctx, ring);
+
+ OUT_PKT3(ring, CP_SET_CONSTANT, 2);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_CONFIG));
+ OUT_RING(ring, 0);
+
+ /* can't patch in SCREEN_SCISSOR_BR as it can be different for each tile.
+ * MEM_WRITE the value in tile_renderprep, and use CP_LOAD_CONSTANT_CONTEXT
+ * the value is read from byte offset 60 in the given bo
+ */
+ OUT_PKT3(ring, CP_LOAD_CONSTANT_CONTEXT, 3);
+ OUT_RELOC(ring, fd_resource(fd2_ctx->solid_vertexbuf)->bo, 0, 0, 0);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_BR));
+ OUT_RING(ring, 1);
+
+ OUT_PKT3(ring, CP_SET_CONSTANT, 4);
+ OUT_RING(ring, CP_REG(REG_A2XX_RB_SURFACE_INFO));
+ OUT_RINGP(ring, GMEM_PATCH_RESTORE_INFO, &batch->gmem_patches);
+ OUT_RING(ring, 0);
+ OUT_RING(ring, 0);
+ return true;
+}
+
+static bool
+fd2_clear(struct fd_context *ctx, unsigned buffers,
+ const union pipe_color_union *color, double depth, unsigned stencil)
+{
+ struct fd_ringbuffer *ring = ctx->batch->draw;
+ struct pipe_framebuffer_state *fb = &ctx->batch->framebuffer;
+
+ if (fd2_clear_fast(ctx, buffers, color, depth, stencil))
+ goto dirty;
+
+ /* set clear value */
+ if (is_a20x(ctx->screen)) {
+ if (buffers & PIPE_CLEAR_COLOR) {
+ /* C0 used by fragment shader */
+ OUT_PKT3(ring, CP_SET_CONSTANT, 5);
+ OUT_RING(ring, 0x00000480);
+ OUT_RING(ring, color->ui[0]);
+ OUT_RING(ring, color->ui[1]);
+ OUT_RING(ring, color->ui[2]);
+ OUT_RING(ring, color->ui[3]);
+ }
+
+ if (buffers & PIPE_CLEAR_DEPTH) {
+ /* use viewport to set depth value */
+ OUT_PKT3(ring, CP_SET_CONSTANT, 3);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_ZSCALE));
+ OUT_RING(ring, fui(0.0f));
+ OUT_RING(ring, fui(depth));
+ }
+
+ if (buffers & PIPE_CLEAR_STENCIL) {
+ OUT_PKT3(ring, CP_SET_CONSTANT, 3);
+ OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF));
+ OUT_RING(ring, 0xff000000 |
+ A2XX_RB_STENCILREFMASK_BF_STENCILREF(stencil) |
+ A2XX_RB_STENCILREFMASK_BF_STENCILWRITEMASK(0xff));
+ OUT_RING(ring, 0xff000000 |
+ A2XX_RB_STENCILREFMASK_STENCILREF(stencil) |
+ A2XX_RB_STENCILREFMASK_STENCILWRITEMASK(0xff));
+ }
+ } else {
+ if (buffers & PIPE_CLEAR_COLOR) {
+ OUT_PKT3(ring, CP_SET_CONSTANT, 2);
+ OUT_RING(ring, CP_REG(REG_A2XX_CLEAR_COLOR));
+ OUT_RING(ring, pack_rgba(PIPE_FORMAT_R8G8B8A8_UNORM, color->f));
+ }
+
+ if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
+ uint32_t clear_mask, depth_clear;
+ switch (fd_pipe2depth(fb->zsbuf->format)) {
+ case DEPTHX_24_8:
+ clear_mask = ((buffers & PIPE_CLEAR_DEPTH) ? 0xe : 0) |
+ ((buffers & PIPE_CLEAR_STENCIL) ? 0x1 : 0);
+ depth_clear = (((uint32_t)(0xffffff * depth)) << 8) |
+ (stencil & 0xff);
+ break;
+ case DEPTHX_16:
+ clear_mask = 0xf;
+ depth_clear = (uint32_t)(0xffffffff * depth);
+ break;
+ default:
+ unreachable("invalid depth");
+ break;
+ }
+
+ OUT_PKT3(ring, CP_SET_CONSTANT, 2);
+ OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL));
+ OUT_RING(ring, A2XX_RB_COPY_CONTROL_DEPTH_CLEAR_ENABLE |
+ A2XX_RB_COPY_CONTROL_CLEAR_MASK(clear_mask));
+
+ OUT_PKT3(ring, CP_SET_CONSTANT, 2);
+ OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTH_CLEAR));
+ OUT_RING(ring, depth_clear);
+ }
+ }
+
+ /* scissor state */
+ OUT_PKT3(ring, CP_SET_CONSTANT, 3);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
+ OUT_RING(ring, xy2d(0, 0));
+ OUT_RING(ring, xy2d(fb->width, fb->height));
+
+ /* viewport state */
+ OUT_PKT3(ring, CP_SET_CONSTANT, 5);
+ OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
+ OUT_RING(ring, fui((float) fb->width / 2.0));
+ OUT_RING(ring, fui((float) fb->width / 2.0));
+ OUT_RING(ring, fui((float) fb->height / 2.0));
+ OUT_RING(ring, fui((float) fb->height / 2.0));
+
+ /* common state */
+ clear_state(ctx->batch, ring, buffers, false);
+
+ fd_draw(ctx->batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
+ DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);
+
+ clear_state_restore(ctx, ring);
+
+dirty: