cso_context.c revision 5f30e0b2316c5d0a50f1b331e7cdb4c46882e918
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 *fragment_samplers[PIPE_MAX_SAMPLERS]; 56 unsigned nr_fragment_samplers; 57 58 void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; 59 unsigned nr_vertex_samplers; 60 } hw; 61 62 void *fragment_samplers[PIPE_MAX_SAMPLERS]; 63 unsigned nr_fragment_samplers; 64 65 void *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; 66 unsigned nr_vertex_samplers; 67 68 unsigned nr_fragment_samplers_saved; 69 void *fragment_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->fragment_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->fragment_samplers[i - 1] != NULL) 486 break; 487 } 488 489 ctx->nr_fragment_samplers = i; 490 491 if (ctx->hw.nr_fragment_samplers != ctx->nr_fragment_samplers || 492 memcmp(ctx->hw.fragment_samplers, 493 ctx->fragment_samplers, 494 ctx->nr_fragment_samplers * sizeof(void *)) != 0) 495 { 496 memcpy(ctx->hw.fragment_samplers, ctx->fragment_samplers, 497 ctx->nr_fragment_samplers * sizeof(void *)); 498 ctx->hw.nr_fragment_samplers = ctx->nr_fragment_samplers; 499 500 ctx->pipe->bind_fragment_sampler_states(ctx->pipe, 501 ctx->nr_fragment_samplers, 502 ctx->fragment_samplers); 503 } 504} 505 506void 507cso_single_vertex_sampler_done(struct cso_context *ctx) 508{ 509 unsigned i; 510 511 /* find highest non-null sampler */ 512 for (i = PIPE_MAX_VERTEX_SAMPLERS; i > 0; i--) { 513 if (ctx->vertex_samplers[i - 1] != NULL) 514 break; 515 } 516 517 ctx->nr_vertex_samplers = i; 518 519 if (ctx->hw.nr_vertex_samplers != ctx->nr_vertex_samplers || 520 memcmp(ctx->hw.vertex_samplers, 521 ctx->vertex_samplers, 522 ctx->nr_vertex_samplers * sizeof(void *)) != 0) 523 { 524 memcpy(ctx->hw.vertex_samplers, 525 ctx->vertex_samplers, 526 ctx->nr_vertex_samplers * sizeof(void *)); 527 ctx->hw.nr_vertex_samplers = ctx->nr_vertex_samplers; 528 529 ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 530 ctx->nr_vertex_samplers, 531 ctx->vertex_samplers); 532 } 533} 534 535/* 536 * If the function encouters any errors it will return the 537 * last one. Done to always try to set as many samplers 538 * as possible. 539 */ 540enum pipe_error cso_set_samplers( struct cso_context *ctx, 541 unsigned nr, 542 const struct pipe_sampler_state **templates ) 543{ 544 unsigned i; 545 enum pipe_error temp, error = PIPE_OK; 546 547 /* TODO: fastpath 548 */ 549 550 for (i = 0; i < nr; i++) { 551 temp = cso_single_sampler( ctx, i, templates[i] ); 552 if (temp != PIPE_OK) 553 error = temp; 554 } 555 556 for ( ; i < ctx->nr_fragment_samplers; i++) { 557 temp = cso_single_sampler( ctx, i, NULL ); 558 if (temp != PIPE_OK) 559 error = temp; 560 } 561 562 cso_single_sampler_done( ctx ); 563 564 return error; 565} 566 567void cso_save_samplers(struct cso_context *ctx) 568{ 569 ctx->nr_fragment_samplers_saved = ctx->nr_fragment_samplers; 570 memcpy(ctx->fragment_samplers_saved, ctx->fragment_samplers, 571 sizeof(ctx->fragment_samplers)); 572} 573 574void cso_restore_samplers(struct cso_context *ctx) 575{ 576 ctx->nr_fragment_samplers = ctx->nr_fragment_samplers_saved; 577 memcpy(ctx->fragment_samplers, ctx->fragment_samplers_saved, 578 sizeof(ctx->fragment_samplers)); 579 cso_single_sampler_done( ctx ); 580} 581 582/* 583 * If the function encouters any errors it will return the 584 * last one. Done to always try to set as many samplers 585 * as possible. 586 */ 587enum pipe_error cso_set_vertex_samplers(struct cso_context *ctx, 588 unsigned nr, 589 const struct pipe_sampler_state **templates) 590{ 591 unsigned i; 592 enum pipe_error temp, error = PIPE_OK; 593 594 /* TODO: fastpath 595 */ 596 597 for (i = 0; i < nr; i++) { 598 temp = cso_single_vertex_sampler( ctx, i, templates[i] ); 599 if (temp != PIPE_OK) 600 error = temp; 601 } 602 603 for ( ; i < ctx->nr_vertex_samplers; i++) { 604 temp = cso_single_vertex_sampler( ctx, i, NULL ); 605 if (temp != PIPE_OK) 606 error = temp; 607 } 608 609 cso_single_vertex_sampler_done( ctx ); 610 611 return error; 612} 613 614void 615cso_save_vertex_samplers(struct cso_context *ctx) 616{ 617 ctx->nr_vertex_samplers_saved = ctx->nr_vertex_samplers; 618 memcpy(ctx->vertex_samplers_saved, ctx->vertex_samplers, sizeof(ctx->vertex_samplers)); 619} 620 621void 622cso_restore_vertex_samplers(struct cso_context *ctx) 623{ 624 ctx->nr_vertex_samplers = ctx->nr_vertex_samplers_saved; 625 memcpy(ctx->vertex_samplers, ctx->vertex_samplers_saved, sizeof(ctx->vertex_samplers)); 626 cso_single_vertex_sampler_done(ctx); 627} 628 629 630enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, 631 const struct pipe_depth_stencil_alpha_state *templ) 632{ 633 unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state); 634 unsigned hash_key = cso_construct_key((void*)templ, key_size); 635 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 636 hash_key, 637 CSO_DEPTH_STENCIL_ALPHA, 638 (void*)templ, key_size); 639 void *handle; 640 641 if (cso_hash_iter_is_null(iter)) { 642 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha)); 643 if (!cso) 644 return PIPE_ERROR_OUT_OF_MEMORY; 645 646 memcpy(&cso->state, templ, sizeof(*templ)); 647 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state); 648 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state; 649 cso->context = ctx->pipe; 650 651 iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso); 652 if (cso_hash_iter_is_null(iter)) { 653 FREE(cso); 654 return PIPE_ERROR_OUT_OF_MEMORY; 655 } 656 657 handle = cso->data; 658 } 659 else { 660 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data; 661 } 662 663 if (ctx->depth_stencil != handle) { 664 ctx->depth_stencil = handle; 665 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle); 666 } 667 return PIPE_OK; 668} 669 670void cso_save_depth_stencil_alpha(struct cso_context *ctx) 671{ 672 assert(!ctx->depth_stencil_saved); 673 ctx->depth_stencil_saved = ctx->depth_stencil; 674} 675 676void cso_restore_depth_stencil_alpha(struct cso_context *ctx) 677{ 678 if (ctx->depth_stencil != ctx->depth_stencil_saved) { 679 ctx->depth_stencil = ctx->depth_stencil_saved; 680 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved); 681 } 682 ctx->depth_stencil_saved = NULL; 683} 684 685 686 687enum pipe_error cso_set_rasterizer(struct cso_context *ctx, 688 const struct pipe_rasterizer_state *templ) 689{ 690 unsigned key_size = sizeof(struct pipe_rasterizer_state); 691 unsigned hash_key = cso_construct_key((void*)templ, key_size); 692 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 693 hash_key, CSO_RASTERIZER, 694 (void*)templ, key_size); 695 void *handle = NULL; 696 697 if (cso_hash_iter_is_null(iter)) { 698 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer)); 699 if (!cso) 700 return PIPE_ERROR_OUT_OF_MEMORY; 701 702 memcpy(&cso->state, templ, sizeof(*templ)); 703 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state); 704 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state; 705 cso->context = ctx->pipe; 706 707 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso); 708 if (cso_hash_iter_is_null(iter)) { 709 FREE(cso); 710 return PIPE_ERROR_OUT_OF_MEMORY; 711 } 712 713 handle = cso->data; 714 } 715 else { 716 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data; 717 } 718 719 if (ctx->rasterizer != handle) { 720 ctx->rasterizer = handle; 721 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle); 722 } 723 return PIPE_OK; 724} 725 726void cso_save_rasterizer(struct cso_context *ctx) 727{ 728 assert(!ctx->rasterizer_saved); 729 ctx->rasterizer_saved = ctx->rasterizer; 730} 731 732void cso_restore_rasterizer(struct cso_context *ctx) 733{ 734 if (ctx->rasterizer != ctx->rasterizer_saved) { 735 ctx->rasterizer = ctx->rasterizer_saved; 736 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved); 737 } 738 ctx->rasterizer_saved = NULL; 739} 740 741 742 743enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx, 744 void *handle ) 745{ 746 if (ctx->fragment_shader != handle) { 747 ctx->fragment_shader = handle; 748 ctx->pipe->bind_fs_state(ctx->pipe, handle); 749 } 750 return PIPE_OK; 751} 752 753void cso_delete_fragment_shader(struct cso_context *ctx, void *handle ) 754{ 755 if (handle == ctx->fragment_shader) { 756 /* unbind before deleting */ 757 ctx->pipe->bind_fs_state(ctx->pipe, NULL); 758 ctx->fragment_shader = NULL; 759 } 760 ctx->pipe->delete_fs_state(ctx->pipe, handle); 761} 762 763/* Not really working: 764 */ 765#if 0 766enum pipe_error cso_set_fragment_shader(struct cso_context *ctx, 767 const struct pipe_shader_state *templ) 768{ 769 const struct tgsi_token *tokens = templ->tokens; 770 unsigned num_tokens = tgsi_num_tokens(tokens); 771 size_t tokens_size = num_tokens*sizeof(struct tgsi_token); 772 unsigned hash_key = cso_construct_key((void*)tokens, tokens_size); 773 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 774 hash_key, 775 CSO_FRAGMENT_SHADER, 776 (void*)tokens, 777 sizeof(*templ)); /* XXX correct? tokens_size? */ 778 void *handle = NULL; 779 780 if (cso_hash_iter_is_null(iter)) { 781 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size); 782 struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso)); 783 784 if (!cso) 785 return PIPE_ERROR_OUT_OF_MEMORY; 786 787 memcpy(cso_tokens, tokens, tokens_size); 788 cso->state.tokens = cso_tokens; 789 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state); 790 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state; 791 cso->context = ctx->pipe; 792 793 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso); 794 if (cso_hash_iter_is_null(iter)) { 795 FREE(cso); 796 return PIPE_ERROR_OUT_OF_MEMORY; 797 } 798 799 handle = cso->data; 800 } 801 else { 802 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data; 803 } 804 805 return cso_set_fragment_shader_handle( ctx, handle ); 806} 807#endif 808 809void cso_save_fragment_shader(struct cso_context *ctx) 810{ 811 assert(!ctx->fragment_shader_saved); 812 ctx->fragment_shader_saved = ctx->fragment_shader; 813} 814 815void cso_restore_fragment_shader(struct cso_context *ctx) 816{ 817 if (ctx->fragment_shader_saved != ctx->fragment_shader) { 818 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved); 819 ctx->fragment_shader = ctx->fragment_shader_saved; 820 } 821 ctx->fragment_shader_saved = NULL; 822} 823 824 825enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx, 826 void *handle ) 827{ 828 if (ctx->vertex_shader != handle) { 829 ctx->vertex_shader = handle; 830 ctx->pipe->bind_vs_state(ctx->pipe, handle); 831 } 832 return PIPE_OK; 833} 834 835void cso_delete_vertex_shader(struct cso_context *ctx, void *handle ) 836{ 837 if (handle == ctx->vertex_shader) { 838 /* unbind before deleting */ 839 ctx->pipe->bind_vs_state(ctx->pipe, NULL); 840 ctx->vertex_shader = NULL; 841 } 842 ctx->pipe->delete_vs_state(ctx->pipe, handle); 843} 844 845 846/* Not really working: 847 */ 848#if 0 849enum pipe_error cso_set_vertex_shader(struct cso_context *ctx, 850 const struct pipe_shader_state *templ) 851{ 852 unsigned hash_key = cso_construct_key((void*)templ, 853 sizeof(struct pipe_shader_state)); 854 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 855 hash_key, CSO_VERTEX_SHADER, 856 (void*)templ, 857 sizeof(*templ)); 858 void *handle = NULL; 859 860 if (cso_hash_iter_is_null(iter)) { 861 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader)); 862 863 if (!cso) 864 return PIPE_ERROR_OUT_OF_MEMORY; 865 866 memcpy(cso->state, templ, sizeof(*templ)); 867 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state); 868 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state; 869 cso->context = ctx->pipe; 870 871 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso); 872 if (cso_hash_iter_is_null(iter)) { 873 FREE(cso); 874 return PIPE_ERROR_OUT_OF_MEMORY; 875 } 876 877 handle = cso->data; 878 } 879 else { 880 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data; 881 } 882 883 return cso_set_vertex_shader_handle( ctx, handle ); 884} 885#endif 886 887 888 889void cso_save_vertex_shader(struct cso_context *ctx) 890{ 891 assert(!ctx->vertex_shader_saved); 892 ctx->vertex_shader_saved = ctx->vertex_shader; 893} 894 895void cso_restore_vertex_shader(struct cso_context *ctx) 896{ 897 if (ctx->vertex_shader_saved != ctx->vertex_shader) { 898 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved); 899 ctx->vertex_shader = ctx->vertex_shader_saved; 900 } 901 ctx->vertex_shader_saved = NULL; 902} 903 904 905enum pipe_error cso_set_framebuffer(struct cso_context *ctx, 906 const struct pipe_framebuffer_state *fb) 907{ 908 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { 909 util_copy_framebuffer_state(&ctx->fb, fb); 910 ctx->pipe->set_framebuffer_state(ctx->pipe, fb); 911 } 912 return PIPE_OK; 913} 914 915void cso_save_framebuffer(struct cso_context *ctx) 916{ 917 util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb); 918} 919 920void cso_restore_framebuffer(struct cso_context *ctx) 921{ 922 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { 923 util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); 924 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); 925 util_unreference_framebuffer_state(&ctx->fb_saved); 926 } 927} 928 929 930enum pipe_error cso_set_viewport(struct cso_context *ctx, 931 const struct pipe_viewport_state *vp) 932{ 933 if (memcmp(&ctx->vp, vp, sizeof(*vp))) { 934 ctx->vp = *vp; 935 ctx->pipe->set_viewport_state(ctx->pipe, vp); 936 } 937 return PIPE_OK; 938} 939 940void cso_save_viewport(struct cso_context *ctx) 941{ 942 ctx->vp_saved = ctx->vp; 943} 944 945 946void cso_restore_viewport(struct cso_context *ctx) 947{ 948 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) { 949 ctx->vp = ctx->vp_saved; 950 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp); 951 } 952} 953 954 955enum pipe_error cso_set_blend_color(struct cso_context *ctx, 956 const struct pipe_blend_color *bc) 957{ 958 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) { 959 ctx->blend_color = *bc; 960 ctx->pipe->set_blend_color(ctx->pipe, bc); 961 } 962 return PIPE_OK; 963} 964 965enum pipe_error cso_set_sample_mask(struct cso_context *ctx, 966 unsigned sample_mask) 967{ 968 if (ctx->sample_mask != sample_mask) { 969 ctx->sample_mask = sample_mask; 970 ctx->pipe->set_sample_mask(ctx->pipe, sample_mask); 971 } 972 return PIPE_OK; 973} 974 975enum pipe_error cso_set_stencil_ref(struct cso_context *ctx, 976 const struct pipe_stencil_ref *sr) 977{ 978 if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) { 979 ctx->stencil_ref = *sr; 980 ctx->pipe->set_stencil_ref(ctx->pipe, sr); 981 } 982 return PIPE_OK; 983} 984 985void cso_save_stencil_ref(struct cso_context *ctx) 986{ 987 ctx->stencil_ref_saved = ctx->stencil_ref; 988} 989 990 991void cso_restore_stencil_ref(struct cso_context *ctx) 992{ 993 if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved, sizeof(ctx->stencil_ref))) { 994 ctx->stencil_ref = ctx->stencil_ref_saved; 995 ctx->pipe->set_stencil_ref(ctx->pipe, &ctx->stencil_ref); 996 } 997} 998 999enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx, 1000 void *handle) 1001{ 1002 if (ctx->geometry_shader != handle) { 1003 ctx->geometry_shader = handle; 1004 ctx->pipe->bind_gs_state(ctx->pipe, handle); 1005 } 1006 return PIPE_OK; 1007} 1008 1009void cso_delete_geometry_shader(struct cso_context *ctx, void *handle) 1010{ 1011 if (handle == ctx->geometry_shader) { 1012 /* unbind before deleting */ 1013 ctx->pipe->bind_gs_state(ctx->pipe, NULL); 1014 ctx->geometry_shader = NULL; 1015 } 1016 ctx->pipe->delete_gs_state(ctx->pipe, handle); 1017} 1018 1019void cso_save_geometry_shader(struct cso_context *ctx) 1020{ 1021 assert(!ctx->geometry_shader_saved); 1022 ctx->geometry_shader_saved = ctx->geometry_shader; 1023} 1024 1025void cso_restore_geometry_shader(struct cso_context *ctx) 1026{ 1027 if (ctx->geometry_shader_saved != ctx->geometry_shader) { 1028 ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved); 1029 ctx->geometry_shader = ctx->geometry_shader_saved; 1030 } 1031 ctx->geometry_shader_saved = NULL; 1032} 1033 1034/* clip state */ 1035 1036static INLINE void 1037clip_state_cpy(struct pipe_clip_state *dst, 1038 const struct pipe_clip_state *src) 1039{ 1040 dst->depth_clamp = src->depth_clamp; 1041 dst->nr = src->nr; 1042 if (src->nr) { 1043 memcpy(dst->ucp, src->ucp, src->nr * sizeof(src->ucp[0])); 1044 } 1045} 1046 1047static INLINE int 1048clip_state_cmp(const struct pipe_clip_state *a, 1049 const struct pipe_clip_state *b) 1050{ 1051 if (a->depth_clamp != b->depth_clamp) { 1052 return 1; 1053 } 1054 if (a->nr != b->nr) { 1055 return 1; 1056 } 1057 if (a->nr) { 1058 return memcmp(a->ucp, b->ucp, a->nr * sizeof(a->ucp[0])); 1059 } 1060 return 0; 1061} 1062 1063void 1064cso_set_clip(struct cso_context *ctx, 1065 const struct pipe_clip_state *clip) 1066{ 1067 if (clip_state_cmp(&ctx->clip, clip)) { 1068 clip_state_cpy(&ctx->clip, clip); 1069 ctx->pipe->set_clip_state(ctx->pipe, clip); 1070 } 1071} 1072 1073void 1074cso_save_clip(struct cso_context *ctx) 1075{ 1076 clip_state_cpy(&ctx->clip_saved, &ctx->clip); 1077} 1078 1079void 1080cso_restore_clip(struct cso_context *ctx) 1081{ 1082 if (clip_state_cmp(&ctx->clip, &ctx->clip_saved)) { 1083 clip_state_cpy(&ctx->clip, &ctx->clip_saved); 1084 ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved); 1085 } 1086} 1087 1088enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, 1089 unsigned count, 1090 const struct pipe_vertex_element *states) 1091{ 1092 unsigned key_size, hash_key; 1093 struct cso_hash_iter iter; 1094 void *handle; 1095 struct cso_velems_state velems_state; 1096 1097 /* need to include the count into the stored state data too. 1098 Otherwise first few count pipe_vertex_elements could be identical even if count 1099 is different, and there's no guarantee the hash would be different in that 1100 case neither */ 1101 key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned); 1102 velems_state.count = count; 1103 memcpy(velems_state.velems, states, sizeof(struct pipe_vertex_element) * count); 1104 hash_key = cso_construct_key((void*)&velems_state, key_size); 1105 iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS, (void*)&velems_state, key_size); 1106 1107 if (cso_hash_iter_is_null(iter)) { 1108 struct cso_velements *cso = MALLOC(sizeof(struct cso_velements)); 1109 if (!cso) 1110 return PIPE_ERROR_OUT_OF_MEMORY; 1111 1112 memcpy(&cso->state, &velems_state, key_size); 1113 cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count, &cso->state.velems[0]); 1114 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vertex_elements_state; 1115 cso->context = ctx->pipe; 1116 1117 iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso); 1118 if (cso_hash_iter_is_null(iter)) { 1119 FREE(cso); 1120 return PIPE_ERROR_OUT_OF_MEMORY; 1121 } 1122 1123 handle = cso->data; 1124 } 1125 else { 1126 handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; 1127 } 1128 1129 if (ctx->velements != handle) { 1130 ctx->velements = handle; 1131 ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle); 1132 } 1133 return PIPE_OK; 1134} 1135 1136void cso_save_vertex_elements(struct cso_context *ctx) 1137{ 1138 assert(!ctx->velements_saved); 1139 ctx->velements_saved = ctx->velements; 1140} 1141 1142void cso_restore_vertex_elements(struct cso_context *ctx) 1143{ 1144 if (ctx->velements != ctx->velements_saved) { 1145 ctx->velements = ctx->velements_saved; 1146 ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved); 1147 } 1148 ctx->velements_saved = NULL; 1149} 1150 1151/* fragment sampler view state */ 1152 1153void 1154cso_set_fragment_sampler_views(struct cso_context *cso, 1155 uint count, 1156 struct pipe_sampler_view **views) 1157{ 1158 uint i; 1159 1160 for (i = 0; i < count; i++) { 1161 pipe_sampler_view_reference(&cso->fragment_sampler_views[i], views[i]); 1162 } 1163 for (; i < cso->nr_fragment_sampler_views; i++) { 1164 pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); 1165 } 1166 1167 cso->pipe->set_fragment_sampler_views(cso->pipe, 1168 MAX2(count, cso->nr_fragment_sampler_views), 1169 cso->fragment_sampler_views); 1170 1171 cso->nr_fragment_sampler_views = count; 1172} 1173 1174void 1175cso_save_fragment_sampler_views(struct cso_context *cso) 1176{ 1177 uint i; 1178 1179 cso->nr_fragment_sampler_views_saved = cso->nr_fragment_sampler_views; 1180 1181 for (i = 0; i < cso->nr_fragment_sampler_views; i++) { 1182 assert(!cso->fragment_sampler_views_saved[i]); 1183 1184 pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], 1185 cso->fragment_sampler_views[i]); 1186 } 1187} 1188 1189void 1190cso_restore_fragment_sampler_views(struct cso_context *cso) 1191{ 1192 uint i; 1193 1194 for (i = 0; i < cso->nr_fragment_sampler_views_saved; i++) { 1195 pipe_sampler_view_reference(&cso->fragment_sampler_views[i], cso->fragment_sampler_views_saved[i]); 1196 pipe_sampler_view_reference(&cso->fragment_sampler_views_saved[i], NULL); 1197 } 1198 for (; i < cso->nr_fragment_sampler_views; i++) { 1199 pipe_sampler_view_reference(&cso->fragment_sampler_views[i], NULL); 1200 } 1201 1202 cso->pipe->set_fragment_sampler_views(cso->pipe, 1203 MAX2(cso->nr_fragment_sampler_views, cso->nr_fragment_sampler_views_saved), 1204 cso->fragment_sampler_views); 1205 1206 cso->nr_fragment_sampler_views = cso->nr_fragment_sampler_views_saved; 1207 cso->nr_fragment_sampler_views_saved = 0; 1208} 1209 1210 1211/* vertex sampler view state */ 1212 1213void 1214cso_set_vertex_sampler_views(struct cso_context *cso, 1215 uint count, 1216 struct pipe_sampler_view **views) 1217{ 1218 uint i; 1219 1220 for (i = 0; i < count; i++) { 1221 pipe_sampler_view_reference(&cso->vertex_sampler_views[i], views[i]); 1222 } 1223 for (; i < cso->nr_vertex_sampler_views; i++) { 1224 pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); 1225 } 1226 1227 cso->pipe->set_vertex_sampler_views(cso->pipe, 1228 MAX2(count, cso->nr_vertex_sampler_views), 1229 cso->vertex_sampler_views); 1230 1231 cso->nr_vertex_sampler_views = count; 1232} 1233 1234void 1235cso_save_vertex_sampler_views(struct cso_context *cso) 1236{ 1237 uint i; 1238 1239 cso->nr_vertex_sampler_views_saved = cso->nr_vertex_sampler_views; 1240 1241 for (i = 0; i < cso->nr_vertex_sampler_views; i++) { 1242 assert(!cso->vertex_sampler_views_saved[i]); 1243 1244 pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], 1245 cso->vertex_sampler_views[i]); 1246 } 1247} 1248 1249void 1250cso_restore_vertex_sampler_views(struct cso_context *cso) 1251{ 1252 uint i; 1253 1254 for (i = 0; i < cso->nr_vertex_sampler_views_saved; i++) { 1255 pipe_sampler_view_reference(&cso->vertex_sampler_views[i], cso->vertex_sampler_views_saved[i]); 1256 pipe_sampler_view_reference(&cso->vertex_sampler_views_saved[i], NULL); 1257 } 1258 for (; i < cso->nr_vertex_sampler_views; i++) { 1259 pipe_sampler_view_reference(&cso->vertex_sampler_views[i], NULL); 1260 } 1261 1262 cso->pipe->set_vertex_sampler_views(cso->pipe, 1263 MAX2(cso->nr_vertex_sampler_views, cso->nr_vertex_sampler_views_saved), 1264 cso->vertex_sampler_views); 1265 1266 cso->nr_vertex_sampler_views = cso->nr_vertex_sampler_views_saved; 1267 cso->nr_vertex_sampler_views_saved = 0; 1268} 1269