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