sp_state_sampler.c revision df87fb59136eb302d72eac4b58fd8ffb25989ed5
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/* Authors: 29 * Brian Paul 30 */ 31 32#include "util/u_memory.h" 33#include "util/u_inlines.h" 34 35#include "draw/draw_context.h" 36 37#include "sp_context.h" 38#include "sp_state.h" 39#include "sp_texture.h" 40#include "sp_tex_sample.h" 41#include "sp_tex_tile_cache.h" 42 43 44struct sp_sampler { 45 struct pipe_sampler_state base; 46 struct sp_sampler_variant *variants; 47 struct sp_sampler_variant *current; 48}; 49 50static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler ) 51{ 52 return (struct sp_sampler *)sampler; 53} 54 55 56static void * 57softpipe_create_sampler_state(struct pipe_context *pipe, 58 const struct pipe_sampler_state *sampler) 59{ 60 struct sp_sampler *sp_sampler = CALLOC_STRUCT(sp_sampler); 61 62 sp_sampler->base = *sampler; 63 sp_sampler->variants = NULL; 64 65 return (void *)sp_sampler; 66} 67 68 69static void 70softpipe_bind_sampler_states(struct pipe_context *pipe, 71 unsigned shader, unsigned num, void **sampler) 72{ 73 struct softpipe_context *softpipe = softpipe_context(pipe); 74 unsigned i; 75 76 assert(shader < PIPE_SHADER_TYPES); 77 assert(num <= PIPE_MAX_SAMPLERS); 78 79 /* Check for no-op */ 80 if (num == softpipe->num_samplers[shader] && 81 !memcmp(softpipe->samplers[shader], sampler, num * sizeof(void *))) 82 return; 83 84 draw_flush(softpipe->draw); 85 86 for (i = 0; i < num; ++i) 87 softpipe->samplers[shader][i] = sampler[i]; 88 for (i = num; i < PIPE_MAX_SAMPLERS; ++i) 89 softpipe->samplers[shader][i] = NULL; 90 91 softpipe->num_samplers[shader] = num; 92 93 if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { 94 draw_set_samplers(softpipe->draw, 95 shader, 96 softpipe->samplers[shader], 97 softpipe->num_samplers[shader]); 98 } 99 100 softpipe->dirty |= SP_NEW_SAMPLER; 101} 102 103 104 105static void 106softpipe_bind_fragment_sampler_states(struct pipe_context *pipe, 107 unsigned num, void **samplers) 108{ 109 softpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, num, samplers); 110} 111 112 113static void 114softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, 115 unsigned num, 116 void **samplers) 117{ 118 softpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, num, samplers); 119} 120 121 122static void 123softpipe_bind_geometry_sampler_states(struct pipe_context *pipe, 124 unsigned num, 125 void **samplers) 126{ 127 softpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, num, samplers); 128} 129 130 131static struct pipe_sampler_view * 132softpipe_create_sampler_view(struct pipe_context *pipe, 133 struct pipe_resource *resource, 134 const struct pipe_sampler_view *templ) 135{ 136 struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); 137 138 if (view) { 139 *view = *templ; 140 view->reference.count = 1; 141 view->texture = NULL; 142 pipe_resource_reference(&view->texture, resource); 143 view->context = pipe; 144 } 145 146 return view; 147} 148 149 150static void 151softpipe_sampler_view_destroy(struct pipe_context *pipe, 152 struct pipe_sampler_view *view) 153{ 154 pipe_resource_reference(&view->texture, NULL); 155 FREE(view); 156} 157 158 159static void 160softpipe_set_sampler_views(struct pipe_context *pipe, 161 unsigned shader, 162 unsigned num, 163 struct pipe_sampler_view **views) 164{ 165 struct softpipe_context *softpipe = softpipe_context(pipe); 166 uint i; 167 168 assert(num <= PIPE_MAX_SAMPLERS); 169 170 /* Check for no-op */ 171 if (num == softpipe->num_sampler_views[shader] && 172 !memcmp(softpipe->sampler_views[shader], views, 173 num * sizeof(struct pipe_sampler_view *))) 174 return; 175 176 draw_flush(softpipe->draw); 177 178 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 179 struct pipe_sampler_view *view = i < num ? views[i] : NULL; 180 181 pipe_sampler_view_reference(&softpipe->sampler_views[shader][i], view); 182 sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][i], view); 183 } 184 185 softpipe->num_sampler_views[shader] = num; 186 187 if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { 188 draw_set_sampler_views(softpipe->draw, 189 shader, 190 softpipe->sampler_views[shader], 191 softpipe->num_sampler_views[shader]); 192 } 193 194 softpipe->dirty |= SP_NEW_TEXTURE; 195} 196 197 198static void 199softpipe_set_fragment_sampler_views(struct pipe_context *pipe, 200 unsigned num, 201 struct pipe_sampler_view **views) 202{ 203 softpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, num, views); 204} 205 206 207static void 208softpipe_set_vertex_sampler_views(struct pipe_context *pipe, 209 unsigned num, 210 struct pipe_sampler_view **views) 211{ 212 softpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, num, views); 213} 214 215 216static void 217softpipe_set_geometry_sampler_views(struct pipe_context *pipe, 218 unsigned num, 219 struct pipe_sampler_view **views) 220{ 221 softpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, num, views); 222} 223 224 225/** 226 * Find/create an sp_sampler_variant object for sampling the given texture, 227 * sampler and tex unit. 228 * 229 * Note that the tex unit is significant. We can't re-use a sampler 230 * variant for multiple texture units because the sampler variant contains 231 * the texture object pointer. If the texture object pointer were stored 232 * somewhere outside the sampler variant, we could re-use samplers for 233 * multiple texture units. 234 */ 235static struct sp_sampler_variant * 236get_sampler_variant( unsigned unit, 237 struct sp_sampler *sampler, 238 struct pipe_sampler_view *view, 239 unsigned processor ) 240{ 241 struct softpipe_resource *sp_texture = softpipe_resource(view->texture); 242 struct sp_sampler_variant *v = NULL; 243 union sp_sampler_key key; 244 245 /* if this fails, widen the key.unit field and update this assertion */ 246 assert(PIPE_MAX_SAMPLERS <= 16); 247 248 key.bits.target = sp_texture->base.target; 249 key.bits.is_pot = sp_texture->pot; 250 key.bits.processor = processor; 251 key.bits.unit = unit; 252 key.bits.swizzle_r = view->swizzle_r; 253 key.bits.swizzle_g = view->swizzle_g; 254 key.bits.swizzle_b = view->swizzle_b; 255 key.bits.swizzle_a = view->swizzle_a; 256 key.bits.pad = 0; 257 258 if (sampler->current && 259 key.value == sampler->current->key.value) { 260 v = sampler->current; 261 } 262 263 if (v == NULL) { 264 for (v = sampler->variants; v; v = v->next) 265 if (v->key.value == key.value) 266 break; 267 268 if (v == NULL) { 269 v = sp_create_sampler_variant( &sampler->base, key ); 270 v->next = sampler->variants; 271 sampler->variants = v; 272 } 273 } 274 275 sampler->current = v; 276 return v; 277} 278 279 280/** 281 * Reset the sampler variants for a shader stage (vert, frag, geom). 282 */ 283static void 284reset_sampler_variants(struct softpipe_context *softpipe, 285 unsigned shader, 286 unsigned tgsi_shader, 287 int max_sampler) 288{ 289 int i; 290 291 for (i = 0; i <= max_sampler; i++) { 292 if (softpipe->samplers[shader][i]) { 293 softpipe->tgsi.samplers_list[shader][i] = 294 get_sampler_variant(i, 295 sp_sampler(softpipe->samplers[shader][i]), 296 softpipe->sampler_views[shader][i], 297 tgsi_shader); 298 299 sp_sampler_variant_bind_view(softpipe->tgsi.samplers_list[shader][i], 300 softpipe->tex_cache[shader][i], 301 softpipe->sampler_views[shader][i]); 302 } 303 } 304} 305 306 307void 308softpipe_reset_sampler_variants(struct softpipe_context *softpipe) 309{ 310 /* It's a bit hard to build these samplers ahead of time -- don't 311 * really know which samplers are going to be used for vertex and 312 * fragment programs. 313 */ 314 315 /* XXX note: PIPE_SHADER_x != TGSI_PROCESSOR_x (fix that someday) */ 316 reset_sampler_variants(softpipe, 317 PIPE_SHADER_VERTEX, 318 TGSI_PROCESSOR_VERTEX, 319 softpipe->vs->max_sampler); 320 321 reset_sampler_variants(softpipe, 322 PIPE_SHADER_FRAGMENT, 323 TGSI_PROCESSOR_FRAGMENT, 324 softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]); 325 326 if (softpipe->gs) { 327 reset_sampler_variants(softpipe, 328 PIPE_SHADER_GEOMETRY, 329 TGSI_PROCESSOR_GEOMETRY, 330 softpipe->gs->max_sampler); 331 } 332} 333 334 335static void 336softpipe_delete_sampler_state(struct pipe_context *pipe, 337 void *sampler) 338{ 339 struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler; 340 struct sp_sampler_variant *v, *tmp; 341 342 for (v = sp_sampler->variants; v; v = tmp) { 343 tmp = v->next; 344 sp_sampler_variant_destroy(v); 345 } 346 347 FREE( sampler ); 348} 349 350 351void 352softpipe_init_sampler_funcs(struct pipe_context *pipe) 353{ 354 pipe->create_sampler_state = softpipe_create_sampler_state; 355 pipe->bind_fragment_sampler_states = softpipe_bind_fragment_sampler_states; 356 pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; 357 pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states; 358 pipe->delete_sampler_state = softpipe_delete_sampler_state; 359 360 pipe->set_fragment_sampler_views = softpipe_set_fragment_sampler_views; 361 pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views; 362 pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views; 363 364 pipe->create_sampler_view = softpipe_create_sampler_view; 365 pipe->sampler_view_destroy = softpipe_sampler_view_destroy; 366} 367 368