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