1 /*
2 * Copyright (c) 2012-2015 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Wladimir J. van der Laan <laanwj@gmail.com>
25 * Christian Gmeiner <christian.gmeiner@gmail.com>
26 */
27
28 #include "etnaviv_state.h"
29
30 #include "etnaviv_blend.h"
31 #include "etnaviv_clear_blit.h"
32 #include "etnaviv_context.h"
33 #include "etnaviv_format.h"
34 #include "etnaviv_rasterizer.h"
35 #include "etnaviv_screen.h"
36 #include "etnaviv_shader.h"
37 #include "etnaviv_surface.h"
38 #include "etnaviv_translate.h"
39 #include "etnaviv_util.h"
40 #include "etnaviv_zsa.h"
41 #include "util/u_framebuffer.h"
42 #include "util/u_helpers.h"
43 #include "util/u_inlines.h"
44 #include "util/u_math.h"
45 #include "util/u_memory.h"
46 #include "util/u_upload_mgr.h"
47
48 static void
etna_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref sr)49 etna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref sr)
50 {
51 struct etna_context *ctx = etna_context(pctx);
52 struct compiled_stencil_ref *cs = &ctx->stencil_ref;
53
54 ctx->stencil_ref_s = sr;
55
56 for (unsigned i = 0; i < 2; i++) {
57 cs->PE_STENCIL_CONFIG[i] =
58 VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr.ref_value[i]);
59 cs->PE_STENCIL_CONFIG_EXT[i] =
60 VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr.ref_value[!i]);
61 }
62 ctx->dirty |= ETNA_DIRTY_STENCIL_REF;
63 }
64
65 static void
etna_set_clip_state(struct pipe_context * pctx,const struct pipe_clip_state * pcs)66 etna_set_clip_state(struct pipe_context *pctx, const struct pipe_clip_state *pcs)
67 {
68 /* NOOP */
69 }
70
71 static void
etna_set_sample_mask(struct pipe_context * pctx,unsigned sample_mask)72 etna_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
73 {
74 struct etna_context *ctx = etna_context(pctx);
75
76 ctx->sample_mask = sample_mask;
77 ctx->dirty |= ETNA_DIRTY_SAMPLE_MASK;
78 }
79
80 static void
etna_set_constant_buffer(struct pipe_context * pctx,enum pipe_shader_type shader,uint index,bool take_ownership,const struct pipe_constant_buffer * cb)81 etna_set_constant_buffer(struct pipe_context *pctx,
82 enum pipe_shader_type shader, uint index, bool take_ownership,
83 const struct pipe_constant_buffer *cb)
84 {
85 struct etna_context *ctx = etna_context(pctx);
86 struct etna_constbuf_state *so = &ctx->constant_buffer[shader];
87
88 assert(index < ETNA_MAX_CONST_BUF);
89
90 util_copy_constant_buffer(&so->cb[index], cb, take_ownership);
91
92 /* Note that the gallium frontends can unbind constant buffers by
93 * passing NULL here. */
94 if (unlikely(!cb || (!cb->buffer && !cb->user_buffer))) {
95 so->enabled_mask &= ~(1 << index);
96 return;
97 }
98
99 assert(index != 0 || cb->user_buffer != NULL);
100
101 if (!cb->buffer) {
102 struct pipe_constant_buffer *cb = &so->cb[index];
103 u_upload_data(pctx->const_uploader, 0, cb->buffer_size, 16, cb->user_buffer, &cb->buffer_offset, &cb->buffer);
104 ctx->dirty |= ETNA_DIRTY_SHADER_CACHES;
105 }
106
107 so->enabled_mask |= 1 << index;
108 ctx->dirty |= ETNA_DIRTY_CONSTBUF;
109 }
110
111 static void
etna_update_render_surface(struct pipe_context * pctx,struct etna_surface * surf)112 etna_update_render_surface(struct pipe_context *pctx, struct etna_surface *surf)
113 {
114 struct etna_resource *base = etna_resource(surf->prsc);
115 struct etna_resource *to = base, *from = base;
116 unsigned level = surf->base.u.tex.level;
117
118 if (base->texture &&
119 etna_resource_level_newer(&etna_resource(base->texture)->levels[level],
120 surf->level))
121 from = etna_resource(base->texture);
122
123 if (base->render)
124 to = etna_resource(base->render);
125
126 if ((to != from) &&
127 etna_resource_level_older(&to->levels[level], &from->levels[level]))
128 etna_copy_resource(pctx, &to->base, &from->base, level, level);
129 }
130
131 static void
etna_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * fb)132 etna_set_framebuffer_state(struct pipe_context *pctx,
133 const struct pipe_framebuffer_state *fb)
134 {
135 struct etna_context *ctx = etna_context(pctx);
136 struct etna_screen *screen = ctx->screen;
137 struct compiled_framebuffer_state *cs = &ctx->framebuffer;
138 int nr_samples_color = -1;
139 int nr_samples_depth = -1;
140 bool target_16bpp = false;
141 bool target_linear = false;
142
143 memset(cs, 0, sizeof(struct compiled_framebuffer_state));
144
145 /* Set up TS as well. Warning: this state is used by both the RS and PE */
146 uint32_t ts_mem_config = 0;
147 uint32_t pe_mem_config = 0;
148 uint32_t pe_logic_op = 0;
149
150 const bool use_ts = etna_use_ts_for_mrt(screen, fb);
151 unsigned rt = 0;
152
153 for (unsigned i = 0; i < fb->nr_cbufs; i++) {
154 if (!fb->cbufs[i])
155 continue;
156
157 struct etna_surface *cbuf = etna_surface(fb->cbufs[i]);
158 struct etna_resource *res = etna_resource(cbuf->base.texture);
159 bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0;
160 uint32_t fmt = translate_pe_format(cbuf->base.format);
161
162 /* Resolve TS if needed */
163 if (!use_ts) {
164 etna_copy_resource(pctx, &res->base, &res->base, cbuf->base.u.tex.level, cbuf->base.u.tex.level);
165 etna_resource_level_ts_mark_invalid(&res->levels[cbuf->base.u.tex.level]);
166 }
167
168 assert((res->layout & ETNA_LAYOUT_BIT_TILE) ||
169 VIV_FEATURE(screen, ETNA_FEATURE_LINEAR_PE));
170 etna_update_render_surface(pctx, cbuf);
171
172 if (res->layout == ETNA_LAYOUT_LINEAR)
173 target_linear = true;
174
175 if (util_format_get_blocksize(cbuf->base.format) <= 2)
176 target_16bpp = true;
177
178 if (rt == 0) {
179 if (fmt >= PE_FORMAT_R16F)
180 cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT_EXT(fmt) |
181 VIVS_PE_COLOR_FORMAT_FORMAT_MASK;
182 else
183 cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(fmt);
184
185 cs->PE_COLOR_FORMAT |=
186 VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK |
187 COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED);
188
189 nr_samples_color = cbuf->base.texture->nr_samples;
190 if (nr_samples_color <= 1)
191 cs->PE_COLOR_FORMAT |= VIVS_PE_COLOR_FORMAT_OVERWRITE;
192
193 if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
194 cs->PE_COLOR_FORMAT |= COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW);
195 /* VIVS_PE_COLOR_FORMAT_COMPONENTS() and
196 * VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state
197 * but only if we set the bits above. */
198 /* merged with depth_stencil_alpha */
199 if ((cbuf->offset & 63) ||
200 (((cbuf->level->stride * 4) & 63) && cbuf->level->height > 4)) {
201 /* XXX Must make temporary surface here.
202 * Need the same mechanism on gc2000 when we want to do mipmap
203 * generation by
204 * rendering to levels > 1 due to multitiled / tiled conversion. */
205 BUG("Alignment error, trying to render to offset %08x with tile "
206 "stride %i",
207 cbuf->offset, cbuf->level->stride * 4);
208 }
209
210 if (screen->info->halti >= 0 && screen->info->model != 0x880) {
211 /* Rendertargets on GPUs with more than a single pixel pipe must always
212 * be multi-tiled, or single-buffer mode must be supported */
213 assert(screen->specs.pixel_pipes == 1 ||
214 (res->layout & ETNA_LAYOUT_BIT_MULTI) || screen->specs.single_buffer);
215 for (int i = 0; i < screen->specs.pixel_pipes; i++) {
216 cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i];
217 cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
218 }
219 } else {
220 cs->PE_COLOR_ADDR = cbuf->reloc[0];
221 cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
222 }
223
224 cs->PE_COLOR_STRIDE = cbuf->level->stride;
225
226 if (cbuf->level->ts_size) {
227 cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value;
228 cs->TS_COLOR_CLEAR_VALUE_EXT = cbuf->level->clear_value >> 32;
229
230 cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc;
231 cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
232
233 cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0];
234 cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
235
236 pe_mem_config |= VIVS_PE_MEM_CONFIG_COLOR_TS_MODE(cbuf->level->ts_mode);
237
238 if (cbuf->level->ts_compress_fmt >= 0) {
239 /* overwrite bit breaks v1/v2 compression */
240 if (!screen->specs.v4_compression)
241 cs->PE_COLOR_FORMAT &= ~VIVS_PE_COLOR_FORMAT_OVERWRITE;
242
243 ts_mem_config |=
244 VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION |
245 VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt);
246 }
247 }
248
249 if (util_format_is_srgb(cbuf->base.format))
250 pe_logic_op |= VIVS_PE_LOGIC_OP_SRGB;
251 } else {
252 cs->PE_RT_PIPE_COLOR_ADDR[rt - 1][0] = cbuf->reloc[0];
253 cs->PE_RT_PIPE_COLOR_ADDR[rt - 1][1] = cbuf->reloc[1];
254 cs->PE_RT_CONFIG[rt - 1] =
255 RT_CONFIG_STRIDE(cbuf->level->stride) |
256 RT_CONFIG_FORMAT(fmt) |
257 COND(color_supertiled, RT_CONFIG_SUPER_TILED);
258
259 if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
260 cs->PE_RT_CONFIG[rt - 1] |= COND(color_supertiled, RT_CONFIG_SUPER_TILED_NEW);
261
262 if (cbuf->level->ts_size) {
263 cs->RT_TS_MEM_CONFIG[rt - 1] =
264 COND(cbuf->level->ts_compress_fmt >= 0, VIVS_TS_RT_CONFIG_COMPRESSION) |
265 COND(cbuf->level->ts_compress_fmt >= 0, VIVS_TS_RT_CONFIG_COMPRESSION_FORMAT(cbuf->level->ts_compress_fmt));
266
267 cs->RT_TS_COLOR_CLEAR_VALUE[rt - 1] = cbuf->level->clear_value;
268 cs->RT_TS_COLOR_CLEAR_VALUE_EXT[rt - 1] = cbuf->level->clear_value >> 32;
269
270 cs->RT_TS_COLOR_STATUS_BASE[rt - 1] = cbuf->ts_reloc;
271 cs->RT_TS_COLOR_STATUS_BASE[rt - 1].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
272
273 cs->RT_TS_COLOR_SURFACE_BASE[rt - 1] = cbuf->reloc[0];
274 cs->RT_TS_COLOR_SURFACE_BASE[rt - 1].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
275 } else {
276 if (VIV_FEATURE(screen, ETNA_FEATURE_CACHE128B256BPERLINE))
277 cs->PE_RT_CONFIG[rt - 1] |= RT_CONFIG_UNK27;
278 }
279 }
280
281 static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 0) == VIVS_PS_CONTROL_SATURATE_RT0, "VIVS_PS_CONTROL_SATURATE_RT0");
282 static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 1) == VIVS_PS_CONTROL_SATURATE_RT1, "VIVS_PS_CONTROL_SATURATE_RT1");
283 static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 2) == VIVS_PS_CONTROL_SATURATE_RT2, "VIVS_PS_CONTROL_SATURATE_RT2");
284 static_assert((VIVS_PS_CONTROL_SATURATE_RT0 << 3) == VIVS_PS_CONTROL_SATURATE_RT3, "VIVS_PS_CONTROL_SATURATE_RT3");
285
286 static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 0) == VIVS_PS_OUTPUT_REG2_SATURATE_RT4, "VIVS_PS_OUTPUT_REG2_SATURATE_RT4");
287 static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 8) == VIVS_PS_OUTPUT_REG2_SATURATE_RT5, "VIVS_PS_OUTPUT_REG2_SATURATE_RT5");
288 static_assert((VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 16) == VIVS_PS_OUTPUT_REG2_SATURATE_RT6, "VIVS_PS_OUTPUT_REG2_SATURATE_RT6");
289 static_assert(((uint32_t)VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << 24) == VIVS_PS_OUTPUT_REG2_SATURATE_RT7, "VIVS_PS_OUTPUT_REG2_SATURATE_RT7");
290
291 if (rt < 4)
292 cs->PS_CONTROL |= COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_CONTROL_SATURATE_RT0 << rt);
293 else
294 cs->PS_OUTPUT_REG2 |= COND(util_format_is_unorm(cbuf->base.format), VIVS_PS_OUTPUT_REG2_SATURATE_RT4 << (8 * (rt - 4)));
295
296 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 4) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE1__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE1__MASK");
297 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 8) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE2__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE2__MASK");
298 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 12) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE3__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE3__MASK");
299 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 16) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE4__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE4__MASK");
300 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 20) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE5__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE5__MASK");
301 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 24) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE6__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE6__MASK");
302 static_assert((VIVS_PS_CONTROL_EXT_OUTPUT_MODE0__MASK << 28) == VIVS_PS_CONTROL_EXT_OUTPUT_MODE7__MASK, "VIVS_PS_CONTROL_EXT_OUTPUT_MODE7__MASK");
303
304 cs->PS_CONTROL_EXT |=
305 translate_output_mode(cbuf->base.format, screen->info->halti >= 5) << (4 * rt);
306
307 /* When there are null render targets we need to modify the fragment
308 * shader output mapping.
309 */
310 assert(rt < ARRAY_SIZE(cs->ps_output_remap));
311 cs->ps_output_remap[rt] = i;
312
313 rt++;
314 }
315
316 cs->num_rt = rt;
317
318 if (rt)
319 cs->PS_CONTROL |= VIVS_PS_CONTROL_RT_COUNT(rt - 1);
320
321 /*
322 * Disable the main render target if needed. The extra render targets are implicitly
323 * disabled by using VIVS_PS_CONTROL_RT_COUNT(0).
324 */
325 if (fb->nr_cbufs == 0) {
326 /* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and
327 * VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the
328 * color target */
329 cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_OVERWRITE;
330 cs->PE_COLOR_STRIDE = 0;
331 cs->TS_COLOR_STATUS_BASE.bo = NULL;
332 cs->TS_COLOR_SURFACE_BASE.bo = NULL;
333
334 cs->PE_COLOR_ADDR = screen->dummy_rt_reloc;
335 for (int i = 0; i < screen->specs.pixel_pipes; i++)
336 cs->PE_PIPE_COLOR_ADDR[i] = screen->dummy_rt_reloc;
337 }
338
339 if (fb->zsbuf != NULL) {
340 struct etna_surface *zsbuf = etna_surface(fb->zsbuf);
341 struct etna_resource *res = etna_resource(zsbuf->base.texture);
342
343 etna_update_render_surface(pctx, zsbuf);
344
345 assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */
346
347 uint32_t depth_format = translate_depth_format(zsbuf->base.format);
348 unsigned depth_bits =
349 depth_format == VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24;
350 bool depth_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0;
351
352 if (depth_bits == 16)
353 target_16bpp = true;
354
355 cs->depth_mrd = util_get_depth_format_mrd(util_format_description(zsbuf->base.format));
356
357 cs->PE_DEPTH_CONFIG =
358 depth_format |
359 COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) |
360 VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z |
361 VIVS_PE_DEPTH_CONFIG_UNK18; /* something to do with clipping? */
362 /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */
363 /* merged with depth_stencil_alpha */
364
365 if (screen->info->halti >= 0 && screen->info->model != 0x880) {
366 for (int i = 0; i < screen->specs.pixel_pipes; i++) {
367 cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i];
368 cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
369 }
370 } else {
371 cs->PE_DEPTH_ADDR = zsbuf->reloc[0];
372 cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
373 }
374
375 cs->PE_DEPTH_STRIDE = zsbuf->level->stride;
376 cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED;
377 cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f);
378
379 if (zsbuf->level->ts_size) {
380 cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value;
381
382 cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc;
383 cs->TS_DEPTH_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
384
385 cs->TS_DEPTH_SURFACE_BASE = zsbuf->reloc[0];
386 cs->TS_DEPTH_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
387
388 pe_mem_config |= VIVS_PE_MEM_CONFIG_DEPTH_TS_MODE(zsbuf->level->ts_mode);
389
390 if (zsbuf->level->ts_compress_fmt >= 0) {
391 ts_mem_config |=
392 VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION |
393 COND(zsbuf->level->ts_compress_fmt == COMPRESSION_FORMAT_D24S8,
394 VIVS_TS_MEM_CONFIG_STENCIL_ENABLE);
395 }
396 }
397
398 ts_mem_config |= COND(depth_bits == 16, VIVS_TS_MEM_CONFIG_DEPTH_16BPP);
399
400 nr_samples_depth = zsbuf->base.texture->nr_samples;
401 } else {
402 cs->depth_mrd = 0.0f;
403 cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE;
404 cs->PE_DEPTH_ADDR.bo = NULL;
405 cs->PE_DEPTH_STRIDE = 0;
406 cs->TS_DEPTH_STATUS_BASE.bo = NULL;
407 cs->TS_DEPTH_SURFACE_BASE.bo = NULL;
408
409 for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++)
410 cs->PE_PIPE_DEPTH_ADDR[i].bo = NULL;
411 }
412
413 /* MSAA setup */
414 if (nr_samples_depth != -1 && nr_samples_color != -1 &&
415 nr_samples_depth != nr_samples_color) {
416 BUG("Number of samples in color and depth texture must match (%i and %i respectively)",
417 nr_samples_color, nr_samples_depth);
418 }
419
420 switch (MAX2(nr_samples_depth, nr_samples_color)) {
421 case 0:
422 case 1: /* Are 0 and 1 samples allowed? */
423 cs->GL_MULTI_SAMPLE_CONFIG =
424 VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
425 cs->msaa_mode = false;
426 break;
427 case 2:
428 cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X;
429 cs->msaa_mode = true; /* Add input to PS */
430 cs->RA_MULTISAMPLE_UNK00E04 = 0x0;
431 cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22;
432 cs->RA_CENTROID_TABLE[0] = 0x66aa2288;
433 cs->RA_CENTROID_TABLE[1] = 0x88558800;
434 cs->RA_CENTROID_TABLE[2] = 0x88881100;
435 cs->RA_CENTROID_TABLE[3] = 0x33888800;
436 break;
437 case 4:
438 cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X;
439 cs->msaa_mode = true; /* Add input to PS */
440 cs->RA_MULTISAMPLE_UNK00E04 = 0x0;
441 cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26;
442 cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a;
443 cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22;
444 cs->RA_CENTROID_TABLE[0] = 0x4a6e2688;
445 cs->RA_CENTROID_TABLE[1] = 0x888888a2;
446 cs->RA_CENTROID_TABLE[2] = 0x888888ea;
447 cs->RA_CENTROID_TABLE[3] = 0x888888c6;
448 cs->RA_CENTROID_TABLE[4] = 0x46622a88;
449 cs->RA_CENTROID_TABLE[5] = 0x888888ae;
450 cs->RA_CENTROID_TABLE[6] = 0x888888e6;
451 cs->RA_CENTROID_TABLE[7] = 0x888888ca;
452 cs->RA_CENTROID_TABLE[8] = 0x262a2288;
453 cs->RA_CENTROID_TABLE[9] = 0x886688a2;
454 cs->RA_CENTROID_TABLE[10] = 0x888866aa;
455 cs->RA_CENTROID_TABLE[11] = 0x668888a6;
456 if (VIV_FEATURE(screen, ETNA_FEATURE_SMALL_MSAA))
457 pe_logic_op |= VIVS_PE_LOGIC_OP_UNK24(0x5);
458 break;
459 }
460
461 cs->TS_MEM_CONFIG = ts_mem_config;
462 cs->PE_MEM_CONFIG = pe_mem_config;
463
464 /* Single buffer setup. There is only one switch for this, not a separate
465 * one per color buffer / depth buffer. To keep the logic simple always use
466 * single buffer when this feature is available.
467 */
468 if (unlikely(target_linear))
469 pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(1);
470 else if (screen->specs.single_buffer)
471 pe_logic_op |= VIVS_PE_LOGIC_OP_SINGLE_BUFFER(target_16bpp ? 3 : 2);
472 cs->PE_LOGIC_OP = pe_logic_op;
473
474 /* keep copy of original structure */
475 util_copy_framebuffer_state(&ctx->framebuffer_s, fb);
476 ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS;
477 }
478
479 static void
etna_set_polygon_stipple(struct pipe_context * pctx,const struct pipe_poly_stipple * stipple)480 etna_set_polygon_stipple(struct pipe_context *pctx,
481 const struct pipe_poly_stipple *stipple)
482 {
483 /* NOP */
484 }
485
486 static void
etna_set_scissor_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * ss)487 etna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot,
488 unsigned num_scissors, const struct pipe_scissor_state *ss)
489 {
490 struct etna_context *ctx = etna_context(pctx);
491 assert(ss->minx <= ss->maxx);
492 assert(ss->miny <= ss->maxy);
493
494 ctx->scissor = *ss;
495 ctx->dirty |= ETNA_DIRTY_SCISSOR;
496 }
497
498 static void
etna_set_viewport_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_viewport_state * vs)499 etna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot,
500 unsigned num_scissors, const struct pipe_viewport_state *vs)
501 {
502 struct etna_context *ctx = etna_context(pctx);
503 struct compiled_viewport_state *cs = &ctx->viewport;
504
505 ctx->viewport_s = *vs;
506 /**
507 * For Vivante GPU, viewport z transformation is 0..1 to 0..1 instead of
508 * -1..1 to 0..1.
509 * scaling and translation to 0..1 already happened, so remove that
510 *
511 * z' = (z * 2 - 1) * scale + translate
512 * = z * (2 * scale) + (translate - scale)
513 *
514 * scale' = 2 * scale
515 * translate' = translate - scale
516 */
517
518 /* must be fixp as v4 state deltas assume it is */
519 cs->PA_VIEWPORT_SCALE_X = etna_f32_to_fixp16(vs->scale[0]);
520 cs->PA_VIEWPORT_SCALE_Y = etna_f32_to_fixp16(vs->scale[1]);
521 cs->PA_VIEWPORT_SCALE_Z = fui(vs->scale[2] * 2.0f);
522 cs->PA_VIEWPORT_OFFSET_X = etna_f32_to_fixp16(vs->translate[0]);
523 cs->PA_VIEWPORT_OFFSET_Y = etna_f32_to_fixp16(vs->translate[1]);
524 cs->PA_VIEWPORT_OFFSET_Z = fui(vs->translate[2] - vs->scale[2]);
525
526 /* Compute scissor rectangle (fixp) from viewport.
527 * Make sure left is always < right and top always < bottom.
528 */
529 cs->SE_SCISSOR_LEFT = MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f);
530 cs->SE_SCISSOR_TOP = MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f);
531 cs->SE_SCISSOR_RIGHT = ceilf(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f));
532 cs->SE_SCISSOR_BOTTOM = ceilf(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f));
533
534 cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */
535 cs->PE_DEPTH_FAR = fui(1.0);
536 ctx->dirty |= ETNA_DIRTY_VIEWPORT;
537 }
538
539 static void
etna_set_vertex_buffers(struct pipe_context * pctx,unsigned num_buffers,const struct pipe_vertex_buffer * vb)540 etna_set_vertex_buffers(struct pipe_context *pctx, unsigned num_buffers,
541 const struct pipe_vertex_buffer *vb)
542 {
543 struct etna_context *ctx = etna_context(pctx);
544 struct etna_vertexbuf_state *so = &ctx->vertex_buffer;
545
546 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, num_buffers,
547 true);
548 so->count = util_last_bit(so->enabled_mask);
549
550 if (!num_buffers) {
551 so->count = 1;
552 so->cvb[0].FE_VERTEX_STREAM_BASE_ADDR.bo = ctx->screen->dummy_bo;
553 so->cvb[0].FE_VERTEX_STREAM_BASE_ADDR.offset = 0;
554 so->cvb[0].FE_VERTEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ;
555 }
556
557 for (unsigned idx = 0; idx < num_buffers; ++idx) {
558 struct compiled_set_vertex_buffer *cs = &so->cvb[idx];
559 struct pipe_vertex_buffer *vbi = &so->vb[idx];
560
561 assert(!vbi->is_user_buffer); /* XXX support user_buffer using
562 etna_usermem_map */
563
564 if (vbi->buffer.resource) { /* GPU buffer */
565 cs->FE_VERTEX_STREAM_BASE_ADDR.bo = etna_resource(vbi->buffer.resource)->bo;
566 cs->FE_VERTEX_STREAM_BASE_ADDR.offset = vbi->buffer_offset;
567 cs->FE_VERTEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ;
568 } else {
569 cs->FE_VERTEX_STREAM_BASE_ADDR.bo = NULL;
570 }
571 }
572
573 ctx->dirty |= ETNA_DIRTY_VERTEX_BUFFERS;
574 }
575
576 static void
etna_blend_state_bind(struct pipe_context * pctx,void * bs)577 etna_blend_state_bind(struct pipe_context *pctx, void *bs)
578 {
579 struct etna_context *ctx = etna_context(pctx);
580
581 ctx->blend = bs;
582 ctx->dirty |= ETNA_DIRTY_BLEND;
583 }
584
585 static void
etna_blend_state_delete(struct pipe_context * pctx,void * bs)586 etna_blend_state_delete(struct pipe_context *pctx, void *bs)
587 {
588 FREE(bs);
589 }
590
591 static void
etna_rasterizer_state_bind(struct pipe_context * pctx,void * rs)592 etna_rasterizer_state_bind(struct pipe_context *pctx, void *rs)
593 {
594 struct etna_context *ctx = etna_context(pctx);
595
596 ctx->rasterizer = rs;
597 ctx->dirty |= ETNA_DIRTY_RASTERIZER;
598 }
599
600 static void
etna_rasterizer_state_delete(struct pipe_context * pctx,void * rs)601 etna_rasterizer_state_delete(struct pipe_context *pctx, void *rs)
602 {
603 FREE(rs);
604 }
605
606 static void
etna_zsa_state_bind(struct pipe_context * pctx,void * zs)607 etna_zsa_state_bind(struct pipe_context *pctx, void *zs)
608 {
609 struct etna_context *ctx = etna_context(pctx);
610
611 ctx->zsa = zs;
612 ctx->dirty |= ETNA_DIRTY_ZSA;
613 }
614
615 static void
etna_zsa_state_delete(struct pipe_context * pctx,void * zs)616 etna_zsa_state_delete(struct pipe_context *pctx, void *zs)
617 {
618 FREE(zs);
619 }
620
621 /** Create vertex element states, which define a layout for fetching
622 * vertices for rendering.
623 */
624 static void *
etna_vertex_elements_state_create(struct pipe_context * pctx,unsigned num_elements,const struct pipe_vertex_element * elements)625 etna_vertex_elements_state_create(struct pipe_context *pctx,
626 unsigned num_elements, const struct pipe_vertex_element *elements)
627 {
628 struct etna_context *ctx = etna_context(pctx);
629 struct etna_screen *screen = ctx->screen;
630 struct compiled_vertex_elements_state *cs = CALLOC_STRUCT(compiled_vertex_elements_state);
631
632 if (!cs)
633 return NULL;
634
635 if (num_elements > screen->specs.vertex_max_elements) {
636 BUG("number of elements (%u) exceeds chip maximum (%u)", num_elements,
637 screen->specs.vertex_max_elements);
638 FREE(cs);
639 return NULL;
640 }
641
642 /* XXX could minimize number of consecutive stretches here by sorting, and
643 * permuting the inputs in shader or does Mesa do this already? */
644
645 if (!num_elements) {
646 /* There's no way to disable all elements on the hardware, so we need to
647 * plug in a dummy element and vertex buffer (stride = 0, so only fetches
648 * first location). */
649 static const struct pipe_vertex_element dummy_element = {
650 .src_format = PIPE_FORMAT_R8G8B8A8_UNORM,
651 };
652
653 elements = &dummy_element;
654 num_elements = 1;
655 }
656
657 cs->num_elements = num_elements;
658
659 unsigned start_offset = 0; /* start of current consecutive stretch */
660 bool nonconsecutive = true; /* previous value of nonconsecutive */
661 uint32_t buffer_mask = 0; /* mask of buffer_idx already seen */
662
663 for (unsigned idx = 0; idx < num_elements; ++idx) {
664 unsigned buffer_idx = elements[idx].vertex_buffer_index;
665 unsigned element_size = util_format_get_blocksize(elements[idx].src_format);
666 unsigned end_offset = elements[idx].src_offset + element_size;
667 uint32_t format_type, normalize;
668
669 if (nonconsecutive)
670 start_offset = elements[idx].src_offset;
671
672 /* guaranteed by pipe_caps.max_vertex_buffers */
673 assert(buffer_idx < screen->info->gpu.stream_count);
674
675 /* maximum vertex size is 256 bytes */
676 assert(element_size != 0 && (end_offset - start_offset) < 256);
677
678 /* check whether next element is consecutive to this one */
679 nonconsecutive = (idx == (num_elements - 1)) ||
680 elements[idx + 1].vertex_buffer_index != buffer_idx ||
681 end_offset != elements[idx + 1].src_offset;
682
683 format_type = translate_vertex_format_type(elements[idx].src_format);
684 normalize = translate_vertex_format_normalize(elements[idx].src_format);
685
686 assert(format_type != ETNA_NO_MATCH);
687 assert(normalize != ETNA_NO_MATCH);
688
689 if (screen->info->halti < 5) {
690 cs->FE_VERTEX_ELEMENT_CONFIG[idx] =
691 COND(nonconsecutive, VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE) |
692 format_type |
693 VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(util_format_get_nr_components(elements[idx].src_format)) |
694 normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) |
695 VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(buffer_idx) |
696 VIVS_FE_VERTEX_ELEMENT_CONFIG_START(elements[idx].src_offset) |
697 VIVS_FE_VERTEX_ELEMENT_CONFIG_END(end_offset - start_offset);
698 } else { /* HALTI5 spread vertex attrib config over two registers */
699 cs->NFE_GENERIC_ATTRIB_CONFIG0[idx] =
700 format_type |
701 VIVS_NFE_GENERIC_ATTRIB_CONFIG0_NUM(util_format_get_nr_components(elements[idx].src_format)) |
702 normalize | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_ENDIAN(ENDIAN_MODE_NO_SWAP) |
703 VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM(buffer_idx) |
704 VIVS_NFE_GENERIC_ATTRIB_CONFIG0_START(elements[idx].src_offset);
705 cs->NFE_GENERIC_ATTRIB_CONFIG1[idx] =
706 COND(nonconsecutive, VIVS_NFE_GENERIC_ATTRIB_CONFIG1_NONCONSECUTIVE) |
707 VIVS_NFE_GENERIC_ATTRIB_CONFIG1_END(end_offset - start_offset);
708 }
709 cs->FE_VERTEX_STREAM_CONTROL[buffer_idx] =
710 FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(elements[idx].src_stride);
711
712 if (util_format_is_pure_integer(elements[idx].src_format))
713 cs->NFE_GENERIC_ATTRIB_SCALE[idx] = 1;
714 else
715 cs->NFE_GENERIC_ATTRIB_SCALE[idx] = fui(1.0f);
716
717 /* instance_divisor is part of elements state but should be the same for all buffers */
718 if (buffer_mask & 1 << buffer_idx)
719 assert(cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] == elements[idx].instance_divisor);
720 else
721 cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] = elements[idx].instance_divisor;
722
723 buffer_mask |= 1 << buffer_idx;
724 cs->num_buffers = MAX2(cs->num_buffers, buffer_idx + 1);
725 }
726
727 return cs;
728 }
729
730 static void
etna_vertex_elements_state_delete(struct pipe_context * pctx,void * ve)731 etna_vertex_elements_state_delete(struct pipe_context *pctx, void *ve)
732 {
733 FREE(ve);
734 }
735
736 static void
etna_vertex_elements_state_bind(struct pipe_context * pctx,void * ve)737 etna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve)
738 {
739 struct etna_context *ctx = etna_context(pctx);
740
741 ctx->vertex_elements = ve;
742 ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS;
743 }
744
745 static void
etna_set_stream_output_targets(struct pipe_context * pctx,unsigned num_targets,struct pipe_stream_output_target ** targets,const unsigned * offsets,enum mesa_prim output_prim)746 etna_set_stream_output_targets(struct pipe_context *pctx,
747 unsigned num_targets, struct pipe_stream_output_target **targets,
748 const unsigned *offsets,
749 enum mesa_prim output_prim)
750 {
751 /* stub */
752 }
753
754 static bool
etna_update_ts_config(struct etna_context * ctx)755 etna_update_ts_config(struct etna_context *ctx)
756 {
757 const struct pipe_framebuffer_state *fb = &ctx->framebuffer_s;
758 bool dirty = ctx->dirty & ETNA_DIRTY_FRAMEBUFFER;
759 unsigned rt = 0;
760
761 for (unsigned i = 0; i < fb->nr_cbufs; i++) {
762 uint32_t ts_config;
763
764 if (!fb->cbufs[i])
765 continue;
766
767 /* Read the current ts config value for the render target. */
768 if (rt == 0)
769 ts_config = ctx->framebuffer.TS_MEM_CONFIG;
770 else
771 ts_config = ctx->framebuffer.RT_TS_MEM_CONFIG[rt - 1];
772
773 /* Update the ts config for color fast clear. */
774 struct etna_surface *c_surf = etna_surface(fb->cbufs[i]);
775 if (etna_resource_level_ts_valid(c_surf->level)) {
776 if (rt == 0)
777 ts_config |= VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR;
778 else
779 ts_config |= VIVS_TS_RT_CONFIG_ENABLE;
780 } else {
781 if (rt == 0)
782 ts_config &= ~VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR;
783 else
784 ts_config &= ~VIVS_TS_RT_CONFIG_ENABLE;
785 }
786
787 /* Update dirty state and if needed store the new ts config value. */
788 if (rt == 0)
789 dirty |= ctx->framebuffer.TS_MEM_CONFIG != ts_config;
790 else
791 dirty |= ctx->framebuffer.RT_TS_MEM_CONFIG[rt] != ts_config;
792
793 if (dirty) {
794 if (rt == 0)
795 ctx->framebuffer.TS_MEM_CONFIG = ts_config;
796 else
797 ctx->framebuffer.RT_TS_MEM_CONFIG[rt - 1] = ts_config;
798 }
799
800 rt++;
801 }
802
803 /* Update the ts config for depth fast clear. */
804 if (ctx->framebuffer_s.zsbuf) {
805 struct etna_surface *zs_surf = etna_surface(ctx->framebuffer_s.zsbuf);
806 uint32_t ts_config = ctx->framebuffer.TS_MEM_CONFIG;
807
808 if (etna_resource_level_ts_valid(zs_surf->level))
809 ts_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR;
810 else
811 ts_config &= ~VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR;
812
813 dirty |= ctx->framebuffer.TS_MEM_CONFIG != ts_config;
814
815 if (dirty)
816 ctx->framebuffer.TS_MEM_CONFIG = ts_config;
817 }
818
819 if (dirty)
820 ctx->dirty |= ETNA_DIRTY_TS;
821
822 ctx->dirty &= ~ETNA_DIRTY_DERIVE_TS;
823
824 return true;
825 }
826
827 static bool
etna_update_clipping(struct etna_context * ctx)828 etna_update_clipping(struct etna_context *ctx)
829 {
830 const struct etna_rasterizer_state *rasterizer = etna_rasterizer_state(ctx->rasterizer);
831 const struct pipe_framebuffer_state *fb = &ctx->framebuffer_s;
832
833 /* clip framebuffer against viewport */
834 uint32_t scissor_left = ctx->viewport.SE_SCISSOR_LEFT;
835 uint32_t scissor_top = ctx->viewport.SE_SCISSOR_TOP;
836 uint32_t scissor_right = MIN2(fb->width, ctx->viewport.SE_SCISSOR_RIGHT);
837 uint32_t scissor_bottom = MIN2(fb->height, ctx->viewport.SE_SCISSOR_BOTTOM);
838
839 /* clip against scissor */
840 if (rasterizer->scissor) {
841 scissor_left = MAX2(ctx->scissor.minx, scissor_left);
842 scissor_top = MAX2(ctx->scissor.miny, scissor_top);
843 scissor_right = MIN2(ctx->scissor.maxx, scissor_right);
844 scissor_bottom = MIN2(ctx->scissor.maxy, scissor_bottom);
845 }
846
847 ctx->clipping.minx = scissor_left;
848 ctx->clipping.miny = scissor_top;
849 ctx->clipping.maxx = scissor_right;
850 ctx->clipping.maxy = scissor_bottom;
851
852 ctx->dirty |= ETNA_DIRTY_SCISSOR_CLIP;
853
854 return true;
855 }
856
857 static bool
etna_update_zsa(struct etna_context * ctx)858 etna_update_zsa(struct etna_context *ctx)
859 {
860 struct pipe_framebuffer_state *fb = &ctx->framebuffer_s;
861 struct compiled_shader_state *shader_state = &ctx->shader_state;
862 struct pipe_depth_stencil_alpha_state *zsa_state = ctx->zsa;
863 struct etna_zsa_state *zsa = etna_zsa_state(zsa_state);
864 struct etna_screen *screen = ctx->screen;
865 uint32_t new_pe_depth, new_ra_depth;
866 bool early_z_allowed = !VIV_FEATURE(screen, ETNA_FEATURE_NO_EARLY_Z);
867 bool late_zs = false, early_zs = false,
868 late_z_test = false, early_z_test = false;
869
870 /* Linear PE breaks the combination of early test with late write, as it
871 * seems RA and PE disagree about the buffer layout in this mode. Fall back
872 * to late Z always even though early Z write might be possible, as we don't
873 * know if any other draws to the same surface require late Z write.
874 */
875 for (unsigned i = 0; i < fb->nr_cbufs; i++) {
876 if (!fb->cbufs[i])
877 continue;
878
879 struct etna_surface *cbuf = etna_surface(fb->cbufs[i]);
880 struct etna_resource *res = etna_resource(cbuf->base.texture);
881
882 if (res->layout == ETNA_LAYOUT_LINEAR)
883 early_z_allowed = false;
884
885 /* Stop after the first render target. */
886 break;
887 }
888
889 if (zsa->z_write_enabled || zsa->stencil_enabled) {
890 if (VIV_FEATURE(screen, ETNA_FEATURE_RA_WRITE_DEPTH) &&
891 early_z_allowed &&
892 !zsa_state->alpha_enabled &&
893 !shader_state->writes_z &&
894 !shader_state->uses_discard)
895 early_zs = true;
896 else
897 late_zs = true;
898 }
899
900 if (zsa->z_test_enabled) {
901 if (early_z_allowed &&
902 (!zsa->stencil_modified || early_zs) &&
903 !shader_state->writes_z)
904 early_z_test = true;
905 else
906 late_z_test = true;
907 }
908
909 new_pe_depth = VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(zsa->z_test_enabled ?
910 /* compare funcs have 1 to 1 mapping */
911 zsa_state->depth_func : PIPE_FUNC_ALWAYS) |
912 COND(zsa->z_write_enabled, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) |
913 COND(early_z_test, VIVS_PE_DEPTH_CONFIG_EARLY_Z) |
914 COND(!late_zs && !late_z_test,
915 VIVS_PE_DEPTH_CONFIG_DISABLE_ZS);
916
917 /* blob sets this to 0x40000031 on GC7000, seems to make no difference,
918 * but keep it in mind if depth behaves strangely. */
919 new_ra_depth = 0x0000030 |
920 COND(early_z_test, VIVS_RA_EARLY_DEPTH_TEST_ENABLE);
921
922 if (VIV_FEATURE(screen, ETNA_FEATURE_RA_WRITE_DEPTH)) {
923 if (!early_zs)
924 new_ra_depth |= VIVS_RA_EARLY_DEPTH_WRITE_DISABLE;
925 /* The new early hierarchical test seems to only work properly if depth
926 * is also written from the early stage.
927 */
928 if (late_z_test || (early_z_test && late_zs))
929 new_ra_depth |= VIVS_RA_EARLY_DEPTH_HDEPTH_DISABLE;
930
931 for (unsigned i = 0; i < fb->nr_cbufs; i++) {
932 if (!fb->cbufs[i])
933 continue;
934
935 struct pipe_resource *res = fb->cbufs[i]->texture;
936
937 if ((late_z_test || late_zs) && res->nr_samples > 1)
938 new_ra_depth |= VIVS_RA_EARLY_DEPTH_LATE_DEPTH_MSAA;
939
940 /* Stop after the first render target. */
941 break;
942 }
943 }
944
945 if (new_pe_depth != zsa->PE_DEPTH_CONFIG ||
946 new_ra_depth != zsa->RA_DEPTH_CONFIG)
947 ctx->dirty |= ETNA_DIRTY_ZSA;
948
949 zsa->PE_DEPTH_CONFIG = new_pe_depth;
950 zsa->RA_DEPTH_CONFIG = new_ra_depth;
951
952 return true;
953 }
954
955 static bool
etna_record_flush_resources(struct etna_context * ctx)956 etna_record_flush_resources(struct etna_context *ctx)
957 {
958 struct pipe_framebuffer_state *fb = &ctx->framebuffer_s;
959
960 for (unsigned i = 0; i < fb->nr_cbufs; i++) {
961 if (!fb->cbufs[i])
962 continue;
963
964 struct etna_surface *surf = etna_surface(fb->cbufs[i]);
965 struct etna_resource *rsc = etna_resource(surf->prsc);
966
967 if (rsc->shared && !rsc->explicit_flush)
968 etna_context_add_flush_resource(ctx, surf->prsc);
969 }
970
971 return true;
972 }
973
974 struct etna_state_updater {
975 bool (*update)(struct etna_context *ctx);
976 uint32_t dirty;
977 };
978
979 static const struct etna_state_updater etna_state_updates[] = {
980 {
981 etna_shader_update_vertex, ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS,
982 },
983 {
984 etna_shader_link, ETNA_DIRTY_SHADER | ETNA_DIRTY_FRAMEBUFFER,
985 },
986 {
987 etna_update_blend, ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER
988 },
989 {
990 etna_update_blend_color, ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER,
991 },
992 {
993 etna_update_ts_config, ETNA_DIRTY_DERIVE_TS,
994 },
995 {
996 etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
997 ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT,
998 },
999 {
1000 etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER |
1001 ETNA_DIRTY_FRAMEBUFFER,
1002 },
1003 {
1004 etna_record_flush_resources, ETNA_DIRTY_FRAMEBUFFER,
1005 }
1006 };
1007
1008 bool
etna_state_update(struct etna_context * ctx)1009 etna_state_update(struct etna_context *ctx)
1010 {
1011 for (unsigned int i = 0; i < ARRAY_SIZE(etna_state_updates); i++)
1012 if (ctx->dirty & etna_state_updates[i].dirty)
1013 if (!etna_state_updates[i].update(ctx))
1014 return false;
1015
1016 return true;
1017 }
1018
1019 void
etna_state_init(struct pipe_context * pctx)1020 etna_state_init(struct pipe_context *pctx)
1021 {
1022 pctx->set_blend_color = etna_set_blend_color;
1023 pctx->set_stencil_ref = etna_set_stencil_ref;
1024 pctx->set_clip_state = etna_set_clip_state;
1025 pctx->set_sample_mask = etna_set_sample_mask;
1026 pctx->set_constant_buffer = etna_set_constant_buffer;
1027 pctx->set_framebuffer_state = etna_set_framebuffer_state;
1028 pctx->set_polygon_stipple = etna_set_polygon_stipple;
1029 pctx->set_scissor_states = etna_set_scissor_states;
1030 pctx->set_viewport_states = etna_set_viewport_states;
1031
1032 pctx->set_vertex_buffers = etna_set_vertex_buffers;
1033
1034 pctx->bind_blend_state = etna_blend_state_bind;
1035 pctx->delete_blend_state = etna_blend_state_delete;
1036
1037 pctx->bind_rasterizer_state = etna_rasterizer_state_bind;
1038 pctx->delete_rasterizer_state = etna_rasterizer_state_delete;
1039
1040 pctx->bind_depth_stencil_alpha_state = etna_zsa_state_bind;
1041 pctx->delete_depth_stencil_alpha_state = etna_zsa_state_delete;
1042
1043 pctx->create_vertex_elements_state = etna_vertex_elements_state_create;
1044 pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete;
1045 pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind;
1046
1047 pctx->set_stream_output_targets = etna_set_stream_output_targets;
1048 }
1049