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