7f31df6ae502cbeeede4d4fcf1f8bc6f59b56404
[mesa.git] / src / gallium / drivers / llvmpipe / lp_setup.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 /**
29 * Tiling engine.
30 *
31 * Builds per-tile display lists and executes them on calls to
32 * lp_setup_flush().
33 */
34
35 #include "pipe/p_defines.h"
36 #include "pipe/p_inlines.h"
37 #include "util/u_math.h"
38 #include "util/u_memory.h"
39 #include "util/u_pack_color.h"
40 #include "lp_debug.h"
41 #include "lp_state.h"
42 #include "lp_buffer.h"
43 #include "lp_texture.h"
44 #include "lp_setup_context.h"
45
46
47 static void set_state( struct setup_context *, unsigned );
48
49
50
51 static void
52 first_triangle( struct setup_context *setup,
53 const float (*v0)[4],
54 const float (*v1)[4],
55 const float (*v2)[4])
56 {
57 set_state( setup, SETUP_ACTIVE );
58 lp_setup_choose_triangle( setup );
59 setup->triangle( setup, v0, v1, v2 );
60 }
61
62 static void
63 first_line( struct setup_context *setup,
64 const float (*v0)[4],
65 const float (*v1)[4])
66 {
67 set_state( setup, SETUP_ACTIVE );
68 lp_setup_choose_line( setup );
69 setup->line( setup, v0, v1 );
70 }
71
72 static void
73 first_point( struct setup_context *setup,
74 const float (*v0)[4])
75 {
76 set_state( setup, SETUP_ACTIVE );
77 lp_setup_choose_point( setup );
78 setup->point( setup, v0 );
79 }
80
81 static void reset_context( struct setup_context *setup )
82 {
83 unsigned i, j;
84
85 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
86
87 /* Reset derived state */
88 setup->constants.stored_size = 0;
89 setup->constants.stored_data = NULL;
90 setup->fs.stored = NULL;
91 setup->dirty = ~0;
92
93 /* Free all but last binner command lists:
94 */
95 for (i = 0; i < setup->tiles_x; i++) {
96 for (j = 0; j < setup->tiles_y; j++) {
97 struct cmd_block_list *list = &setup->tile[i][j].commands;
98 struct cmd_block *block;
99 struct cmd_block *tmp;
100
101 for (block = list->head; block != list->tail; block = tmp) {
102 tmp = block->next;
103 FREE(block);
104 }
105
106 assert(list->tail->next == NULL);
107 list->head = list->tail;
108 list->head->count = 0;
109 }
110 }
111
112 /* Free all but last binned data block:
113 */
114 {
115 struct data_block_list *list = &setup->data;
116 struct data_block *block, *tmp;
117
118 for (block = list->head; block != list->tail; block = tmp) {
119 tmp = block->next;
120 FREE(block);
121 }
122
123 assert(list->tail->next == NULL);
124 list->head = list->tail;
125 list->head->used = 0;
126 }
127
128 /* Reset some state:
129 */
130 setup->clear.flags = 0;
131
132 /* Have an explicit "start-binning" call and get rid of this
133 * pointer twiddling?
134 */
135 setup->line = first_line;
136 setup->point = first_point;
137 setup->triangle = first_triangle;
138 }
139
140
141 /**
142 * Return last command in the bin
143 */
144 static lp_rast_cmd
145 lp_get_last_command( const struct cmd_bin *bin )
146 {
147 const struct cmd_block *tail = bin->commands.tail;
148 const unsigned i = tail->count;
149 if (i > 0)
150 return tail->cmd[i - 1];
151 else
152 return NULL;
153 }
154
155
156 /**
157 * Replace the arg of the last command in the bin.
158 */
159 static void
160 lp_replace_last_command_arg( struct cmd_bin *bin,
161 const union lp_rast_cmd_arg arg )
162 {
163 struct cmd_block *tail = bin->commands.tail;
164 const unsigned i = tail->count;
165 assert(i > 0);
166 tail->arg[i - 1] = arg;
167 }
168
169
170
171 /* Add a command to all active bins.
172 */
173 static void bin_everywhere( struct setup_context *setup,
174 lp_rast_cmd cmd,
175 const union lp_rast_cmd_arg arg )
176 {
177 unsigned i, j;
178 for (i = 0; i < setup->tiles_x; i++)
179 for (j = 0; j < setup->tiles_y; j++)
180 lp_bin_command( &setup->tile[i][j], cmd, arg );
181 }
182
183
184 /**
185 * Put a state-change command into all bins.
186 * If we find that the last command in a bin was also a state-change
187 * command, we can simply replace that one with the new one.
188 */
189 static void
190 bin_state_command( struct setup_context *setup,
191 lp_rast_cmd cmd,
192 const union lp_rast_cmd_arg arg )
193 {
194 unsigned i, j;
195 for (i = 0; i < setup->tiles_x; i++) {
196 for (j = 0; j < setup->tiles_y; j++) {
197 struct cmd_bin *bin = &setup->tile[i][j];
198 lp_rast_cmd last_cmd = lp_get_last_command(bin);
199 if (last_cmd == cmd) {
200 lp_replace_last_command_arg(bin, arg);
201 }
202 else {
203 lp_bin_command( bin, cmd, arg );
204 }
205 }
206 }
207 }
208
209
210 /** Rasterize commands for a single bin */
211 static void
212 rasterize_bin( struct lp_rasterizer *rast,
213 const struct cmd_bin *bin,
214 int x, int y)
215 {
216 const struct cmd_block_list *commands = &bin->commands;
217 struct cmd_block *block;
218 unsigned k;
219
220 lp_rast_start_tile( rast, x, y );
221
222 /* simply execute each of the commands in the block list */
223 for (block = commands->head; block; block = block->next) {
224 for (k = 0; k < block->count; k++) {
225 block->cmd[k]( rast, block->arg[k] );
226 }
227 }
228
229 lp_rast_end_tile( rast );
230 }
231
232
233 /** Rasterize all tile's bins */
234 static void
235 rasterize_bins( struct setup_context *setup,
236 boolean write_depth )
237 {
238 struct lp_rasterizer *rast = setup->rast;
239 unsigned i, j;
240
241 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
242
243 lp_rast_begin( rast,
244 setup->fb.cbuf,
245 setup->fb.zsbuf,
246 setup->fb.cbuf != NULL,
247 setup->fb.zsbuf != NULL && write_depth,
248 setup->fb.width,
249 setup->fb.height );
250
251 /* loop over tile bins, rasterize each */
252 for (i = 0; i < setup->tiles_x; i++) {
253 for (j = 0; j < setup->tiles_y; j++) {
254 rasterize_bin( rast, &setup->tile[i][j],
255 i * TILE_SIZE,
256 j * TILE_SIZE );
257 }
258 }
259
260 lp_rast_end( rast );
261
262 reset_context( setup );
263
264 LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
265 }
266
267
268
269 static void
270 begin_binning( struct setup_context *setup )
271 {
272 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
273
274 if (setup->fb.cbuf) {
275 if (setup->clear.flags & PIPE_CLEAR_COLOR)
276 bin_everywhere( setup,
277 lp_rast_clear_color,
278 setup->clear.color );
279 else
280 bin_everywhere( setup, lp_rast_load_color, lp_rast_arg_null() );
281 }
282
283 if (setup->fb.zsbuf) {
284 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL)
285 bin_everywhere( setup,
286 lp_rast_clear_zstencil,
287 setup->clear.zstencil );
288 else
289 bin_everywhere( setup, lp_rast_load_zstencil, lp_rast_arg_null() );
290 }
291
292 LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__);
293 }
294
295
296 /* This basically bins and then flushes any outstanding full-screen
297 * clears.
298 *
299 * TODO: fast path for fullscreen clears and no triangles.
300 */
301 static void
302 execute_clears( struct setup_context *setup )
303 {
304 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
305
306 begin_binning( setup );
307 rasterize_bins( setup, TRUE );
308 }
309
310
311 static void
312 set_state( struct setup_context *setup,
313 unsigned new_state )
314 {
315 unsigned old_state = setup->state;
316
317 if (old_state == new_state)
318 return;
319
320 LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state);
321
322 switch (new_state) {
323 case SETUP_ACTIVE:
324 begin_binning( setup );
325 break;
326
327 case SETUP_CLEARED:
328 if (old_state == SETUP_ACTIVE) {
329 assert(0);
330 return;
331 }
332 break;
333
334 case SETUP_FLUSHED:
335 if (old_state == SETUP_CLEARED)
336 execute_clears( setup );
337 else
338 rasterize_bins( setup, TRUE );
339 break;
340 }
341
342 setup->state = new_state;
343 }
344
345
346 void
347 lp_setup_flush( struct setup_context *setup,
348 unsigned flags )
349 {
350 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
351
352 set_state( setup, SETUP_FLUSHED );
353 }
354
355
356 void
357 lp_setup_bind_framebuffer( struct setup_context *setup,
358 struct pipe_surface *color,
359 struct pipe_surface *zstencil )
360 {
361 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
362
363 set_state( setup, SETUP_FLUSHED );
364
365 pipe_surface_reference( &setup->fb.cbuf, color );
366 pipe_surface_reference( &setup->fb.zsbuf, zstencil );
367
368 if (!setup->fb.cbuf && !setup->fb.zsbuf) {
369 setup->fb.width = 0;
370 setup->fb.height = 0;
371 }
372 else if (!setup->fb.zsbuf) {
373 setup->fb.width = setup->fb.cbuf->width;
374 setup->fb.height = setup->fb.cbuf->height;
375 }
376 else if (!setup->fb.cbuf) {
377 setup->fb.width = setup->fb.zsbuf->width;
378 setup->fb.height = setup->fb.zsbuf->height;
379 }
380 else {
381 /* XXX: not sure what we're really supposed to do for
382 * mis-matched color & depth buffer sizes.
383 */
384 setup->fb.width = MIN2(setup->fb.cbuf->width,
385 setup->fb.zsbuf->width);
386 setup->fb.height = MIN2(setup->fb.cbuf->height,
387 setup->fb.zsbuf->height);
388 }
389
390 setup->tiles_x = align(setup->fb.width, TILE_SIZE) / TILE_SIZE;
391 setup->tiles_y = align(setup->fb.height, TILE_SIZE) / TILE_SIZE;
392 }
393
394
395 void
396 lp_setup_clear( struct setup_context *setup,
397 const float *color,
398 double depth,
399 unsigned stencil,
400 unsigned flags )
401 {
402 unsigned i;
403
404 LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state);
405
406
407 if (flags & PIPE_CLEAR_COLOR) {
408 for (i = 0; i < 4; ++i)
409 setup->clear.color.clear_color[i] = float_to_ubyte(color[i]);
410 }
411
412 if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
413 setup->clear.zstencil.clear_zstencil =
414 util_pack_z_stencil(setup->fb.zsbuf->format,
415 depth,
416 stencil);
417 }
418
419 if (setup->state == SETUP_ACTIVE) {
420 /* Add the clear to existing bins. In the unusual case where
421 * both color and depth-stencilare being cleared, we could
422 * discard the currently binned scene and start again, but I
423 * don't see that as being a common usage.
424 */
425 if (flags & PIPE_CLEAR_COLOR)
426 bin_everywhere( setup,
427 lp_rast_clear_color,
428 setup->clear.color );
429
430 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL)
431 bin_everywhere( setup,
432 lp_rast_clear_zstencil,
433 setup->clear.zstencil );
434 }
435 else {
436 /* Put ourselves into the 'pre-clear' state, specifically to try
437 * and accumulate multiple clears to color and depth_stencil
438 * buffers which the app or state-tracker might issue
439 * separately.
440 */
441 set_state( setup, SETUP_CLEARED );
442
443 setup->clear.flags |= flags;
444 }
445 }
446
447
448
449 void
450 lp_setup_set_triangle_state( struct setup_context *setup,
451 unsigned cull_mode,
452 boolean ccw_is_frontface)
453 {
454 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
455
456 setup->ccw_is_frontface = ccw_is_frontface;
457 setup->cullmode = cull_mode;
458 setup->triangle = first_triangle;
459 }
460
461
462
463 void
464 lp_setup_set_fs_inputs( struct setup_context *setup,
465 const struct lp_shader_input *input,
466 unsigned nr )
467 {
468 LP_DBG(DEBUG_SETUP, "%s %p %u\n", __FUNCTION__, (void *) input, nr);
469
470 memcpy( setup->fs.input, input, nr * sizeof input[0] );
471 setup->fs.nr_inputs = nr;
472 }
473
474 void
475 lp_setup_set_fs( struct setup_context *setup,
476 struct lp_fragment_shader *fs )
477 {
478 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) fs);
479 /* FIXME: reference count */
480
481 setup->fs.current.jit_function = fs ? fs->current->jit_function : NULL;
482 setup->dirty |= LP_SETUP_NEW_FS;
483 }
484
485 void
486 lp_setup_set_fs_constants(struct setup_context *setup,
487 struct pipe_buffer *buffer)
488 {
489 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer);
490
491 pipe_buffer_reference(&setup->constants.current, buffer);
492
493 setup->dirty |= LP_SETUP_NEW_CONSTANTS;
494 }
495
496
497 void
498 lp_setup_set_alpha_ref_value( struct setup_context *setup,
499 float alpha_ref_value )
500 {
501 LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value);
502
503 if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) {
504 setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value;
505 setup->dirty |= LP_SETUP_NEW_FS;
506 }
507 }
508
509 void
510 lp_setup_set_blend_color( struct setup_context *setup,
511 const struct pipe_blend_color *blend_color )
512 {
513 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
514
515 assert(blend_color);
516
517 if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) {
518 memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color);
519 setup->dirty |= LP_SETUP_NEW_BLEND_COLOR;
520 }
521 }
522
523 void
524 lp_setup_set_sampler_textures( struct setup_context *setup,
525 unsigned num, struct pipe_texture **texture)
526 {
527 struct pipe_texture *dummy;
528 unsigned i;
529
530 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
531
532
533 assert(num <= PIPE_MAX_SAMPLERS);
534
535 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
536 struct pipe_texture *tex = i < num ? texture[i] : NULL;
537
538 /* FIXME: hold on to the reference */
539 dummy = NULL;
540 pipe_texture_reference(&dummy, tex);
541
542 if(tex) {
543 struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex);
544 struct lp_jit_texture *jit_tex;
545 jit_tex = &setup->fs.current.jit_context.textures[i];
546 jit_tex->width = tex->width[0];
547 jit_tex->height = tex->height[0];
548 jit_tex->stride = lp_tex->stride[0];
549 if(!lp_tex->dt)
550 jit_tex->data = lp_tex->data;
551 else
552 /* FIXME: map the rendertarget */
553 assert(0);
554 }
555 }
556
557 setup->dirty |= LP_SETUP_NEW_FS;
558 }
559
560 boolean
561 lp_setup_is_texture_referenced( struct setup_context *setup,
562 const struct pipe_texture *texture )
563 {
564 /* FIXME */
565 return PIPE_UNREFERENCED;
566 }
567
568
569 static INLINE void
570 lp_setup_update_shader_state( struct setup_context *setup )
571 {
572 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
573
574 assert(setup->fs.current.jit_function);
575
576 if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
577 uint8_t *stored;
578 unsigned i, j;
579
580 stored = lp_bin_alloc_aligned(&setup->data, 4 * 16, 16);
581
582 /* smear each blend color component across 16 ubyte elements */
583 for (i = 0; i < 4; ++i) {
584 uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]);
585 for (j = 0; j < 16; ++j)
586 stored[i*16 + j] = c;
587 }
588
589 setup->blend_color.stored = stored;
590
591 setup->fs.current.jit_context.blend_color = setup->blend_color.stored;
592 setup->dirty |= LP_SETUP_NEW_FS;
593 }
594
595
596 if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
597 struct pipe_buffer *buffer = setup->constants.current;
598
599 if(buffer) {
600 unsigned current_size = buffer->size;
601 const void *current_data = llvmpipe_buffer(buffer)->data;
602
603 /* TODO: copy only the actually used constants? */
604
605 if(setup->constants.stored_size != current_size ||
606 !setup->constants.stored_data ||
607 memcmp(setup->constants.stored_data,
608 current_data,
609 current_size) != 0) {
610 void *stored;
611
612 stored = lp_bin_alloc(&setup->data, current_size);
613 if(stored) {
614 memcpy(stored,
615 current_data,
616 current_size);
617 setup->constants.stored_size = current_size;
618 setup->constants.stored_data = stored;
619 }
620 }
621 }
622 else {
623 setup->constants.stored_size = 0;
624 setup->constants.stored_data = NULL;
625 }
626
627 setup->fs.current.jit_context.constants = setup->constants.stored_data;
628 setup->dirty |= LP_SETUP_NEW_FS;
629 }
630
631
632 if(setup->dirty & LP_SETUP_NEW_FS) {
633 if(!setup->fs.stored ||
634 memcmp(setup->fs.stored,
635 &setup->fs.current,
636 sizeof setup->fs.current) != 0) {
637 /* The fs state that's been stored in the bins is different from
638 * the new, current state. So allocate a new lp_rast_state object
639 * and append it to the bin's setup data buffer.
640 */
641 struct lp_rast_state *stored =
642 (struct lp_rast_state *) lp_bin_alloc(&setup->data, sizeof *stored);
643 if(stored) {
644 memcpy(stored,
645 &setup->fs.current,
646 sizeof setup->fs.current);
647 setup->fs.stored = stored;
648
649 /* put the state-set command into all bins */
650 bin_state_command( setup,
651 lp_rast_set_state,
652 lp_rast_arg_state(setup->fs.stored) );
653 }
654 }
655 }
656
657 setup->dirty = 0;
658
659 assert(setup->fs.stored);
660 }
661
662
663 /* Stubs for lines & points for now:
664 */
665 void
666 lp_setup_point(struct setup_context *setup,
667 const float (*v0)[4])
668 {
669 lp_setup_update_shader_state(setup);
670 setup->point( setup, v0 );
671 }
672
673 void
674 lp_setup_line(struct setup_context *setup,
675 const float (*v0)[4],
676 const float (*v1)[4])
677 {
678 lp_setup_update_shader_state(setup);
679 setup->line( setup, v0, v1 );
680 }
681
682 void
683 lp_setup_tri(struct setup_context *setup,
684 const float (*v0)[4],
685 const float (*v1)[4],
686 const float (*v2)[4])
687 {
688 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
689
690 lp_setup_update_shader_state(setup);
691 setup->triangle( setup, v0, v1, v2 );
692 }
693
694
695 void
696 lp_setup_destroy( struct setup_context *setup )
697 {
698 unsigned i, j;
699
700 reset_context( setup );
701
702 pipe_buffer_reference(&setup->constants.current, NULL);
703
704 for (i = 0; i < TILES_X; i++)
705 for (j = 0; j < TILES_Y; j++)
706 FREE(setup->tile[i][j].commands.head);
707
708 FREE(setup->data.head);
709
710 lp_rast_destroy( setup->rast );
711 FREE( setup );
712 }
713
714
715 /**
716 * Create a new primitive tiling engine. Currently also creates a
717 * rasterizer to use with it.
718 */
719 struct setup_context *
720 lp_setup_create( struct pipe_screen *screen )
721 {
722 struct setup_context *setup = CALLOC_STRUCT(setup_context);
723 unsigned i, j;
724
725 setup->rast = lp_rast_create( screen );
726 if (!setup->rast)
727 goto fail;
728
729 for (i = 0; i < TILES_X; i++)
730 for (j = 0; j < TILES_Y; j++)
731 setup->tile[i][j].commands.head =
732 setup->tile[i][j].commands.tail = CALLOC_STRUCT(cmd_block);
733
734 setup->data.head =
735 setup->data.tail = CALLOC_STRUCT(data_block);
736
737 setup->triangle = first_triangle;
738 setup->line = first_line;
739 setup->point = first_point;
740
741 setup->dirty = ~0;
742
743 return setup;
744
745 fail:
746 FREE(setup);
747 return NULL;
748 }
749