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