sp_state_sampler.c revision 1f34e1a6cbac4b96d07a3d6d01bc443d5282add4
1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/************************************************************************** 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * All Rights Reserved. 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Permission is hereby granted, free of charge, to any person obtaining a 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * copy of this software and associated documentation files (the 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * "Software"), to deal in the Software without restriction, including 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * without limitation the rights to use, copy, modify, merge, publish, 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * distribute, sub license, and/or sell copies of the Software, and to 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * permit persons to whom the Software is furnished to do so, subject to 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the following conditions: 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The above copyright notice and this permission notice (including the 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * next paragraph) shall be included in all copies or substantial portions 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * of the Software. 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam **************************************************************************/ 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/* Authors: 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Brian Paul 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "util/u_memory.h" 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "util/u_inlines.h" 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "draw/draw_context.h" 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "sp_context.h" 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "sp_state.h" 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "sp_texture.h" 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "sp_tex_sample.h" 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam#include "sp_tex_tile_cache.h" 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamstruct sp_sampler { 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam struct pipe_sampler_state base; 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam struct sp_sampler_variant *variants; 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam struct sp_sampler_variant *current; 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}; 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamstatic struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler ) 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 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) { 94 draw_set_samplers(softpipe->draw, 95 softpipe->samplers[PIPE_SHADER_VERTEX], 96 softpipe->num_samplers[PIPE_SHADER_VERTEX]); 97 } 98 99 softpipe->dirty |= SP_NEW_SAMPLER; 100} 101 102 103 104static void 105softpipe_bind_fragment_sampler_states(struct pipe_context *pipe, 106 unsigned num, void **samplers) 107{ 108 softpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, num, samplers); 109} 110 111 112static void 113softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, 114 unsigned num, 115 void **samplers) 116{ 117 softpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, num, samplers); 118} 119 120 121static void 122softpipe_bind_geometry_sampler_states(struct pipe_context *pipe, 123 unsigned num, 124 void **samplers) 125{ 126 softpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, num, samplers); 127} 128 129 130static struct pipe_sampler_view * 131softpipe_create_sampler_view(struct pipe_context *pipe, 132 struct pipe_resource *resource, 133 const struct pipe_sampler_view *templ) 134{ 135 struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); 136 137 if (view) { 138 *view = *templ; 139 view->reference.count = 1; 140 view->texture = NULL; 141 pipe_resource_reference(&view->texture, resource); 142 view->context = pipe; 143 } 144 145 return view; 146} 147 148 149static void 150softpipe_sampler_view_destroy(struct pipe_context *pipe, 151 struct pipe_sampler_view *view) 152{ 153 pipe_resource_reference(&view->texture, NULL); 154 FREE(view); 155} 156 157 158static void 159softpipe_set_sampler_views(struct pipe_context *pipe, 160 unsigned shader, 161 unsigned num, 162 struct pipe_sampler_view **views) 163{ 164 struct softpipe_context *softpipe = softpipe_context(pipe); 165 uint i; 166 167 assert(num <= PIPE_MAX_SAMPLERS); 168 169 /* Check for no-op */ 170 if (num == softpipe->num_sampler_views[shader] && 171 !memcmp(softpipe->sampler_views[shader], views, 172 num * sizeof(struct pipe_sampler_view *))) 173 return; 174 175 draw_flush(softpipe->draw); 176 177 for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { 178 struct pipe_sampler_view *view = i < num ? views[i] : NULL; 179 180 pipe_sampler_view_reference(&softpipe->sampler_views[shader][i], view); 181 sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][i], view); 182 } 183 184 softpipe->num_sampler_views[shader] = num; 185 186 if (shader == PIPE_SHADER_VERTEX) { 187 draw_set_sampler_views(softpipe->draw, 188 softpipe->sampler_views[PIPE_SHADER_VERTEX], 189 softpipe->num_sampler_views[PIPE_SHADER_VERTEX]); 190 } 191 192 softpipe->dirty |= SP_NEW_TEXTURE; 193} 194 195 196static void 197softpipe_set_fragment_sampler_views(struct pipe_context *pipe, 198 unsigned num, 199 struct pipe_sampler_view **views) 200{ 201 softpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, num, views); 202} 203 204 205static void 206softpipe_set_vertex_sampler_views(struct pipe_context *pipe, 207 unsigned num, 208 struct pipe_sampler_view **views) 209{ 210 softpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, num, views); 211} 212 213 214static void 215softpipe_set_geometry_sampler_views(struct pipe_context *pipe, 216 unsigned num, 217 struct pipe_sampler_view **views) 218{ 219 softpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, num, views); 220} 221 222 223/** 224 * Find/create an sp_sampler_variant object for sampling the given texture, 225 * sampler and tex unit. 226 * 227 * Note that the tex unit is significant. We can't re-use a sampler 228 * variant for multiple texture units because the sampler variant contains 229 * the texture object pointer. If the texture object pointer were stored 230 * somewhere outside the sampler variant, we could re-use samplers for 231 * multiple texture units. 232 */ 233static struct sp_sampler_variant * 234get_sampler_variant( unsigned unit, 235 struct sp_sampler *sampler, 236 struct pipe_sampler_view *view, 237 unsigned processor ) 238{ 239 struct softpipe_resource *sp_texture = softpipe_resource(view->texture); 240 struct sp_sampler_variant *v = NULL; 241 union sp_sampler_key key; 242 243 /* if this fails, widen the key.unit field and update this assertion */ 244 assert(PIPE_MAX_SAMPLERS <= 16); 245 246 key.bits.target = sp_texture->base.target; 247 key.bits.is_pot = sp_texture->pot; 248 key.bits.processor = processor; 249 key.bits.unit = unit; 250 key.bits.swizzle_r = view->swizzle_r; 251 key.bits.swizzle_g = view->swizzle_g; 252 key.bits.swizzle_b = view->swizzle_b; 253 key.bits.swizzle_a = view->swizzle_a; 254 key.bits.pad = 0; 255 256 if (sampler->current && 257 key.value == sampler->current->key.value) { 258 v = sampler->current; 259 } 260 261 if (v == NULL) { 262 for (v = sampler->variants; v; v = v->next) 263 if (v->key.value == key.value) 264 break; 265 266 if (v == NULL) { 267 v = sp_create_sampler_variant( &sampler->base, key ); 268 v->next = sampler->variants; 269 sampler->variants = v; 270 } 271 } 272 273 sampler->current = v; 274 return v; 275} 276 277 278/** 279 * Reset the sampler variants for a shader stage (vert, frag, geom). 280 */ 281static void 282reset_sampler_variants(struct softpipe_context *softpipe, 283 unsigned shader, 284 unsigned tgsi_shader, 285 int max_sampler) 286{ 287 int i; 288 289 for (i = 0; i <= max_sampler; i++) { 290 if (softpipe->samplers[shader][i]) { 291 softpipe->tgsi.samplers_list[shader][i] = 292 get_sampler_variant(i, 293 sp_sampler(softpipe->samplers[shader][i]), 294 softpipe->sampler_views[shader][i], 295 tgsi_shader); 296 297 sp_sampler_variant_bind_view(softpipe->tgsi.samplers_list[shader][i], 298 softpipe->tex_cache[shader][i], 299 softpipe->sampler_views[shader][i]); 300 } 301 } 302} 303 304 305void 306softpipe_reset_sampler_variants(struct softpipe_context *softpipe) 307{ 308 /* It's a bit hard to build these samplers ahead of time -- don't 309 * really know which samplers are going to be used for vertex and 310 * fragment programs. 311 */ 312 313 /* XXX note: PIPE_SHADER_x != TGSI_PROCESSOR_x (fix that someday) */ 314 reset_sampler_variants(softpipe, 315 PIPE_SHADER_VERTEX, 316 TGSI_PROCESSOR_VERTEX, 317 softpipe->vs->max_sampler); 318 319 reset_sampler_variants(softpipe, 320 PIPE_SHADER_FRAGMENT, 321 TGSI_PROCESSOR_FRAGMENT, 322 softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]); 323 324 if (softpipe->gs) { 325 reset_sampler_variants(softpipe, 326 PIPE_SHADER_GEOMETRY, 327 TGSI_PROCESSOR_GEOMETRY, 328 softpipe->gs->max_sampler); 329 } 330} 331 332 333static void 334softpipe_delete_sampler_state(struct pipe_context *pipe, 335 void *sampler) 336{ 337 struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler; 338 struct sp_sampler_variant *v, *tmp; 339 340 for (v = sp_sampler->variants; v; v = tmp) { 341 tmp = v->next; 342 sp_sampler_variant_destroy(v); 343 } 344 345 FREE( sampler ); 346} 347 348 349void 350softpipe_init_sampler_funcs(struct pipe_context *pipe) 351{ 352 pipe->create_sampler_state = softpipe_create_sampler_state; 353 pipe->bind_fragment_sampler_states = softpipe_bind_fragment_sampler_states; 354 pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; 355 pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states; 356 pipe->delete_sampler_state = softpipe_delete_sampler_state; 357 358 pipe->set_fragment_sampler_views = softpipe_set_fragment_sampler_views; 359 pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views; 360 pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views; 361 362 pipe->create_sampler_view = softpipe_create_sampler_view; 363 pipe->sampler_view_destroy = softpipe_sampler_view_destroy; 364} 365 366