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