move mesa32 over to new dir
[reactos.git] / reactos / lib / mesa32 / src / tnl / t_vb_render.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 5.1
5 *
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions 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 MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 * Keith Whitwell <keith@tungstengraphics.com>
27 */
28
29
30 /*
31 * Render whole vertex buffers, including projection of vertices from
32 * clip space and clipping of primitives.
33 *
34 * This file makes calls to project vertices and to the point, line
35 * and triangle rasterizers via the function pointers:
36 *
37 * context->Driver.Render.*
38 *
39 */
40
41
42 #include "glheader.h"
43 #include "context.h"
44 #include "enums.h"
45 #include "macros.h"
46 #include "imports.h"
47 #include "mtypes.h"
48 #include "nvfragprog.h"
49 #include "math/m_matrix.h"
50 #include "math/m_xform.h"
51
52 #include "t_pipeline.h"
53
54
55
56 /**********************************************************************/
57 /* Clip single primitives */
58 /**********************************************************************/
59
60
61 #define W(i) coord[i][3]
62 #define Z(i) coord[i][2]
63 #define Y(i) coord[i][1]
64 #define X(i) coord[i][0]
65 #define SIZE 4
66 #define TAG(x) x##_4
67 #include "t_vb_cliptmp.h"
68
69
70
71 /**********************************************************************/
72 /* Clip and render whole begin/end objects */
73 /**********************************************************************/
74
75 #define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
76 #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
77 #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
78
79
80 #define CLIPMASK (CLIP_ALL_BITS|CLIP_CULL_BIT)
81
82
83 /* Vertices, with the possibility of clipping.
84 */
85 #define RENDER_POINTS( start, count ) \
86 tnl->Driver.Render.Points( ctx, start, count )
87
88 #define RENDER_LINE( v1, v2 ) \
89 do { \
90 GLubyte c1 = mask[v1], c2 = mask[v2]; \
91 GLubyte ormask = c1|c2; \
92 if (!ormask) \
93 LineFunc( ctx, v1, v2 ); \
94 else if (!(c1 & c2 & CLIPMASK)) \
95 clip_line_4( ctx, v1, v2, ormask ); \
96 } while (0)
97
98 #define RENDER_TRI( v1, v2, v3 ) \
99 do { \
100 GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
101 GLubyte ormask = c1|c2|c3; \
102 if (!ormask) \
103 TriangleFunc( ctx, v1, v2, v3 ); \
104 else if (!(c1 & c2 & c3 & CLIPMASK)) \
105 clip_tri_4( ctx, v1, v2, v3, ormask ); \
106 } while (0)
107
108 #define RENDER_QUAD( v1, v2, v3, v4 ) \
109 do { \
110 GLubyte c1 = mask[v1], c2 = mask[v2]; \
111 GLubyte c3 = mask[v3], c4 = mask[v4]; \
112 GLubyte ormask = c1|c2|c3|c4; \
113 if (!ormask) \
114 QuadFunc( ctx, v1, v2, v3, v4 ); \
115 else if (!(c1 & c2 & c3 & c4 & CLIPMASK)) \
116 clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
117 } while (0)
118
119
120 #define LOCAL_VARS \
121 TNLcontext *tnl = TNL_CONTEXT(ctx); \
122 struct vertex_buffer *VB = &tnl->vb; \
123 const GLuint * const elt = VB->Elts; \
124 const GLubyte *mask = VB->ClipMask; \
125 const GLuint sz = VB->ClipPtr->size; \
126 const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
127 const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
128 const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
129 const GLboolean stipple = ctx->Line.StippleFlag; \
130 (void) (LineFunc && TriangleFunc && QuadFunc); \
131 (void) elt; (void) mask; (void) sz; (void) stipple;
132
133 #define TAG(x) clip_##x##_verts
134 #define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
135 #define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
136 #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
137 #define PRESERVE_VB_DEFS
138 #include "t_vb_rendertmp.h"
139
140
141
142 /* Elts, with the possibility of clipping.
143 */
144 #undef ELT
145 #undef TAG
146 #define ELT(x) elt[x]
147 #define TAG(x) clip_##x##_elts
148 #include "t_vb_rendertmp.h"
149
150 /* TODO: do this for all primitives, verts and elts:
151 */
152 static void clip_elt_triangles( GLcontext *ctx,
153 GLuint start,
154 GLuint count,
155 GLuint flags )
156 {
157 TNLcontext *tnl = TNL_CONTEXT(ctx);
158 tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
159 struct vertex_buffer *VB = &tnl->vb;
160 const GLuint * const elt = VB->Elts;
161 GLubyte *mask = VB->ClipMask;
162 GLuint last = count-2;
163 GLuint j;
164 (void) flags;
165
166 tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
167
168 for (j=start; j < last; j+=3 ) {
169 GLubyte c1 = mask[elt[j]];
170 GLubyte c2 = mask[elt[j+1]];
171 GLubyte c3 = mask[elt[j+2]];
172 GLubyte ormask = c1|c2|c3;
173 if (ormask) {
174 if (start < j)
175 render_tris( ctx, start, j, 0 );
176 if (!(c1&c2&c3&CLIPMASK))
177 clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
178 start = j+3;
179 }
180 }
181
182 if (start < j)
183 render_tris( ctx, start, j, 0 );
184 }
185
186 /**********************************************************************/
187 /* Render whole begin/end objects */
188 /**********************************************************************/
189
190 #define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
191 #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
192 #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
193
194
195 /* Vertices, no clipping.
196 */
197 #define RENDER_POINTS( start, count ) \
198 tnl->Driver.Render.Points( ctx, start, count )
199
200 #define RENDER_LINE( v1, v2 ) \
201 LineFunc( ctx, v1, v2 )
202
203 #define RENDER_TRI( v1, v2, v3 ) \
204 TriangleFunc( ctx, v1, v2, v3 )
205
206 #define RENDER_QUAD( v1, v2, v3, v4 ) \
207 QuadFunc( ctx, v1, v2, v3, v4 )
208
209 #define TAG(x) _tnl_##x##_verts
210
211 #define LOCAL_VARS \
212 TNLcontext *tnl = TNL_CONTEXT(ctx); \
213 struct vertex_buffer *VB = &tnl->vb; \
214 const GLuint * const elt = VB->Elts; \
215 const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
216 const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
217 const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
218 const GLboolean stipple = ctx->Line.StippleFlag; \
219 (void) (LineFunc && TriangleFunc && QuadFunc); \
220 (void) elt; (void) stipple
221
222 #define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
223 #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
224 #define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
225 #define RENDER_TAB_QUALIFIER
226 #define PRESERVE_VB_DEFS
227 #include "t_vb_rendertmp.h"
228
229
230 /* Elts, no clipping.
231 */
232 #undef ELT
233 #define TAG(x) _tnl_##x##_elts
234 #define ELT(x) elt[x]
235 #include "t_vb_rendertmp.h"
236
237
238 /**********************************************************************/
239 /* Helper functions for drivers */
240 /**********************************************************************/
241
242 void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
243 {
244 TNLcontext *tnl = TNL_CONTEXT(ctx);
245 struct vertex_buffer *VB = &tnl->vb;
246 GLuint *tmp = VB->Elts;
247
248 VB->Elts = (GLuint *)elts;
249 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
250 VB->Elts = tmp;
251 }
252
253 void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
254 {
255 TNLcontext *tnl = TNL_CONTEXT(ctx);
256 tnl->Driver.Render.Line( ctx, ii, jj );
257 }
258
259
260
261 /**********************************************************************/
262 /* Clip and render whole vertex buffers */
263 /**********************************************************************/
264
265
266 static GLboolean run_render( GLcontext *ctx,
267 struct tnl_pipeline_stage *stage )
268 {
269 TNLcontext *tnl = TNL_CONTEXT(ctx);
270 struct vertex_buffer *VB = &tnl->vb;
271 tnl_render_func *tab;
272 GLint pass = 0;
273
274 /* Allow the drivers to lock before projected verts are built so
275 * that window coordinates are guarenteed not to change before
276 * rendering.
277 */
278 ASSERT(tnl->Driver.Render.Start);
279
280 tnl->Driver.Render.Start( ctx );
281
282 ASSERT(tnl->Driver.Render.BuildVertices);
283 ASSERT(tnl->Driver.Render.PrimitiveNotify);
284 ASSERT(tnl->Driver.Render.Points);
285 ASSERT(tnl->Driver.Render.Line);
286 ASSERT(tnl->Driver.Render.Triangle);
287 ASSERT(tnl->Driver.Render.Quad);
288 ASSERT(tnl->Driver.Render.ResetLineStipple);
289 ASSERT(tnl->Driver.Render.Interp);
290 ASSERT(tnl->Driver.Render.CopyPV);
291 ASSERT(tnl->Driver.Render.ClippedLine);
292 ASSERT(tnl->Driver.Render.ClippedPolygon);
293 ASSERT(tnl->Driver.Render.Finish);
294
295 tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
296
297 if (VB->ClipOrMask) {
298 tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
299 clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
300 }
301 else {
302 tab = (VB->Elts ?
303 tnl->Driver.Render.PrimTabElts :
304 tnl->Driver.Render.PrimTabVerts);
305 }
306
307 do
308 {
309 GLuint i;
310
311 for (i = 0 ; i < VB->PrimitiveCount ; i++)
312 {
313 GLuint prim = VB->Primitive[i].mode;
314 GLuint start = VB->Primitive[i].start;
315 GLuint length = VB->Primitive[i].count;
316
317 assert((prim & PRIM_MODE_MASK) < GL_POLYGON+1);
318
319 if (MESA_VERBOSE & VERBOSE_PRIMS)
320 _mesa_debug(NULL, "MESA prim %s %d..%d\n",
321 _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK),
322 start, start+length);
323
324 if (length)
325 tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
326 }
327 } while (tnl->Driver.Render.Multipass &&
328 tnl->Driver.Render.Multipass( ctx, ++pass ));
329
330 tnl->Driver.Render.Finish( ctx );
331
332 return GL_FALSE; /* finished the pipe */
333 }
334
335
336 /**********************************************************************/
337 /* Render pipeline stage */
338 /**********************************************************************/
339
340
341
342
343
344 const struct tnl_pipeline_stage _tnl_render_stage =
345 {
346 "render", /* name */
347 NULL, /* private data */
348 NULL, /* creator */
349 NULL, /* destructor */
350 NULL, /* validate */
351 run_render /* run */
352 };