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