cso_context.c revision d2ec02f44026244130b4e6f9d87eac6a03a9c6c1
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 "pipe/p_util.h" 40#include "pipe/p_inlines.h" 41#include "tgsi/util/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 47struct cso_context { 48 struct pipe_context *pipe; 49 struct cso_cache *cache; 50 51 struct { 52 void *samplers[PIPE_MAX_SAMPLERS]; 53 unsigned nr_samplers; 54 } hw; 55 56 void *samplers[PIPE_MAX_SAMPLERS]; 57 unsigned nr_samplers; 58 59 void *samplers_saved[PIPE_MAX_SAMPLERS]; 60 unsigned nr_samplers_saved; 61 62 struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; 63 uint nr_textures; 64 65 struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS]; 66 uint nr_textures_saved; 67 68 /** Current and saved state. 69 * The saved state is used as a 1-deep stack. 70 */ 71 void *blend, *blend_saved; 72 void *depth_stencil, *depth_stencil_saved; 73 void *rasterizer, *rasterizer_saved; 74 void *fragment_shader, *fragment_shader_saved; 75 void *vertex_shader, *vertex_shader_saved; 76 77 struct pipe_framebuffer_state fb, fb_saved; 78 struct pipe_viewport_state vp, vp_saved; 79 struct pipe_blend_color blend_color; 80}; 81 82 83static boolean delete_blend_state(struct cso_context *ctx, void *state) 84{ 85 struct cso_blend *cso = (struct cso_blend *)state; 86 87 if (ctx->blend == cso->data) 88 return FALSE; 89 90 if (cso->delete_state) 91 cso->delete_state(cso->context, cso->data); 92 FREE(state); 93 return TRUE; 94} 95 96static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state) 97{ 98 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state; 99 100 if (ctx->depth_stencil == cso->data) 101 return FALSE; 102 103 if (cso->delete_state) 104 cso->delete_state(cso->context, cso->data); 105 FREE(state); 106 107 return TRUE; 108} 109 110static boolean delete_sampler_state(struct cso_context *ctx, void *state) 111{ 112 struct cso_sampler *cso = (struct cso_sampler *)state; 113 if (cso->delete_state) 114 cso->delete_state(cso->context, cso->data); 115 FREE(state); 116 return TRUE; 117} 118 119static boolean delete_rasterizer_state(struct cso_context *ctx, void *state) 120{ 121 struct cso_rasterizer *cso = (struct cso_rasterizer *)state; 122 123 if (ctx->rasterizer == cso->data) 124 return FALSE; 125 if (cso->delete_state) 126 cso->delete_state(cso->context, cso->data); 127 FREE(state); 128 return TRUE; 129} 130 131static boolean delete_fs_state(struct cso_context *ctx, void *state) 132{ 133 struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state; 134 if (ctx->fragment_shader == cso->data) 135 return FALSE; 136 if (cso->delete_state) 137 cso->delete_state(cso->context, cso->data); 138 FREE(state); 139 return TRUE; 140} 141 142static boolean delete_vs_state(struct cso_context *ctx, void *state) 143{ 144 struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state; 145 if (ctx->vertex_shader == cso->data) 146 return TRUE; 147 if (cso->delete_state) 148 cso->delete_state(cso->context, cso->data); 149 FREE(state); 150 return FALSE; 151} 152 153 154static INLINE boolean delete_cso(struct cso_context *ctx, 155 void *state, enum cso_cache_type type) 156{ 157 switch (type) { 158 case CSO_BLEND: 159 return delete_blend_state(ctx, state); 160 break; 161 case CSO_SAMPLER: 162 return delete_sampler_state(ctx, state); 163 break; 164 case CSO_DEPTH_STENCIL_ALPHA: 165 return delete_depth_stencil_state(ctx, state); 166 break; 167 case CSO_RASTERIZER: 168 return delete_rasterizer_state(ctx, state); 169 break; 170 case CSO_FRAGMENT_SHADER: 171 return delete_fs_state(ctx, state); 172 break; 173 case CSO_VERTEX_SHADER: 174 return delete_vs_state(ctx, state); 175 break; 176 default: 177 assert(0); 178 FREE(state); 179 } 180 return FALSE; 181} 182 183static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type, 184 int max_size, void *user_data) 185{ 186 struct cso_context *ctx = (struct cso_context *)user_data; 187 /* if we're approach the maximum size, remove fourth of the entries 188 * otherwise every subsequent call will go through the same */ 189 int hash_size = cso_hash_size(hash); 190 int max_entries = (max_size > hash_size) ? max_size : hash_size; 191 int to_remove = (max_size < max_entries) * max_entries/4; 192 struct cso_hash_iter iter = cso_hash_first_node(hash); 193 if (hash_size > max_size) 194 to_remove += hash_size - max_size; 195 while (to_remove) { 196 /*remove elements until we're good */ 197 /*fixme: currently we pick the nodes to remove at random*/ 198 void *cso = cso_hash_iter_data(iter); 199 if (delete_cso(ctx, cso, type)) { 200 iter = cso_hash_erase(hash, iter); 201 --to_remove; 202 } else 203 iter = cso_hash_iter_next(iter); 204 } 205} 206 207 208struct cso_context *cso_create_context( struct pipe_context *pipe ) 209{ 210 struct cso_context *ctx = CALLOC_STRUCT(cso_context); 211 if (ctx == NULL) 212 goto out; 213 214 ctx->cache = cso_cache_create(); 215 if (ctx->cache == NULL) 216 goto out; 217 cso_cache_set_sanitize_callback(ctx->cache, 218 sanitize_hash, 219 ctx); 220 221 ctx->pipe = pipe; 222 223 /* Enable for testing: */ 224 if (0) cso_set_maximum_cache_size( ctx->cache, 4 ); 225 226 return ctx; 227 228out: 229 cso_destroy_context( ctx ); 230 return NULL; 231} 232 233 234/** 235 * Prior to context destruction, this function unbinds all state objects. 236 */ 237void cso_release_all( struct cso_context *ctx ) 238{ 239 unsigned i; 240 241 if (ctx->pipe) { 242 ctx->pipe->bind_blend_state( ctx->pipe, NULL ); 243 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL ); 244 ctx->pipe->bind_sampler_states( ctx->pipe, 0, NULL ); 245 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL ); 246 ctx->pipe->bind_fs_state( ctx->pipe, NULL ); 247 ctx->pipe->bind_vs_state( ctx->pipe, NULL ); 248 } 249 250 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 251 pipe_texture_reference(&ctx->textures[i], NULL); 252 pipe_texture_reference(&ctx->textures_saved[i], NULL); 253 } 254 255 if (ctx->cache) { 256 cso_cache_delete( ctx->cache ); 257 ctx->cache = NULL; 258 } 259} 260 261 262void cso_destroy_context( struct cso_context *ctx ) 263{ 264 if (ctx) { 265 //cso_release_all( ctx ); 266 FREE( ctx ); 267 } 268} 269 270 271/* Those function will either find the state of the given template 272 * in the cache or they will create a new state from the given 273 * template, insert it in the cache and return it. 274 */ 275 276/* 277 * If the driver returns 0 from the create method then they will assign 278 * the data member of the cso to be the template itself. 279 */ 280 281enum pipe_error cso_set_blend(struct cso_context *ctx, 282 const struct pipe_blend_state *templ) 283{ 284 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state)); 285 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 286 hash_key, CSO_BLEND, 287 (void*)templ); 288 void *handle; 289 290 if (cso_hash_iter_is_null(iter)) { 291 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend)); 292 if (!cso) 293 return PIPE_ERROR_OUT_OF_MEMORY; 294 295 cso->state = *templ; 296 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state); 297 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state; 298 cso->context = ctx->pipe; 299 300 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso); 301 if (cso_hash_iter_is_null(iter)) { 302 FREE(cso); 303 return PIPE_ERROR_OUT_OF_MEMORY; 304 } 305 306 handle = cso->data; 307 } 308 else { 309 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data; 310 } 311 312 if (ctx->blend != handle) { 313 ctx->blend = handle; 314 ctx->pipe->bind_blend_state(ctx->pipe, handle); 315 } 316 return PIPE_OK; 317} 318 319void cso_save_blend(struct cso_context *ctx) 320{ 321 assert(!ctx->blend_saved); 322 ctx->blend_saved = ctx->blend; 323} 324 325void cso_restore_blend(struct cso_context *ctx) 326{ 327 if (ctx->blend != ctx->blend_saved) { 328 ctx->blend = ctx->blend_saved; 329 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved); 330 } 331 ctx->blend_saved = NULL; 332} 333 334 335 336enum pipe_error cso_single_sampler(struct cso_context *ctx, 337 unsigned idx, 338 const struct pipe_sampler_state *templ) 339{ 340 void *handle = NULL; 341 342 if (templ != NULL) { 343 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state)); 344 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 345 hash_key, CSO_SAMPLER, 346 (void*)templ); 347 348 if (cso_hash_iter_is_null(iter)) { 349 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); 350 if (!cso) 351 return PIPE_ERROR_OUT_OF_MEMORY; 352 353 cso->state = *templ; 354 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); 355 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; 356 cso->context = ctx->pipe; 357 358 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); 359 if (cso_hash_iter_is_null(iter)) { 360 FREE(cso); 361 return PIPE_ERROR_OUT_OF_MEMORY; 362 } 363 364 handle = cso->data; 365 } 366 else { 367 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; 368 } 369 } 370 371 ctx->samplers[idx] = handle; 372 return PIPE_OK; 373} 374 375void cso_single_sampler_done( struct cso_context *ctx ) 376{ 377 unsigned i; 378 379 /* find highest non-null sampler */ 380 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) { 381 if (ctx->samplers[i - 1] != NULL) 382 break; 383 } 384 385 ctx->nr_samplers = i; 386 387 if (ctx->hw.nr_samplers != ctx->nr_samplers || 388 memcmp(ctx->hw.samplers, 389 ctx->samplers, 390 ctx->nr_samplers * sizeof(void *)) != 0) 391 { 392 memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *)); 393 ctx->hw.nr_samplers = ctx->nr_samplers; 394 395 ctx->pipe->bind_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers); 396 } 397} 398 399/* 400 * If the function encouters any errors it will return the 401 * last one. Done to always try to set as many samplers 402 * as possible. 403 */ 404enum pipe_error cso_set_samplers( struct cso_context *ctx, 405 unsigned nr, 406 const struct pipe_sampler_state **templates ) 407{ 408 unsigned i; 409 enum pipe_error temp, error = PIPE_OK; 410 411 /* TODO: fastpath 412 */ 413 414 for (i = 0; i < nr; i++) { 415 temp = cso_single_sampler( ctx, i, templates[i] ); 416 if (temp != PIPE_OK) 417 error = temp; 418 } 419 420 for ( ; i < ctx->nr_samplers; i++) { 421 temp = cso_single_sampler( ctx, i, NULL ); 422 if (temp != PIPE_OK) 423 error = temp; 424 } 425 426 cso_single_sampler_done( ctx ); 427 428 return error; 429} 430 431void cso_save_samplers(struct cso_context *ctx) 432{ 433 ctx->nr_samplers_saved = ctx->nr_samplers; 434 memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers)); 435} 436 437void cso_restore_samplers(struct cso_context *ctx) 438{ 439 ctx->nr_samplers = ctx->nr_samplers_saved; 440 memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers)); 441 cso_single_sampler_done( ctx ); 442} 443 444 445enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, 446 uint count, 447 struct pipe_texture **textures ) 448{ 449 uint i; 450 451 ctx->nr_textures = count; 452 453 for (i = 0; i < count; i++) 454 pipe_texture_reference(&ctx->textures[i], textures[i]); 455 for ( ; i < PIPE_MAX_SAMPLERS; i++) 456 pipe_texture_reference(&ctx->textures[i], NULL); 457 458 ctx->pipe->set_sampler_textures(ctx->pipe, count, textures); 459 460 return PIPE_OK; 461} 462 463void cso_save_sampler_textures( struct cso_context *ctx ) 464{ 465 uint i; 466 467 ctx->nr_textures_saved = ctx->nr_textures; 468 for (i = 0; i < ctx->nr_textures; i++) { 469 assert(!ctx->textures_saved[i]); 470 pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]); 471 } 472} 473 474void cso_restore_sampler_textures( struct cso_context *ctx ) 475{ 476 uint i; 477 478 ctx->nr_textures = ctx->nr_textures_saved; 479 480 for (i = 0; i < ctx->nr_textures; i++) { 481 pipe_texture_reference(&ctx->textures[i], NULL); 482 ctx->textures[i] = ctx->textures_saved[i]; 483 ctx->textures_saved[i] = NULL; 484 } 485 for ( ; i < PIPE_MAX_SAMPLERS; i++) 486 pipe_texture_reference(&ctx->textures[i], NULL); 487 488 ctx->pipe->set_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures); 489 490 ctx->nr_textures_saved = 0; 491} 492 493 494 495enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, 496 const struct pipe_depth_stencil_alpha_state *templ) 497{ 498 unsigned hash_key = cso_construct_key((void*)templ, 499 sizeof(struct pipe_depth_stencil_alpha_state)); 500 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 501 hash_key, 502 CSO_DEPTH_STENCIL_ALPHA, 503 (void*)templ); 504 void *handle; 505 506 if (cso_hash_iter_is_null(iter)) { 507 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha)); 508 if (!cso) 509 return PIPE_ERROR_OUT_OF_MEMORY; 510 511 cso->state = *templ; 512 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state); 513 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state; 514 cso->context = ctx->pipe; 515 516 iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso); 517 if (cso_hash_iter_is_null(iter)) { 518 FREE(cso); 519 return PIPE_ERROR_OUT_OF_MEMORY; 520 } 521 522 handle = cso->data; 523 } 524 else { 525 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data; 526 } 527 528 if (ctx->depth_stencil != handle) { 529 ctx->depth_stencil = handle; 530 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle); 531 } 532 return PIPE_OK; 533} 534 535void cso_save_depth_stencil_alpha(struct cso_context *ctx) 536{ 537 assert(!ctx->depth_stencil_saved); 538 ctx->depth_stencil_saved = ctx->depth_stencil; 539} 540 541void cso_restore_depth_stencil_alpha(struct cso_context *ctx) 542{ 543 if (ctx->depth_stencil != ctx->depth_stencil_saved) { 544 ctx->depth_stencil = ctx->depth_stencil_saved; 545 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved); 546 } 547 ctx->depth_stencil_saved = NULL; 548} 549 550 551 552enum pipe_error cso_set_rasterizer(struct cso_context *ctx, 553 const struct pipe_rasterizer_state *templ) 554{ 555 unsigned hash_key = cso_construct_key((void*)templ, 556 sizeof(struct pipe_rasterizer_state)); 557 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 558 hash_key, CSO_RASTERIZER, 559 (void*)templ); 560 void *handle = NULL; 561 562 if (cso_hash_iter_is_null(iter)) { 563 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer)); 564 if (!cso) 565 return PIPE_ERROR_OUT_OF_MEMORY; 566 567 cso->state = *templ; 568 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state); 569 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state; 570 cso->context = ctx->pipe; 571 572 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso); 573 if (cso_hash_iter_is_null(iter)) { 574 FREE(cso); 575 return PIPE_ERROR_OUT_OF_MEMORY; 576 } 577 578 handle = cso->data; 579 } 580 else { 581 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data; 582 } 583 584 if (ctx->rasterizer != handle) { 585 ctx->rasterizer = handle; 586 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle); 587 } 588 return PIPE_OK; 589} 590 591void cso_save_rasterizer(struct cso_context *ctx) 592{ 593 assert(!ctx->rasterizer_saved); 594 ctx->rasterizer_saved = ctx->rasterizer; 595} 596 597void cso_restore_rasterizer(struct cso_context *ctx) 598{ 599 if (ctx->rasterizer != ctx->rasterizer_saved) { 600 ctx->rasterizer = ctx->rasterizer_saved; 601 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved); 602 } 603 ctx->rasterizer_saved = NULL; 604} 605 606 607 608enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx, 609 void *handle ) 610{ 611 if (ctx->fragment_shader != handle) { 612 ctx->fragment_shader = handle; 613 ctx->pipe->bind_fs_state(ctx->pipe, handle); 614 } 615 return PIPE_OK; 616} 617 618void cso_delete_fragment_shader(struct cso_context *ctx, void *handle ) 619{ 620 if (handle == ctx->fragment_shader) { 621 /* unbind before deleting */ 622 ctx->pipe->bind_fs_state(ctx->pipe, NULL); 623 ctx->fragment_shader = NULL; 624 } 625 ctx->pipe->delete_fs_state(ctx->pipe, handle); 626} 627 628/* Not really working: 629 */ 630#if 0 631enum pipe_error cso_set_fragment_shader(struct cso_context *ctx, 632 const struct pipe_shader_state *templ) 633{ 634 const struct tgsi_token *tokens = templ->tokens; 635 unsigned num_tokens = tgsi_num_tokens(tokens); 636 size_t tokens_size = num_tokens*sizeof(struct tgsi_token); 637 unsigned hash_key = cso_construct_key((void*)tokens, tokens_size); 638 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 639 hash_key, 640 CSO_FRAGMENT_SHADER, 641 (void*)tokens); 642 void *handle = NULL; 643 644 if (cso_hash_iter_is_null(iter)) { 645 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size); 646 struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso)); 647 648 if (!cso) 649 return PIPE_ERROR_OUT_OF_MEMORY; 650 651 memcpy(cso_tokens, tokens, tokens_size); 652 cso->state.tokens = cso_tokens; 653 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state); 654 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state; 655 cso->context = ctx->pipe; 656 657 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso); 658 if (cso_hash_iter_is_null(iter)) { 659 FREE(cso); 660 return PIPE_ERROR_OUT_OF_MEMORY; 661 } 662 663 handle = cso->data; 664 } 665 else { 666 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data; 667 } 668 669 return cso_set_fragment_shader_handle( ctx, handle ); 670} 671#endif 672 673void cso_save_fragment_shader(struct cso_context *ctx) 674{ 675 assert(!ctx->fragment_shader_saved); 676 ctx->fragment_shader_saved = ctx->fragment_shader; 677} 678 679void cso_restore_fragment_shader(struct cso_context *ctx) 680{ 681 if (ctx->fragment_shader_saved != ctx->fragment_shader) { 682 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved); 683 ctx->fragment_shader = ctx->fragment_shader_saved; 684 } 685 ctx->fragment_shader_saved = NULL; 686} 687 688 689enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx, 690 void *handle ) 691{ 692 if (ctx->vertex_shader != handle) { 693 ctx->vertex_shader = handle; 694 ctx->pipe->bind_vs_state(ctx->pipe, handle); 695 } 696 return PIPE_OK; 697} 698 699void cso_delete_vertex_shader(struct cso_context *ctx, void *handle ) 700{ 701 if (handle == ctx->vertex_shader) { 702 /* unbind before deleting */ 703 ctx->pipe->bind_vs_state(ctx->pipe, NULL); 704 ctx->vertex_shader = NULL; 705 } 706 ctx->pipe->delete_vs_state(ctx->pipe, handle); 707} 708 709 710/* Not really working: 711 */ 712#if 0 713enum pipe_error cso_set_vertex_shader(struct cso_context *ctx, 714 const struct pipe_shader_state *templ) 715{ 716 unsigned hash_key = cso_construct_key((void*)templ, 717 sizeof(struct pipe_shader_state)); 718 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 719 hash_key, CSO_VERTEX_SHADER, 720 (void*)templ); 721 void *handle = NULL; 722 723 if (cso_hash_iter_is_null(iter)) { 724 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader)); 725 726 if (!cso) 727 return PIPE_ERROR_OUT_OF_MEMORY; 728 729 cso->state = *templ; 730 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state); 731 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state; 732 cso->context = ctx->pipe; 733 734 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso); 735 if (cso_hash_iter_is_null(iter)) { 736 FREE(cso); 737 return PIPE_ERROR_OUT_OF_MEMORY; 738 } 739 740 handle = cso->data; 741 } 742 else { 743 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data; 744 } 745 746 return cso_set_vertex_shader_handle( ctx, handle ); 747} 748#endif 749 750 751 752void cso_save_vertex_shader(struct cso_context *ctx) 753{ 754 assert(!ctx->vertex_shader_saved); 755 ctx->vertex_shader_saved = ctx->vertex_shader; 756} 757 758void cso_restore_vertex_shader(struct cso_context *ctx) 759{ 760 if (ctx->vertex_shader_saved != ctx->vertex_shader) { 761 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved); 762 ctx->vertex_shader = ctx->vertex_shader_saved; 763 } 764 ctx->vertex_shader_saved = NULL; 765} 766 767 768 769enum pipe_error cso_set_framebuffer(struct cso_context *ctx, 770 const struct pipe_framebuffer_state *fb) 771{ 772 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { 773 ctx->fb = *fb; 774 ctx->pipe->set_framebuffer_state(ctx->pipe, fb); 775 } 776 return PIPE_OK; 777} 778 779void cso_save_framebuffer(struct cso_context *ctx) 780{ 781 ctx->fb_saved = ctx->fb; 782} 783 784void cso_restore_framebuffer(struct cso_context *ctx) 785{ 786 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { 787 ctx->fb = ctx->fb_saved; 788 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); 789 } 790} 791 792 793enum pipe_error cso_set_viewport(struct cso_context *ctx, 794 const struct pipe_viewport_state *vp) 795{ 796 if (memcmp(&ctx->vp, vp, sizeof(*vp))) { 797 ctx->vp = *vp; 798 ctx->pipe->set_viewport_state(ctx->pipe, vp); 799 } 800 return PIPE_OK; 801} 802 803void cso_save_viewport(struct cso_context *ctx) 804{ 805 ctx->vp_saved = ctx->vp; 806} 807 808 809void cso_restore_viewport(struct cso_context *ctx) 810{ 811 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) { 812 ctx->vp = ctx->vp_saved; 813 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp); 814 } 815} 816 817 818 819 820enum pipe_error cso_set_blend_color(struct cso_context *ctx, 821 const struct pipe_blend_color *bc) 822{ 823 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) { 824 ctx->blend_color = *bc; 825 ctx->pipe->set_blend_color(ctx->pipe, bc); 826 } 827 return PIPE_OK; 828} 829