1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (c) 2012-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#ifndef H_ETNA_EMIT
28bf215546Sopenharmony_ci#define H_ETNA_EMIT
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "etnaviv_screen.h"
31bf215546Sopenharmony_ci#include "etnaviv_util.h"
32bf215546Sopenharmony_ci#include "hw/cmdstream.xml.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistruct etna_context;
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_cistruct etna_coalesce {
37bf215546Sopenharmony_ci   uint32_t start;
38bf215546Sopenharmony_ci   uint32_t last_reg;
39bf215546Sopenharmony_ci   uint32_t last_fixp;
40bf215546Sopenharmony_ci};
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic inline void
43bf215546Sopenharmony_cietna_emit_load_state(struct etna_cmd_stream *stream, const uint16_t offset,
44bf215546Sopenharmony_ci                     const uint16_t count, const int fixp)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   uint32_t v;
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci   v = VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
49bf215546Sopenharmony_ci       COND(fixp, VIV_FE_LOAD_STATE_HEADER_FIXP) |
50bf215546Sopenharmony_ci       VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) |
51bf215546Sopenharmony_ci       (VIV_FE_LOAD_STATE_HEADER_COUNT(count) &
52bf215546Sopenharmony_ci        VIV_FE_LOAD_STATE_HEADER_COUNT__MASK);
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, v);
55bf215546Sopenharmony_ci}
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_cistatic inline void
58bf215546Sopenharmony_cietna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value)
59bf215546Sopenharmony_ci{
60bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, 2);
61bf215546Sopenharmony_ci   etna_emit_load_state(stream, address >> 2, 1, 0);
62bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, value);
63bf215546Sopenharmony_ci}
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistatic inline void
66bf215546Sopenharmony_cietna_set_state_reloc(struct etna_cmd_stream *stream, uint32_t address,
67bf215546Sopenharmony_ci                     const struct etna_reloc *reloc)
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, 2);
70bf215546Sopenharmony_ci   etna_emit_load_state(stream, address >> 2, 1, 0);
71bf215546Sopenharmony_ci   etna_cmd_stream_reloc(stream, reloc);
72bf215546Sopenharmony_ci}
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_cistatic inline void
75bf215546Sopenharmony_cietna_set_state_multi(struct etna_cmd_stream *stream, uint32_t base,
76bf215546Sopenharmony_ci                     uint32_t num, const uint32_t *values)
77bf215546Sopenharmony_ci{
78bf215546Sopenharmony_ci   if (num == 0)
79bf215546Sopenharmony_ci      return;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, 1 + num + 1); /* 1 extra for potential alignment */
82bf215546Sopenharmony_ci   etna_emit_load_state(stream, base >> 2, num, 0);
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci   for (uint32_t i = 0; i < num; i++)
85bf215546Sopenharmony_ci      etna_cmd_stream_emit(stream, values[i]);
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   /* add potential padding */
88bf215546Sopenharmony_ci   if ((num % 2) == 0)
89bf215546Sopenharmony_ci      etna_cmd_stream_emit(stream, 0);
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_civoid
93bf215546Sopenharmony_cietna_stall(struct etna_cmd_stream *stream, uint32_t from, uint32_t to);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_cistatic inline void
96bf215546Sopenharmony_cietna_draw_primitives(struct etna_cmd_stream *stream, uint32_t primitive_type,
97bf215546Sopenharmony_ci                     uint32_t start, uint32_t count)
98bf215546Sopenharmony_ci{
99bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, 4);
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES);
102bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, primitive_type);
103bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, start);
104bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, count);
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_cistatic inline void
108bf215546Sopenharmony_cietna_draw_indexed_primitives(struct etna_cmd_stream *stream,
109bf215546Sopenharmony_ci                             uint32_t primitive_type, uint32_t start,
110bf215546Sopenharmony_ci                             uint32_t count, uint32_t offset)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, 5 + 1);
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES);
115bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, primitive_type);
116bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, start);
117bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, count);
118bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, offset);
119bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, 0);
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci/* important: this takes a vertex count, not a primitive count */
123bf215546Sopenharmony_cistatic inline void
124bf215546Sopenharmony_cietna_draw_instanced(struct etna_cmd_stream *stream,
125bf215546Sopenharmony_ci                    uint32_t indexed, uint32_t primitive_type,
126bf215546Sopenharmony_ci                    uint32_t instance_count,
127bf215546Sopenharmony_ci                    uint32_t vertex_count, uint32_t offset)
128bf215546Sopenharmony_ci{
129bf215546Sopenharmony_ci   etna_cmd_stream_reserve(stream, 3 + 1);
130bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream,
131bf215546Sopenharmony_ci      VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED |
132bf215546Sopenharmony_ci      COND(indexed, VIV_FE_DRAW_INSTANCED_HEADER_INDEXED) |
133bf215546Sopenharmony_ci      VIV_FE_DRAW_INSTANCED_HEADER_TYPE(primitive_type) |
134bf215546Sopenharmony_ci      VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(instance_count & 0xffff));
135bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream,
136bf215546Sopenharmony_ci      VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(instance_count >> 16) |
137bf215546Sopenharmony_ci      VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(vertex_count));
138bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream,
139bf215546Sopenharmony_ci      VIV_FE_DRAW_INSTANCED_START_INDEX(offset));
140bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, 0);
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_cistatic inline void
144bf215546Sopenharmony_cietna_coalesce_start(struct etna_cmd_stream *stream,
145bf215546Sopenharmony_ci                    struct etna_coalesce *coalesce)
146bf215546Sopenharmony_ci{
147bf215546Sopenharmony_ci   coalesce->start = etna_cmd_stream_offset(stream);
148bf215546Sopenharmony_ci   coalesce->last_reg = 0;
149bf215546Sopenharmony_ci   coalesce->last_fixp = 0;
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_cistatic inline void
153bf215546Sopenharmony_cietna_coalesce_end(struct etna_cmd_stream *stream,
154bf215546Sopenharmony_ci                  struct etna_coalesce *coalesce)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   uint32_t end = etna_cmd_stream_offset(stream);
157bf215546Sopenharmony_ci   uint32_t size = end - coalesce->start;
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   if (size) {
160bf215546Sopenharmony_ci      uint32_t offset = coalesce->start - 1;
161bf215546Sopenharmony_ci      uint32_t value = etna_cmd_stream_get(stream, offset);
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci      value |= VIV_FE_LOAD_STATE_HEADER_COUNT(size);
164bf215546Sopenharmony_ci      etna_cmd_stream_set(stream, offset, value);
165bf215546Sopenharmony_ci   }
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   /* append needed padding */
168bf215546Sopenharmony_ci   if (end % 2 == 1)
169bf215546Sopenharmony_ci      etna_cmd_stream_emit(stream, 0xdeadbeef);
170bf215546Sopenharmony_ci}
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_cistatic inline void
173bf215546Sopenharmony_cicheck_coalsence(struct etna_cmd_stream *stream, struct etna_coalesce *coalesce,
174bf215546Sopenharmony_ci                uint32_t reg, uint32_t fixp)
175bf215546Sopenharmony_ci{
176bf215546Sopenharmony_ci   if (coalesce->last_reg != 0) {
177bf215546Sopenharmony_ci      if (((coalesce->last_reg + 4) != reg) || (coalesce->last_fixp != fixp)) {
178bf215546Sopenharmony_ci         etna_coalesce_end(stream, coalesce);
179bf215546Sopenharmony_ci         etna_emit_load_state(stream, reg >> 2, 0, fixp);
180bf215546Sopenharmony_ci         coalesce->start = etna_cmd_stream_offset(stream);
181bf215546Sopenharmony_ci      }
182bf215546Sopenharmony_ci   } else {
183bf215546Sopenharmony_ci      etna_emit_load_state(stream, reg >> 2, 0, fixp);
184bf215546Sopenharmony_ci      coalesce->start = etna_cmd_stream_offset(stream);
185bf215546Sopenharmony_ci   }
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   coalesce->last_reg = reg;
188bf215546Sopenharmony_ci   coalesce->last_fixp = fixp;
189bf215546Sopenharmony_ci}
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_cistatic inline void
192bf215546Sopenharmony_cietna_coalsence_emit(struct etna_cmd_stream *stream,
193bf215546Sopenharmony_ci                    struct etna_coalesce *coalesce, uint32_t reg,
194bf215546Sopenharmony_ci                    uint32_t value)
195bf215546Sopenharmony_ci{
196bf215546Sopenharmony_ci   check_coalsence(stream, coalesce, reg, 0);
197bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, value);
198bf215546Sopenharmony_ci}
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_cistatic inline void
201bf215546Sopenharmony_cietna_coalsence_emit_fixp(struct etna_cmd_stream *stream,
202bf215546Sopenharmony_ci                         struct etna_coalesce *coalesce, uint32_t reg,
203bf215546Sopenharmony_ci                         uint32_t value)
204bf215546Sopenharmony_ci{
205bf215546Sopenharmony_ci   check_coalsence(stream, coalesce, reg, 1);
206bf215546Sopenharmony_ci   etna_cmd_stream_emit(stream, value);
207bf215546Sopenharmony_ci}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_cistatic inline void
210bf215546Sopenharmony_cietna_coalsence_emit_reloc(struct etna_cmd_stream *stream,
211bf215546Sopenharmony_ci                          struct etna_coalesce *coalesce, uint32_t reg,
212bf215546Sopenharmony_ci                          const struct etna_reloc *r)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   if (r->bo) {
215bf215546Sopenharmony_ci      check_coalsence(stream, coalesce, reg, 0);
216bf215546Sopenharmony_ci      etna_cmd_stream_reloc(stream, r);
217bf215546Sopenharmony_ci   }
218bf215546Sopenharmony_ci}
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_civoid
221bf215546Sopenharmony_cietna_emit_state(struct etna_context *ctx);
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci#endif
224