1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2005  Brian Paul   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 "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg *
24848b8605Smrg * Authors:
25848b8605Smrg *    Keith Whitwell <keithw@vmware.com>
26848b8605Smrg */
27848b8605Smrg
28848b8605Smrg
29848b8605Smrg/*
30848b8605Smrg * Render whole vertex buffers, including projection of vertices from
31848b8605Smrg * clip space and clipping of primitives.
32848b8605Smrg *
33848b8605Smrg * This file makes calls to project vertices and to the point, line
34848b8605Smrg * and triangle rasterizers via the function pointers:
35848b8605Smrg *
36848b8605Smrg *    context->Driver.Render.*
37848b8605Smrg *
38848b8605Smrg */
39848b8605Smrg
40848b8605Smrg
41b8e80941Smrg#include <stdio.h>
42848b8605Smrg#include "main/glheader.h"
43848b8605Smrg#include "main/context.h"
44848b8605Smrg#include "main/enums.h"
45848b8605Smrg#include "main/macros.h"
46848b8605Smrg#include "main/imports.h"
47848b8605Smrg#include "main/mtypes.h"
48848b8605Smrg#include "math/m_xform.h"
49b8e80941Smrg#include "util/bitscan.h"
50848b8605Smrg
51848b8605Smrg#include "t_pipeline.h"
52848b8605Smrg
53848b8605Smrg
54848b8605Smrg
55848b8605Smrg/**********************************************************************/
56848b8605Smrg/*                        Clip single primitives                      */
57848b8605Smrg/**********************************************************************/
58848b8605Smrg
59848b8605Smrg
60848b8605Smrg#define W(i) coord[i][3]
61848b8605Smrg#define Z(i) coord[i][2]
62848b8605Smrg#define Y(i) coord[i][1]
63848b8605Smrg#define X(i) coord[i][0]
64848b8605Smrg#define SIZE 4
65848b8605Smrg#define TAG(x) x##_4
66848b8605Smrg#include "t_vb_cliptmp.h"
67848b8605Smrg
68848b8605Smrg
69848b8605Smrg
70848b8605Smrg/**********************************************************************/
71848b8605Smrg/*              Clip and render whole begin/end objects               */
72848b8605Smrg/**********************************************************************/
73848b8605Smrg
74848b8605Smrg#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
75848b8605Smrg#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
76848b8605Smrg#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
77848b8605Smrg
78848b8605Smrg
79848b8605Smrg/* This does NOT include the CLIP_USER_BIT! */
80848b8605Smrg#define CLIPMASK (CLIP_FRUSTUM_BITS | CLIP_CULL_BIT)
81848b8605Smrg
82848b8605Smrg
83848b8605Smrg/* Vertices, with the possibility of clipping.
84848b8605Smrg */
85848b8605Smrg#define RENDER_POINTS( start, count ) \
86848b8605Smrg   tnl->Driver.Render.Points( ctx, start, count )
87848b8605Smrg
88848b8605Smrg#define RENDER_LINE( v1, v2 )			\
89848b8605Smrgdo {						\
90848b8605Smrg   GLubyte c1 = mask[v1], c2 = mask[v2];	\
91848b8605Smrg   GLubyte ormask = c1|c2;			\
92848b8605Smrg   if (!ormask)					\
93848b8605Smrg      LineFunc( ctx, v1, v2 );			\
94848b8605Smrg   else if (!(c1 & c2 & CLIPMASK))			\
95848b8605Smrg      clip_line_4( ctx, v1, v2, ormask );	\
96848b8605Smrg} while (0)
97848b8605Smrg
98848b8605Smrg#define RENDER_TRI( v1, v2, v3 )			\
99848b8605Smrgdo {							\
100848b8605Smrg   GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3];	\
101848b8605Smrg   GLubyte ormask = c1|c2|c3;				\
102848b8605Smrg   if (!ormask)						\
103848b8605Smrg      TriangleFunc( ctx, v1, v2, v3 );			\
104848b8605Smrg   else if (!(c1 & c2 & c3 & CLIPMASK)) 			\
105848b8605Smrg      clip_tri_4( ctx, v1, v2, v3, ormask );    	\
106848b8605Smrg} while (0)
107848b8605Smrg
108848b8605Smrg#define RENDER_QUAD( v1, v2, v3, v4 )			\
109848b8605Smrgdo {							\
110848b8605Smrg   GLubyte c1 = mask[v1], c2 = mask[v2];		\
111848b8605Smrg   GLubyte c3 = mask[v3], c4 = mask[v4];		\
112848b8605Smrg   GLubyte ormask = c1|c2|c3|c4;			\
113848b8605Smrg   if (!ormask)						\
114848b8605Smrg      QuadFunc( ctx, v1, v2, v3, v4 );			\
115848b8605Smrg   else if (!(c1 & c2 & c3 & c4 & CLIPMASK)) 		\
116848b8605Smrg      clip_quad_4( ctx, v1, v2, v3, v4, ormask );	\
117848b8605Smrg} while (0)
118848b8605Smrg
119848b8605Smrg
120848b8605Smrg#define LOCAL_VARS						\
121848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);				\
122848b8605Smrg   struct vertex_buffer *VB = &tnl->vb;				\
123848b8605Smrg   const GLuint * const elt = VB->Elts;				\
124848b8605Smrg   const GLubyte *mask = VB->ClipMask;				\
125848b8605Smrg   const GLuint sz = VB->ClipPtr->size;				\
126848b8605Smrg   const tnl_line_func LineFunc = tnl->Driver.Render.Line;		\
127848b8605Smrg   const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle;	\
128848b8605Smrg   const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad;		\
129848b8605Smrg   const GLboolean stipple = ctx->Line.StippleFlag;		\
130848b8605Smrg   (void) (LineFunc && TriangleFunc && QuadFunc);		\
131848b8605Smrg   (void) elt; (void) mask; (void) sz; (void) stipple;
132848b8605Smrg
133848b8605Smrg#define TAG(x) clip_##x##_verts
134848b8605Smrg#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
135848b8605Smrg#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
136848b8605Smrg#define PRESERVE_VB_DEFS
137848b8605Smrg#include "t_vb_rendertmp.h"
138848b8605Smrg
139848b8605Smrg
140848b8605Smrg
141848b8605Smrg/* Elts, with the possibility of clipping.
142848b8605Smrg */
143848b8605Smrg#undef ELT
144848b8605Smrg#undef TAG
145848b8605Smrg#define ELT(x) elt[x]
146848b8605Smrg#define TAG(x) clip_##x##_elts
147848b8605Smrg#include "t_vb_rendertmp.h"
148848b8605Smrg
149848b8605Smrg/* TODO: do this for all primitives, verts and elts:
150848b8605Smrg */
151848b8605Smrgstatic void clip_elt_triangles( struct gl_context *ctx,
152848b8605Smrg				GLuint start,
153848b8605Smrg				GLuint count,
154848b8605Smrg				GLuint flags )
155848b8605Smrg{
156848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
157848b8605Smrg   tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
158848b8605Smrg   struct vertex_buffer *VB = &tnl->vb;
159848b8605Smrg   const GLuint * const elt = VB->Elts;
160848b8605Smrg   GLubyte *mask = VB->ClipMask;
161848b8605Smrg   GLuint last = count-2;
162848b8605Smrg   GLuint j;
163848b8605Smrg   (void) flags;
164848b8605Smrg
165848b8605Smrg   tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
166848b8605Smrg
167848b8605Smrg   for (j=start; j < last; j+=3 ) {
168848b8605Smrg      GLubyte c1 = mask[elt[j]];
169848b8605Smrg      GLubyte c2 = mask[elt[j+1]];
170848b8605Smrg      GLubyte c3 = mask[elt[j+2]];
171848b8605Smrg      GLubyte ormask = c1|c2|c3;
172848b8605Smrg      if (ormask) {
173848b8605Smrg	 if (start < j)
174848b8605Smrg	    render_tris( ctx, start, j, 0 );
175848b8605Smrg	 if (!(c1&c2&c3&CLIPMASK))
176848b8605Smrg	    clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
177848b8605Smrg	 start = j+3;
178848b8605Smrg      }
179848b8605Smrg   }
180848b8605Smrg
181848b8605Smrg   if (start < j)
182848b8605Smrg      render_tris( ctx, start, j, 0 );
183848b8605Smrg}
184848b8605Smrg
185848b8605Smrg/**********************************************************************/
186848b8605Smrg/*                  Render whole begin/end objects                    */
187848b8605Smrg/**********************************************************************/
188848b8605Smrg
189848b8605Smrg#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
190848b8605Smrg#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
191848b8605Smrg#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
192848b8605Smrg
193848b8605Smrg
194848b8605Smrg/* Vertices, no clipping.
195848b8605Smrg */
196848b8605Smrg#define RENDER_POINTS( start, count ) \
197848b8605Smrg   tnl->Driver.Render.Points( ctx, start, count )
198848b8605Smrg
199848b8605Smrg#define RENDER_LINE( v1, v2 ) \
200848b8605Smrg   LineFunc( ctx, v1, v2 )
201848b8605Smrg
202848b8605Smrg#define RENDER_TRI( v1, v2, v3 ) \
203848b8605Smrg   TriangleFunc( ctx, v1, v2, v3 )
204848b8605Smrg
205848b8605Smrg#define RENDER_QUAD( v1, v2, v3, v4 ) \
206848b8605Smrg   QuadFunc( ctx, v1, v2, v3, v4 )
207848b8605Smrg
208848b8605Smrg#define TAG(x) _tnl_##x##_verts
209848b8605Smrg
210848b8605Smrg#define LOCAL_VARS						\
211848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);				\
212848b8605Smrg   struct vertex_buffer *VB = &tnl->vb;				\
213848b8605Smrg   const GLuint * const elt = VB->Elts;				\
214848b8605Smrg   const tnl_line_func LineFunc = tnl->Driver.Render.Line;		\
215848b8605Smrg   const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle;	\
216848b8605Smrg   const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad;		\
217848b8605Smrg   const GLboolean stipple = ctx->Line.StippleFlag;		\
218848b8605Smrg   (void) (LineFunc && TriangleFunc && QuadFunc);		\
219848b8605Smrg   (void) elt; (void) stipple
220848b8605Smrg
221848b8605Smrg#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
222848b8605Smrg#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
223848b8605Smrg#define RENDER_TAB_QUALIFIER
224848b8605Smrg#define PRESERVE_VB_DEFS
225848b8605Smrg#include "t_vb_rendertmp.h"
226848b8605Smrg
227848b8605Smrg
228848b8605Smrg/* Elts, no clipping.
229848b8605Smrg */
230848b8605Smrg#undef ELT
231848b8605Smrg#define TAG(x) _tnl_##x##_elts
232848b8605Smrg#define ELT(x) elt[x]
233848b8605Smrg#include "t_vb_rendertmp.h"
234848b8605Smrg
235848b8605Smrg
236848b8605Smrg/**********************************************************************/
237848b8605Smrg/*              Helper functions for drivers                  */
238848b8605Smrg/**********************************************************************/
239848b8605Smrg
240848b8605Smrgvoid _tnl_RenderClippedPolygon( struct gl_context *ctx, const GLuint *elts, GLuint n )
241848b8605Smrg{
242848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
243848b8605Smrg   struct vertex_buffer *VB = &tnl->vb;
244848b8605Smrg   GLuint *tmp = VB->Elts;
245848b8605Smrg
246848b8605Smrg   VB->Elts = (GLuint *)elts;
247848b8605Smrg   tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
248848b8605Smrg   VB->Elts = tmp;
249848b8605Smrg}
250848b8605Smrg
251848b8605Smrgvoid _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj )
252848b8605Smrg{
253848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
254848b8605Smrg   tnl->Driver.Render.Line( ctx, ii, jj );
255848b8605Smrg}
256848b8605Smrg
257848b8605Smrg
258848b8605Smrg
259848b8605Smrg/**********************************************************************/
260848b8605Smrg/*              Clip and render whole vertex buffers                  */
261848b8605Smrg/**********************************************************************/
262848b8605Smrg
263848b8605Smrg
264848b8605Smrgstatic GLboolean run_render( struct gl_context *ctx,
265848b8605Smrg			     struct tnl_pipeline_stage *stage )
266848b8605Smrg{
267848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
268848b8605Smrg   struct vertex_buffer *VB = &tnl->vb;
269848b8605Smrg   tnl_render_func *tab;
270848b8605Smrg   GLint pass = 0;
271848b8605Smrg
272848b8605Smrg   /* Allow the drivers to lock before projected verts are built so
273848b8605Smrg    * that window coordinates are guarenteed not to change before
274848b8605Smrg    * rendering.
275848b8605Smrg    */
276b8e80941Smrg   assert(tnl->Driver.Render.Start);
277848b8605Smrg
278848b8605Smrg   tnl->Driver.Render.Start( ctx );
279848b8605Smrg
280b8e80941Smrg   assert(tnl->Driver.Render.BuildVertices);
281b8e80941Smrg   assert(tnl->Driver.Render.PrimitiveNotify);
282b8e80941Smrg   assert(tnl->Driver.Render.Points);
283b8e80941Smrg   assert(tnl->Driver.Render.Line);
284b8e80941Smrg   assert(tnl->Driver.Render.Triangle);
285b8e80941Smrg   assert(tnl->Driver.Render.Quad);
286b8e80941Smrg   assert(tnl->Driver.Render.ResetLineStipple);
287b8e80941Smrg   assert(tnl->Driver.Render.Interp);
288b8e80941Smrg   assert(tnl->Driver.Render.CopyPV);
289b8e80941Smrg   assert(tnl->Driver.Render.ClippedLine);
290b8e80941Smrg   assert(tnl->Driver.Render.ClippedPolygon);
291b8e80941Smrg   assert(tnl->Driver.Render.Finish);
292848b8605Smrg
293848b8605Smrg   tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
294848b8605Smrg
295848b8605Smrg   if (VB->ClipOrMask) {
296848b8605Smrg      tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
297848b8605Smrg      clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
298848b8605Smrg   }
299848b8605Smrg   else {
300848b8605Smrg      tab = (VB->Elts ?
301848b8605Smrg	     tnl->Driver.Render.PrimTabElts :
302848b8605Smrg	     tnl->Driver.Render.PrimTabVerts);
303848b8605Smrg   }
304848b8605Smrg
305848b8605Smrg   do
306848b8605Smrg   {
307848b8605Smrg      GLuint i;
308848b8605Smrg
309848b8605Smrg      for (i = 0 ; i < VB->PrimitiveCount ; i++)
310848b8605Smrg      {
311848b8605Smrg	 GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
312848b8605Smrg	 GLuint start = VB->Primitive[i].start;
313848b8605Smrg	 GLuint length = VB->Primitive[i].count;
314848b8605Smrg
315848b8605Smrg	 assert((prim & PRIM_MODE_MASK) <= GL_POLYGON);
316848b8605Smrg
317848b8605Smrg	 if (MESA_VERBOSE & VERBOSE_PRIMS)
318848b8605Smrg	    _mesa_debug(NULL, "MESA prim %s %d..%d\n",
319b8e80941Smrg			_mesa_enum_to_string(prim & PRIM_MODE_MASK),
320848b8605Smrg			start, start+length);
321848b8605Smrg
322848b8605Smrg	 if (length)
323848b8605Smrg	    tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
324848b8605Smrg      }
325848b8605Smrg   } while (tnl->Driver.Render.Multipass &&
326848b8605Smrg	    tnl->Driver.Render.Multipass( ctx, ++pass ));
327848b8605Smrg
328848b8605Smrg   tnl->Driver.Render.Finish( ctx );
329848b8605Smrg
330848b8605Smrg   return GL_FALSE;		/* finished the pipe */
331848b8605Smrg}
332848b8605Smrg
333848b8605Smrg
334848b8605Smrg/**********************************************************************/
335848b8605Smrg/*                          Render pipeline stage                     */
336848b8605Smrg/**********************************************************************/
337848b8605Smrg
338848b8605Smrg
339848b8605Smrg
340848b8605Smrg
341848b8605Smrg
342848b8605Smrgconst struct tnl_pipeline_stage _tnl_render_stage =
343848b8605Smrg{
344848b8605Smrg   "render",			/* name */
345848b8605Smrg   NULL,			/* private data */
346848b8605Smrg   NULL,			/* creator */
347848b8605Smrg   NULL,			/* destructor */
348848b8605Smrg   NULL,			/* validate */
349848b8605Smrg   run_render			/* run */
350848b8605Smrg};
351