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