1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2007  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
28b8e80941Smrg#include "c99_math.h"
29848b8605Smrg#include "main/glheader.h"
30848b8605Smrg#include "main/macros.h"
31848b8605Smrg#include "main/mtypes.h"
32b8e80941Smrg#include "main/stencil.h"
33b8e80941Smrg#include "main/state.h"
34848b8605Smrg
35848b8605Smrg#include "tnl/t_context.h"
36848b8605Smrg
37848b8605Smrg#include "ss_triangle.h"
38848b8605Smrg#include "ss_context.h"
39848b8605Smrg
40848b8605Smrg#define SS_OFFSET_BIT	    0x1
41848b8605Smrg#define SS_TWOSIDE_BIT	    0x2
42848b8605Smrg#define SS_UNFILLED_BIT	    0x4
43848b8605Smrg#define SS_MAX_TRIFUNC      0x8
44848b8605Smrg
45848b8605Smrgstatic tnl_triangle_func tri_tab[SS_MAX_TRIFUNC];
46848b8605Smrgstatic tnl_quad_func     quad_tab[SS_MAX_TRIFUNC];
47848b8605Smrg
48848b8605Smrg
49848b8605Smrg/*
50848b8605Smrg * Render a triangle respecting edge flags.
51848b8605Smrg */
52848b8605Smrgtypedef void (* swsetup_edge_render_prim_tri)(struct gl_context *ctx,
53848b8605Smrg                                              const GLubyte *ef,
54848b8605Smrg                                              GLuint e0,
55848b8605Smrg                                              GLuint e1,
56848b8605Smrg                                              GLuint e2,
57848b8605Smrg                                              const SWvertex *v0,
58848b8605Smrg                                              const SWvertex *v1,
59848b8605Smrg                                              const SWvertex *v2);
60848b8605Smrg
61848b8605Smrg/*
62848b8605Smrg * Render a triangle using lines and respecting edge flags.
63848b8605Smrg */
64848b8605Smrgstatic void
65848b8605Smrg_swsetup_edge_render_line_tri(struct gl_context *ctx,
66848b8605Smrg                              const GLubyte *ef,
67848b8605Smrg                              GLuint e0,
68848b8605Smrg                              GLuint e1,
69848b8605Smrg                              GLuint e2,
70848b8605Smrg                              const SWvertex *v0,
71848b8605Smrg                              const SWvertex *v1,
72848b8605Smrg                              const SWvertex *v2)
73848b8605Smrg{
74848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
75848b8605Smrg
76848b8605Smrg   if (swsetup->render_prim == GL_POLYGON) {
77848b8605Smrg      if (ef[e2]) _swrast_Line( ctx, v2, v0 );
78848b8605Smrg      if (ef[e0]) _swrast_Line( ctx, v0, v1 );
79848b8605Smrg      if (ef[e1]) _swrast_Line( ctx, v1, v2 );
80848b8605Smrg   } else {
81848b8605Smrg      if (ef[e0]) _swrast_Line( ctx, v0, v1 );
82848b8605Smrg      if (ef[e1]) _swrast_Line( ctx, v1, v2 );
83848b8605Smrg      if (ef[e2]) _swrast_Line( ctx, v2, v0 );
84848b8605Smrg   }
85848b8605Smrg}
86848b8605Smrg
87848b8605Smrg/*
88848b8605Smrg * Render a triangle using points and respecting edge flags.
89848b8605Smrg */
90848b8605Smrgstatic void
91848b8605Smrg_swsetup_edge_render_point_tri(struct gl_context *ctx,
92848b8605Smrg                               const GLubyte *ef,
93848b8605Smrg                               GLuint e0,
94848b8605Smrg                               GLuint e1,
95848b8605Smrg                               GLuint e2,
96848b8605Smrg                               const SWvertex *v0,
97848b8605Smrg                               const SWvertex *v1,
98848b8605Smrg                               const SWvertex *v2)
99848b8605Smrg{
100848b8605Smrg   if (ef[e0]) _swrast_Point( ctx, v0 );
101848b8605Smrg   if (ef[e1]) _swrast_Point( ctx, v1 );
102848b8605Smrg   if (ef[e2]) _swrast_Point( ctx, v2 );
103848b8605Smrg
104848b8605Smrg   _swrast_flush(ctx);
105848b8605Smrg}
106848b8605Smrg
107848b8605Smrg/*
108848b8605Smrg * Render a triangle respecting cull and shade model.
109848b8605Smrg */
110848b8605Smrgstatic void _swsetup_render_tri(struct gl_context *ctx,
111848b8605Smrg                                GLuint e0,
112848b8605Smrg                                GLuint e1,
113848b8605Smrg                                GLuint e2,
114848b8605Smrg                                GLuint facing,
115848b8605Smrg                                swsetup_edge_render_prim_tri render)
116848b8605Smrg{
117848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
118848b8605Smrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
119848b8605Smrg   GLubyte *ef = VB->EdgeFlag;
120848b8605Smrg   SWvertex *verts = swsetup->verts;
121848b8605Smrg   SWvertex *v0 = &verts[e0];
122848b8605Smrg   SWvertex *v1 = &verts[e1];
123848b8605Smrg   SWvertex *v2 = &verts[e2];
124848b8605Smrg
125848b8605Smrg   /* cull testing */
126848b8605Smrg   if (ctx->Polygon.CullFlag) {
127848b8605Smrg      if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
128848b8605Smrg         return;
129848b8605Smrg      if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
130848b8605Smrg         return;
131848b8605Smrg   }
132848b8605Smrg
133848b8605Smrg   _swrast_SetFacing(ctx, facing);
134848b8605Smrg
135848b8605Smrg   if (ctx->Light.ShadeModel == GL_FLAT) {
136848b8605Smrg      GLchan c[2][4];
137848b8605Smrg      GLfloat s[2][4];
138848b8605Smrg
139848b8605Smrg      /* save colors/indexes for v0, v1 vertices */
140848b8605Smrg      COPY_CHAN4(c[0], v0->color);
141848b8605Smrg      COPY_CHAN4(c[1], v1->color);
142848b8605Smrg      COPY_4V(s[0], v0->attrib[VARYING_SLOT_COL1]);
143848b8605Smrg      COPY_4V(s[1], v1->attrib[VARYING_SLOT_COL1]);
144848b8605Smrg
145848b8605Smrg      /* copy v2 color/indexes to v0, v1 indexes */
146848b8605Smrg      COPY_CHAN4(v0->color, v2->color);
147848b8605Smrg      COPY_CHAN4(v1->color, v2->color);
148848b8605Smrg      COPY_4V(v0->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
149848b8605Smrg      COPY_4V(v1->attrib[VARYING_SLOT_COL1], v2->attrib[VARYING_SLOT_COL1]);
150848b8605Smrg
151848b8605Smrg      render(ctx, ef, e0, e1, e2, v0, v1, v2);
152848b8605Smrg
153848b8605Smrg      COPY_CHAN4(v0->color, c[0]);
154848b8605Smrg      COPY_CHAN4(v1->color, c[1]);
155848b8605Smrg      COPY_4V(v0->attrib[VARYING_SLOT_COL1], s[0]);
156848b8605Smrg      COPY_4V(v1->attrib[VARYING_SLOT_COL1], s[1]);
157848b8605Smrg   }
158848b8605Smrg   else {
159848b8605Smrg      render(ctx, ef, e0, e1, e2, v0, v1, v2);
160848b8605Smrg   }
161848b8605Smrg}
162848b8605Smrg
163848b8605Smrg#define SS_COLOR(a,b) UNCLAMPED_FLOAT_TO_RGBA_CHAN(a,b)
164848b8605Smrg#define SS_SPEC(a,b) COPY_4V(a,b)
165848b8605Smrg#define SS_IND(a,b) (a = b)
166848b8605Smrg
167848b8605Smrg#define IND (0)
168848b8605Smrg#define TAG(x) x##_rgba
169848b8605Smrg#include "ss_tritmp.h"
170848b8605Smrg
171848b8605Smrg#define IND (SS_OFFSET_BIT)
172848b8605Smrg#define TAG(x) x##_offset_rgba
173848b8605Smrg#include "ss_tritmp.h"
174848b8605Smrg
175848b8605Smrg#define IND (SS_TWOSIDE_BIT)
176848b8605Smrg#define TAG(x) x##_twoside_rgba
177848b8605Smrg#include "ss_tritmp.h"
178848b8605Smrg
179848b8605Smrg#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT)
180848b8605Smrg#define TAG(x) x##_offset_twoside_rgba
181848b8605Smrg#include "ss_tritmp.h"
182848b8605Smrg
183848b8605Smrg#define IND (SS_UNFILLED_BIT)
184848b8605Smrg#define TAG(x) x##_unfilled_rgba
185848b8605Smrg#include "ss_tritmp.h"
186848b8605Smrg
187848b8605Smrg#define IND (SS_OFFSET_BIT|SS_UNFILLED_BIT)
188848b8605Smrg#define TAG(x) x##_offset_unfilled_rgba
189848b8605Smrg#include "ss_tritmp.h"
190848b8605Smrg
191848b8605Smrg#define IND (SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
192848b8605Smrg#define TAG(x) x##_twoside_unfilled_rgba
193848b8605Smrg#include "ss_tritmp.h"
194848b8605Smrg
195848b8605Smrg#define IND (SS_OFFSET_BIT|SS_TWOSIDE_BIT|SS_UNFILLED_BIT)
196848b8605Smrg#define TAG(x) x##_offset_twoside_unfilled_rgba
197848b8605Smrg#include "ss_tritmp.h"
198848b8605Smrg
199848b8605Smrg
200848b8605Smrgvoid _swsetup_trifuncs_init( struct gl_context *ctx )
201848b8605Smrg{
202848b8605Smrg   (void) ctx;
203848b8605Smrg
204848b8605Smrg   init_rgba();
205848b8605Smrg   init_offset_rgba();
206848b8605Smrg   init_twoside_rgba();
207848b8605Smrg   init_offset_twoside_rgba();
208848b8605Smrg   init_unfilled_rgba();
209848b8605Smrg   init_offset_unfilled_rgba();
210848b8605Smrg   init_twoside_unfilled_rgba();
211848b8605Smrg   init_offset_twoside_unfilled_rgba();
212848b8605Smrg}
213848b8605Smrg
214848b8605Smrg
215848b8605Smrgstatic void swsetup_points( struct gl_context *ctx, GLuint first, GLuint last )
216848b8605Smrg{
217848b8605Smrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
218848b8605Smrg   SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
219848b8605Smrg   GLuint i;
220848b8605Smrg
221848b8605Smrg   if (VB->Elts) {
222848b8605Smrg      for (i = first; i < last; i++)
223848b8605Smrg	 if (VB->ClipMask[VB->Elts[i]] == 0)
224848b8605Smrg	    _swrast_Point( ctx, &verts[VB->Elts[i]] );
225848b8605Smrg   }
226848b8605Smrg   else {
227848b8605Smrg      for (i = first; i < last; i++)
228848b8605Smrg	 if (VB->ClipMask[i] == 0)
229848b8605Smrg	    _swrast_Point( ctx, &verts[i] );
230848b8605Smrg   }
231848b8605Smrg}
232848b8605Smrg
233848b8605Smrgstatic void swsetup_line( struct gl_context *ctx, GLuint v0, GLuint v1 )
234848b8605Smrg{
235848b8605Smrg   SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
236848b8605Smrg   _swrast_Line( ctx, &verts[v0], &verts[v1] );
237848b8605Smrg}
238848b8605Smrg
239848b8605Smrg
240848b8605Smrg
241848b8605Smrgvoid _swsetup_choose_trifuncs( struct gl_context *ctx )
242848b8605Smrg{
243848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
244848b8605Smrg   GLuint ind = 0;
245848b8605Smrg
246848b8605Smrg   if (ctx->Polygon.OffsetPoint ||
247848b8605Smrg       ctx->Polygon.OffsetLine ||
248848b8605Smrg       ctx->Polygon.OffsetFill)
249848b8605Smrg      ind |= SS_OFFSET_BIT;
250848b8605Smrg
251848b8605Smrg   if ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||
252848b8605Smrg       (ctx->VertexProgram._Current && ctx->VertexProgram.TwoSideEnabled))
253848b8605Smrg      ind |= SS_TWOSIDE_BIT;
254848b8605Smrg
255848b8605Smrg   /* We piggyback the two-sided stencil front/back determination on the
256848b8605Smrg    * unfilled triangle path.
257848b8605Smrg    */
258848b8605Smrg   if (ctx->Polygon.FrontMode != GL_FILL ||
259848b8605Smrg       ctx->Polygon.BackMode != GL_FILL ||
260b8e80941Smrg       (ctx->Stencil.Enabled && _mesa_stencil_is_two_sided(ctx)))
261848b8605Smrg      ind |= SS_UNFILLED_BIT;
262848b8605Smrg
263848b8605Smrg   tnl->Driver.Render.Triangle = tri_tab[ind];
264848b8605Smrg   tnl->Driver.Render.Quad = quad_tab[ind];
265848b8605Smrg   tnl->Driver.Render.Line = swsetup_line;
266848b8605Smrg   tnl->Driver.Render.Points = swsetup_points;
267848b8605Smrg}
268