00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00038 #include "pipe/p_state.h"
00039 #include "util/u_memory.h"
00040 #include "pipe/p_inlines.h"
00041 #include "tgsi/tgsi_parse.h"
00042
00043 #include "cso_cache/cso_context.h"
00044 #include "cso_cache/cso_cache.h"
00045 #include "cso_cache/cso_hash.h"
00046
00047 struct cso_context {
00048 struct pipe_context *pipe;
00049 struct cso_cache *cache;
00050
00051 struct {
00052 void *samplers[PIPE_MAX_SAMPLERS];
00053 unsigned nr_samplers;
00054 } hw;
00055
00056 void *samplers[PIPE_MAX_SAMPLERS];
00057 unsigned nr_samplers;
00058
00059 void *samplers_saved[PIPE_MAX_SAMPLERS];
00060 unsigned nr_samplers_saved;
00061
00062 struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
00063 uint nr_textures;
00064
00065 struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS];
00066 uint nr_textures_saved;
00067
00071 void *blend, *blend_saved;
00072 void *depth_stencil, *depth_stencil_saved;
00073 void *rasterizer, *rasterizer_saved;
00074 void *fragment_shader, *fragment_shader_saved;
00075 void *vertex_shader, *vertex_shader_saved;
00076
00077 struct pipe_framebuffer_state fb, fb_saved;
00078 struct pipe_viewport_state vp, vp_saved;
00079 struct pipe_blend_color blend_color;
00080 };
00081
00082
00083 static void
00084 free_framebuffer_state(struct pipe_framebuffer_state *fb);
00085
00086
00087 static boolean delete_blend_state(struct cso_context *ctx, void *state)
00088 {
00089 struct cso_blend *cso = (struct cso_blend *)state;
00090
00091 if (ctx->blend == cso->data)
00092 return FALSE;
00093
00094 if (cso->delete_state)
00095 cso->delete_state(cso->context, cso->data);
00096 FREE(state);
00097 return TRUE;
00098 }
00099
00100 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
00101 {
00102 struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
00103
00104 if (ctx->depth_stencil == cso->data)
00105 return FALSE;
00106
00107 if (cso->delete_state)
00108 cso->delete_state(cso->context, cso->data);
00109 FREE(state);
00110
00111 return TRUE;
00112 }
00113
00114 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
00115 {
00116 struct cso_sampler *cso = (struct cso_sampler *)state;
00117 if (cso->delete_state)
00118 cso->delete_state(cso->context, cso->data);
00119 FREE(state);
00120 return TRUE;
00121 }
00122
00123 static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
00124 {
00125 struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
00126
00127 if (ctx->rasterizer == cso->data)
00128 return FALSE;
00129 if (cso->delete_state)
00130 cso->delete_state(cso->context, cso->data);
00131 FREE(state);
00132 return TRUE;
00133 }
00134
00135 static boolean delete_fs_state(struct cso_context *ctx, void *state)
00136 {
00137 struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
00138 if (ctx->fragment_shader == cso->data)
00139 return FALSE;
00140 if (cso->delete_state)
00141 cso->delete_state(cso->context, cso->data);
00142 FREE(state);
00143 return TRUE;
00144 }
00145
00146 static boolean delete_vs_state(struct cso_context *ctx, void *state)
00147 {
00148 struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
00149 if (ctx->vertex_shader == cso->data)
00150 return TRUE;
00151 if (cso->delete_state)
00152 cso->delete_state(cso->context, cso->data);
00153 FREE(state);
00154 return FALSE;
00155 }
00156
00157
00158 static INLINE boolean delete_cso(struct cso_context *ctx,
00159 void *state, enum cso_cache_type type)
00160 {
00161 switch (type) {
00162 case CSO_BLEND:
00163 return delete_blend_state(ctx, state);
00164 break;
00165 case CSO_SAMPLER:
00166 return delete_sampler_state(ctx, state);
00167 break;
00168 case CSO_DEPTH_STENCIL_ALPHA:
00169 return delete_depth_stencil_state(ctx, state);
00170 break;
00171 case CSO_RASTERIZER:
00172 return delete_rasterizer_state(ctx, state);
00173 break;
00174 case CSO_FRAGMENT_SHADER:
00175 return delete_fs_state(ctx, state);
00176 break;
00177 case CSO_VERTEX_SHADER:
00178 return delete_vs_state(ctx, state);
00179 break;
00180 default:
00181 assert(0);
00182 FREE(state);
00183 }
00184 return FALSE;
00185 }
00186
00187 static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
00188 int max_size, void *user_data)
00189 {
00190 struct cso_context *ctx = (struct cso_context *)user_data;
00191
00192
00193 int hash_size = cso_hash_size(hash);
00194 int max_entries = (max_size > hash_size) ? max_size : hash_size;
00195 int to_remove = (max_size < max_entries) * max_entries/4;
00196 struct cso_hash_iter iter = cso_hash_first_node(hash);
00197 if (hash_size > max_size)
00198 to_remove += hash_size - max_size;
00199 while (to_remove) {
00200
00201
00202 void *cso = cso_hash_iter_data(iter);
00203 if (delete_cso(ctx, cso, type)) {
00204 iter = cso_hash_erase(hash, iter);
00205 --to_remove;
00206 } else
00207 iter = cso_hash_iter_next(iter);
00208 }
00209 }
00210
00211
00212 struct cso_context *cso_create_context( struct pipe_context *pipe )
00213 {
00214 struct cso_context *ctx = CALLOC_STRUCT(cso_context);
00215 if (ctx == NULL)
00216 goto out;
00217
00218 ctx->cache = cso_cache_create();
00219 if (ctx->cache == NULL)
00220 goto out;
00221 cso_cache_set_sanitize_callback(ctx->cache,
00222 sanitize_hash,
00223 ctx);
00224
00225 ctx->pipe = pipe;
00226
00227
00228 if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
00229
00230 return ctx;
00231
00232 out:
00233 cso_destroy_context( ctx );
00234 return NULL;
00235 }
00236
00237
00241 void cso_release_all( struct cso_context *ctx )
00242 {
00243 unsigned i;
00244
00245 if (ctx->pipe) {
00246 ctx->pipe->bind_blend_state( ctx->pipe, NULL );
00247 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
00248 ctx->pipe->bind_sampler_states( ctx->pipe, 0, NULL );
00249 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
00250 ctx->pipe->bind_fs_state( ctx->pipe, NULL );
00251 ctx->pipe->bind_vs_state( ctx->pipe, NULL );
00252 }
00253
00254 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
00255 pipe_texture_reference(&ctx->textures[i], NULL);
00256 pipe_texture_reference(&ctx->textures_saved[i], NULL);
00257 }
00258
00259 free_framebuffer_state(&ctx->fb);
00260 free_framebuffer_state(&ctx->fb_saved);
00261
00262 if (ctx->cache) {
00263 cso_cache_delete( ctx->cache );
00264 ctx->cache = NULL;
00265 }
00266 }
00267
00268
00269 void cso_destroy_context( struct cso_context *ctx )
00270 {
00271 if (ctx) {
00272
00273 FREE( ctx );
00274 }
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 enum pipe_error cso_set_blend(struct cso_context *ctx,
00289 const struct pipe_blend_state *templ)
00290 {
00291 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state));
00292 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
00293 hash_key, CSO_BLEND,
00294 (void*)templ);
00295 void *handle;
00296
00297 if (cso_hash_iter_is_null(iter)) {
00298 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
00299 if (!cso)
00300 return PIPE_ERROR_OUT_OF_MEMORY;
00301
00302 memcpy(&cso->state, templ, sizeof(*templ));
00303 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
00304 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
00305 cso->context = ctx->pipe;
00306
00307 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
00308 if (cso_hash_iter_is_null(iter)) {
00309 FREE(cso);
00310 return PIPE_ERROR_OUT_OF_MEMORY;
00311 }
00312
00313 handle = cso->data;
00314 }
00315 else {
00316 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
00317 }
00318
00319 if (ctx->blend != handle) {
00320 ctx->blend = handle;
00321 ctx->pipe->bind_blend_state(ctx->pipe, handle);
00322 }
00323 return PIPE_OK;
00324 }
00325
00326 void cso_save_blend(struct cso_context *ctx)
00327 {
00328 assert(!ctx->blend_saved);
00329 ctx->blend_saved = ctx->blend;
00330 }
00331
00332 void cso_restore_blend(struct cso_context *ctx)
00333 {
00334 if (ctx->blend != ctx->blend_saved) {
00335 ctx->blend = ctx->blend_saved;
00336 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
00337 }
00338 ctx->blend_saved = NULL;
00339 }
00340
00341
00342
00343 enum pipe_error cso_single_sampler(struct cso_context *ctx,
00344 unsigned idx,
00345 const struct pipe_sampler_state *templ)
00346 {
00347 void *handle = NULL;
00348
00349 if (templ != NULL) {
00350 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state));
00351 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
00352 hash_key, CSO_SAMPLER,
00353 (void*)templ);
00354
00355 if (cso_hash_iter_is_null(iter)) {
00356 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
00357 if (!cso)
00358 return PIPE_ERROR_OUT_OF_MEMORY;
00359
00360 memcpy(&cso->state, templ, sizeof(*templ));
00361 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
00362 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
00363 cso->context = ctx->pipe;
00364
00365 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
00366 if (cso_hash_iter_is_null(iter)) {
00367 FREE(cso);
00368 return PIPE_ERROR_OUT_OF_MEMORY;
00369 }
00370
00371 handle = cso->data;
00372 }
00373 else {
00374 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
00375 }
00376 }
00377
00378 ctx->samplers[idx] = handle;
00379 return PIPE_OK;
00380 }
00381
00382 void cso_single_sampler_done( struct cso_context *ctx )
00383 {
00384 unsigned i;
00385
00386
00387 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
00388 if (ctx->samplers[i - 1] != NULL)
00389 break;
00390 }
00391
00392 ctx->nr_samplers = i;
00393
00394 if (ctx->hw.nr_samplers != ctx->nr_samplers ||
00395 memcmp(ctx->hw.samplers,
00396 ctx->samplers,
00397 ctx->nr_samplers * sizeof(void *)) != 0)
00398 {
00399 memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *));
00400 ctx->hw.nr_samplers = ctx->nr_samplers;
00401
00402 ctx->pipe->bind_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers);
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411 enum pipe_error cso_set_samplers( struct cso_context *ctx,
00412 unsigned nr,
00413 const struct pipe_sampler_state **templates )
00414 {
00415 unsigned i;
00416 enum pipe_error temp, error = PIPE_OK;
00417
00418
00419
00420
00421 for (i = 0; i < nr; i++) {
00422 temp = cso_single_sampler( ctx, i, templates[i] );
00423 if (temp != PIPE_OK)
00424 error = temp;
00425 }
00426
00427 for ( ; i < ctx->nr_samplers; i++) {
00428 temp = cso_single_sampler( ctx, i, NULL );
00429 if (temp != PIPE_OK)
00430 error = temp;
00431 }
00432
00433 cso_single_sampler_done( ctx );
00434
00435 return error;
00436 }
00437
00438 void cso_save_samplers(struct cso_context *ctx)
00439 {
00440 ctx->nr_samplers_saved = ctx->nr_samplers;
00441 memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers));
00442 }
00443
00444 void cso_restore_samplers(struct cso_context *ctx)
00445 {
00446 ctx->nr_samplers = ctx->nr_samplers_saved;
00447 memcpy(ctx->samplers, ctx->samplers_saved, sizeof(ctx->samplers));
00448 cso_single_sampler_done( ctx );
00449 }
00450
00451
00452 enum pipe_error cso_set_sampler_textures( struct cso_context *ctx,
00453 uint count,
00454 struct pipe_texture **textures )
00455 {
00456 uint i;
00457
00458 ctx->nr_textures = count;
00459
00460 for (i = 0; i < count; i++)
00461 pipe_texture_reference(&ctx->textures[i], textures[i]);
00462 for ( ; i < PIPE_MAX_SAMPLERS; i++)
00463 pipe_texture_reference(&ctx->textures[i], NULL);
00464
00465 ctx->pipe->set_sampler_textures(ctx->pipe, count, textures);
00466
00467 return PIPE_OK;
00468 }
00469
00470 void cso_save_sampler_textures( struct cso_context *ctx )
00471 {
00472 uint i;
00473
00474 ctx->nr_textures_saved = ctx->nr_textures;
00475 for (i = 0; i < ctx->nr_textures; i++) {
00476 assert(!ctx->textures_saved[i]);
00477 pipe_texture_reference(&ctx->textures_saved[i], ctx->textures[i]);
00478 }
00479 }
00480
00481 void cso_restore_sampler_textures( struct cso_context *ctx )
00482 {
00483 uint i;
00484
00485 ctx->nr_textures = ctx->nr_textures_saved;
00486
00487 for (i = 0; i < ctx->nr_textures; i++) {
00488 pipe_texture_reference(&ctx->textures[i], NULL);
00489 ctx->textures[i] = ctx->textures_saved[i];
00490 ctx->textures_saved[i] = NULL;
00491 }
00492 for ( ; i < PIPE_MAX_SAMPLERS; i++)
00493 pipe_texture_reference(&ctx->textures[i], NULL);
00494
00495 ctx->pipe->set_sampler_textures(ctx->pipe, ctx->nr_textures, ctx->textures);
00496
00497 ctx->nr_textures_saved = 0;
00498 }
00499
00500
00501
00502 enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
00503 const struct pipe_depth_stencil_alpha_state *templ)
00504 {
00505 unsigned hash_key = cso_construct_key((void*)templ,
00506 sizeof(struct pipe_depth_stencil_alpha_state));
00507 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
00508 hash_key,
00509 CSO_DEPTH_STENCIL_ALPHA,
00510 (void*)templ);
00511 void *handle;
00512
00513 if (cso_hash_iter_is_null(iter)) {
00514 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha));
00515 if (!cso)
00516 return PIPE_ERROR_OUT_OF_MEMORY;
00517
00518 memcpy(&cso->state, templ, sizeof(*templ));
00519 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state);
00520 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
00521 cso->context = ctx->pipe;
00522
00523 iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso);
00524 if (cso_hash_iter_is_null(iter)) {
00525 FREE(cso);
00526 return PIPE_ERROR_OUT_OF_MEMORY;
00527 }
00528
00529 handle = cso->data;
00530 }
00531 else {
00532 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
00533 }
00534
00535 if (ctx->depth_stencil != handle) {
00536 ctx->depth_stencil = handle;
00537 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
00538 }
00539 return PIPE_OK;
00540 }
00541
00542 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
00543 {
00544 assert(!ctx->depth_stencil_saved);
00545 ctx->depth_stencil_saved = ctx->depth_stencil;
00546 }
00547
00548 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
00549 {
00550 if (ctx->depth_stencil != ctx->depth_stencil_saved) {
00551 ctx->depth_stencil = ctx->depth_stencil_saved;
00552 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
00553 }
00554 ctx->depth_stencil_saved = NULL;
00555 }
00556
00557
00558
00559 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
00560 const struct pipe_rasterizer_state *templ)
00561 {
00562 unsigned hash_key = cso_construct_key((void*)templ,
00563 sizeof(struct pipe_rasterizer_state));
00564 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
00565 hash_key, CSO_RASTERIZER,
00566 (void*)templ);
00567 void *handle = NULL;
00568
00569 if (cso_hash_iter_is_null(iter)) {
00570 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
00571 if (!cso)
00572 return PIPE_ERROR_OUT_OF_MEMORY;
00573
00574 memcpy(&cso->state, templ, sizeof(*templ));
00575 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
00576 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state;
00577 cso->context = ctx->pipe;
00578
00579 iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
00580 if (cso_hash_iter_is_null(iter)) {
00581 FREE(cso);
00582 return PIPE_ERROR_OUT_OF_MEMORY;
00583 }
00584
00585 handle = cso->data;
00586 }
00587 else {
00588 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
00589 }
00590
00591 if (ctx->rasterizer != handle) {
00592 ctx->rasterizer = handle;
00593 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
00594 }
00595 return PIPE_OK;
00596 }
00597
00598 void cso_save_rasterizer(struct cso_context *ctx)
00599 {
00600 assert(!ctx->rasterizer_saved);
00601 ctx->rasterizer_saved = ctx->rasterizer;
00602 }
00603
00604 void cso_restore_rasterizer(struct cso_context *ctx)
00605 {
00606 if (ctx->rasterizer != ctx->rasterizer_saved) {
00607 ctx->rasterizer = ctx->rasterizer_saved;
00608 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
00609 }
00610 ctx->rasterizer_saved = NULL;
00611 }
00612
00613
00614
00615 enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
00616 void *handle )
00617 {
00618 if (ctx->fragment_shader != handle) {
00619 ctx->fragment_shader = handle;
00620 ctx->pipe->bind_fs_state(ctx->pipe, handle);
00621 }
00622 return PIPE_OK;
00623 }
00624
00625 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
00626 {
00627 if (handle == ctx->fragment_shader) {
00628
00629 ctx->pipe->bind_fs_state(ctx->pipe, NULL);
00630 ctx->fragment_shader = NULL;
00631 }
00632 ctx->pipe->delete_fs_state(ctx->pipe, handle);
00633 }
00634
00635
00636
00637 #if 0
00638 enum pipe_error cso_set_fragment_shader(struct cso_context *ctx,
00639 const struct pipe_shader_state *templ)
00640 {
00641 const struct tgsi_token *tokens = templ->tokens;
00642 unsigned num_tokens = tgsi_num_tokens(tokens);
00643 size_t tokens_size = num_tokens*sizeof(struct tgsi_token);
00644 unsigned hash_key = cso_construct_key((void*)tokens, tokens_size);
00645 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
00646 hash_key,
00647 CSO_FRAGMENT_SHADER,
00648 (void*)tokens);
00649 void *handle = NULL;
00650
00651 if (cso_hash_iter_is_null(iter)) {
00652 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size);
00653 struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso));
00654
00655 if (!cso)
00656 return PIPE_ERROR_OUT_OF_MEMORY;
00657
00658 memcpy(cso_tokens, tokens, tokens_size);
00659 cso->state.tokens = cso_tokens;
00660 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state);
00661 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state;
00662 cso->context = ctx->pipe;
00663
00664 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso);
00665 if (cso_hash_iter_is_null(iter)) {
00666 FREE(cso);
00667 return PIPE_ERROR_OUT_OF_MEMORY;
00668 }
00669
00670 handle = cso->data;
00671 }
00672 else {
00673 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
00674 }
00675
00676 return cso_set_fragment_shader_handle( ctx, handle );
00677 }
00678 #endif
00679
00680 void cso_save_fragment_shader(struct cso_context *ctx)
00681 {
00682 assert(!ctx->fragment_shader_saved);
00683 ctx->fragment_shader_saved = ctx->fragment_shader;
00684 }
00685
00686 void cso_restore_fragment_shader(struct cso_context *ctx)
00687 {
00688 if (ctx->fragment_shader_saved != ctx->fragment_shader) {
00689 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
00690 ctx->fragment_shader = ctx->fragment_shader_saved;
00691 }
00692 ctx->fragment_shader_saved = NULL;
00693 }
00694
00695
00696 enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
00697 void *handle )
00698 {
00699 if (ctx->vertex_shader != handle) {
00700 ctx->vertex_shader = handle;
00701 ctx->pipe->bind_vs_state(ctx->pipe, handle);
00702 }
00703 return PIPE_OK;
00704 }
00705
00706 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
00707 {
00708 if (handle == ctx->vertex_shader) {
00709
00710 ctx->pipe->bind_vs_state(ctx->pipe, NULL);
00711 ctx->vertex_shader = NULL;
00712 }
00713 ctx->pipe->delete_vs_state(ctx->pipe, handle);
00714 }
00715
00716
00717
00718
00719 #if 0
00720 enum pipe_error cso_set_vertex_shader(struct cso_context *ctx,
00721 const struct pipe_shader_state *templ)
00722 {
00723 unsigned hash_key = cso_construct_key((void*)templ,
00724 sizeof(struct pipe_shader_state));
00725 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
00726 hash_key, CSO_VERTEX_SHADER,
00727 (void*)templ);
00728 void *handle = NULL;
00729
00730 if (cso_hash_iter_is_null(iter)) {
00731 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
00732
00733 if (!cso)
00734 return PIPE_ERROR_OUT_OF_MEMORY;
00735
00736 memcpy(cso->state, templ, sizeof(*templ));
00737 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state);
00738 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state;
00739 cso->context = ctx->pipe;
00740
00741 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso);
00742 if (cso_hash_iter_is_null(iter)) {
00743 FREE(cso);
00744 return PIPE_ERROR_OUT_OF_MEMORY;
00745 }
00746
00747 handle = cso->data;
00748 }
00749 else {
00750 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
00751 }
00752
00753 return cso_set_vertex_shader_handle( ctx, handle );
00754 }
00755 #endif
00756
00757
00758
00759 void cso_save_vertex_shader(struct cso_context *ctx)
00760 {
00761 assert(!ctx->vertex_shader_saved);
00762 ctx->vertex_shader_saved = ctx->vertex_shader;
00763 }
00764
00765 void cso_restore_vertex_shader(struct cso_context *ctx)
00766 {
00767 if (ctx->vertex_shader_saved != ctx->vertex_shader) {
00768 ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
00769 ctx->vertex_shader = ctx->vertex_shader_saved;
00770 }
00771 ctx->vertex_shader_saved = NULL;
00772 }
00773
00774
00778 static void
00779 copy_framebuffer_state(struct pipe_framebuffer_state *dst,
00780 const struct pipe_framebuffer_state *src)
00781 {
00782 uint i;
00783
00784 dst->width = src->width;
00785 dst->height = src->height;
00786 dst->num_cbufs = src->num_cbufs;
00787 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
00788 pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
00789 }
00790 pipe_surface_reference(&dst->zsbuf, src->zsbuf);
00791 }
00792
00793
00794 static void
00795 free_framebuffer_state(struct pipe_framebuffer_state *fb)
00796 {
00797 uint i;
00798
00799 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
00800 pipe_surface_reference(&fb->cbufs[i], NULL);
00801 }
00802 pipe_surface_reference(&fb->zsbuf, NULL);
00803 }
00804
00805
00806 enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
00807 const struct pipe_framebuffer_state *fb)
00808 {
00809 if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
00810 copy_framebuffer_state(&ctx->fb, fb);
00811 ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
00812 }
00813 return PIPE_OK;
00814 }
00815
00816 void cso_save_framebuffer(struct cso_context *ctx)
00817 {
00818 copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
00819 }
00820
00821 void cso_restore_framebuffer(struct cso_context *ctx)
00822 {
00823 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
00824 copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
00825 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
00826 free_framebuffer_state(&ctx->fb_saved);
00827 }
00828 }
00829
00830
00831 enum pipe_error cso_set_viewport(struct cso_context *ctx,
00832 const struct pipe_viewport_state *vp)
00833 {
00834 if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
00835 ctx->vp = *vp;
00836 ctx->pipe->set_viewport_state(ctx->pipe, vp);
00837 }
00838 return PIPE_OK;
00839 }
00840
00841 void cso_save_viewport(struct cso_context *ctx)
00842 {
00843 ctx->vp_saved = ctx->vp;
00844 }
00845
00846
00847 void cso_restore_viewport(struct cso_context *ctx)
00848 {
00849 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
00850 ctx->vp = ctx->vp_saved;
00851 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
00852 }
00853 }
00854
00855
00856
00857
00858 enum pipe_error cso_set_blend_color(struct cso_context *ctx,
00859 const struct pipe_blend_color *bc)
00860 {
00861 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
00862 ctx->blend_color = *bc;
00863 ctx->pipe->set_blend_color(ctx->pipe, bc);
00864 }
00865 return PIPE_OK;
00866 }