1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (c) 2014-2015 Etnaviv Project
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
12bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
13bf215546Sopenharmony_ci * of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Wladimir J. van der Laan <laanwj@gmail.com>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "etnaviv_emit.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "etnaviv_blend.h"
30bf215546Sopenharmony_ci#include "etnaviv_compiler.h"
31bf215546Sopenharmony_ci#include "etnaviv_context.h"
32bf215546Sopenharmony_ci#include "etnaviv_rasterizer.h"
33bf215546Sopenharmony_ci#include "etnaviv_resource.h"
34bf215546Sopenharmony_ci#include "etnaviv_rs.h"
35bf215546Sopenharmony_ci#include "etnaviv_screen.h"
36bf215546Sopenharmony_ci#include "etnaviv_shader.h"
37bf215546Sopenharmony_ci#include "etnaviv_texture.h"
38bf215546Sopenharmony_ci#include "etnaviv_translate.h"
39bf215546Sopenharmony_ci#include "etnaviv_uniforms.h"
40bf215546Sopenharmony_ci#include "etnaviv_util.h"
41bf215546Sopenharmony_ci#include "etnaviv_zsa.h"
42bf215546Sopenharmony_ci#include "hw/common.xml.h"
43bf215546Sopenharmony_ci#include "hw/state.xml.h"
44bf215546Sopenharmony_ci#include "hw/state_blt.xml.h"
45bf215546Sopenharmony_ci#include "util/u_math.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci/* Queue a STALL command (queues 2 words) */
48bf215546Sopenharmony_cistatic inline void
49bf215546Sopenharmony_ciCMD_STALL(struct etna_cmd_stream *stream, uint32_t from, uint32_t to)
50bf215546Sopenharmony_ci{
51bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, VIV_FE_STALL_HEADER_OP_STALL);
52bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to));
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_civoid
56bf215546Sopenharmony_cietna_stall(struct etna_cmd_stream *stream, uint32_t from, uint32_t to)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   bool blt = (from == SYNC_RECIPIENT_BLT) || (to == SYNC_RECIPIENT_BLT);
59bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, blt ? 8 : 4);
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   if (blt) {
62bf215546Sopenharmony_ci      etna_emit_load_state(stream, VIVS_BLT_ENABLE >> 2, 1, 0);
63bf215546Sopenharmony_ci      etna_cmd_stream_emit(stream, 1);
64bf215546Sopenharmony_ci   }
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   /* TODO: set bit 28/29 of token after BLT COPY_BUFFER */
67bf215546Sopenharmony_ci   etna_emit_load_state(stream, VIVS_GL_SEMAPHORE_TOKEN >> 2, 1, 0);
68bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, VIVS_GL_SEMAPHORE_TOKEN_FROM(from) | VIVS_GL_SEMAPHORE_TOKEN_TO(to));
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci   if (from == SYNC_RECIPIENT_FE) {
71bf215546Sopenharmony_ci      /* if the frontend is to be stalled, queue a STALL frontend command */
72bf215546Sopenharmony_ci      CMD_STALL(stream, from, to);
73bf215546Sopenharmony_ci   } else {
74bf215546Sopenharmony_ci      /* otherwise, load the STALL token state */
75bf215546Sopenharmony_ci      etna_emit_load_state(stream, VIVS_GL_STALL_TOKEN >> 2, 1, 0);
76bf215546Sopenharmony_ci      etna_cmd_stream_emit(stream, VIVS_GL_STALL_TOKEN_FROM(from) | VIVS_GL_STALL_TOKEN_TO(to));
77bf215546Sopenharmony_ci   }
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   if (blt) {
80bf215546Sopenharmony_ci      etna_emit_load_state(stream, VIVS_BLT_ENABLE >> 2, 1, 0);
81bf215546Sopenharmony_ci      etna_cmd_stream_emit(stream, 0);
82bf215546Sopenharmony_ci   }
83bf215546Sopenharmony_ci}
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci#define EMIT_STATE(state_name, src_value) \
86bf215546Sopenharmony_ci   etna_coalsence_emit(stream, &coalesce, VIVS_##state_name, src_value)
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci#define EMIT_STATE_FIXP(state_name, src_value) \
89bf215546Sopenharmony_ci   etna_coalsence_emit_fixp(stream, &coalesce, VIVS_##state_name, src_value)
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci#define EMIT_STATE_RELOC(state_name, src_value) \
92bf215546Sopenharmony_ci   etna_coalsence_emit_reloc(stream, &coalesce, VIVS_##state_name, src_value)
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci#define ETNA_3D_CONTEXT_SIZE  (400) /* keep this number above "Total state updates (fixed)" from gen_weave_state tool */
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistatic unsigned
97bf215546Sopenharmony_cirequired_stream_size(struct etna_context *ctx)
98bf215546Sopenharmony_ci{
99bf215546Sopenharmony_ci   unsigned size = ETNA_3D_CONTEXT_SIZE;
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   /* stall + flush */
102bf215546Sopenharmony_ci   size += 2 + 4;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   /* vertex elements */
105bf215546Sopenharmony_ci   size += ctx->vertex_elements->num_elements + 1;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   /* uniforms - worst case (2 words per uniform load) */
108bf215546Sopenharmony_ci   size += ctx->shader.vs->uniforms.count * 2;
109bf215546Sopenharmony_ci   size += ctx->shader.fs->uniforms.count * 2;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   /* shader */
112bf215546Sopenharmony_ci   size += ctx->shader_state.vs_inst_mem_size + 1;
113bf215546Sopenharmony_ci   size += ctx->shader_state.ps_inst_mem_size + 1;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   /* DRAW_INDEXED_PRIMITIVES command */
116bf215546Sopenharmony_ci   size += 6;
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   /* reserve for alignment etc. */
119bf215546Sopenharmony_ci   size += 64;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   return size;
122bf215546Sopenharmony_ci}
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci/* Emit state that only exists on HALTI5+ */
125bf215546Sopenharmony_cistatic void
126bf215546Sopenharmony_ciemit_halti5_only_state(struct etna_context *ctx, int vs_output_count)
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   struct etna_cmd_stream *stream = ctx->stream;
129bf215546Sopenharmony_ci   uint32_t dirty = ctx->dirty;
130bf215546Sopenharmony_ci   struct etna_coalesce coalesce;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   etna_coalesce_start(stream, &coalesce);
133bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
134bf215546Sopenharmony_ci      /* Magic states (load balancing, inter-unit sync, buffers) */
135bf215546Sopenharmony_ci      /*007C4*/ EMIT_STATE(FE_HALTI5_ID_CONFIG, ctx->shader_state.FE_HALTI5_ID_CONFIG);
136bf215546Sopenharmony_ci      /*00870*/ EMIT_STATE(VS_HALTI5_OUTPUT_COUNT, vs_output_count | ((vs_output_count * 0x10) << 8));
137bf215546Sopenharmony_ci      /*008A0*/ EMIT_STATE(VS_HALTI5_UNK008A0, 0x0001000e | ((0x110/vs_output_count) << 20));
138bf215546Sopenharmony_ci      for (int x = 0; x < 4; ++x) {
139bf215546Sopenharmony_ci         /*008E0*/ EMIT_STATE(VS_HALTI5_OUTPUT(x), ctx->shader_state.VS_OUTPUT[x]);
140bf215546Sopenharmony_ci      }
141bf215546Sopenharmony_ci   }
142bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_VERTEX_ELEMENTS | ETNA_DIRTY_SHADER))) {
143bf215546Sopenharmony_ci      for (int x = 0; x < 4; ++x) {
144bf215546Sopenharmony_ci         /*008C0*/ EMIT_STATE(VS_HALTI5_INPUT(x), ctx->shader_state.VS_INPUT[x]);
145bf215546Sopenharmony_ci      }
146bf215546Sopenharmony_ci   }
147bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
148bf215546Sopenharmony_ci      /*00A90*/ EMIT_STATE(PA_VARYING_NUM_COMPONENTS(0), ctx->shader_state.GL_VARYING_NUM_COMPONENTS[0]);
149bf215546Sopenharmony_ci      /*00A94*/ EMIT_STATE(PA_VARYING_NUM_COMPONENTS(1), ctx->shader_state.GL_VARYING_NUM_COMPONENTS[1]);
150bf215546Sopenharmony_ci      /*00AA8*/ EMIT_STATE(PA_VS_OUTPUT_COUNT, vs_output_count);
151bf215546Sopenharmony_ci      /*01080*/ EMIT_STATE(PS_VARYING_NUM_COMPONENTS(0), ctx->shader_state.GL_VARYING_NUM_COMPONENTS[0]);
152bf215546Sopenharmony_ci      /*01084*/ EMIT_STATE(PS_VARYING_NUM_COMPONENTS(1), ctx->shader_state.GL_VARYING_NUM_COMPONENTS[1]);
153bf215546Sopenharmony_ci      /*03888*/ EMIT_STATE(GL_HALTI5_SH_SPECIALS, ctx->shader_state.GL_HALTI5_SH_SPECIALS);
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci   etna_coalesce_end(stream, &coalesce);
156bf215546Sopenharmony_ci}
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci/* Emit state that no longer exists on HALTI5 */
159bf215546Sopenharmony_cistatic void
160bf215546Sopenharmony_ciemit_pre_halti5_state(struct etna_context *ctx)
161bf215546Sopenharmony_ci{
162bf215546Sopenharmony_ci   struct etna_cmd_stream *stream = ctx->stream;
163bf215546Sopenharmony_ci   uint32_t dirty = ctx->dirty;
164bf215546Sopenharmony_ci   struct etna_coalesce coalesce;
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci   etna_coalesce_start(stream, &coalesce);
167bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
168bf215546Sopenharmony_ci      /*00800*/ EMIT_STATE(VS_END_PC, ctx->shader_state.VS_END_PC);
169bf215546Sopenharmony_ci   }
170bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
171bf215546Sopenharmony_ci      for (int x = 0; x < 4; ++x) {
172bf215546Sopenharmony_ci        /*00810*/ EMIT_STATE(VS_OUTPUT(x), ctx->shader_state.VS_OUTPUT[x]);
173bf215546Sopenharmony_ci      }
174bf215546Sopenharmony_ci   }
175bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_VERTEX_ELEMENTS | ETNA_DIRTY_SHADER))) {
176bf215546Sopenharmony_ci      for (int x = 0; x < 4; ++x) {
177bf215546Sopenharmony_ci        /*00820*/ EMIT_STATE(VS_INPUT(x), ctx->shader_state.VS_INPUT[x]);
178bf215546Sopenharmony_ci      }
179bf215546Sopenharmony_ci   }
180bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
181bf215546Sopenharmony_ci      /*00838*/ EMIT_STATE(VS_START_PC, ctx->shader_state.VS_START_PC);
182bf215546Sopenharmony_ci   }
183bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
184bf215546Sopenharmony_ci      for (int x = 0; x < 10; ++x) {
185bf215546Sopenharmony_ci         /*00A40*/ EMIT_STATE(PA_SHADER_ATTRIBUTES(x), ctx->shader_state.PA_SHADER_ATTRIBUTES[x]);
186bf215546Sopenharmony_ci      }
187bf215546Sopenharmony_ci   }
188bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) {
189bf215546Sopenharmony_ci      /*00E04*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E04, ctx->framebuffer.RA_MULTISAMPLE_UNK00E04);
190bf215546Sopenharmony_ci      for (int x = 0; x < 4; ++x) {
191bf215546Sopenharmony_ci         /*00E10*/ EMIT_STATE(RA_MULTISAMPLE_UNK00E10(x), ctx->framebuffer.RA_MULTISAMPLE_UNK00E10[x]);
192bf215546Sopenharmony_ci      }
193bf215546Sopenharmony_ci      for (int x = 0; x < 16; ++x) {
194bf215546Sopenharmony_ci         /*00E40*/ EMIT_STATE(RA_CENTROID_TABLE(x), ctx->framebuffer.RA_CENTROID_TABLE[x]);
195bf215546Sopenharmony_ci      }
196bf215546Sopenharmony_ci   }
197bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_FRAMEBUFFER))) {
198bf215546Sopenharmony_ci      /*01000*/ EMIT_STATE(PS_END_PC, ctx->shader_state.PS_END_PC);
199bf215546Sopenharmony_ci   }
200bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_FRAMEBUFFER))) {
201bf215546Sopenharmony_ci      /*01018*/ EMIT_STATE(PS_START_PC, ctx->shader_state.PS_START_PC);
202bf215546Sopenharmony_ci   }
203bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
204bf215546Sopenharmony_ci      /*03820*/ EMIT_STATE(GL_VARYING_NUM_COMPONENTS, ctx->shader_state.GL_VARYING_NUM_COMPONENTS[0]);
205bf215546Sopenharmony_ci      for (int x = 0; x < 2; ++x) {
206bf215546Sopenharmony_ci         /*03828*/ EMIT_STATE(GL_VARYING_COMPONENT_USE(x), ctx->shader_state.GL_VARYING_COMPONENT_USE[x]);
207bf215546Sopenharmony_ci      }
208bf215546Sopenharmony_ci      /*03834*/ EMIT_STATE(GL_VARYING_NUM_COMPONENTS2, ctx->shader_state.GL_VARYING_NUM_COMPONENTS[1]);
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci   etna_coalesce_end(stream, &coalesce);
211bf215546Sopenharmony_ci}
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci/* Weave state before draw operation. This function merges all the compiled
214bf215546Sopenharmony_ci * state blocks under the context into one device register state. Parts of
215bf215546Sopenharmony_ci * this state that are changed since last call (dirty) will be uploaded as
216bf215546Sopenharmony_ci * state changes in the command buffer. */
217bf215546Sopenharmony_civoid
218bf215546Sopenharmony_cietna_emit_state(struct etna_context *ctx)
219bf215546Sopenharmony_ci{
220bf215546Sopenharmony_ci   struct etna_cmd_stream *stream = ctx->stream;
221bf215546Sopenharmony_ci   struct etna_screen *screen = ctx->screen;
222bf215546Sopenharmony_ci   unsigned ccw = ctx->rasterizer->front_ccw;
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   /* Pre-reserve the command buffer space which we are likely to need.
226bf215546Sopenharmony_ci    * This must cover all the state emitted below, and the following
227bf215546Sopenharmony_ci    * draw command. */
228bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, required_stream_size(ctx));
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci   uint32_t dirty = ctx->dirty;
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   /* Pre-processing: see what caches we need to flush before making state changes. */
233bf215546Sopenharmony_ci   uint32_t to_flush = 0;
234bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND)))
235bf215546Sopenharmony_ci      to_flush |= VIVS_GL_FLUSH_CACHE_COLOR;
236bf215546Sopenharmony_ci   if (unlikely(dirty & ETNA_DIRTY_ZSA))
237bf215546Sopenharmony_ci      to_flush |= VIVS_GL_FLUSH_CACHE_DEPTH;
238bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_TEXTURE_CACHES)))
239bf215546Sopenharmony_ci      to_flush |= VIVS_GL_FLUSH_CACHE_TEXTURE;
240bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) /* Framebuffer config changed? */
241bf215546Sopenharmony_ci      to_flush |= VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH;
242bf215546Sopenharmony_ci   if (DBG_ENABLED(ETNA_DBG_CFLUSH_ALL))
243bf215546Sopenharmony_ci      to_flush |= VIVS_GL_FLUSH_CACHE_TEXTURE | VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH;
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   if (to_flush) {
246bf215546Sopenharmony_ci      etna_set_state(stream, VIVS_GL_FLUSH_CACHE, to_flush);
247bf215546Sopenharmony_ci      etna_stall(stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
248bf215546Sopenharmony_ci   }
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   /* Flush TS cache before changing TS configuration. */
251bf215546Sopenharmony_ci   if (unlikely(dirty & ETNA_DIRTY_TS)) {
252bf215546Sopenharmony_ci      etna_set_state(stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);
253bf215546Sopenharmony_ci   }
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci   /* Update vertex elements. This is different from any of the other states, in that
256bf215546Sopenharmony_ci    * a) the number of vertex elements written matters: so write only active ones
257bf215546Sopenharmony_ci    * b) the vertex element states must all be written: do not skip entries that stay the same */
258bf215546Sopenharmony_ci   if (dirty & (ETNA_DIRTY_VERTEX_ELEMENTS)) {
259bf215546Sopenharmony_ci      if (screen->specs.halti >= 5) {
260bf215546Sopenharmony_ci         /*17800*/ etna_set_state_multi(stream, VIVS_NFE_GENERIC_ATTRIB_CONFIG0(0),
261bf215546Sopenharmony_ci            ctx->vertex_elements->num_elements,
262bf215546Sopenharmony_ci            ctx->vertex_elements->NFE_GENERIC_ATTRIB_CONFIG0);
263bf215546Sopenharmony_ci         /*17A00*/ etna_set_state_multi(stream, VIVS_NFE_GENERIC_ATTRIB_SCALE(0),
264bf215546Sopenharmony_ci            ctx->vertex_elements->num_elements,
265bf215546Sopenharmony_ci            ctx->vertex_elements->NFE_GENERIC_ATTRIB_SCALE);
266bf215546Sopenharmony_ci         /*17A80*/ etna_set_state_multi(stream, VIVS_NFE_GENERIC_ATTRIB_CONFIG1(0),
267bf215546Sopenharmony_ci            ctx->vertex_elements->num_elements,
268bf215546Sopenharmony_ci            ctx->vertex_elements->NFE_GENERIC_ATTRIB_CONFIG1);
269bf215546Sopenharmony_ci      } else {
270bf215546Sopenharmony_ci         /* Special case: vertex elements must always be sent in full if changed */
271bf215546Sopenharmony_ci         /*00600*/ etna_set_state_multi(stream, VIVS_FE_VERTEX_ELEMENT_CONFIG(0),
272bf215546Sopenharmony_ci            ctx->vertex_elements->num_elements,
273bf215546Sopenharmony_ci            ctx->vertex_elements->FE_VERTEX_ELEMENT_CONFIG);
274bf215546Sopenharmony_ci         if (screen->specs.halti >= 2) {
275bf215546Sopenharmony_ci            /*00780*/ etna_set_state_multi(stream, VIVS_FE_GENERIC_ATTRIB_SCALE(0),
276bf215546Sopenharmony_ci               ctx->vertex_elements->num_elements,
277bf215546Sopenharmony_ci               ctx->vertex_elements->NFE_GENERIC_ATTRIB_SCALE);
278bf215546Sopenharmony_ci         }
279bf215546Sopenharmony_ci      }
280bf215546Sopenharmony_ci   }
281bf215546Sopenharmony_ci   unsigned vs_output_count = etna_rasterizer_state(ctx->rasterizer)->point_size_per_vertex
282bf215546Sopenharmony_ci                           ? ctx->shader_state.VS_OUTPUT_COUNT_PSIZE
283bf215546Sopenharmony_ci                           : ctx->shader_state.VS_OUTPUT_COUNT;
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   /* The following code is originally generated by gen_merge_state.py, to
286bf215546Sopenharmony_ci    * emit state in increasing order of address (this makes it possible to merge
287bf215546Sopenharmony_ci    * consecutive register updates into one SET_STATE command)
288bf215546Sopenharmony_ci    *
289bf215546Sopenharmony_ci    * There have been some manual changes, where the weaving operation is not
290bf215546Sopenharmony_ci    * simply bitwise or:
291bf215546Sopenharmony_ci    * - scissor fixp
292bf215546Sopenharmony_ci    * - num vertex elements
293bf215546Sopenharmony_ci    * - scissor handling
294bf215546Sopenharmony_ci    * - num samplers
295bf215546Sopenharmony_ci    * - texture lod
296bf215546Sopenharmony_ci    * - ETNA_DIRTY_TS
297bf215546Sopenharmony_ci    * - removed ETNA_DIRTY_BASE_SETUP statements -- these are guaranteed to not
298bf215546Sopenharmony_ci    * change anyway
299bf215546Sopenharmony_ci    * - PS / framebuffer interaction for MSAA
300bf215546Sopenharmony_ci    * - move update of GL_MULTI_SAMPLE_CONFIG first
301bf215546Sopenharmony_ci    * - add unlikely()/likely()
302bf215546Sopenharmony_ci    */
303bf215546Sopenharmony_ci   struct etna_coalesce coalesce;
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   etna_coalesce_start(stream, &coalesce);
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci   /* begin only EMIT_STATE -- make sure no new etna_reserve calls are done here
308bf215546Sopenharmony_ci    * directly
309bf215546Sopenharmony_ci    *    or indirectly */
310bf215546Sopenharmony_ci   /* multi sample config is set first, and outside of the normal sorting
311bf215546Sopenharmony_ci    * order, as changing the multisample state clobbers PS.INPUT_COUNT (and
312bf215546Sopenharmony_ci    * possibly PS.TEMP_REGISTER_CONTROL).
313bf215546Sopenharmony_ci    */
314bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_SAMPLE_MASK))) {
315bf215546Sopenharmony_ci      uint32_t val = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_ENABLES(ctx->sample_mask);
316bf215546Sopenharmony_ci      val |= ctx->framebuffer.GL_MULTI_SAMPLE_CONFIG;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci      /*03818*/ EMIT_STATE(GL_MULTI_SAMPLE_CONFIG, val);
319bf215546Sopenharmony_ci   }
320bf215546Sopenharmony_ci   if (likely(dirty & (ETNA_DIRTY_INDEX_BUFFER))) {
321bf215546Sopenharmony_ci      /*00644*/ EMIT_STATE_RELOC(FE_INDEX_STREAM_BASE_ADDR, &ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR);
322bf215546Sopenharmony_ci      /*00648*/ EMIT_STATE(FE_INDEX_STREAM_CONTROL, ctx->index_buffer.FE_INDEX_STREAM_CONTROL);
323bf215546Sopenharmony_ci   }
324bf215546Sopenharmony_ci   if (likely(dirty & (ETNA_DIRTY_INDEX_BUFFER))) {
325bf215546Sopenharmony_ci      /*00674*/ EMIT_STATE(FE_PRIMITIVE_RESTART_INDEX, ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX);
326bf215546Sopenharmony_ci   }
327bf215546Sopenharmony_ci   if (likely(dirty & (ETNA_DIRTY_VERTEX_BUFFERS))) {
328bf215546Sopenharmony_ci      if (screen->specs.halti >= 2) { /* HALTI2+: NFE_VERTEX_STREAMS */
329bf215546Sopenharmony_ci         for (int x = 0; x < ctx->vertex_buffer.count; ++x) {
330bf215546Sopenharmony_ci            /*14600*/ EMIT_STATE_RELOC(NFE_VERTEX_STREAMS_BASE_ADDR(x), &ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR);
331bf215546Sopenharmony_ci         }
332bf215546Sopenharmony_ci         for (int x = 0; x < ctx->vertex_buffer.count; ++x) {
333bf215546Sopenharmony_ci            if (ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR.bo) {
334bf215546Sopenharmony_ci               /*14640*/ EMIT_STATE(NFE_VERTEX_STREAMS_CONTROL(x), ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_CONTROL);
335bf215546Sopenharmony_ci            }
336bf215546Sopenharmony_ci         }
337bf215546Sopenharmony_ci      } else if(screen->specs.stream_count > 1) { /* hw w/ multiple vertex streams */
338bf215546Sopenharmony_ci         for (int x = 0; x < ctx->vertex_buffer.count; ++x) {
339bf215546Sopenharmony_ci            /*00680*/ EMIT_STATE_RELOC(FE_VERTEX_STREAMS_BASE_ADDR(x), &ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR);
340bf215546Sopenharmony_ci         }
341bf215546Sopenharmony_ci         for (int x = 0; x < ctx->vertex_buffer.count; ++x) {
342bf215546Sopenharmony_ci            if (ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR.bo) {
343bf215546Sopenharmony_ci               /*006A0*/ EMIT_STATE(FE_VERTEX_STREAMS_CONTROL(x), ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_CONTROL);
344bf215546Sopenharmony_ci            }
345bf215546Sopenharmony_ci         }
346bf215546Sopenharmony_ci      } else { /* hw w/ single vertex stream */
347bf215546Sopenharmony_ci         /*0064C*/ EMIT_STATE_RELOC(FE_VERTEX_STREAM_BASE_ADDR, &ctx->vertex_buffer.cvb[0].FE_VERTEX_STREAM_BASE_ADDR);
348bf215546Sopenharmony_ci         /*00650*/ EMIT_STATE(FE_VERTEX_STREAM_CONTROL, ctx->vertex_buffer.cvb[0].FE_VERTEX_STREAM_CONTROL);
349bf215546Sopenharmony_ci      }
350bf215546Sopenharmony_ci   }
351bf215546Sopenharmony_ci   /* gallium has instance divisor as part of elements state */
352bf215546Sopenharmony_ci   if ((dirty & (ETNA_DIRTY_VERTEX_ELEMENTS)) && screen->specs.halti >= 2) {
353bf215546Sopenharmony_ci      for (int x = 0; x < ctx->vertex_elements->num_buffers; ++x) {
354bf215546Sopenharmony_ci         /*14680*/ EMIT_STATE(NFE_VERTEX_STREAMS_VERTEX_DIVISOR(x), ctx->vertex_elements->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[x]);
355bf215546Sopenharmony_ci      }
356bf215546Sopenharmony_ci   }
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_RASTERIZER))) {
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci      /*00804*/ EMIT_STATE(VS_OUTPUT_COUNT, vs_output_count);
361bf215546Sopenharmony_ci   }
362bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_VERTEX_ELEMENTS | ETNA_DIRTY_SHADER))) {
363bf215546Sopenharmony_ci      /*00808*/ EMIT_STATE(VS_INPUT_COUNT, ctx->shader_state.VS_INPUT_COUNT);
364bf215546Sopenharmony_ci      /*0080C*/ EMIT_STATE(VS_TEMP_REGISTER_CONTROL, ctx->shader_state.VS_TEMP_REGISTER_CONTROL);
365bf215546Sopenharmony_ci   }
366bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
367bf215546Sopenharmony_ci      /*00830*/ EMIT_STATE(VS_LOAD_BALANCING, ctx->shader_state.VS_LOAD_BALANCING);
368bf215546Sopenharmony_ci   }
369bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) {
370bf215546Sopenharmony_ci      /*00A00*/ EMIT_STATE_FIXP(PA_VIEWPORT_SCALE_X, ctx->viewport.PA_VIEWPORT_SCALE_X);
371bf215546Sopenharmony_ci      /*00A04*/ EMIT_STATE_FIXP(PA_VIEWPORT_SCALE_Y, ctx->viewport.PA_VIEWPORT_SCALE_Y);
372bf215546Sopenharmony_ci      /*00A08*/ EMIT_STATE(PA_VIEWPORT_SCALE_Z, ctx->viewport.PA_VIEWPORT_SCALE_Z);
373bf215546Sopenharmony_ci      /*00A0C*/ EMIT_STATE_FIXP(PA_VIEWPORT_OFFSET_X, ctx->viewport.PA_VIEWPORT_OFFSET_X);
374bf215546Sopenharmony_ci      /*00A10*/ EMIT_STATE_FIXP(PA_VIEWPORT_OFFSET_Y, ctx->viewport.PA_VIEWPORT_OFFSET_Y);
375bf215546Sopenharmony_ci      /*00A14*/ EMIT_STATE(PA_VIEWPORT_OFFSET_Z, ctx->viewport.PA_VIEWPORT_OFFSET_Z);
376bf215546Sopenharmony_ci   }
377bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER))) {
378bf215546Sopenharmony_ci      struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer);
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci      /*00A18*/ EMIT_STATE(PA_LINE_WIDTH, rasterizer->PA_LINE_WIDTH);
381bf215546Sopenharmony_ci      /*00A1C*/ EMIT_STATE(PA_POINT_SIZE, rasterizer->PA_POINT_SIZE);
382bf215546Sopenharmony_ci      /*00A28*/ EMIT_STATE(PA_SYSTEM_MODE, rasterizer->PA_SYSTEM_MODE);
383bf215546Sopenharmony_ci   }
384bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
385bf215546Sopenharmony_ci      /*00A30*/ EMIT_STATE(PA_ATTRIBUTE_ELEMENT_COUNT, ctx->shader_state.PA_ATTRIBUTE_ELEMENT_COUNT);
386bf215546Sopenharmony_ci   }
387bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_SHADER))) {
388bf215546Sopenharmony_ci      uint32_t val = etna_rasterizer_state(ctx->rasterizer)->PA_CONFIG;
389bf215546Sopenharmony_ci      /*00A34*/ EMIT_STATE(PA_CONFIG, val & ctx->shader_state.PA_CONFIG);
390bf215546Sopenharmony_ci   }
391bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER))) {
392bf215546Sopenharmony_ci      struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer);
393bf215546Sopenharmony_ci      /*00A38*/ EMIT_STATE(PA_WIDE_LINE_WIDTH0, rasterizer->PA_LINE_WIDTH);
394bf215546Sopenharmony_ci      /*00A3C*/ EMIT_STATE(PA_WIDE_LINE_WIDTH1, rasterizer->PA_LINE_WIDTH);
395bf215546Sopenharmony_ci   }
396bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SCISSOR_CLIP))) {
397bf215546Sopenharmony_ci      /*00C00*/ EMIT_STATE_FIXP(SE_SCISSOR_LEFT, ctx->clipping.minx << 16);
398bf215546Sopenharmony_ci      /*00C04*/ EMIT_STATE_FIXP(SE_SCISSOR_TOP, ctx->clipping.miny << 16);
399bf215546Sopenharmony_ci      /*00C08*/ EMIT_STATE_FIXP(SE_SCISSOR_RIGHT, (ctx->clipping.maxx << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT);
400bf215546Sopenharmony_ci      /*00C0C*/ EMIT_STATE_FIXP(SE_SCISSOR_BOTTOM, (ctx->clipping.maxy << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM);
401bf215546Sopenharmony_ci   }
402bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_RASTERIZER))) {
403bf215546Sopenharmony_ci      struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer);
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci      /*00C10*/ EMIT_STATE(SE_DEPTH_SCALE, rasterizer->SE_DEPTH_SCALE);
406bf215546Sopenharmony_ci      /*00C14*/ EMIT_STATE(SE_DEPTH_BIAS, rasterizer->SE_DEPTH_BIAS);
407bf215546Sopenharmony_ci      /*00C18*/ EMIT_STATE(SE_CONFIG, rasterizer->SE_CONFIG);
408bf215546Sopenharmony_ci   }
409bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SCISSOR_CLIP))) {
410bf215546Sopenharmony_ci      /*00C20*/ EMIT_STATE_FIXP(SE_CLIP_RIGHT, (ctx->clipping.maxx << 16) + ETNA_SE_CLIP_MARGIN_RIGHT);
411bf215546Sopenharmony_ci      /*00C24*/ EMIT_STATE_FIXP(SE_CLIP_BOTTOM, (ctx->clipping.maxy << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM);
412bf215546Sopenharmony_ci   }
413bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
414bf215546Sopenharmony_ci      /*00E00*/ EMIT_STATE(RA_CONTROL, ctx->shader_state.RA_CONTROL);
415bf215546Sopenharmony_ci   }
416bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_ZSA))) {
417bf215546Sopenharmony_ci      /*00E08*/ EMIT_STATE(RA_EARLY_DEPTH, etna_zsa_state(ctx->zsa)->RA_DEPTH_CONFIG);
418bf215546Sopenharmony_ci   }
419bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_FRAMEBUFFER))) {
420bf215546Sopenharmony_ci      /*01004*/ EMIT_STATE(PS_OUTPUT_REG, ctx->shader_state.PS_OUTPUT_REG);
421bf215546Sopenharmony_ci      /*01008*/ EMIT_STATE(PS_INPUT_COUNT,
422bf215546Sopenharmony_ci                           ctx->framebuffer.msaa_mode
423bf215546Sopenharmony_ci                              ? ctx->shader_state.PS_INPUT_COUNT_MSAA
424bf215546Sopenharmony_ci                              : ctx->shader_state.PS_INPUT_COUNT);
425bf215546Sopenharmony_ci      /*0100C*/ EMIT_STATE(PS_TEMP_REGISTER_CONTROL,
426bf215546Sopenharmony_ci                           ctx->framebuffer.msaa_mode
427bf215546Sopenharmony_ci                              ? ctx->shader_state.PS_TEMP_REGISTER_CONTROL_MSAA
428bf215546Sopenharmony_ci                              : ctx->shader_state.PS_TEMP_REGISTER_CONTROL);
429bf215546Sopenharmony_ci      /*01010*/ EMIT_STATE(PS_CONTROL, ctx->framebuffer.PS_CONTROL);
430bf215546Sopenharmony_ci      /*01030*/ EMIT_STATE(PS_CONTROL_EXT, ctx->framebuffer.PS_CONTROL_EXT);
431bf215546Sopenharmony_ci   }
432bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_SHADER))) {
433bf215546Sopenharmony_ci      /*01400*/ EMIT_STATE(PE_DEPTH_CONFIG, (etna_zsa_state(ctx->zsa)->PE_DEPTH_CONFIG |
434bf215546Sopenharmony_ci                                             ctx->framebuffer.PE_DEPTH_CONFIG));
435bf215546Sopenharmony_ci   }
436bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) {
437bf215546Sopenharmony_ci      /*01404*/ EMIT_STATE(PE_DEPTH_NEAR, ctx->viewport.PE_DEPTH_NEAR);
438bf215546Sopenharmony_ci      /*01408*/ EMIT_STATE(PE_DEPTH_FAR, ctx->viewport.PE_DEPTH_FAR);
439bf215546Sopenharmony_ci   }
440bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) {
441bf215546Sopenharmony_ci      /*0140C*/ EMIT_STATE(PE_DEPTH_NORMALIZE, ctx->framebuffer.PE_DEPTH_NORMALIZE);
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci      if (screen->specs.halti < 0 || screen->model == 0x880) {
444bf215546Sopenharmony_ci         /*01410*/ EMIT_STATE_RELOC(PE_DEPTH_ADDR, &ctx->framebuffer.PE_DEPTH_ADDR);
445bf215546Sopenharmony_ci      }
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci      /*01414*/ EMIT_STATE(PE_DEPTH_STRIDE, ctx->framebuffer.PE_DEPTH_STRIDE);
448bf215546Sopenharmony_ci   }
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_RASTERIZER))) {
451bf215546Sopenharmony_ci      uint32_t val = etna_zsa_state(ctx->zsa)->PE_STENCIL_OP[ccw];
452bf215546Sopenharmony_ci      /*01418*/ EMIT_STATE(PE_STENCIL_OP, val);
453bf215546Sopenharmony_ci   }
454bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_STENCIL_REF | ETNA_DIRTY_RASTERIZER))) {
455bf215546Sopenharmony_ci      uint32_t val = etna_zsa_state(ctx->zsa)->PE_STENCIL_CONFIG[ccw];
456bf215546Sopenharmony_ci      /*0141C*/ EMIT_STATE(PE_STENCIL_CONFIG, val | ctx->stencil_ref.PE_STENCIL_CONFIG[ccw]);
457bf215546Sopenharmony_ci   }
458bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_ZSA))) {
459bf215546Sopenharmony_ci      uint32_t val = etna_zsa_state(ctx->zsa)->PE_ALPHA_OP;
460bf215546Sopenharmony_ci      /*01420*/ EMIT_STATE(PE_ALPHA_OP, val);
461bf215546Sopenharmony_ci   }
462bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND_COLOR))) {
463bf215546Sopenharmony_ci      /*01424*/ EMIT_STATE(PE_ALPHA_BLEND_COLOR, ctx->blend_color.PE_ALPHA_BLEND_COLOR);
464bf215546Sopenharmony_ci   }
465bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND))) {
466bf215546Sopenharmony_ci      uint32_t val = etna_blend_state(ctx->blend)->PE_ALPHA_CONFIG;
467bf215546Sopenharmony_ci      /*01428*/ EMIT_STATE(PE_ALPHA_CONFIG, val);
468bf215546Sopenharmony_ci   }
469bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER))) {
470bf215546Sopenharmony_ci      uint32_t val;
471bf215546Sopenharmony_ci      /* Use the components and overwrite bits in framebuffer.PE_COLOR_FORMAT
472bf215546Sopenharmony_ci       * as a mask to enable the bits from blend PE_COLOR_FORMAT */
473bf215546Sopenharmony_ci      val = ~(VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK |
474bf215546Sopenharmony_ci              VIVS_PE_COLOR_FORMAT_OVERWRITE);
475bf215546Sopenharmony_ci      val |= etna_blend_state(ctx->blend)->PE_COLOR_FORMAT;
476bf215546Sopenharmony_ci      val &= ctx->framebuffer.PE_COLOR_FORMAT;
477bf215546Sopenharmony_ci      /*0142C*/ EMIT_STATE(PE_COLOR_FORMAT, val);
478bf215546Sopenharmony_ci   }
479bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER))) {
480bf215546Sopenharmony_ci      if (screen->specs.halti >= 0 && screen->model != 0x880) {
481bf215546Sopenharmony_ci         /*01434*/ EMIT_STATE(PE_COLOR_STRIDE, ctx->framebuffer.PE_COLOR_STRIDE);
482bf215546Sopenharmony_ci         /*01454*/ EMIT_STATE(PE_HDEPTH_CONTROL, ctx->framebuffer.PE_HDEPTH_CONTROL);
483bf215546Sopenharmony_ci         /*01460*/ EMIT_STATE_RELOC(PE_PIPE_COLOR_ADDR(0), &ctx->framebuffer.PE_PIPE_COLOR_ADDR[0]);
484bf215546Sopenharmony_ci         /*01464*/ EMIT_STATE_RELOC(PE_PIPE_COLOR_ADDR(1), &ctx->framebuffer.PE_PIPE_COLOR_ADDR[1]);
485bf215546Sopenharmony_ci         /*01480*/ EMIT_STATE_RELOC(PE_PIPE_DEPTH_ADDR(0), &ctx->framebuffer.PE_PIPE_DEPTH_ADDR[0]);
486bf215546Sopenharmony_ci         /*01484*/ EMIT_STATE_RELOC(PE_PIPE_DEPTH_ADDR(1), &ctx->framebuffer.PE_PIPE_DEPTH_ADDR[1]);
487bf215546Sopenharmony_ci      } else {
488bf215546Sopenharmony_ci         /*01430*/ EMIT_STATE_RELOC(PE_COLOR_ADDR, &ctx->framebuffer.PE_COLOR_ADDR);
489bf215546Sopenharmony_ci         /*01434*/ EMIT_STATE(PE_COLOR_STRIDE, ctx->framebuffer.PE_COLOR_STRIDE);
490bf215546Sopenharmony_ci         /*01454*/ EMIT_STATE(PE_HDEPTH_CONTROL, ctx->framebuffer.PE_HDEPTH_CONTROL);
491bf215546Sopenharmony_ci      }
492bf215546Sopenharmony_ci   }
493bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_STENCIL_REF | ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_ZSA))) {
494bf215546Sopenharmony_ci      uint32_t val = etna_zsa_state(ctx->zsa)->PE_STENCIL_CONFIG_EXT;
495bf215546Sopenharmony_ci      /*014A0*/ EMIT_STATE(PE_STENCIL_CONFIG_EXT, val | ctx->stencil_ref.PE_STENCIL_CONFIG_EXT[ccw]);
496bf215546Sopenharmony_ci   }
497bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER))) {
498bf215546Sopenharmony_ci      struct etna_blend_state *blend = etna_blend_state(ctx->blend);
499bf215546Sopenharmony_ci      /*014A4*/ EMIT_STATE(PE_LOGIC_OP, blend->PE_LOGIC_OP | ctx->framebuffer.PE_LOGIC_OP);
500bf215546Sopenharmony_ci   }
501bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND))) {
502bf215546Sopenharmony_ci      struct etna_blend_state *blend = etna_blend_state(ctx->blend);
503bf215546Sopenharmony_ci      for (int x = 0; x < 2; ++x) {
504bf215546Sopenharmony_ci         /*014A8*/ EMIT_STATE(PE_DITHER(x), blend->PE_DITHER[x]);
505bf215546Sopenharmony_ci      }
506bf215546Sopenharmony_ci   }
507bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_BLEND_COLOR)) &&
508bf215546Sopenharmony_ci       VIV_FEATURE(screen, chipMinorFeatures1, HALF_FLOAT)) {
509bf215546Sopenharmony_ci         /*014B0*/ EMIT_STATE(PE_ALPHA_COLOR_EXT0, ctx->blend_color.PE_ALPHA_COLOR_EXT0);
510bf215546Sopenharmony_ci         /*014B4*/ EMIT_STATE(PE_ALPHA_COLOR_EXT1, ctx->blend_color.PE_ALPHA_COLOR_EXT1);
511bf215546Sopenharmony_ci   }
512bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_RASTERIZER))) {
513bf215546Sopenharmony_ci      /*014B8*/ EMIT_STATE(PE_STENCIL_CONFIG_EXT2, etna_zsa_state(ctx->zsa)->PE_STENCIL_CONFIG_EXT2[ccw]);
514bf215546Sopenharmony_ci   }
515bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER)) && screen->specs.halti >= 3)
516bf215546Sopenharmony_ci      /*014BC*/ EMIT_STATE(PE_MEM_CONFIG, ctx->framebuffer.PE_MEM_CONFIG);
517bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_TS))) {
518bf215546Sopenharmony_ci      /*01654*/ EMIT_STATE(TS_MEM_CONFIG, ctx->framebuffer.TS_MEM_CONFIG);
519bf215546Sopenharmony_ci      /*01658*/ EMIT_STATE_RELOC(TS_COLOR_STATUS_BASE, &ctx->framebuffer.TS_COLOR_STATUS_BASE);
520bf215546Sopenharmony_ci      /*0165C*/ EMIT_STATE_RELOC(TS_COLOR_SURFACE_BASE, &ctx->framebuffer.TS_COLOR_SURFACE_BASE);
521bf215546Sopenharmony_ci      /*01660*/ EMIT_STATE(TS_COLOR_CLEAR_VALUE, ctx->framebuffer.TS_COLOR_CLEAR_VALUE);
522bf215546Sopenharmony_ci      /*01664*/ EMIT_STATE_RELOC(TS_DEPTH_STATUS_BASE, &ctx->framebuffer.TS_DEPTH_STATUS_BASE);
523bf215546Sopenharmony_ci      /*01668*/ EMIT_STATE_RELOC(TS_DEPTH_SURFACE_BASE, &ctx->framebuffer.TS_DEPTH_SURFACE_BASE);
524bf215546Sopenharmony_ci      /*0166C*/ EMIT_STATE(TS_DEPTH_CLEAR_VALUE, ctx->framebuffer.TS_DEPTH_CLEAR_VALUE);
525bf215546Sopenharmony_ci      /*016BC*/ EMIT_STATE(TS_COLOR_CLEAR_VALUE_EXT, ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT);
526bf215546Sopenharmony_ci   }
527bf215546Sopenharmony_ci   if (unlikely(dirty & (ETNA_DIRTY_SHADER))) {
528bf215546Sopenharmony_ci      /*0381C*/ EMIT_STATE(GL_VARYING_TOTAL_COMPONENTS, ctx->shader_state.GL_VARYING_TOTAL_COMPONENTS);
529bf215546Sopenharmony_ci   }
530bf215546Sopenharmony_ci   etna_coalesce_end(stream, &coalesce);
531bf215546Sopenharmony_ci   /* end only EMIT_STATE */
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   /* Emit strongly architecture-specific state */
534bf215546Sopenharmony_ci   if (screen->specs.halti >= 5)
535bf215546Sopenharmony_ci      emit_halti5_only_state(ctx, vs_output_count);
536bf215546Sopenharmony_ci   else
537bf215546Sopenharmony_ci      emit_pre_halti5_state(ctx);
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   /* Beginning from Halti0 some of the new shader and sampler states are not
540bf215546Sopenharmony_ci    * self-synchronizing anymore. Thus we need to stall the FE on PE completion
541bf215546Sopenharmony_ci    * before loading the new states to avoid corrupting the state of the
542bf215546Sopenharmony_ci    * in-flight draw.
543bf215546Sopenharmony_ci    */
544bf215546Sopenharmony_ci   if (screen->specs.halti >= 0 &&
545bf215546Sopenharmony_ci       (ctx->dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_CONSTBUF |
546bf215546Sopenharmony_ci                      ETNA_DIRTY_SAMPLERS | ETNA_DIRTY_SAMPLER_VIEWS)))
547bf215546Sopenharmony_ci      etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci   ctx->emit_texture_state(ctx);
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   /* We need to update the uniform cache only if one of the following bits are
552bf215546Sopenharmony_ci    * set in ctx->dirty:
553bf215546Sopenharmony_ci    * - ETNA_DIRTY_SHADER
554bf215546Sopenharmony_ci    * - ETNA_DIRTY_CONSTBUF
555bf215546Sopenharmony_ci    * - uniforms_dirty_bits
556bf215546Sopenharmony_ci    *
557bf215546Sopenharmony_ci    * In case of ETNA_DIRTY_SHADER we need load all uniforms from the cache. In
558bf215546Sopenharmony_ci    * all
559bf215546Sopenharmony_ci    * other cases we can load on the changed uniforms.
560bf215546Sopenharmony_ci    */
561bf215546Sopenharmony_ci   static const uint32_t uniform_dirty_bits =
562bf215546Sopenharmony_ci      ETNA_DIRTY_SHADER | ETNA_DIRTY_CONSTBUF;
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci   /**** Large dynamically-sized state ****/
565bf215546Sopenharmony_ci   bool do_uniform_flush = screen->specs.halti < 5;
566bf215546Sopenharmony_ci   if (dirty & (ETNA_DIRTY_SHADER)) {
567bf215546Sopenharmony_ci      /* Special case: a new shader was loaded; simply re-load all uniforms and
568bf215546Sopenharmony_ci       * shader code at once */
569bf215546Sopenharmony_ci      /* This sequence is special, do not change ordering unless necessary. According to comment
570bf215546Sopenharmony_ci         snippets in the Vivante kernel driver a process called "steering" goes on while programming
571bf215546Sopenharmony_ci         shader state. This (as I understand it) means certain unified states are "steered"
572bf215546Sopenharmony_ci         toward a specific shader unit (VS/PS/...) based on either explicit flags in register
573bf215546Sopenharmony_ci         00860, or what other state is written before "auto-steering". So this means some
574bf215546Sopenharmony_ci         state can legitimately be programmed multiple times.
575bf215546Sopenharmony_ci       */
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci      if (screen->specs.halti >= 5) { /* ICACHE (HALTI5) */
578bf215546Sopenharmony_ci         assert(ctx->shader_state.VS_INST_ADDR.bo && ctx->shader_state.PS_INST_ADDR.bo);
579bf215546Sopenharmony_ci         /* Set icache (VS) */
580bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_NEWRANGE_LOW, 0);
581bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_NEWRANGE_HIGH, ctx->shader_state.vs_inst_mem_size / 4);
582bf215546Sopenharmony_ci         assert(ctx->shader_state.VS_INST_ADDR.bo);
583bf215546Sopenharmony_ci         etna_set_state_reloc(stream, VIVS_VS_INST_ADDR, &ctx->shader_state.VS_INST_ADDR);
584bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_SH_CONFIG, 0x00000002);
585bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_ICACHE_CONTROL, VIVS_VS_ICACHE_CONTROL_ENABLE);
586bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_ICACHE_COUNT, ctx->shader_state.vs_inst_mem_size / 4 - 1);
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci         /* Set icache (PS) */
589bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_PS_NEWRANGE_LOW, 0);
590bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_PS_NEWRANGE_HIGH, ctx->shader_state.ps_inst_mem_size / 4);
591bf215546Sopenharmony_ci         assert(ctx->shader_state.PS_INST_ADDR.bo);
592bf215546Sopenharmony_ci         etna_set_state_reloc(stream, VIVS_PS_INST_ADDR, &ctx->shader_state.PS_INST_ADDR);
593bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_SH_CONFIG, 0x00000002);
594bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_ICACHE_CONTROL, VIVS_VS_ICACHE_CONTROL_ENABLE);
595bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_PS_ICACHE_COUNT, ctx->shader_state.ps_inst_mem_size / 4 - 1);
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci      } else if (ctx->shader_state.VS_INST_ADDR.bo || ctx->shader_state.PS_INST_ADDR.bo) {
598bf215546Sopenharmony_ci         /* ICACHE (pre-HALTI5) */
599bf215546Sopenharmony_ci         assert(screen->specs.has_icache && screen->specs.has_shader_range_registers);
600bf215546Sopenharmony_ci         /* Set icache (VS) */
601bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_RANGE, (ctx->shader_state.vs_inst_mem_size / 4 - 1) << 16);
602bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_ICACHE_CONTROL,
603bf215546Sopenharmony_ci               VIVS_VS_ICACHE_CONTROL_ENABLE |
604bf215546Sopenharmony_ci               VIVS_VS_ICACHE_CONTROL_FLUSH_VS);
605bf215546Sopenharmony_ci         assert(ctx->shader_state.VS_INST_ADDR.bo);
606bf215546Sopenharmony_ci         etna_set_state_reloc(stream, VIVS_VS_INST_ADDR, &ctx->shader_state.VS_INST_ADDR);
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci         /* Set icache (PS) */
609bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_PS_RANGE, (ctx->shader_state.ps_inst_mem_size / 4 - 1) << 16);
610bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_ICACHE_CONTROL,
611bf215546Sopenharmony_ci               VIVS_VS_ICACHE_CONTROL_ENABLE |
612bf215546Sopenharmony_ci               VIVS_VS_ICACHE_CONTROL_FLUSH_PS);
613bf215546Sopenharmony_ci         assert(ctx->shader_state.PS_INST_ADDR.bo);
614bf215546Sopenharmony_ci         etna_set_state_reloc(stream, VIVS_PS_INST_ADDR, &ctx->shader_state.PS_INST_ADDR);
615bf215546Sopenharmony_ci      } else {
616bf215546Sopenharmony_ci         /* Upload shader directly, first flushing and disabling icache if
617bf215546Sopenharmony_ci          * supported on this hw */
618bf215546Sopenharmony_ci         if (screen->specs.has_icache) {
619bf215546Sopenharmony_ci            etna_set_state(stream, VIVS_VS_ICACHE_CONTROL,
620bf215546Sopenharmony_ci                  VIVS_VS_ICACHE_CONTROL_FLUSH_PS |
621bf215546Sopenharmony_ci                  VIVS_VS_ICACHE_CONTROL_FLUSH_VS);
622bf215546Sopenharmony_ci         }
623bf215546Sopenharmony_ci         if (screen->specs.has_shader_range_registers) {
624bf215546Sopenharmony_ci            etna_set_state(stream, VIVS_VS_RANGE, (ctx->shader_state.vs_inst_mem_size / 4 - 1) << 16);
625bf215546Sopenharmony_ci            etna_set_state(stream, VIVS_PS_RANGE, ((ctx->shader_state.ps_inst_mem_size / 4 - 1 + 0x100) << 16) |
626bf215546Sopenharmony_ci                                        0x100);
627bf215546Sopenharmony_ci         }
628bf215546Sopenharmony_ci         etna_set_state_multi(stream, screen->specs.vs_offset,
629bf215546Sopenharmony_ci                              ctx->shader_state.vs_inst_mem_size,
630bf215546Sopenharmony_ci                              ctx->shader_state.VS_INST_MEM);
631bf215546Sopenharmony_ci         etna_set_state_multi(stream, screen->specs.ps_offset,
632bf215546Sopenharmony_ci                              ctx->shader_state.ps_inst_mem_size,
633bf215546Sopenharmony_ci                              ctx->shader_state.PS_INST_MEM);
634bf215546Sopenharmony_ci      }
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_ci      if (screen->specs.has_unified_uniforms) {
637bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_UNIFORM_BASE, 0);
638bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_PS_UNIFORM_BASE, screen->specs.max_vs_uniforms);
639bf215546Sopenharmony_ci      }
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci      if (do_uniform_flush)
642bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH);
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci      etna_uniforms_write(ctx, ctx->shader.vs, ctx->constant_buffer[PIPE_SHADER_VERTEX].cb);
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci      if (do_uniform_flush)
647bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH | VIVS_VS_UNIFORM_CACHE_PS);
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci      etna_uniforms_write(ctx, ctx->shader.fs, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].cb);
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci      if (screen->specs.halti >= 5) {
652bf215546Sopenharmony_ci         /* HALTI5 needs to be prompted to pre-fetch shaders */
653bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_ICACHE_PREFETCH, 0x00000000);
654bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_PS_ICACHE_PREFETCH, 0x00000000);
655bf215546Sopenharmony_ci         etna_stall(stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
656bf215546Sopenharmony_ci      }
657bf215546Sopenharmony_ci   } else {
658bf215546Sopenharmony_ci      /* ideally this cache would only be flushed if there are VS uniform changes */
659bf215546Sopenharmony_ci      if (do_uniform_flush)
660bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH);
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci      if (dirty & (uniform_dirty_bits | ctx->shader.vs->uniforms_dirty_bits))
663bf215546Sopenharmony_ci         etna_uniforms_write(ctx, ctx->shader.vs, ctx->constant_buffer[PIPE_SHADER_VERTEX].cb);
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci      /* ideally this cache would only be flushed if there are PS uniform changes */
666bf215546Sopenharmony_ci      if (do_uniform_flush)
667bf215546Sopenharmony_ci         etna_set_state(stream, VIVS_VS_UNIFORM_CACHE, VIVS_VS_UNIFORM_CACHE_FLUSH | VIVS_VS_UNIFORM_CACHE_PS);
668bf215546Sopenharmony_ci
669bf215546Sopenharmony_ci      if (dirty & (uniform_dirty_bits | ctx->shader.fs->uniforms_dirty_bits))
670bf215546Sopenharmony_ci         etna_uniforms_write(ctx, ctx->shader.fs, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].cb);
671bf215546Sopenharmony_ci   }
672bf215546Sopenharmony_ci/**** End of state update ****/
673bf215546Sopenharmony_ci#undef EMIT_STATE
674bf215546Sopenharmony_ci#undef EMIT_STATE_FIXP
675bf215546Sopenharmony_ci#undef EMIT_STATE_RELOC
676bf215546Sopenharmony_ci   ctx->dirty = 0;
677bf215546Sopenharmony_ci   ctx->dirty_sampler_views = 0;
678bf215546Sopenharmony_ci}
679