cso_context.c revision ac87bc18359825890a53d4dbfda5c6eecd916afd
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 /* Wrap the cso cache & hash mechanisms in a simplified 29 * pipe-driver-specific interface. 30 * 31 * Authors: 32 * Zack Rusin <zack@tungstengraphics.com> 33 * Keith Whitwell <keith@tungstengraphics.com> 34 */ 35 36#include "pipe/p_state.h" 37#include "pipe/p_util.h" 38 39#include "cso_cache/cso_context.h" 40#include "cso_cache/cso_cache.h" 41#include "cso_cache/cso_hash.h" 42 43struct cso_context { 44 struct pipe_context *pipe; 45 struct cso_cache *cache; 46 47 struct { 48 void *samplers[PIPE_MAX_SAMPLERS]; 49 unsigned nr_samplers; 50 } hw; 51 52 void *samplers[PIPE_MAX_SAMPLERS]; 53 unsigned nr_samplers; 54 55 void *blend; 56 void *depth_stencil; 57 void *rasterizer; 58 void *fragment_shader; 59 void *vertex_shader; 60}; 61 62 63struct cso_context *cso_create_context( struct pipe_context *pipe ) 64{ 65 struct cso_context *ctx = CALLOC_STRUCT(cso_context); 66 if (ctx == NULL) 67 goto out; 68 69 ctx->cache = cso_cache_create(); 70 if (ctx->cache == NULL) 71 goto out; 72 73 ctx->pipe = pipe; 74 75 return ctx; 76 77out: 78 cso_destroy_context( ctx ); 79 return NULL; 80} 81 82 83void cso_destroy_context( struct cso_context *ctx ) 84{ 85 if (ctx == NULL) 86 return; 87 88/* 89 if (ctx->pipe) 90 ctx->pipe->flush( ctx->pipe, PIPE_FLUSH_UNBIND_ALL ); 91*/ 92 93 if (ctx->cache) 94 cso_cache_delete( ctx->cache ); 95 96 FREE( ctx ); 97} 98 99 100/* Those function will either find the state of the given template 101 * in the cache or they will create a new state from the given 102 * template, insert it in the cache and return it. 103 */ 104 105/* 106 * If the driver returns 0 from the create method then they will assign 107 * the data member of the cso to be the template itself. 108 */ 109 110void cso_set_blend(struct cso_context *ctx, 111 const struct pipe_blend_state *templ) 112{ 113 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state)); 114 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 115 hash_key, CSO_BLEND, 116 (void*)templ); 117 void *handle; 118 119 if (cso_hash_iter_is_null(iter)) { 120 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend)); 121 122 cso->state = *templ; 123 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state); 124 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state; 125 cso->context = ctx->pipe; 126 127 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso); 128 handle = cso->data; 129 } 130 else { 131 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data; 132 } 133 134 if (ctx->blend != handle) { 135 ctx->blend = handle; 136 ctx->pipe->bind_blend_state(ctx->pipe, handle); 137 } 138} 139 140void cso_single_sampler(struct cso_context *ctx, 141 unsigned idx, 142 const struct pipe_sampler_state *templ) 143{ 144 void *handle = NULL; 145 146 if (templ != NULL) { 147 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state)); 148 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 149 hash_key, CSO_SAMPLER, 150 (void*)templ); 151 152 if (cso_hash_iter_is_null(iter)) { 153 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler)); 154 155 cso->state = *templ; 156 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); 157 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state; 158 cso->context = ctx->pipe; 159 160 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso); 161 handle = cso->data; 162 } 163 else { 164 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data; 165 } 166 } 167 168 ctx->samplers[idx] = handle; 169} 170 171void cso_single_sampler_done( struct cso_context *ctx ) 172{ 173 unsigned i; 174 175 for (i = 0; i < 8; i++) 176 if (ctx->samplers[i] == NULL) 177 break; 178 179 ctx->nr_samplers = i; 180 181 if (ctx->hw.nr_samplers != ctx->nr_samplers || 182 memcmp(ctx->hw.samplers, 183 ctx->samplers, 184 ctx->nr_samplers * sizeof(void *)) != 0) 185 { 186 memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *)); 187 ctx->hw.nr_samplers = ctx->nr_samplers; 188 189 ctx->pipe->bind_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers); 190 } 191} 192 193void cso_set_samplers( struct cso_context *ctx, 194 unsigned nr, 195 const struct pipe_sampler_state **templates ) 196{ 197 unsigned i; 198 199 /* TODO: fastpath 200 */ 201 202 for (i = 0; i < nr; i++) 203 cso_single_sampler( ctx, i, templates[i] ); 204 205 for ( ; i < ctx->nr_samplers; i++) 206 cso_single_sampler( ctx, i, NULL ); 207 208 cso_single_sampler_done( ctx ); 209} 210 211void cso_set_depth_stencil_alpha(struct cso_context *ctx, 212 const struct pipe_depth_stencil_alpha_state *templ) 213{ 214 unsigned hash_key = cso_construct_key((void*)templ, 215 sizeof(struct pipe_depth_stencil_alpha_state)); 216 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 217 hash_key, 218 CSO_DEPTH_STENCIL_ALPHA, 219 (void*)templ); 220 void *handle; 221 222 if (cso_hash_iter_is_null(iter)) { 223 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha)); 224 225 cso->state = *templ; 226 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state); 227 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state; 228 cso->context = ctx->pipe; 229 230 cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso); 231 handle = cso->data; 232 } 233 else { 234 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data; 235 } 236 237 if (ctx->depth_stencil != handle) { 238 ctx->depth_stencil = handle; 239 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle); 240 } 241} 242 243 244 245void cso_set_rasterizer(struct cso_context *ctx, 246 const struct pipe_rasterizer_state *templ) 247{ 248 unsigned hash_key = cso_construct_key((void*)templ, 249 sizeof(struct pipe_rasterizer_state)); 250 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 251 hash_key, CSO_RASTERIZER, 252 (void*)templ); 253 void *handle = NULL; 254 255 if (cso_hash_iter_is_null(iter)) { 256 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer)); 257 258 cso->state = *templ; 259 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state); 260 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state; 261 cso->context = ctx->pipe; 262 263 cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso); 264 handle = cso->data; 265 } 266 else { 267 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data; 268 } 269 270 if (ctx->rasterizer != handle) { 271 ctx->rasterizer = handle; 272 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle); 273 } 274} 275 276 277 278 279 280void cso_set_fragment_shader(struct cso_context *ctx, 281 const struct pipe_shader_state *templ) 282{ 283 unsigned hash_key = cso_construct_key((void*)templ, 284 sizeof(struct pipe_shader_state)); 285 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 286 hash_key, CSO_FRAGMENT_SHADER, 287 (void*)templ); 288 void *handle = NULL; 289 290 if (cso_hash_iter_is_null(iter)) { 291 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader)); 292 293 cso->state = *templ; 294 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state); 295 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state; 296 cso->context = ctx->pipe; 297 298 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso); 299 handle = cso->data; 300 } 301 else { 302 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data; 303 } 304 305 if (ctx->fragment_shader != handle) { 306 ctx->fragment_shader = handle; 307 ctx->pipe->bind_fs_state(ctx->pipe, handle); 308 } 309} 310 311void cso_set_vertex_shader(struct cso_context *ctx, 312 const struct pipe_shader_state *templ) 313{ 314 unsigned hash_key = cso_construct_key((void*)templ, 315 sizeof(struct pipe_shader_state)); 316 struct cso_hash_iter iter = cso_find_state_template(ctx->cache, 317 hash_key, CSO_VERTEX_SHADER, 318 (void*)templ); 319 void *handle = NULL; 320 321 if (cso_hash_iter_is_null(iter)) { 322 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader)); 323 324 cso->state = *templ; 325 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state); 326 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state; 327 cso->context = ctx->pipe; 328 329 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso); 330 handle = cso->data; 331 } 332 else { 333 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data; 334 } 335 336 if (ctx->vertex_shader != handle) { 337 ctx->vertex_shader = handle; 338 ctx->pipe->bind_fs_state(ctx->pipe, handle); 339 } 340} 341