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