xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r300/r300_flush.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2008 Corbin Simpson <[email protected]>
3  * Copyright 2010 Marek Olšák <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "draw/draw_context.h"
8 #include "draw/draw_private.h"
9 
10 #include "util/u_upload_mgr.h"
11 
12 #include "util/os_time.h"
13 
14 #include "r300_context.h"
15 #include "r300_cs.h"
16 #include "r300_emit.h"
17 
18 
r300_flush_and_cleanup(struct r300_context * r300,unsigned flags,struct pipe_fence_handle ** fence)19 static void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags,
20                                    struct pipe_fence_handle **fence)
21 {
22     struct r300_atom *atom;
23 
24     r300_emit_hyperz_end(r300);
25     r300_emit_query_end(r300);
26     if (r300->screen->caps.is_r500)
27         r500_emit_index_bias(r300, 0);
28 
29     /* The DDX doesn't set these regs. */
30     {
31         CS_LOCALS(r300);
32         OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
33         OUT_CS(0x66666666);
34         OUT_CS(0x6666666);
35     }
36 
37     r300->flush_counter++;
38     r300->rws->cs_flush(&r300->cs, flags, fence);
39     r300->dirty_hw = 0;
40 
41     /* New kitchen sink, baby. */
42     foreach_atom(r300, atom) {
43         if (atom->state || atom->allow_null_state) {
44             r300_mark_atom_dirty(r300, atom);
45         }
46     }
47     r300->vertex_arrays_dirty = true;
48 
49     /* Unmark HWTCL state for SWTCL. */
50     if (!r300->screen->caps.has_tcl) {
51         r300->vs_state.dirty = false;
52         r300->vs_constants.dirty = false;
53         r300->clip_state.dirty = false;
54     }
55 }
56 
r300_flush(struct pipe_context * pipe,unsigned flags,struct pipe_fence_handle ** fence)57 void r300_flush(struct pipe_context *pipe,
58                 unsigned flags,
59                 struct pipe_fence_handle **fence)
60 {
61     struct r300_context *r300 = r300_context(pipe);
62 
63     if (r300->dirty_hw) {
64         r300_flush_and_cleanup(r300, flags, fence);
65     } else {
66         if (fence) {
67             /* We have to create a fence object, but the command stream is empty
68              * and we cannot emit an empty CS. Let's write to some reg. */
69             CS_LOCALS(r300);
70             OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0);
71             r300->rws->cs_flush(&r300->cs, flags, fence);
72         } else {
73             /* Even if hw is not dirty, we should at least reset the CS in case
74              * the space checking failed for the first draw operation. */
75             r300->rws->cs_flush(&r300->cs, flags, NULL);
76         }
77     }
78 
79     /* Update Hyper-Z status. */
80     if (r300->hyperz_enabled) {
81         /* If there was a Z clear, keep Hyper-Z access. */
82         if (r300->num_z_clears) {
83             r300->hyperz_time_of_last_flush = os_time_get();
84             r300->num_z_clears = 0;
85         } else if (r300->hyperz_time_of_last_flush - os_time_get() > 2000000) {
86             /* If there hasn't been a Z clear for 2 seconds, revoke Hyper-Z access. */
87             r300->hiz_in_use = false;
88 
89             /* Decompress the Z buffer. */
90             if (r300->zmask_in_use) {
91                 if (r300->locked_zbuffer) {
92                     r300_decompress_zmask_locked(r300);
93                 } else {
94                     r300_decompress_zmask(r300);
95                 }
96 
97                 if (fence && *fence)
98                     r300->rws->fence_reference(r300->rws, fence, NULL);
99                 r300_flush_and_cleanup(r300, flags, fence);
100             }
101 
102             /* Revoke Hyper-Z access, so that some other process can take it. */
103             r300->rws->cs_request_feature(&r300->cs, RADEON_FID_R300_HYPERZ_ACCESS,
104                                           false);
105             r300->hyperz_enabled = false;
106         }
107     }
108 }
109 
r300_flush_wrapped(struct pipe_context * pipe,struct pipe_fence_handle ** fence,unsigned flags)110 static void r300_flush_wrapped(struct pipe_context *pipe,
111                                struct pipe_fence_handle **fence,
112                                unsigned flags)
113 {
114     if (flags & PIPE_FLUSH_HINT_FINISH)
115         flags &= ~PIPE_FLUSH_ASYNC;
116 
117     r300_flush(pipe, flags, fence);
118 }
119 
r300_init_flush_functions(struct r300_context * r300)120 void r300_init_flush_functions(struct r300_context* r300)
121 {
122     r300->context.flush = r300_flush_wrapped;
123 }
124