lp_setup.c revision 86afe8250edaa2e6129c937a62a695f616c48d70
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 <limits.h> 36 37#include "pipe/p_defines.h" 38#include "util/u_framebuffer.h" 39#include "util/u_inlines.h" 40#include "util/u_memory.h" 41#include "util/u_pack_color.h" 42#include "lp_context.h" 43#include "lp_scene.h" 44#include "lp_scene_queue.h" 45#include "lp_texture.h" 46#include "lp_debug.h" 47#include "lp_fence.h" 48#include "lp_query.h" 49#include "lp_rast.h" 50#include "lp_setup_context.h" 51#include "lp_screen.h" 52#include "lp_state.h" 53#include "state_tracker/sw_winsys.h" 54#include "lp_rast_priv.h" 55 56#include "draw/draw_context.h" 57#include "draw/draw_vbuf.h" 58 59 60static void set_scene_state( struct lp_setup_context *, enum setup_state ); 61 62 63struct lp_scene * 64lp_setup_get_current_scene(struct lp_setup_context *setup) 65{ 66 if (!setup->scene) { 67 68 /* wait for a free/empty scene 69 */ 70 setup->scene = lp_scene_dequeue(setup->empty_scenes, TRUE); 71 72 assert(lp_scene_is_empty(setup->scene)); 73 74 lp_scene_begin_binning(setup->scene, 75 &setup->fb ); 76 } 77 return setup->scene; 78} 79 80 81/** 82 * Check if the size of the current scene has exceeded the limit. 83 * If so, flush/render it. 84 */ 85static void 86setup_check_scene_size_and_flush(struct lp_setup_context *setup) 87{ 88 if (setup->scene) { 89 struct lp_scene *scene = lp_setup_get_current_scene(setup); 90 unsigned size = lp_scene_get_size(scene); 91 92 if (size > LP_MAX_SCENE_SIZE) { 93 /*printf("LLVMPIPE: scene size = %u, flushing.\n", size);*/ 94 set_scene_state( setup, SETUP_FLUSHED ); 95 /*assert(lp_scene_get_size(scene) == 0);*/ 96 } 97 } 98} 99 100 101static void 102first_triangle( struct lp_setup_context *setup, 103 const float (*v0)[4], 104 const float (*v1)[4], 105 const float (*v2)[4]) 106{ 107 set_scene_state( setup, SETUP_ACTIVE ); 108 lp_setup_choose_triangle( setup ); 109 setup->triangle( setup, v0, v1, v2 ); 110} 111 112static void 113first_line( struct lp_setup_context *setup, 114 const float (*v0)[4], 115 const float (*v1)[4]) 116{ 117 set_scene_state( setup, SETUP_ACTIVE ); 118 lp_setup_choose_line( setup ); 119 setup->line( setup, v0, v1 ); 120} 121 122static void 123first_point( struct lp_setup_context *setup, 124 const float (*v0)[4]) 125{ 126 set_scene_state( setup, SETUP_ACTIVE ); 127 lp_setup_choose_point( setup ); 128 setup->point( setup, v0 ); 129} 130 131static void reset_context( struct lp_setup_context *setup ) 132{ 133 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 134 135 /* Reset derived state */ 136 setup->constants.stored_size = 0; 137 setup->constants.stored_data = NULL; 138 setup->fs.stored = NULL; 139 setup->dirty = ~0; 140 141 /* no current bin */ 142 setup->scene = NULL; 143 144 /* Reset some state: 145 */ 146 setup->clear.flags = 0; 147 148 /* Have an explicit "start-binning" call and get rid of this 149 * pointer twiddling? 150 */ 151 setup->line = first_line; 152 setup->point = first_point; 153 setup->triangle = first_triangle; 154} 155 156 157/** Rasterize all scene's bins */ 158static void 159lp_setup_rasterize_scene( struct lp_setup_context *setup ) 160{ 161 struct lp_scene *scene = lp_setup_get_current_scene(setup); 162 163 lp_scene_rasterize(scene, setup->rast); 164 165 reset_context( setup ); 166 167 LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); 168} 169 170 171 172static void 173begin_binning( struct lp_setup_context *setup ) 174{ 175 struct lp_scene *scene = lp_setup_get_current_scene(setup); 176 177 LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, 178 (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", 179 (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) ? "clear": "load"); 180 181 if (setup->fb.nr_cbufs) { 182 if (setup->clear.flags & PIPE_CLEAR_COLOR) { 183 lp_scene_bin_everywhere( scene, 184 lp_rast_clear_color, 185 setup->clear.color ); 186 scene->has_color_clear = TRUE; 187 } 188 } 189 190 if (setup->fb.zsbuf) { 191 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { 192 lp_scene_bin_everywhere( scene, 193 lp_rast_clear_zstencil, 194 setup->clear.zstencil ); 195 scene->has_depth_clear = TRUE; 196 } 197 } 198 199 LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); 200} 201 202 203/* This basically bins and then flushes any outstanding full-screen 204 * clears. 205 * 206 * TODO: fast path for fullscreen clears and no triangles. 207 */ 208static void 209execute_clears( struct lp_setup_context *setup ) 210{ 211 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 212 213 begin_binning( setup ); 214 lp_setup_rasterize_scene( setup ); 215} 216 217 218static void 219set_scene_state( struct lp_setup_context *setup, 220 enum setup_state new_state ) 221{ 222 unsigned old_state = setup->state; 223 224 if (old_state == new_state) 225 return; 226 227 LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state); 228 229 switch (new_state) { 230 case SETUP_ACTIVE: 231 begin_binning( setup ); 232 break; 233 234 case SETUP_CLEARED: 235 if (old_state == SETUP_ACTIVE) { 236 assert(0); 237 return; 238 } 239 break; 240 241 case SETUP_FLUSHED: 242 if (old_state == SETUP_CLEARED) 243 execute_clears( setup ); 244 else 245 lp_setup_rasterize_scene( setup ); 246 break; 247 248 default: 249 assert(0 && "invalid setup state mode"); 250 } 251 252 setup->state = new_state; 253} 254 255 256/** 257 * \param flags bitmask of PIPE_FLUSH_x flags 258 */ 259void 260lp_setup_flush( struct lp_setup_context *setup, 261 unsigned flags ) 262{ 263 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 264 265 if (setup->scene) { 266 struct lp_scene *scene = lp_setup_get_current_scene(setup); 267 union lp_rast_cmd_arg dummy = {0}; 268 269 if (flags & (PIPE_FLUSH_SWAPBUFFERS | 270 PIPE_FLUSH_FRAME)) { 271 /* Store colors in the linear color buffer(s). 272 * If we don't do this here, we'll end up converting the tiled 273 * data to linear in the texture_unmap() function, which will 274 * not be a parallel/threaded operation as here. 275 */ 276 lp_scene_bin_everywhere(scene, lp_rast_store_color, dummy); 277 } 278 } 279 280 set_scene_state( setup, SETUP_FLUSHED ); 281} 282 283 284void 285lp_setup_bind_framebuffer( struct lp_setup_context *setup, 286 const struct pipe_framebuffer_state *fb ) 287{ 288 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 289 290 /* Flush any old scene. 291 */ 292 set_scene_state( setup, SETUP_FLUSHED ); 293 294 /* Set new state. This will be picked up later when we next need a 295 * scene. 296 */ 297 util_copy_framebuffer_state(&setup->fb, fb); 298} 299 300 301void 302lp_setup_clear( struct lp_setup_context *setup, 303 const float *color, 304 double depth, 305 unsigned stencil, 306 unsigned flags ) 307{ 308 struct lp_scene *scene = lp_setup_get_current_scene(setup); 309 unsigned i; 310 311 LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 312 313 314 if (flags & PIPE_CLEAR_COLOR) { 315 for (i = 0; i < 4; ++i) 316 setup->clear.color.clear_color[i] = float_to_ubyte(color[i]); 317 } 318 319 if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 320 setup->clear.zstencil.clear_zstencil = 321 util_pack_z_stencil(setup->fb.zsbuf->format, 322 depth, 323 stencil); 324 } 325 326 if (setup->state == SETUP_ACTIVE) { 327 /* Add the clear to existing scene. In the unusual case where 328 * both color and depth-stencil are being cleared when there's 329 * already been some rendering, we could discard the currently 330 * binned scene and start again, but I don't see that as being 331 * a common usage. 332 */ 333 if (flags & PIPE_CLEAR_COLOR) { 334 lp_scene_bin_everywhere( scene, 335 lp_rast_clear_color, 336 setup->clear.color ); 337 scene->has_color_clear = TRUE; 338 } 339 340 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { 341 lp_scene_bin_everywhere( scene, 342 lp_rast_clear_zstencil, 343 setup->clear.zstencil ); 344 scene->has_depth_clear = TRUE; 345 } 346 347 } 348 else { 349 /* Put ourselves into the 'pre-clear' state, specifically to try 350 * and accumulate multiple clears to color and depth_stencil 351 * buffers which the app or state-tracker might issue 352 * separately. 353 */ 354 set_scene_state( setup, SETUP_CLEARED ); 355 356 setup->clear.flags |= flags; 357 } 358} 359 360 361/** 362 * Emit a fence. 363 */ 364struct pipe_fence_handle * 365lp_setup_fence( struct lp_setup_context *setup ) 366{ 367 if (setup->num_threads == 0) { 368 return NULL; 369 } 370 else { 371 struct lp_scene *scene = lp_setup_get_current_scene(setup); 372 const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ 373 struct lp_fence *fence = lp_fence_create(rank); 374 375 LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); 376 377 set_scene_state( setup, SETUP_ACTIVE ); 378 379 /* insert the fence into all command bins */ 380 lp_scene_bin_everywhere( scene, 381 lp_rast_fence, 382 lp_rast_arg_fence(fence) ); 383 384 return (struct pipe_fence_handle *) fence; 385 } 386} 387 388 389void 390lp_setup_set_triangle_state( struct lp_setup_context *setup, 391 unsigned cull_mode, 392 boolean ccw_is_frontface, 393 boolean scissor, 394 boolean gl_rasterization_rules) 395{ 396 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 397 398 setup->ccw_is_frontface = ccw_is_frontface; 399 setup->cullmode = cull_mode; 400 setup->triangle = first_triangle; 401 setup->scissor_test = scissor; 402 setup->pixel_offset = gl_rasterization_rules ? 0.5f : 0.0f; 403} 404 405 406 407void 408lp_setup_set_fs_inputs( struct lp_setup_context *setup, 409 const struct lp_shader_input *input, 410 unsigned nr ) 411{ 412 LP_DBG(DEBUG_SETUP, "%s %p %u\n", __FUNCTION__, (void *) input, nr); 413 414 memcpy( setup->fs.input, input, nr * sizeof input[0] ); 415 setup->fs.nr_inputs = nr; 416} 417 418void 419lp_setup_set_fs_functions( struct lp_setup_context *setup, 420 lp_jit_frag_func jit_function0, 421 lp_jit_frag_func jit_function1, 422 boolean opaque ) 423{ 424 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) jit_function0); 425 /* FIXME: reference count */ 426 427 setup->fs.current.jit_function[0] = jit_function0; 428 setup->fs.current.jit_function[1] = jit_function1; 429 setup->fs.current.opaque = opaque; 430 setup->dirty |= LP_SETUP_NEW_FS; 431} 432 433void 434lp_setup_set_fs_constants(struct lp_setup_context *setup, 435 struct pipe_resource *buffer) 436{ 437 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); 438 439 pipe_resource_reference(&setup->constants.current, buffer); 440 441 setup->dirty |= LP_SETUP_NEW_CONSTANTS; 442} 443 444 445void 446lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, 447 float alpha_ref_value ) 448{ 449 LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); 450 451 if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { 452 setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; 453 setup->dirty |= LP_SETUP_NEW_FS; 454 } 455} 456 457void 458lp_setup_set_stencil_ref_values( struct lp_setup_context *setup, 459 const ubyte refs[2] ) 460{ 461 LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]); 462 463 if (setup->fs.current.jit_context.stencil_ref_front != refs[0] || 464 setup->fs.current.jit_context.stencil_ref_back != refs[1]) { 465 setup->fs.current.jit_context.stencil_ref_front = refs[0]; 466 setup->fs.current.jit_context.stencil_ref_back = refs[1]; 467 setup->dirty |= LP_SETUP_NEW_FS; 468 } 469} 470 471void 472lp_setup_set_blend_color( struct lp_setup_context *setup, 473 const struct pipe_blend_color *blend_color ) 474{ 475 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 476 477 assert(blend_color); 478 479 if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) { 480 memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); 481 setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; 482 } 483} 484 485 486void 487lp_setup_set_scissor( struct lp_setup_context *setup, 488 const struct pipe_scissor_state *scissor ) 489{ 490 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 491 492 assert(scissor); 493 494 if (memcmp(&setup->scissor.current, scissor, sizeof(*scissor)) != 0) { 495 setup->scissor.current = *scissor; /* struct copy */ 496 setup->dirty |= LP_SETUP_NEW_SCISSOR; 497 } 498} 499 500 501void 502lp_setup_set_flatshade_first( struct lp_setup_context *setup, 503 boolean flatshade_first ) 504{ 505 setup->flatshade_first = flatshade_first; 506} 507 508 509void 510lp_setup_set_vertex_info( struct lp_setup_context *setup, 511 struct vertex_info *vertex_info ) 512{ 513 /* XXX: just silently holding onto the pointer: 514 */ 515 setup->vertex_info = vertex_info; 516} 517 518 519/** 520 * Called during state validation when LP_NEW_SAMPLER_VIEW is set. 521 */ 522void 523lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, 524 unsigned num, 525 struct pipe_sampler_view **views) 526{ 527 unsigned i; 528 529 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 530 531 assert(num <= PIPE_MAX_SAMPLERS); 532 533 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 534 struct pipe_sampler_view *view = i < num ? views[i] : NULL; 535 536 if(view) { 537 struct pipe_resource *tex = view->texture; 538 struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex); 539 struct lp_jit_texture *jit_tex; 540 jit_tex = &setup->fs.current.jit_context.textures[i]; 541 jit_tex->width = tex->width0; 542 jit_tex->height = tex->height0; 543 jit_tex->depth = tex->depth0; 544 jit_tex->last_level = tex->last_level; 545 546 /* We're referencing the texture's internal data, so save a 547 * reference to it. 548 */ 549 pipe_resource_reference(&setup->fs.current_tex[i], tex); 550 551 if (!lp_tex->dt) { 552 /* regular texture - setup array of mipmap level pointers */ 553 int j; 554 for (j = 0; j <= tex->last_level; j++) { 555 jit_tex->data[j] = 556 llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, 557 LP_TEX_LAYOUT_LINEAR); 558 jit_tex->row_stride[j] = lp_tex->row_stride[j]; 559 jit_tex->img_stride[j] = lp_tex->img_stride[j]; 560 } 561 } 562 else { 563 /* display target texture/surface */ 564 /* 565 * XXX: Where should this be unmapped? 566 */ 567 568 struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); 569 struct sw_winsys *winsys = screen->winsys; 570 jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, 571 PIPE_TRANSFER_READ); 572 jit_tex->row_stride[0] = lp_tex->row_stride[0]; 573 jit_tex->img_stride[0] = lp_tex->img_stride[0]; 574 assert(jit_tex->data[0]); 575 } 576 } 577 } 578 579 setup->dirty |= LP_SETUP_NEW_FS; 580} 581 582 583/** 584 * Is the given texture referenced by any scene? 585 * Note: we have to check all scenes including any scenes currently 586 * being rendered and the current scene being built. 587 */ 588unsigned 589lp_setup_is_resource_referenced( const struct lp_setup_context *setup, 590 const struct pipe_resource *texture ) 591{ 592 unsigned i; 593 594 /* check the render targets */ 595 for (i = 0; i < setup->fb.nr_cbufs; i++) { 596 if (setup->fb.cbufs[i]->texture == texture) 597 return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; 598 } 599 if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { 600 return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; 601 } 602 603 /* check textures referenced by the scene */ 604 for (i = 0; i < Elements(setup->scenes); i++) { 605 if (lp_scene_is_resource_referenced(setup->scenes[i], texture)) { 606 return PIPE_REFERENCED_FOR_READ; 607 } 608 } 609 610 return PIPE_UNREFERENCED; 611} 612 613 614/** 615 * Called by vbuf code when we're about to draw something. 616 */ 617void 618lp_setup_update_state( struct lp_setup_context *setup ) 619{ 620 struct lp_scene *scene; 621 622 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 623 624 setup_check_scene_size_and_flush(setup); 625 626 scene = lp_setup_get_current_scene(setup); 627 628 assert(setup->fs.current.jit_function); 629 630 /* Some of the 'draw' pipeline stages may have changed some driver state. 631 * Make sure we've processed those state changes before anything else. 632 * 633 * XXX this is the only place where llvmpipe_context is used in the 634 * setup code. This may get refactored/changed... 635 */ 636 { 637 struct llvmpipe_context *lp = llvmpipe_context(scene->pipe); 638 if (lp->dirty) { 639 llvmpipe_update_derived(lp); 640 } 641 assert(lp->dirty == 0); 642 } 643 644 if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { 645 uint8_t *stored; 646 unsigned i, j; 647 648 stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); 649 650 if (stored) { 651 /* smear each blend color component across 16 ubyte elements */ 652 for (i = 0; i < 4; ++i) { 653 uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); 654 for (j = 0; j < 16; ++j) 655 stored[i*16 + j] = c; 656 } 657 658 setup->blend_color.stored = stored; 659 660 setup->fs.current.jit_context.blend_color = setup->blend_color.stored; 661 } 662 663 setup->dirty |= LP_SETUP_NEW_FS; 664 } 665 666 if (setup->dirty & LP_SETUP_NEW_SCISSOR) { 667 float *stored; 668 669 stored = lp_scene_alloc_aligned(scene, 4 * sizeof(int32_t), 16); 670 671 if (stored) { 672 stored[0] = (float) setup->scissor.current.minx; 673 stored[1] = (float) setup->scissor.current.miny; 674 stored[2] = (float) setup->scissor.current.maxx; 675 stored[3] = (float) setup->scissor.current.maxy; 676 677 setup->scissor.stored = stored; 678 679 setup->fs.current.jit_context.scissor_xmin = stored[0]; 680 setup->fs.current.jit_context.scissor_ymin = stored[1]; 681 setup->fs.current.jit_context.scissor_xmax = stored[2]; 682 setup->fs.current.jit_context.scissor_ymax = stored[3]; 683 } 684 685 setup->dirty |= LP_SETUP_NEW_FS; 686 } 687 688 if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { 689 struct pipe_resource *buffer = setup->constants.current; 690 691 if(buffer) { 692 unsigned current_size = buffer->width0; 693 const void *current_data = llvmpipe_resource_data(buffer); 694 695 /* TODO: copy only the actually used constants? */ 696 697 if(setup->constants.stored_size != current_size || 698 !setup->constants.stored_data || 699 memcmp(setup->constants.stored_data, 700 current_data, 701 current_size) != 0) { 702 void *stored; 703 704 stored = lp_scene_alloc(scene, current_size); 705 if(stored) { 706 memcpy(stored, 707 current_data, 708 current_size); 709 setup->constants.stored_size = current_size; 710 setup->constants.stored_data = stored; 711 } 712 } 713 } 714 else { 715 setup->constants.stored_size = 0; 716 setup->constants.stored_data = NULL; 717 } 718 719 setup->fs.current.jit_context.constants = setup->constants.stored_data; 720 setup->dirty |= LP_SETUP_NEW_FS; 721 } 722 723 724 if(setup->dirty & LP_SETUP_NEW_FS) { 725 if(!setup->fs.stored || 726 memcmp(setup->fs.stored, 727 &setup->fs.current, 728 sizeof setup->fs.current) != 0) { 729 /* The fs state that's been stored in the scene is different from 730 * the new, current state. So allocate a new lp_rast_state object 731 * and append it to the bin's setup data buffer. 732 */ 733 uint i; 734 struct lp_rast_state *stored = 735 (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); 736 if(stored) { 737 memcpy(stored, 738 &setup->fs.current, 739 sizeof setup->fs.current); 740 setup->fs.stored = stored; 741 742 /* put the state-set command into all bins */ 743 lp_scene_bin_state_command( scene, 744 lp_rast_set_state, 745 lp_rast_arg_state(setup->fs.stored) ); 746 } 747 748 /* The scene now references the textures in the rasterization 749 * state record. Note that now. 750 */ 751 for (i = 0; i < Elements(setup->fs.current_tex); i++) { 752 if (setup->fs.current_tex[i]) 753 lp_scene_add_resource_reference(scene, setup->fs.current_tex[i]); 754 } 755 } 756 } 757 758 setup->dirty = 0; 759 760 assert(setup->fs.stored); 761} 762 763 764 765/* Only caller is lp_setup_vbuf_destroy() 766 */ 767void 768lp_setup_destroy( struct lp_setup_context *setup ) 769{ 770 uint i; 771 772 reset_context( setup ); 773 774 util_unreference_framebuffer_state(&setup->fb); 775 776 for (i = 0; i < Elements(setup->fs.current_tex); i++) { 777 pipe_resource_reference(&setup->fs.current_tex[i], NULL); 778 } 779 780 pipe_resource_reference(&setup->constants.current, NULL); 781 782 /* free the scenes in the 'empty' queue */ 783 while (1) { 784 struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes, FALSE); 785 if (!scene) 786 break; 787 lp_scene_destroy(scene); 788 } 789 790 lp_scene_queue_destroy(setup->empty_scenes); 791 792 lp_rast_destroy( setup->rast ); 793 794 FREE( setup ); 795} 796 797 798/** 799 * Create a new primitive tiling engine. Plug it into the backend of 800 * the draw module. Currently also creates a rasterizer to use with 801 * it. 802 */ 803struct lp_setup_context * 804lp_setup_create( struct pipe_context *pipe, 805 struct draw_context *draw ) 806{ 807 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 808 struct lp_setup_context *setup = CALLOC_STRUCT(lp_setup_context); 809 unsigned i; 810 811 if (!setup) 812 return NULL; 813 814 lp_setup_init_vbuf(setup); 815 816 setup->empty_scenes = lp_scene_queue_create(); 817 if (!setup->empty_scenes) 818 goto fail; 819 820 /* XXX: move this to the screen and share between contexts: 821 */ 822 setup->num_threads = screen->num_threads; 823 setup->rast = lp_rast_create(screen->num_threads); 824 if (!setup->rast) 825 goto fail; 826 827 setup->vbuf = draw_vbuf_stage(draw, &setup->base); 828 if (!setup->vbuf) 829 goto fail; 830 831 draw_set_rasterize_stage(draw, setup->vbuf); 832 draw_set_render(draw, &setup->base); 833 834 /* create some empty scenes */ 835 for (i = 0; i < MAX_SCENES; i++) { 836 setup->scenes[i] = lp_scene_create( pipe, setup->empty_scenes ); 837 838 lp_scene_enqueue(setup->empty_scenes, setup->scenes[i]); 839 } 840 841 setup->triangle = first_triangle; 842 setup->line = first_line; 843 setup->point = first_point; 844 845 setup->dirty = ~0; 846 847 return setup; 848 849fail: 850 if (setup->rast) 851 lp_rast_destroy( setup->rast ); 852 853 if (setup->vbuf) 854 ; 855 856 if (setup->empty_scenes) 857 lp_scene_queue_destroy(setup->empty_scenes); 858 859 FREE(setup); 860 return NULL; 861} 862 863 864/** 865 * Put a BeginQuery command into all bins. 866 */ 867void 868lp_setup_begin_query(struct lp_setup_context *setup, 869 struct llvmpipe_query *pq) 870{ 871 struct lp_scene * scene = lp_setup_get_current_scene(setup); 872 union lp_rast_cmd_arg cmd_arg; 873 874 /* init the query to its beginning state */ 875 pq->done = FALSE; 876 pq->tile_count = 0; 877 pq->num_tiles = scene->tiles_x * scene->tiles_y; 878 assert(pq->num_tiles > 0); 879 880 memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */ 881 882 cmd_arg.query_obj = pq; 883 lp_scene_bin_everywhere(scene, lp_rast_begin_query, cmd_arg); 884 pq->binned = TRUE; 885} 886 887 888/** 889 * Put an EndQuery command into all bins. 890 */ 891void 892lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) 893{ 894 struct lp_scene * scene = lp_setup_get_current_scene(setup); 895 union lp_rast_cmd_arg cmd_arg; 896 897 cmd_arg.query_obj = pq; 898 lp_scene_bin_everywhere(scene, lp_rast_end_query, cmd_arg); 899} 900