etnaviv: move pctx initialisation to avoid a null dereference
[mesa.git] / src / gallium / drivers / etnaviv / etnaviv_context.c
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_context.h"
29
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_rasterizer.h"
38 #include "etnaviv_screen.h"
39 #include "etnaviv_shader.h"
40 #include "etnaviv_state.h"
41 #include "etnaviv_surface.h"
42 #include "etnaviv_texture.h"
43 #include "etnaviv_transfer.h"
44 #include "etnaviv_translate.h"
45 #include "etnaviv_zsa.h"
46
47 #include "pipe/p_context.h"
48 #include "pipe/p_state.h"
49 #include "util/u_blitter.h"
50 #include "util/u_memory.h"
51 #include "util/u_prim.h"
52 #include "util/u_upload_mgr.h"
53
54 #include "hw/common.xml.h"
55
56 static void
57 etna_context_destroy(struct pipe_context *pctx)
58 {
59 struct etna_context *ctx = etna_context(pctx);
60
61 if (ctx->primconvert)
62 util_primconvert_destroy(ctx->primconvert);
63
64 if (ctx->blitter)
65 util_blitter_destroy(ctx->blitter);
66
67 if (pctx->stream_uploader)
68 u_upload_destroy(pctx->stream_uploader);
69
70 if (ctx->stream)
71 etna_cmd_stream_del(ctx->stream);
72
73 slab_destroy_child(&ctx->transfer_pool);
74
75 FREE(pctx);
76 }
77
78 /* Update render state where needed based on draw operation */
79 static void
80 etna_update_state_for_draw(struct etna_context *ctx, const struct pipe_draw_info *info)
81 {
82 /* Handle primitive restart:
83 * - If not an indexed draw, we don't care about the state of the primitive restart bit.
84 * - Otherwise, set the bit in INDEX_STREAM_CONTROL in the index buffer state
85 * accordingly
86 * - If the value of the INDEX_STREAM_CONTROL register changed due to this, or
87 * primitive restart is enabled and the restart index changed, mark the index
88 * buffer state as dirty
89 */
90
91 if (info->indexed) {
92 uint32_t new_control = ctx->index_buffer.FE_INDEX_STREAM_CONTROL;
93
94 if (info->primitive_restart)
95 new_control |= VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART;
96 else
97 new_control &= ~VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART;
98
99 if (ctx->index_buffer.FE_INDEX_STREAM_CONTROL != new_control ||
100 (info->primitive_restart && ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX != info->restart_index)) {
101 ctx->index_buffer.FE_INDEX_STREAM_CONTROL = new_control;
102 ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX = info->restart_index;
103 ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER;
104 }
105 }
106 }
107
108
109 static void
110 etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
111 {
112 struct etna_context *ctx = etna_context(pctx);
113 struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s;
114 uint32_t draw_mode;
115 unsigned i;
116
117 if (ctx->vertex_elements == NULL || ctx->vertex_elements->num_elements == 0)
118 return; /* Nothing to do */
119
120 if (!(ctx->prim_hwsupport & (1 << info->mode))) {
121 struct primconvert_context *primconvert = ctx->primconvert;
122 util_primconvert_save_index_buffer(primconvert, &ctx->index_buffer.ib);
123 util_primconvert_save_rasterizer_state(primconvert, ctx->rasterizer);
124 util_primconvert_draw_vbo(primconvert, info);
125 return;
126 }
127
128 int prims = u_decomposed_prims_for_vertices(info->mode, info->count);
129 if (unlikely(prims <= 0)) {
130 DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode);
131 return;
132 }
133
134 draw_mode = translate_draw_mode(info->mode);
135 if (draw_mode == ETNA_NO_MATCH) {
136 BUG("Unsupported draw mode");
137 return;
138 }
139
140 if (info->indexed && !ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo) {
141 BUG("Unsupported or no index buffer");
142 return;
143 }
144
145 /* Update any derived state */
146 if (!etna_state_update(ctx))
147 return;
148
149 /*
150 * Figure out the buffers/features we need:
151 */
152 if (etna_depth_enabled(ctx))
153 resource_written(ctx, pfb->zsbuf->texture);
154
155 if (etna_stencil_enabled(ctx))
156 resource_written(ctx, pfb->zsbuf->texture);
157
158 for (i = 0; i < pfb->nr_cbufs; i++) {
159 struct pipe_resource *surf;
160
161 if (!pfb->cbufs[i])
162 continue;
163
164 surf = pfb->cbufs[i]->texture;
165 resource_written(ctx, surf);
166 }
167
168 /* Mark constant buffers as being read */
169 resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_VERTEX].buffer);
170 resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].buffer);
171
172 /* Mark VBOs as being read */
173 for (i = 0; i < ctx->vertex_buffer.count; i++) {
174 assert(!ctx->vertex_buffer.vb[i].user_buffer);
175 resource_read(ctx, ctx->vertex_buffer.vb[i].buffer);
176 }
177
178 /* Mark index buffer as being read */
179 resource_read(ctx, ctx->index_buffer.ib.buffer);
180
181 /* Mark textures as being read */
182 for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
183 if (ctx->sampler_view[i])
184 resource_read(ctx, ctx->sampler_view[i]->texture);
185
186 ctx->stats.prims_emitted += u_reduced_prims_for_vertices(info->mode, info->count);
187 ctx->stats.draw_calls++;
188
189 /* Update state for this draw operation */
190 etna_update_state_for_draw(ctx, info);
191
192 /* First, sync state, then emit DRAW_PRIMITIVES or DRAW_INDEXED_PRIMITIVES */
193 etna_emit_state(ctx);
194
195 if (info->indexed)
196 etna_draw_indexed_primitives(ctx->stream, draw_mode, info->start, prims, info->index_bias);
197 else
198 etna_draw_primitives(ctx->stream, draw_mode, info->start, prims);
199
200 if (DBG_ENABLED(ETNA_DBG_DRAW_STALL)) {
201 /* Stall the FE after every draw operation. This allows better
202 * debug of GPU hang conditions, as the FE will indicate which
203 * draw op has caused the hang. */
204 etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
205 }
206
207 if (DBG_ENABLED(ETNA_DBG_FLUSH_ALL))
208 pctx->flush(pctx, NULL, 0);
209
210 if (ctx->framebuffer.cbuf)
211 etna_resource(ctx->framebuffer.cbuf->texture)->seqno++;
212 if (ctx->framebuffer.zsbuf)
213 etna_resource(ctx->framebuffer.zsbuf->texture)->seqno++;
214 }
215
216 static void
217 etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
218 enum pipe_flush_flags flags)
219 {
220 struct etna_context *ctx = etna_context(pctx);
221
222 etna_cmd_stream_flush(ctx->stream);
223
224 if (fence)
225 *fence = etna_fence_create(pctx);
226 }
227
228 static void
229 etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
230 {
231 struct etna_context *ctx = priv;
232 struct etna_resource *rsc, *rsc_tmp;
233
234 etna_set_state(stream, VIVS_GL_API_MODE, VIVS_GL_API_MODE_OPENGL);
235 etna_set_state(stream, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x00000001);
236 etna_set_state(stream, VIVS_RA_EARLY_DEPTH, 0x00000031);
237 etna_set_state(stream, VIVS_PA_W_CLIP_LIMIT, 0x34000001);
238
239 ctx->dirty = ~0L;
240
241 /* go through all the used resources and clear their status flag */
242 LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list)
243 {
244 debug_assert(rsc->status != 0);
245 rsc->status = 0;
246 rsc->pending_ctx = NULL;
247 list_delinit(&rsc->list);
248 }
249
250 assert(LIST_IS_EMPTY(&ctx->used_resources));
251 }
252
253 static void
254 etna_set_debug_callback(struct pipe_context *pctx,
255 const struct pipe_debug_callback *cb)
256 {
257 struct etna_context *ctx = etna_context(pctx);
258
259 if (cb)
260 ctx->debug = *cb;
261 else
262 memset(&ctx->debug, 0, sizeof(ctx->debug));
263 }
264
265 struct pipe_context *
266 etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
267 {
268 struct etna_context *ctx = CALLOC_STRUCT(etna_context);
269 struct etna_screen *screen;
270 struct pipe_context *pctx;
271
272 if (ctx == NULL)
273 return NULL;
274
275 pctx = &ctx->base;
276 pctx->priv = ctx;
277 pctx->screen = pscreen;
278 pctx->stream_uploader = u_upload_create_default(pctx);
279 if (!pctx->stream_uploader)
280 goto fail;
281 pctx->const_uploader = pctx->stream_uploader;
282
283 screen = etna_screen(pscreen);
284 ctx->stream = etna_cmd_stream_new(screen->pipe, 0x2000, &etna_cmd_stream_reset_notify, ctx);
285 if (ctx->stream == NULL)
286 goto fail;
287
288 /* context ctxate setup */
289 ctx->specs = screen->specs;
290 ctx->screen = screen;
291 /* need some sane default in case state tracker doesn't set some state: */
292 ctx->sample_mask = 0xffff;
293
294 list_inithead(&ctx->used_resources);
295
296 /* Set sensible defaults for state */
297 etna_cmd_stream_reset_notify(ctx->stream, ctx);
298
299 pctx->destroy = etna_context_destroy;
300 pctx->draw_vbo = etna_draw_vbo;
301 pctx->flush = etna_flush;
302 pctx->set_debug_callback = etna_set_debug_callback;
303
304 /* creation of compile states */
305 pctx->create_blend_state = etna_blend_state_create;
306 pctx->create_rasterizer_state = etna_rasterizer_state_create;
307 pctx->create_depth_stencil_alpha_state = etna_zsa_state_create;
308
309 etna_clear_blit_init(pctx);
310 etna_query_context_init(pctx);
311 etna_state_init(pctx);
312 etna_surface_init(pctx);
313 etna_shader_init(pctx);
314 etna_texture_init(pctx);
315 etna_transfer_init(pctx);
316
317 ctx->blitter = util_blitter_create(pctx);
318 if (!ctx->blitter)
319 goto fail;
320
321 /* Generate the bitmask of supported draw primitives. */
322 ctx->prim_hwsupport = 1 << PIPE_PRIM_POINTS |
323 1 << PIPE_PRIM_LINES |
324 1 << PIPE_PRIM_LINE_STRIP |
325 1 << PIPE_PRIM_TRIANGLES |
326 1 << PIPE_PRIM_TRIANGLE_STRIP |
327 1 << PIPE_PRIM_TRIANGLE_FAN;
328
329 if (VIV_FEATURE(ctx->screen, chipMinorFeatures2, LINE_LOOP))
330 ctx->prim_hwsupport |= 1 << PIPE_PRIM_LINE_LOOP;
331
332 ctx->primconvert = util_primconvert_create(pctx, ctx->prim_hwsupport);
333 if (!ctx->primconvert)
334 goto fail;
335
336 slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
337
338 return pctx;
339
340 fail:
341 pctx->destroy(pctx);
342
343 return NULL;
344 }