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