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