lp_setup.c revision 3464ebd5
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_memory.h" 44#include "lp_scene.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 boolean set_scene_state( struct lp_setup_context *, enum setup_state, 60 const char *reason); 61static boolean try_update_scene_state( struct lp_setup_context *setup ); 62 63 64static void 65lp_setup_get_empty_scene(struct lp_setup_context *setup) 66{ 67 assert(setup->scene == NULL); 68 69 setup->scene_idx++; 70 setup->scene_idx %= Elements(setup->scenes); 71 72 setup->scene = setup->scenes[setup->scene_idx]; 73 74 if (setup->scene->fence) { 75 if (LP_DEBUG & DEBUG_SETUP) 76 debug_printf("%s: wait for scene %d\n", 77 __FUNCTION__, setup->scene->fence->id); 78 79 lp_fence_wait(setup->scene->fence); 80 } 81 82 lp_scene_begin_binning(setup->scene, &setup->fb); 83 84} 85 86 87static void 88first_triangle( struct lp_setup_context *setup, 89 const float (*v0)[4], 90 const float (*v1)[4], 91 const float (*v2)[4]) 92{ 93 assert(setup->state == SETUP_ACTIVE); 94 lp_setup_choose_triangle( setup ); 95 setup->triangle( setup, v0, v1, v2 ); 96} 97 98static void 99first_line( struct lp_setup_context *setup, 100 const float (*v0)[4], 101 const float (*v1)[4]) 102{ 103 assert(setup->state == SETUP_ACTIVE); 104 lp_setup_choose_line( setup ); 105 setup->line( setup, v0, v1 ); 106} 107 108static void 109first_point( struct lp_setup_context *setup, 110 const float (*v0)[4]) 111{ 112 assert(setup->state == SETUP_ACTIVE); 113 lp_setup_choose_point( setup ); 114 setup->point( setup, v0 ); 115} 116 117void lp_setup_reset( struct lp_setup_context *setup ) 118{ 119 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 120 121 /* Reset derived state */ 122 setup->constants.stored_size = 0; 123 setup->constants.stored_data = NULL; 124 setup->fs.stored = NULL; 125 setup->dirty = ~0; 126 127 /* no current bin */ 128 setup->scene = NULL; 129 130 /* Reset some state: 131 */ 132 memset(&setup->clear, 0, sizeof setup->clear); 133 134 /* Have an explicit "start-binning" call and get rid of this 135 * pointer twiddling? 136 */ 137 setup->line = first_line; 138 setup->point = first_point; 139 setup->triangle = first_triangle; 140} 141 142 143/** Rasterize all scene's bins */ 144static void 145lp_setup_rasterize_scene( struct lp_setup_context *setup ) 146{ 147 struct lp_scene *scene = setup->scene; 148 struct llvmpipe_screen *screen = llvmpipe_screen(scene->pipe->screen); 149 150 lp_scene_end_binning(scene); 151 152 lp_fence_reference(&setup->last_fence, scene->fence); 153 154 if (setup->last_fence) 155 setup->last_fence->issued = TRUE; 156 157 pipe_mutex_lock(screen->rast_mutex); 158 lp_rast_queue_scene(screen->rast, scene); 159 lp_rast_finish(screen->rast); 160 pipe_mutex_unlock(screen->rast_mutex); 161 162 lp_scene_end_rasterization(setup->scene); 163 lp_setup_reset( setup ); 164 165 LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); 166} 167 168 169 170static boolean 171begin_binning( struct lp_setup_context *setup ) 172{ 173 struct lp_scene *scene = setup->scene; 174 boolean need_zsload = FALSE; 175 boolean ok; 176 unsigned i, j; 177 178 assert(scene); 179 assert(scene->fence == NULL); 180 181 /* Always create a fence: 182 */ 183 scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); 184 if (!scene->fence) 185 return FALSE; 186 187 /* Initialize the bin flags and x/y coords: 188 */ 189 for (i = 0; i < scene->tiles_x; i++) { 190 for (j = 0; j < scene->tiles_y; j++) { 191 scene->tile[i][j].x = i; 192 scene->tile[i][j].y = j; 193 } 194 } 195 196 ok = try_update_scene_state(setup); 197 if (!ok) 198 return FALSE; 199 200 if (setup->fb.zsbuf && 201 ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && 202 util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) 203 need_zsload = TRUE; 204 205 LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, 206 (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", 207 need_zsload ? "clear": "load"); 208 209 if (setup->fb.nr_cbufs) { 210 if (setup->clear.flags & PIPE_CLEAR_COLOR) { 211 ok = lp_scene_bin_everywhere( scene, 212 LP_RAST_OP_CLEAR_COLOR, 213 setup->clear.color ); 214 if (!ok) 215 return FALSE; 216 } 217 } 218 219 if (setup->fb.zsbuf) { 220 if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { 221 if (!need_zsload) 222 scene->has_depthstencil_clear = TRUE; 223 224 ok = lp_scene_bin_everywhere( scene, 225 LP_RAST_OP_CLEAR_ZSTENCIL, 226 lp_rast_arg_clearzs( 227 setup->clear.zsvalue, 228 setup->clear.zsmask)); 229 if (!ok) 230 return FALSE; 231 } 232 } 233 234 if (setup->active_query) { 235 ok = lp_scene_bin_everywhere( scene, 236 LP_RAST_OP_BEGIN_QUERY, 237 lp_rast_arg_query(setup->active_query) ); 238 if (!ok) 239 return FALSE; 240 } 241 242 setup->clear.flags = 0; 243 setup->clear.zsmask = 0; 244 setup->clear.zsvalue = 0; 245 246 LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); 247 return TRUE; 248} 249 250 251/* This basically bins and then flushes any outstanding full-screen 252 * clears. 253 * 254 * TODO: fast path for fullscreen clears and no triangles. 255 */ 256static boolean 257execute_clears( struct lp_setup_context *setup ) 258{ 259 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 260 261 return begin_binning( setup ); 262} 263 264const char *states[] = { 265 "FLUSHED", 266 "CLEARED", 267 "ACTIVE " 268}; 269 270 271static boolean 272set_scene_state( struct lp_setup_context *setup, 273 enum setup_state new_state, 274 const char *reason) 275{ 276 unsigned old_state = setup->state; 277 278 if (old_state == new_state) 279 return TRUE; 280 281 if (LP_DEBUG & DEBUG_SCENE) { 282 debug_printf("%s old %s new %s%s%s\n", 283 __FUNCTION__, 284 states[old_state], 285 states[new_state], 286 (new_state == SETUP_FLUSHED) ? ": " : "", 287 (new_state == SETUP_FLUSHED) ? reason : ""); 288 289 if (new_state == SETUP_FLUSHED && setup->scene) 290 lp_debug_draw_bins_by_cmd_length(setup->scene); 291 } 292 293 /* wait for a free/empty scene 294 */ 295 if (old_state == SETUP_FLUSHED) 296 lp_setup_get_empty_scene(setup); 297 298 switch (new_state) { 299 case SETUP_CLEARED: 300 break; 301 302 case SETUP_ACTIVE: 303 if (!begin_binning( setup )) 304 goto fail; 305 break; 306 307 case SETUP_FLUSHED: 308 if (old_state == SETUP_CLEARED) 309 if (!execute_clears( setup )) 310 goto fail; 311 312 lp_setup_rasterize_scene( setup ); 313 assert(setup->scene == NULL); 314 break; 315 316 default: 317 assert(0 && "invalid setup state mode"); 318 goto fail; 319 } 320 321 setup->state = new_state; 322 return TRUE; 323 324fail: 325 if (setup->scene) { 326 lp_scene_end_rasterization(setup->scene); 327 setup->scene = NULL; 328 } 329 330 setup->state = SETUP_FLUSHED; 331 lp_setup_reset( setup ); 332 return FALSE; 333} 334 335 336void 337lp_setup_flush( struct lp_setup_context *setup, 338 struct pipe_fence_handle **fence, 339 const char *reason) 340{ 341 set_scene_state( setup, SETUP_FLUSHED, reason ); 342 343 if (fence) { 344 lp_fence_reference((struct lp_fence **)fence, setup->last_fence); 345 } 346} 347 348 349void 350lp_setup_bind_framebuffer( struct lp_setup_context *setup, 351 const struct pipe_framebuffer_state *fb ) 352{ 353 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 354 355 /* Flush any old scene. 356 */ 357 set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); 358 359 /* 360 * Ensure the old scene is not reused. 361 */ 362 assert(!setup->scene); 363 364 /* Set new state. This will be picked up later when we next need a 365 * scene. 366 */ 367 util_copy_framebuffer_state(&setup->fb, fb); 368 setup->framebuffer.x0 = 0; 369 setup->framebuffer.y0 = 0; 370 setup->framebuffer.x1 = fb->width-1; 371 setup->framebuffer.y1 = fb->height-1; 372 setup->dirty |= LP_SETUP_NEW_SCISSOR; 373} 374 375 376static boolean 377lp_setup_try_clear( struct lp_setup_context *setup, 378 const float *color, 379 double depth, 380 unsigned stencil, 381 unsigned flags ) 382{ 383 uint32_t zsmask = 0; 384 uint32_t zsvalue = 0; 385 union lp_rast_cmd_arg color_arg; 386 unsigned i; 387 388 LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); 389 390 if (flags & PIPE_CLEAR_COLOR) { 391 for (i = 0; i < 4; i++) 392 color_arg.clear_color[i] = float_to_ubyte(color[i]); 393 } 394 395 if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 396 uint32_t zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; 397 uint32_t smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; 398 399 zsvalue = util_pack_z_stencil(setup->fb.zsbuf->format, 400 depth, 401 stencil); 402 403 404 zsmask = util_pack_mask_z_stencil(setup->fb.zsbuf->format, 405 zmask, 406 smask); 407 408 zsvalue &= zsmask; 409 } 410 411 if (setup->state == SETUP_ACTIVE) { 412 struct lp_scene *scene = setup->scene; 413 414 /* Add the clear to existing scene. In the unusual case where 415 * both color and depth-stencil are being cleared when there's 416 * already been some rendering, we could discard the currently 417 * binned scene and start again, but I don't see that as being 418 * a common usage. 419 */ 420 if (flags & PIPE_CLEAR_COLOR) { 421 if (!lp_scene_bin_everywhere( scene, 422 LP_RAST_OP_CLEAR_COLOR, 423 color_arg )) 424 return FALSE; 425 } 426 427 if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 428 if (!lp_scene_bin_everywhere( scene, 429 LP_RAST_OP_CLEAR_ZSTENCIL, 430 lp_rast_arg_clearzs(zsvalue, zsmask) )) 431 return FALSE; 432 } 433 } 434 else { 435 /* Put ourselves into the 'pre-clear' state, specifically to try 436 * and accumulate multiple clears to color and depth_stencil 437 * buffers which the app or state-tracker might issue 438 * separately. 439 */ 440 set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); 441 442 setup->clear.flags |= flags; 443 444 if (flags & PIPE_CLEAR_DEPTHSTENCIL) { 445 setup->clear.zsmask |= zsmask; 446 setup->clear.zsvalue = 447 (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); 448 } 449 450 if (flags & PIPE_CLEAR_COLOR) { 451 memcpy(setup->clear.color.clear_color, 452 &color_arg, 453 sizeof setup->clear.color.clear_color); 454 } 455 } 456 457 return TRUE; 458} 459 460void 461lp_setup_clear( struct lp_setup_context *setup, 462 const float *color, 463 double depth, 464 unsigned stencil, 465 unsigned flags ) 466{ 467 if (!lp_setup_try_clear( setup, color, depth, stencil, flags )) { 468 lp_setup_flush(setup, NULL, __FUNCTION__); 469 470 if (!lp_setup_try_clear( setup, color, depth, stencil, flags )) 471 assert(0); 472 } 473} 474 475 476 477 478 479void 480lp_setup_set_triangle_state( struct lp_setup_context *setup, 481 unsigned cull_mode, 482 boolean ccw_is_frontface, 483 boolean scissor, 484 boolean gl_rasterization_rules) 485{ 486 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 487 488 setup->ccw_is_frontface = ccw_is_frontface; 489 setup->cullmode = cull_mode; 490 setup->triangle = first_triangle; 491 setup->pixel_offset = gl_rasterization_rules ? 0.5f : 0.0f; 492 493 if (setup->scissor_test != scissor) { 494 setup->dirty |= LP_SETUP_NEW_SCISSOR; 495 setup->scissor_test = scissor; 496 } 497} 498 499void 500lp_setup_set_line_state( struct lp_setup_context *setup, 501 float line_width) 502{ 503 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 504 505 setup->line_width = line_width; 506} 507 508void 509lp_setup_set_point_state( struct lp_setup_context *setup, 510 float point_size, 511 boolean point_size_per_vertex, 512 uint sprite_coord_enable, 513 uint sprite_coord_origin) 514{ 515 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 516 517 setup->point_size = point_size; 518 setup->sprite_coord_enable = sprite_coord_enable; 519 setup->sprite_coord_origin = sprite_coord_origin; 520 setup->point_size_per_vertex = point_size_per_vertex; 521} 522 523void 524lp_setup_set_setup_variant( struct lp_setup_context *setup, 525 const struct lp_setup_variant *variant) 526{ 527 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 528 529 setup->setup.variant = variant; 530} 531 532void 533lp_setup_set_fs_variant( struct lp_setup_context *setup, 534 struct lp_fragment_shader_variant *variant) 535{ 536 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, 537 variant); 538 /* FIXME: reference count */ 539 540 setup->fs.current.variant = variant; 541 setup->dirty |= LP_SETUP_NEW_FS; 542} 543 544void 545lp_setup_set_fs_constants(struct lp_setup_context *setup, 546 struct pipe_resource *buffer) 547{ 548 LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); 549 550 pipe_resource_reference(&setup->constants.current, buffer); 551 552 setup->dirty |= LP_SETUP_NEW_CONSTANTS; 553} 554 555 556void 557lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, 558 float alpha_ref_value ) 559{ 560 LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); 561 562 if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { 563 setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; 564 setup->dirty |= LP_SETUP_NEW_FS; 565 } 566} 567 568void 569lp_setup_set_stencil_ref_values( struct lp_setup_context *setup, 570 const ubyte refs[2] ) 571{ 572 LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]); 573 574 if (setup->fs.current.jit_context.stencil_ref_front != refs[0] || 575 setup->fs.current.jit_context.stencil_ref_back != refs[1]) { 576 setup->fs.current.jit_context.stencil_ref_front = refs[0]; 577 setup->fs.current.jit_context.stencil_ref_back = refs[1]; 578 setup->dirty |= LP_SETUP_NEW_FS; 579 } 580} 581 582void 583lp_setup_set_blend_color( struct lp_setup_context *setup, 584 const struct pipe_blend_color *blend_color ) 585{ 586 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 587 588 assert(blend_color); 589 590 if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) { 591 memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); 592 setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; 593 } 594} 595 596 597void 598lp_setup_set_scissor( struct lp_setup_context *setup, 599 const struct pipe_scissor_state *scissor ) 600{ 601 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 602 603 assert(scissor); 604 605 setup->scissor.x0 = scissor->minx; 606 setup->scissor.x1 = scissor->maxx-1; 607 setup->scissor.y0 = scissor->miny; 608 setup->scissor.y1 = scissor->maxy-1; 609 setup->dirty |= LP_SETUP_NEW_SCISSOR; 610} 611 612 613void 614lp_setup_set_flatshade_first( struct lp_setup_context *setup, 615 boolean flatshade_first ) 616{ 617 setup->flatshade_first = flatshade_first; 618} 619 620 621void 622lp_setup_set_vertex_info( struct lp_setup_context *setup, 623 struct vertex_info *vertex_info ) 624{ 625 /* XXX: just silently holding onto the pointer: 626 */ 627 setup->vertex_info = vertex_info; 628} 629 630 631/** 632 * Called during state validation when LP_NEW_SAMPLER_VIEW is set. 633 */ 634void 635lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, 636 unsigned num, 637 struct pipe_sampler_view **views) 638{ 639 unsigned i; 640 641 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 642 643 assert(num <= PIPE_MAX_SAMPLERS); 644 645 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 646 struct pipe_sampler_view *view = i < num ? views[i] : NULL; 647 648 if (view) { 649 struct pipe_resource *tex = view->texture; 650 struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex); 651 struct lp_jit_texture *jit_tex; 652 jit_tex = &setup->fs.current.jit_context.textures[i]; 653 jit_tex->width = tex->width0; 654 jit_tex->height = tex->height0; 655 jit_tex->depth = tex->depth0; 656 jit_tex->first_level = view->u.tex.first_level; 657 jit_tex->last_level = tex->last_level; 658 659 /* We're referencing the texture's internal data, so save a 660 * reference to it. 661 */ 662 pipe_resource_reference(&setup->fs.current_tex[i], tex); 663 664 if (!lp_tex->dt) { 665 /* regular texture - setup array of mipmap level pointers */ 666 int j; 667 for (j = view->u.tex.first_level; j <= tex->last_level; j++) { 668 jit_tex->data[j] = 669 llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, 670 LP_TEX_LAYOUT_LINEAR); 671 jit_tex->row_stride[j] = lp_tex->row_stride[j]; 672 jit_tex->img_stride[j] = lp_tex->img_stride[j]; 673 674 if ((LP_PERF & PERF_TEX_MEM) || 675 !jit_tex->data[j]) { 676 /* out of memory - use dummy tile memory */ 677 jit_tex->data[j] = lp_dummy_tile; 678 jit_tex->width = TILE_SIZE/8; 679 jit_tex->height = TILE_SIZE/8; 680 jit_tex->depth = 1; 681 jit_tex->first_level = 0; 682 jit_tex->last_level = 0; 683 jit_tex->row_stride[j] = 0; 684 jit_tex->img_stride[j] = 0; 685 } 686 } 687 } 688 else { 689 /* display target texture/surface */ 690 /* 691 * XXX: Where should this be unmapped? 692 */ 693 struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); 694 struct sw_winsys *winsys = screen->winsys; 695 jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, 696 PIPE_TRANSFER_READ); 697 jit_tex->row_stride[0] = lp_tex->row_stride[0]; 698 jit_tex->img_stride[0] = lp_tex->img_stride[0]; 699 assert(jit_tex->data[0]); 700 } 701 } 702 } 703 704 setup->dirty |= LP_SETUP_NEW_FS; 705} 706 707 708/** 709 * Called during state validation when LP_NEW_SAMPLER is set. 710 */ 711void 712lp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, 713 unsigned num, 714 const struct pipe_sampler_state **samplers) 715{ 716 unsigned i; 717 718 LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); 719 720 assert(num <= PIPE_MAX_SAMPLERS); 721 722 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 723 const struct pipe_sampler_state *sampler = i < num ? samplers[i] : NULL; 724 725 if (sampler) { 726 struct lp_jit_texture *jit_tex; 727 jit_tex = &setup->fs.current.jit_context.textures[i]; 728 729 jit_tex->min_lod = sampler->min_lod; 730 jit_tex->max_lod = sampler->max_lod; 731 jit_tex->lod_bias = sampler->lod_bias; 732 COPY_4V(jit_tex->border_color, sampler->border_color); 733 } 734 } 735 736 setup->dirty |= LP_SETUP_NEW_FS; 737} 738 739 740/** 741 * Is the given texture referenced by any scene? 742 * Note: we have to check all scenes including any scenes currently 743 * being rendered and the current scene being built. 744 */ 745unsigned 746lp_setup_is_resource_referenced( const struct lp_setup_context *setup, 747 const struct pipe_resource *texture ) 748{ 749 unsigned i; 750 751 /* check the render targets */ 752 for (i = 0; i < setup->fb.nr_cbufs; i++) { 753 if (setup->fb.cbufs[i]->texture == texture) 754 return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 755 } 756 if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { 757 return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; 758 } 759 760 /* check textures referenced by the scene */ 761 for (i = 0; i < Elements(setup->scenes); i++) { 762 if (lp_scene_is_resource_referenced(setup->scenes[i], texture)) { 763 return LP_REFERENCED_FOR_READ; 764 } 765 } 766 767 return LP_UNREFERENCED; 768} 769 770 771/** 772 * Called by vbuf code when we're about to draw something. 773 */ 774static boolean 775try_update_scene_state( struct lp_setup_context *setup ) 776{ 777 boolean new_scene = (setup->fs.stored == NULL); 778 struct lp_scene *scene = setup->scene; 779 780 assert(scene); 781 782 if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { 783 uint8_t *stored; 784 unsigned i, j; 785 786 stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); 787 if (!stored) { 788 assert(!new_scene); 789 return FALSE; 790 } 791 792 /* smear each blend color component across 16 ubyte elements */ 793 for (i = 0; i < 4; ++i) { 794 uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); 795 for (j = 0; j < 16; ++j) 796 stored[i*16 + j] = c; 797 } 798 799 setup->blend_color.stored = stored; 800 setup->fs.current.jit_context.blend_color = setup->blend_color.stored; 801 setup->dirty |= LP_SETUP_NEW_FS; 802 } 803 804 if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { 805 struct pipe_resource *buffer = setup->constants.current; 806 807 if(buffer) { 808 unsigned current_size = buffer->width0; 809 const void *current_data = llvmpipe_resource_data(buffer); 810 811 /* TODO: copy only the actually used constants? */ 812 813 if(setup->constants.stored_size != current_size || 814 !setup->constants.stored_data || 815 memcmp(setup->constants.stored_data, 816 current_data, 817 current_size) != 0) { 818 void *stored; 819 820 stored = lp_scene_alloc(scene, current_size); 821 if (!stored) { 822 assert(!new_scene); 823 return FALSE; 824 } 825 826 memcpy(stored, 827 current_data, 828 current_size); 829 setup->constants.stored_size = current_size; 830 setup->constants.stored_data = stored; 831 } 832 } 833 else { 834 setup->constants.stored_size = 0; 835 setup->constants.stored_data = NULL; 836 } 837 838 setup->fs.current.jit_context.constants = setup->constants.stored_data; 839 setup->dirty |= LP_SETUP_NEW_FS; 840 } 841 842 843 if (setup->dirty & LP_SETUP_NEW_FS) { 844 if (!setup->fs.stored || 845 memcmp(setup->fs.stored, 846 &setup->fs.current, 847 sizeof setup->fs.current) != 0) 848 { 849 struct lp_rast_state *stored; 850 uint i; 851 852 /* The fs state that's been stored in the scene is different from 853 * the new, current state. So allocate a new lp_rast_state object 854 * and append it to the bin's setup data buffer. 855 */ 856 stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); 857 if (!stored) { 858 assert(!new_scene); 859 return FALSE; 860 } 861 862 memcpy(stored, 863 &setup->fs.current, 864 sizeof setup->fs.current); 865 setup->fs.stored = stored; 866 867 /* The scene now references the textures in the rasterization 868 * state record. Note that now. 869 */ 870 for (i = 0; i < Elements(setup->fs.current_tex); i++) { 871 if (setup->fs.current_tex[i]) { 872 if (!lp_scene_add_resource_reference(scene, 873 setup->fs.current_tex[i], 874 new_scene)) { 875 assert(!new_scene); 876 return FALSE; 877 } 878 } 879 } 880 } 881 } 882 883 if (setup->dirty & LP_SETUP_NEW_SCISSOR) { 884 setup->draw_region = setup->framebuffer; 885 if (setup->scissor_test) { 886 u_rect_possible_intersection(&setup->scissor, 887 &setup->draw_region); 888 } 889 } 890 891 setup->dirty = 0; 892 893 assert(setup->fs.stored); 894 return TRUE; 895} 896 897boolean 898lp_setup_update_state( struct lp_setup_context *setup, 899 boolean update_scene ) 900{ 901 /* Some of the 'draw' pipeline stages may have changed some driver state. 902 * Make sure we've processed those state changes before anything else. 903 * 904 * XXX this is the only place where llvmpipe_context is used in the 905 * setup code. This may get refactored/changed... 906 */ 907 { 908 struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); 909 if (lp->dirty) { 910 llvmpipe_update_derived(lp); 911 } 912 913 if (lp->setup->dirty) { 914 llvmpipe_update_setup(lp); 915 } 916 917 assert(setup->setup.variant); 918 919 /* Will probably need to move this somewhere else, just need 920 * to know about vertex shader point size attribute. 921 */ 922 setup->psize = lp->psize_slot; 923 924 assert(lp->dirty == 0); 925 926 assert(lp->setup_variant.key.size == 927 setup->setup.variant->key.size); 928 929 assert(memcmp(&lp->setup_variant.key, 930 &setup->setup.variant->key, 931 setup->setup.variant->key.size) == 0); 932 } 933 934 if (update_scene && setup->state != SETUP_ACTIVE) { 935 if (!set_scene_state( setup, SETUP_ACTIVE, __FUNCTION__ )) 936 return FALSE; 937 } 938 939 /* Only call into update_scene_state() if we already have a 940 * scene: 941 */ 942 if (update_scene && setup->scene) { 943 assert(setup->state == SETUP_ACTIVE); 944 945 if (try_update_scene_state(setup)) 946 return TRUE; 947 948 /* Update failed, try to restart the scene. 949 * 950 * Cannot call lp_setup_flush_and_restart() directly here 951 * because of potential recursion. 952 */ 953 if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__)) 954 return FALSE; 955 956 if (!set_scene_state(setup, SETUP_ACTIVE, __FUNCTION__)) 957 return FALSE; 958 959 if (!setup->scene) 960 return FALSE; 961 962 return try_update_scene_state(setup); 963 } 964 965 return TRUE; 966} 967 968 969 970/* Only caller is lp_setup_vbuf_destroy() 971 */ 972void 973lp_setup_destroy( struct lp_setup_context *setup ) 974{ 975 uint i; 976 977 lp_setup_reset( setup ); 978 979 util_unreference_framebuffer_state(&setup->fb); 980 981 for (i = 0; i < Elements(setup->fs.current_tex); i++) { 982 pipe_resource_reference(&setup->fs.current_tex[i], NULL); 983 } 984 985 pipe_resource_reference(&setup->constants.current, NULL); 986 987 /* free the scenes in the 'empty' queue */ 988 for (i = 0; i < Elements(setup->scenes); i++) { 989 struct lp_scene *scene = setup->scenes[i]; 990 991 if (scene->fence) 992 lp_fence_wait(scene->fence); 993 994 lp_scene_destroy(scene); 995 } 996 997 lp_fence_reference(&setup->last_fence, NULL); 998 999 FREE( setup ); 1000} 1001 1002 1003/** 1004 * Create a new primitive tiling engine. Plug it into the backend of 1005 * the draw module. Currently also creates a rasterizer to use with 1006 * it. 1007 */ 1008struct lp_setup_context * 1009lp_setup_create( struct pipe_context *pipe, 1010 struct draw_context *draw ) 1011{ 1012 struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); 1013 struct lp_setup_context *setup = CALLOC_STRUCT(lp_setup_context); 1014 unsigned i; 1015 1016 if (!setup) 1017 return NULL; 1018 1019 lp_setup_init_vbuf(setup); 1020 1021 /* Used only in update_state(): 1022 */ 1023 setup->pipe = pipe; 1024 1025 1026 setup->num_threads = screen->num_threads; 1027 setup->vbuf = draw_vbuf_stage(draw, &setup->base); 1028 if (!setup->vbuf) 1029 goto fail; 1030 1031 draw_set_rasterize_stage(draw, setup->vbuf); 1032 draw_set_render(draw, &setup->base); 1033 1034 /* create some empty scenes */ 1035 for (i = 0; i < MAX_SCENES; i++) { 1036 setup->scenes[i] = lp_scene_create( pipe ); 1037 } 1038 1039 setup->triangle = first_triangle; 1040 setup->line = first_line; 1041 setup->point = first_point; 1042 1043 setup->dirty = ~0; 1044 1045 return setup; 1046 1047fail: 1048 if (setup->vbuf) 1049 ; 1050 1051 FREE(setup); 1052 return NULL; 1053} 1054 1055 1056/** 1057 * Put a BeginQuery command into all bins. 1058 */ 1059void 1060lp_setup_begin_query(struct lp_setup_context *setup, 1061 struct llvmpipe_query *pq) 1062{ 1063 /* init the query to its beginning state */ 1064 assert(setup->active_query == NULL); 1065 1066 set_scene_state(setup, SETUP_ACTIVE, "begin_query"); 1067 1068 setup->active_query = pq; 1069 1070 if (setup->scene) { 1071 if (!lp_scene_bin_everywhere(setup->scene, 1072 LP_RAST_OP_BEGIN_QUERY, 1073 lp_rast_arg_query(pq))) { 1074 1075 if (!lp_setup_flush_and_restart(setup)) 1076 return; 1077 1078 if (!lp_scene_bin_everywhere(setup->scene, 1079 LP_RAST_OP_BEGIN_QUERY, 1080 lp_rast_arg_query(pq))) { 1081 return; 1082 } 1083 } 1084 } 1085} 1086 1087 1088/** 1089 * Put an EndQuery command into all bins. 1090 */ 1091void 1092lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) 1093{ 1094 union lp_rast_cmd_arg dummy = { 0 }; 1095 1096 set_scene_state(setup, SETUP_ACTIVE, "end_query"); 1097 1098 assert(setup->active_query == pq); 1099 setup->active_query = NULL; 1100 1101 /* Setup will automatically re-issue any query which carried over a 1102 * scene boundary, and the rasterizer automatically "ends" queries 1103 * which are active at the end of a scene, so there is no need to 1104 * retry this commands on failure. 1105 */ 1106 if (setup->scene) { 1107 /* pq->fence should be the fence of the *last* scene which 1108 * contributed to the query result. 1109 */ 1110 lp_fence_reference(&pq->fence, setup->scene->fence); 1111 1112 if (!lp_scene_bin_everywhere(setup->scene, 1113 LP_RAST_OP_END_QUERY, 1114 dummy)) { 1115 lp_setup_flush(setup, NULL, __FUNCTION__); 1116 } 1117 } 1118 else { 1119 lp_fence_reference(&pq->fence, setup->last_fence); 1120 } 1121} 1122 1123 1124boolean 1125lp_setup_flush_and_restart(struct lp_setup_context *setup) 1126{ 1127 if (0) debug_printf("%s\n", __FUNCTION__); 1128 1129 assert(setup->state == SETUP_ACTIVE); 1130 1131 if (!set_scene_state(setup, SETUP_FLUSHED, __FUNCTION__)) 1132 return FALSE; 1133 1134 if (!lp_setup_update_state(setup, TRUE)) 1135 return FALSE; 1136 1137 return TRUE; 1138} 1139 1140 1141