• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   /*
29    * Authors:
30    *   Keith Whitwell <keith@tungstengraphics.com>
31    */
32  
33  #include "draw/draw_private.h"
34  #include "draw/draw_pipe.h"
35  #include "util/u_debug.h"
36  
37  
38  
draw_pipeline_init(struct draw_context * draw)39  boolean draw_pipeline_init( struct draw_context *draw )
40  {
41     /* create pipeline stages */
42     draw->pipeline.wide_line  = draw_wide_line_stage( draw );
43     draw->pipeline.wide_point = draw_wide_point_stage( draw );
44     draw->pipeline.stipple   = draw_stipple_stage( draw );
45     draw->pipeline.unfilled  = draw_unfilled_stage( draw );
46     draw->pipeline.twoside   = draw_twoside_stage( draw );
47     draw->pipeline.offset    = draw_offset_stage( draw );
48     draw->pipeline.clip      = draw_clip_stage( draw );
49     draw->pipeline.flatshade = draw_flatshade_stage( draw );
50     draw->pipeline.cull      = draw_cull_stage( draw );
51     draw->pipeline.validate  = draw_validate_stage( draw );
52     draw->pipeline.first     = draw->pipeline.validate;
53  
54     if (!draw->pipeline.wide_line ||
55         !draw->pipeline.wide_point ||
56         !draw->pipeline.stipple ||
57         !draw->pipeline.unfilled ||
58         !draw->pipeline.twoside ||
59         !draw->pipeline.offset ||
60         !draw->pipeline.clip ||
61         !draw->pipeline.flatshade ||
62         !draw->pipeline.cull ||
63         !draw->pipeline.validate)
64        return FALSE;
65  
66     /* these defaults are oriented toward the needs of softpipe */
67     draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */
68     draw->pipeline.wide_line_threshold = 1.0f;
69     draw->pipeline.wide_point_sprites = FALSE;
70     draw->pipeline.line_stipple = TRUE;
71     draw->pipeline.point_sprite = TRUE;
72  
73     return TRUE;
74  }
75  
76  
draw_pipeline_destroy(struct draw_context * draw)77  void draw_pipeline_destroy( struct draw_context *draw )
78  {
79     if (draw->pipeline.wide_line)
80        draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
81     if (draw->pipeline.wide_point)
82        draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
83     if (draw->pipeline.stipple)
84        draw->pipeline.stipple->destroy( draw->pipeline.stipple );
85     if (draw->pipeline.unfilled)
86        draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
87     if (draw->pipeline.twoside)
88        draw->pipeline.twoside->destroy( draw->pipeline.twoside );
89     if (draw->pipeline.offset)
90        draw->pipeline.offset->destroy( draw->pipeline.offset );
91     if (draw->pipeline.clip)
92        draw->pipeline.clip->destroy( draw->pipeline.clip );
93     if (draw->pipeline.flatshade)
94        draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
95     if (draw->pipeline.cull)
96        draw->pipeline.cull->destroy( draw->pipeline.cull );
97     if (draw->pipeline.validate)
98        draw->pipeline.validate->destroy( draw->pipeline.validate );
99     if (draw->pipeline.aaline)
100        draw->pipeline.aaline->destroy( draw->pipeline.aaline );
101     if (draw->pipeline.aapoint)
102        draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
103     if (draw->pipeline.pstipple)
104        draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
105     if (draw->pipeline.rasterize)
106        draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
107  }
108  
109  
110  
111  /**
112   * Build primitive to render a point with vertex at v0.
113   */
do_point(struct draw_context * draw,const char * v0)114  static void do_point( struct draw_context *draw,
115  		      const char *v0 )
116  {
117     struct prim_header prim;
118  
119     prim.flags = 0;
120     prim.pad = 0;
121     prim.v[0] = (struct vertex_header *)v0;
122  
123     draw->pipeline.first->point( draw->pipeline.first, &prim );
124  }
125  
126  
127  /**
128   * Build primitive to render a line with vertices at v0, v1.
129   * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
130   */
do_line(struct draw_context * draw,ushort flags,const char * v0,const char * v1)131  static void do_line( struct draw_context *draw,
132                       ushort flags,
133  		     const char *v0,
134  		     const char *v1 )
135  {
136     struct prim_header prim;
137  
138     prim.flags = flags;
139     prim.pad = 0;
140     prim.v[0] = (struct vertex_header *)v0;
141     prim.v[1] = (struct vertex_header *)v1;
142  
143     draw->pipeline.first->line( draw->pipeline.first, &prim );
144  }
145  
146  
147  /**
148   * Build primitive to render a triangle with vertices at v0, v1, v2.
149   * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
150   */
do_triangle(struct draw_context * draw,ushort flags,char * v0,char * v1,char * v2)151  static void do_triangle( struct draw_context *draw,
152                           ushort flags,
153  			 char *v0,
154  			 char *v1,
155  			 char *v2 )
156  {
157     struct prim_header prim;
158  
159     prim.v[0] = (struct vertex_header *)v0;
160     prim.v[1] = (struct vertex_header *)v1;
161     prim.v[2] = (struct vertex_header *)v2;
162     prim.flags = flags;
163     prim.pad = 0;
164  
165     draw->pipeline.first->tri( draw->pipeline.first, &prim );
166  }
167  
168  
169  /*
170   * Set up macros for draw_pt_decompose.h template code.
171   * This code uses vertex indexes / elements.
172   */
173  
174  #define TRIANGLE(flags,i0,i1,i2)                                  \
175     do {                                                           \
176        do_triangle( draw,                                          \
177                     flags,                                         \
178                     verts + stride * (i0),                         \
179                     verts + stride * (i1),                         \
180                     verts + stride * (i2) );                       \
181     } while (0)
182  
183  #define LINE(flags,i0,i1)                                         \
184     do {                                                           \
185        do_line( draw,                                              \
186                 flags,                                             \
187                 verts + stride * (i0),                             \
188                 verts + stride * (i1) );                           \
189     } while (0)
190  
191  #define POINT(i0)                               \
192     do {                                         \
193        do_point( draw, verts + stride * (i0) );  \
194     } while (0)
195  
196  #define GET_ELT(idx) (elts[idx])
197  
198  #define FUNC pipe_run_elts
199  #define FUNC_VARS                               \
200      struct draw_context *draw,                  \
201      unsigned prim,                              \
202      unsigned prim_flags,                        \
203      struct vertex_header *vertices,             \
204      unsigned stride,                            \
205      const ushort *elts,                         \
206      unsigned count
207  
208  #include "draw_pt_decompose.h"
209  
210  
211  
212  /**
213   * Code to run the pipeline on a fairly arbitrary collection of vertices.
214   * For drawing indexed primitives.
215   *
216   * Vertex headers must be pre-initialized with the
217   * UNDEFINED_VERTEX_ID, this code will cause that id to become
218   * overwritten, so it may have to be reset if there is the intention
219   * to reuse the vertices.
220   *
221   * This code provides a callback to reset the vertex id's which the
222   * draw_vbuf.c code uses when it has to perform a flush.
223   */
draw_pipeline_run(struct draw_context * draw,const struct draw_vertex_info * vert_info,const struct draw_prim_info * prim_info)224  void draw_pipeline_run( struct draw_context *draw,
225                          const struct draw_vertex_info *vert_info,
226                          const struct draw_prim_info *prim_info)
227  {
228     unsigned i, start;
229  
230     draw->pipeline.verts = (char *)vert_info->verts;
231     draw->pipeline.vertex_stride = vert_info->stride;
232     draw->pipeline.vertex_count = vert_info->count;
233  
234     for (start = i = 0;
235          i < prim_info->primitive_count;
236          start += prim_info->primitive_lengths[i], i++)
237     {
238        const unsigned count = prim_info->primitive_lengths[i];
239  
240  #if DEBUG
241        /* Warn if one of the element indexes go outside the vertex buffer */
242        {
243           unsigned max_index = 0x0, i;
244           /* find the largest element index */
245           for (i = 0; i < count; i++) {
246              unsigned int index = prim_info->elts[start + i];
247              if (index > max_index)
248                 max_index = index;
249           }
250           if (max_index >= vert_info->count) {
251              debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
252                           __FUNCTION__,
253                           max_index,
254                           vert_info->count);
255           }
256        }
257  #endif
258  
259        pipe_run_elts(draw,
260                      prim_info->prim,
261                      prim_info->flags,
262                      vert_info->verts,
263                      vert_info->stride,
264                      prim_info->elts + start,
265                      count);
266     }
267  
268     draw->pipeline.verts = NULL;
269     draw->pipeline.vertex_count = 0;
270  }
271  
272  
273  /*
274   * Set up macros for draw_pt_decompose.h template code.
275   * This code is for non-indexed (aka linear) rendering (no elts).
276   */
277  
278  #define TRIANGLE(flags,i0,i1,i2)       \
279     do_triangle( draw, flags,           \
280                  verts + stride * (i0), \
281                  verts + stride * (i1), \
282                  verts + stride * (i2) )
283  
284  #define LINE(flags,i0,i1)              \
285     do_line( draw, flags,               \
286              verts + stride * (i0),     \
287              verts + stride * (i1) )
288  
289  #define POINT(i0)                      \
290     do_point( draw, verts + stride * (i0) )
291  
292  
293  #define GET_ELT(idx) (idx)
294  
295  #define FUNC pipe_run_linear
296  #define FUNC_VARS                      \
297      struct draw_context *draw,         \
298      unsigned prim,                     \
299      unsigned prim_flags,               \
300      struct vertex_header *vertices,    \
301      unsigned stride,                   \
302      unsigned count
303  
304  #include "draw_pt_decompose.h"
305  
306  
307  /*
308   * For drawing non-indexed primitives.
309   */
draw_pipeline_run_linear(struct draw_context * draw,const struct draw_vertex_info * vert_info,const struct draw_prim_info * prim_info)310  void draw_pipeline_run_linear( struct draw_context *draw,
311                                 const struct draw_vertex_info *vert_info,
312                                 const struct draw_prim_info *prim_info)
313  {
314     unsigned i, start;
315  
316     for (start = i = 0;
317          i < prim_info->primitive_count;
318          start += prim_info->primitive_lengths[i], i++)
319     {
320        unsigned count = prim_info->primitive_lengths[i];
321        char *verts = ((char*)vert_info->verts) +
322                      (start * vert_info->stride);
323  
324        draw->pipeline.verts = verts;
325        draw->pipeline.vertex_stride = vert_info->stride;
326        draw->pipeline.vertex_count = count;
327  
328        assert(count <= vert_info->count);
329  
330        pipe_run_linear(draw,
331                        prim_info->prim,
332                        prim_info->flags,
333                        (struct vertex_header*)verts,
334                        vert_info->stride,
335                        count);
336     }
337  
338     draw->pipeline.verts = NULL;
339     draw->pipeline.vertex_count = 0;
340  }
341  
342  
draw_pipeline_flush(struct draw_context * draw,unsigned flags)343  void draw_pipeline_flush( struct draw_context *draw,
344                            unsigned flags )
345  {
346     draw->pipeline.first->flush( draw->pipeline.first, flags );
347     if (!(flags & DRAW_FLUSH_BACKEND))
348        draw->pipeline.first = draw->pipeline.validate;
349  }
350