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>
25 * Christian Gmeiner <christian.gmeiner@gmail.com>
28 #include "etnaviv_context.h"
30 #include "etnaviv_blend.h"
31 #include "etnaviv_clear_blit.h"
32 #include "etnaviv_compiler.h"
33 #include "etnaviv_debug.h"
34 #include "etnaviv_emit.h"
35 #include "etnaviv_fence.h"
36 #include "etnaviv_query.h"
37 #include "etnaviv_query_hw.h"
38 #include "etnaviv_rasterizer.h"
39 #include "etnaviv_screen.h"
40 #include "etnaviv_shader.h"
41 #include "etnaviv_state.h"
42 #include "etnaviv_surface.h"
43 #include "etnaviv_texture.h"
44 #include "etnaviv_transfer.h"
45 #include "etnaviv_translate.h"
46 #include "etnaviv_zsa.h"
48 #include "pipe/p_context.h"
49 #include "pipe/p_state.h"
50 #include "util/u_blitter.h"
51 #include "util/u_helpers.h"
52 #include "util/u_memory.h"
53 #include "util/u_prim.h"
54 #include "util/u_upload_mgr.h"
56 #include "hw/common.xml.h"
59 etna_context_destroy(struct pipe_context
*pctx
)
61 struct etna_context
*ctx
= etna_context(pctx
);
64 util_primconvert_destroy(ctx
->primconvert
);
67 util_blitter_destroy(ctx
->blitter
);
69 if (pctx
->stream_uploader
)
70 u_upload_destroy(pctx
->stream_uploader
);
73 etna_cmd_stream_del(ctx
->stream
);
75 slab_destroy_child(&ctx
->transfer_pool
);
77 if (ctx
->in_fence_fd
!= -1)
78 close(ctx
->in_fence_fd
);
83 /* Update render state where needed based on draw operation */
85 etna_update_state_for_draw(struct etna_context
*ctx
, const struct pipe_draw_info
*info
)
87 /* Handle primitive restart:
88 * - If not an indexed draw, we don't care about the state of the primitive restart bit.
89 * - Otherwise, set the bit in INDEX_STREAM_CONTROL in the index buffer state
91 * - If the value of the INDEX_STREAM_CONTROL register changed due to this, or
92 * primitive restart is enabled and the restart index changed, mark the index
93 * buffer state as dirty
96 if (info
->index_size
) {
97 uint32_t new_control
= ctx
->index_buffer
.FE_INDEX_STREAM_CONTROL
;
99 if (info
->primitive_restart
)
100 new_control
|= VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART
;
102 new_control
&= ~VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART
;
104 if (ctx
->index_buffer
.FE_INDEX_STREAM_CONTROL
!= new_control
||
105 (info
->primitive_restart
&& ctx
->index_buffer
.FE_PRIMITIVE_RESTART_INDEX
!= info
->restart_index
)) {
106 ctx
->index_buffer
.FE_INDEX_STREAM_CONTROL
= new_control
;
107 ctx
->index_buffer
.FE_PRIMITIVE_RESTART_INDEX
= info
->restart_index
;
108 ctx
->dirty
|= ETNA_DIRTY_INDEX_BUFFER
;
114 etna_get_vs(struct etna_context
*ctx
, struct etna_shader_key key
)
116 const struct etna_shader_variant
*old
= ctx
->shader
.vs
;
118 ctx
->shader
.vs
= etna_shader_variant(ctx
->shader
.bind_vs
, key
, &ctx
->debug
);
123 if (old
!= ctx
->shader
.vs
)
124 ctx
->dirty
|= ETNA_DIRTY_SHADER
;
130 etna_get_fs(struct etna_context
*ctx
, struct etna_shader_key key
)
132 const struct etna_shader_variant
*old
= ctx
->shader
.fs
;
134 ctx
->shader
.fs
= etna_shader_variant(ctx
->shader
.bind_fs
, key
, &ctx
->debug
);
139 if (old
!= ctx
->shader
.fs
)
140 ctx
->dirty
|= ETNA_DIRTY_SHADER
;
146 etna_draw_vbo(struct pipe_context
*pctx
, const struct pipe_draw_info
*info
)
148 struct etna_context
*ctx
= etna_context(pctx
);
149 struct pipe_framebuffer_state
*pfb
= &ctx
->framebuffer_s
;
153 if (!info
->count_from_stream_output
&& !info
->indirect
&&
154 !info
->primitive_restart
&&
155 !u_trim_pipe_prim(info
->mode
, (unsigned*)&info
->count
))
158 if (ctx
->vertex_elements
== NULL
|| ctx
->vertex_elements
->num_elements
== 0)
159 return; /* Nothing to do */
161 if (!(ctx
->prim_hwsupport
& (1 << info
->mode
))) {
162 struct primconvert_context
*primconvert
= ctx
->primconvert
;
163 util_primconvert_save_rasterizer_state(primconvert
, ctx
->rasterizer
);
164 util_primconvert_draw_vbo(primconvert
, info
);
168 int prims
= u_decomposed_prims_for_vertices(info
->mode
, info
->count
);
169 if (unlikely(prims
<= 0)) {
170 DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info
->mode
);
174 draw_mode
= translate_draw_mode(info
->mode
);
175 if (draw_mode
== ETNA_NO_MATCH
) {
176 BUG("Unsupported draw mode");
180 /* Upload a user index buffer. */
181 unsigned index_offset
= 0;
182 struct pipe_resource
*indexbuf
= NULL
;
184 if (info
->index_size
) {
185 indexbuf
= info
->has_user_indices
? NULL
: info
->index
.resource
;
186 if (info
->has_user_indices
&&
187 !util_upload_index_buffer(pctx
, info
, &indexbuf
, &index_offset
)) {
188 BUG("Index buffer upload failed.");
192 ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.bo
= etna_resource(indexbuf
)->bo
;
193 ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.offset
= index_offset
;
194 ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.flags
= ETNA_RELOC_READ
;
195 ctx
->index_buffer
.FE_INDEX_STREAM_CONTROL
= translate_index_size(info
->index_size
);
197 if (!ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.bo
) {
198 BUG("Unsupported or no index buffer");
202 ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.bo
= 0;
203 ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.offset
= 0;
204 ctx
->index_buffer
.FE_INDEX_STREAM_BASE_ADDR
.flags
= 0;
205 ctx
->index_buffer
.FE_INDEX_STREAM_CONTROL
= 0;
207 ctx
->dirty
|= ETNA_DIRTY_INDEX_BUFFER
;
209 struct etna_shader_key key
= {};
210 struct etna_surface
*cbuf
= etna_surface(pfb
->cbufs
[0]);
213 struct etna_resource
*res
= etna_resource(cbuf
->base
.texture
);
215 key
.frag_rb_swap
= !!translate_rs_format_rb_swap(res
->base
.format
);
218 if (!etna_get_vs(ctx
, key
) || !etna_get_fs(ctx
, key
)) {
219 BUG("compiled shaders are not okay");
223 /* Update any derived state */
224 if (!etna_state_update(ctx
))
228 * Figure out the buffers/features we need:
230 if (etna_depth_enabled(ctx
))
231 resource_written(ctx
, pfb
->zsbuf
->texture
);
233 if (etna_stencil_enabled(ctx
))
234 resource_written(ctx
, pfb
->zsbuf
->texture
);
236 for (i
= 0; i
< pfb
->nr_cbufs
; i
++) {
237 struct pipe_resource
*surf
;
242 surf
= pfb
->cbufs
[i
]->texture
;
243 resource_written(ctx
, surf
);
246 /* Mark constant buffers as being read */
247 resource_read(ctx
, ctx
->constant_buffer
[PIPE_SHADER_VERTEX
].buffer
);
248 resource_read(ctx
, ctx
->constant_buffer
[PIPE_SHADER_FRAGMENT
].buffer
);
250 /* Mark VBOs as being read */
251 for (i
= 0; i
< ctx
->vertex_buffer
.count
; i
++) {
252 assert(!ctx
->vertex_buffer
.vb
[i
].is_user_buffer
);
253 resource_read(ctx
, ctx
->vertex_buffer
.vb
[i
].buffer
.resource
);
256 /* Mark index buffer as being read */
257 resource_read(ctx
, indexbuf
);
259 /* Mark textures as being read */
260 for (i
= 0; i
< PIPE_MAX_SAMPLERS
; i
++)
261 if (ctx
->sampler_view
[i
])
262 resource_read(ctx
, ctx
->sampler_view
[i
]->texture
);
264 list_for_each_entry(struct etna_hw_query
, hq
, &ctx
->active_hw_queries
, node
)
265 resource_written(ctx
, hq
->prsc
);
267 ctx
->stats
.prims_emitted
+= u_reduced_prims_for_vertices(info
->mode
, info
->count
);
268 ctx
->stats
.draw_calls
++;
270 /* Update state for this draw operation */
271 etna_update_state_for_draw(ctx
, info
);
273 /* First, sync state, then emit DRAW_PRIMITIVES or DRAW_INDEXED_PRIMITIVES */
274 etna_emit_state(ctx
);
276 if (info
->index_size
)
277 etna_draw_indexed_primitives(ctx
->stream
, draw_mode
, info
->start
, prims
, info
->index_bias
);
279 etna_draw_primitives(ctx
->stream
, draw_mode
, info
->start
, prims
);
281 if (DBG_ENABLED(ETNA_DBG_DRAW_STALL
)) {
282 /* Stall the FE after every draw operation. This allows better
283 * debug of GPU hang conditions, as the FE will indicate which
284 * draw op has caused the hang. */
285 etna_stall(ctx
->stream
, SYNC_RECIPIENT_FE
, SYNC_RECIPIENT_PE
);
288 if (DBG_ENABLED(ETNA_DBG_FLUSH_ALL
))
289 pctx
->flush(pctx
, NULL
, 0);
291 if (ctx
->framebuffer
.cbuf
)
292 etna_resource(ctx
->framebuffer
.cbuf
->texture
)->seqno
++;
293 if (ctx
->framebuffer
.zsbuf
)
294 etna_resource(ctx
->framebuffer
.zsbuf
->texture
)->seqno
++;
295 if (info
->index_size
&& indexbuf
!= info
->index
.resource
)
296 pipe_resource_reference(&indexbuf
, NULL
);
300 etna_flush(struct pipe_context
*pctx
, struct pipe_fence_handle
**fence
,
301 enum pipe_flush_flags flags
)
303 struct etna_context
*ctx
= etna_context(pctx
);
304 int out_fence_fd
= -1;
306 list_for_each_entry(struct etna_hw_query
, hq
, &ctx
->active_hw_queries
, node
)
307 etna_hw_query_suspend(hq
, ctx
);
309 etna_cmd_stream_flush2(ctx
->stream
, ctx
->in_fence_fd
,
310 (flags
& PIPE_FLUSH_FENCE_FD
) ? &out_fence_fd
:
313 list_for_each_entry(struct etna_hw_query
, hq
, &ctx
->active_hw_queries
, node
)
314 etna_hw_query_resume(hq
, ctx
);
317 *fence
= etna_fence_create(pctx
, out_fence_fd
);
321 etna_cmd_stream_reset_notify(struct etna_cmd_stream
*stream
, void *priv
)
323 struct etna_context
*ctx
= priv
;
324 struct etna_resource
*rsc
, *rsc_tmp
;
326 etna_set_state(stream
, VIVS_GL_API_MODE
, VIVS_GL_API_MODE_OPENGL
);
327 etna_set_state(stream
, VIVS_GL_VERTEX_ELEMENT_CONFIG
, 0x00000001);
328 etna_set_state(stream
, VIVS_RA_EARLY_DEPTH
, 0x00000031);
329 etna_set_state(stream
, VIVS_PA_W_CLIP_LIMIT
, 0x34000001);
330 etna_set_state(stream
, VIVS_PA_FLAGS
, 0x00000000); /* blob sets ZCONVERT_BYPASS on GC3000, this messes up z for us */
331 etna_set_state(stream
, VIVS_RA_UNK00E0C
, 0x00000000);
332 etna_set_state(stream
, VIVS_PA_VIEWPORT_UNK00A80
, 0x38a01404);
333 etna_set_state(stream
, VIVS_PA_VIEWPORT_UNK00A84
, fui(8192.0));
334 etna_set_state(stream
, VIVS_PA_ZFARCLIPPING
, 0x00000000);
335 etna_set_state(stream
, VIVS_PE_ALPHA_COLOR_EXT0
, 0x00000000);
336 etna_set_state(stream
, VIVS_PE_ALPHA_COLOR_EXT1
, 0x00000000);
337 etna_set_state(stream
, VIVS_RA_HDEPTH_CONTROL
, 0x00007000);
338 etna_set_state(stream
, VIVS_PE_STENCIL_CONFIG_EXT2
, 0x00000000);
339 etna_set_state(stream
, VIVS_GL_UNK03834
, 0x00000000);
340 etna_set_state(stream
, VIVS_GL_UNK03838
, 0x00000000);
341 etna_set_state(stream
, VIVS_GL_UNK03854
, 0x00000000);
342 etna_set_state(stream
, VIVS_PS_CONTROL_EXT
, 0x00000000);
344 /* Enable SINGLE_BUFFER for resolve, if supported */
345 etna_set_state(stream
, VIVS_RS_SINGLE_BUFFER
, COND(ctx
->specs
.single_buffer
, VIVS_RS_SINGLE_BUFFER_ENABLE
));
349 /* go through all the used resources and clear their status flag */
350 LIST_FOR_EACH_ENTRY_SAFE(rsc
, rsc_tmp
, &ctx
->used_resources
, list
)
352 debug_assert(rsc
->status
!= 0);
354 rsc
->pending_ctx
= NULL
;
355 list_delinit(&rsc
->list
);
358 assert(LIST_IS_EMPTY(&ctx
->used_resources
));
362 etna_set_debug_callback(struct pipe_context
*pctx
,
363 const struct pipe_debug_callback
*cb
)
365 struct etna_context
*ctx
= etna_context(pctx
);
370 memset(&ctx
->debug
, 0, sizeof(ctx
->debug
));
373 struct pipe_context
*
374 etna_context_create(struct pipe_screen
*pscreen
, void *priv
, unsigned flags
)
376 struct etna_context
*ctx
= CALLOC_STRUCT(etna_context
);
377 struct etna_screen
*screen
;
378 struct pipe_context
*pctx
;
385 pctx
->screen
= pscreen
;
386 pctx
->stream_uploader
= u_upload_create_default(pctx
);
387 if (!pctx
->stream_uploader
)
389 pctx
->const_uploader
= pctx
->stream_uploader
;
391 screen
= etna_screen(pscreen
);
392 ctx
->stream
= etna_cmd_stream_new(screen
->pipe
, 0x2000, &etna_cmd_stream_reset_notify
, ctx
);
393 if (ctx
->stream
== NULL
)
396 /* context ctxate setup */
397 ctx
->specs
= screen
->specs
;
398 ctx
->screen
= screen
;
399 /* need some sane default in case state tracker doesn't set some state: */
400 ctx
->sample_mask
= 0xffff;
402 list_inithead(&ctx
->used_resources
);
404 /* Set sensible defaults for state */
405 etna_cmd_stream_reset_notify(ctx
->stream
, ctx
);
407 ctx
->in_fence_fd
= -1;
409 pctx
->destroy
= etna_context_destroy
;
410 pctx
->draw_vbo
= etna_draw_vbo
;
411 pctx
->flush
= etna_flush
;
412 pctx
->set_debug_callback
= etna_set_debug_callback
;
413 pctx
->create_fence_fd
= etna_create_fence_fd
;
414 pctx
->fence_server_sync
= etna_fence_server_sync
;
416 /* creation of compile states */
417 pctx
->create_blend_state
= etna_blend_state_create
;
418 pctx
->create_rasterizer_state
= etna_rasterizer_state_create
;
419 pctx
->create_depth_stencil_alpha_state
= etna_zsa_state_create
;
421 etna_clear_blit_init(pctx
);
422 etna_query_context_init(pctx
);
423 etna_state_init(pctx
);
424 etna_surface_init(pctx
);
425 etna_shader_init(pctx
);
426 etna_texture_init(pctx
);
427 etna_transfer_init(pctx
);
429 ctx
->blitter
= util_blitter_create(pctx
);
433 /* Generate the bitmask of supported draw primitives. */
434 ctx
->prim_hwsupport
= 1 << PIPE_PRIM_POINTS
|
435 1 << PIPE_PRIM_LINES
|
436 1 << PIPE_PRIM_LINE_STRIP
|
437 1 << PIPE_PRIM_TRIANGLES
|
438 1 << PIPE_PRIM_TRIANGLE_STRIP
|
439 1 << PIPE_PRIM_TRIANGLE_FAN
;
441 if (VIV_FEATURE(ctx
->screen
, chipMinorFeatures2
, LINE_LOOP
))
442 ctx
->prim_hwsupport
|= 1 << PIPE_PRIM_LINE_LOOP
;
444 ctx
->primconvert
= util_primconvert_create(pctx
, ctx
->prim_hwsupport
);
445 if (!ctx
->primconvert
)
448 slab_create_child(&ctx
->transfer_pool
, &screen
->transfer_pool
);
449 list_inithead(&ctx
->active_hw_queries
);