Merge branch 'llvm-cliptest-viewport'
[mesa.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 = 0; 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 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 }