gallium: Avoid void pointer arithmetic.
[mesa.git] / src / gallium / drivers / r300 / r300_context.c
1 /*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * 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 AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #include "draw/draw_context.h"
24
25 #include "util/u_memory.h"
26 #include "util/u_sampler.h"
27 #include "util/u_simple_list.h"
28 #include "util/u_upload_mgr.h"
29
30 #include "r300_cb.h"
31 #include "r300_context.h"
32 #include "r300_emit.h"
33 #include "r300_screen.h"
34 #include "r300_screen_buffer.h"
35 #include "r300_winsys.h"
36
37 #include <inttypes.h>
38
39 static void r300_update_num_contexts(struct r300_screen *r300screen,
40 int diff)
41 {
42 if (diff > 0) {
43 p_atomic_inc(&r300screen->num_contexts);
44
45 if (r300screen->num_contexts > 1)
46 util_mempool_set_thread_safety(&r300screen->pool_buffers,
47 UTIL_MEMPOOL_MULTITHREADED);
48 } else {
49 p_atomic_dec(&r300screen->num_contexts);
50
51 if (r300screen->num_contexts <= 1)
52 util_mempool_set_thread_safety(&r300screen->pool_buffers,
53 UTIL_MEMPOOL_SINGLETHREADED);
54 }
55 }
56
57 static void r300_release_referenced_objects(struct r300_context *r300)
58 {
59 struct pipe_framebuffer_state *fb =
60 (struct pipe_framebuffer_state*)r300->fb_state.state;
61 struct r300_textures_state *textures =
62 (struct r300_textures_state*)r300->textures_state.state;
63 struct r300_query *query, *temp;
64 unsigned i;
65
66 /* Framebuffer state. */
67 util_assign_framebuffer_state(fb, NULL);
68
69 /* Textures. */
70 for (i = 0; i < textures->sampler_view_count; i++)
71 pipe_sampler_view_reference(
72 (struct pipe_sampler_view**)&textures->sampler_views[i], NULL);
73
74 /* The special dummy texture for texkill. */
75 if (r300->texkill_sampler) {
76 pipe_sampler_view_reference(
77 (struct pipe_sampler_view**)&r300->texkill_sampler,
78 NULL);
79 }
80
81 /* The SWTCL VBO. */
82 pipe_resource_reference(&r300->vbo, NULL);
83
84 /* Vertex buffers. */
85 for (i = 0; i < r300->vertex_buffer_count; i++) {
86 pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL);
87 }
88
89 /* If there are any queries pending or not destroyed, remove them now. */
90 foreach_s(query, temp, &r300->query_list) {
91 remove_from_list(query);
92 FREE(query);
93 }
94 }
95
96 static void r300_destroy_context(struct pipe_context* context)
97 {
98 struct r300_context* r300 = r300_context(context);
99 struct r300_atom *atom;
100
101 util_blitter_destroy(r300->blitter);
102 draw_destroy(r300->draw);
103
104 /* Print stats, if enabled. */
105 if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) {
106 fprintf(stderr, "r300: Stats for context %p:\n", r300);
107 fprintf(stderr, " : Flushes: %" PRIu64 "\n", r300->flush_counter);
108 foreach(atom, &r300->atom_list) {
109 fprintf(stderr, " : %s: %" PRIu64 " emits\n",
110 atom->name, atom->counter);
111 }
112 }
113
114 u_upload_destroy(r300->upload_vb);
115 u_upload_destroy(r300->upload_ib);
116
117 translate_cache_destroy(r300->tran.translate_cache);
118
119 r300_release_referenced_objects(r300);
120
121 r300->rws->cs_destroy(r300->cs);
122
123 util_mempool_destroy(&r300->pool_transfers);
124
125 r300_update_num_contexts(r300->screen, -1);
126
127 FREE(r300->aa_state.state);
128 FREE(r300->blend_color_state.state);
129 FREE(r300->clip_state.state);
130 FREE(r300->fb_state.state);
131 FREE(r300->gpu_flush.state);
132 FREE(r300->hyperz_state.state);
133 FREE(r300->invariant_state.state);
134 FREE(r300->rs_block_state.state);
135 FREE(r300->scissor_state.state);
136 FREE(r300->textures_state.state);
137 FREE(r300->vap_invariant_state.state);
138 FREE(r300->viewport_state.state);
139 FREE(r300->ztop_state.state);
140 FREE(r300->fs_constants.state);
141 FREE(r300->vs_constants.state);
142 if (!r300->screen->caps.has_tcl) {
143 FREE(r300->vertex_stream_state.state);
144 }
145 FREE(r300);
146 }
147
148 void r300_flush_cb(void *data)
149 {
150 struct r300_context* const cs_context_copy = data;
151
152 cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL);
153 }
154
155 #define R300_INIT_ATOM(atomname, atomsize) \
156 r300->atomname.name = #atomname; \
157 r300->atomname.state = NULL; \
158 r300->atomname.size = atomsize; \
159 r300->atomname.emit = r300_emit_##atomname; \
160 r300->atomname.dirty = FALSE; \
161 insert_at_tail(&r300->atom_list, &r300->atomname);
162
163 static void r300_setup_atoms(struct r300_context* r300)
164 {
165 boolean is_rv350 = r300->screen->caps.is_rv350;
166 boolean is_r500 = r300->screen->caps.is_r500;
167 boolean has_tcl = r300->screen->caps.has_tcl;
168 boolean drm_2_3_0 = r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
169
170 /* Create the actual atom list.
171 *
172 * Each atom is examined and emitted in the order it appears here, which
173 * can affect performance and conformance if not handled with care.
174 *
175 * Some atoms never change size, others change every emit - those have
176 * the size of 0 here.
177 *
178 * NOTE: The framebuffer state is split into these atoms:
179 * - gpu_flush (unpipelined regs)
180 * - aa_state (unpipelined regs)
181 * - fb_state (unpipelined regs)
182 * - hyperz_state (unpipelined regs followed by pipelined ones)
183 * - fb_state_pipelined (pipelined regs)
184 * The motivation behind this is to be able to emit a strict
185 * subset of the regs, and to have reasonable register ordering. */
186 make_empty_list(&r300->atom_list);
187 /* SC, GB (unpipelined), RB3D (unpipelined), ZB (unpipelined). */
188 R300_INIT_ATOM(gpu_flush, 9);
189 R300_INIT_ATOM(aa_state, 4);
190 R300_INIT_ATOM(fb_state, 0);
191 /* ZB (unpipelined), SC. */
192 R300_INIT_ATOM(hyperz_state, 6);
193 R300_INIT_ATOM(ztop_state, 2);
194 /* ZB, FG. */
195 R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6);
196 /* RB3D. */
197 R300_INIT_ATOM(blend_state, 8);
198 R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2);
199 /* SC. */
200 R300_INIT_ATOM(scissor_state, 3);
201 /* GB, FG, GA, SU, SC, RB3D. */
202 R300_INIT_ATOM(invariant_state, 16 + (is_rv350 ? 4 : 0));
203 /* VAP. */
204 R300_INIT_ATOM(viewport_state, 9);
205 R300_INIT_ATOM(pvs_flush, 2);
206 R300_INIT_ATOM(vap_invariant_state, 9);
207 R300_INIT_ATOM(vertex_stream_state, 0);
208 R300_INIT_ATOM(vs_state, 0);
209 R300_INIT_ATOM(vs_constants, 0);
210 R300_INIT_ATOM(clip_state, has_tcl ? 5 + (6 * 4) : 2);
211 /* VAP, RS, GA, GB, SU, SC. */
212 R300_INIT_ATOM(rs_block_state, 0);
213 R300_INIT_ATOM(rs_state, 0);
214 /* SC, US. */
215 R300_INIT_ATOM(fb_state_pipelined, 5 + (drm_2_3_0 ? 3 : 0));
216 /* US. */
217 R300_INIT_ATOM(fs, 0);
218 R300_INIT_ATOM(fs_rc_constant_state, 0);
219 R300_INIT_ATOM(fs_constants, 0);
220 /* TX. */
221 R300_INIT_ATOM(texture_cache_inval, 2);
222 R300_INIT_ATOM(textures_state, 0);
223 /* ZB (unpipelined), SU. */
224 R300_INIT_ATOM(query_start, 4);
225
226 /* Replace emission functions for r500. */
227 if (is_r500) {
228 r300->fs.emit = r500_emit_fs;
229 r300->fs_rc_constant_state.emit = r500_emit_fs_rc_constant_state;
230 r300->fs_constants.emit = r500_emit_fs_constants;
231 }
232
233 /* Some non-CSO atoms need explicit space to store the state locally. */
234 r300->aa_state.state = CALLOC_STRUCT(r300_aa_state);
235 r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state);
236 r300->clip_state.state = CALLOC_STRUCT(r300_clip_state);
237 r300->fb_state.state = CALLOC_STRUCT(pipe_framebuffer_state);
238 r300->gpu_flush.state = CALLOC_STRUCT(pipe_framebuffer_state);
239 r300->hyperz_state.state = CALLOC_STRUCT(r300_hyperz_state);
240 r300->invariant_state.state = CALLOC_STRUCT(r300_invariant_state);
241 r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block);
242 r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state);
243 r300->textures_state.state = CALLOC_STRUCT(r300_textures_state);
244 r300->vap_invariant_state.state = CALLOC_STRUCT(r300_vap_invariant_state);
245 r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state);
246 r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state);
247 r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
248 r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer);
249 if (!r300->screen->caps.has_tcl) {
250 r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state);
251 }
252
253 /* Some non-CSO atoms don't use the state pointer. */
254 r300->fb_state_pipelined.allow_null_state = TRUE;
255 r300->fs_rc_constant_state.allow_null_state = TRUE;
256 r300->pvs_flush.allow_null_state = TRUE;
257 r300->query_start.allow_null_state = TRUE;
258 r300->texture_cache_inval.allow_null_state = TRUE;
259
260 /* Some states must be marked as dirty here to properly set up
261 * hardware in the first command stream. */
262 r300->invariant_state.dirty = TRUE;
263 r300->pvs_flush.dirty = TRUE;
264 r300->vap_invariant_state.dirty = TRUE;
265 r300->texture_cache_inval.dirty = TRUE;
266 r300->textures_state.dirty = TRUE;
267 }
268
269 /* Not every state tracker calls every driver function before the first draw
270 * call and we must initialize the command buffers somehow. */
271 static void r300_init_states(struct pipe_context *pipe)
272 {
273 struct r300_context *r300 = r300_context(pipe);
274 struct pipe_blend_color bc = {{0}};
275 struct pipe_clip_state cs = {{{0}}};
276 struct pipe_scissor_state ss = {0};
277 struct r300_clip_state *clip =
278 (struct r300_clip_state*)r300->clip_state.state;
279 struct r300_gpu_flush *gpuflush =
280 (struct r300_gpu_flush*)r300->gpu_flush.state;
281 struct r300_vap_invariant_state *vap_invariant =
282 (struct r300_vap_invariant_state*)r300->vap_invariant_state.state;
283 struct r300_invariant_state *invariant =
284 (struct r300_invariant_state*)r300->invariant_state.state;
285 struct r300_hyperz_state *hyperz =
286 (struct r300_hyperz_state*)r300->hyperz_state.state;
287 CB_LOCALS;
288
289 pipe->set_blend_color(pipe, &bc);
290 pipe->set_scissor_state(pipe, &ss);
291
292 /* Initialize the clip state. */
293 if (r300_context(pipe)->screen->caps.has_tcl) {
294 pipe->set_clip_state(pipe, &cs);
295 } else {
296 BEGIN_CB(clip->cb, 2);
297 OUT_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
298 END_CB;
299 }
300
301 /* Initialize the GPU flush. */
302 {
303 BEGIN_CB(gpuflush->cb_flush_clean, 6);
304
305 /* Flush and free renderbuffer caches. */
306 OUT_CB_REG(R300_RB3D_DSTCACHE_CTLSTAT,
307 R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
308 R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
309 OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT,
310 R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
311 R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);
312
313 /* Wait until the GPU is idle.
314 * This fixes random pixels sometimes appearing probably caused
315 * by incomplete rendering. */
316 OUT_CB_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
317 END_CB;
318 }
319
320 /* Initialize the VAP invariant state. */
321 {
322 BEGIN_CB(vap_invariant->cb, 9);
323 OUT_CB_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff);
324 OUT_CB_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4);
325 OUT_CB_32F(1.0);
326 OUT_CB_32F(1.0);
327 OUT_CB_32F(1.0);
328 OUT_CB_32F(1.0);
329 OUT_CB_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO);
330 END_CB;
331 }
332
333 /* Initialize the invariant state. */
334 {
335 BEGIN_CB(invariant->cb, r300->invariant_state.size);
336 OUT_CB_REG(R300_GB_SELECT, 0);
337 OUT_CB_REG(R300_FG_FOG_BLEND, 0);
338 OUT_CB_REG(R300_GA_ROUND_MODE, 1);
339 OUT_CB_REG(R300_GA_OFFSET, 0);
340 OUT_CB_REG(R300_SU_TEX_WRAP, 0);
341 OUT_CB_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF);
342 OUT_CB_REG(R300_SU_DEPTH_OFFSET, 0);
343 OUT_CB_REG(R300_SC_EDGERULE, 0x2DA49525);
344
345 if (r300->screen->caps.is_rv350) {
346 OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
347 OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
348 }
349 END_CB;
350 }
351
352 /* Initialize the hyperz state. */
353 {
354 BEGIN_CB(&hyperz->cb_begin, r300->hyperz_state.size);
355 OUT_CB_REG(R300_ZB_BW_CNTL, 0);
356 OUT_CB_REG(R300_ZB_DEPTHCLEARVALUE, 0);
357 OUT_CB_REG(R300_SC_HYPERZ, R300_SC_HYPERZ_ADJ_2);
358 END_CB;
359 }
360 }
361
362 struct pipe_context* r300_create_context(struct pipe_screen* screen,
363 void *priv)
364 {
365 struct r300_context* r300 = CALLOC_STRUCT(r300_context);
366 struct r300_screen* r300screen = r300_screen(screen);
367 struct r300_winsys_screen *rws = r300screen->rws;
368
369 if (!r300)
370 return NULL;
371
372 r300_update_num_contexts(r300screen, 1);
373
374 r300->rws = rws;
375 r300->screen = r300screen;
376
377 r300->context.winsys = (struct pipe_winsys*)rws;
378 r300->context.screen = screen;
379 r300->context.priv = priv;
380
381 r300->context.destroy = r300_destroy_context;
382
383 r300->cs = rws->cs_create(rws);
384
385 util_mempool_create(&r300->pool_transfers,
386 sizeof(struct pipe_transfer), 64,
387 UTIL_MEMPOOL_SINGLETHREADED);
388
389 if (!r300screen->caps.has_tcl) {
390 /* Create a Draw. This is used for SW TCL. */
391 r300->draw = draw_create(&r300->context);
392 /* Enable our renderer. */
393 draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300));
394 /* Enable Draw's clipping. */
395 draw_set_driver_clipping(r300->draw, FALSE);
396 /* Disable converting points/lines to triangles. */
397 draw_wide_line_threshold(r300->draw, 10000000.f);
398 draw_wide_point_threshold(r300->draw, 10000000.f);
399 }
400
401 r300_setup_atoms(r300);
402
403 make_empty_list(&r300->query_list);
404
405 r300_init_blit_functions(r300);
406 r300_init_flush_functions(r300);
407 r300_init_query_functions(r300);
408 r300_init_state_functions(r300);
409 r300_init_resource_functions(r300);
410
411 r300->blitter = util_blitter_create(&r300->context);
412
413 /* Render functions must be initialized after blitter. */
414 r300_init_render_functions(r300);
415
416 rws->cs_set_flush(r300->cs, r300_flush_cb, r300);
417
418 r300->upload_ib = u_upload_create(&r300->context,
419 32 * 1024, 16,
420 PIPE_BIND_INDEX_BUFFER);
421
422 if (r300->upload_ib == NULL)
423 goto no_upload_ib;
424
425 r300->upload_vb = u_upload_create(&r300->context,
426 128 * 1024, 16,
427 PIPE_BIND_VERTEX_BUFFER);
428 if (r300->upload_vb == NULL)
429 goto no_upload_vb;
430
431 r300->tran.translate_cache = translate_cache_create();
432
433 r300_init_states(&r300->context);
434
435 /* The KIL opcode needs the first texture unit to be enabled
436 * on r3xx-r4xx. In order to calm down the CS checker, we bind this
437 * dummy texture there. */
438 if (!r300->screen->caps.is_r500) {
439 struct pipe_resource *tex;
440 struct pipe_resource rtempl = {{0}};
441 struct pipe_sampler_view vtempl = {{0}};
442
443 rtempl.target = PIPE_TEXTURE_2D;
444 rtempl.format = PIPE_FORMAT_I8_UNORM;
445 rtempl.bind = PIPE_BIND_SAMPLER_VIEW;
446 rtempl.width0 = 1;
447 rtempl.height0 = 1;
448 rtempl.depth0 = 1;
449 tex = screen->resource_create(screen, &rtempl);
450
451 u_sampler_view_default_template(&vtempl, tex, tex->format);
452
453 r300->texkill_sampler = (struct r300_sampler_view*)
454 r300->context.create_sampler_view(&r300->context, tex, &vtempl);
455
456 pipe_resource_reference(&tex, NULL);
457 }
458
459 return &r300->context;
460
461 no_upload_ib:
462 u_upload_destroy(r300->upload_ib);
463 no_upload_vb:
464 FREE(r300);
465 return NULL;
466 }
467
468 void r300_finish(struct r300_context *r300)
469 {
470 struct pipe_framebuffer_state *fb;
471 unsigned i;
472
473 /* This is a preliminary implementation of glFinish.
474 *
475 * The ideal implementation should use something like EmitIrqLocked and
476 * WaitIrq, or better, real fences.
477 */
478 if (r300->fb_state.state) {
479 fb = r300->fb_state.state;
480
481 for (i = 0; i < fb->nr_cbufs; i++) {
482 if (fb->cbufs[i]->texture) {
483 r300->rws->buffer_wait(r300->rws,
484 r300_texture(fb->cbufs[i]->texture)->buffer);
485 return;
486 }
487 }
488 if (fb->zsbuf && fb->zsbuf->texture) {
489 r300->rws->buffer_wait(r300->rws,
490 r300_texture(fb->zsbuf->texture)->buffer);
491 }
492 }
493 }