3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
26 * Keith Whitwell <keithw@valinux.com>
31 * Render whole vertex buffers, including projection of vertices from
32 * clip space and clipping of primitives.
34 * This file makes calls to project vertices and to the point, line
35 * and triangle rasterizers via the function pointers:
37 * context->Driver.Render.*
42 //---------------------------------------------------------------------------
44 //#include "../GLDirect.h"
45 //#include "../gld_log.h"
46 //#include "gld_dx8.h"
48 #include "dglcontext.h"
52 //---------------------------------------------------------------------------
61 #include "math/m_matrix.h"
62 #include "math/m_xform.h"
64 #include "tnl/t_pipeline.h"
66 /**********************************************************************/
67 /* Clip single primitives */
68 /**********************************************************************/
72 #define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
73 //#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
75 #define NEGATIVE(x) (x < 0)
76 //#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
77 /* Could just use (x*y<0) except for the flatshading requirements.
78 * Maybe there's a better way?
83 #define W(i) coord[i][3]
84 #define Z(i) coord[i][2]
85 #define Y(i) coord[i][1]
86 #define X(i) coord[i][0]
89 #include "tnl/t_vb_cliptmp.h"
93 /**********************************************************************/
94 /* Clip and render whole begin/end objects */
95 /**********************************************************************/
97 #define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
98 #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
99 #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
102 /* Vertices, with the possibility of clipping.
104 #define RENDER_POINTS( start, count ) \
105 tnl->Driver.Render.Points( ctx, start, count )
107 #define RENDER_LINE( v1, v2 ) \
109 GLubyte c1 = mask[v1], c2 = mask[v2]; \
110 GLubyte ormask = c1|c2; \
112 LineFunc( ctx, v1, v2 ); \
113 else if (!(c1 & c2 & 0x3f)) \
114 clip_line_4( ctx, v1, v2, ormask ); \
117 #define RENDER_TRI( v1, v2, v3 ) \
119 GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
120 GLubyte ormask = c1|c2|c3; \
122 TriangleFunc( ctx, v1, v2, v3 ); \
123 else if (!(c1 & c2 & c3 & 0x3f)) \
124 clip_tri_4( ctx, v1, v2, v3, ormask ); \
127 #define RENDER_QUAD( v1, v2, v3, v4 ) \
129 GLubyte c1 = mask[v1], c2 = mask[v2]; \
130 GLubyte c3 = mask[v3], c4 = mask[v4]; \
131 GLubyte ormask = c1|c2|c3|c4; \
133 QuadFunc( ctx, v1, v2, v3, v4 ); \
134 else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
135 clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
140 TNLcontext *tnl = TNL_CONTEXT(ctx); \
141 struct vertex_buffer *VB = &tnl->vb; \
142 const GLuint * const elt = VB->Elts; \
143 const GLubyte *mask = VB->ClipMask; \
144 const GLuint sz = VB->ClipPtr->size; \
145 const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
146 const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
147 const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
148 const GLboolean stipple = ctx->Line.StippleFlag; \
149 (void) (LineFunc && TriangleFunc && QuadFunc); \
150 (void) elt; (void) mask; (void) sz; (void) stipple;
152 #define TAG(x) clip_##x##_verts
153 #define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
154 #define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
155 #define PRESERVE_VB_DEFS
156 #include "tnl/t_vb_rendertmp.h"
160 /* Elts, with the possibility of clipping.
164 #define ELT(x) elt[x]
165 #define TAG(x) clip_##x##_elts
166 #include "tnl/t_vb_rendertmp.h"
168 /* TODO: do this for all primitives, verts and elts:
170 static void clip_elt_triangles( GLcontext
*ctx
,
175 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
176 tnl_render_func render_tris
= tnl
->Driver
.Render
.PrimTabElts
[GL_TRIANGLES
];
177 struct vertex_buffer
*VB
= &tnl
->vb
;
178 const GLuint
* const elt
= VB
->Elts
;
179 GLubyte
*mask
= VB
->ClipMask
;
180 GLuint last
= count
-2;
184 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, GL_TRIANGLES
);
186 for (j
=start
; j
< last
; j
+=3 ) {
187 GLubyte c1
= mask
[elt
[j
]];
188 GLubyte c2
= mask
[elt
[j
+1]];
189 GLubyte c3
= mask
[elt
[j
+2]];
190 GLubyte ormask
= c1
|c2
|c3
;
193 render_tris( ctx
, start
, j
, 0 );
194 if (!(c1
&c2
&c3
&0x3f))
195 clip_tri_4( ctx
, elt
[j
], elt
[j
+1], elt
[j
+2], ormask
);
201 render_tris( ctx
, start
, j
, 0 );
204 /**********************************************************************/
205 /* Render whole begin/end objects */
206 /**********************************************************************/
208 #define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
209 #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
210 #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
213 /* Vertices, no clipping.
215 #define RENDER_POINTS( start, count ) \
216 tnl->Driver.Render.Points( ctx, start, count )
218 #define RENDER_LINE( v1, v2 ) \
219 LineFunc( ctx, v1, v2 )
221 #define RENDER_TRI( v1, v2, v3 ) \
222 TriangleFunc( ctx, v1, v2, v3 )
224 #define RENDER_QUAD( v1, v2, v3, v4 ) \
225 QuadFunc( ctx, v1, v2, v3, v4 )
227 #define TAG(x) _gld_tnl_##x##_verts
230 TNLcontext *tnl = TNL_CONTEXT(ctx); \
231 struct vertex_buffer *VB = &tnl->vb; \
232 const GLuint * const elt = VB->Elts; \
233 const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
234 const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
235 const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
236 (void) (LineFunc && TriangleFunc && QuadFunc); \
239 #define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
240 #define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
241 #define RENDER_TAB_QUALIFIER
242 #define PRESERVE_VB_DEFS
243 #include "tnl/t_vb_rendertmp.h"
246 /* Elts, no clipping.
249 #define TAG(x) _gld_tnl_##x##_elts
250 #define ELT(x) elt[x]
251 #include "tnl/t_vb_rendertmp.h"
254 /**********************************************************************/
255 /* Helper functions for drivers */
256 /**********************************************************************/
258 void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
260 TNLcontext *tnl = TNL_CONTEXT(ctx);
261 struct vertex_buffer *VB = &tnl->vb;
262 GLuint *tmp = VB->Elts;
264 VB->Elts = (GLuint *)elts;
265 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
269 void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
271 TNLcontext *tnl = TNL_CONTEXT(ctx);
272 tnl->Driver.Render.Line( ctx, ii, jj );
277 /**********************************************************************/
278 /* Clip and render whole vertex buffers */
279 /**********************************************************************/
281 tnl_points_func _gldSetupPoints
[4] = {
287 tnl_line_func _gldSetupLine
[4] = {
289 gld_Line2DSmooth_DX7
,
291 gld_Line2DSmooth_DX7
,
293 tnl_triangle_func _gldSetupTriangle
[4] = {
294 gld_Triangle2DFlat_DX7
,
295 gld_Triangle2DSmooth_DX7
,
296 gld_Triangle2DFlatExtras_DX7
,
297 gld_Triangle2DSmoothExtras_DX7
299 tnl_quad_func _gldSetupQuad
[4] = {
301 gld_Quad2DSmooth_DX7
,
302 gld_Quad2DFlatExtras_DX7
,
303 gld_Quad2DSmoothExtras_DX7
306 //---------------------------------------------------------------------------
308 static GLboolean
_gld_mesa_render_stage_run(
310 struct tnl_pipeline_stage
*stage
)
312 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
313 GLD_driver_dx7
*gld
= GLD_GET_DX7_DRIVER(gldCtx
);
315 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
316 struct vertex_buffer
*VB
= &tnl
->vb
;
317 tnl_render_func
*tab
;
322 /* Allow the drivers to lock before projected verts are built so
323 * that window coordinates are guarenteed not to change before
326 ASSERT(tnl
->Driver
.Render
.Start
);
328 tnl
->Driver
.Render
.Start( ctx
);
331 tnl
->Driver
.Render
.Points
= _gldSetupPoints
[gld
->iSetupFunc
];
332 tnl
->Driver
.Render
.Line
= _gldSetupLine
[gld
->iSetupFunc
];
333 tnl
->Driver
.Render
.Triangle
= _gldSetupTriangle
[gld
->iSetupFunc
];
334 tnl
->Driver
.Render
.Quad
= _gldSetupQuad
[gld
->iSetupFunc
];
336 dwFlags
= DDLOCK_DISCARDCONTENTS
| DDLOCK_WAIT
| DDLOCK_SURFACEMEMORYPTR
| DDLOCK_WRITEONLY
;
337 _GLD_DX7_VB(Lock(gldPB
->pVB
, dwFlags
, &gldPB
->pPoints
, NULL
));
338 gldPB
->nPoints
= gldPB
->nLines
= gldPB
->nTriangles
= 0;
340 // Allocate primitive pointers - gldPB->pPoints is always first
341 gldPB
->pLines
= gldPB
->pPoints
+ (gldPB
->dwStride
* gldPB
->iFirstLine
);
342 gldPB
->pTriangles
= gldPB
->pPoints
+ (gldPB
->dwStride
* gldPB
->iFirstTriangle
);
344 ASSERT(tnl
->Driver
.Render
.BuildVertices
);
345 ASSERT(tnl
->Driver
.Render
.PrimitiveNotify
);
346 ASSERT(tnl
->Driver
.Render
.Points
);
347 ASSERT(tnl
->Driver
.Render
.Line
);
348 ASSERT(tnl
->Driver
.Render
.Triangle
);
349 ASSERT(tnl
->Driver
.Render
.Quad
);
350 ASSERT(tnl
->Driver
.Render
.ResetLineStipple
);
351 ASSERT(tnl
->Driver
.Render
.Interp
);
352 ASSERT(tnl
->Driver
.Render
.CopyPV
);
353 ASSERT(tnl
->Driver
.Render
.ClippedLine
);
354 ASSERT(tnl
->Driver
.Render
.ClippedPolygon
);
355 ASSERT(tnl
->Driver
.Render
.Finish
);
357 tnl
->Driver
.Render
.BuildVertices( ctx
, 0, VB
->Count
, ~0 );
359 if (VB
->ClipOrMask
) {
360 tab
= VB
->Elts
? clip_render_tab_elts
: clip_render_tab_verts
;
361 clip_render_tab_elts
[GL_TRIANGLES
] = clip_elt_triangles
;
365 tnl
->Driver
.Render
.PrimTabElts
:
366 tnl
->Driver
.Render
.PrimTabVerts
);
370 GLuint i
, length
, flags
= 0;
371 for (i
= 0 ; !(flags
& PRIM_END
) ; i
+= length
) {
372 flags
= VB
->Primitive
[i
].mode
;
373 length
= VB
->Primitive
[i
].count
;
374 ASSERT(length
|| (flags
& PRIM_END
));
375 ASSERT((flags
& PRIM_MODE_MASK
) <= GL_POLYGON
+1);
377 tab
[flags
& PRIM_MODE_MASK
]( ctx
, i
, i
+ length
, flags
);
379 } while (tnl
->Driver
.Render
.Multipass
&&
380 tnl
->Driver
.Render
.Multipass( ctx
, ++pass
));
383 // tnl->Driver.Render.Finish( ctx );
385 _GLD_DX7_VB(Unlock(gldPB
->pVB
));
387 if (gldPB
->nPoints
) {
388 _GLD_DX7_DEV(DrawPrimitiveVB(gld
->pDev
, D3DPT_POINTLIST
, gldPB
->pVB
, 0, gldPB
->nPoints
, 0));
393 _GLD_DX7_DEV(DrawPrimitiveVB(gld
->pDev
, D3DPT_LINELIST
, gldPB
->pVB
, gldPB
->iFirstLine
, gldPB
->nLines
*2, 0));
397 if (gldPB
->nTriangles
) {
398 _GLD_DX7_DEV(DrawPrimitiveVB(gld
->pDev
, D3DPT_TRIANGLELIST
, gldPB
->pVB
, gldPB
->iFirstTriangle
, gldPB
->nTriangles
*3, 0));
399 gldPB
->nTriangles
= 0;
402 return GL_FALSE
; /* finished the pipe */
406 /**********************************************************************/
407 /* Render pipeline stage */
408 /**********************************************************************/
412 const struct tnl_pipeline_stage _gld_mesa_render_stage
=
414 "gld_mesa_render_stage",
419 _gld_mesa_render_stage_run
/* run */
422 //---------------------------------------------------------------------------