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