cso_context.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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    /* if we're approach the maximum size, remove fourth of the entries
00192     * otherwise every subsequent call will go through the same */
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       /*remove elements until we're good */
00201       /*fixme: currently we pick the nodes to remove at random*/
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    /* Enable for testing: */
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       //cso_release_all( ctx );
00273       FREE( ctx );
00274    }
00275 }
00276 
00277 
00278 /* Those function will either find the state of the given template
00279  * in the cache or they will create a new state from the given
00280  * template, insert it in the cache and return it.
00281  */
00282 
00283 /*
00284  * If the driver returns 0 from the create method then they will assign
00285  * the data member of the cso to be the template itself.
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    /* find highest non-null sampler */
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  * If the function encouters any errors it will return the
00408  * last one. Done to always try to set as many samplers
00409  * as possible.
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    /* TODO: fastpath
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       /* unbind before deleting */
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 /* Not really working:
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       /* unbind before deleting */
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 /* Not really working:
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 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4