lp_setup.c revision 931210424bc46b2c13919f0ac3e0ef781eff207e
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 "lp_setup.h" 36#include "util/u_math.h" 37#include "util/u_memory.h" 38 39void lp_setup_new_cmd_block( struct cmd_block_list *list ) 40{ 41 struct cmd_block *block = MALLOC_STRUCT(cmd_block); 42 list->tail->next = block; 43 list->tail = block; 44 block->next = NULL; 45 block->count = 0; 46} 47 48void lp_setup_new_data_block( struct data_block_list *list ) 49{ 50 struct data_block *block = MALLOC_STRUCT(data_block); 51 list->tail->next = block; 52 list->tail = block; 53 block->next = NULL; 54 block->used = 0; 55} 56 57static void reset_context( struct setup_context *setup ) 58{ 59 for (i = 0; i < setup->tiles_x; i++) { 60 for (j = 0; j < setup->tiles_y; j++) { 61 struct cmd_block_list *list = scene->tile[i][j]; 62 struct cmd_block *block; 63 struct cmd_block *tmp; 64 65 for (block = list->first; block != list->tail; block = tmp) { 66 tmp = block->next; 67 FREE(block); 68 } 69 70 list->first = list->tail; 71 } 72 } 73 74 { 75 struct data_block_list *list = &scene->data; 76 struct data_block *block, *tmp; 77 78 for (block = list->first; block != list->tail; block = tmp) { 79 tmp = block->next; 80 FREE(block); 81 } 82 83 list->first = list->tail; 84 } 85} 86 87 88 89 90/* Add a command to all active bins. 91 */ 92static void bin_everywhere( struct setup_context *setup, 93 bin_cmd cmd, 94 const union lp_rast_cmd_arg *arg ) 95{ 96 unsigned i, j; 97 for (i = 0; i < setup->tiles_x; i++) 98 for (j = 0; j < setup->tiles_y; j++) 99 bin_cmd( setup, &setup->tile[i][j], cmd, arg ); 100} 101 102 103static void 104rasterize_bins( struct setup_context *setup, 105 struct lp_rast *rast, 106 boolean write_depth ) 107{ 108 lp_rast_bind_color( rast, 109 scene->fb.color, 110 TRUE ); /* WRITE */ 111 112 lp_rast_bind_depth( rast, 113 scene->fb.depth, 114 write_depth ); /* WRITE */ 115 116 for (i = 0; i < scene->tiles_x; i++) { 117 for (j = 0; j < scene->tiles_y; j++) { 118 119 lp_rast_start_tile( rast, 120 i * TILESIZE, 121 j * TILESIZE ); 122 123 for (block = scene->tile[i][j].first; block; block = block->next) { 124 for (k = 0; k < block->nr_cmds; k++) { 125 block->cmd[k].func( rast, block->cmd[k].arg ); 126 } 127 } 128 129 lp_rast_finish_tile( rast ); 130 } 131 } 132 133 lp_setup_free_data( setup ); 134} 135 136 137 138static void 139begin_binning( struct setup_context *setup ) 140{ 141 if (setup->fb.color) { 142 if (setup->fb.clear_color) 143 bin_everywhere( setup, 144 lp_rast_clear_color, 145 &setup->clear_data ); 146 else 147 bin_everywhere( setup, 148 lp_rast_load_color, 149 NULL ); 150 } 151 152 if (setup->fb.zstencil) { 153 if (setup->fb.clear_zstencil) 154 bin_everywhere( setup, 155 lp_rast_clear_zstencil, 156 &setup->clear_data ); 157 else 158 bin_everywhere( setup, 159 lp_rast_load_zstencil, 160 NULL ); 161 } 162} 163 164 165/* This basically bins and then flushes any outstanding full-screen 166 * clears. 167 * 168 * TODO: fast path for fullscreen clears and no triangles. 169 */ 170static void 171execute_clears( struct setup_context *setup ) 172{ 173 begin_binning( setup ); 174 rasterize_bins( setup ); 175} 176 177 178static void 179set_state( struct setup_context *setup, 180 unsigned new_state ) 181{ 182 unsigned old_state = setup->state; 183 184 if (old_state == new_state) 185 return; 186 187 switch (new_state) { 188 case SETUP_ACTIVE: 189 if (old_state == SETUP_FLUSHED) 190 setup_begin_binning( setup ); 191 break; 192 193 case SETUP_CLEARED: 194 if (old_state == SETUP_ACTIVE) { 195 assert(0); 196 return; 197 } 198 break; 199 200 case SETUP_FLUSHED: 201 if (old_state == SETUP_CLEAR) 202 execute_clears( setup ); 203 else 204 rasterize_bins( setup ); 205 break; 206 } 207 208 setup->state = new_state; 209} 210 211 212void 213lp_setup_flush( struct setup_context *setup, 214 unsigned flags ) 215{ 216 set_state( setup, SETUP_FLUSHED ); 217} 218 219 220void 221lp_setup_bind_framebuffer( struct setup_context *setup, 222 struct pipe_surface *color, 223 struct pipe_surface *zstencil ) 224{ 225 unsigned width, height; 226 227 set_state( setup, SETUP_FLUSHED ); 228 229 pipe_surface_reference( &setup->fb.color, color ); 230 pipe_surface_reference( &setup->fb.zstencil, zstencil ); 231 232 width = MAX2( color->width, zstencil->width ); 233 height = MAX2( color->height, zstencil->height ); 234 235 setup->tiles_x = align( width, TILESIZE ) / TILESIZE; 236 setup->tiles_y = align( height, TILESIZE ) / TILESIZE; 237} 238 239void 240lp_setup_clear( struct setup_context *setup, 241 const float *clear_color, 242 double clear_depth, 243 unsigned clear_stencil, 244 unsigned flags ) 245{ 246 if (setup->state == SETUP_ACTIVE) { 247 struct lp_rast_clear_info *clear_info; 248 unsigned i, j; 249 250 clear_info = alloc_clear_info( setup ); 251 252 if (flags & PIPE_CLEAR_COLOR) { 253 pack_color( setup, 254 clear_info->color, 255 clear_color ); 256 bin_everywhere(setup, lp_rast_clear_color, clear_info ); 257 } 258 259 if (flags & PIPE_CLEAR_DEPTH_STENCIL) { 260 pack_depth_stencil( setup, 261 clear_info->depth, 262 clear_depth, 263 clear_stencil ); 264 265 bin_everywhere(setup, lp_rast_clear_zstencil, clear_info ); 266 } 267 } 268 else { 269 set_state( setup, SETUP_CLEARED ); 270 setup->clear.flags |= flags; 271 272 if (flags & PIPE_CLEAR_COLOR) { 273 memcpy(setup->clear.color, color, sizeof setup->clear.color); 274 } 275 276 if (flags & PIPE_CLEAR_DEPTH_STENCIL) { 277 setup->clear.depth = clear_depth; 278 setup->clear.stencil = clear_stencil; 279 } 280 } 281} 282 283 284void 285lp_setup_set_fs_inputs( struct setup_context *setup, 286 const enum lp_interp *interp, 287 unsigned nr ) 288{ 289 memcpy( setup->interp, interp, nr * sizeof interp[0] ); 290} 291 292 293static void 294first_triangle( struct setup_context *setup, 295 const float (*v0)[4], 296 const float (*v1)[4], 297 const float (*v2)[4]) 298{ 299 set_state( setup, STATE_ACTIVE ); 300 setup_choose_triangle( setup, v0, v1, v2 ); 301} 302 303 304 305/* Stubs for lines & points for now: 306 */ 307void 308lp_setup_point(struct setup_context *setup, 309 const float (*v0)[4]) 310{ 311 setup->point( setup, v0 ); 312} 313 314void 315lp_setup_line(struct setup_context *setup, 316 const float (*v0)[4], 317 const float (*v1)[4]) 318{ 319 setup->line( setup, v0, v1 ); 320} 321 322void 323lp_setup_triangle(struct setup_context *setup, 324 const float (*v0)[4], 325 const float (*v1)[4], 326 const float (*v2)[4]) 327{ 328 setup->triangle( setup, v0, v1, v2 ); 329} 330 331 332void setup_destroy_context( struct setup_context *setup ) 333{ 334 lp_rast_destroy( setup->rast ); 335 FREE( setup ); 336} 337 338 339/** 340 * Create a new primitive tiling engine. Currently also creates a 341 * rasterizer to use with it. 342 */ 343struct setup_context *setup_create_context( void ) 344{ 345 struct setup_context *setup = CALLOC_STRUCT(setup_context); 346 347 setup->rast = lp_rast_create( void ); 348 if (!setup->rast) 349 goto fail; 350 351 for (i = 0; i < TILES_X; i++) 352 for (j = 0; j < TILES_Y; j++) 353 setup->tile[i][j].first = 354 setup->tile[i][j].next = CALLOC_STRUCT(cmd_block); 355 356 return setup; 357 358fail: 359 FREE(setup); 360 return NULL; 361} 362 363