Tizen 2.0 Release
[profile/ivi/osmesa.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 #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
44 struct sp_sampler {
45    struct pipe_sampler_state base;
46    struct sp_sampler_variant *variants;
47    struct sp_sampler_variant *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 static 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->variants = NULL;
64
65    return (void *)sp_sampler;
66 }
67
68
69 static void
70 softpipe_bind_fragment_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_fragment_samplers &&
80        !memcmp(softpipe->fragment_samplers, sampler, num * sizeof(void *)))
81       return;
82
83    draw_flush(softpipe->draw);
84
85    for (i = 0; i < num; ++i)
86       softpipe->fragment_samplers[i] = sampler[i];
87    for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
88       softpipe->fragment_samplers[i] = NULL;
89
90    softpipe->num_fragment_samplers = num;
91
92    softpipe->dirty |= SP_NEW_SAMPLER;
93 }
94
95
96 static 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    draw_set_samplers(softpipe->draw,
121                      softpipe->vertex_samplers,
122                      softpipe->num_vertex_samplers);
123
124    softpipe->dirty |= SP_NEW_SAMPLER;
125 }
126
127 static void
128 softpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
129                                       unsigned num_samplers,
130                                       void **samplers)
131 {
132    struct softpipe_context *softpipe = softpipe_context(pipe);
133    unsigned i;
134
135    assert(num_samplers <= PIPE_MAX_GEOMETRY_SAMPLERS);
136
137    /* Check for no-op */
138    if (num_samplers == softpipe->num_geometry_samplers &&
139        !memcmp(softpipe->geometry_samplers, samplers, num_samplers * sizeof(void *)))
140       return;
141
142    draw_flush(softpipe->draw);
143
144    for (i = 0; i < num_samplers; ++i)
145       softpipe->geometry_samplers[i] = samplers[i];
146    for (i = num_samplers; i < PIPE_MAX_GEOMETRY_SAMPLERS; ++i)
147       softpipe->geometry_samplers[i] = NULL;
148
149    softpipe->num_geometry_samplers = num_samplers;
150
151    softpipe->dirty |= SP_NEW_SAMPLER;
152 }
153
154
155 static struct pipe_sampler_view *
156 softpipe_create_sampler_view(struct pipe_context *pipe,
157                              struct pipe_resource *resource,
158                              const struct pipe_sampler_view *templ)
159 {
160    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
161
162    if (view) {
163       *view = *templ;
164       view->reference.count = 1;
165       view->texture = NULL;
166       pipe_resource_reference(&view->texture, resource);
167       view->context = pipe;
168    }
169
170    return view;
171 }
172
173
174 static void
175 softpipe_sampler_view_destroy(struct pipe_context *pipe,
176                               struct pipe_sampler_view *view)
177 {
178    pipe_resource_reference(&view->texture, NULL);
179    FREE(view);
180 }
181
182
183 static void
184 softpipe_set_fragment_sampler_views(struct pipe_context *pipe,
185                                     unsigned num,
186                                     struct pipe_sampler_view **views)
187 {
188    struct softpipe_context *softpipe = softpipe_context(pipe);
189    uint i;
190
191    assert(num <= PIPE_MAX_SAMPLERS);
192
193    /* Check for no-op */
194    if (num == softpipe->num_fragment_sampler_views &&
195        !memcmp(softpipe->fragment_sampler_views, views,
196                num * sizeof(struct pipe_sampler_view *)))
197       return;
198
199    draw_flush(softpipe->draw);
200
201    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
202       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
203
204       pipe_sampler_view_reference(&softpipe->fragment_sampler_views[i], view);
205       sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[i], view);
206    }
207
208    softpipe->num_fragment_sampler_views = num;
209
210    softpipe->dirty |= SP_NEW_TEXTURE;
211 }
212
213
214 static void
215 softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
216                                   unsigned num,
217                                   struct pipe_sampler_view **views)
218 {
219    struct softpipe_context *softpipe = softpipe_context(pipe);
220    uint i;
221
222    assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
223
224    /* Check for no-op */
225    if (num == softpipe->num_vertex_sampler_views &&
226        !memcmp(softpipe->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
227       return;
228    }
229
230    draw_flush(softpipe->draw);
231
232    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
233       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
234
235       pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], view);
236       sp_tex_tile_cache_set_sampler_view(softpipe->vertex_tex_cache[i], view);
237    }
238
239    softpipe->num_vertex_sampler_views = num;
240
241    draw_set_sampler_views(softpipe->draw,
242                           softpipe->vertex_sampler_views,
243                           softpipe->num_vertex_sampler_views);
244
245    softpipe->dirty |= SP_NEW_TEXTURE;
246 }
247
248
249 static void
250 softpipe_set_geometry_sampler_views(struct pipe_context *pipe,
251                                     unsigned num,
252                                     struct pipe_sampler_view **views)
253 {
254    struct softpipe_context *softpipe = softpipe_context(pipe);
255    uint i;
256
257    assert(num <= PIPE_MAX_GEOMETRY_SAMPLERS);
258
259    /* Check for no-op */
260    if (num == softpipe->num_geometry_sampler_views &&
261        !memcmp(softpipe->geometry_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
262       return;
263    }
264
265    draw_flush(softpipe->draw);
266
267    for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) {
268       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
269
270       pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], view);
271       sp_tex_tile_cache_set_sampler_view(softpipe->geometry_tex_cache[i], view);
272    }
273
274    softpipe->num_geometry_sampler_views = num;
275
276    softpipe->dirty |= SP_NEW_TEXTURE;
277 }
278
279
280 /**
281  * Find/create an sp_sampler_variant object for sampling the given texture,
282  * sampler and tex unit.
283  *
284  * Note that the tex unit is significant.  We can't re-use a sampler
285  * variant for multiple texture units because the sampler variant contains
286  * the texture object pointer.  If the texture object pointer were stored
287  * somewhere outside the sampler variant, we could re-use samplers for
288  * multiple texture units.
289  */
290 static struct sp_sampler_variant *
291 get_sampler_variant( unsigned unit,
292                      struct sp_sampler *sampler,
293                      struct pipe_sampler_view *view,
294                      unsigned processor )
295 {
296    struct softpipe_resource *sp_texture = softpipe_resource(view->texture);
297    struct sp_sampler_variant *v = NULL;
298    union sp_sampler_key key;
299
300    /* if this fails, widen the key.unit field and update this assertion */
301    assert(PIPE_MAX_SAMPLERS <= 16);
302
303    key.bits.target = sp_texture->base.target;
304    key.bits.is_pot = sp_texture->pot;
305    key.bits.processor = processor;
306    key.bits.unit = unit;
307    key.bits.swizzle_r = view->swizzle_r;
308    key.bits.swizzle_g = view->swizzle_g;
309    key.bits.swizzle_b = view->swizzle_b;
310    key.bits.swizzle_a = view->swizzle_a;
311    key.bits.pad = 0;
312
313    if (sampler->current && 
314        key.value == sampler->current->key.value) {
315       v = sampler->current;
316    }
317
318    if (v == NULL) {
319       for (v = sampler->variants; v; v = v->next)
320          if (v->key.value == key.value)
321             break;
322
323       if (v == NULL) {
324          v = sp_create_sampler_variant( &sampler->base, key );
325          v->next = sampler->variants;
326          sampler->variants = v;
327       }
328    }
329    
330    sampler->current = v;
331    return v;
332 }
333
334
335 void
336 softpipe_reset_sampler_variants(struct softpipe_context *softpipe)
337 {
338    int i;
339
340    /* It's a bit hard to build these samplers ahead of time -- don't
341     * really know which samplers are going to be used for vertex and
342     * fragment programs.
343     */
344    for (i = 0; i <= softpipe->vs->max_sampler; i++) {
345       if (softpipe->vertex_samplers[i]) {
346          softpipe->tgsi.vert_samplers_list[i] = 
347             get_sampler_variant( i,
348                                  sp_sampler(softpipe->vertex_samplers[i]),
349                                  softpipe->vertex_sampler_views[i],
350                                  TGSI_PROCESSOR_VERTEX );
351
352          sp_sampler_variant_bind_view( softpipe->tgsi.vert_samplers_list[i],
353                                        softpipe->vertex_tex_cache[i],
354                                        softpipe->vertex_sampler_views[i] );
355       }
356    }
357
358    if (softpipe->gs) {
359       for (i = 0; i <= softpipe->gs->max_sampler; i++) {
360          if (softpipe->geometry_samplers[i]) {
361             softpipe->tgsi.geom_samplers_list[i] =
362                get_sampler_variant(
363                   i,
364                   sp_sampler(softpipe->geometry_samplers[i]),
365                   softpipe->geometry_sampler_views[i],
366                   TGSI_PROCESSOR_GEOMETRY );
367
368             sp_sampler_variant_bind_view(
369                softpipe->tgsi.geom_samplers_list[i],
370                softpipe->geometry_tex_cache[i],
371                softpipe->geometry_sampler_views[i] );
372          }
373       }
374    }
375
376    for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) {
377       if (softpipe->fragment_samplers[i]) {
378          softpipe->tgsi.frag_samplers_list[i] =
379             get_sampler_variant( i,
380                                  sp_sampler(softpipe->fragment_samplers[i]),
381                                  softpipe->fragment_sampler_views[i],
382                                  TGSI_PROCESSOR_FRAGMENT );
383
384          sp_sampler_variant_bind_view( softpipe->tgsi.frag_samplers_list[i],
385                                        softpipe->fragment_tex_cache[i],
386                                        softpipe->fragment_sampler_views[i] );
387       }
388    }
389 }
390
391 static void
392 softpipe_delete_sampler_state(struct pipe_context *pipe,
393                               void *sampler)
394 {
395    struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler;
396    struct sp_sampler_variant *v, *tmp;
397
398    for (v = sp_sampler->variants; v; v = tmp) {
399       tmp = v->next;
400       sp_sampler_variant_destroy(v);
401    }
402
403    FREE( sampler );
404 }
405
406
407 void
408 softpipe_init_sampler_funcs(struct pipe_context *pipe)
409 {
410    pipe->create_sampler_state = softpipe_create_sampler_state;
411    pipe->bind_fragment_sampler_states  = softpipe_bind_fragment_sampler_states;
412    pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states;
413    pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states;
414    pipe->delete_sampler_state = softpipe_delete_sampler_state;
415
416    pipe->set_fragment_sampler_views = softpipe_set_fragment_sampler_views;
417    pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views;
418    pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views;
419
420    pipe->create_sampler_view = softpipe_create_sampler_view;
421    pipe->sampler_view_destroy = softpipe_sampler_view_destroy;
422 }
423