d501952bba9e5846830cd723952ea82e74fd65c9
[profile/ivi/mesa.git] / src / gallium / drivers / softpipe / sp_state_sampler.c
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
34 #include "draw/draw_context.h"
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
44 struct sp_sampler {
45    struct pipe_sampler_state base;
46    struct sp_sampler_varient *varients;
47    struct sp_sampler_varient *current;
48 };
49
50 static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler )
51 {
52    return (struct sp_sampler *)sampler;
53 }
54
55
56 void *
57 softpipe_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->varients = NULL;
64
65    return (void *)sp_sampler;
66 }
67
68
69 void
70 softpipe_bind_sampler_states(struct pipe_context *pipe,
71                              unsigned num, void **sampler)
72 {
73    struct softpipe_context *softpipe = softpipe_context(pipe);
74    unsigned i;
75
76    assert(num <= PIPE_MAX_SAMPLERS);
77
78    /* Check for no-op */
79    if (num == softpipe->num_samplers &&
80        !memcmp(softpipe->sampler, sampler, num * sizeof(void *)))
81       return;
82
83    draw_flush(softpipe->draw);
84
85    for (i = 0; i < num; ++i)
86       softpipe->sampler[i] = sampler[i];
87    for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
88       softpipe->sampler[i] = NULL;
89
90    softpipe->num_samplers = num;
91
92    softpipe->dirty |= SP_NEW_SAMPLER;
93 }
94
95
96 void
97 softpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
98                                     unsigned num_samplers,
99                                     void **samplers)
100 {
101    struct softpipe_context *softpipe = softpipe_context(pipe);
102    unsigned i;
103
104    assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS);
105
106    /* Check for no-op */
107    if (num_samplers == softpipe->num_vertex_samplers &&
108        !memcmp(softpipe->vertex_samplers, samplers, num_samplers * sizeof(void *)))
109       return;
110
111    draw_flush(softpipe->draw);
112
113    for (i = 0; i < num_samplers; ++i)
114       softpipe->vertex_samplers[i] = samplers[i];
115    for (i = num_samplers; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
116       softpipe->vertex_samplers[i] = NULL;
117
118    softpipe->num_vertex_samplers = num_samplers;
119
120    softpipe->dirty |= SP_NEW_SAMPLER;
121 }
122
123
124 struct pipe_sampler_view *
125 softpipe_create_sampler_view(struct pipe_context *pipe,
126                              struct pipe_texture *texture,
127                              const struct pipe_sampler_view *templ)
128 {
129    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
130
131    if (view) {
132       *view = *templ;
133       view->reference.count = 1;
134       view->texture = NULL;
135       pipe_texture_reference(&view->texture, texture);
136       view->context = pipe;
137    }
138
139    return view;
140 }
141
142
143 void
144 softpipe_sampler_view_destroy(struct pipe_context *pipe,
145                               struct pipe_sampler_view *view)
146 {
147    pipe_texture_reference(&view->texture, NULL);
148    FREE(view);
149 }
150
151
152 void
153 softpipe_set_sampler_views(struct pipe_context *pipe,
154                            unsigned num,
155                            struct pipe_sampler_view **views)
156 {
157    struct softpipe_context *softpipe = softpipe_context(pipe);
158    uint i;
159
160    assert(num <= PIPE_MAX_SAMPLERS);
161
162    /* Check for no-op */
163    if (num == softpipe->num_sampler_views &&
164        !memcmp(softpipe->sampler_views, views, num * sizeof(struct pipe_sampler_view *)))
165       return;
166
167    draw_flush(softpipe->draw);
168
169    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
170       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
171
172       pipe_sampler_view_reference(&softpipe->sampler_views[i], view);
173       sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[i], view);
174    }
175
176    softpipe->num_sampler_views = num;
177
178    softpipe->dirty |= SP_NEW_TEXTURE;
179 }
180
181
182 void
183 softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
184                                   unsigned num,
185                                   struct pipe_sampler_view **views)
186 {
187    struct softpipe_context *softpipe = softpipe_context(pipe);
188    uint i;
189
190    assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
191
192    /* Check for no-op */
193    if (num == softpipe->num_vertex_sampler_views &&
194        !memcmp(softpipe->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
195       return;
196    }
197
198    draw_flush(softpipe->draw);
199
200    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
201       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
202
203       pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], view);
204       sp_tex_tile_cache_set_sampler_view(softpipe->vertex_tex_cache[i], view);
205    }
206
207    softpipe->num_vertex_sampler_views = num;
208
209    softpipe->dirty |= SP_NEW_TEXTURE;
210 }
211
212
213 /**
214  * Find/create an sp_sampler_varient object for sampling the given texture,
215  * sampler and tex unit.
216  *
217  * Note that the tex unit is significant.  We can't re-use a sampler
218  * varient for multiple texture units because the sampler varient contains
219  * the texture object pointer.  If the texture object pointer were stored
220  * somewhere outside the sampler varient, we could re-use samplers for
221  * multiple texture units.
222  */
223 static struct sp_sampler_varient *
224 get_sampler_varient( unsigned unit,
225                      struct sp_sampler *sampler,
226                      struct pipe_texture *texture,
227                      unsigned processor )
228 {
229    struct softpipe_texture *sp_texture = softpipe_texture(texture);
230    struct sp_sampler_varient *v = NULL;
231    union sp_sampler_key key;
232
233    /* if this fails, widen the key.unit field and update this assertion */
234    assert(PIPE_MAX_SAMPLERS <= 16);
235
236    key.bits.target = sp_texture->base.target;
237    key.bits.is_pot = sp_texture->pot;
238    key.bits.processor = processor;
239    key.bits.unit = unit;
240    key.bits.pad = 0;
241
242    if (sampler->current && 
243        key.value == sampler->current->key.value) {
244       v = sampler->current;
245    }
246
247    if (v == NULL) {
248       for (v = sampler->varients; v; v = v->next)
249          if (v->key.value == key.value)
250             break;
251
252       if (v == NULL) {
253          v = sp_create_sampler_varient( &sampler->base, key );
254          v->next = sampler->varients;
255          sampler->varients = v;
256       }
257    }
258    
259    sampler->current = v;
260    return v;
261 }
262
263
264
265
266 void
267 softpipe_reset_sampler_varients(struct softpipe_context *softpipe)
268 {
269    int i;
270
271    /* It's a bit hard to build these samplers ahead of time -- don't
272     * really know which samplers are going to be used for vertex and
273     * fragment programs.
274     */
275    for (i = 0; i <= softpipe->vs->max_sampler; i++) {
276       if (softpipe->vertex_samplers[i]) {
277          struct pipe_texture *texture = NULL;
278
279          if (softpipe->vertex_sampler_views[i]) {
280             texture = softpipe->vertex_sampler_views[i]->texture;
281          }
282
283          softpipe->tgsi.vert_samplers_list[i] = 
284             get_sampler_varient( i,
285                                  sp_sampler(softpipe->vertex_samplers[i]),
286                                  texture,
287                                  TGSI_PROCESSOR_VERTEX );
288
289          sp_sampler_varient_bind_texture( softpipe->tgsi.vert_samplers_list[i], 
290                                           softpipe->vertex_tex_cache[i],
291                                           texture );
292       }
293    }
294
295    for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
296       if (softpipe->sampler[i]) {
297          struct pipe_texture *texture = NULL;
298
299          if (softpipe->sampler_views[i]) {
300             texture = softpipe->sampler_views[i]->texture;
301          }
302
303          softpipe->tgsi.frag_samplers_list[i] =
304             get_sampler_varient( i,
305                                  sp_sampler(softpipe->sampler[i]),
306                                  texture,
307                                  TGSI_PROCESSOR_FRAGMENT );
308
309          sp_sampler_varient_bind_texture( softpipe->tgsi.frag_samplers_list[i], 
310                                           softpipe->tex_cache[i],
311                                           texture );
312       }
313    }
314 }
315
316
317
318 void
319 softpipe_delete_sampler_state(struct pipe_context *pipe,
320                               void *sampler)
321 {
322    struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler;
323    struct sp_sampler_varient *v, *tmp;
324
325    for (v = sp_sampler->varients; v; v = tmp) {
326       tmp = v->next;
327       sp_sampler_varient_destroy(v);
328    }
329
330    FREE( sampler );
331 }
332
333
334