1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2007 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg /*
29848b8605Smrg  * Authors:
30848b8605Smrg  *   Keith Whitwell <keithw@vmware.com>
31848b8605Smrg  */
32848b8605Smrg
33848b8605Smrg#include "draw/draw_private.h"
34848b8605Smrg#include "draw/draw_pipe.h"
35848b8605Smrg#include "util/u_debug.h"
36848b8605Smrg#include "util/u_math.h"
37848b8605Smrg
38848b8605Smrg
39848b8605Smrg
40848b8605Smrgboolean draw_pipeline_init( struct draw_context *draw )
41848b8605Smrg{
42848b8605Smrg   /* create pipeline stages */
43848b8605Smrg   draw->pipeline.wide_line  = draw_wide_line_stage( draw );
44848b8605Smrg   draw->pipeline.wide_point = draw_wide_point_stage( draw );
45848b8605Smrg   draw->pipeline.stipple   = draw_stipple_stage( draw );
46848b8605Smrg   draw->pipeline.unfilled  = draw_unfilled_stage( draw );
47848b8605Smrg   draw->pipeline.twoside   = draw_twoside_stage( draw );
48848b8605Smrg   draw->pipeline.offset    = draw_offset_stage( draw );
49848b8605Smrg   draw->pipeline.clip      = draw_clip_stage( draw );
50848b8605Smrg   draw->pipeline.flatshade = draw_flatshade_stage( draw );
51848b8605Smrg   draw->pipeline.cull      = draw_cull_stage( draw );
52848b8605Smrg   draw->pipeline.validate  = draw_validate_stage( draw );
53848b8605Smrg   draw->pipeline.first     = draw->pipeline.validate;
54848b8605Smrg
55848b8605Smrg   if (!draw->pipeline.wide_line ||
56848b8605Smrg       !draw->pipeline.wide_point ||
57848b8605Smrg       !draw->pipeline.stipple ||
58848b8605Smrg       !draw->pipeline.unfilled ||
59848b8605Smrg       !draw->pipeline.twoside ||
60848b8605Smrg       !draw->pipeline.offset ||
61848b8605Smrg       !draw->pipeline.clip ||
62848b8605Smrg       !draw->pipeline.flatshade ||
63848b8605Smrg       !draw->pipeline.cull ||
64848b8605Smrg       !draw->pipeline.validate)
65848b8605Smrg      return FALSE;
66848b8605Smrg
67848b8605Smrg   /* these defaults are oriented toward the needs of softpipe */
68848b8605Smrg   draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */
69848b8605Smrg   draw->pipeline.wide_line_threshold = 1.0f;
70848b8605Smrg   draw->pipeline.wide_point_sprites = FALSE;
71848b8605Smrg   draw->pipeline.line_stipple = TRUE;
72848b8605Smrg   draw->pipeline.point_sprite = TRUE;
73848b8605Smrg
74848b8605Smrg   return TRUE;
75848b8605Smrg}
76848b8605Smrg
77848b8605Smrg
78848b8605Smrgvoid draw_pipeline_destroy( struct draw_context *draw )
79848b8605Smrg{
80848b8605Smrg   if (draw->pipeline.wide_line)
81848b8605Smrg      draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
82848b8605Smrg   if (draw->pipeline.wide_point)
83848b8605Smrg      draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
84848b8605Smrg   if (draw->pipeline.stipple)
85848b8605Smrg      draw->pipeline.stipple->destroy( draw->pipeline.stipple );
86848b8605Smrg   if (draw->pipeline.unfilled)
87848b8605Smrg      draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
88848b8605Smrg   if (draw->pipeline.twoside)
89848b8605Smrg      draw->pipeline.twoside->destroy( draw->pipeline.twoside );
90848b8605Smrg   if (draw->pipeline.offset)
91848b8605Smrg      draw->pipeline.offset->destroy( draw->pipeline.offset );
92848b8605Smrg   if (draw->pipeline.clip)
93848b8605Smrg      draw->pipeline.clip->destroy( draw->pipeline.clip );
94848b8605Smrg   if (draw->pipeline.flatshade)
95848b8605Smrg      draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
96848b8605Smrg   if (draw->pipeline.cull)
97848b8605Smrg      draw->pipeline.cull->destroy( draw->pipeline.cull );
98848b8605Smrg   if (draw->pipeline.validate)
99848b8605Smrg      draw->pipeline.validate->destroy( draw->pipeline.validate );
100848b8605Smrg   if (draw->pipeline.aaline)
101848b8605Smrg      draw->pipeline.aaline->destroy( draw->pipeline.aaline );
102848b8605Smrg   if (draw->pipeline.aapoint)
103848b8605Smrg      draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
104848b8605Smrg   if (draw->pipeline.pstipple)
105848b8605Smrg      draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
106848b8605Smrg   if (draw->pipeline.rasterize)
107848b8605Smrg      draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
108848b8605Smrg}
109848b8605Smrg
110848b8605Smrg
111848b8605Smrg
112848b8605Smrg/**
113848b8605Smrg * Build primitive to render a point with vertex at v0.
114848b8605Smrg */
115848b8605Smrgstatic void do_point( struct draw_context *draw,
116848b8605Smrg		      const char *v0 )
117848b8605Smrg{
118848b8605Smrg   struct prim_header prim;
119848b8605Smrg
120848b8605Smrg   prim.flags = 0;
121848b8605Smrg   prim.pad = 0;
122848b8605Smrg   prim.v[0] = (struct vertex_header *)v0;
123848b8605Smrg
124848b8605Smrg   draw->pipeline.first->point( draw->pipeline.first, &prim );
125848b8605Smrg}
126848b8605Smrg
127848b8605Smrg
128848b8605Smrg/**
129848b8605Smrg * Build primitive to render a line with vertices at v0, v1.
130848b8605Smrg * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
131848b8605Smrg */
132848b8605Smrgstatic void do_line( struct draw_context *draw,
133848b8605Smrg                     ushort flags,
134848b8605Smrg		     const char *v0,
135848b8605Smrg		     const char *v1 )
136848b8605Smrg{
137848b8605Smrg   struct prim_header prim;
138848b8605Smrg
139848b8605Smrg   prim.flags = flags;
140848b8605Smrg   prim.pad = 0;
141848b8605Smrg   prim.v[0] = (struct vertex_header *)v0;
142848b8605Smrg   prim.v[1] = (struct vertex_header *)v1;
143848b8605Smrg
144848b8605Smrg   draw->pipeline.first->line( draw->pipeline.first, &prim );
145848b8605Smrg}
146848b8605Smrg
147848b8605Smrg
148848b8605Smrg/**
149848b8605Smrg * Build primitive to render a triangle with vertices at v0, v1, v2.
150848b8605Smrg * \param flags  bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
151848b8605Smrg */
152848b8605Smrgstatic void do_triangle( struct draw_context *draw,
153848b8605Smrg                         ushort flags,
154848b8605Smrg			 char *v0,
155848b8605Smrg			 char *v1,
156848b8605Smrg			 char *v2 )
157848b8605Smrg{
158848b8605Smrg   struct prim_header prim;
159848b8605Smrg
160848b8605Smrg   prim.v[0] = (struct vertex_header *)v0;
161848b8605Smrg   prim.v[1] = (struct vertex_header *)v1;
162848b8605Smrg   prim.v[2] = (struct vertex_header *)v2;
163848b8605Smrg   prim.flags = flags;
164848b8605Smrg   prim.pad = 0;
165848b8605Smrg
166848b8605Smrg   draw->pipeline.first->tri( draw->pipeline.first, &prim );
167848b8605Smrg}
168848b8605Smrg
169848b8605Smrg
170848b8605Smrg/*
171848b8605Smrg * Set up macros for draw_pt_decompose.h template code.
172848b8605Smrg * This code uses vertex indexes / elements.
173848b8605Smrg */
174848b8605Smrg
175848b8605Smrg#define TRIANGLE(flags,i0,i1,i2)                                  \
176848b8605Smrg   do {                                                           \
177848b8605Smrg      do_triangle( draw,                                          \
178848b8605Smrg                   flags,                                         \
179848b8605Smrg                   verts + stride * (i0),                         \
180848b8605Smrg                   verts + stride * (i1),                         \
181848b8605Smrg                   verts + stride * (i2) );                       \
182848b8605Smrg   } while (0)
183848b8605Smrg
184848b8605Smrg#define LINE(flags,i0,i1)                                         \
185848b8605Smrg   do {                                                           \
186848b8605Smrg      do_line( draw,                                              \
187848b8605Smrg               flags,                                             \
188848b8605Smrg               verts + stride * (i0),                             \
189848b8605Smrg               verts + stride * (i1) );                           \
190848b8605Smrg   } while (0)
191848b8605Smrg
192848b8605Smrg#define POINT(i0)                               \
193848b8605Smrg   do {                                         \
194848b8605Smrg      do_point( draw, verts + stride * (i0) );  \
195848b8605Smrg   } while (0)
196848b8605Smrg
197848b8605Smrg#define GET_ELT(idx) (MIN2(elts[idx], max_index))
198848b8605Smrg
199848b8605Smrg#define FUNC pipe_run_elts
200848b8605Smrg#define FUNC_VARS                               \
201848b8605Smrg    struct draw_context *draw,                  \
202848b8605Smrg    unsigned prim,                              \
203848b8605Smrg    unsigned prim_flags,                        \
204848b8605Smrg    struct vertex_header *vertices,             \
205848b8605Smrg    unsigned stride,                            \
206848b8605Smrg    const ushort *elts,                         \
207848b8605Smrg    unsigned count,                             \
208848b8605Smrg    unsigned max_index
209848b8605Smrg
210848b8605Smrg#include "draw_pt_decompose.h"
211848b8605Smrg
212848b8605Smrg
213848b8605Smrg
214848b8605Smrg/**
215848b8605Smrg * Code to run the pipeline on a fairly arbitrary collection of vertices.
216848b8605Smrg * For drawing indexed primitives.
217848b8605Smrg *
218848b8605Smrg * Vertex headers must be pre-initialized with the
219848b8605Smrg * UNDEFINED_VERTEX_ID, this code will cause that id to become
220848b8605Smrg * overwritten, so it may have to be reset if there is the intention
221848b8605Smrg * to reuse the vertices.
222848b8605Smrg *
223848b8605Smrg * This code provides a callback to reset the vertex id's which the
224848b8605Smrg * draw_vbuf.c code uses when it has to perform a flush.
225848b8605Smrg */
226848b8605Smrgvoid draw_pipeline_run( struct draw_context *draw,
227848b8605Smrg                        const struct draw_vertex_info *vert_info,
228848b8605Smrg                        const struct draw_prim_info *prim_info)
229848b8605Smrg{
230848b8605Smrg   unsigned i, start;
231848b8605Smrg
232848b8605Smrg   draw->pipeline.verts = (char *)vert_info->verts;
233848b8605Smrg   draw->pipeline.vertex_stride = vert_info->stride;
234848b8605Smrg   draw->pipeline.vertex_count = vert_info->count;
235848b8605Smrg
236848b8605Smrg   for (start = i = 0;
237848b8605Smrg        i < prim_info->primitive_count;
238848b8605Smrg        start += prim_info->primitive_lengths[i], i++)
239848b8605Smrg   {
240848b8605Smrg      const unsigned count = prim_info->primitive_lengths[i];
241848b8605Smrg
242848b8605Smrg#if DEBUG
243848b8605Smrg      /* Warn if one of the element indexes go outside the vertex buffer */
244848b8605Smrg      {
245848b8605Smrg         unsigned max_index = 0x0, i;
246848b8605Smrg         /* find the largest element index */
247848b8605Smrg         for (i = 0; i < count; i++) {
248848b8605Smrg            unsigned int index = prim_info->elts[start + i];
249848b8605Smrg            if (index > max_index)
250848b8605Smrg               max_index = index;
251848b8605Smrg         }
252848b8605Smrg         if (max_index >= vert_info->count) {
253848b8605Smrg            debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
254848b8605Smrg                         __FUNCTION__,
255848b8605Smrg                         max_index,
256848b8605Smrg                         vert_info->count);
257848b8605Smrg         }
258848b8605Smrg      }
259848b8605Smrg#endif
260848b8605Smrg
261848b8605Smrg      pipe_run_elts(draw,
262848b8605Smrg                    prim_info->prim,
263848b8605Smrg                    prim_info->flags,
264848b8605Smrg                    vert_info->verts,
265848b8605Smrg                    vert_info->stride,
266848b8605Smrg                    prim_info->elts + start,
267848b8605Smrg                    count,
268848b8605Smrg                    vert_info->count - 1);
269848b8605Smrg   }
270848b8605Smrg
271848b8605Smrg   draw->pipeline.verts = NULL;
272848b8605Smrg   draw->pipeline.vertex_count = 0;
273848b8605Smrg}
274848b8605Smrg
275848b8605Smrg
276848b8605Smrg/*
277848b8605Smrg * Set up macros for draw_pt_decompose.h template code.
278848b8605Smrg * This code is for non-indexed (aka linear) rendering (no elts).
279848b8605Smrg */
280848b8605Smrg
281848b8605Smrg#define TRIANGLE(flags,i0,i1,i2)       \
282848b8605Smrg   do_triangle( draw, flags,           \
283848b8605Smrg                verts + stride * (i0), \
284848b8605Smrg                verts + stride * (i1), \
285848b8605Smrg                verts + stride * (i2) )
286848b8605Smrg
287848b8605Smrg#define LINE(flags,i0,i1)              \
288848b8605Smrg   do_line( draw, flags,               \
289848b8605Smrg            verts + stride * (i0),     \
290848b8605Smrg            verts + stride * (i1) )
291848b8605Smrg
292848b8605Smrg#define POINT(i0)                      \
293848b8605Smrg   do_point( draw, verts + stride * (i0) )
294848b8605Smrg
295848b8605Smrg
296848b8605Smrg#define GET_ELT(idx) (idx)
297848b8605Smrg
298848b8605Smrg#define FUNC pipe_run_linear
299848b8605Smrg#define FUNC_VARS                      \
300848b8605Smrg    struct draw_context *draw,         \
301848b8605Smrg    unsigned prim,                     \
302848b8605Smrg    unsigned prim_flags,               \
303848b8605Smrg    struct vertex_header *vertices,    \
304848b8605Smrg    unsigned stride,                   \
305848b8605Smrg    unsigned count
306848b8605Smrg
307848b8605Smrg#include "draw_pt_decompose.h"
308848b8605Smrg
309848b8605Smrg
310848b8605Smrg/*
311848b8605Smrg * For drawing non-indexed primitives.
312848b8605Smrg */
313848b8605Smrgvoid draw_pipeline_run_linear( struct draw_context *draw,
314848b8605Smrg                               const struct draw_vertex_info *vert_info,
315848b8605Smrg                               const struct draw_prim_info *prim_info)
316848b8605Smrg{
317848b8605Smrg   unsigned i, start;
318848b8605Smrg
319848b8605Smrg   for (start = i = 0;
320848b8605Smrg        i < prim_info->primitive_count;
321848b8605Smrg        start += prim_info->primitive_lengths[i], i++)
322848b8605Smrg   {
323848b8605Smrg      unsigned count = prim_info->primitive_lengths[i];
324848b8605Smrg      char *verts = ((char*)vert_info->verts) +
325848b8605Smrg                    (start * vert_info->stride);
326848b8605Smrg
327848b8605Smrg      draw->pipeline.verts = verts;
328848b8605Smrg      draw->pipeline.vertex_stride = vert_info->stride;
329848b8605Smrg      draw->pipeline.vertex_count = count;
330848b8605Smrg
331848b8605Smrg      assert(count <= vert_info->count);
332848b8605Smrg
333848b8605Smrg      pipe_run_linear(draw,
334848b8605Smrg                      prim_info->prim,
335848b8605Smrg                      prim_info->flags,
336848b8605Smrg                      (struct vertex_header*)verts,
337848b8605Smrg                      vert_info->stride,
338848b8605Smrg                      count);
339848b8605Smrg   }
340848b8605Smrg
341848b8605Smrg   draw->pipeline.verts = NULL;
342848b8605Smrg   draw->pipeline.vertex_count = 0;
343848b8605Smrg}
344848b8605Smrg
345848b8605Smrg
346848b8605Smrgvoid draw_pipeline_flush( struct draw_context *draw,
347848b8605Smrg                          unsigned flags )
348848b8605Smrg{
349848b8605Smrg   draw->pipeline.first->flush( draw->pipeline.first, flags );
350848b8605Smrg   if (flags & DRAW_FLUSH_STATE_CHANGE)
351848b8605Smrg      draw->pipeline.first = draw->pipeline.validate;
352848b8605Smrg}
353