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