OSDN Git Service

softpipe: draw_find_shader_output returns -1 on invalid outputs
[android-x86/external-mesa.git] / src / gallium / drivers / softpipe / sp_state_derived.c
1 /**************************************************************************
2  * 
3  * Copyright 2003 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 #include "util/u_inlines.h"
29 #include "util/u_math.h"
30 #include "util/u_memory.h"
31 #include "util/u_pstipple.h"
32 #include "pipe/p_shader_tokens.h"
33 #include "draw/draw_context.h"
34 #include "draw/draw_vertex.h"
35 #include "sp_context.h"
36 #include "sp_screen.h"
37 #include "sp_state.h"
38 #include "sp_texture.h"
39 #include "sp_tex_sample.h"
40 #include "sp_tex_tile_cache.h"
41
42
43 /**
44  * Mark the current vertex layout as "invalid".
45  * We'll validate the vertex layout later, when we start to actually
46  * render a point or line or tri.
47  */
48 static void
49 invalidate_vertex_layout(struct softpipe_context *softpipe)
50 {
51    softpipe->vertex_info.num_attribs =  0;
52 }
53
54
55 /**
56  * The vertex info describes how to convert the post-transformed vertices
57  * (simple float[][4]) used by the 'draw' module into vertices for
58  * rasterization.
59  *
60  * This function validates the vertex layout and returns a pointer to a
61  * vertex_info object.
62  */
63 struct vertex_info *
64 softpipe_get_vertex_info(struct softpipe_context *softpipe)
65 {
66    struct vertex_info *vinfo = &softpipe->vertex_info;
67
68    if (vinfo->num_attribs == 0) {
69       /* compute vertex layout now */
70       const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
71       struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
72       const uint num = draw_num_shader_outputs(softpipe->draw);
73       uint i;
74
75       /* Tell draw_vbuf to simply emit the whole post-xform vertex
76        * as-is.  No longer any need to try and emit draw vertex_header
77        * info.
78        */
79       vinfo_vbuf->num_attribs = 0;
80       for (i = 0; i < num; i++) {
81          draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
82       }
83       draw_compute_vertex_size(vinfo_vbuf);
84
85       /*
86        * Loop over fragment shader inputs, searching for the matching output
87        * from the vertex shader.
88        */
89       vinfo->num_attribs = 0;
90       for (i = 0; i < fsInfo->num_inputs; i++) {
91          int src;
92          enum interp_mode interp = INTERP_LINEAR;
93
94          switch (fsInfo->input_interpolate[i]) {
95          case TGSI_INTERPOLATE_CONSTANT:
96             interp = INTERP_CONSTANT;
97             break;
98          case TGSI_INTERPOLATE_LINEAR:
99             interp = INTERP_LINEAR;
100             break;
101          case TGSI_INTERPOLATE_PERSPECTIVE:
102             interp = INTERP_PERSPECTIVE;
103             break;
104          case TGSI_INTERPOLATE_COLOR:
105             assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
106             break;
107          default:
108             assert(0);
109          }
110
111          switch (fsInfo->input_semantic_name[i]) {
112          case TGSI_SEMANTIC_POSITION:
113             interp = INTERP_POS;
114             break;
115
116          case TGSI_SEMANTIC_COLOR:
117             if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
118                if (softpipe->rasterizer->flatshade)
119                   interp = INTERP_CONSTANT;
120                else
121                   interp = INTERP_PERSPECTIVE;
122             }
123             break;
124          }
125
126          /* this includes texcoords and varying vars */
127          src = draw_find_shader_output(softpipe->draw,
128                                        fsInfo->input_semantic_name[i],
129                                        fsInfo->input_semantic_index[i]);
130          if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == -1)
131            /* try and find a bcolor */
132            src = draw_find_shader_output(softpipe->draw,
133                                          TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);
134
135          draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
136       }
137
138       softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
139                                                  TGSI_SEMANTIC_PSIZE, 0);
140       if (softpipe->psize_slot >= 0) {
141          draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
142                                softpipe->psize_slot);
143       }
144
145       draw_compute_vertex_size(vinfo);
146    }
147
148    return vinfo;
149 }
150
151
152 /**
153  * Called from vbuf module.
154  *
155  * Note that there's actually two different vertex layouts in softpipe.
156  *
157  * The normal one is computed in softpipe_get_vertex_info() above and is
158  * used by the point/line/tri "setup" code.
159  *
160  * The other one (this one) is only used by the vbuf module (which is
161  * not normally used by default but used in testing).  For the vbuf module,
162  * we basically want to pass-through the draw module's vertex layout as-is.
163  * When the softpipe vbuf code begins drawing, the normal vertex layout
164  * will come into play again.
165  */
166 struct vertex_info *
167 softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
168 {
169    (void) softpipe_get_vertex_info(softpipe);
170    return &softpipe->vertex_info_vbuf;
171 }
172
173
174 /**
175  * Recompute cliprect from scissor bounds, scissor enable and surface size.
176  */
177 static void
178 compute_cliprect(struct softpipe_context *sp)
179 {
180    /* SP_NEW_FRAMEBUFFER
181     */
182    uint surfWidth = sp->framebuffer.width;
183    uint surfHeight = sp->framebuffer.height;
184
185    /* SP_NEW_RASTERIZER
186     */
187    if (sp->rasterizer->scissor) {
188
189       /* SP_NEW_SCISSOR
190        *
191        * clip to scissor rect:
192        */
193       sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
194       sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
195       sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
196       sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
197    }
198    else {
199       /* clip to surface bounds */
200       sp->cliprect.minx = 0;
201       sp->cliprect.miny = 0;
202       sp->cliprect.maxx = surfWidth;
203       sp->cliprect.maxy = surfHeight;
204    }
205 }
206
207
208 static void
209 set_shader_sampler(struct softpipe_context *softpipe,
210                    unsigned shader,
211                    int max_sampler)
212 {
213    int i;
214    for (i = 0; i <= max_sampler; i++) {
215       softpipe->tgsi.sampler[shader]->sp_sampler[i] =
216          (struct sp_sampler *)(softpipe->samplers[shader][i]);
217    }
218 }
219
220 static void
221 update_tgsi_samplers( struct softpipe_context *softpipe )
222 {
223    unsigned i, sh;
224
225    set_shader_sampler(softpipe, PIPE_SHADER_VERTEX,
226                       softpipe->vs->max_sampler);
227    set_shader_sampler(softpipe, PIPE_SHADER_FRAGMENT,
228                       softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
229    if (softpipe->gs) {
230       set_shader_sampler(softpipe, PIPE_SHADER_GEOMETRY,
231                          softpipe->gs->max_sampler);
232    }
233
234    /* XXX is this really necessary here??? */
235    for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
236       for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
237          struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
238          if (tc && tc->texture) {
239             struct softpipe_resource *spt = softpipe_resource(tc->texture);
240             if (spt->timestamp != tc->timestamp) {
241                sp_tex_tile_cache_validate_texture( tc );
242                /*
243                  _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
244                */
245                tc->timestamp = spt->timestamp;
246             }
247          }
248       }
249    }
250 }
251
252
253 static void
254 update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
255 {
256    struct sp_fragment_shader_variant_key key;
257
258    memset(&key, 0, sizeof(key));
259
260    if (prim == PIPE_PRIM_TRIANGLES)
261       key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
262
263    if (softpipe->fs) {
264       softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
265                                                       softpipe->fs, &key);
266
267       /* prepare the TGSI interpreter for FS execution */
268       softpipe->fs_variant->prepare(softpipe->fs_variant, 
269                                     softpipe->fs_machine,
270                                     (struct tgsi_sampler *) softpipe->
271                                     tgsi.sampler[PIPE_SHADER_FRAGMENT]);
272    }
273    else {
274       softpipe->fs_variant = NULL;
275    }
276
277    /* This would be the logical place to pass the fragment shader
278     * to the draw module.  However, doing this here, during state
279     * validation, causes problems with the 'draw' module helpers for
280     * wide/AA/stippled lines.
281     * In principle, the draw's fragment shader should be per-variant
282     * but that doesn't work.  So we use a single draw fragment shader
283     * per fragment shader, not per variant.
284     */
285 #if 0
286    if (softpipe->fs_variant) {
287       draw_bind_fragment_shader(softpipe->draw,
288                                 softpipe->fs_variant->draw_shader);
289    }
290    else {
291       draw_bind_fragment_shader(softpipe->draw, NULL);
292    }
293 #endif
294 }
295
296
297 /**
298  * This should be called when the polygon stipple pattern changes.
299  * We create a new texture from the stipple pattern and create a new
300  * sampler view.
301  */
302 static void
303 update_polygon_stipple_pattern(struct softpipe_context *softpipe)
304 {
305    struct pipe_resource *tex;
306    struct pipe_sampler_view *view;
307
308    tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
309                                               softpipe->poly_stipple.stipple);
310    pipe_resource_reference(&softpipe->pstipple.texture, tex);
311    pipe_resource_reference(&tex, NULL);
312
313    view = util_pstipple_create_sampler_view(&softpipe->pipe,
314                                             softpipe->pstipple.texture);
315    pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
316    pipe_sampler_view_reference(&view, NULL);
317 }
318
319
320 /**
321  * Should be called when polygon stipple is enabled/disabled or when
322  * the fragment shader changes.
323  * We add/update the fragment sampler and sampler views to sample from
324  * the polygon stipple texture.  The texture unit that we use depends on
325  * the fragment shader (we need to use a unit not otherwise used by the
326  * shader).
327  */
328 static void
329 update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
330 {
331    if (prim == PIPE_PRIM_TRIANGLES &&
332        softpipe->fs_variant->key.polygon_stipple) {
333       const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
334
335       /* sampler state */
336       softpipe->samplers[PIPE_SHADER_FRAGMENT][unit] = softpipe->pstipple.sampler;
337
338       /* sampler view state */
339       softpipe_set_sampler_views(&softpipe->pipe, PIPE_SHADER_FRAGMENT,
340                                  unit, 1, &softpipe->pstipple.sampler_view);
341
342       softpipe->dirty |= SP_NEW_SAMPLER;
343    }
344 }
345
346
347 /* Hopefully this will remain quite simple, otherwise need to pull in
348  * something like the state tracker mechanism.
349  */
350 void
351 softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
352 {
353    struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
354
355    /* Check for updated textures.
356     */
357    if (softpipe->tex_timestamp != sp_screen->timestamp) {
358       softpipe->tex_timestamp = sp_screen->timestamp;
359       softpipe->dirty |= SP_NEW_TEXTURE;
360    }
361
362 #if DO_PSTIPPLE_IN_HELPER_MODULE
363    if (softpipe->dirty & SP_NEW_STIPPLE)
364       /* before updating samplers! */
365       update_polygon_stipple_pattern(softpipe);
366 #endif
367
368    if (softpipe->dirty & (SP_NEW_RASTERIZER |
369                           SP_NEW_FS))
370       update_fragment_shader(softpipe, prim);
371
372 #if DO_PSTIPPLE_IN_HELPER_MODULE
373    if (softpipe->dirty & (SP_NEW_RASTERIZER |
374                           SP_NEW_STIPPLE |
375                           SP_NEW_FS))
376       update_polygon_stipple_enable(softpipe, prim);
377 #endif
378
379    /* TODO: this looks suboptimal */
380    if (softpipe->dirty & (SP_NEW_SAMPLER |
381                           SP_NEW_TEXTURE |
382                           SP_NEW_FS | 
383                           SP_NEW_VS))
384       update_tgsi_samplers( softpipe );
385
386    if (softpipe->dirty & (SP_NEW_RASTERIZER |
387                           SP_NEW_FS |
388                           SP_NEW_VS))
389       invalidate_vertex_layout( softpipe );
390
391    if (softpipe->dirty & (SP_NEW_SCISSOR |
392                           SP_NEW_RASTERIZER |
393                           SP_NEW_FRAMEBUFFER))
394       compute_cliprect(softpipe);
395
396    if (softpipe->dirty & (SP_NEW_BLEND |
397                           SP_NEW_DEPTH_STENCIL_ALPHA |
398                           SP_NEW_FRAMEBUFFER |
399                           SP_NEW_FS))
400       sp_build_quad_pipeline(softpipe);
401
402    softpipe->dirty = 0;
403 }