1b8e80941Smrg/*
2b8e80941Smrg * Copyright (c) 2012-2015 Etnaviv Project
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the
12b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions
13b8e80941Smrg * of the Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21b8e80941Smrg * DEALINGS IN THE SOFTWARE.
22b8e80941Smrg *
23b8e80941Smrg * Authors:
24b8e80941Smrg *    Wladimir J. van der Laan <laanwj@gmail.com>
25b8e80941Smrg */
26b8e80941Smrg
27b8e80941Smrg#ifndef H_ETNA_EMIT
28b8e80941Smrg#define H_ETNA_EMIT
29b8e80941Smrg
30b8e80941Smrg#include "etnaviv_screen.h"
31b8e80941Smrg#include "etnaviv_util.h"
32b8e80941Smrg#include "hw/cmdstream.xml.h"
33b8e80941Smrg
34b8e80941Smrgstruct etna_context;
35b8e80941Smrgstruct compiled_rs_state;
36b8e80941Smrg
37b8e80941Smrgstruct etna_coalesce {
38b8e80941Smrg   uint32_t start;
39b8e80941Smrg   uint32_t last_reg;
40b8e80941Smrg   uint32_t last_fixp;
41b8e80941Smrg};
42b8e80941Smrg
43b8e80941Smrgstatic inline void
44b8e80941Smrgetna_emit_load_state(struct etna_cmd_stream *stream, const uint16_t offset,
45b8e80941Smrg                     const uint16_t count, const int fixp)
46b8e80941Smrg{
47b8e80941Smrg   uint32_t v;
48b8e80941Smrg
49b8e80941Smrg   v = VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
50b8e80941Smrg       COND(fixp, VIV_FE_LOAD_STATE_HEADER_FIXP) |
51b8e80941Smrg       VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) |
52b8e80941Smrg       (VIV_FE_LOAD_STATE_HEADER_COUNT(count) &
53b8e80941Smrg        VIV_FE_LOAD_STATE_HEADER_COUNT__MASK);
54b8e80941Smrg
55b8e80941Smrg   etna_cmd_stream_emit(stream, v);
56b8e80941Smrg}
57b8e80941Smrg
58b8e80941Smrgstatic inline void
59b8e80941Smrgetna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value)
60b8e80941Smrg{
61b8e80941Smrg   etna_cmd_stream_reserve(stream, 2);
62b8e80941Smrg   etna_emit_load_state(stream, address >> 2, 1, 0);
63b8e80941Smrg   etna_cmd_stream_emit(stream, value);
64b8e80941Smrg}
65b8e80941Smrg
66b8e80941Smrgstatic inline void
67b8e80941Smrgetna_set_state_reloc(struct etna_cmd_stream *stream, uint32_t address,
68b8e80941Smrg                     const struct etna_reloc *reloc)
69b8e80941Smrg{
70b8e80941Smrg   etna_cmd_stream_reserve(stream, 2);
71b8e80941Smrg   etna_emit_load_state(stream, address >> 2, 1, 0);
72b8e80941Smrg   etna_cmd_stream_reloc(stream, reloc);
73b8e80941Smrg}
74b8e80941Smrg
75b8e80941Smrgstatic inline void
76b8e80941Smrgetna_set_state_multi(struct etna_cmd_stream *stream, uint32_t base,
77b8e80941Smrg                     uint32_t num, const uint32_t *values)
78b8e80941Smrg{
79b8e80941Smrg   if (num == 0)
80b8e80941Smrg      return;
81b8e80941Smrg
82b8e80941Smrg   etna_cmd_stream_reserve(stream, 1 + num + 1); /* 1 extra for potential alignment */
83b8e80941Smrg   etna_emit_load_state(stream, base >> 2, num, 0);
84b8e80941Smrg
85b8e80941Smrg   for (uint32_t i = 0; i < num; i++)
86b8e80941Smrg      etna_cmd_stream_emit(stream, values[i]);
87b8e80941Smrg
88b8e80941Smrg   /* add potential padding */
89b8e80941Smrg   if ((num % 2) == 0)
90b8e80941Smrg      etna_cmd_stream_emit(stream, 0);
91b8e80941Smrg}
92b8e80941Smrg
93b8e80941Smrgvoid
94b8e80941Smrgetna_stall(struct etna_cmd_stream *stream, uint32_t from, uint32_t to);
95b8e80941Smrg
96b8e80941Smrgstatic inline void
97b8e80941Smrgetna_draw_primitives(struct etna_cmd_stream *stream, uint32_t primitive_type,
98b8e80941Smrg                     uint32_t start, uint32_t count)
99b8e80941Smrg{
100b8e80941Smrg   etna_cmd_stream_reserve(stream, 4);
101b8e80941Smrg
102b8e80941Smrg   etna_cmd_stream_emit(stream, VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES);
103b8e80941Smrg   etna_cmd_stream_emit(stream, primitive_type);
104b8e80941Smrg   etna_cmd_stream_emit(stream, start);
105b8e80941Smrg   etna_cmd_stream_emit(stream, count);
106b8e80941Smrg}
107b8e80941Smrg
108b8e80941Smrgstatic inline void
109b8e80941Smrgetna_draw_indexed_primitives(struct etna_cmd_stream *stream,
110b8e80941Smrg                             uint32_t primitive_type, uint32_t start,
111b8e80941Smrg                             uint32_t count, uint32_t offset)
112b8e80941Smrg{
113b8e80941Smrg   etna_cmd_stream_reserve(stream, 5 + 1);
114b8e80941Smrg
115b8e80941Smrg   etna_cmd_stream_emit(stream, VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES);
116b8e80941Smrg   etna_cmd_stream_emit(stream, primitive_type);
117b8e80941Smrg   etna_cmd_stream_emit(stream, start);
118b8e80941Smrg   etna_cmd_stream_emit(stream, count);
119b8e80941Smrg   etna_cmd_stream_emit(stream, offset);
120b8e80941Smrg   etna_cmd_stream_emit(stream, 0);
121b8e80941Smrg}
122b8e80941Smrg
123b8e80941Smrg/* important: this takes a vertex count, not a primitive count */
124b8e80941Smrgstatic inline void
125b8e80941Smrgetna_draw_instanced(struct etna_cmd_stream *stream,
126b8e80941Smrg                    uint32_t indexed, uint32_t primitive_type,
127b8e80941Smrg                    uint32_t instance_count,
128b8e80941Smrg                    uint32_t vertex_count, uint32_t offset)
129b8e80941Smrg{
130b8e80941Smrg   etna_cmd_stream_reserve(stream, 3 + 1);
131b8e80941Smrg   etna_cmd_stream_emit(stream,
132b8e80941Smrg      VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED |
133b8e80941Smrg      COND(indexed, VIV_FE_DRAW_INSTANCED_HEADER_INDEXED) |
134b8e80941Smrg      VIV_FE_DRAW_INSTANCED_HEADER_TYPE(primitive_type) |
135b8e80941Smrg      VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(instance_count & 0xffff));
136b8e80941Smrg   etna_cmd_stream_emit(stream,
137b8e80941Smrg      VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(instance_count >> 16) |
138b8e80941Smrg      VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(vertex_count));
139b8e80941Smrg   etna_cmd_stream_emit(stream,
140b8e80941Smrg      VIV_FE_DRAW_INSTANCED_START_INDEX(offset));
141b8e80941Smrg   etna_cmd_stream_emit(stream, 0);
142b8e80941Smrg}
143b8e80941Smrg
144b8e80941Smrgstatic inline void
145b8e80941Smrgetna_coalesce_start(struct etna_cmd_stream *stream,
146b8e80941Smrg                    struct etna_coalesce *coalesce)
147b8e80941Smrg{
148b8e80941Smrg   coalesce->start = etna_cmd_stream_offset(stream);
149b8e80941Smrg   coalesce->last_reg = 0;
150b8e80941Smrg   coalesce->last_fixp = 0;
151b8e80941Smrg}
152b8e80941Smrg
153b8e80941Smrgstatic inline void
154b8e80941Smrgetna_coalesce_end(struct etna_cmd_stream *stream,
155b8e80941Smrg                  struct etna_coalesce *coalesce)
156b8e80941Smrg{
157b8e80941Smrg   uint32_t end = etna_cmd_stream_offset(stream);
158b8e80941Smrg   uint32_t size = end - coalesce->start;
159b8e80941Smrg
160b8e80941Smrg   if (size) {
161b8e80941Smrg      uint32_t offset = coalesce->start - 1;
162b8e80941Smrg      uint32_t value = etna_cmd_stream_get(stream, offset);
163b8e80941Smrg
164b8e80941Smrg      value |= VIV_FE_LOAD_STATE_HEADER_COUNT(size);
165b8e80941Smrg      etna_cmd_stream_set(stream, offset, value);
166b8e80941Smrg   }
167b8e80941Smrg
168b8e80941Smrg   /* append needed padding */
169b8e80941Smrg   if (end % 2 == 1)
170b8e80941Smrg      etna_cmd_stream_emit(stream, 0xdeadbeef);
171b8e80941Smrg}
172b8e80941Smrg
173b8e80941Smrgstatic inline void
174b8e80941Smrgcheck_coalsence(struct etna_cmd_stream *stream, struct etna_coalesce *coalesce,
175b8e80941Smrg                uint32_t reg, uint32_t fixp)
176b8e80941Smrg{
177b8e80941Smrg   if (coalesce->last_reg != 0) {
178b8e80941Smrg      if (((coalesce->last_reg + 4) != reg) || (coalesce->last_fixp != fixp)) {
179b8e80941Smrg         etna_coalesce_end(stream, coalesce);
180b8e80941Smrg         etna_emit_load_state(stream, reg >> 2, 0, fixp);
181b8e80941Smrg         coalesce->start = etna_cmd_stream_offset(stream);
182b8e80941Smrg      }
183b8e80941Smrg   } else {
184b8e80941Smrg      etna_emit_load_state(stream, reg >> 2, 0, fixp);
185b8e80941Smrg      coalesce->start = etna_cmd_stream_offset(stream);
186b8e80941Smrg   }
187b8e80941Smrg
188b8e80941Smrg   coalesce->last_reg = reg;
189b8e80941Smrg   coalesce->last_fixp = fixp;
190b8e80941Smrg}
191b8e80941Smrg
192b8e80941Smrgstatic inline void
193b8e80941Smrgetna_coalsence_emit(struct etna_cmd_stream *stream,
194b8e80941Smrg                    struct etna_coalesce *coalesce, uint32_t reg,
195b8e80941Smrg                    uint32_t value)
196b8e80941Smrg{
197b8e80941Smrg   check_coalsence(stream, coalesce, reg, 0);
198b8e80941Smrg   etna_cmd_stream_emit(stream, value);
199b8e80941Smrg}
200b8e80941Smrg
201b8e80941Smrgstatic inline void
202b8e80941Smrgetna_coalsence_emit_fixp(struct etna_cmd_stream *stream,
203b8e80941Smrg                         struct etna_coalesce *coalesce, uint32_t reg,
204b8e80941Smrg                         uint32_t value)
205b8e80941Smrg{
206b8e80941Smrg   check_coalsence(stream, coalesce, reg, 1);
207b8e80941Smrg   etna_cmd_stream_emit(stream, value);
208b8e80941Smrg}
209b8e80941Smrg
210b8e80941Smrgstatic inline void
211b8e80941Smrgetna_coalsence_emit_reloc(struct etna_cmd_stream *stream,
212b8e80941Smrg                          struct etna_coalesce *coalesce, uint32_t reg,
213b8e80941Smrg                          const struct etna_reloc *r)
214b8e80941Smrg{
215b8e80941Smrg   if (r->bo) {
216b8e80941Smrg      check_coalsence(stream, coalesce, reg, 0);
217b8e80941Smrg      etna_cmd_stream_reloc(stream, r);
218b8e80941Smrg   }
219b8e80941Smrg}
220b8e80941Smrg
221b8e80941Smrgvoid
222b8e80941Smrgetna_emit_state(struct etna_context *ctx);
223b8e80941Smrg
224b8e80941Smrg#endif
225