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"
41 #include "lp_buffer.h"
42 #include "lp_texture.h"
43 #include "lp_setup_context.h"
45 #define SETUP_DEBUG debug_printf
47 static void set_state( struct setup_context
*, unsigned );
49 void lp_setup_new_cmd_block( struct cmd_block_list
*list
)
51 struct cmd_block
*block
= MALLOC_STRUCT(cmd_block
);
52 list
->tail
->next
= block
;
58 void lp_setup_new_data_block( struct data_block_list
*list
)
60 struct data_block
*block
= MALLOC_STRUCT(data_block
);
61 list
->tail
->next
= block
;
69 first_triangle( struct setup_context
*setup
,
74 set_state( setup
, SETUP_ACTIVE
);
75 lp_setup_choose_triangle( setup
);
76 setup
->triangle( setup
, v0
, v1
, v2
);
80 first_line( struct setup_context
*setup
,
84 set_state( setup
, SETUP_ACTIVE
);
85 lp_setup_choose_line( setup
);
86 setup
->line( setup
, v0
, v1
);
90 first_point( struct setup_context
*setup
,
93 set_state( setup
, SETUP_ACTIVE
);
94 lp_setup_choose_point( setup
);
95 setup
->point( setup
, v0
);
98 static void reset_context( struct setup_context
*setup
)
102 SETUP_DEBUG("%s\n", __FUNCTION__
);
104 /* Reset derived state */
105 setup
->constants
.stored_size
= 0;
106 setup
->constants
.stored_data
= NULL
;
107 setup
->fs
.stored
= NULL
;
110 /* Free all but last binner command lists:
112 for (i
= 0; i
< setup
->tiles_x
; i
++) {
113 for (j
= 0; j
< setup
->tiles_y
; j
++) {
114 struct cmd_block_list
*list
= &setup
->tile
[i
][j
];
115 struct cmd_block
*block
;
116 struct cmd_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
->count
= 0;
129 /* Free all but last binned data block:
132 struct data_block_list
*list
= &setup
->data
;
133 struct data_block
*block
, *tmp
;
135 for (block
= list
->head
; block
!= list
->tail
; block
= tmp
) {
140 assert(list
->tail
->next
== NULL
);
141 list
->head
= list
->tail
;
142 list
->head
->used
= 0;
147 setup
->clear
.flags
= 0;
149 /* Have an explicit "start-binning" call and get rid of this
152 setup
->line
= first_line
;
153 setup
->point
= first_point
;
154 setup
->triangle
= first_triangle
;
160 /* Add a command to all active bins.
162 static void bin_everywhere( struct setup_context
*setup
,
164 const union lp_rast_cmd_arg arg
)
167 for (i
= 0; i
< setup
->tiles_x
; i
++)
168 for (j
= 0; j
< setup
->tiles_y
; j
++)
169 bin_command( &setup
->tile
[i
][j
], cmd
, arg
);
174 rasterize_bins( struct setup_context
*setup
,
175 boolean write_depth
)
177 struct lp_rasterizer
*rast
= setup
->rast
;
178 struct cmd_block
*block
;
181 SETUP_DEBUG("%s\n", __FUNCTION__
);
186 setup
->fb
.cbuf
!= NULL
,
187 setup
->fb
.zsbuf
!= NULL
&& write_depth
,
193 for (i
= 0; i
< setup
->tiles_x
; i
++) {
194 for (j
= 0; j
< setup
->tiles_y
; j
++) {
196 lp_rast_start_tile( rast
,
200 for (block
= setup
->tile
[i
][j
].head
; block
; block
= block
->next
) {
201 for (k
= 0; k
< block
->count
; k
++) {
202 block
->cmd
[k
]( rast
, block
->arg
[k
] );
206 lp_rast_end_tile( rast
);
212 reset_context( setup
);
218 begin_binning( struct setup_context
*setup
)
220 SETUP_DEBUG("%s\n", __FUNCTION__
);
222 if (!setup
->fb
.cbuf
&& !setup
->fb
.zsbuf
) {
224 setup
->fb
.height
= 0;
226 else if (!setup
->fb
.zsbuf
) {
227 setup
->fb
.width
= setup
->fb
.cbuf
->width
;
228 setup
->fb
.height
= setup
->fb
.cbuf
->height
;
230 else if (!setup
->fb
.cbuf
) {
231 setup
->fb
.width
= setup
->fb
.zsbuf
->width
;
232 setup
->fb
.height
= setup
->fb
.zsbuf
->height
;
235 /* XXX: not sure what we're really supposed to do for
236 * mis-matched color & depth buffer sizes.
238 setup
->fb
.width
= MIN2(setup
->fb
.cbuf
->width
,
239 setup
->fb
.zsbuf
->width
);
240 setup
->fb
.height
= MIN2(setup
->fb
.cbuf
->height
,
241 setup
->fb
.zsbuf
->height
);
244 setup
->tiles_x
= align(setup
->fb
.width
, TILE_SIZE
) / TILE_SIZE
;
245 setup
->tiles_y
= align(setup
->fb
.height
, TILE_SIZE
) / TILE_SIZE
;
247 if (setup
->fb
.cbuf
) {
248 if (setup
->clear
.flags
& PIPE_CLEAR_COLOR
)
249 bin_everywhere( setup
,
251 setup
->clear
.color
);
253 bin_everywhere( setup
, lp_rast_load_color
, lp_rast_arg_null() );
256 if (setup
->fb
.zsbuf
) {
257 if (setup
->clear
.flags
& PIPE_CLEAR_DEPTHSTENCIL
)
258 bin_everywhere( setup
,
259 lp_rast_clear_zstencil
,
260 setup
->clear
.zstencil
);
262 bin_everywhere( setup
, lp_rast_load_zstencil
, lp_rast_arg_null() );
267 /* This basically bins and then flushes any outstanding full-screen
270 * TODO: fast path for fullscreen clears and no triangles.
273 execute_clears( struct setup_context
*setup
)
275 SETUP_DEBUG("%s\n", __FUNCTION__
);
277 begin_binning( setup
);
278 rasterize_bins( setup
, TRUE
);
283 set_state( struct setup_context
*setup
,
286 unsigned old_state
= setup
->state
;
288 if (old_state
== new_state
)
291 SETUP_DEBUG("%s old %d new %d\n", __FUNCTION__
, old_state
, new_state
);
295 begin_binning( setup
);
299 if (old_state
== SETUP_ACTIVE
) {
306 if (old_state
== SETUP_CLEARED
)
307 execute_clears( setup
);
309 rasterize_bins( setup
, TRUE
);
313 setup
->state
= new_state
;
318 lp_setup_flush( struct setup_context
*setup
,
321 SETUP_DEBUG("%s\n", __FUNCTION__
);
323 set_state( setup
, SETUP_FLUSHED
);
328 lp_setup_bind_framebuffer( struct setup_context
*setup
,
329 struct pipe_surface
*color
,
330 struct pipe_surface
*zstencil
)
332 SETUP_DEBUG("%s\n", __FUNCTION__
);
334 set_state( setup
, SETUP_FLUSHED
);
336 pipe_surface_reference( &setup
->fb
.cbuf
, color
);
337 pipe_surface_reference( &setup
->fb
.zsbuf
, zstencil
);
341 lp_setup_clear( struct setup_context
*setup
,
349 SETUP_DEBUG("%s state %d\n", __FUNCTION__
, setup
->state
);
352 if (flags
& PIPE_CLEAR_COLOR
) {
353 for (i
= 0; i
< 4; ++i
)
354 setup
->clear
.color
.clear_color
[i
] = float_to_ubyte(color
[i
]);
357 if (flags
& PIPE_CLEAR_DEPTHSTENCIL
) {
358 setup
->clear
.zstencil
.clear_zstencil
=
359 util_pack_z_stencil(setup
->fb
.zsbuf
->format
,
364 if (setup
->state
== SETUP_ACTIVE
) {
365 /* Add the clear to existing bins. In the unusual case where
366 * both color and depth-stencilare being cleared, we could
367 * discard the currently binned scene and start again, but I
368 * don't see that as being a common usage.
370 if (flags
& PIPE_CLEAR_COLOR
)
371 bin_everywhere( setup
,
373 setup
->clear
.color
);
375 if (setup
->clear
.flags
& PIPE_CLEAR_DEPTHSTENCIL
)
376 bin_everywhere( setup
,
377 lp_rast_clear_zstencil
,
378 setup
->clear
.zstencil
);
381 /* Put ourselves into the 'pre-clear' state, specifically to try
382 * and accumulate multiple clears to color and depth_stencil
383 * buffers which the app or state-tracker might issue
386 set_state( setup
, SETUP_CLEARED
);
388 setup
->clear
.flags
|= flags
;
395 lp_setup_set_triangle_state( struct setup_context
*setup
,
397 boolean ccw_is_frontface
)
399 SETUP_DEBUG("%s\n", __FUNCTION__
);
401 setup
->ccw_is_frontface
= ccw_is_frontface
;
402 setup
->cullmode
= cull_mode
;
403 setup
->triangle
= first_triangle
;
409 lp_setup_set_fs_inputs( struct setup_context
*setup
,
410 const struct lp_shader_input
*input
,
413 SETUP_DEBUG("%s\n", __FUNCTION__
);
415 memcpy( setup
->fs
.input
, input
, nr
* sizeof input
[0] );
416 setup
->fs
.nr_inputs
= nr
;
420 lp_setup_set_fs( struct setup_context
*setup
,
421 struct lp_fragment_shader
*fs
)
423 SETUP_DEBUG("%s\n", __FUNCTION__
);
424 /* FIXME: reference count */
426 setup
->fs
.current
.jit_function
= fs
? fs
->current
->jit_function
: NULL
;
430 lp_setup_set_fs_constants(struct setup_context
*setup
,
431 struct pipe_buffer
*buffer
)
433 SETUP_DEBUG("%s\n", __FUNCTION__
);
435 pipe_buffer_reference(&setup
->constants
.current
, buffer
);
437 setup
->dirty
|= LP_SETUP_NEW_CONSTANTS
;
442 lp_setup_set_alpha_ref_value( struct setup_context
*setup
,
443 float alpha_ref_value
)
445 SETUP_DEBUG("%s\n", __FUNCTION__
);
447 if(setup
->fs
.current
.jit_context
.alpha_ref_value
!= alpha_ref_value
) {
448 setup
->fs
.current
.jit_context
.alpha_ref_value
= alpha_ref_value
;
449 setup
->dirty
|= LP_SETUP_NEW_FS
;
454 lp_setup_set_blend_color( struct setup_context
*setup
,
455 const struct pipe_blend_color
*blend_color
)
457 SETUP_DEBUG("%s\n", __FUNCTION__
);
461 if(memcmp(&setup
->blend_color
.current
, blend_color
, sizeof *blend_color
) != 0) {
462 memcpy(&setup
->blend_color
.current
, blend_color
, sizeof *blend_color
);
463 setup
->dirty
|= LP_SETUP_NEW_BLEND_COLOR
;
468 lp_setup_set_sampler_textures( struct setup_context
*setup
,
469 unsigned num
, struct pipe_texture
**texture
)
471 struct pipe_texture
*dummy
;
474 SETUP_DEBUG("%s\n", __FUNCTION__
);
477 assert(num
<= PIPE_MAX_SAMPLERS
);
479 for (i
= 0; i
< PIPE_MAX_SAMPLERS
; i
++) {
480 struct pipe_texture
*tex
= i
< num
? texture
[i
] : NULL
;
482 /* FIXME: hold on to the reference */
484 pipe_texture_reference(&dummy
, tex
);
487 struct llvmpipe_texture
*lp_tex
= llvmpipe_texture(tex
);
488 struct lp_jit_texture
*jit_tex
;
489 jit_tex
= &setup
->fs
.current
.jit_context
.textures
[i
];
490 jit_tex
->width
= tex
->width
[0];
491 jit_tex
->height
= tex
->height
[0];
492 jit_tex
->stride
= lp_tex
->stride
[0];
494 jit_tex
->data
= lp_tex
->data
;
496 /* FIXME: map the rendertarget */
501 setup
->dirty
|= LP_SETUP_NEW_FS
;
505 lp_setup_is_texture_referenced( struct setup_context
*setup
,
506 const struct pipe_texture
*texture
)
509 return PIPE_UNREFERENCED
;
514 lp_setup_update_shader_state( struct setup_context
*setup
)
516 SETUP_DEBUG("%s\n", __FUNCTION__
);
518 assert(setup
->fs
.current
.jit_function
);
520 if(setup
->dirty
& LP_SETUP_NEW_BLEND_COLOR
) {
524 stored
= get_data_aligned(&setup
->data
, 4 * 16, 16);
526 for (i
= 0; i
< 4; ++i
) {
527 uint8_t c
= float_to_ubyte(setup
->blend_color
.current
.color
[i
]);
528 for (j
= 0; j
< 16; ++j
)
532 setup
->blend_color
.stored
= stored
;
534 setup
->fs
.current
.jit_context
.blend_color
= setup
->blend_color
.stored
;
535 setup
->dirty
|= LP_SETUP_NEW_FS
;
539 if(setup
->dirty
& LP_SETUP_NEW_CONSTANTS
) {
540 struct pipe_buffer
*buffer
= setup
->constants
.current
;
543 unsigned current_size
= buffer
->size
;
544 const void *current_data
= llvmpipe_buffer(buffer
)->data
;
546 /* TODO: copy only the actually used constants? */
548 if(setup
->constants
.stored_size
!= current_size
||
549 !setup
->constants
.stored_data
||
550 memcmp(setup
->constants
.stored_data
,
552 current_size
) != 0) {
555 stored
= get_data(&setup
->data
, current_size
);
560 setup
->constants
.stored_size
= current_size
;
561 setup
->constants
.stored_data
= stored
;
566 setup
->constants
.stored_size
= 0;
567 setup
->constants
.stored_data
= NULL
;
570 setup
->fs
.current
.jit_context
.constants
= setup
->constants
.stored_data
;
571 setup
->dirty
|= LP_SETUP_NEW_FS
;
575 if(setup
->dirty
& LP_SETUP_NEW_FS
) {
576 if(!setup
->fs
.stored
||
577 memcmp(setup
->fs
.stored
,
579 sizeof setup
->fs
.current
) != 0) {
580 struct lp_rast_state
*stored
;
582 stored
= get_data(&setup
->data
, sizeof *stored
);
586 sizeof setup
->fs
.current
);
587 setup
->fs
.stored
= stored
;
594 assert(setup
->fs
.stored
);
598 /* Stubs for lines & points for now:
601 lp_setup_point(struct setup_context
*setup
,
602 const float (*v0
)[4])
604 lp_setup_update_shader_state(setup
);
605 setup
->point( setup
, v0
);
609 lp_setup_line(struct setup_context
*setup
,
610 const float (*v0
)[4],
611 const float (*v1
)[4])
613 lp_setup_update_shader_state(setup
);
614 setup
->line( setup
, v0
, v1
);
618 lp_setup_tri(struct setup_context
*setup
,
619 const float (*v0
)[4],
620 const float (*v1
)[4],
621 const float (*v2
)[4])
623 SETUP_DEBUG("%s\n", __FUNCTION__
);
625 lp_setup_update_shader_state(setup
);
626 setup
->triangle( setup
, v0
, v1
, v2
);
631 lp_setup_destroy( struct setup_context
*setup
)
635 reset_context( setup
);
637 pipe_buffer_reference(&setup
->constants
.current
, NULL
);
639 for (i
= 0; i
< TILES_X
; i
++)
640 for (j
= 0; j
< TILES_Y
; j
++)
641 FREE(setup
->tile
[i
][j
].head
);
643 FREE(setup
->data
.head
);
645 lp_rast_destroy( setup
->rast
);
651 * Create a new primitive tiling engine. Currently also creates a
652 * rasterizer to use with it.
654 struct setup_context
*
655 lp_setup_create( struct pipe_screen
*screen
)
657 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
660 setup
->rast
= lp_rast_create( screen
);
664 for (i
= 0; i
< TILES_X
; i
++)
665 for (j
= 0; j
< TILES_Y
; j
++)
666 setup
->tile
[i
][j
].head
=
667 setup
->tile
[i
][j
].tail
= CALLOC_STRUCT(cmd_block
);
670 setup
->data
.tail
= CALLOC_STRUCT(data_block
);
672 setup
->triangle
= first_triangle
;
673 setup
->line
= first_line
;
674 setup
->point
= first_point
;