7f31df6ae502cbeeede4d4fcf1f8bc6f59b56404
1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
31 * Builds per-tile display lists and executes them on calls to
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"
42 #include "lp_buffer.h"
43 #include "lp_texture.h"
44 #include "lp_setup_context.h"
47 static void set_state( struct setup_context
*, unsigned );
52 first_triangle( struct setup_context
*setup
,
57 set_state( setup
, SETUP_ACTIVE
);
58 lp_setup_choose_triangle( setup
);
59 setup
->triangle( setup
, v0
, v1
, v2
);
63 first_line( struct setup_context
*setup
,
67 set_state( setup
, SETUP_ACTIVE
);
68 lp_setup_choose_line( setup
);
69 setup
->line( setup
, v0
, v1
);
73 first_point( struct setup_context
*setup
,
76 set_state( setup
, SETUP_ACTIVE
);
77 lp_setup_choose_point( setup
);
78 setup
->point( setup
, v0
);
81 static void reset_context( struct setup_context
*setup
)
85 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
87 /* Reset derived state */
88 setup
->constants
.stored_size
= 0;
89 setup
->constants
.stored_data
= NULL
;
90 setup
->fs
.stored
= NULL
;
93 /* Free all but last binner command lists:
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
;
101 for (block
= list
->head
; block
!= list
->tail
; block
= tmp
) {
106 assert(list
->tail
->next
== NULL
);
107 list
->head
= list
->tail
;
108 list
->head
->count
= 0;
112 /* Free all but last binned data block:
115 struct data_block_list
*list
= &setup
->data
;
116 struct data_block
*block
, *tmp
;
118 for (block
= list
->head
; block
!= list
->tail
; block
= tmp
) {
123 assert(list
->tail
->next
== NULL
);
124 list
->head
= list
->tail
;
125 list
->head
->used
= 0;
130 setup
->clear
.flags
= 0;
132 /* Have an explicit "start-binning" call and get rid of this
135 setup
->line
= first_line
;
136 setup
->point
= first_point
;
137 setup
->triangle
= first_triangle
;
142 * Return last command in the bin
145 lp_get_last_command( const struct cmd_bin
*bin
)
147 const struct cmd_block
*tail
= bin
->commands
.tail
;
148 const unsigned i
= tail
->count
;
150 return tail
->cmd
[i
- 1];
157 * Replace the arg of the last command in the bin.
160 lp_replace_last_command_arg( struct cmd_bin
*bin
,
161 const union lp_rast_cmd_arg arg
)
163 struct cmd_block
*tail
= bin
->commands
.tail
;
164 const unsigned i
= tail
->count
;
166 tail
->arg
[i
- 1] = arg
;
171 /* Add a command to all active bins.
173 static void bin_everywhere( struct setup_context
*setup
,
175 const union lp_rast_cmd_arg arg
)
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
);
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.
190 bin_state_command( struct setup_context
*setup
,
192 const union lp_rast_cmd_arg arg
)
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
);
203 lp_bin_command( bin
, cmd
, arg
);
210 /** Rasterize commands for a single bin */
212 rasterize_bin( struct lp_rasterizer
*rast
,
213 const struct cmd_bin
*bin
,
216 const struct cmd_block_list
*commands
= &bin
->commands
;
217 struct cmd_block
*block
;
220 lp_rast_start_tile( rast
, x
, y
);
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
] );
229 lp_rast_end_tile( rast
);
233 /** Rasterize all tile's bins */
235 rasterize_bins( struct setup_context
*setup
,
236 boolean write_depth
)
238 struct lp_rasterizer
*rast
= setup
->rast
;
241 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
246 setup
->fb
.cbuf
!= NULL
,
247 setup
->fb
.zsbuf
!= NULL
&& write_depth
,
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
],
262 reset_context( setup
);
264 LP_DBG(DEBUG_SETUP
, "%s done \n", __FUNCTION__
);
270 begin_binning( struct setup_context
*setup
)
272 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
274 if (setup
->fb
.cbuf
) {
275 if (setup
->clear
.flags
& PIPE_CLEAR_COLOR
)
276 bin_everywhere( setup
,
278 setup
->clear
.color
);
280 bin_everywhere( setup
, lp_rast_load_color
, lp_rast_arg_null() );
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
);
289 bin_everywhere( setup
, lp_rast_load_zstencil
, lp_rast_arg_null() );
292 LP_DBG(DEBUG_SETUP
, "%s done\n", __FUNCTION__
);
296 /* This basically bins and then flushes any outstanding full-screen
299 * TODO: fast path for fullscreen clears and no triangles.
302 execute_clears( struct setup_context
*setup
)
304 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
306 begin_binning( setup
);
307 rasterize_bins( setup
, TRUE
);
312 set_state( struct setup_context
*setup
,
315 unsigned old_state
= setup
->state
;
317 if (old_state
== new_state
)
320 LP_DBG(DEBUG_SETUP
, "%s old %d new %d\n", __FUNCTION__
, old_state
, new_state
);
324 begin_binning( setup
);
328 if (old_state
== SETUP_ACTIVE
) {
335 if (old_state
== SETUP_CLEARED
)
336 execute_clears( setup
);
338 rasterize_bins( setup
, TRUE
);
342 setup
->state
= new_state
;
347 lp_setup_flush( struct setup_context
*setup
,
350 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
352 set_state( setup
, SETUP_FLUSHED
);
357 lp_setup_bind_framebuffer( struct setup_context
*setup
,
358 struct pipe_surface
*color
,
359 struct pipe_surface
*zstencil
)
361 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
363 set_state( setup
, SETUP_FLUSHED
);
365 pipe_surface_reference( &setup
->fb
.cbuf
, color
);
366 pipe_surface_reference( &setup
->fb
.zsbuf
, zstencil
);
368 if (!setup
->fb
.cbuf
&& !setup
->fb
.zsbuf
) {
370 setup
->fb
.height
= 0;
372 else if (!setup
->fb
.zsbuf
) {
373 setup
->fb
.width
= setup
->fb
.cbuf
->width
;
374 setup
->fb
.height
= setup
->fb
.cbuf
->height
;
376 else if (!setup
->fb
.cbuf
) {
377 setup
->fb
.width
= setup
->fb
.zsbuf
->width
;
378 setup
->fb
.height
= setup
->fb
.zsbuf
->height
;
381 /* XXX: not sure what we're really supposed to do for
382 * mis-matched color & depth buffer sizes.
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
);
390 setup
->tiles_x
= align(setup
->fb
.width
, TILE_SIZE
) / TILE_SIZE
;
391 setup
->tiles_y
= align(setup
->fb
.height
, TILE_SIZE
) / TILE_SIZE
;
396 lp_setup_clear( struct setup_context
*setup
,
404 LP_DBG(DEBUG_SETUP
, "%s state %d\n", __FUNCTION__
, setup
->state
);
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
]);
412 if (flags
& PIPE_CLEAR_DEPTHSTENCIL
) {
413 setup
->clear
.zstencil
.clear_zstencil
=
414 util_pack_z_stencil(setup
->fb
.zsbuf
->format
,
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.
425 if (flags
& PIPE_CLEAR_COLOR
)
426 bin_everywhere( setup
,
428 setup
->clear
.color
);
430 if (setup
->clear
.flags
& PIPE_CLEAR_DEPTHSTENCIL
)
431 bin_everywhere( setup
,
432 lp_rast_clear_zstencil
,
433 setup
->clear
.zstencil
);
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
441 set_state( setup
, SETUP_CLEARED
);
443 setup
->clear
.flags
|= flags
;
450 lp_setup_set_triangle_state( struct setup_context
*setup
,
452 boolean ccw_is_frontface
)
454 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
456 setup
->ccw_is_frontface
= ccw_is_frontface
;
457 setup
->cullmode
= cull_mode
;
458 setup
->triangle
= first_triangle
;
464 lp_setup_set_fs_inputs( struct setup_context
*setup
,
465 const struct lp_shader_input
*input
,
468 LP_DBG(DEBUG_SETUP
, "%s %p %u\n", __FUNCTION__
, (void *) input
, nr
);
470 memcpy( setup
->fs
.input
, input
, nr
* sizeof input
[0] );
471 setup
->fs
.nr_inputs
= nr
;
475 lp_setup_set_fs( struct setup_context
*setup
,
476 struct lp_fragment_shader
*fs
)
478 LP_DBG(DEBUG_SETUP
, "%s %p\n", __FUNCTION__
, (void *) fs
);
479 /* FIXME: reference count */
481 setup
->fs
.current
.jit_function
= fs
? fs
->current
->jit_function
: NULL
;
482 setup
->dirty
|= LP_SETUP_NEW_FS
;
486 lp_setup_set_fs_constants(struct setup_context
*setup
,
487 struct pipe_buffer
*buffer
)
489 LP_DBG(DEBUG_SETUP
, "%s %p\n", __FUNCTION__
, (void *) buffer
);
491 pipe_buffer_reference(&setup
->constants
.current
, buffer
);
493 setup
->dirty
|= LP_SETUP_NEW_CONSTANTS
;
498 lp_setup_set_alpha_ref_value( struct setup_context
*setup
,
499 float alpha_ref_value
)
501 LP_DBG(DEBUG_SETUP
, "%s %f\n", __FUNCTION__
, alpha_ref_value
);
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
;
510 lp_setup_set_blend_color( struct setup_context
*setup
,
511 const struct pipe_blend_color
*blend_color
)
513 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
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
;
524 lp_setup_set_sampler_textures( struct setup_context
*setup
,
525 unsigned num
, struct pipe_texture
**texture
)
527 struct pipe_texture
*dummy
;
530 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
533 assert(num
<= PIPE_MAX_SAMPLERS
);
535 for (i
= 0; i
< PIPE_MAX_SAMPLERS
; i
++) {
536 struct pipe_texture
*tex
= i
< num
? texture
[i
] : NULL
;
538 /* FIXME: hold on to the reference */
540 pipe_texture_reference(&dummy
, 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];
550 jit_tex
->data
= lp_tex
->data
;
552 /* FIXME: map the rendertarget */
557 setup
->dirty
|= LP_SETUP_NEW_FS
;
561 lp_setup_is_texture_referenced( struct setup_context
*setup
,
562 const struct pipe_texture
*texture
)
565 return PIPE_UNREFERENCED
;
570 lp_setup_update_shader_state( struct setup_context
*setup
)
572 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
574 assert(setup
->fs
.current
.jit_function
);
576 if(setup
->dirty
& LP_SETUP_NEW_BLEND_COLOR
) {
580 stored
= lp_bin_alloc_aligned(&setup
->data
, 4 * 16, 16);
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
;
589 setup
->blend_color
.stored
= stored
;
591 setup
->fs
.current
.jit_context
.blend_color
= setup
->blend_color
.stored
;
592 setup
->dirty
|= LP_SETUP_NEW_FS
;
596 if(setup
->dirty
& LP_SETUP_NEW_CONSTANTS
) {
597 struct pipe_buffer
*buffer
= setup
->constants
.current
;
600 unsigned current_size
= buffer
->size
;
601 const void *current_data
= llvmpipe_buffer(buffer
)->data
;
603 /* TODO: copy only the actually used constants? */
605 if(setup
->constants
.stored_size
!= current_size
||
606 !setup
->constants
.stored_data
||
607 memcmp(setup
->constants
.stored_data
,
609 current_size
) != 0) {
612 stored
= lp_bin_alloc(&setup
->data
, current_size
);
617 setup
->constants
.stored_size
= current_size
;
618 setup
->constants
.stored_data
= stored
;
623 setup
->constants
.stored_size
= 0;
624 setup
->constants
.stored_data
= NULL
;
627 setup
->fs
.current
.jit_context
.constants
= setup
->constants
.stored_data
;
628 setup
->dirty
|= LP_SETUP_NEW_FS
;
632 if(setup
->dirty
& LP_SETUP_NEW_FS
) {
633 if(!setup
->fs
.stored
||
634 memcmp(setup
->fs
.stored
,
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.
641 struct lp_rast_state
*stored
=
642 (struct lp_rast_state
*) lp_bin_alloc(&setup
->data
, sizeof *stored
);
646 sizeof setup
->fs
.current
);
647 setup
->fs
.stored
= stored
;
649 /* put the state-set command into all bins */
650 bin_state_command( setup
,
652 lp_rast_arg_state(setup
->fs
.stored
) );
659 assert(setup
->fs
.stored
);
663 /* Stubs for lines & points for now:
666 lp_setup_point(struct setup_context
*setup
,
667 const float (*v0
)[4])
669 lp_setup_update_shader_state(setup
);
670 setup
->point( setup
, v0
);
674 lp_setup_line(struct setup_context
*setup
,
675 const float (*v0
)[4],
676 const float (*v1
)[4])
678 lp_setup_update_shader_state(setup
);
679 setup
->line( setup
, v0
, v1
);
683 lp_setup_tri(struct setup_context
*setup
,
684 const float (*v0
)[4],
685 const float (*v1
)[4],
686 const float (*v2
)[4])
688 LP_DBG(DEBUG_SETUP
, "%s\n", __FUNCTION__
);
690 lp_setup_update_shader_state(setup
);
691 setup
->triangle( setup
, v0
, v1
, v2
);
696 lp_setup_destroy( struct setup_context
*setup
)
700 reset_context( setup
);
702 pipe_buffer_reference(&setup
->constants
.current
, NULL
);
704 for (i
= 0; i
< TILES_X
; i
++)
705 for (j
= 0; j
< TILES_Y
; j
++)
706 FREE(setup
->tile
[i
][j
].commands
.head
);
708 FREE(setup
->data
.head
);
710 lp_rast_destroy( setup
->rast
);
716 * Create a new primitive tiling engine. Currently also creates a
717 * rasterizer to use with it.
719 struct setup_context
*
720 lp_setup_create( struct pipe_screen
*screen
)
722 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
725 setup
->rast
= lp_rast_create( screen
);
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
);
735 setup
->data
.tail
= CALLOC_STRUCT(data_block
);
737 setup
->triangle
= first_triangle
;
738 setup
->line
= first_line
;
739 setup
->point
= first_point
;