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