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