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