2 * Copyright (c) 2012-2015 Etnaviv Project
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:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
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.
24 * Wladimir J. van der Laan <laanwj@gmail.com>
30 #include "etnaviv_screen.h"
31 #include "etnaviv_util.h"
32 #include "hw/cmdstream.xml.h"
35 struct compiled_rs_state
;
37 struct etna_coalesce
{
44 etna_emit_load_state(struct etna_cmd_stream
*stream
, const uint16_t offset
,
45 const uint16_t count
, const int fixp
)
49 v
= VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE
|
50 COND(fixp
, VIV_FE_LOAD_STATE_HEADER_FIXP
) |
51 VIV_FE_LOAD_STATE_HEADER_OFFSET(offset
) |
52 (VIV_FE_LOAD_STATE_HEADER_COUNT(count
) &
53 VIV_FE_LOAD_STATE_HEADER_COUNT__MASK
);
55 etna_cmd_stream_emit(stream
, v
);
59 etna_set_state(struct etna_cmd_stream
*stream
, uint32_t address
, uint32_t value
)
61 etna_cmd_stream_reserve(stream
, 2);
62 etna_emit_load_state(stream
, address
>> 2, 1, 0);
63 etna_cmd_stream_emit(stream
, value
);
67 etna_set_state_reloc(struct etna_cmd_stream
*stream
, uint32_t address
,
68 const struct etna_reloc
*reloc
)
70 etna_cmd_stream_reserve(stream
, 2);
71 etna_emit_load_state(stream
, address
>> 2, 1, 0);
72 etna_cmd_stream_reloc(stream
, reloc
);
76 etna_set_state_multi(struct etna_cmd_stream
*stream
, uint32_t base
,
77 uint32_t num
, const uint32_t *values
)
82 etna_cmd_stream_reserve(stream
, 1 + num
+ 1); /* 1 extra for potential alignment */
83 etna_emit_load_state(stream
, base
>> 2, num
, 0);
85 for (uint32_t i
= 0; i
< num
; i
++)
86 etna_cmd_stream_emit(stream
, values
[i
]);
88 /* add potential padding */
90 etna_cmd_stream_emit(stream
, 0);
94 etna_stall(struct etna_cmd_stream
*stream
, uint32_t from
, uint32_t to
);
97 etna_draw_primitives(struct etna_cmd_stream
*stream
, uint32_t primitive_type
,
98 uint32_t start
, uint32_t count
)
100 etna_cmd_stream_reserve(stream
, 4);
102 etna_cmd_stream_emit(stream
, VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES
);
103 etna_cmd_stream_emit(stream
, primitive_type
);
104 etna_cmd_stream_emit(stream
, start
);
105 etna_cmd_stream_emit(stream
, count
);
109 etna_draw_indexed_primitives(struct etna_cmd_stream
*stream
,
110 uint32_t primitive_type
, uint32_t start
,
111 uint32_t count
, uint32_t offset
)
113 etna_cmd_stream_reserve(stream
, 5 + 1);
115 etna_cmd_stream_emit(stream
, VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES
);
116 etna_cmd_stream_emit(stream
, primitive_type
);
117 etna_cmd_stream_emit(stream
, start
);
118 etna_cmd_stream_emit(stream
, count
);
119 etna_cmd_stream_emit(stream
, offset
);
120 etna_cmd_stream_emit(stream
, 0);
123 /* important: this takes a vertex count, not a primitive count */
125 etna_draw_instanced(struct etna_cmd_stream
*stream
,
126 uint32_t indexed
, uint32_t primitive_type
,
127 uint32_t instance_count
,
128 uint32_t vertex_count
, uint32_t offset
)
130 etna_cmd_stream_reserve(stream
, 3 + 1);
131 etna_cmd_stream_emit(stream
,
132 VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED
|
133 COND(indexed
, VIV_FE_DRAW_INSTANCED_HEADER_INDEXED
) |
134 VIV_FE_DRAW_INSTANCED_HEADER_TYPE(primitive_type
) |
135 VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(instance_count
& 0xffff));
136 etna_cmd_stream_emit(stream
,
137 VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(instance_count
>> 16) |
138 VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(vertex_count
));
139 etna_cmd_stream_emit(stream
,
140 VIV_FE_DRAW_INSTANCED_START_INDEX(offset
));
141 etna_cmd_stream_emit(stream
, 0);
145 etna_coalesce_start(struct etna_cmd_stream
*stream
,
146 struct etna_coalesce
*coalesce
)
148 coalesce
->start
= etna_cmd_stream_offset(stream
);
149 coalesce
->last_reg
= 0;
150 coalesce
->last_fixp
= 0;
154 etna_coalesce_end(struct etna_cmd_stream
*stream
,
155 struct etna_coalesce
*coalesce
)
157 uint32_t end
= etna_cmd_stream_offset(stream
);
158 uint32_t size
= end
- coalesce
->start
;
161 uint32_t offset
= coalesce
->start
- 1;
162 uint32_t value
= etna_cmd_stream_get(stream
, offset
);
164 value
|= VIV_FE_LOAD_STATE_HEADER_COUNT(size
);
165 etna_cmd_stream_set(stream
, offset
, value
);
168 /* append needed padding */
170 etna_cmd_stream_emit(stream
, 0xdeadbeef);
174 check_coalsence(struct etna_cmd_stream
*stream
, struct etna_coalesce
*coalesce
,
175 uint32_t reg
, uint32_t fixp
)
177 if (coalesce
->last_reg
!= 0) {
178 if (((coalesce
->last_reg
+ 4) != reg
) || (coalesce
->last_fixp
!= fixp
)) {
179 etna_coalesce_end(stream
, coalesce
);
180 etna_emit_load_state(stream
, reg
>> 2, 0, fixp
);
181 coalesce
->start
= etna_cmd_stream_offset(stream
);
184 etna_emit_load_state(stream
, reg
>> 2, 0, fixp
);
185 coalesce
->start
= etna_cmd_stream_offset(stream
);
188 coalesce
->last_reg
= reg
;
189 coalesce
->last_fixp
= fixp
;
193 etna_coalsence_emit(struct etna_cmd_stream
*stream
,
194 struct etna_coalesce
*coalesce
, uint32_t reg
,
197 check_coalsence(stream
, coalesce
, reg
, 0);
198 etna_cmd_stream_emit(stream
, value
);
202 etna_coalsence_emit_fixp(struct etna_cmd_stream
*stream
,
203 struct etna_coalesce
*coalesce
, uint32_t reg
,
206 check_coalsence(stream
, coalesce
, reg
, 1);
207 etna_cmd_stream_emit(stream
, value
);
211 etna_coalsence_emit_reloc(struct etna_cmd_stream
*stream
,
212 struct etna_coalesce
*coalesce
, uint32_t reg
,
213 const struct etna_reloc
*r
)
216 check_coalsence(stream
, coalesce
, reg
, 0);
217 etna_cmd_stream_reloc(stream
, r
);
222 etna_emit_state(struct etna_context
*ctx
);