cso_context.c revision 51d139f03898e5e46af6363c6bba131455738cc4
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 * @file 30 * 31 * Wrap the cso cache & hash mechanisms in a simplified 32 * pipe-driver-specific interface. 33 * 34 * @author Zack Rusin <zack@tungstengraphics.com> 35 * @author Keith Whitwell <keith@tungstengraphics.com> 36 */ 37 38#include "pipe/p_state.h" 39#include "util/u_inlines.h" 40#include "util/u_memory.h" 41#include "tgsi/tgsi_parse.h" 42 43#include "cso_cache/cso_context.h" 44#include "cso_cache/cso_cache.h" 45#include "cso_cache/cso_hash.h" 46#include "cso_context.h" 47 48struct cso_context { 49 struct pipe_context *pipe; 50 struct cso_cache *cache; 51 52 struct { 53 void *samplers[PIPE_MAX_SAMPLERS]; 54 unsigned nr_samplers; 55 56 void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; 57 unsigned nr_vertex_samplers; 58 } hw; 59 60 void *samplers[PIPE_MAX_SAMPLERS]; 61 unsigned nr_samplers; 62 63 void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; 64 unsigned nr_vertex_samplers; 65 66 unsigned nr_samplers_saved; 67 void *samplers_saved[PIPE_MAX_SAMPLERS]; 68 69 unsigned nr_vertex_samplers_saved; 70 void *vertex_samplers_saved[PIPE_MAX_VERTEX_SAMPLERS]; 71 72 struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; 73 uint nr_textures; 74 75 struct pipe_texture *vertex_textures[PIPE_MAX_VERTEX_SAMPLERS]; 76 uint nr_vertex_textures; 77 78 uint nr_textures_saved; 79 struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS]; 80 81 uint nr_vertex_textures_saved; 82 struct pipe_texture *vertex_textures_saved[PIPE_MAX_SAMPLERS]; 83 84 /** Current and saved state. 85 * The saved state is used as a 1-deep stack. 86 */ 87 void *blend, *blend_saved; 88 void *depth_stencil, *depth_stencil_saved; 89 void *rasterizer, *rasterizer_saved; 90 void *fragment_shader, *fragment_shader_saved, *geometry_shader; 91 void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved; 92 void *velements, *velements_saved; 93 94 struct pipe_framebuffer_state fb, fb_saved; 95 struct pipe_viewport_state vp, vp_saved; 96 struct pipe_blend_color blend_color; 97 struct pipe_stencil_ref stencil_ref, stencil_ref_saved; 98}; 99 100 101static void 102free_framebuffer_state(struct pipe_framebuffer_state *fb); 103 104 105static boolean delete_blend_state(struct cso_context *ctx, void *state) 106{ 107 struct cso_blend *cso = (struct cso_blend *)state; 108 109 if (ctx->blend == cso->data) 110 return FALSE; 111 112 if (cso->delete_state) 113 cso->delete_state(cso->context, cso->data); 114 FREE(state); 115 return TRUE; 116} 117 118static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state) 119{ 120 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state; 121 122 if (ctx->depth_stencil == cso->data) 123 return FALSE; 124 125 if (cso->delete_state) 126 cso->delete_state(cso->context, cso->data); 127 FREE(state); 128 129 return TRUE; 130} 131 132static boolean delete_sampler_state(struct cso_context *ctx, void *state) 133{ 134 struct cso_sampler *cso = (struct cso_sampler *)state; 135 if (cso->delete_state) 136 cso->delete_state(cso->context, cso->data); 137 FREE(state); 138 return TRUE; 139} 140 141static boolean delete_rasterizer_state(struct cso_context *ctx, void *state) 142{ 143 struct cso_rasterizer *cso = (struct cso_rasterizer *)state; 144 145 if (ctx->rasterizer == cso->data) 146 return FALSE; 147 if (cso->delete_state) 148 cso->delete_state(cso->context, cso->data); 149 FREE(state); 150 return TRUE; 151} 152 153static boolean delete_fs_state(struct cso_context *ctx, void *state) 154{ 155 struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state; 156 if (ctx->fragment_shader == cso->data) 157 return FALSE; 158 if (cso->delete_state) 159 cso->delete_state(cso->context, cso->data); 160 FREE(state); 161 return TRUE; 162} 163 164static boolean delete_vs_state(struct cso_context *ctx, void *state) 165{ 166 struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state; 167 if (ctx->vertex_shader == cso->data) 168 return TRUE; 169 if (cso->delete_state) 170 cso->delete_state(cso->context, cso->data); 171 FREE(state); 172 return FALSE; 173} 174 175static boolean delete_vertex_elements(struct cso_context *ctx, 176 void *state) 177{ 178 struct cso_velements *cso = (struct cso_velements *)state; 179 180 if (ctx->velements == cso->data) 181 return FALSE; 182 183 if (cso->delete_state) 184 cso->delete_state(cso->context, cso->data); 185 FREE(state); 186 return TRUE; 187} 188 189 190static INLINE boolean delete_cso(struct cso_context *ctx, 191 void *state, enum cso_cache_type type) 192{ 193 switch (type) { 194 case CSO_BLEND: 195 return delete_blend_state(ctx, state); 196 break; 197 case CSO_SAMPLER: 198 return delete_sampler_state(ctx, state); 199 break; 200 case CSO_DEPTH_STENCIL_ALPHA: 201 return delete_depth_stencil_state(ctx, state); 202 break; 203 case CSO_RASTERIZER: 204 return delete_rasterizer_state(ctx, state); 205 break; 206 case CSO_FRAGMENT_SHADER: 207 return delete_fs_state(ctx, state); 208 break; 209 case CSO_VERTEX_SHADER: 210 return delete_vs_state(ctx, state); 211 break; 212 case CSO_VELEMENTS: 213 return delete_vertex_elements(ctx, state); 214 break; 215 default: 216 assert(0); 217 FREE(state); 218 } 219 return FALSE; 220} 221 222static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type, 223 int max_size, void *user_data) 224{ 225 struct cso_context *ctx = (struct cso_context *)user_data; 226 /* if we're approach the maximum size, remove fourth of the entries 227 * otherwise every subsequent call will go through the same */ 228 int hash_size = cso_hash_size(hash); 229 int max_entries = (max_size > hash_size) ? max_size : hash_size; 230 int to_remove = (max_size < max_entries) * max_entries/4; 231 struct cso_hash_iter iter = cso_hash_first_node(hash); 232 if (hash_size > max_size) 233 to_remove += hash_size - max_size; 234 while (to_remove) { 235 /*remove elements until we're good */ 236 /*fixme: currently we pick the nodes to remove at random*/ 237 void *cso = cso_hash_iter_data(iter); 238 if (delete_cso(ctx, cso, type)) { 239 iter = cso_hash_erase(hash, iter); 240 --to_remove; 241 } else 242 iter = cso_hash_iter_next(iter); 243 } 244} 245 246 247struct cso_context *cso_create_context( struct pipe_context *pipe ) 248{ 249 struct cso_context *ctx = CALLOC_STRUCT(cso_context); 250 if (ctx == NULL) 251 goto out; 252 253 ctx->cache = cso_cache_create(); 254 if (ctx->cache == NULL) 255 goto out; 256 cso_cache_set_sanitize_callback(ctx->cache, 257 sanitize_hash, 258 ctx); 259 260 ctx->pipe = pipe; 261 262 /* Enable for testing: */ 263 if (0) cso_set_maximum_cache_size( ctx->cache, 4 ); 264 265 return ctx; 266 267out: 268 cso_destroy_context( ctx ); 269 return NULL; 270} 271 272 273/** 274 * Prior to context destruction, this function unbinds all state objects. 275 */ 276void cso_release_all( struct cso_context *ctx ) 277{ 278 unsigned i; 279 280 if (ctx->pipe) { 281 ctx->pipe->bind_blend_state( ctx->pipe, NULL ); 282 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL ); 283 ctx->pipe->bind_fragment_sampler_states( ctx->pipe, 0, NULL ); 284 if (ctx->pipe->bind_vertex_sampler_states) 285 ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 0, NULL); 286 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL ); 287 ctx->pipe->bind_fs_state( ctx->pipe, NULL ); 288 ctx->pipe->bind_vs_state( ctx->pipe, NULL ); 289 } 290 291 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 292 pipe_texture_reference(&ctx->textures[i], NULL); 293 pipe_texture_reference(&ctx->textures_saved[i], NULL); 294 } 295 296 for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { 297 pipe_texture_reference(&ctx->vertex_textures[i], NULL); 298 pipe_texture_reference(&ctx->vertex_textures_saved[i], NULL); 299 } 300 301 free_framebuffer_state(&ctx->fb); 302 free_framebuffer_state(&ctx->fb_saved); 303 304 if (ctx->cache) { 305 cso_cache_delete( ctx->cache ); 306 ctx->cache = NULL; 307 } 308} 309 310 311void cso_destroy_context( struct cso_context *ctx ) 312{ 313 if (ctx) { 314 /*cso_release_all( ctx );*/ 315 FREE( ctx ); 316 } 317} 318 319 320/* Those function will either find the state of the given template 321 * in the cache or they will create a new state from the given 322 * template, insert it in the cache and return it. 323 */ 324 325/* 326 * If the driver returns 0 from the create method then they will assign 327 * the data member of the cso to be the template itself. 328 */ 329 330enum pipe_error cso_set_blend(struct cso_context *ctx, 331 const struct pipe_blend_state *templ) 332{ 333 unsigned key_size, hash_key; 334 struct cso_hash_iter iter; 335 void *handle; 336 337 key_size = templ->independent_blend_enable ? sizeof(struct pipe_blend_state) : 338 (char *)&(templ->rt[1]) - (char *)templ; 339 hash_key = cso_construct_key((void*)templ, key_size); 340 iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND, (void*)templ, key_size); 341 342 if (cso_hash_iter_is_null(iter)) { 343 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend)); 344 if (!cso) 345 return PIPE_ERROR_OUT_OF_MEMORY; 346 347 memcpy(&cso->state, templ, key_size); 348 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state); 349 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state; 350 cso->context = ctx->pipe; 351 352 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso); 353 if (cso_hash_iter_is_null(iter)) { 354 FREE(cso); 355 return PIPE_ERROR_OUT_OF_MEMORY; 356 } 357 358 handle = cso->data; 359 } 360 else { 361 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data; 362 } 363 364 if (ctx->blend != handle) { 365 ctx->blend = handle; 366 ctx->pipe->bind_blend_state(ctx->pipe, handle); 367 } 368 return PIPE_OK; 369} 370 371void cso_save_blend(struct cso_context *ctx) 372{ 373 assert(!ctx->blend_saved); 374 ctx->blend_saved = ctx->blend; 375} 376 377void cso_restore_blend(struct cso_context *ctx) 378{ 379 if (ctx->blend != ctx->blend_saved) { 380 ctx->blend = ctx->blend_saved; 381 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved); 382 } 383 ctx->blend_saved = NULL; 384} 385 386 387 388enum pipe_error cso_single_sampler(struct cso_context *ctx, 389 unsigned idx, 390 const struct pipe_sampler_state *templ) 391{ 392 void *handle = NULL; 393 394 if (templ != NULL) { 395 unsigned key_size = sizeof(struct pipe_sampler_state); 396 unsigned hash_key = cso_construct_key((void*)templ, key_size); 397 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 398 hash_key, CSO_SAMPLER, 399 (void*)templ, key_size); 400 401 if (cso_hash_iter_is_null(iter)) { 402 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); 403 if (!cso) 404 return PIPE_ERROR_OUT_OF_MEMORY; 405 406 memcpy(&cso->state, templ, sizeof(*templ)); 407 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); 408 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; 409 cso->context = ctx->pipe; 410 411 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); 412 if (cso_hash_iter_is_null(iter)) { 413 FREE(cso); 414 return PIPE_ERROR_OUT_OF_MEMORY; 415 } 416 417 handle = cso->data; 418 } 419 else { 420 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; 421 } 422 } 423 424 ctx->samplers[idx] = handle; 425 return PIPE_OK; 426} 427 428enum pipe_error 429cso_single_vertex_sampler(struct cso_context *ctx, 430 unsigned idx, 431 const struct pipe_sampler_state *templ) 432{ 433 void *handle = NULL; 434 435 if (templ != NULL) { 436 unsigned key_size = sizeof(struct pipe_sampler_state); 437 unsigned hash_key = cso_construct_key((void*)templ, key_size); 438 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 439 hash_key, CSO_SAMPLER, 440 (void*)templ, key_size); 441 442 if (cso_hash_iter_is_null(iter)) { 443 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); 444 if (!cso) 445 return PIPE_ERROR_OUT_OF_MEMORY; 446 447 memcpy(&cso->state, templ, sizeof(*templ)); 448 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); 449 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; 450 cso->context = ctx->pipe; 451 452 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); 453 if (cso_hash_iter_is_null(iter)) { 454 FREE(cso); 455 return PIPE_ERROR_OUT_OF_MEMORY; 456 } 457 458 handle = cso->data; 459 } 460 else { 461 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; 462 } 463 } 464 465 ctx->vertex_samplers[idx] = handle; 466 return PIPE_OK; 467} 468 469void cso_single_sampler_done( struct cso_context *ctx ) 470{ 471 unsigned i; 472 473 /* find highest non-null sampler */ 474 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) { 475 if (ctx->samplers[i - 1] != NULL) 476 break; 477 } 478 479 ctx->nr_samplers = i; 480 481 if (ctx->hw.nr_samplers != ctx->nr_samplers || 482 memcmp(ctx->hw.samplers, 483 ctx->samplers, 484 ctx->nr_samplers * sizeof(void *)) != 0) 485 { 486 memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *)); 487 ctx->hw.nr_samplers = ctx->nr_samplers; 488 489 ctx->pipe->bind_fragment_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers); 490 } 491} 492 493void 494cso_single_vertex_sampler_done(struct cso_context *ctx) 495{ 496 unsigned i; 497 498 /* find highest non-null sampler */ 499 for (i = PIPE_MAX_VERTEX_SAMPLERS; i > 0; i--) { 500 if (ctx->vertex_samplers[i - 1] != NULL) 501 break; 502 } 503 504 ctx->nr_vertex_samplers = i; 505 506 if (ctx->hw.nr_vertex_samplers != ctx->nr_vertex_samplers || 507 memcmp(ctx->hw.vertex_samplers, 508 ctx->vertex_samplers, 509 ctx->nr_vertex_samplers * sizeof(void *)) != 0) 510 { 511 memcpy(ctx->hw.vertex_samplers, 512 ctx->vertex_samplers, 513 ctx->nr_vertex_samplers * sizeof(void *)); 514 ctx->hw.nr_vertex_samplers = ctx->nr_vertex_samplers; 515 516 ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 517 ctx->nr_vertex_samplers, 518 ctx->vertex_samplers); 519 } 520} 521 522/* 523 * If the function encouters any errors it will return the 524 * last one. Done to always try to set as many samplers 525 * as possible. 526 */ 527enum pipe_error cso_set_samplers( struct cso_context *ctx, 528 unsigned nr, 529 const struct pipe_sampler_state **templates ) 530{ 531 unsigned i; 532 enum pipe_error temp, error = PIPE_OK; 533 534 /* TODO: fastpath 535 */ 536 537 for (i = 0; i < nr; i++) { 538 temp = cso_single_sampler( ctx, i, templates[i] ); 539 if (temp != PIPE_OK) 540 error = temp; 541 } 542 543 for ( ; i < ctx->nr_samplers; i++) { 544 temp = cso_single_sampler( ctx, i, NULL ); 545 if (temp != PIPE_OK) 546 error = temp; 547 } 548 549 cso_single_sampler_done( ctx ); 550 551 return error; 552} 553 554void cso_save_samplers(struct cso_context *ctx) 555{ 556 ctx->nr_samplers_saved = ctx->nr_samplers; 557 memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers)); 558} 559 560void cso_restore_samplers(struct cso_context *ctx) 561{ 562 ctx->nr_samplers = ctx->nr_samplers_saved; 563 memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers)); 564 cso_single_sampler_done( ctx ); 565} 566 567/* 568 * If the function encouters any errors it will return the 569 * last one. Done to always try to set as many samplers 570 * as possible. 571 */ 572enum pipe_error cso_set_vertex_samplers(struct cso_context *ctx, 573 unsigned nr, 574 const struct pipe_sampler_state **templates) 575{ 576 unsigned i; 577 enum pipe_error temp, error = PIPE_OK; 578 579 /* TODO: fastpath 580 */ 581 582 for (i = 0; i < nr; i++) { 583 temp = cso_single_vertex_sampler( ctx, i, templates[i] ); 584 if (temp != PIPE_OK) 585 error = temp; 586 } 587 588 for ( ; i < ctx->nr_samplers; i++) { 589 temp = cso_single_vertex_sampler( ctx, i, NULL ); 590 if (temp != PIPE_OK) 591 error = temp; 592 } 593 594 cso_single_vertex_sampler_done( ctx ); 595 596 return error; 597} 598 599void 600cso_save_vertex_samplers(struct cso_context *ctx) 601{ 602 ctx->nr_vertex_samplers_saved = ctx->nr_vertex_samplers; 603 memcpy(ctx->vertex_samplers_saved, ctx->vertex_samplers, sizeof(ctx->vertex_samplers)); 604} 605 606void 607cso_restore_vertex_samplers(struct cso_context *ctx) 608{ 609 ctx->nr_vertex_samplers = ctx->nr_vertex_samplers_saved; 610 memcpy(ctx->vertex_samplers, ctx->vertex_samplers_saved, sizeof(ctx->vertex_samplers)); 611 cso_single_vertex_sampler_done(ctx); 612} 613 614 615enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, 616 uint count, 617 struct pipe_texture **textures ) 618{ 619 uint i; 620 621 ctx->nr_textures = count; 622 623 for (i = 0; i < count; i++) 624 pipe_texture_reference(&ctx->textures[i], textures[i]); 625 for ( ; i < PIPE_MAX_SAMPLERS; i++) 626 pipe_texture_reference(&ctx->textures[i], NULL); 627 628 ctx->pipe->set_fragment_sampler_textures(ctx->pipe, count, textures); 629 630 return PIPE_OK; 631} 632 633void cso_save_sampler_textures( struct cso_context *ctx ) 634{ 635 uint i; 636 637 ctx->nr_textures_saved = ctx->nr_textures; 638 for (i = 0; i < ctx->nr_textures; i++) { 639 assert(!ctx->textures_saved[i]); 640 pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]); 641 } 642} 643 644void cso_restore_sampler_textures( struct cso_context *ctx ) 645{ 646 uint i; 647 648 ctx->nr_textures = ctx->nr_textures_saved; 649 650 for (i = 0; i < ctx->nr_textures; i++) { 651 pipe_texture_reference(&ctx->textures[i], NULL); 652 ctx->textures[i] = ctx->textures_saved[i]; 653 ctx->textures_saved[i] = NULL; 654 } 655 for ( ; i < PIPE_MAX_SAMPLERS; i++) 656 pipe_texture_reference(&ctx->textures[i], NULL); 657 658 ctx->pipe->set_fragment_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures); 659 660 ctx->nr_textures_saved = 0; 661} 662 663 664 665enum pipe_error 666cso_set_vertex_sampler_textures(struct cso_context *ctx, 667 uint count, 668 struct pipe_texture **textures) 669{ 670 uint i; 671 672 ctx->nr_vertex_textures = count; 673 674 for (i = 0; i < count; i++) { 675 pipe_texture_reference(&ctx->vertex_textures[i], textures[i]); 676 } 677 for ( ; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { 678 pipe_texture_reference(&ctx->vertex_textures[i], NULL); 679 } 680 681 ctx->pipe->set_vertex_sampler_textures(ctx->pipe, count, textures); 682 683 return PIPE_OK; 684} 685 686void 687cso_save_vertex_sampler_textures(struct cso_context *ctx) 688{ 689 uint i; 690 691 ctx->nr_vertex_textures_saved = ctx->nr_vertex_textures; 692 for (i = 0; i < ctx->nr_vertex_textures; i++) { 693 assert(!ctx->vertex_textures_saved[i]); 694 pipe_texture_reference(&ctx->vertex_textures_saved[i], ctx->vertex_textures[i]); 695 } 696} 697 698void 699cso_restore_vertex_sampler_textures(struct cso_context *ctx) 700{ 701 uint i; 702 703 ctx->nr_vertex_textures = ctx->nr_vertex_textures_saved; 704 705 for (i = 0; i < ctx->nr_vertex_textures; i++) { 706 pipe_texture_reference(&ctx->vertex_textures[i], NULL); 707 ctx->vertex_textures[i] = ctx->vertex_textures_saved[i]; 708 ctx->vertex_textures_saved[i] = NULL; 709 } 710 for ( ; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { 711 pipe_texture_reference(&ctx->vertex_textures[i], NULL); 712 } 713 714 ctx->pipe->set_vertex_sampler_textures(ctx->pipe, 715 ctx->nr_vertex_textures, 716 ctx->vertex_textures); 717 718 ctx->nr_vertex_textures_saved = 0; 719} 720 721 722 723enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, 724 const struct pipe_depth_stencil_alpha_state *templ) 725{ 726 unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state); 727 unsigned hash_key = cso_construct_key((void*)templ, key_size); 728 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 729 hash_key, 730 CSO_DEPTH_STENCIL_ALPHA, 731 (void*)templ, key_size); 732 void *handle; 733 734 if (cso_hash_iter_is_null(iter)) { 735 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha)); 736 if (!cso) 737 return PIPE_ERROR_OUT_OF_MEMORY; 738 739 memcpy(&cso->state, templ, sizeof(*templ)); 740 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state); 741 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state; 742 cso->context = ctx->pipe; 743 744 iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso); 745 if (cso_hash_iter_is_null(iter)) { 746 FREE(cso); 747 return PIPE_ERROR_OUT_OF_MEMORY; 748 } 749 750 handle = cso->data; 751 } 752 else { 753 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data; 754 } 755 756 if (ctx->depth_stencil != handle) { 757 ctx->depth_stencil = handle; 758 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle); 759 } 760 return PIPE_OK; 761} 762 763void cso_save_depth_stencil_alpha(struct cso_context *ctx) 764{ 765 assert(!ctx->depth_stencil_saved); 766 ctx->depth_stencil_saved = ctx->depth_stencil; 767} 768 769void cso_restore_depth_stencil_alpha(struct cso_context *ctx) 770{ 771 if (ctx->depth_stencil != ctx->depth_stencil_saved) { 772 ctx->depth_stencil = ctx->depth_stencil_saved; 773 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved); 774 } 775 ctx->depth_stencil_saved = NULL; 776} 777 778 779 780enum pipe_error cso_set_rasterizer(struct cso_context *ctx, 781 const struct pipe_rasterizer_state *templ) 782{ 783 unsigned key_size = sizeof(struct pipe_rasterizer_state); 784 unsigned hash_key = cso_construct_key((void*)templ, key_size); 785 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 786 hash_key, CSO_RASTERIZER, 787 (void*)templ, key_size); 788 void *handle = NULL; 789 790 if (cso_hash_iter_is_null(iter)) { 791 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer)); 792 if (!cso) 793 return PIPE_ERROR_OUT_OF_MEMORY; 794 795 memcpy(&cso->state, templ, sizeof(*templ)); 796 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state); 797 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state; 798 cso->context = ctx->pipe; 799 800 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso); 801 if (cso_hash_iter_is_null(iter)) { 802 FREE(cso); 803 return PIPE_ERROR_OUT_OF_MEMORY; 804 } 805 806 handle = cso->data; 807 } 808 else { 809 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data; 810 } 811 812 if (ctx->rasterizer != handle) { 813 ctx->rasterizer = handle; 814 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle); 815 } 816 return PIPE_OK; 817} 818 819void cso_save_rasterizer(struct cso_context *ctx) 820{ 821 assert(!ctx->rasterizer_saved); 822 ctx->rasterizer_saved = ctx->rasterizer; 823} 824 825void cso_restore_rasterizer(struct cso_context *ctx) 826{ 827 if (ctx->rasterizer != ctx->rasterizer_saved) { 828 ctx->rasterizer = ctx->rasterizer_saved; 829 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved); 830 } 831 ctx->rasterizer_saved = NULL; 832} 833 834 835 836enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx, 837 void *handle ) 838{ 839 if (ctx->fragment_shader != handle) { 840 ctx->fragment_shader = handle; 841 ctx->pipe->bind_fs_state(ctx->pipe, handle); 842 } 843 return PIPE_OK; 844} 845 846void cso_delete_fragment_shader(struct cso_context *ctx, void *handle ) 847{ 848 if (handle == ctx->fragment_shader) { 849 /* unbind before deleting */ 850 ctx->pipe->bind_fs_state(ctx->pipe, NULL); 851 ctx->fragment_shader = NULL; 852 } 853 ctx->pipe->delete_fs_state(ctx->pipe, handle); 854} 855 856/* Not really working: 857 */ 858#if 0 859enum pipe_error cso_set_fragment_shader(struct cso_context *ctx, 860 const struct pipe_shader_state *templ) 861{ 862 const struct tgsi_token *tokens = templ->tokens; 863 unsigned num_tokens = tgsi_num_tokens(tokens); 864 size_t tokens_size = num_tokens*sizeof(struct tgsi_token); 865 unsigned hash_key = cso_construct_key((void*)tokens, tokens_size); 866 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 867 hash_key, 868 CSO_FRAGMENT_SHADER, 869 (void*)tokens, 870 sizeof(*templ)); /* XXX correct? tokens_size? */ 871 void *handle = NULL; 872 873 if (cso_hash_iter_is_null(iter)) { 874 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size); 875 struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso)); 876 877 if (!cso) 878 return PIPE_ERROR_OUT_OF_MEMORY; 879 880 memcpy(cso_tokens, tokens, tokens_size); 881 cso->state.tokens = cso_tokens; 882 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state); 883 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state; 884 cso->context = ctx->pipe; 885 886 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso); 887 if (cso_hash_iter_is_null(iter)) { 888 FREE(cso); 889 return PIPE_ERROR_OUT_OF_MEMORY; 890 } 891 892 handle = cso->data; 893 } 894 else { 895 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data; 896 } 897 898 return cso_set_fragment_shader_handle( ctx, handle ); 899} 900#endif 901 902void cso_save_fragment_shader(struct cso_context *ctx) 903{ 904 assert(!ctx->fragment_shader_saved); 905 ctx->fragment_shader_saved = ctx->fragment_shader; 906} 907 908void cso_restore_fragment_shader(struct cso_context *ctx) 909{ 910 if (ctx->fragment_shader_saved != ctx->fragment_shader) { 911 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved); 912 ctx->fragment_shader = ctx->fragment_shader_saved; 913 } 914 ctx->fragment_shader_saved = NULL; 915} 916 917 918enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx, 919 void *handle ) 920{ 921 if (ctx->vertex_shader != handle) { 922 ctx->vertex_shader = handle; 923 ctx->pipe->bind_vs_state(ctx->pipe, handle); 924 } 925 return PIPE_OK; 926} 927 928void cso_delete_vertex_shader(struct cso_context *ctx, void *handle ) 929{ 930 if (handle == ctx->vertex_shader) { 931 /* unbind before deleting */ 932 ctx->pipe->bind_vs_state(ctx->pipe, NULL); 933 ctx->vertex_shader = NULL; 934 } 935 ctx->pipe->delete_vs_state(ctx->pipe, handle); 936} 937 938 939/* Not really working: 940 */ 941#if 0 942enum pipe_error cso_set_vertex_shader(struct cso_context *ctx, 943 const struct pipe_shader_state *templ) 944{ 945 unsigned hash_key = cso_construct_key((void*)templ, 946 sizeof(struct pipe_shader_state)); 947 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 948 hash_key, CSO_VERTEX_SHADER, 949 (void*)templ, 950 sizeof(*templ)); 951 void *handle = NULL; 952 953 if (cso_hash_iter_is_null(iter)) { 954 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader)); 955 956 if (!cso) 957 return PIPE_ERROR_OUT_OF_MEMORY; 958 959 memcpy(cso->state, templ, sizeof(*templ)); 960 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state); 961 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state; 962 cso->context = ctx->pipe; 963 964 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso); 965 if (cso_hash_iter_is_null(iter)) { 966 FREE(cso); 967 return PIPE_ERROR_OUT_OF_MEMORY; 968 } 969 970 handle = cso->data; 971 } 972 else { 973 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data; 974 } 975 976 return cso_set_vertex_shader_handle( ctx, handle ); 977} 978#endif 979 980 981 982void cso_save_vertex_shader(struct cso_context *ctx) 983{ 984 assert(!ctx->vertex_shader_saved); 985 ctx->vertex_shader_saved = ctx->vertex_shader; 986} 987 988void cso_restore_vertex_shader(struct cso_context *ctx) 989{ 990 if (ctx->vertex_shader_saved != ctx->vertex_shader) { 991 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved); 992 ctx->vertex_shader = ctx->vertex_shader_saved; 993 } 994 ctx->vertex_shader_saved = NULL; 995} 996 997 998/** 999 * Copy framebuffer state from src to dst with refcounting of surfaces. 1000 */ 1001static void 1002copy_framebuffer_state(struct pipe_framebuffer_state *dst, 1003 const struct pipe_framebuffer_state *src) 1004{ 1005 uint i; 1006 1007 dst->width = src->width; 1008 dst->height = src->height; 1009 dst->nr_cbufs = src->nr_cbufs; 1010 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 1011 pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]); 1012 } 1013 pipe_surface_reference(&dst->zsbuf, src->zsbuf); 1014} 1015 1016 1017static void 1018free_framebuffer_state(struct pipe_framebuffer_state *fb) 1019{ 1020 uint i; 1021 1022 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 1023 pipe_surface_reference(&fb->cbufs[i], NULL); 1024 } 1025 pipe_surface_reference(&fb->zsbuf, NULL); 1026} 1027 1028 1029enum pipe_error cso_set_framebuffer(struct cso_context *ctx, 1030 const struct pipe_framebuffer_state *fb) 1031{ 1032 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { 1033 copy_framebuffer_state(&ctx->fb, fb); 1034 ctx->pipe->set_framebuffer_state(ctx->pipe, fb); 1035 } 1036 return PIPE_OK; 1037} 1038 1039void cso_save_framebuffer(struct cso_context *ctx) 1040{ 1041 copy_framebuffer_state(&ctx->fb_saved, &ctx->fb); 1042} 1043 1044void cso_restore_framebuffer(struct cso_context *ctx) 1045{ 1046 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { 1047 copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); 1048 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); 1049 free_framebuffer_state(&ctx->fb_saved); 1050 } 1051} 1052 1053 1054enum pipe_error cso_set_viewport(struct cso_context *ctx, 1055 const struct pipe_viewport_state *vp) 1056{ 1057 if (memcmp(&ctx->vp, vp, sizeof(*vp))) { 1058 ctx->vp = *vp; 1059 ctx->pipe->set_viewport_state(ctx->pipe, vp); 1060 } 1061 return PIPE_OK; 1062} 1063 1064void cso_save_viewport(struct cso_context *ctx) 1065{ 1066 ctx->vp_saved = ctx->vp; 1067} 1068 1069 1070void cso_restore_viewport(struct cso_context *ctx) 1071{ 1072 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) { 1073 ctx->vp = ctx->vp_saved; 1074 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp); 1075 } 1076} 1077 1078 1079enum pipe_error cso_set_blend_color(struct cso_context *ctx, 1080 const struct pipe_blend_color *bc) 1081{ 1082 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) { 1083 ctx->blend_color = *bc; 1084 ctx->pipe->set_blend_color(ctx->pipe, bc); 1085 } 1086 return PIPE_OK; 1087} 1088 1089enum pipe_error cso_set_stencil_ref(struct cso_context *ctx, 1090 const struct pipe_stencil_ref *sr) 1091{ 1092 if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) { 1093 ctx->stencil_ref = *sr; 1094 ctx->pipe->set_stencil_ref(ctx->pipe, sr); 1095 } 1096 return PIPE_OK; 1097} 1098 1099void cso_save_stencil_ref(struct cso_context *ctx) 1100{ 1101 ctx->stencil_ref_saved = ctx->stencil_ref; 1102} 1103 1104 1105void cso_restore_stencil_ref(struct cso_context *ctx) 1106{ 1107 if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved, sizeof(ctx->stencil_ref))) { 1108 ctx->stencil_ref = ctx->stencil_ref_saved; 1109 ctx->pipe->set_stencil_ref(ctx->pipe, &ctx->stencil_ref); 1110 } 1111} 1112 1113enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx, 1114 void *handle) 1115{ 1116 if (ctx->geometry_shader != handle) { 1117 ctx->geometry_shader = handle; 1118 ctx->pipe->bind_gs_state(ctx->pipe, handle); 1119 } 1120 return PIPE_OK; 1121} 1122 1123void cso_delete_geometry_shader(struct cso_context *ctx, void *handle) 1124{ 1125 if (handle == ctx->geometry_shader) { 1126 /* unbind before deleting */ 1127 ctx->pipe->bind_gs_state(ctx->pipe, NULL); 1128 ctx->geometry_shader = NULL; 1129 } 1130 ctx->pipe->delete_gs_state(ctx->pipe, handle); 1131} 1132 1133void cso_save_geometry_shader(struct cso_context *ctx) 1134{ 1135 assert(!ctx->geometry_shader_saved); 1136 ctx->geometry_shader_saved = ctx->geometry_shader; 1137} 1138 1139void cso_restore_geometry_shader(struct cso_context *ctx) 1140{ 1141 if (ctx->geometry_shader_saved != ctx->geometry_shader) { 1142 ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved); 1143 ctx->geometry_shader = ctx->geometry_shader_saved; 1144 } 1145 ctx->geometry_shader_saved = NULL; 1146} 1147 1148enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, 1149 unsigned count, 1150 const struct pipe_vertex_element *states) 1151{ 1152 unsigned key_size, hash_key; 1153 struct cso_hash_iter iter; 1154 void *handle; 1155 1156 key_size = sizeof(struct pipe_vertex_element) * count; 1157 hash_key = cso_construct_key((void*)states, key_size); 1158 iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS, (void*)states, key_size); 1159 1160 if (cso_hash_iter_is_null(iter)) { 1161 struct cso_velements *cso = MALLOC(sizeof(struct cso_velements)); 1162 if (!cso) 1163 return PIPE_ERROR_OUT_OF_MEMORY; 1164 1165 memcpy(&cso->state, states, key_size); 1166 cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count, &cso->state[0]); 1167 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vertex_elements_state; 1168 cso->context = ctx->pipe; 1169 1170 iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso); 1171 if (cso_hash_iter_is_null(iter)) { 1172 FREE(cso); 1173 return PIPE_ERROR_OUT_OF_MEMORY; 1174 } 1175 1176 handle = cso->data; 1177 } 1178 else { 1179 handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; 1180 } 1181 1182 if (ctx->velements != handle) { 1183 ctx->velements = handle; 1184 ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle); 1185 } 1186 return PIPE_OK; 1187} 1188 1189void cso_save_vertex_elements(struct cso_context *ctx) 1190{ 1191 assert(!ctx->velements); 1192 ctx->velements_saved = ctx->velements; 1193} 1194 1195void cso_restore_vertex_elements(struct cso_context *ctx) 1196{ 1197 if (ctx->velements != ctx->velements_saved) { 1198 ctx->velements = ctx->velements_saved; 1199 ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved); 1200 } 1201 ctx->velements_saved = NULL; 1202}