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