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 "hw/common.xml.h"
31 
32 #include "etnaviv_blend.h"
33 #include "etnaviv_clear_blit.h"
34 #include "etnaviv_context.h"
35 #include "etnaviv_format.h"
36 #include "etnaviv_shader.h"
37 #include "etnaviv_surface.h"
38 #include "etnaviv_translate.h"
39 #include "etnaviv_util.h"
40 #include "util/u_helpers.h"
41 #include "util/u_inlines.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44 
45 static void
etna_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref * sr)46 etna_set_stencil_ref(struct pipe_context *pctx, const struct pipe_stencil_ref *sr)
47 {
48    struct etna_context *ctx = etna_context(pctx);
49    struct compiled_stencil_ref *cs = &ctx->stencil_ref;
50 
51    ctx->stencil_ref_s = *sr;
52 
53    cs->PE_STENCIL_CONFIG = VIVS_PE_STENCIL_CONFIG_REF_FRONT(sr->ref_value[0]);
54    /* rest of bits weaved in from depth_stencil_alpha */
55    cs->PE_STENCIL_CONFIG_EXT =
56       VIVS_PE_STENCIL_CONFIG_EXT_REF_BACK(sr->ref_value[0]);
57    ctx->dirty |= ETNA_DIRTY_STENCIL_REF;
58 }
59 
60 static void
etna_set_clip_state(struct pipe_context * pctx,const struct pipe_clip_state * pcs)61 etna_set_clip_state(struct pipe_context *pctx, const struct pipe_clip_state *pcs)
62 {
63    /* NOOP */
64 }
65 
66 static void
etna_set_sample_mask(struct pipe_context * pctx,unsigned sample_mask)67 etna_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
68 {
69    struct etna_context *ctx = etna_context(pctx);
70 
71    ctx->sample_mask = sample_mask;
72    ctx->dirty |= ETNA_DIRTY_SAMPLE_MASK;
73 }
74 
75 static void
etna_set_constant_buffer(struct pipe_context * pctx,enum pipe_shader_type shader,uint index,const struct pipe_constant_buffer * cb)76 etna_set_constant_buffer(struct pipe_context *pctx,
77       enum pipe_shader_type shader, uint index,
78       const struct pipe_constant_buffer *cb)
79 {
80    struct etna_context *ctx = etna_context(pctx);
81 
82    if (unlikely(index > 0)) {
83       DBG("Unhandled buffer index %i", index);
84       return;
85    }
86 
87 
88    util_copy_constant_buffer(&ctx->constant_buffer[shader], cb);
89 
90    /* Note that the state tracker can unbind constant buffers by
91     * passing NULL here. */
92    if (unlikely(!cb || (!cb->buffer && !cb->user_buffer)))
93       return;
94 
95    /* there is no support for ARB_uniform_buffer_object */
96    assert(cb->buffer == NULL && cb->user_buffer != NULL);
97 
98    ctx->dirty |= ETNA_DIRTY_CONSTBUF;
99 }
100 
101 static void
etna_update_render_resource(struct pipe_context * pctx,struct pipe_resource * pres)102 etna_update_render_resource(struct pipe_context *pctx, struct pipe_resource *pres)
103 {
104    struct etna_resource *res = etna_resource(pres);
105 
106    if (res->texture && etna_resource_older(res, etna_resource(res->texture))) {
107       /* The render buffer is older than the texture buffer. Copy it over. */
108       etna_copy_resource(pctx, pres, res->texture, 0, pres->last_level);
109       res->seqno = etna_resource(res->texture)->seqno;
110    }
111 }
112 
113 static void
etna_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * sv)114 etna_set_framebuffer_state(struct pipe_context *pctx,
115       const struct pipe_framebuffer_state *sv)
116 {
117    struct etna_context *ctx = etna_context(pctx);
118    struct compiled_framebuffer_state *cs = &ctx->framebuffer;
119    int nr_samples_color = -1;
120    int nr_samples_depth = -1;
121 
122    /* Set up TS as well. Warning: this state is used by both the RS and PE */
123    uint32_t ts_mem_config = 0;
124 
125    if (sv->nr_cbufs > 0) { /* at least one color buffer? */
126       struct etna_surface *cbuf = etna_surface(sv->cbufs[0]);
127       struct etna_resource *res = etna_resource(cbuf->base.texture);
128       bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0;
129 
130       assert(res->layout & ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */
131       etna_update_render_resource(pctx, cbuf->base.texture);
132 
133       pipe_surface_reference(&cs->cbuf, &cbuf->base);
134       cs->PE_COLOR_FORMAT =
135          VIVS_PE_COLOR_FORMAT_FORMAT(translate_rs_format(cbuf->base.format)) |
136          VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK |
137          VIVS_PE_COLOR_FORMAT_OVERWRITE |
138          COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED) |
139          COND(color_supertiled && ctx->specs.halti >= 5, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW);
140       /* VIVS_PE_COLOR_FORMAT_COMPONENTS() and
141        * VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state
142        * but only if we set the bits above. */
143       /* merged with depth_stencil_alpha */
144       if ((cbuf->surf.offset & 63) ||
145           (((cbuf->surf.stride * 4) & 63) && cbuf->surf.height > 4)) {
146          /* XXX Must make temporary surface here.
147           * Need the same mechanism on gc2000 when we want to do mipmap
148           * generation by
149           * rendering to levels > 1 due to multitiled / tiled conversion. */
150          BUG("Alignment error, trying to render to offset %08x with tile "
151              "stride %i",
152              cbuf->surf.offset, cbuf->surf.stride * 4);
153       }
154 
155       if (ctx->specs.pixel_pipes == 1) {
156          cs->PE_COLOR_ADDR = cbuf->reloc[0];
157          cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
158       } else {
159          /* Rendered textures must always be multi-tiled, or single-buffer mode must be supported */
160          assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || ctx->specs.single_buffer);
161          for (int i = 0; i < ctx->specs.pixel_pipes; i++) {
162             cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i];
163             cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
164          }
165       }
166       cs->PE_COLOR_STRIDE = cbuf->surf.stride;
167 
168       if (cbuf->surf.ts_size) {
169          cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value;
170 
171          cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc;
172          cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
173 
174          cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0];
175          cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
176       }
177 
178       /* MSAA */
179       if (cbuf->base.texture->nr_samples > 1)
180          ts_mem_config |=
181             VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION | translate_msaa_format(cbuf->base.format);
182 
183       nr_samples_color = cbuf->base.texture->nr_samples;
184    } else {
185       pipe_surface_reference(&cs->cbuf, NULL);
186       /* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and
187        * VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the
188        * color target */
189       cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_OVERWRITE;
190       cs->PE_COLOR_STRIDE = 0;
191       cs->TS_COLOR_STATUS_BASE.bo = NULL;
192       cs->TS_COLOR_SURFACE_BASE.bo = NULL;
193 
194       for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++)
195          cs->PE_PIPE_COLOR_ADDR[i].bo = NULL;
196    }
197 
198    if (sv->zsbuf != NULL) {
199       struct etna_surface *zsbuf = etna_surface(sv->zsbuf);
200       struct etna_resource *res = etna_resource(zsbuf->base.texture);
201 
202       etna_update_render_resource(pctx, zsbuf->base.texture);
203 
204       pipe_surface_reference(&cs->zsbuf, &zsbuf->base);
205       assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */
206 
207       uint32_t depth_format = translate_depth_format(zsbuf->base.format);
208       unsigned depth_bits =
209          depth_format == VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24;
210       bool depth_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0;
211 
212       cs->PE_DEPTH_CONFIG =
213          depth_format |
214          COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) |
215          VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z |
216          COND(ctx->specs.halti >= 5, VIVS_PE_DEPTH_CONFIG_DISABLE_ZS) /* Needs to be enabled on GC7000, otherwise depth writes hang w/ TS - apparently it does something else now */
217          ;
218       /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */
219       /* merged with depth_stencil_alpha */
220 
221       if (ctx->specs.pixel_pipes == 1) {
222          cs->PE_DEPTH_ADDR = zsbuf->reloc[0];
223          cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
224       } else {
225          for (int i = 0; i < ctx->specs.pixel_pipes; i++) {
226             cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i];
227             cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
228          }
229       }
230 
231       cs->PE_DEPTH_STRIDE = zsbuf->surf.stride;
232       cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED;
233       cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f);
234 
235       if (zsbuf->surf.ts_size) {
236          cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value;
237 
238          cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc;
239          cs->TS_DEPTH_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
240 
241          cs->TS_DEPTH_SURFACE_BASE = zsbuf->reloc[0];
242          cs->TS_DEPTH_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
243       }
244 
245       ts_mem_config |= COND(depth_bits == 16, VIVS_TS_MEM_CONFIG_DEPTH_16BPP);
246 
247       /* MSAA */
248       if (zsbuf->base.texture->nr_samples > 1)
249          /* XXX VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION;
250           * Disable without MSAA for now, as it causes corruption in glquake. */
251          ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION;
252 
253       nr_samples_depth = zsbuf->base.texture->nr_samples;
254    } else {
255       pipe_surface_reference(&cs->zsbuf, NULL);
256       cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE;
257       cs->PE_DEPTH_ADDR.bo = NULL;
258       cs->PE_DEPTH_STRIDE = 0;
259       cs->TS_DEPTH_STATUS_BASE.bo = NULL;
260       cs->TS_DEPTH_SURFACE_BASE.bo = NULL;
261 
262       for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++)
263          cs->PE_PIPE_DEPTH_ADDR[i].bo = NULL;
264    }
265 
266    /* MSAA setup */
267    if (nr_samples_depth != -1 && nr_samples_color != -1 &&
268        nr_samples_depth != nr_samples_color) {
269       BUG("Number of samples in color and depth texture must match (%i and %i respectively)",
270           nr_samples_color, nr_samples_depth);
271    }
272 
273    switch (MAX2(nr_samples_depth, nr_samples_color)) {
274    case 0:
275    case 1: /* Are 0 and 1 samples allowed? */
276       cs->GL_MULTI_SAMPLE_CONFIG =
277          VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
278       cs->msaa_mode = false;
279       break;
280    case 2:
281       cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X;
282       cs->msaa_mode = true; /* Add input to PS */
283       cs->RA_MULTISAMPLE_UNK00E04 = 0x0;
284       cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22;
285       cs->RA_CENTROID_TABLE[0] = 0x66aa2288;
286       cs->RA_CENTROID_TABLE[1] = 0x88558800;
287       cs->RA_CENTROID_TABLE[2] = 0x88881100;
288       cs->RA_CENTROID_TABLE[3] = 0x33888800;
289       break;
290    case 4:
291       cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X;
292       cs->msaa_mode = true; /* Add input to PS */
293       cs->RA_MULTISAMPLE_UNK00E04 = 0x0;
294       cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26;
295       cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a;
296       cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22;
297       cs->RA_CENTROID_TABLE[0] = 0x4a6e2688;
298       cs->RA_CENTROID_TABLE[1] = 0x888888a2;
299       cs->RA_CENTROID_TABLE[2] = 0x888888ea;
300       cs->RA_CENTROID_TABLE[3] = 0x888888c6;
301       cs->RA_CENTROID_TABLE[4] = 0x46622a88;
302       cs->RA_CENTROID_TABLE[5] = 0x888888ae;
303       cs->RA_CENTROID_TABLE[6] = 0x888888e6;
304       cs->RA_CENTROID_TABLE[7] = 0x888888ca;
305       cs->RA_CENTROID_TABLE[8] = 0x262a2288;
306       cs->RA_CENTROID_TABLE[9] = 0x886688a2;
307       cs->RA_CENTROID_TABLE[10] = 0x888866aa;
308       cs->RA_CENTROID_TABLE[11] = 0x668888a6;
309       break;
310    }
311 
312    /* Scissor setup */
313    cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */
314    cs->SE_SCISSOR_TOP = 0;
315    cs->SE_SCISSOR_RIGHT = (sv->width << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT;
316    cs->SE_SCISSOR_BOTTOM = (sv->height << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
317    cs->SE_CLIP_RIGHT = (sv->width << 16) + ETNA_SE_CLIP_MARGIN_RIGHT;
318    cs->SE_CLIP_BOTTOM = (sv->height << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM;
319 
320    cs->TS_MEM_CONFIG = ts_mem_config;
321 
322    /* Single buffer setup. There is only one switch for this, not a separate
323     * one per color buffer / depth buffer. To keep the logic simple always use
324     * single buffer when this feature is available.
325     */
326    cs->PE_LOGIC_OP = VIVS_PE_LOGIC_OP_SINGLE_BUFFER(ctx->specs.single_buffer ? 2 : 0);
327 
328    ctx->framebuffer_s = *sv; /* keep copy of original structure */
329    ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS;
330 }
331 
332 static void
etna_set_polygon_stipple(struct pipe_context * pctx,const struct pipe_poly_stipple * stipple)333 etna_set_polygon_stipple(struct pipe_context *pctx,
334       const struct pipe_poly_stipple *stipple)
335 {
336    /* NOP */
337 }
338 
339 static void
etna_set_scissor_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * ss)340 etna_set_scissor_states(struct pipe_context *pctx, unsigned start_slot,
341       unsigned num_scissors, const struct pipe_scissor_state *ss)
342 {
343    struct etna_context *ctx = etna_context(pctx);
344    struct compiled_scissor_state *cs = &ctx->scissor;
345    assert(ss->minx <= ss->maxx);
346    assert(ss->miny <= ss->maxy);
347 
348    /* note that this state is only used when rasterizer_state->scissor is on */
349    ctx->scissor_s = *ss;
350    cs->SE_SCISSOR_LEFT = (ss->minx << 16);
351    cs->SE_SCISSOR_TOP = (ss->miny << 16);
352    cs->SE_SCISSOR_RIGHT = (ss->maxx << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT;
353    cs->SE_SCISSOR_BOTTOM = (ss->maxy << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
354    cs->SE_CLIP_RIGHT = (ss->maxx << 16) + ETNA_SE_CLIP_MARGIN_RIGHT;
355    cs->SE_CLIP_BOTTOM = (ss->maxy << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM;
356 
357    ctx->dirty |= ETNA_DIRTY_SCISSOR;
358 }
359 
360 static void
etna_set_viewport_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_viewport_state * vs)361 etna_set_viewport_states(struct pipe_context *pctx, unsigned start_slot,
362       unsigned num_scissors, const struct pipe_viewport_state *vs)
363 {
364    struct etna_context *ctx = etna_context(pctx);
365    struct compiled_viewport_state *cs = &ctx->viewport;
366 
367    ctx->viewport_s = *vs;
368    /**
369     * For Vivante GPU, viewport z transformation is 0..1 to 0..1 instead of
370     * -1..1 to 0..1.
371     * scaling and translation to 0..1 already happened, so remove that
372     *
373     * z' = (z * 2 - 1) * scale + translate
374     *    = z * (2 * scale) + (translate - scale)
375     *
376     * scale' = 2 * scale
377     * translate' = translate - scale
378     */
379 
380    /* must be fixp as v4 state deltas assume it is */
381    cs->PA_VIEWPORT_SCALE_X = etna_f32_to_fixp16(vs->scale[0]);
382    cs->PA_VIEWPORT_SCALE_Y = etna_f32_to_fixp16(vs->scale[1]);
383    cs->PA_VIEWPORT_SCALE_Z = fui(vs->scale[2] * 2.0f);
384    cs->PA_VIEWPORT_OFFSET_X = etna_f32_to_fixp16(vs->translate[0]);
385    cs->PA_VIEWPORT_OFFSET_Y = etna_f32_to_fixp16(vs->translate[1]);
386    cs->PA_VIEWPORT_OFFSET_Z = fui(vs->translate[2] - vs->scale[2]);
387 
388    /* Compute scissor rectangle (fixp) from viewport.
389     * Make sure left is always < right and top always < bottom.
390     */
391    cs->SE_SCISSOR_LEFT = etna_f32_to_fixp16(MAX2(vs->translate[0] - fabsf(vs->scale[0]), 0.0f));
392    cs->SE_SCISSOR_TOP = etna_f32_to_fixp16(MAX2(vs->translate[1] - fabsf(vs->scale[1]), 0.0f));
393    uint32_t right_fixp = etna_f32_to_fixp16(MAX2(vs->translate[0] + fabsf(vs->scale[0]), 0.0f));
394    uint32_t bottom_fixp = etna_f32_to_fixp16(MAX2(vs->translate[1] + fabsf(vs->scale[1]), 0.0f));
395    cs->SE_SCISSOR_RIGHT = right_fixp + ETNA_SE_SCISSOR_MARGIN_RIGHT;
396    cs->SE_SCISSOR_BOTTOM = bottom_fixp + ETNA_SE_SCISSOR_MARGIN_BOTTOM;
397    cs->SE_CLIP_RIGHT = right_fixp + ETNA_SE_CLIP_MARGIN_RIGHT;
398    cs->SE_CLIP_BOTTOM = bottom_fixp + ETNA_SE_CLIP_MARGIN_BOTTOM;
399 
400    cs->PE_DEPTH_NEAR = fui(0.0); /* not affected if depth mode is Z (as in GL) */
401    cs->PE_DEPTH_FAR = fui(1.0);
402    ctx->dirty |= ETNA_DIRTY_VIEWPORT;
403 }
404 
405 static void
etna_set_vertex_buffers(struct pipe_context * pctx,unsigned start_slot,unsigned num_buffers,const struct pipe_vertex_buffer * vb)406 etna_set_vertex_buffers(struct pipe_context *pctx, unsigned start_slot,
407       unsigned num_buffers, const struct pipe_vertex_buffer *vb)
408 {
409    struct etna_context *ctx = etna_context(pctx);
410    struct etna_vertexbuf_state *so = &ctx->vertex_buffer;
411 
412    util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, start_slot, num_buffers);
413    so->count = util_last_bit(so->enabled_mask);
414 
415    for (unsigned idx = start_slot; idx < start_slot + num_buffers; ++idx) {
416       struct compiled_set_vertex_buffer *cs = &so->cvb[idx];
417       struct pipe_vertex_buffer *vbi = &so->vb[idx];
418 
419       assert(!vbi->is_user_buffer); /* XXX support user_buffer using
420                                        etna_usermem_map */
421 
422       if (vbi->buffer.resource) { /* GPU buffer */
423          cs->FE_VERTEX_STREAM_BASE_ADDR.bo = etna_resource(vbi->buffer.resource)->bo;
424          cs->FE_VERTEX_STREAM_BASE_ADDR.offset = vbi->buffer_offset;
425          cs->FE_VERTEX_STREAM_BASE_ADDR.flags = ETNA_RELOC_READ;
426          cs->FE_VERTEX_STREAM_CONTROL =
427             FE_VERTEX_STREAM_CONTROL_VERTEX_STRIDE(vbi->stride);
428       } else {
429          cs->FE_VERTEX_STREAM_BASE_ADDR.bo = NULL;
430          cs->FE_VERTEX_STREAM_CONTROL = 0;
431       }
432    }
433 
434    ctx->dirty |= ETNA_DIRTY_VERTEX_BUFFERS;
435 }
436 
437 static void
etna_blend_state_bind(struct pipe_context * pctx,void * bs)438 etna_blend_state_bind(struct pipe_context *pctx, void *bs)
439 {
440    struct etna_context *ctx = etna_context(pctx);
441 
442    ctx->blend = bs;
443    ctx->dirty |= ETNA_DIRTY_BLEND;
444 }
445 
446 static void
etna_blend_state_delete(struct pipe_context * pctx,void * bs)447 etna_blend_state_delete(struct pipe_context *pctx, void *bs)
448 {
449    FREE(bs);
450 }
451 
452 static void
etna_rasterizer_state_bind(struct pipe_context * pctx,void * rs)453 etna_rasterizer_state_bind(struct pipe_context *pctx, void *rs)
454 {
455    struct etna_context *ctx = etna_context(pctx);
456 
457    ctx->rasterizer = rs;
458    ctx->dirty |= ETNA_DIRTY_RASTERIZER;
459 }
460 
461 static void
etna_rasterizer_state_delete(struct pipe_context * pctx,void * rs)462 etna_rasterizer_state_delete(struct pipe_context *pctx, void *rs)
463 {
464    FREE(rs);
465 }
466 
467 static void
etna_zsa_state_bind(struct pipe_context * pctx,void * zs)468 etna_zsa_state_bind(struct pipe_context *pctx, void *zs)
469 {
470    struct etna_context *ctx = etna_context(pctx);
471 
472    ctx->zsa = zs;
473    ctx->dirty |= ETNA_DIRTY_ZSA;
474 }
475 
476 static void
etna_zsa_state_delete(struct pipe_context * pctx,void * zs)477 etna_zsa_state_delete(struct pipe_context *pctx, void *zs)
478 {
479    FREE(zs);
480 }
481 
482 /** Create vertex element states, which define a layout for fetching
483  * vertices for rendering.
484  */
485 static void *
etna_vertex_elements_state_create(struct pipe_context * pctx,unsigned num_elements,const struct pipe_vertex_element * elements)486 etna_vertex_elements_state_create(struct pipe_context *pctx,
487       unsigned num_elements, const struct pipe_vertex_element *elements)
488 {
489    struct etna_context *ctx = etna_context(pctx);
490    struct compiled_vertex_elements_state *cs = CALLOC_STRUCT(compiled_vertex_elements_state);
491 
492    if (!cs)
493       return NULL;
494 
495    if (num_elements > ctx->specs.vertex_max_elements) {
496       BUG("number of elements (%u) exceeds chip maximum (%u)", num_elements,
497           ctx->specs.vertex_max_elements);
498       return NULL;
499    }
500 
501    /* XXX could minimize number of consecutive stretches here by sorting, and
502     * permuting the inputs in shader or does Mesa do this already? */
503 
504    /* Check that vertex element binding is compatible with hardware; thus
505     * elements[idx].vertex_buffer_index are < stream_count. If not, the binding
506     * uses more streams than is supported, and u_vbuf should have done some
507     * reorganization for compatibility. */
508 
509    /* TODO: does mesa this for us? */
510    bool incompatible = false;
511    for (unsigned idx = 0; idx < num_elements; ++idx) {
512       if (elements[idx].vertex_buffer_index >= ctx->specs.stream_count || elements[idx].instance_divisor > 0)
513          incompatible = true;
514    }
515 
516    cs->num_elements = num_elements;
517    if (incompatible || num_elements == 0) {
518       DBG("Error: zero vertex elements, or more vertex buffers used than supported");
519       FREE(cs);
520       return NULL;
521    }
522 
523    unsigned start_offset = 0; /* start of current consecutive stretch */
524    bool nonconsecutive = true; /* previous value of nonconsecutive */
525 
526    for (unsigned idx = 0; idx < num_elements; ++idx) {
527       unsigned element_size = util_format_get_blocksize(elements[idx].src_format);
528       unsigned end_offset = elements[idx].src_offset + element_size;
529       uint32_t format_type, normalize;
530 
531       if (nonconsecutive)
532          start_offset = elements[idx].src_offset;
533 
534       /* maximum vertex size is 256 bytes */
535       assert(element_size != 0 && end_offset <= 256);
536 
537       /* check whether next element is consecutive to this one */
538       nonconsecutive = (idx == (num_elements - 1)) ||
539                        elements[idx + 1].vertex_buffer_index != elements[idx].vertex_buffer_index ||
540                        end_offset != elements[idx + 1].src_offset;
541 
542       format_type = translate_vertex_format_type(elements[idx].src_format);
543       normalize = translate_vertex_format_normalize(elements[idx].src_format);
544 
545       assert(format_type != ETNA_NO_MATCH);
546       assert(normalize != ETNA_NO_MATCH);
547 
548       if (ctx->specs.halti < 5) {
549          cs->FE_VERTEX_ELEMENT_CONFIG[idx] =
550             COND(nonconsecutive, VIVS_FE_VERTEX_ELEMENT_CONFIG_NONCONSECUTIVE) |
551             format_type |
552             VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(util_format_get_nr_components(elements[idx].src_format)) |
553             normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) |
554             VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(elements[idx].vertex_buffer_index) |
555             VIVS_FE_VERTEX_ELEMENT_CONFIG_START(elements[idx].src_offset) |
556             VIVS_FE_VERTEX_ELEMENT_CONFIG_END(end_offset - start_offset);
557       } else { /* HALTI5 spread vertex attrib config over two registers */
558          cs->NFE_GENERIC_ATTRIB_CONFIG0[idx] =
559             format_type |
560             VIVS_NFE_GENERIC_ATTRIB_CONFIG0_NUM(util_format_get_nr_components(elements[idx].src_format)) |
561             normalize | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_ENDIAN(ENDIAN_MODE_NO_SWAP) |
562             VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM(elements[idx].vertex_buffer_index) |
563             VIVS_NFE_GENERIC_ATTRIB_CONFIG0_START(elements[idx].src_offset);
564          cs->NFE_GENERIC_ATTRIB_CONFIG1[idx] =
565             COND(nonconsecutive, VIVS_NFE_GENERIC_ATTRIB_CONFIG1_NONCONSECUTIVE) |
566             VIVS_NFE_GENERIC_ATTRIB_CONFIG1_END(end_offset - start_offset);
567       }
568       cs->NFE_GENERIC_ATTRIB_SCALE[idx] = 0x3f800000; /* 1 for integer, 1.0 for float */
569    }
570 
571    return cs;
572 }
573 
574 static void
etna_vertex_elements_state_delete(struct pipe_context * pctx,void * ve)575 etna_vertex_elements_state_delete(struct pipe_context *pctx, void *ve)
576 {
577    FREE(ve);
578 }
579 
580 static void
etna_vertex_elements_state_bind(struct pipe_context * pctx,void * ve)581 etna_vertex_elements_state_bind(struct pipe_context *pctx, void *ve)
582 {
583    struct etna_context *ctx = etna_context(pctx);
584 
585    ctx->vertex_elements = ve;
586    ctx->dirty |= ETNA_DIRTY_VERTEX_ELEMENTS;
587 }
588 
589 static bool
etna_update_ts_config(struct etna_context * ctx)590 etna_update_ts_config(struct etna_context *ctx)
591 {
592    uint32_t new_ts_config = ctx->framebuffer.TS_MEM_CONFIG;
593 
594    if (ctx->framebuffer_s.nr_cbufs > 0) {
595       struct etna_surface *c_surf = etna_surface(ctx->framebuffer_s.cbufs[0]);
596 
597       if(c_surf->level->ts_size && c_surf->level->ts_valid) {
598          new_ts_config |= VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR;
599       } else {
600          new_ts_config &= ~VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR;
601       }
602    }
603 
604    if (ctx->framebuffer_s.zsbuf) {
605       struct etna_surface *zs_surf = etna_surface(ctx->framebuffer_s.zsbuf);
606 
607       if(zs_surf->level->ts_size && zs_surf->level->ts_valid) {
608          new_ts_config |= VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR;
609       } else {
610          new_ts_config &= ~VIVS_TS_MEM_CONFIG_DEPTH_FAST_CLEAR;
611       }
612    }
613 
614    if (new_ts_config != ctx->framebuffer.TS_MEM_CONFIG ||
615        (ctx->dirty & ETNA_DIRTY_FRAMEBUFFER)) {
616       ctx->framebuffer.TS_MEM_CONFIG = new_ts_config;
617       ctx->dirty |= ETNA_DIRTY_TS;
618    }
619 
620    ctx->dirty &= ~ETNA_DIRTY_DERIVE_TS;
621 
622    return true;
623 }
624 
625 struct etna_state_updater {
626    bool (*update)(struct etna_context *ctx);
627    uint32_t dirty;
628 };
629 
630 static const struct etna_state_updater etna_state_updates[] = {
631    {
632       etna_shader_update_vertex, ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS,
633    },
634    {
635       etna_shader_link, ETNA_DIRTY_SHADER,
636    },
637    {
638       etna_update_blend, ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER
639    },
640    {
641       etna_update_blend_color, ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER,
642    },
643    {
644       etna_update_ts_config, ETNA_DIRTY_DERIVE_TS,
645    }
646 };
647 
648 bool
etna_state_update(struct etna_context * ctx)649 etna_state_update(struct etna_context *ctx)
650 {
651    for (unsigned int i = 0; i < ARRAY_SIZE(etna_state_updates); i++)
652       if (ctx->dirty & etna_state_updates[i].dirty)
653          if (!etna_state_updates[i].update(ctx))
654             return false;
655 
656    return true;
657 }
658 
659 void
etna_state_init(struct pipe_context * pctx)660 etna_state_init(struct pipe_context *pctx)
661 {
662    pctx->set_blend_color = etna_set_blend_color;
663    pctx->set_stencil_ref = etna_set_stencil_ref;
664    pctx->set_clip_state = etna_set_clip_state;
665    pctx->set_sample_mask = etna_set_sample_mask;
666    pctx->set_constant_buffer = etna_set_constant_buffer;
667    pctx->set_framebuffer_state = etna_set_framebuffer_state;
668    pctx->set_polygon_stipple = etna_set_polygon_stipple;
669    pctx->set_scissor_states = etna_set_scissor_states;
670    pctx->set_viewport_states = etna_set_viewport_states;
671 
672    pctx->set_vertex_buffers = etna_set_vertex_buffers;
673 
674    pctx->bind_blend_state = etna_blend_state_bind;
675    pctx->delete_blend_state = etna_blend_state_delete;
676 
677    pctx->bind_rasterizer_state = etna_rasterizer_state_bind;
678    pctx->delete_rasterizer_state = etna_rasterizer_state_delete;
679 
680    pctx->bind_depth_stencil_alpha_state = etna_zsa_state_bind;
681    pctx->delete_depth_stencil_alpha_state = etna_zsa_state_delete;
682 
683    pctx->create_vertex_elements_state = etna_vertex_elements_state_create;
684    pctx->delete_vertex_elements_state = etna_vertex_elements_state_delete;
685    pctx->bind_vertex_elements_state = etna_vertex_elements_state_bind;
686 }
687