source: trunk/src/opengl/mesa/vbrender.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 22.4 KB
Line 
1/* $Id: vbrender.c,v 1.3 2000-05-23 20:41:03 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * Render points, lines, and polygons. The only entry point to this
30 * file is the gl_render_vb() function. This function is called after
31 * the vertex buffer has filled up or a state change has occurred.
32 *
33 * This file basically only makes calls to the clipping functions and
34 * the point, line and triangle rasterizers via the function pointers.
35 * context->Driver.PointsFunc()
36 * context->Driver.LineFunc()
37 * context->Driver.TriangleFunc()
38 */
39
40
41#ifdef PC_HEADER
42#include "all.h"
43#else
44#include "glheader.h"
45#include "clip.h"
46#include "types.h"
47#include "context.h"
48#include "light.h"
49#include "lines.h"
50#include "macros.h"
51#include "matrix.h"
52#include "pb.h"
53#include "points.h"
54#include "pipeline.h"
55#include "stages.h"
56#include "vb.h"
57#include "vbcull.h"
58#include "vbrender.h"
59#include "vbindirect.h"
60#include "xform.h"
61#endif
62
63
64/*
65 * This file implements rendering of points, lines and polygons defined by
66 * vertices in the vertex buffer.
67 */
68
69/*
70 * Render a line segment from VB[v1] to VB[v2] when either one or both
71 * endpoints must be clipped.
72 */
73void gl_render_clipped_line( GLcontext *ctx, GLuint v1, GLuint v2 )
74{
75 GLuint pv = v2;
76 struct vertex_buffer *VB = ctx->VB;
77 GLubyte mask = (GLubyte) (VB->ClipMask[v1] | VB->ClipMask[v2]);
78/* GLubyte andmask = VB->ClipMask[v1] & VB->ClipMask[v2]; */
79
80 if ((ctx->line_clip_tab[VB->ClipPtr->size])( VB, &v1, &v2, mask ))
81 ctx->Driver.LineFunc( ctx, v1, v2, pv );
82}
83
84static INLINE void gl_render_clipped_line2( GLcontext *ctx,
85 GLuint v1, GLuint v2 )
86{
87 GLuint pv = v2;
88 struct vertex_buffer *VB = ctx->VB;
89 GLubyte mask = (GLubyte) (VB->ClipMask[v1] | VB->ClipMask[v2]);
90
91 if (!mask || (ctx->line_clip_tab[VB->ClipPtr->size])( VB, &v1, &v2, mask ))
92 ctx->Driver.LineFunc( ctx, v1, v2, pv );
93}
94
95
96
97/*
98 * Compute Z offsets for a polygon with plane defined by (A,B,C,D)
99 * D is not needed.
100 */
101static void offset_polygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c )
102{
103 GLfloat ac, bc, m;
104 GLfloat offset;
105
106 if (c<0.001F && c>-0.001F) {
107 /* to prevent underflow problems */
108 offset = 0.0F;
109 }
110 else {
111 ac = a / c;
112 bc = b / c;
113 if (ac<0.0F) ac = -ac;
114 if (bc<0.0F) bc = -bc;
115 m = MAX2( ac, bc );
116 /* m = sqrt( ac*ac + bc*bc ); */
117
118 offset = m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits;
119 }
120
121 ctx->PointZoffset = ctx->Polygon.OffsetPoint ? offset : 0.0F;
122 ctx->LineZoffset = ctx->Polygon.OffsetLine ? offset : 0.0F;
123 ctx->PolygonZoffset = ctx->Polygon.OffsetFill ? offset : 0.0F;
124}
125
126#define FLUSH_PRIM(prim) \
127do { \
128 if (ctx->PB->primitive != prim) { \
129 gl_reduced_prim_change( ctx, prim ); \
130 } \
131} while(0)
132
133
134/*
135 * When glPolygonMode() is used to specify that the front/back rendering
136 * mode for polygons is not GL_FILL we end up calling this function.
137 */
138static void unfilled_polygon( GLcontext *ctx,
139 GLuint n, GLuint vlist[],
140 GLuint pv, GLuint facing )
141{
142 GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
143 struct vertex_buffer *VB = ctx->VB;
144 GLubyte *edge_ptr = (GLubyte *)VB->EdgeFlagPtr->data;
145
146 FLUSH_PRIM(mode);
147
148 if (mode==GL_POINT) {
149 GLuint i, j;
150 for (i=0;i<n;i++) {
151 j = vlist[i];
152 if (edge_ptr[j] & 0x3) {
153 edge_ptr[j] &= ~0x3;
154 (*ctx->Driver.PointsFunc)( ctx, j, j );
155 }
156 }
157 }
158 else if (mode==GL_LINE) {
159 GLuint i, j0, j1;
160 ctx->StippleCounter = 0;
161
162 /* draw the edges */
163 for (i=0;i<n-1;i++) {
164 j0 = vlist[i];
165 j1 = vlist[i+1];
166
167 if (edge_ptr[j0] & 0x1) {
168 edge_ptr[j0] &= ~0x1;
169 (*ctx->Driver.LineFunc)( ctx, j0, j1, pv );
170 }
171 }
172
173 /* last edge is special */
174 j0 = vlist[i];
175 j1 = vlist[0];
176
177 if (edge_ptr[j0] & 0x2) {
178 edge_ptr[j0] &= ~0x2;
179 (*ctx->Driver.LineFunc)( ctx, j0, j1, pv );
180 }
181 }
182 else {
183 /* Fill the polygon */
184 GLuint j0, i;
185 j0 = vlist[0];
186 for (i=2;i<n;i++) {
187 (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
188 }
189 }
190}
191
192
193
194
195/*
196 * Render a polygon in which at least one vertex has to be clipped.
197 * Input: n - number of vertices
198 * vlist - list of vertices in the polygon.
199 * CCW order = front facing.
200 */
201void gl_render_clipped_triangle( GLcontext *ctx, GLuint n, GLuint vlist[],
202 GLuint pv )
203{
204 struct vertex_buffer *VB = ctx->VB;
205 GLubyte mask = 0;
206 GLuint i;
207
208 for (i = 0 ; i < n ; i++)
209 mask |= VB->ClipMask[vlist[i]];
210
211 n = (ctx->poly_clip_tab[VB->ClipPtr->size])( VB, n, vlist, mask );
212
213 for (i=2;i<n;i++)
214 ctx->TriangleFunc( ctx, *vlist, vlist[i-1], vlist[i], pv );
215}
216
217
218static INLINE void gl_render_clipped_triangle2( GLcontext *ctx,
219 GLuint v1, GLuint v2, GLuint v3,
220 GLuint pv )
221{
222 struct vertex_buffer *VB = ctx->VB;
223 GLubyte mask = (GLubyte) (VB->ClipMask[v1] |
224 VB->ClipMask[v2] |
225 VB->ClipMask[v3]);
226 GLuint vlist[VB_MAX_CLIPPED_VERTS];
227 GLuint i, n;
228
229 if (!mask) {
230 ctx->TriangleFunc( ctx, v1, v2, v3, pv );
231 return;
232 }
233
234 if (CLIP_ALL_BITS & VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3])
235 return;
236
237 ASSIGN_3V(vlist, v1, v2, v3 );
238 n = (ctx->poly_clip_tab[VB->ClipPtr->size])( VB, 3, vlist, mask );
239
240 for (i=2;i<n;i++)
241 ctx->TriangleFunc( ctx, *vlist, vlist[i-1], vlist[i], pv );
242}
243
244
245static INLINE void gl_render_clipped_quad2( GLcontext *ctx,
246 GLuint v1, GLuint v2, GLuint v3,
247 GLuint v4,
248 GLuint pv )
249{
250 struct vertex_buffer *VB = ctx->VB;
251 GLubyte mask = (GLubyte) (VB->ClipMask[v1] |
252 VB->ClipMask[v2] |
253 VB->ClipMask[v3] |
254 VB->ClipMask[v4]);
255 GLuint vlist[VB_MAX_CLIPPED_VERTS];
256 GLuint i, n;
257
258 if (!mask) {
259 ctx->QuadFunc( ctx, v1, v2, v3, v4, pv );
260 return;
261 }
262
263 if (CLIP_ALL_BITS & VB->ClipMask[v1] &
264 VB->ClipMask[v2] & VB->ClipMask[v3] &
265 VB->ClipMask[v4])
266 return;
267
268 ASSIGN_4V(vlist, v1, v2, v3, v4 );
269 n = (ctx->poly_clip_tab[VB->ClipPtr->size])( VB, 4, vlist, mask );
270
271 for (i=2;i<n;i++)
272 ctx->TriangleFunc( ctx, *vlist, vlist[i-1], vlist[i], pv );
273}
274
275
276/* Implements triangle_rendering when (IndirectTriangles & DD_SW_SETUP)
277 * is non-zero.
278 */
279static void render_triangle( GLcontext *ctx,
280 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
281{
282 struct vertex_buffer *VB = ctx->VB;
283 GLfloat (*win)[4] = VB->Win.data;
284 GLfloat ex = win[v1][0] - win[v0][0];
285 GLfloat ey = win[v1][1] - win[v0][1];
286 GLfloat fx = win[v2][0] - win[v0][0];
287 GLfloat fy = win[v2][1] - win[v0][1];
288 GLfloat c = ex*fy-ey*fx;
289 GLuint facing;
290 GLuint tricaps;
291
292 if (c * ctx->backface_sign > 0)
293 return;
294
295 facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
296 tricaps = ctx->IndirectTriangles;
297
298 if (tricaps & DD_TRI_OFFSET) {
299 /* finish computing plane equation of polygon, compute offset */
300 GLfloat fz = win[v2][2] - win[v0][2];
301 GLfloat ez = win[v1][2] - win[v0][2];
302 GLfloat a = ey*fz-ez*fy;
303 GLfloat b = ez*fx-ex*fz;
304 offset_polygon( ctx, a, b, c );
305 }
306
307 if (tricaps & DD_TRI_LIGHT_TWOSIDE) {
308 VB->Specular = VB->Spec[facing];
309 VB->ColorPtr = VB->Color[facing];
310 VB->IndexPtr = VB->Index[facing];
311 }
312
313 if (tricaps & DD_TRI_UNFILLED) {
314 GLuint vlist[3];
315 vlist[0] = v0;
316 vlist[1] = v1;
317 vlist[2] = v2;
318 unfilled_polygon( ctx, 3, vlist, pv, facing );
319 }
320 else {
321 (*ctx->Driver.TriangleFunc)( ctx, v0, v1, v2, pv );
322 }
323}
324
325
326static void null_triangle( GLcontext *ctx,
327 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
328{
329}
330
331
332/* Implements triangle_rendering when (IndirectTriangles & DD_SW_SETUP)
333 * is non-zero.
334 */
335static void render_quad( GLcontext *ctx, GLuint v0, GLuint v1,
336 GLuint v2, GLuint v3, GLuint pv )
337{
338 struct vertex_buffer *VB = ctx->VB;
339 GLfloat (*win)[4] = VB->Win.data;
340 GLfloat ex = win[v2][0] - win[v0][0];
341 GLfloat ey = win[v2][1] - win[v0][1];
342 GLfloat fx = win[v3][0] - win[v1][0];
343 GLfloat fy = win[v3][1] - win[v1][1];
344 GLfloat c = ex*fy-ey*fx;
345 GLuint facing;
346 GLuint tricaps = ctx->IndirectTriangles;
347
348 if (c * ctx->backface_sign > 0)
349 return;
350
351 facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
352
353 if (tricaps & DD_TRI_OFFSET) {
354 GLfloat ez = win[v2][2] - win[v0][2];
355 GLfloat fz = win[v3][2] - win[v1][2];
356 GLfloat a = ey*fz-ez*fy;
357 GLfloat b = ez*fx-ex*fz;
358 offset_polygon( ctx, a, b, c );
359 }
360
361
362 if (tricaps & DD_TRI_LIGHT_TWOSIDE) {
363 VB->Specular = VB->Spec[facing];
364 VB->ColorPtr = VB->Color[facing];
365 VB->IndexPtr = VB->Index[facing];
366 }
367
368
369 /* Render the quad! */
370 if (tricaps & DD_TRI_UNFILLED) {
371 GLuint vlist[4];
372 vlist[0] = v0;
373 vlist[1] = v1;
374 vlist[2] = v2;
375 vlist[3] = v3;
376 unfilled_polygon( ctx, 4, vlist, pv, facing );
377 }
378 else {
379 (*ctx->Driver.QuadFunc)( ctx, v0, v1, v2, v3, pv );
380 }
381}
382
383
384#if 0
385static void null_quad( GLcontext *ctx, GLuint v0, GLuint v1,
386 GLuint v2, GLuint v3, GLuint pv )
387{
388}
389#endif
390
391
392extern const char *gl_prim_name[];
393
394
395/*
396 * Either the vertex buffer is full (VB->Count==VB_MAX) or glEnd() has been
397 * called. Render the primitives defined by the vertices and reset the
398 * buffer.
399 *
400 * This function won't be called if the device driver implements a
401 * RenderVB() function.
402 */
403
404#define NEED_EDGEFLAG_SETUP (ctx->TriangleCaps & DD_TRI_UNFILLED)
405
406#define EDGEFLAG_TRI( i2, i1, i, pv, parity) \
407do { \
408 eflag[i2] = eflag[i1] = 1; eflag[i] = 2; \
409} while (0)
410
411#define EDGEFLAG_QUAD( i3, i2, i1, i, pv) \
412do { \
413 eflag[i3] = eflag[i2] = eflag[i1] = 1; eflag[i] = 2; \
414} while (0)
415
416
417#define EDGEFLAG_POLY_TRI_PRE( i2, i1, i, pv) \
418do { \
419 eflag[i1] |= (eflag[i1] >> 2) & 1; \
420 eflag[i] |= (eflag[i] >> 2) & 2; \
421} while (0)
422
423#define EDGEFLAG_POLY_TRI_POST( i2, i1, i, pv) \
424do { \
425 eflag[i2] = 0; \
426 eflag[i1] &= ~(4|1); \
427 eflag[i] &= ~(8|2); \
428} while (0)
429
430
431
432/* Culled and possibly clipped primitives.
433 */
434#define RENDER_POINTS( start, count ) \
435 (void) cullmask; \
436 (*ctx->Driver.PointsFunc)( ctx, start, count-1 );
437
438
439#define RENDER_LINE( i1, i ) \
440do { \
441 const GLubyte flags = cullmask[i]; \
442 \
443 if (!(flags & PRIM_NOT_CULLED)) \
444 continue; \
445 \
446 if (flags & PRIM_ANY_CLIP) \
447 gl_render_clipped_line( ctx, i1, i ); \
448 else \
449 ctx->Driver.LineFunc( ctx, i1, i, i ); \
450} while (0)
451
452
453
454#define RENDER_TRI( i2, i1, i, pv, parity) \
455do { \
456 const GLubyte flags = cullmask[i]; \
457 \
458 if (!(flags & PRIM_NOT_CULLED)) \
459 continue; \
460 \
461 if (flags & PRIM_ANY_CLIP) { \
462 if (parity) { \
463 vlist[0] = i1; \
464 vlist[1] = i2; \
465 vlist[2] = i; \
466 } else { \
467 vlist[0] = i2; \
468 vlist[1] = i1; \
469 vlist[2] = i; \
470 } \
471 gl_render_clipped_triangle( ctx, 3, vlist, pv ); \
472 } else if (parity) \
473 ctx->TriangleFunc( ctx, i1, i2, i, pv ); \
474 else \
475 ctx->TriangleFunc( ctx, i2, i1, i, pv ); \
476 \
477} while (0)
478
479
480#define RENDER_QUAD( i3, i2, i1, i, pv) \
481do { \
482 const GLubyte flags = cullmask[i]; \
483 \
484 if (!(flags & PRIM_NOT_CULLED)) \
485 continue; \
486 \
487 if (flags&PRIM_ANY_CLIP) { \
488 vlist[0] = i3; \
489 vlist[1] = i2; \
490 vlist[2] = i1; \
491 vlist[3] = i; \
492 gl_render_clipped_triangle( ctx, 4, vlist, pv ); \
493 } else \
494 ctx->QuadFunc( ctx, i3, i2, i1, i, pv ); \
495} while (0)
496
497
498#define LOCAL_VARS \
499 GLcontext *ctx = VB->ctx; \
500 const GLubyte *cullmask = VB->CullMask; \
501 GLuint vlist[VB_SIZE]; \
502 GLubyte *eflag = VB->EdgeFlagPtr->data; \
503 GLuint *stipplecounter = &VB->ctx->StippleCounter; \
504 (void) vlist; (void) eflag; (void) stipplecounter;
505
506#define TAG(x) x##_cull
507#define INIT(x) FLUSH_PRIM(x)
508#define RESET_STIPPLE *stipplecounter = 0
509#include "render_tmp.h"
510
511
512
513
514
515
516
517/* Direct, no clipping or culling.
518 */
519#define RENDER_POINTS( start, count ) \
520 (*ctx->Driver.PointsFunc)( ctx, start, count-1 )
521
522#define RENDER_LINE( i1, i ) \
523 (*ctx->Driver.LineFunc)( ctx, i1, i, i )
524
525#define RENDER_TRI( i2, i1, i, pv, parity ) \
526do { \
527 if (parity) \
528 ctx->TriangleFunc( ctx, i1, i2, i, pv ); \
529 else \
530 ctx->TriangleFunc( ctx, i2, i1, i, pv ); \
531} while (0)
532
533
534#define RENDER_QUAD( i3, i2, i1, i, pv ) \
535 ctx->QuadFunc( ctx, i3, i2, i1, i, i );
536
537#define TAG(x) x##_raw
538
539#define LOCAL_VARS \
540 GLcontext *ctx = VB->ctx; \
541 GLubyte *eflag = VB->EdgeFlagPtr->data; \
542 GLuint *stipplecounter = &VB->ctx->StippleCounter; \
543 (void) eflag; (void) stipplecounter;
544
545#define INIT(x) FLUSH_PRIM(x);
546#define RESET_STIPPLE *stipplecounter = 0
547#include "render_tmp.h"
548
549
550
551
552/* Direct, with the possibility of clipping.
553 */
554#define RENDER_POINTS( start, count ) \
555 (*ctx->Driver.PointsFunc)( ctx, start, count-1 )
556
557#define RENDER_LINE( i1, i ) \
558 gl_render_clipped_line2( ctx, i1, i )
559
560#define RENDER_TRI( i2, i1, i, pv, parity) \
561do { \
562 GLuint e2=i2, e1=i1; \
563 if (parity) { GLuint t=e2; e2=e1; e1=t; } \
564 gl_render_clipped_triangle2(ctx,e2,e1,i,pv); \
565} while (0)
566
567#define RENDER_QUAD( i3, i2, i1, i, pv) \
568do { \
569 gl_render_clipped_quad2(ctx,i3,i2,i1,i,pv); \
570} while (0)
571
572
573#define LOCAL_VARS \
574 GLcontext *ctx = VB->ctx; \
575 GLubyte *eflag = VB->EdgeFlagPtr->data; \
576 GLuint *stipplecounter = &VB->ctx->StippleCounter; \
577 (void) eflag; (void) stipplecounter;
578
579#define INIT(x) FLUSH_PRIM(x);
580#define TAG(x) x##_clipped
581#define RESET_STIPPLE *stipplecounter = 0
582
583#include "render_tmp.h"
584
585/* Bits:
586 * 0x1 - draw this edge if it is first or second in a triangle.
587 * 0x2 - draw this edge if it is last in a triangle.
588 * 0x4 - placeholder for multipass rendering.
589 *
590 * Bits 0x1 and 0x2 are cleared after they are used. Bit 0x4 is used
591 * to stop these values going to zero in multipass rendering.
592 *
593 * Clipping introduces vertices on outgoing edges with edgeflag 0x1.
594 * Incoming edges retain the value of the clipped vertex, with the following
595 * masks:
596 * - If the incoming edge originates from the last vertex in the
597 * clipped primitive (triangle or quad), the introduced vertex
598 * retains both bits (0x3) of the original flag.
599 * - All other introduced vertices retain only bit 1 (0x1).
600 *
601 * In a horrible hack I've had to push tristrips, fans & quadstrip handling
602 * into render_tmp.h...
603 *
604 * Keith.
605 */
606static void
607setup_edgeflag( struct vertex_buffer *VB,
608 GLenum prim,
609 GLuint start,
610 GLuint count,
611 GLuint parity )
612{
613 GLubyte *flag = VB->EdgeFlagPtr->data + start;
614 GLuint n = count - start;
615 GLuint i;
616 (void) parity;
617
618 switch (prim) {
619 case GL_TRIANGLES:
620 for (i = 0 ; i < n-2 ; i+=3) {
621 if (flag[i]) flag[i] = 0x1;
622 if (flag[i+1]) flag[i+1] = 0x1;
623 if (flag[i+2]) flag[i+2] = 0x3;
624 }
625 break;
626 case GL_QUADS:
627 for (i = 0 ; i < n-3 ; i+=4) {
628 if (flag[i]) flag[i] = 0x1;
629 if (flag[i+1]) flag[i+1] = 0x1;
630 if (flag[i+2]) flag[i+2] = 0x1;
631 if (flag[i+3]) flag[i+3] = 0x3;
632 }
633 break;
634 case GL_POLYGON:
635 if (flag[0]) flag[0] = 0x1;
636 for (i = 1 ; i < n-1 ; i++) {
637 if (flag[i]) flag[i] = 0x1<<2;
638 }
639 if (flag[i]) flag[i] = 0x3<<2;
640 break;
641 default:
642 break;
643 }
644}
645
646
647
648/* Could eventually generalize to handle changes of rasterization
649 * state other than change-of-primitive. An example might be
650 * some bind-texture calls.
651 */
652void gl_render_vb( struct vertex_buffer *VB )
653{
654 GLcontext *ctx = VB->ctx;
655 GLuint i, next, prim;
656 GLuint parity = VB->Parity;
657 render_func *tab;
658 GLuint count = VB->Count;
659 GLint p = 0;
660
661 if (VB->Indirect) {
662/* gl_render_vb_indirect( VB, VB ); */
663 return;
664 } else if (VB->CullMode & CULL_MASK_ACTIVE) {
665 tab = ctx->Driver.RenderVBCulledTab;
666 } else if (VB->CullMode & CLIP_MASK_ACTIVE) {
667 tab = ctx->Driver.RenderVBClippedTab;
668 } else {
669 tab = ctx->Driver.RenderVBRawTab;
670 }
671
672 if (!VB->CullDone)
673 gl_fast_copy_vb( VB );
674
675 if (ctx->TriangleCaps & DD_TRI_UNFILLED)
676 gl_import_client_data( VB, VERT_EDGE, VEC_WRITABLE|VEC_GOOD_STRIDE );
677
678 gl_import_client_data( VB, ctx->RenderFlags,
679 (VB->ClipOrMask
680 ? VEC_WRITABLE|VEC_GOOD_STRIDE
681 : VEC_GOOD_STRIDE));
682
683 if (/* ctx->Current.Primitive == GL_POLYGON+1 && */
684 ctx->Driver.RenderStart)
685 ctx->Driver.RenderStart( ctx );
686
687 do
688 {
689 for ( i= VB->CopyStart ; i < count ; parity = 0, i = next )
690 {
691 prim = VB->Primitive[i];
692 next = VB->NextPrimitive[i];
693
694 if (ctx->TriangleCaps & DD_TRI_UNFILLED)
695 setup_edgeflag(VB, prim, i, next, parity);
696
697 tab[prim]( VB, i, next, parity );
698
699 if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
700 VB->Specular = VB->Spec[0];
701 VB->ColorPtr = VB->Color[0];
702 VB->IndexPtr = VB->Index[0];
703 }
704 }
705
706 } while (ctx->Driver.MultipassFunc &&
707 ctx->Driver.MultipassFunc( VB, ++p ));
708
709 if (ctx->PB->count > 0)
710 gl_flush_pb(ctx);
711
712 if (/* ctx->Current.Primitive == GL_POLYGON+1 && */
713 ctx->Driver.RenderFinish)
714 ctx->Driver.RenderFinish( ctx );
715}
716
717
718void gl_reduced_prim_change( GLcontext *ctx, GLenum prim )
719{
720 if (ctx->PB->count > 0)
721 gl_flush_pb(ctx);
722
723 ctx->PB->count = 0;
724 ctx->PB->mono = GL_FALSE;
725
726 if (ctx->PB->primitive != prim) {
727 ctx->PB->primitive = prim;
728
729 if (ctx->Driver.ReducedPrimitiveChange)
730 ctx->Driver.ReducedPrimitiveChange( ctx, prim );
731 }
732}
733
734
735void gl_set_render_vb_function( GLcontext *ctx )
736{
737 if (ctx->Driver.RenderVBCulledTab == 0)
738 ctx->Driver.RenderVBCulledTab = render_tab_cull;
739
740 if (ctx->Driver.RenderVBClippedTab == 0)
741 ctx->Driver.RenderVBClippedTab = render_tab_clipped;
742
743 if (ctx->Driver.RenderVBRawTab == 0)
744 ctx->Driver.RenderVBRawTab = render_tab_raw;
745
746 ctx->TriangleFunc = ctx->Driver.TriangleFunc;
747 ctx->QuadFunc = ctx->Driver.QuadFunc;
748 ctx->ClippedTriangleFunc = ctx->TriangleFunc;
749
750 if (ctx->IndirectTriangles & DD_SW_SETUP) {
751
752 ctx->ClippedTriangleFunc = render_triangle;
753
754 if (ctx->IndirectTriangles & (DD_SW_SETUP & ~DD_TRI_CULL)) {
755 if (ctx->IndirectTriangles & DD_TRI_CULL_FRONT_BACK) {
756 ctx->TriangleFunc = null_triangle;
757 ctx->QuadFunc = render_quad;
758 ctx->ClippedTriangleFunc = null_triangle;
759 } else {
760 ctx->TriangleFunc = render_triangle;
761 ctx->QuadFunc = render_quad;
762 }
763 }
764 }
765}
766
767void gl_init_vbrender( void )
768{
769 render_init_raw();
770 render_init_cull();
771 render_init_clipped();
772}
773
774
775
776
Note: See TracBrowser for help on using the repository browser.