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