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 static void set_state( struct setup_context
*, unsigned );
47 void lp_setup_new_cmd_block( struct cmd_block_list
*list
)
49 struct cmd_block
*block
= MALLOC_STRUCT(cmd_block
);
50 list
->tail
->next
= block
;
56 void lp_setup_new_data_block( struct data_block_list
*list
)
58 struct data_block
*block
= MALLOC_STRUCT(data_block
);
59 list
->tail
->next
= block
;
67 first_triangle( struct setup_context
*setup
,
72 set_state( setup
, SETUP_ACTIVE
);
73 lp_setup_choose_triangle( setup
);
74 setup
->triangle( setup
, v0
, v1
, v2
);
78 first_line( struct setup_context
*setup
,
82 set_state( setup
, SETUP_ACTIVE
);
83 lp_setup_choose_line( setup
);
84 setup
->line( setup
, v0
, v1
);
88 first_point( struct setup_context
*setup
,
91 set_state( setup
, SETUP_ACTIVE
);
92 lp_setup_choose_point( setup
);
93 setup
->point( setup
, v0
);
96 static void reset_context( struct setup_context
*setup
)
100 /* Free binner command lists:
102 for (i
= 0; i
< setup
->tiles_x
; i
++) {
103 for (j
= 0; j
< setup
->tiles_y
; j
++) {
104 struct cmd_block_list
*list
= &setup
->tile
[i
][j
];
105 struct cmd_block
*block
;
106 struct cmd_block
*tmp
;
108 for (block
= list
->head
; block
!= list
->tail
; block
= tmp
) {
113 list
->head
= list
->tail
;
120 struct data_block_list
*list
= &setup
->data
;
121 struct data_block
*block
, *tmp
;
123 for (block
= list
->head
; block
!= list
->tail
; block
= tmp
) {
128 list
->head
= list
->tail
;
133 setup
->clear
.flags
= 0;
135 /* Have an explicit "start-binning" call and get rid of this
138 setup
->line
= first_line
;
139 setup
->point
= first_point
;
140 setup
->triangle
= first_triangle
;
146 /* Add a command to all active bins.
148 static void bin_everywhere( struct setup_context
*setup
,
150 const union lp_rast_cmd_arg arg
)
153 for (i
= 0; i
< setup
->tiles_x
; i
++)
154 for (j
= 0; j
< setup
->tiles_y
; j
++)
155 bin_command( &setup
->tile
[i
][j
], cmd
, arg
);
160 rasterize_bins( struct setup_context
*setup
,
161 boolean write_depth
)
163 struct lp_rasterizer
*rast
= setup
->rast
;
164 struct cmd_block
*block
;
171 lp_rast_bind_color( rast
,
173 setup
->fb
.cbuf
!= NULL
);
175 lp_rast_bind_zstencil( rast
,
177 setup
->fb
.zsbuf
!= NULL
&& write_depth
);
179 for (i
= 0; i
< setup
->tiles_x
; i
++) {
180 for (j
= 0; j
< setup
->tiles_y
; j
++) {
182 lp_rast_start_tile( rast
,
186 for (block
= setup
->tile
[i
][j
].head
; block
; block
= block
->next
) {
187 for (k
= 0; k
< block
->count
; k
++) {
188 block
->cmd
[k
]( rast
, block
->arg
[k
] );
192 lp_rast_end_tile( rast
);
196 reset_context( setup
);
202 begin_binning( struct setup_context
*setup
)
204 if (!setup
->fb
.cbuf
&& !setup
->fb
.zsbuf
) {
206 setup
->fb
.height
= 0;
208 else if (!setup
->fb
.zsbuf
) {
209 setup
->fb
.width
= setup
->fb
.cbuf
->width
;
210 setup
->fb
.height
= setup
->fb
.cbuf
->height
;
212 else if (!setup
->fb
.cbuf
) {
213 setup
->fb
.width
= setup
->fb
.zsbuf
->width
;
214 setup
->fb
.height
= setup
->fb
.zsbuf
->height
;
217 /* XXX: not sure what we're really supposed to do for
218 * mis-matched color & depth buffer sizes.
220 setup
->fb
.width
= MIN2(setup
->fb
.cbuf
->width
,
221 setup
->fb
.zsbuf
->width
);
222 setup
->fb
.height
= MIN2(setup
->fb
.cbuf
->height
,
223 setup
->fb
.zsbuf
->height
);
226 setup
->tiles_x
= align(setup
->fb
.width
, TILESIZE
) / TILESIZE
;
227 setup
->tiles_y
= align(setup
->fb
.height
, TILESIZE
) / TILESIZE
;
229 if (setup
->fb
.cbuf
) {
230 if (setup
->clear
.flags
& PIPE_CLEAR_COLOR
)
231 bin_everywhere( setup
,
233 setup
->clear
.color
);
235 bin_everywhere( setup
, lp_rast_load_color
, lp_rast_arg_null() );
238 if (setup
->fb
.zsbuf
) {
239 if (setup
->clear
.flags
& PIPE_CLEAR_DEPTHSTENCIL
)
240 bin_everywhere( setup
,
241 lp_rast_clear_zstencil
,
242 setup
->clear
.zstencil
);
244 bin_everywhere( setup
, lp_rast_load_zstencil
, lp_rast_arg_null() );
249 /* This basically bins and then flushes any outstanding full-screen
252 * TODO: fast path for fullscreen clears and no triangles.
255 execute_clears( struct setup_context
*setup
)
257 begin_binning( setup
);
258 rasterize_bins( setup
, TRUE
);
263 set_state( struct setup_context
*setup
,
266 unsigned old_state
= setup
->state
;
268 if (old_state
== new_state
)
273 if (old_state
== SETUP_FLUSHED
)
274 begin_binning( setup
);
278 if (old_state
== SETUP_ACTIVE
) {
285 if (old_state
== SETUP_CLEARED
)
286 execute_clears( setup
);
288 rasterize_bins( setup
, TRUE
);
292 setup
->state
= new_state
;
297 lp_setup_flush( struct setup_context
*setup
,
300 set_state( setup
, SETUP_FLUSHED
);
305 lp_setup_bind_framebuffer( struct setup_context
*setup
,
306 struct pipe_surface
*color
,
307 struct pipe_surface
*zstencil
)
309 set_state( setup
, SETUP_FLUSHED
);
311 pipe_surface_reference( &setup
->fb
.cbuf
, color
);
312 pipe_surface_reference( &setup
->fb
.zsbuf
, zstencil
);
316 lp_setup_clear( struct setup_context
*setup
,
324 if (flags
& PIPE_CLEAR_COLOR
) {
325 for (i
= 0; i
< 4; ++i
)
326 setup
->clear
.color
.clear_color
[i
] = float_to_ubyte(color
[i
]);
329 if (flags
& PIPE_CLEAR_DEPTHSTENCIL
) {
330 setup
->clear
.zstencil
.clear_zstencil
=
331 util_pack_z_stencil(setup
->fb
.zsbuf
->format
,
336 if (setup
->state
== SETUP_ACTIVE
) {
337 /* Add the clear to existing bins. In the unusual case where
338 * both color and depth-stencilare being cleared, we could
339 * discard the currently binned scene and start again, but I
340 * don't see that as being a common usage.
342 if (flags
& PIPE_CLEAR_COLOR
)
343 bin_everywhere( setup
,
345 setup
->clear
.color
);
347 if (setup
->clear
.flags
& PIPE_CLEAR_DEPTHSTENCIL
)
348 bin_everywhere( setup
,
349 lp_rast_clear_zstencil
,
350 setup
->clear
.zstencil
);
353 /* Put ourselves into the 'pre-clear' state, specifically to try
354 * and accumulate multiple clears to color and depth_stencil
355 * buffers which the app or state-tracker might issue
358 set_state( setup
, SETUP_CLEARED
);
360 setup
->clear
.flags
|= flags
;
367 lp_setup_set_triangle_state( struct setup_context
*setup
,
369 boolean ccw_is_frontface
)
371 setup
->ccw_is_frontface
= ccw_is_frontface
;
372 setup
->cullmode
= cull_mode
;
373 setup
->triangle
= first_triangle
;
379 lp_setup_set_fs_inputs( struct setup_context
*setup
,
380 const struct lp_shader_input
*input
,
383 memcpy( setup
->fs
.input
, input
, nr
* sizeof input
[0] );
384 setup
->fs
.nr_inputs
= nr
;
388 lp_setup_set_fs( struct setup_context
*setup
,
389 struct lp_fragment_shader
*fs
)
391 /* FIXME: reference count */
393 setup
->fs
.jit_function
= fs
->current
->jit_function
;
397 lp_setup_set_fs_constants(struct setup_context
*setup
,
398 struct pipe_buffer
*buffer
)
400 const void *data
= buffer
? llvmpipe_buffer(buffer
)->data
: NULL
;
401 struct pipe_buffer
*dummy
;
403 /* FIXME: hold on to the reference */
405 pipe_buffer_reference(&dummy
, buffer
);
407 setup
->fs
.jit_context
.constants
= data
;
409 setup
->fs
.jit_context_dirty
= TRUE
;
414 lp_setup_set_alpha_ref_value( struct setup_context
*setup
,
415 float alpha_ref_value
)
417 if(setup
->fs
.jit_context
.alpha_ref_value
!= alpha_ref_value
) {
418 setup
->fs
.jit_context
.alpha_ref_value
= alpha_ref_value
;
419 setup
->fs
.jit_context_dirty
= TRUE
;
424 lp_setup_set_blend_color( struct setup_context
*setup
,
425 const struct pipe_blend_color
*blend_color
)
429 if(!setup
->fs
.jit_context
.blend_color
)
430 setup
->fs
.jit_context
.blend_color
= align_malloc(4 * 16, 16);
432 for (i
= 0; i
< 4; ++i
) {
433 uint8_t c
= float_to_ubyte(blend_color
->color
[i
]);
434 for (j
= 0; j
< 16; ++j
)
435 setup
->fs
.jit_context
.blend_color
[i
*4 + j
] = c
;
438 setup
->fs
.jit_context_dirty
= TRUE
;
442 lp_setup_set_sampler_textures( struct setup_context
*setup
,
443 unsigned num
, struct pipe_texture
**texture
)
445 struct pipe_texture
*dummy
;
448 assert(num
<= PIPE_MAX_SAMPLERS
);
450 for (i
= 0; i
< PIPE_MAX_SAMPLERS
; i
++) {
451 struct pipe_texture
*tex
= i
< num
? texture
[i
] : NULL
;
453 /* FIXME: hold on to the reference */
455 pipe_texture_reference(&dummy
, tex
);
458 struct llvmpipe_texture
*lp_tex
= llvmpipe_texture(tex
);
459 struct lp_jit_texture
*jit_tex
= &setup
->fs
.jit_context
.textures
[i
];
460 jit_tex
->width
= tex
->width
[0];
461 jit_tex
->height
= tex
->height
[0];
462 jit_tex
->stride
= lp_tex
->stride
[0];
464 jit_tex
->data
= lp_tex
->data
;
466 /* FIXME: map the rendertarget */
471 setup
->fs
.jit_context_dirty
= TRUE
;
475 lp_setup_is_texture_referenced( struct setup_context
*setup
,
476 const struct pipe_texture
*texture
)
479 return PIPE_UNREFERENCED
;
483 /* Stubs for lines & points for now:
486 lp_setup_point(struct setup_context
*setup
,
487 const float (*v0
)[4])
489 setup
->point( setup
, v0
);
493 lp_setup_line(struct setup_context
*setup
,
494 const float (*v0
)[4],
495 const float (*v1
)[4])
497 setup
->line( setup
, v0
, v1
);
501 lp_setup_tri(struct setup_context
*setup
,
502 const float (*v0
)[4],
503 const float (*v1
)[4],
504 const float (*v2
)[4])
506 setup
->triangle( setup
, v0
, v1
, v2
);
511 lp_setup_destroy( struct setup_context
*setup
)
515 reset_context( setup
);
517 for (i
= 0; i
< TILES_X
; i
++)
518 for (j
= 0; j
< TILES_Y
; j
++)
519 FREE(setup
->tile
[i
][j
].head
);
521 lp_rast_destroy( setup
->rast
);
527 * Create a new primitive tiling engine. Currently also creates a
528 * rasterizer to use with it.
530 struct setup_context
*
531 lp_setup_create( void )
533 struct setup_context
*setup
= CALLOC_STRUCT(setup_context
);
536 setup
->rast
= lp_rast_create();
540 for (i
= 0; i
< TILES_X
; i
++)
541 for (j
= 0; j
< TILES_Y
; j
++)
542 setup
->tile
[i
][j
].head
=
543 setup
->tile
[i
][j
].tail
= CALLOC_STRUCT(cmd_block
);