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
28848b8605Smrg#include "main/glheader.h"
29848b8605Smrg#include "main/imports.h"
30b8e80941Smrg#include "main/macros.h"
31b8e80941Smrg#include "main/state.h"
32848b8605Smrg#include "tnl/tnl.h"
33848b8605Smrg#include "tnl/t_context.h"
34848b8605Smrg#include "tnl/t_pipeline.h"
35848b8605Smrg#include "tnl/t_vertex.h"
36848b8605Smrg#include "swrast_setup.h"
37848b8605Smrg#include "ss_context.h"
38848b8605Smrg#include "ss_triangle.h"
39848b8605Smrg
40848b8605Smrg
41848b8605Smrg/* Need to check lighting state and vertex program state to know
42848b8605Smrg * if two-sided lighting is in effect.
43848b8605Smrg */
44848b8605Smrg#define _SWSETUP_NEW_RENDERINDEX (_NEW_POLYGON|_NEW_LIGHT|_NEW_PROGRAM)
45848b8605Smrg
46848b8605Smrg
47848b8605Smrg#define VARYING_EMIT_STYLE  EMIT_4F
48848b8605Smrg
49848b8605Smrg
50848b8605SmrgGLboolean
51848b8605Smrg_swsetup_CreateContext( struct gl_context *ctx )
52848b8605Smrg{
53848b8605Smrg   SScontext *swsetup = calloc(1, sizeof(SScontext));
54848b8605Smrg
55848b8605Smrg   if (!swsetup)
56848b8605Smrg      return GL_FALSE;
57848b8605Smrg
58848b8605Smrg   ctx->swsetup_context = swsetup;
59848b8605Smrg
60848b8605Smrg   swsetup->NewState = ~0;
61848b8605Smrg   _swsetup_trifuncs_init( ctx );
62848b8605Smrg
63848b8605Smrg   _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
64848b8605Smrg		       sizeof(SWvertex) );
65848b8605Smrg
66848b8605Smrg
67848b8605Smrg   return GL_TRUE;
68848b8605Smrg}
69848b8605Smrg
70848b8605Smrgvoid
71848b8605Smrg_swsetup_DestroyContext( struct gl_context *ctx )
72848b8605Smrg{
73848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
74848b8605Smrg
75848b8605Smrg   if (swsetup) {
76848b8605Smrg      free(swsetup);
77848b8605Smrg      ctx->swsetup_context = 0;
78848b8605Smrg   }
79848b8605Smrg
80848b8605Smrg   _tnl_free_vertices( ctx );
81848b8605Smrg}
82848b8605Smrg
83848b8605Smrgstatic void
84848b8605Smrg_swsetup_RenderPrimitive( struct gl_context *ctx, GLenum mode )
85848b8605Smrg{
86848b8605Smrg   SWSETUP_CONTEXT(ctx)->render_prim = mode;
87848b8605Smrg   _swrast_render_primitive( ctx, mode );
88848b8605Smrg}
89848b8605Smrg
90848b8605Smrg
91848b8605Smrg/**
92848b8605Smrg * Helper macros for setup_vertex_format()
93848b8605Smrg */
94848b8605Smrg#define SWZ ((SWvertex *)0)
95848b8605Smrg#define SWOffset(MEMBER) (((char *)&(SWZ->MEMBER)) - ((char *)SWZ))
96848b8605Smrg
97848b8605Smrg#define EMIT_ATTR( ATTR, STYLE, MEMBER )	\
98848b8605Smrgdo {						\
99848b8605Smrg   map[e].attrib = (ATTR);			\
100848b8605Smrg   map[e].format = (STYLE);			\
101848b8605Smrg   map[e].offset = SWOffset(MEMBER);	       	\
102848b8605Smrg   e++;						\
103848b8605Smrg} while (0)
104848b8605Smrg
105848b8605Smrg
106848b8605Smrg/**
107848b8605Smrg * Tell the tnl module how to build SWvertex objects for swrast.
108848b8605Smrg * We'll build the map[] array with that info and pass it to
109848b8605Smrg * _tnl_install_attrs().
110848b8605Smrg */
111848b8605Smrgstatic void
112848b8605Smrgsetup_vertex_format(struct gl_context *ctx)
113848b8605Smrg{
114848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
115848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
116848b8605Smrg   GLboolean intColors = !ctx->FragmentProgram._Current
117b8e80941Smrg                      && !_mesa_ati_fragment_shader_enabled(ctx)
118848b8605Smrg                      && ctx->RenderMode == GL_RENDER
119848b8605Smrg                      && CHAN_TYPE != GL_FLOAT;
120848b8605Smrg
121848b8605Smrg   if (intColors != swsetup->intColors ||
122848b8605Smrg       tnl->render_inputs_bitset != swsetup->last_index_bitset) {
123848b8605Smrg      GLbitfield64 index_bitset = tnl->render_inputs_bitset;
124848b8605Smrg      struct tnl_attr_map map[_TNL_ATTRIB_MAX];
125848b8605Smrg      unsigned int i, e = 0;
126848b8605Smrg
127848b8605Smrg      swsetup->intColors = intColors;
128848b8605Smrg
129848b8605Smrg      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, attrib[VARYING_SLOT_POS] );
130848b8605Smrg
131848b8605Smrg      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR0)) {
132848b8605Smrg         if (swsetup->intColors)
133848b8605Smrg            EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4CHAN_4F_RGBA, color );
134848b8605Smrg         else
135848b8605Smrg            EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4F, attrib[VARYING_SLOT_COL0]);
136848b8605Smrg      }
137848b8605Smrg
138848b8605Smrg      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
139848b8605Smrg         EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_4F, attrib[VARYING_SLOT_COL1]);
140848b8605Smrg      }
141848b8605Smrg
142848b8605Smrg      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
143848b8605Smrg         const GLint emit = ctx->FragmentProgram._Current ? EMIT_4F : EMIT_1F;
144848b8605Smrg         EMIT_ATTR( _TNL_ATTRIB_FOG, emit, attrib[VARYING_SLOT_FOGC]);
145848b8605Smrg      }
146848b8605Smrg
147848b8605Smrg      if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))
148848b8605Smrg      {
149848b8605Smrg         for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
150848b8605Smrg            if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) {
151848b8605Smrg               EMIT_ATTR( _TNL_ATTRIB_TEX(i), EMIT_4F,
152848b8605Smrg                          attrib[VARYING_SLOT_TEX0 + i] );
153848b8605Smrg            }
154848b8605Smrg         }
155848b8605Smrg      }
156848b8605Smrg
157848b8605Smrg      /* shader varying vars */
158848b8605Smrg      if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_GENERIC0, _TNL_NUM_GENERIC)) {
159848b8605Smrg         for (i = 0; i < ctx->Const.MaxVarying; i++) {
160848b8605Smrg            if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i))) {
161848b8605Smrg               EMIT_ATTR( _TNL_ATTRIB_GENERIC(i), VARYING_EMIT_STYLE,
162848b8605Smrg                          attrib[VARYING_SLOT_VAR0 + i] );
163848b8605Smrg            }
164848b8605Smrg         }
165848b8605Smrg      }
166848b8605Smrg
167848b8605Smrg      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE))
168848b8605Smrg         EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize );
169848b8605Smrg
170848b8605Smrg      _tnl_install_attrs( ctx, map, e,
171b8e80941Smrg                          tnl->_WindowMap.m,
172848b8605Smrg                          sizeof(SWvertex) );
173848b8605Smrg
174848b8605Smrg      swsetup->last_index_bitset = index_bitset;
175848b8605Smrg   }
176848b8605Smrg}
177848b8605Smrg
178848b8605Smrg
179848b8605Smrg/**
180848b8605Smrg * Prepare to render a vertex buffer.
181848b8605Smrg * Called via tnl->Driver.Render.Start.
182848b8605Smrg */
183848b8605Smrgstatic void
184848b8605Smrg_swsetup_RenderStart( struct gl_context *ctx )
185848b8605Smrg{
186848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
187848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
188848b8605Smrg   struct vertex_buffer *VB = &tnl->vb;
189848b8605Smrg
190848b8605Smrg   if (swsetup->NewState & _SWSETUP_NEW_RENDERINDEX) {
191848b8605Smrg      _swsetup_choose_trifuncs(ctx);
192848b8605Smrg   }
193848b8605Smrg
194848b8605Smrg   if (swsetup->NewState & _NEW_PROGRAM) {
195848b8605Smrg      swsetup->last_index_bitset = 0;
196848b8605Smrg   }
197848b8605Smrg
198848b8605Smrg   swsetup->NewState = 0;
199848b8605Smrg
200848b8605Smrg   /* This will change if drawing unfilled tris */
201848b8605Smrg   _swrast_SetFacing(ctx, 0);
202848b8605Smrg
203848b8605Smrg   _swrast_render_start(ctx);
204848b8605Smrg
205848b8605Smrg   /* Important */
206848b8605Smrg   VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
207848b8605Smrg
208848b8605Smrg   setup_vertex_format(ctx);
209848b8605Smrg}
210848b8605Smrg
211848b8605Smrg
212848b8605Smrg/*
213848b8605Smrg * We patch this function into tnl->Driver.Render.Finish.
214848b8605Smrg * It's called when we finish rendering a vertex buffer.
215848b8605Smrg */
216848b8605Smrgstatic void
217848b8605Smrg_swsetup_RenderFinish( struct gl_context *ctx )
218848b8605Smrg{
219848b8605Smrg   _swrast_render_finish( ctx );
220848b8605Smrg}
221848b8605Smrg
222848b8605Smrgvoid
223848b8605Smrg_swsetup_InvalidateState( struct gl_context *ctx, GLuint new_state )
224848b8605Smrg{
225848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
226848b8605Smrg   swsetup->NewState |= new_state;
227848b8605Smrg   _tnl_invalidate_vertex_state( ctx, new_state );
228848b8605Smrg}
229848b8605Smrg
230848b8605Smrg
231848b8605Smrgvoid
232848b8605Smrg_swsetup_Wakeup( struct gl_context *ctx )
233848b8605Smrg{
234848b8605Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
235848b8605Smrg   SScontext *swsetup = SWSETUP_CONTEXT(ctx);
236848b8605Smrg
237848b8605Smrg   tnl->Driver.Render.Start = _swsetup_RenderStart;
238848b8605Smrg   tnl->Driver.Render.Finish = _swsetup_RenderFinish;
239848b8605Smrg   tnl->Driver.Render.PrimitiveNotify = _swsetup_RenderPrimitive;
240848b8605Smrg   tnl->Driver.Render.Interp = _tnl_interp;
241848b8605Smrg   tnl->Driver.Render.CopyPV = _tnl_copy_pv;
242848b8605Smrg   tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; /* new */
243848b8605Smrg   tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; /* new */
244848b8605Smrg   /* points */
245848b8605Smrg   /* line */
246848b8605Smrg   /* triangle */
247848b8605Smrg   /* quad */
248848b8605Smrg   tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
249848b8605Smrg   tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
250848b8605Smrg   tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
251848b8605Smrg   tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
252848b8605Smrg   tnl->Driver.Render.Multipass = 0;
253848b8605Smrg
254848b8605Smrg   _tnl_invalidate_vertices( ctx, ~0 );
255848b8605Smrg   _tnl_need_projected_coords( ctx, GL_TRUE );
256848b8605Smrg   _swsetup_InvalidateState( ctx, ~0 );
257848b8605Smrg
258848b8605Smrg   swsetup->verts = (SWvertex *)tnl->clipspace.vertex_buf;
259848b8605Smrg   swsetup->last_index_bitset = 0;
260848b8605Smrg}
261848b8605Smrg
262848b8605Smrg
263848b8605Smrg/**
264848b8605Smrg * Populate a swrast SWvertex from an attrib-style vertex.
265848b8605Smrg */
266848b8605Smrgvoid
267848b8605Smrg_swsetup_Translate( struct gl_context *ctx, const void *vertex, SWvertex *dest )
268848b8605Smrg{
269b8e80941Smrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
270b8e80941Smrg   const GLfloat *m = tnl->_WindowMap.m;
271848b8605Smrg   GLfloat tmp[4];
272848b8605Smrg   GLuint i;
273848b8605Smrg
274848b8605Smrg   _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POS, tmp );
275848b8605Smrg
276848b8605Smrg   dest->attrib[VARYING_SLOT_POS][0] = m[0]  * tmp[0] + m[12];
277848b8605Smrg   dest->attrib[VARYING_SLOT_POS][1] = m[5]  * tmp[1] + m[13];
278848b8605Smrg   dest->attrib[VARYING_SLOT_POS][2] = m[10] * tmp[2] + m[14];
279848b8605Smrg   dest->attrib[VARYING_SLOT_POS][3] =         tmp[3];
280848b8605Smrg
281848b8605Smrg   /** XXX try to limit these loops someday */
282848b8605Smrg   for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
283848b8605Smrg      _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_TEX0 + i,
284848b8605Smrg                     dest->attrib[VARYING_SLOT_TEX0 + i] );
285848b8605Smrg
286848b8605Smrg   for (i = 0 ; i < ctx->Const.MaxVarying ; i++)
287848b8605Smrg      _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_GENERIC0 + i,
288848b8605Smrg                     dest->attrib[VARYING_SLOT_VAR0 + i] );
289848b8605Smrg
290848b8605Smrg   _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR0,
291848b8605Smrg                  dest->attrib[VARYING_SLOT_COL0] );
292848b8605Smrg
293848b8605Smrg   UNCLAMPED_FLOAT_TO_RGBA_CHAN(dest->color, dest->attrib[VARYING_SLOT_COL0]);
294848b8605Smrg
295848b8605Smrg   _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_COLOR1,
296848b8605Smrg                  dest->attrib[VARYING_SLOT_COL1]);
297848b8605Smrg
298848b8605Smrg   _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_FOG, tmp );
299848b8605Smrg   dest->attrib[VARYING_SLOT_FOGC][0] = tmp[0];
300848b8605Smrg
301848b8605Smrg   /* XXX See _tnl_get_attr about pointsize ... */
302848b8605Smrg   _tnl_get_attr( ctx, vertex, _TNL_ATTRIB_POINTSIZE, tmp );
303848b8605Smrg   dest->pointSize = tmp[0];
304848b8605Smrg}
305848b8605Smrg
306