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