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