lp_setup.c revision b08583da468ee186b43ea678f8d33fb7df3ab372
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_memory.h" 38#include "util/u_pack_color.h" 39#include "util/u_surface.h" 40#include "lp_scene.h" 41#include "lp_scene_queue.h" 42#include "lp_buffer.h" 43#include "lp_texture.h" 44#include "lp_debug.h" 45#include "lp_fence.h" 46#include "lp_rast.h" 47#include "lp_setup_context.h" 48 49#include "draw/draw_context.h" 50#include "draw/draw_vbuf.h" 51 52 53/** XXX temporary value, temporary here */ 54#define MAX_SCENES 2 55 56 57static void set_scene_state( struct setup_context *, unsigned ); 58 59 60struct lp_scene * 61lp_setup_get_current_scene(struct setup_context *setup) 62{ 63 if (!setup->scene) { 64 /* wait for a free/empty bin */ 65 setup->scene = lp_scene_dequeue(setup->empty_scenes); 66 if(0)lp_scene_reset( setup->scene ); /* XXX temporary? */ 67 68 lp_scene_set_framebuffer_size(setup->scene, 69 setup->fb.width, 70 setup->fb.height); 71 } 72 return setup->scene; 73} 74 75 76static void 77first_triangle( struct setup_context *setup, 78 const float (*v0)[4], 79 const float (*v1)[4], 80 const float (*v2)[4]) 81{ 82 set_scene_state( setup, SETUP_ACTIVE ); 83 lp_setup_choose_triangle( setup ); 84 setup->triangle( setup, v0, v1, v2 ); 85} 86 87static void 88first_line( struct setup_context *setup, 89 const float (*v0)[4], 90 const float (*v1)[4]) 91{ 92 set_scene_state( setup, SETUP_ACTIVE ); 93 lp_setup_choose_line( setup ); 94 setup->line( setup, v0, v1 ); 95} 96 97static void 98first_point( struct setup_context *setup, 99 const float (*v0)[4]) 100{ 101 set_scene_state( setup, SETUP_ACTIVE ); 102 lp_setup_choose_point( setup ); 103 setup->point( setup, v0 ); 104} 105 106static void reset_context( struct setup_context *setup ) 107{ 108 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 109 110 /* Reset derived state */ 111 setup->constants.stored_size = 0; 112 setup->constants.stored_data = NULL; 113 setup->fs.stored = NULL; 114 setup->dirty = ~0; 115 116 /* no current bin */ 117 setup->scene = NULL; 118 119 /* Reset some state: 120 */ 121 setup->clear.flags = 0; 122 123 /* Have an explicit "start-binning" call and get rid of this 124 * pointer twiddling? 125 */ 126 setup->line = first_line; 127 setup->point = first_point; 128 setup->triangle = first_triangle; 129} 130 131 132/** Rasterize all scene's bins */ 133static void 134lp_setup_rasterize_scene( struct setup_context *setup, 135 boolean write_depth ) 136{ 137 struct lp_scene *scene = lp_setup_get_current_scene(setup); 138 139 lp_rasterize_scene(setup->rast, 140 scene, 141 &setup->fb, 142 write_depth); 143 144 reset_context( setup ); 145 146 LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); 147} 148 149 150 151static void 152begin_binning( struct setup_context *setup ) 153{ 154 struct lp_scene *scene = lp_setup_get_current_scene(setup); 155 156 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 157 158 if (setup->fb.cbufs[0]) { 159 if (setup->clear.flags & PIPE_CLEAR_COLOR) 160 lp_scene_bin_everywhere( scene, 161 lp_rast_clear_color, 162 setup->clear.color ); 163 else 164 lp_scene_bin_everywhere( scene, 165 lp_rast_load_color, 166 lp_rast_arg_null() ); 167 } 168 169 if (setup->fb.zsbuf) { 170 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) 171 lp_scene_bin_everywhere( scene, 172 lp_rast_clear_zstencil, 173 setup->clear.zstencil ); 174 else 175 lp_scene_bin_everywhere( scene, 176 lp_rast_load_zstencil, 177 lp_rast_arg_null() ); 178 } 179 180 LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); 181} 182 183 184/* This basically bins and then flushes any outstanding full-screen 185 * clears. 186 * 187 * TODO: fast path for fullscreen clears and no triangles. 188 */ 189static void 190execute_clears( struct setup_context *setup ) 191{ 192 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 193 194 begin_binning( setup ); 195 lp_setup_rasterize_scene( setup, TRUE ); 196} 197 198 199static void 200set_scene_state( struct setup_context *setup, 201 unsigned new_state ) 202{ 203 unsigned old_state = setup->state; 204 205 if (old_state == new_state) 206 return; 207 208 LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state); 209 210 switch (new_state) { 211 case SETUP_ACTIVE: 212 begin_binning( setup ); 213 break; 214 215 case SETUP_CLEARED: 216 if (old_state == SETUP_ACTIVE) { 217 assert(0); 218 return; 219 } 220 break; 221 222 case SETUP_FLUSHED: 223 if (old_state == SETUP_CLEARED) 224 execute_clears( setup ); 225 else 226 lp_setup_rasterize_scene( setup, TRUE ); 227 break; 228 } 229 230 setup->state = new_state; 231} 232 233 234void 235lp_setup_flush( struct setup_context *setup, 236 unsigned flags ) 237{ 238 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 239 240 set_scene_state( setup, SETUP_FLUSHED ); 241} 242 243 244void 245lp_setup_bind_framebuffer( struct setup_context *setup, 246 const struct pipe_framebuffer_state *fb ) 247{ 248 struct lp_scene *scene = lp_setup_get_current_scene(setup); 249 250 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 251 252 set_scene_state( setup, SETUP_FLUSHED ); 253 254 util_copy_framebuffer_state(&setup->fb, fb); 255 256 lp_scene_set_framebuffer_size(scene, setup->fb.width, setup->fb.height); 257} 258 259 260void 261lp_setup_clear( struct setup_context *setup, 262 const float *color, 263 double depth, 264 unsigned stencil, 265 unsigned flags ) 266{ 267 struct lp_scene *scene = lp_setup_get_current_scene(setup); 268 unsigned i; 269 270 LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 271 272 273 if (flags & PIPE_CLEAR_COLOR) { 274 for (i = 0; i < 4; ++i) 275 setup->clear.color.clear_color[i] = float_to_ubyte(color[i]); 276 } 277 278 if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 279 setup->clear.zstencil.clear_zstencil = 280 util_pack_z_stencil(setup->fb.zsbuf->format, 281 depth, 282 stencil); 283 } 284 285 if (setup->state == SETUP_ACTIVE) { 286 /* Add the clear to existing scene. In the unusual case where 287 * both color and depth-stencil are being cleared when there's 288 * already been some rendering, we could discard the currently 289 * binned scene and start again, but I don't see that as being 290 * a common usage. 291 */ 292 if (flags & PIPE_CLEAR_COLOR) 293 lp_scene_bin_everywhere( scene, 294 lp_rast_clear_color, 295 setup->clear.color ); 296 297 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) 298 lp_scene_bin_everywhere( scene, 299 lp_rast_clear_zstencil, 300 setup->clear.zstencil ); 301 } 302 else { 303 /* Put ourselves into the 'pre-clear' state, specifically to try 304 * and accumulate multiple clears to color and depth_stencil 305 * buffers which the app or state-tracker might issue 306 * separately. 307 */ 308 set_scene_state( setup, SETUP_CLEARED ); 309 310 setup->clear.flags |= flags; 311 } 312} 313 314 315/** 316 * Emit a fence. 317 */ 318struct pipe_fence_handle * 319lp_setup_fence( struct setup_context *setup ) 320{ 321 struct lp_scene *scene = lp_setup_get_current_scene(setup); 322 const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ 323 struct lp_fence *fence = lp_fence_create(rank); 324 325 LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); 326 327 set_scene_state( setup, SETUP_ACTIVE ); 328 329 /* insert the fence into all command bins */ 330 lp_scene_bin_everywhere( scene, 331 lp_rast_fence, 332 lp_rast_arg_fence(fence) ); 333 334 return (struct pipe_fence_handle *) fence; 335} 336 337 338void 339lp_setup_set_triangle_state( struct setup_context *setup, 340 unsigned cull_mode, 341 boolean ccw_is_frontface) 342{ 343 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 344 345 setup->ccw_is_frontface = ccw_is_frontface; 346 setup->cullmode = cull_mode; 347 setup->triangle = first_triangle; 348} 349 350 351 352void 353lp_setup_set_fs_inputs( struct setup_context *setup, 354 const struct lp_shader_input *input, 355 unsigned nr ) 356{ 357 LP_DBG(DEBUG_SETUP, "%s %p %u\n", __FUNCTION__, (void *) input, nr); 358 359 memcpy( setup->fs.input, input, nr * sizeof input[0] ); 360 setup->fs.nr_inputs = nr; 361} 362 363void 364lp_setup_set_fs_function( struct setup_context *setup, 365 lp_jit_frag_func jit_function ) 366{ 367 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) jit_function); 368 /* FIXME: reference count */ 369 370 setup->fs.current.jit_function = jit_function; 371 setup->dirty |= LP_SETUP_NEW_FS; 372} 373 374void 375lp_setup_set_fs_constants(struct setup_context *setup, 376 struct pipe_buffer *buffer) 377{ 378 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); 379 380 pipe_buffer_reference(&setup->constants.current, buffer); 381 382 setup->dirty |= LP_SETUP_NEW_CONSTANTS; 383} 384 385 386void 387lp_setup_set_alpha_ref_value( struct setup_context *setup, 388 float alpha_ref_value ) 389{ 390 LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); 391 392 if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { 393 setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; 394 setup->dirty |= LP_SETUP_NEW_FS; 395 } 396} 397 398void 399lp_setup_set_blend_color( struct setup_context *setup, 400 const struct pipe_blend_color *blend_color ) 401{ 402 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 403 404 assert(blend_color); 405 406 if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) { 407 memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); 408 setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; 409 } 410} 411 412 413void 414lp_setup_set_flatshade_first( struct setup_context *setup, 415 boolean flatshade_first ) 416{ 417 setup->flatshade_first = flatshade_first; 418} 419 420 421void 422lp_setup_set_vertex_info( struct setup_context *setup, 423 struct vertex_info *vertex_info ) 424{ 425 /* XXX: just silently holding onto the pointer: 426 */ 427 setup->vertex_info = vertex_info; 428} 429 430 431void 432lp_setup_set_sampler_textures( struct setup_context *setup, 433 unsigned num, struct pipe_texture **texture) 434{ 435 struct pipe_texture *dummy; 436 unsigned i; 437 438 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 439 440 441 assert(num <= PIPE_MAX_SAMPLERS); 442 443 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 444 struct pipe_texture *tex = i < num ? texture[i] : NULL; 445 446 /* FIXME: hold on to the reference */ 447 dummy = NULL; 448 pipe_texture_reference(&dummy, tex); 449 450 if(tex) { 451 struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex); 452 struct lp_jit_texture *jit_tex; 453 jit_tex = &setup->fs.current.jit_context.textures[i]; 454 jit_tex->width = tex->width[0]; 455 jit_tex->height = tex->height[0]; 456 jit_tex->stride = lp_tex->stride[0]; 457 if(!lp_tex->dt) 458 jit_tex->data = lp_tex->data; 459 else 460 /* FIXME: map the rendertarget */ 461 assert(0); 462 } 463 } 464 465 setup->dirty |= LP_SETUP_NEW_FS; 466} 467 468boolean 469lp_setup_is_texture_referenced( struct setup_context *setup, 470 const struct pipe_texture *texture ) 471{ 472 /* FIXME */ 473 return PIPE_UNREFERENCED; 474} 475 476 477void 478lp_setup_update_state( struct setup_context *setup ) 479{ 480 struct lp_scene *scene = lp_setup_get_current_scene(setup); 481 482 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 483 484 assert(setup->fs.current.jit_function); 485 486 if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { 487 uint8_t *stored; 488 unsigned i, j; 489 490 stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); 491 492 /* smear each blend color component across 16 ubyte elements */ 493 for (i = 0; i < 4; ++i) { 494 uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); 495 for (j = 0; j < 16; ++j) 496 stored[i*16 + j] = c; 497 } 498 499 setup->blend_color.stored = stored; 500 501 setup->fs.current.jit_context.blend_color = setup->blend_color.stored; 502 setup->dirty |= LP_SETUP_NEW_FS; 503 } 504 505 506 if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { 507 struct pipe_buffer *buffer = setup->constants.current; 508 509 if(buffer) { 510 unsigned current_size = buffer->size; 511 const void *current_data = llvmpipe_buffer(buffer)->data; 512 513 /* TODO: copy only the actually used constants? */ 514 515 if(setup->constants.stored_size != current_size || 516 !setup->constants.stored_data || 517 memcmp(setup->constants.stored_data, 518 current_data, 519 current_size) != 0) { 520 void *stored; 521 522 stored = lp_scene_alloc(scene, current_size); 523 if(stored) { 524 memcpy(stored, 525 current_data, 526 current_size); 527 setup->constants.stored_size = current_size; 528 setup->constants.stored_data = stored; 529 } 530 } 531 } 532 else { 533 setup->constants.stored_size = 0; 534 setup->constants.stored_data = NULL; 535 } 536 537 setup->fs.current.jit_context.constants = setup->constants.stored_data; 538 setup->dirty |= LP_SETUP_NEW_FS; 539 } 540 541 542 if(setup->dirty & LP_SETUP_NEW_FS) { 543 if(!setup->fs.stored || 544 memcmp(setup->fs.stored, 545 &setup->fs.current, 546 sizeof setup->fs.current) != 0) { 547 /* The fs state that's been stored in the scene is different from 548 * the new, current state. So allocate a new lp_rast_state object 549 * and append it to the bin's setup data buffer. 550 */ 551 struct lp_rast_state *stored = 552 (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); 553 if(stored) { 554 memcpy(stored, 555 &setup->fs.current, 556 sizeof setup->fs.current); 557 setup->fs.stored = stored; 558 559 /* put the state-set command into all bins */ 560 lp_scene_bin_state_command( scene, 561 lp_rast_set_state, 562 lp_rast_arg_state(setup->fs.stored) ); 563 } 564 } 565 } 566 567 setup->dirty = 0; 568 569 assert(setup->fs.stored); 570} 571 572 573 574/* Only caller is lp_setup_vbuf_destroy() 575 */ 576void 577lp_setup_destroy( struct setup_context *setup ) 578{ 579 reset_context( setup ); 580 581 pipe_buffer_reference(&setup->constants.current, NULL); 582 583 /* free the scenes in the 'empty' queue */ 584 while (lp_scene_queue_count(setup->empty_scenes) > 0) { 585 struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes); 586 if (!scene) 587 break; 588 lp_scene_destroy(scene); 589 } 590 591 lp_rast_destroy( setup->rast ); 592 593 FREE( setup ); 594} 595 596 597/** 598 * Create a new primitive tiling engine. Plug it into the backend of 599 * the draw module. Currently also creates a rasterizer to use with 600 * it. 601 */ 602struct setup_context * 603lp_setup_create( struct pipe_screen *screen, 604 struct draw_context *draw ) 605{ 606 unsigned i; 607 struct setup_context *setup = CALLOC_STRUCT(setup_context); 608 609 if (!setup) 610 return NULL; 611 612 lp_setup_init_vbuf(setup); 613 614 setup->empty_scenes = lp_scene_queue_create(); 615 if (!setup->empty_scenes) 616 goto fail; 617 618 setup->rast = lp_rast_create( screen, setup->empty_scenes ); 619 if (!setup->rast) 620 goto fail; 621 622 setup->vbuf = draw_vbuf_stage(draw, &setup->base); 623 if (!setup->vbuf) 624 goto fail; 625 626 draw_set_rasterize_stage(draw, setup->vbuf); 627 draw_set_render(draw, &setup->base); 628 629 /* create some empty scenes */ 630 for (i = 0; i < MAX_SCENES; i++) { 631 struct lp_scene *scene = lp_scene_create(); 632 lp_scene_enqueue(setup->empty_scenes, scene); 633 } 634 635 setup->triangle = first_triangle; 636 setup->line = first_line; 637 setup->point = first_point; 638 639 setup->dirty = ~0; 640 641 return setup; 642 643fail: 644 if (setup->rast) 645 lp_rast_destroy( setup->rast ); 646 647 if (setup->vbuf) 648 ; 649 650 if (setup->empty_scenes) 651 lp_scene_queue_destroy(setup->empty_scenes); 652 653 FREE(setup); 654 return NULL; 655} 656 657