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