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