llvmpipe: rename texture refs to resource refs
[mesa.git] / src / gallium / drivers / llvmpipe / lp_scene.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "util/u_math.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_simple_list.h"
32 #include "util/u_surface.h"
33 #include "lp_scene.h"
34 #include "lp_scene_queue.h"
35 #include "lp_debug.h"
36
37
38 /** List of texture references */
39 struct texture_ref {
40 struct pipe_resource *texture;
41 struct texture_ref *prev, *next; /**< linked list w/ u_simple_list.h */
42 };
43
44
45
46 struct lp_scene *
47 lp_scene_create( struct pipe_context *pipe,
48 struct lp_scene_queue *queue )
49 {
50 unsigned i, j;
51 struct lp_scene *scene = CALLOC_STRUCT(lp_scene);
52 if (!scene)
53 return NULL;
54
55 scene->pipe = pipe;
56 scene->empty_queue = queue;
57
58 for (i = 0; i < TILES_X; i++) {
59 for (j = 0; j < TILES_Y; j++) {
60 struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
61 bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block);
62 }
63 }
64
65 scene->data.head =
66 scene->data.tail = CALLOC_STRUCT(data_block);
67
68 make_empty_list(&scene->resources);
69
70 pipe_mutex_init(scene->mutex);
71
72 return scene;
73 }
74
75
76 /**
77 * Free all data associated with the given scene, and free(scene).
78 */
79 void
80 lp_scene_destroy(struct lp_scene *scene)
81 {
82 unsigned i, j;
83
84 lp_scene_reset(scene);
85
86 for (i = 0; i < TILES_X; i++)
87 for (j = 0; j < TILES_Y; j++) {
88 struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
89 assert(bin->commands.head == bin->commands.tail);
90 FREE(bin->commands.head);
91 bin->commands.head = NULL;
92 bin->commands.tail = NULL;
93 }
94
95 FREE(scene->data.head);
96 scene->data.head = NULL;
97
98 pipe_mutex_destroy(scene->mutex);
99
100 FREE(scene);
101 }
102
103
104 /**
105 * Check if the scene's bins are all empty.
106 * For debugging purposes.
107 */
108 boolean
109 lp_scene_is_empty(struct lp_scene *scene )
110 {
111 unsigned x, y;
112
113 for (y = 0; y < TILES_Y; y++) {
114 for (x = 0; x < TILES_X; x++) {
115 const struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
116 const struct cmd_block_list *list = &bin->commands;
117 if (list->head != list->tail || list->head->count > 0) {
118 return FALSE;
119 }
120 }
121 }
122 return TRUE;
123 }
124
125
126 /* Free data for one particular bin. May be called from the
127 * rasterizer thread(s).
128 */
129 void
130 lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y)
131 {
132 struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
133 struct cmd_block_list *list = &bin->commands;
134 struct cmd_block *block;
135 struct cmd_block *tmp;
136
137 assert(x < TILES_X);
138 assert(y < TILES_Y);
139
140 for (block = list->head; block != list->tail; block = tmp) {
141 tmp = block->next;
142 FREE(block);
143 }
144
145 assert(list->tail->next == NULL);
146 list->head = list->tail;
147 list->head->count = 0;
148 }
149
150
151 /**
152 * Free all the temporary data in a scene. May be called from the
153 * rasterizer thread(s).
154 */
155 void
156 lp_scene_reset(struct lp_scene *scene )
157 {
158 unsigned i, j;
159
160 /* Free all but last binner command lists:
161 */
162 for (i = 0; i < scene->tiles_x; i++) {
163 for (j = 0; j < scene->tiles_y; j++) {
164 lp_scene_bin_reset(scene, i, j);
165 }
166 }
167
168 assert(lp_scene_is_empty(scene));
169
170 /* Free all but last binned data block:
171 */
172 {
173 struct data_block_list *list = &scene->data;
174 struct data_block *block, *tmp;
175
176 for (block = list->head; block != list->tail; block = tmp) {
177 tmp = block->next;
178 FREE(block);
179 }
180
181 assert(list->tail->next == NULL);
182 list->head = list->tail;
183 list->head->used = 0;
184 }
185
186 /* Release texture refs
187 */
188 {
189 struct resource_ref *ref, *next, *ref_list = &scene->resources;
190 for (ref = ref_list->next; ref != ref_list; ref = next) {
191 next = next_elem(ref);
192 pipe_resource_reference(&ref->resource, NULL);
193 FREE(ref);
194 }
195 make_empty_list(ref_list);
196 }
197
198 scene->has_color_clear = FALSE;
199 scene->has_depth_clear = FALSE;
200 }
201
202
203
204
205
206
207 void
208 lp_bin_new_cmd_block( struct cmd_block_list *list )
209 {
210 struct cmd_block *block = MALLOC_STRUCT(cmd_block);
211 list->tail->next = block;
212 list->tail = block;
213 block->next = NULL;
214 block->count = 0;
215 }
216
217
218 void
219 lp_bin_new_data_block( struct data_block_list *list )
220 {
221 struct data_block *block = MALLOC_STRUCT(data_block);
222 list->tail->next = block;
223 list->tail = block;
224 block->next = NULL;
225 block->used = 0;
226 }
227
228
229 /** Return number of bytes used for all bin data within a scene */
230 unsigned
231 lp_scene_data_size( const struct lp_scene *scene )
232 {
233 unsigned size = 0;
234 const struct data_block *block;
235 for (block = scene->data.head; block; block = block->next) {
236 size += block->used;
237 }
238 return size;
239 }
240
241
242 /** Return number of bytes used for a single bin */
243 unsigned
244 lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y )
245 {
246 struct cmd_bin *bin = lp_scene_get_bin((struct lp_scene *) scene, x, y);
247 const struct cmd_block *cmd;
248 unsigned size = 0;
249 for (cmd = bin->commands.head; cmd; cmd = cmd->next) {
250 size += (cmd->count *
251 (sizeof(lp_rast_cmd) + sizeof(union lp_rast_cmd_arg)));
252 }
253 return size;
254 }
255
256
257 /**
258 * Add a reference to a resource by the scene.
259 */
260 void
261 lp_scene_add_resource_reference(struct lp_scene *scene,
262 struct pipe_resource *resource)
263 {
264 struct resource_ref *ref = CALLOC_STRUCT(resource_ref);
265 if (ref) {
266 struct resource_ref *ref_list = &scene->resources;
267 pipe_resource_reference(&ref->resource, resource);
268 insert_at_tail(ref_list, ref);
269 }
270 }
271
272
273 /**
274 * Does this scene have a reference to the given resource?
275 */
276 boolean
277 lp_scene_is_resource_referenced(const struct lp_scene *scene,
278 const struct pipe_resource *resource)
279 {
280 const struct resource_ref *ref_list = &scene->resources;
281 const struct resource_ref *ref;
282 foreach (ref, ref_list) {
283 if (ref->resource == resource)
284 return TRUE;
285 }
286 return FALSE;
287 }
288
289
290 /**
291 * Return last command in the bin
292 */
293 static lp_rast_cmd
294 lp_get_last_command( const struct cmd_bin *bin )
295 {
296 const struct cmd_block *tail = bin->commands.tail;
297 const unsigned i = tail->count;
298 if (i > 0)
299 return tail->cmd[i - 1];
300 else
301 return NULL;
302 }
303
304
305 /**
306 * Replace the arg of the last command in the bin.
307 */
308 static void
309 lp_replace_last_command_arg( struct cmd_bin *bin,
310 const union lp_rast_cmd_arg arg )
311 {
312 struct cmd_block *tail = bin->commands.tail;
313 const unsigned i = tail->count;
314 assert(i > 0);
315 tail->arg[i - 1] = arg;
316 }
317
318
319
320 /**
321 * Put a state-change command into all bins.
322 * If we find that the last command in a bin was also a state-change
323 * command, we can simply replace that one with the new one.
324 */
325 void
326 lp_scene_bin_state_command( struct lp_scene *scene,
327 lp_rast_cmd cmd,
328 const union lp_rast_cmd_arg arg )
329 {
330 unsigned i, j;
331 for (i = 0; i < scene->tiles_x; i++) {
332 for (j = 0; j < scene->tiles_y; j++) {
333 struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
334 lp_rast_cmd last_cmd = lp_get_last_command(bin);
335 if (last_cmd == cmd) {
336 lp_replace_last_command_arg(bin, arg);
337 }
338 else {
339 lp_scene_bin_command( scene, i, j, cmd, arg );
340 }
341 }
342 }
343 }
344
345
346 /** advance curr_x,y to the next bin */
347 static boolean
348 next_bin(struct lp_scene *scene)
349 {
350 scene->curr_x++;
351 if (scene->curr_x >= scene->tiles_x) {
352 scene->curr_x = 0;
353 scene->curr_y++;
354 }
355 if (scene->curr_y >= scene->tiles_y) {
356 /* no more bins */
357 return FALSE;
358 }
359 return TRUE;
360 }
361
362
363 void
364 lp_scene_bin_iter_begin( struct lp_scene *scene )
365 {
366 scene->curr_x = scene->curr_y = -1;
367 }
368
369
370 /**
371 * Return pointer to next bin to be rendered.
372 * The lp_scene::curr_x and ::curr_y fields will be advanced.
373 * Multiple rendering threads will call this function to get a chunk
374 * of work (a bin) to work on.
375 */
376 struct cmd_bin *
377 lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y )
378 {
379 struct cmd_bin *bin = NULL;
380
381 pipe_mutex_lock(scene->mutex);
382
383 if (scene->curr_x < 0) {
384 /* first bin */
385 scene->curr_x = 0;
386 scene->curr_y = 0;
387 }
388 else if (!next_bin(scene)) {
389 /* no more bins left */
390 goto end;
391 }
392
393 bin = lp_scene_get_bin(scene, scene->curr_x, scene->curr_y);
394 *bin_x = scene->curr_x;
395 *bin_y = scene->curr_y;
396
397 end:
398 /*printf("return bin %p at %d, %d\n", (void *) bin, *bin_x, *bin_y);*/
399 pipe_mutex_unlock(scene->mutex);
400 return bin;
401 }
402
403
404
405 /**
406 * Prepare this scene for the rasterizer.
407 * Map the framebuffer surfaces. Initialize the 'rast' state.
408 */
409 static boolean
410 lp_scene_map_buffers( struct lp_scene *scene )
411 {
412 LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
413
414 /* XXX framebuffer surfaces are no longer mapped here */
415 /* XXX move all map/unmap stuff into rast module... */
416
417 return TRUE;
418 }
419
420
421
422 /**
423 * Called after rasterizer as finished rasterizing a scene.
424 *
425 * We want to call this from the pipe_context's current thread to
426 * avoid having to have mutexes on the transfer functions.
427 */
428 static void
429 lp_scene_unmap_buffers( struct lp_scene *scene )
430 {
431 #if 0
432 unsigned i;
433
434 for (i = 0; i < scene->fb.nr_cbufs; i++) {
435 if (scene->cbuf_map[i]) {
436 struct pipe_surface *cbuf = scene->fb.cbufs[i];
437 llvmpipe_resource_unmap(cbuf->texture,
438 cbuf->face,
439 cbuf->level,
440 cbuf->zslice);
441 scene->cbuf_map[i] = NULL;
442 }
443 }
444
445 if (scene->zsbuf_map) {
446 struct pipe_surface *zsbuf = scene->fb.zsbuf;
447 llvmpipe_resource_unmap(zsbuf->texture,
448 zsbuf->face,
449 zsbuf->level,
450 zsbuf->zslice);
451 scene->zsbuf_map = NULL;
452 }
453 #endif
454
455 util_unreference_framebuffer_state( &scene->fb );
456 }
457
458
459 void lp_scene_begin_binning( struct lp_scene *scene,
460 struct pipe_framebuffer_state *fb )
461 {
462 assert(lp_scene_is_empty(scene));
463
464 util_copy_framebuffer_state(&scene->fb, fb);
465
466 scene->tiles_x = align(fb->width, TILE_SIZE) / TILE_SIZE;
467 scene->tiles_y = align(fb->height, TILE_SIZE) / TILE_SIZE;
468
469 assert(scene->tiles_x <= TILES_X);
470 assert(scene->tiles_y <= TILES_Y);
471 }
472
473
474 void lp_scene_rasterize( struct lp_scene *scene,
475 struct lp_rasterizer *rast,
476 boolean write_depth )
477 {
478 if (0) {
479 unsigned x, y;
480 debug_printf("rasterize scene:\n");
481 debug_printf(" data size: %u\n", lp_scene_data_size(scene));
482 for (y = 0; y < scene->tiles_y; y++) {
483 for (x = 0; x < scene->tiles_x; x++) {
484 debug_printf(" bin %u, %u size: %u\n", x, y,
485 lp_scene_bin_size(scene, x, y));
486 }
487 }
488 }
489
490 scene->write_depth = (scene->fb.zsbuf != NULL &&
491 write_depth);
492
493 lp_scene_map_buffers( scene );
494
495 /* Enqueue the scene for rasterization, then immediately wait for
496 * it to finish.
497 */
498 lp_rast_queue_scene( rast, scene );
499
500 /* Currently just wait for the rasterizer to finish. Some
501 * threading interactions need to be worked out, particularly once
502 * transfers become per-context:
503 */
504 lp_rast_finish( rast );
505 lp_scene_unmap_buffers( scene );
506 lp_scene_enqueue( scene->empty_queue, scene );
507 }