• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2003 VMware, Inc.
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 VMWARE 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 #include "util/u_inlines.h"
29 #include "util/u_math.h"
30 #include "util/u_memory.h"
31 #include "pipe/p_shader_tokens.h"
32 #include "draw/draw_context.h"
33 #include "draw/draw_vertex.h"
34 #include "sp_context.h"
35 #include "sp_screen.h"
36 #include "sp_state.h"
37 #include "sp_texture.h"
38 #include "sp_tex_sample.h"
39 #include "sp_tex_tile_cache.h"
40 
41 
42 /**
43  * Mark the current vertex layout as "invalid".
44  * We'll validate the vertex layout later, when we start to actually
45  * render a point or line or tri.
46  */
47 static void
invalidate_vertex_layout(struct softpipe_context * softpipe)48 invalidate_vertex_layout(struct softpipe_context *softpipe)
49 {
50    softpipe->setup_info.valid =  0;
51 }
52 
53 
54 /**
55  * The vertex info describes how to convert the post-transformed vertices
56  * (simple float[][4]) used by the 'draw' module into vertices for
57  * rasterization.
58  *
59  * This function validates the vertex layout.
60  */
61 static void
softpipe_compute_vertex_info(struct softpipe_context * softpipe)62 softpipe_compute_vertex_info(struct softpipe_context *softpipe)
63 {
64    struct sp_setup_info *sinfo = &softpipe->setup_info;
65 
66    if (sinfo->valid == 0) {
67       const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
68       struct vertex_info *vinfo = &softpipe->vertex_info;
69       uint i;
70       int vs_index;
71       /*
72        * This doesn't quite work right (wrt face injection, prim id,
73        * wide points) - hit a couple assertions, misrenderings plus
74        * memory corruption. Albeit could fix (the former two) by calling
75        * this "more often" (rasterizer changes etc.). (The latter would
76        * need to be included in draw_prepare_shader_outputs, but it looks
77        * like that would potentially allocate quite some unused additional
78        * vertex outputs.)
79        * draw_prepare_shader_outputs(softpipe->draw);
80        */
81 
82       /*
83        * Those can't actually be 0 (because pos is always at 0).
84        * But use ints anyway to avoid confusion (in vs outputs, they
85        * can very well be at pos 0).
86        */
87       softpipe->viewport_index_slot = -1;
88       softpipe->layer_slot = -1;
89       softpipe->psize_slot = -1;
90 
91       vinfo->num_attribs = 0;
92 
93       /*
94        * Put position always first (setup needs it there).
95        */
96       vs_index = draw_find_shader_output(softpipe->draw,
97                                          TGSI_SEMANTIC_POSITION, 0);
98 
99       draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
100 
101       /*
102        * Match FS inputs against VS outputs, emitting the necessary
103        * attributes.
104        */
105       for (i = 0; i < fsInfo->num_inputs; i++) {
106          enum sp_interp_mode interp = SP_INTERP_LINEAR;
107 
108          switch (fsInfo->input_interpolate[i]) {
109          case TGSI_INTERPOLATE_CONSTANT:
110             interp = SP_INTERP_CONSTANT;
111             break;
112          case TGSI_INTERPOLATE_LINEAR:
113             interp = SP_INTERP_LINEAR;
114             break;
115          case TGSI_INTERPOLATE_PERSPECTIVE:
116             interp = SP_INTERP_PERSPECTIVE;
117             break;
118          case TGSI_INTERPOLATE_COLOR:
119             assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
120             break;
121          default:
122             assert(0);
123          }
124 
125          switch (fsInfo->input_semantic_name[i]) {
126          case TGSI_SEMANTIC_POSITION:
127             interp = SP_INTERP_POS;
128             break;
129 
130          case TGSI_SEMANTIC_COLOR:
131             if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
132                if (softpipe->rasterizer->flatshade)
133                   interp = SP_INTERP_CONSTANT;
134                else
135                   interp = SP_INTERP_PERSPECTIVE;
136             }
137             break;
138          }
139 
140          /*
141           * Search for each input in current vs output:
142           */
143          vs_index = draw_find_shader_output(softpipe->draw,
144                                             fsInfo->input_semantic_name[i],
145                                             fsInfo->input_semantic_index[i]);
146 
147          if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
148              vs_index == -1) {
149             /*
150              * try and find a bcolor.
151              * Note that if there's both front and back color, draw will
152              * have copied back to front color already.
153              */
154             vs_index = draw_find_shader_output(softpipe->draw,
155                                                TGSI_SEMANTIC_BCOLOR,
156                                                fsInfo->input_semantic_index[i]);
157          }
158 
159          sinfo->attrib[i].interp = interp;
160          /* extremely pointless index map */
161          sinfo->attrib[i].src_index = i + 1;
162          /*
163           * For vp index and layer, if the fs requires them but the vs doesn't
164           * provide them, draw (vbuf) will give us the required 0 (slot -1).
165           * (This means in this case we'll also use those slots in setup, which
166           * isn't necessary but they'll contain the correct (0) value.)
167           */
168          if (fsInfo->input_semantic_name[i] ==
169                     TGSI_SEMANTIC_VIEWPORT_INDEX) {
170             softpipe->viewport_index_slot = (int)vinfo->num_attribs;
171             draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
172          } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_LAYER) {
173             softpipe->layer_slot = (int)vinfo->num_attribs;
174             draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
175             /*
176              * Note that we'd actually want to skip position (as we won't use
177              * the attribute in the fs) but can't. The reason is that we don't
178              * actually have an input/output map for setup (even though it looks
179              * like we do...). Could adjust for this though even without a map.
180              */
181          } else {
182             /*
183              * Note that we'd actually want to skip position (as we won't use
184              * the attribute in the fs) but can't. The reason is that we don't
185              * actually have an input/output map for setup (even though it looks
186              * like we do...). Could adjust for this though even without a map.
187              */
188             draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
189          }
190       }
191 
192       /* Figure out if we need pointsize as well.
193        */
194       vs_index = draw_find_shader_output(softpipe->draw,
195                                          TGSI_SEMANTIC_PSIZE, 0);
196 
197       if (vs_index >= 0) {
198          softpipe->psize_slot = (int)vinfo->num_attribs;
199          draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
200       }
201 
202       /* Figure out if we need viewport index (if it wasn't already in fs input) */
203       if (softpipe->viewport_index_slot < 0) {
204          vs_index = draw_find_shader_output(softpipe->draw,
205                                             TGSI_SEMANTIC_VIEWPORT_INDEX,
206                                             0);
207          if (vs_index >= 0) {
208             softpipe->viewport_index_slot =(int)vinfo->num_attribs;
209             draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
210          }
211       }
212 
213       /* Figure out if we need layer (if it wasn't already in fs input) */
214       if (softpipe->layer_slot < 0) {
215          vs_index = draw_find_shader_output(softpipe->draw,
216                                             TGSI_SEMANTIC_LAYER,
217                                             0);
218          if (vs_index >= 0) {
219             softpipe->layer_slot = (int)vinfo->num_attribs;
220             draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index);
221          }
222       }
223 
224       draw_compute_vertex_size(vinfo);
225       softpipe->setup_info.valid = 1;
226    }
227    return;
228 }
229 
230 
231 /**
232  * Called from vbuf module.
233  *
234  * This will trigger validation of the vertex layout (and also compute
235  * the required information for setup).
236  */
237 struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context * softpipe)238 softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
239 {
240    softpipe_compute_vertex_info(softpipe);
241    return &softpipe->vertex_info;
242 }
243 
244 
245 /**
246  * Recompute cliprect from scissor bounds, scissor enable and surface size.
247  */
248 static void
compute_cliprect(struct softpipe_context * sp)249 compute_cliprect(struct softpipe_context *sp)
250 {
251    unsigned i;
252    /* SP_NEW_FRAMEBUFFER
253     */
254    uint surfWidth = sp->framebuffer.width;
255    uint surfHeight = sp->framebuffer.height;
256 
257    for (i = 0; i < PIPE_MAX_VIEWPORTS; i++) {
258       /* SP_NEW_RASTERIZER
259        */
260       if (sp->rasterizer->scissor) {
261 
262          /* SP_NEW_SCISSOR
263           *
264           * clip to scissor rect:
265           */
266          sp->cliprect[i].minx = MAX2(sp->scissors[i].minx, 0);
267          sp->cliprect[i].miny = MAX2(sp->scissors[i].miny, 0);
268          sp->cliprect[i].maxx = MIN2(sp->scissors[i].maxx, surfWidth);
269          sp->cliprect[i].maxy = MIN2(sp->scissors[i].maxy, surfHeight);
270       }
271       else {
272          /* clip to surface bounds */
273          sp->cliprect[i].minx = 0;
274          sp->cliprect[i].miny = 0;
275          sp->cliprect[i].maxx = surfWidth;
276          sp->cliprect[i].maxy = surfHeight;
277       }
278    }
279 }
280 
281 
282 static void
set_shader_sampler(struct softpipe_context * softpipe,enum pipe_shader_type shader,int max_sampler)283 set_shader_sampler(struct softpipe_context *softpipe,
284                    enum pipe_shader_type shader,
285                    int max_sampler)
286 {
287    int i;
288    for (i = 0; i <= max_sampler; i++) {
289       softpipe->tgsi.sampler[shader]->sp_sampler[i] =
290          (struct sp_sampler *)(softpipe->samplers[shader][i]);
291    }
292 }
293 
294 void
softpipe_update_compute_samplers(struct softpipe_context * softpipe)295 softpipe_update_compute_samplers(struct softpipe_context *softpipe)
296 {
297    set_shader_sampler(softpipe, PIPE_SHADER_COMPUTE, softpipe->cs->max_sampler);
298 }
299 
300 static void
update_tgsi_samplers(struct softpipe_context * softpipe)301 update_tgsi_samplers( struct softpipe_context *softpipe )
302 {
303    unsigned i, sh;
304 
305    set_shader_sampler(softpipe, PIPE_SHADER_VERTEX,
306                       softpipe->vs->max_sampler);
307    set_shader_sampler(softpipe, PIPE_SHADER_FRAGMENT,
308                       softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
309    if (softpipe->gs) {
310       set_shader_sampler(softpipe, PIPE_SHADER_GEOMETRY,
311                          softpipe->gs->max_sampler);
312    }
313 
314    /* XXX is this really necessary here??? */
315    for (sh = 0; sh < ARRAY_SIZE(softpipe->tex_cache); sh++) {
316       for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
317          struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
318          if (tc && tc->texture) {
319             struct softpipe_resource *spt = softpipe_resource(tc->texture);
320             if (spt->timestamp != tc->timestamp) {
321                sp_tex_tile_cache_validate_texture( tc );
322                /*
323                  _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
324                */
325                tc->timestamp = spt->timestamp;
326             }
327          }
328       }
329    }
330 }
331 
332 
333 static void
update_fragment_shader(struct softpipe_context * softpipe,unsigned prim)334 update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
335 {
336    struct sp_fragment_shader_variant_key key;
337 
338    memset(&key, 0, sizeof(key));
339 
340    if (softpipe->fs) {
341       softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
342                                                       softpipe->fs, &key);
343 
344       /* prepare the TGSI interpreter for FS execution */
345       softpipe->fs_variant->prepare(softpipe->fs_variant,
346                                     softpipe->fs_machine,
347                                     (struct tgsi_sampler *) softpipe->
348                                     tgsi.sampler[PIPE_SHADER_FRAGMENT],
349                                     (struct tgsi_image *)softpipe->tgsi.image[PIPE_SHADER_FRAGMENT],
350                                     (struct tgsi_buffer *)softpipe->tgsi.buffer[PIPE_SHADER_FRAGMENT]);
351    }
352    else {
353       softpipe->fs_variant = NULL;
354    }
355 
356    /* This would be the logical place to pass the fragment shader
357     * to the draw module.  However, doing this here, during state
358     * validation, causes problems with the 'draw' module helpers for
359     * wide/AA/stippled lines.
360     * In principle, the draw's fragment shader should be per-variant
361     * but that doesn't work.  So we use a single draw fragment shader
362     * per fragment shader, not per variant.
363     */
364 #if 0
365    if (softpipe->fs_variant) {
366       draw_bind_fragment_shader(softpipe->draw,
367                                 softpipe->fs_variant->draw_shader);
368    }
369    else {
370       draw_bind_fragment_shader(softpipe->draw, NULL);
371    }
372 #endif
373 }
374 
375 
376 /* Hopefully this will remain quite simple, otherwise need to pull in
377  * something like the gallium frontend mechanism.
378  */
379 void
softpipe_update_derived(struct softpipe_context * softpipe,unsigned prim)380 softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
381 {
382    struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
383 
384    /* Check for updated textures.
385     */
386    if (softpipe->tex_timestamp != sp_screen->timestamp) {
387       softpipe->tex_timestamp = sp_screen->timestamp;
388       softpipe->dirty |= SP_NEW_TEXTURE;
389    }
390 
391    if (softpipe->dirty & (SP_NEW_RASTERIZER |
392                           SP_NEW_FS))
393       update_fragment_shader(softpipe, prim);
394 
395    /* TODO: this looks suboptimal */
396    if (softpipe->dirty & (SP_NEW_SAMPLER |
397                           SP_NEW_TEXTURE |
398                           SP_NEW_FS |
399                           SP_NEW_VS))
400       update_tgsi_samplers( softpipe );
401 
402    if (softpipe->dirty & (SP_NEW_RASTERIZER |
403                           SP_NEW_FS |
404                           SP_NEW_VS))
405       invalidate_vertex_layout( softpipe );
406 
407    if (softpipe->dirty & (SP_NEW_SCISSOR |
408                           SP_NEW_RASTERIZER |
409                           SP_NEW_FRAMEBUFFER))
410       compute_cliprect(softpipe);
411 
412    if (softpipe->dirty & (SP_NEW_BLEND |
413                           SP_NEW_DEPTH_STENCIL_ALPHA |
414                           SP_NEW_FRAMEBUFFER |
415                           SP_NEW_FS))
416       sp_build_quad_pipeline(softpipe);
417 
418    softpipe->dirty = 0;
419 }
420