Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / llvmpipe / lp_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_inlines.h"
33 #include "util/u_memory.h"
34
35 #include "draw/draw_context.h"
36
37 #include "lp_context.h"
38 #include "lp_screen.h"
39 #include "lp_state.h"
40 #include "lp_debug.h"
41 #include "state_tracker/sw_winsys.h"
42
43
44 static void *
45 llvmpipe_create_sampler_state(struct pipe_context *pipe,
46                               const struct pipe_sampler_state *sampler)
47 {
48    struct pipe_sampler_state *state = mem_dup(sampler, sizeof *sampler);
49
50    if (LP_PERF & PERF_NO_MIP_LINEAR) {
51       if (state->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
52          state->min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
53    }
54
55    if (LP_PERF & PERF_NO_MIPMAPS)
56       state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
57
58    if (LP_PERF & PERF_NO_LINEAR) {
59       state->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
60       state->min_img_filter = PIPE_TEX_FILTER_NEAREST;
61    }
62
63    return state;
64 }
65
66
67 static void
68 llvmpipe_bind_sampler_states(struct pipe_context *pipe,
69                              unsigned num, void **sampler)
70 {
71    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
72    unsigned i;
73
74    assert(num <= PIPE_MAX_SAMPLERS);
75
76    /* Check for no-op */
77    if (num == llvmpipe->num_samplers &&
78        !memcmp(llvmpipe->sampler, sampler, num * sizeof(void *)))
79       return;
80
81    draw_flush(llvmpipe->draw);
82
83    for (i = 0; i < num; ++i)
84       llvmpipe->sampler[i] = sampler[i];
85    for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
86       llvmpipe->sampler[i] = NULL;
87
88    llvmpipe->num_samplers = num;
89
90    llvmpipe->dirty |= LP_NEW_SAMPLER;
91 }
92
93
94 static void
95 llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
96                                     unsigned num_samplers,
97                                     void **samplers)
98 {
99    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
100    unsigned i;
101
102    assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS);
103
104    /* Check for no-op */
105    if (num_samplers == llvmpipe->num_vertex_samplers &&
106        !memcmp(llvmpipe->vertex_samplers, samplers, num_samplers * sizeof(void *)))
107       return;
108
109    draw_flush(llvmpipe->draw);
110
111    for (i = 0; i < num_samplers; ++i)
112       llvmpipe->vertex_samplers[i] = samplers[i];
113    for (i = num_samplers; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
114       llvmpipe->vertex_samplers[i] = NULL;
115
116    llvmpipe->num_vertex_samplers = num_samplers;
117
118    draw_set_samplers(llvmpipe->draw,
119                      llvmpipe->vertex_samplers,
120                      llvmpipe->num_vertex_samplers);
121
122    llvmpipe->dirty |= LP_NEW_SAMPLER;
123 }
124
125
126 static void
127 llvmpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
128                                       unsigned num, void **sampler)
129 {
130    /* XXX: implementation missing */
131 }
132
133 static void
134 llvmpipe_set_fragment_sampler_views(struct pipe_context *pipe,
135                                     unsigned num,
136                                     struct pipe_sampler_view **views)
137 {
138    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
139    uint i;
140
141    assert(num <= PIPE_MAX_SAMPLERS);
142
143    /* Check for no-op */
144    if (num == llvmpipe->num_fragment_sampler_views &&
145        !memcmp(llvmpipe->fragment_sampler_views, views, num * sizeof(struct pipe_sampler_view *)))
146       return;
147
148    draw_flush(llvmpipe->draw);
149
150    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
151       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
152
153       pipe_sampler_view_reference(&llvmpipe->fragment_sampler_views[i], view);
154    }
155
156    llvmpipe->num_fragment_sampler_views = num;
157
158    llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW;
159 }
160
161
162 static void
163 llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe,
164                                   unsigned num,
165                                   struct pipe_sampler_view **views)
166 {
167    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
168    uint i;
169
170    assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
171
172    /* Check for no-op */
173    if (num == llvmpipe->num_vertex_sampler_views &&
174        !memcmp(llvmpipe->vertex_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) {
175       return;
176    }
177
178    draw_flush(llvmpipe->draw);
179
180    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
181       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
182
183       pipe_sampler_view_reference(&llvmpipe->vertex_sampler_views[i], view);
184    }
185
186    llvmpipe->num_vertex_sampler_views = num;
187
188    draw_set_sampler_views(llvmpipe->draw,
189                           llvmpipe->vertex_sampler_views,
190                           llvmpipe->num_vertex_sampler_views);
191
192    llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW;
193 }
194
195
196 static void
197 llvmpipe_set_geometry_sampler_views(struct pipe_context *pipe,
198                                     unsigned num,
199                                     struct pipe_sampler_view **views)
200 {
201    /*XXX: implementation missing */
202 }
203
204 static struct pipe_sampler_view *
205 llvmpipe_create_sampler_view(struct pipe_context *pipe,
206                             struct pipe_resource *texture,
207                             const struct pipe_sampler_view *templ)
208 {
209    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
210
211    if (view) {
212       *view = *templ;
213       view->reference.count = 1;
214       view->texture = NULL;
215       pipe_resource_reference(&view->texture, texture);
216       view->context = pipe;
217    }
218
219    return view;
220 }
221
222
223 static void
224 llvmpipe_sampler_view_destroy(struct pipe_context *pipe,
225                               struct pipe_sampler_view *view)
226 {
227    pipe_resource_reference(&view->texture, NULL);
228    FREE(view);
229 }
230
231
232 static void
233 llvmpipe_delete_sampler_state(struct pipe_context *pipe,
234                               void *sampler)
235 {
236    FREE( sampler );
237 }
238
239
240 /**
241  * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
242  */
243 void
244 llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
245                                  unsigned num,
246                                  struct pipe_sampler_view **views)
247 {
248    unsigned i;
249    uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
250    uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
251    const void *data[PIPE_MAX_TEXTURE_LEVELS];
252
253    assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
254    if (!num)
255       return;
256
257    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
258       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
259
260       if (view) {
261          struct pipe_resource *tex = view->texture;
262          struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex);
263
264          /* We're referencing the texture's internal data, so save a
265           * reference to it.
266           */
267          pipe_resource_reference(&lp->mapped_vs_tex[i], tex);
268
269          if (!lp_tex->dt) {
270             /* regular texture - setup array of mipmap level pointers */
271             int j;
272             for (j = view->u.tex.first_level; j <= tex->last_level; j++) {
273                data[j] =
274                   llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ,
275                                                  LP_TEX_LAYOUT_LINEAR);
276                row_stride[j] = lp_tex->row_stride[j];
277                img_stride[j] = lp_tex->img_stride[j];
278             }
279          }
280          else {
281             /* display target texture/surface */
282             /*
283              * XXX: Where should this be unmapped?
284              */
285             struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen);
286             struct sw_winsys *winsys = screen->winsys;
287             data[0] = winsys->displaytarget_map(winsys, lp_tex->dt,
288                                                 PIPE_TRANSFER_READ);
289             row_stride[0] = lp_tex->row_stride[0];
290             img_stride[0] = lp_tex->img_stride[0];
291             assert(data[0]);
292          }
293          draw_set_mapped_texture(lp->draw,
294                                  i,
295                                  tex->width0, tex->height0, tex->depth0,
296                                  view->u.tex.first_level, tex->last_level,
297                                  row_stride, img_stride, data);
298       }
299    }
300 }
301
302 void
303 llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx)
304 {
305    unsigned i;
306    for (i = 0; i < Elements(ctx->mapped_vs_tex); i++) {
307       pipe_resource_reference(&ctx->mapped_vs_tex[i], NULL);
308    }
309 }
310
311 void
312 llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
313 {
314    llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state;
315
316    llvmpipe->pipe.bind_fragment_sampler_states  = llvmpipe_bind_sampler_states;
317    llvmpipe->pipe.bind_vertex_sampler_states  = llvmpipe_bind_vertex_sampler_states;
318    llvmpipe->pipe.bind_geometry_sampler_states  = llvmpipe_bind_geometry_sampler_states;
319    llvmpipe->pipe.set_fragment_sampler_views = llvmpipe_set_fragment_sampler_views;
320    llvmpipe->pipe.set_vertex_sampler_views = llvmpipe_set_vertex_sampler_views;
321    llvmpipe->pipe.set_geometry_sampler_views = llvmpipe_set_geometry_sampler_views;
322    llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view;
323    llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy;
324    llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
325 }