Remove CVS keywords.
[mesa.git] / src / mesa / drivers / dri / ffb / ffb_vtxfmt.c
1 /*
2 *
3 * GLX Hardware Device Driver for Sun Creator/Creator3D
4 * Copyright (C) 2001 David S. Miller
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 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *
25 * David S. Miller <davem@redhat.com>
26 */
27
28 #include "main/glheader.h"
29 #include "api_noop.h"
30 #include "main/context.h"
31 #include "light.h"
32 #include "main/macros.h"
33 #include "main/imports.h"
34 #include "main/mtypes.h"
35 #include "main/simple_list.h"
36 #include "vtxfmt.h"
37 #include "ffb_xmesa.h"
38 #include "ffb_context.h"
39 #include "ffb_vb.h"
40 #include "tnl/tnl.h"
41 #include "tnl/tcontext.h"
42
43 #include "ffb_vtxfmt.h"
44
45 #define TNL_VERTEX ffbTnlVertex
46
47 #define INTERP_RGBA(t, out, a, b) \
48 do { \
49 GLint i; \
50 for ( i = 0 ; i < 4 ; i++ ) { \
51 GLfloat fa = a[i]; \
52 GLfloat fb = b[i]; \
53 out[i] = LINTERP( t, fa, fb ); \
54 } \
55 } while (0)
56
57 /* Color functions: */
58
59 static INLINE void ffb_recalc_base_color(GLcontext *ctx)
60 {
61 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
62 struct gl_light *light;
63
64 COPY_3V(fmesa->vtx_state.light.base_color, ctx->Light._BaseColor[0]);
65 foreach (light, &ctx->Light.EnabledList) {
66 ACC_3V(fmesa->vtx_state.light.base_color,
67 light->_MatAmbient[0]);
68 }
69
70 fmesa->vtx_state.light.base_alpha = ctx->Light._BaseAlpha[0];
71 }
72
73 #define GET_CURRENT \
74 GET_CURRENT_CONTEXT(ctx); \
75 ffbContextPtr fmesa = FFB_CONTEXT(ctx)
76
77 #define CURRENT_COLOR(COMP) fmesa->vtx_state.current.color[COMP]
78 #define CURRENT_SPECULAR(COMP) fmesa->vtx_state.current.specular[COMP]
79 #define COLOR_IS_FLOAT
80 #define RECALC_BASE_COLOR(ctx) ffb_recalc_base_color(ctx)
81
82 #define TAG(x) ffb_##x
83 #include "tnl_dd/t_dd_imm_capi.h"
84
85 /* Normal functions: */
86
87 struct ffb_norm_tab {
88 void (*normal3f_multi)(GLfloat x, GLfloat y, GLfloat z);
89 void (*normal3fv_multi)(const GLfloat *v);
90 void (*normal3f_single)(GLfloat x, GLfloat y, GLfloat z);
91 void (*normal3fv_single)(const GLfloat *v);
92 };
93
94 static struct ffb_norm_tab norm_tab[0x4];
95
96 #define HAVE_HW_LIGHTING 0
97 #define GET_CURRENT_VERTEX \
98 GET_CURRENT_CONTEXT(ctx); \
99 ffbContextPtr fmesa = FFB_CONTEXT(ctx); \
100 ffbTnlVertexPtr v = fmesa->imm.v0
101
102 #define CURRENT_NORMAL fmesa->vtx_state.current.normal
103 #define BASE_COLOR fmesa->vtx_state.light.base_color
104 #define BASE_ALPHA fmesa->vtx_state.light.base_alpha
105 #define VERT_COLOR( COMP ) v->color[COMP]
106 #define VERT_COLOR_IS_FLOAT
107
108 #define IND (0)
109 #define TAG(x) ffb_##x
110 #define PRESERVE_NORMAL_DEFS
111 #include "tnl_dd/t_dd_imm_napi.h"
112
113 #define IND (NORM_RESCALE)
114 #define TAG(x) ffb_##x##_rescale
115 #define PRESERVE_NORMAL_DEFS
116 #include "tnl_dd/t_dd_imm_napi.h"
117
118 #define IND (NORM_NORMALIZE)
119 #define TAG(x) ffb_##x##_normalize
120 #include "tnl_dd/t_dd_imm_napi.h"
121
122 static void ffb_init_norm_funcs(void)
123 {
124 ffb_init_norm();
125 ffb_init_norm_rescale();
126 ffb_init_norm_normalize();
127 }
128
129 static void choose_normals(void)
130 {
131 GET_CURRENT_CONTEXT(ctx);
132 GLuint index;
133
134 if (ctx->Light.Enabled) {
135 if (ctx->Transform.Normalize) {
136 index = NORM_NORMALIZE;
137 } else if (!ctx->Transform.RescaleNormals &&
138 ctx->_ModelViewInvScale != 1.0) {
139 index = NORM_RESCALE;
140 } else {
141 index = 0;
142 }
143
144 if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev) {
145 SET_Normal3f(ctx->Exec, norm_tab[index].normal3f_single);
146 SET_Normal3fv(ctx->Exec, norm_tab[index].normal3fv_single);
147 } else {
148 SET_Normal3f(ctx->Exec, norm_tab[index].normal3f_multi);
149 SET_Normal3fv(ctx->Exec, norm_tab[index].normal3fv_multi);
150 }
151 } else {
152 SET_Normal3f(ctx->Exec, _mesa_noop_Normal3f);
153 SET_Normal3fv(ctx->Exec, _mesa_noop_Normal3fv);
154 }
155 }
156
157 static void ffb_choose_Normal3f(GLfloat x, GLfloat y, GLfloat z)
158 {
159 choose_normals();
160 CALL_Normal3f(GET_DISPATCH(), (x, y, z));
161 }
162
163 static void ffb_choose_Normal3fv(const GLfloat *v)
164 {
165 choose_normals();
166 CALL_Normal3fv(GET_DISPATCH(), (v));
167 }
168
169 /* Vertex functions: */
170
171 #define GET_CURRENT_VERTEX \
172 GET_CURRENT_CONTEXT(ctx); \
173 ffbContextPtr fmesa = FFB_CONTEXT(ctx); \
174 ffbTnlVertexPtr v = fmesa->imm.v0
175
176 #define CURRENT_VERTEX v->obj
177 #define SAVE_VERTEX fmesa->imm.save_vertex(ctx, v)
178
179 #define TAG(x) ffb_##x
180 #include "tnl_dd/t_dd_imm_vapi.h"
181
182 struct ffb_vert_tab {
183 void (*save_vertex)(GLcontext *ctx, ffbTnlVertexPtr v);
184 void (*interpolate_vertex)(GLfloat t,
185 ffbTnlVertex *O,
186 const ffbTnlVertex *I,
187 const ffbTnlVertex *J);
188 };
189
190 static struct ffb_vert_tab vert_tab[0xf];
191
192 #define VTX_NORMAL 0x0
193 #define VTX_RGBA 0x1
194
195 #define LOCAL_VARS \
196 ffbContextPtr fmesa = FFB_CONTEXT(ctx)
197
198 #define CURRENT_COLOR fmesa->vtx_state.current.color
199 #define COLOR_IS_FLOAT
200 #define FLUSH_VERTEX fmesa->imm.flush_vertex( ctx, v );
201
202 #define IND (VTX_NORMAL)
203 #define TAG(x) ffb_##x##_NORMAL
204 #define PRESERVE_VERTEX_DEFS
205 #include "tnl_dd/t_dd_imm_vertex.h"
206
207 #define IND (VTX_RGBA)
208 #define TAG(x) ffb_##x##_RGBA
209 #include "tnl_dd/t_dd_imm_vertex.h"
210
211 static void ffb_init_vert_funcs( void )
212 {
213 ffb_init_vert_NORMAL();
214 ffb_init_vert_RGBA();
215 }
216
217 #define LOCAL_VARS \
218 ffbContextPtr fmesa = FFB_CONTEXT(ctx)
219
220 #define GET_INTERP_FUNC \
221 ffb_interp_func interp = fmesa->imm.interp
222
223 #define FLUSH_VERTEX fmesa->imm.flush_vertex
224 #define IMM_VERTEX( V ) fmesa->imm.V
225 #define IMM_VERTICES( n ) fmesa->imm.vertices[n]
226
227 #define EMIT_VERTEX_USES_HWREGS
228
229 /* XXX Implement me XXX */
230 #define EMIT_VERTEX_TRI(VTX0, VTX1, VTX2) \
231 do { } while (0)
232 #define EMIT_VERTEX_LINE(VTX0, VTX1) \
233 do { } while (0)
234 #define EMIT_VERTEX_POINT(VTX0) \
235 do { } while (0)
236
237 #define TAG(x) ffb_##x
238 #include "tnl_dd/t_dd_imm_primtmp.h"
239
240 /* Bzzt: Material changes are lost on fallback. */
241 static void ffb_Materialfv(GLenum face, GLenum pname,
242 const GLfloat *params)
243 {
244 GET_CURRENT_CONTEXT(ctx);
245
246 _mesa_noop_Materialfv( face, pname, params );
247 ffb_recalc_base_color( ctx );
248 }
249
250 /* Fallback functions: */
251
252 static void ffb_do_fallback(GLcontext *ctx)
253 {
254 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
255 struct ffb_current_state *current = &fmesa->vtx_state.current;
256
257 /* Tell tnl to restore its exec vtxfmt, rehook its driver callbacks
258 * and revive internal state that depended on those callbacks:
259 */
260 _tnl_wakeup_exec(ctx);
261
262 /* Replay enough vertices that the current primitive is continued
263 * correctly:
264 */
265 if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END )
266 CALL_Begin(GET_DISPATCH(), (fmesa->imm.prim));
267
268 if (ctx->Light.Enabled) {
269 /* Catch ColorMaterial */
270 CALL_Color4fv(GET_DISPATCH(), (ctx->Current.Color));
271 CALL_Normal3fv(GET_DISPATCH(), (current->normal));
272 } else {
273 CALL_Color4fv(GET_DISPATCH(), (current->color));
274 }
275 }
276
277 #define PRE_LOOPBACK( FUNC ) do { \
278 GET_CURRENT_CONTEXT(ctx); \
279 ffb_do_fallback( ctx ); \
280 } while (0)
281
282 #define TAG(x) ffb_fallback_##x
283 #include "vtxfmt_tmp.h"
284
285 static void ffb_Begin(GLenum prim)
286 {
287 GET_CURRENT_CONTEXT(ctx);
288 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
289
290 if (prim > GL_POLYGON) {
291 _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
292 return;
293 }
294
295 if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END) {
296 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
297 return;
298 }
299
300 ctx->Driver.NeedFlush |= (FLUSH_STORED_VERTICES |
301 FLUSH_UPDATE_CURRENT);
302
303 fmesa->imm.prim = prim;
304 fmesa->imm.v0 = &fmesa->imm.vertices[0];
305 fmesa->imm.save_vertex = ffb_save_vertex_RGBA;
306 fmesa->imm.flush_vertex = ffb_flush_tab[prim];
307
308 /* XXX Lock hardware, update FBC, PPC, DRAWOP, etc. XXX */
309 }
310
311 static void ffb_End(void)
312 {
313 GET_CURRENT_CONTEXT(ctx);
314 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
315
316 if (fmesa->imm.prim == PRIM_OUTSIDE_BEGIN_END) {
317 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
318 return;
319 }
320
321 fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END;
322
323 ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES |
324 FLUSH_UPDATE_CURRENT);
325
326 /* XXX Unlock hardware, etc. */
327 }
328
329 void ffbInitTnlModule(GLcontext *ctx)
330 {
331 ffbContextPtr fmesa = FFB_CONTEXT(ctx);
332 GLvertexformat *vfmt = &(fmesa->imm.vtxfmt);
333
334 /* Work in progress... */
335 return;
336
337 ffb_init_norm_funcs();
338 ffb_init_vert_funcs();
339
340 /* start by initializing to no-op functions */
341 _mesa_noop_vtxfmt_init(vfmt);
342
343 /* Handled fully in supported states: */
344 vfmt->ArrayElement = NULL; /* FIXME: ... */
345 vfmt->Color3f = ffb_choose_Color3f;
346 vfmt->Color3fv = ffb_choose_Color3fv;
347 vfmt->Color3ub = ffb_choose_Color3ub;
348 vfmt->Color3ubv = ffb_choose_Color3ubv;
349 vfmt->Color4f = ffb_choose_Color4f;
350 vfmt->Color4fv = ffb_choose_Color4fv;
351 vfmt->Color4ub = ffb_choose_Color4ub;
352 vfmt->Color4ubv = ffb_choose_Color4ubv;
353 vfmt->FogCoordfvEXT = ffb_FogCoordfvEXT;
354 vfmt->FogCoordfEXT = ffb_FogCoordfEXT;
355 vfmt->Materialfv = ffb_Materialfv;
356 vfmt->MultiTexCoord1fARB = ffb_fallback_MultiTexCoord1fARB;
357 vfmt->MultiTexCoord1fvARB = ffb_fallback_MultiTexCoord1fvARB;
358 vfmt->MultiTexCoord2fARB = ffb_fallback_MultiTexCoord2fARB;
359 vfmt->MultiTexCoord2fvARB = ffb_fallback_MultiTexCoord2fvARB;
360 vfmt->MultiTexCoord3fARB = ffb_fallback_MultiTexCoord3fARB;
361 vfmt->MultiTexCoord3fvARB = ffb_fallback_MultiTexCoord3fvARB;
362 vfmt->MultiTexCoord4fARB = ffb_fallback_MultiTexCoord4fARB;
363 vfmt->MultiTexCoord4fvARB = ffb_fallback_MultiTexCoord4fvARB;
364 vfmt->Normal3f = ffb_choose_Normal3f;
365 vfmt->Normal3fv = ffb_choose_Normal3fv;
366 vfmt->SecondaryColor3ubEXT = ffb_SecondaryColor3ubEXT;
367 vfmt->SecondaryColor3ubvEXT = ffb_SecondaryColor3ubvEXT;
368 vfmt->SecondaryColor3fEXT = ffb_SecondaryColor3fEXT;
369 vfmt->SecondaryColor3fvEXT = ffb_SecondaryColor3fvEXT;
370 vfmt->TexCoord1f = ffb_fallback_TexCoord1f;
371 vfmt->TexCoord1fv = ffb_fallback_TexCoord1fv;
372 vfmt->TexCoord2f = ffb_fallback_TexCoord2f;
373 vfmt->TexCoord2fv = ffb_fallback_TexCoord2fv;
374 vfmt->TexCoord3f = ffb_fallback_TexCoord3f;
375 vfmt->TexCoord3fv = ffb_fallback_TexCoord3fv;
376 vfmt->TexCoord4f = ffb_fallback_TexCoord4f;
377 vfmt->TexCoord4fv = ffb_fallback_TexCoord4fv;
378
379 vfmt->Vertex2f = ffb_Vertex2f;
380 vfmt->Vertex2fv = ffb_Vertex2fv;
381 vfmt->Vertex3f = ffb_Vertex3f;
382 vfmt->Vertex3fv = ffb_Vertex3fv;
383 vfmt->Vertex4f = ffb_Vertex4f;
384 vfmt->Vertex4fv = ffb_Vertex4fv;
385
386 vfmt->Begin = ffb_Begin;
387 vfmt->End = ffb_End;
388
389 vfmt->DrawArrays = NULL;
390 vfmt->DrawElements = NULL;
391
392 /* Active but unsupported -- fallback if we receive these:
393 *
394 * All of these fallbacks can be fixed with additional code, except
395 * CallList, unless we build a play_immediate_noop() command which
396 * turns an immediate back into glBegin/glEnd commands...
397 */
398 vfmt->CallList = ffb_fallback_CallList;
399 vfmt->EvalCoord1f = ffb_fallback_EvalCoord1f;
400 vfmt->EvalCoord1fv = ffb_fallback_EvalCoord1fv;
401 vfmt->EvalCoord2f = ffb_fallback_EvalCoord2f;
402 vfmt->EvalCoord2fv = ffb_fallback_EvalCoord2fv;
403 vfmt->EvalMesh1 = ffb_fallback_EvalMesh1;
404 vfmt->EvalMesh2 = ffb_fallback_EvalMesh2;
405 vfmt->EvalPoint1 = ffb_fallback_EvalPoint1;
406 vfmt->EvalPoint2 = ffb_fallback_EvalPoint2;
407
408 vfmt->prefer_float_colors = GL_TRUE;
409
410 fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END;
411
412 /* THIS IS A HACK! */
413 _mesa_install_exec_vtxfmt( ctx, vfmt );
414 }