1 /* -*- mode: c; c-basic-offset: 3 -*- */
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>
28 * Adapted to Mach64 by:
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
33 /* DO_XYZW: Emit xyz and maybe w coordinates.
34 * DO_RGBA: Emit color.
35 * DO_SPEC: Emit specular color.
36 * DO_FOG: Emit fog coordinate in specular alpha.
37 * DO_TEX0: Emit tex0 u,v coordinates.
38 * DO_TEX1: Emit tex1 u,v coordinates.
39 * DO_PTEX: Emit tex0,1 q coordinates where possible.
41 * Additionally, this template assumes it is emitting *transformed*
42 * vertices; the modifications to emit untransformed vertices (ie. to
43 * t&l hardware) are probably too great to cooexist with the code
44 * already in this file.
47 #define VIEWPORT_X(x) ((GLint) ((s[0] * (x) + s[12]) * 4.0))
48 #define VIEWPORT_Y(y) ((GLint) ((s[5] * (y) + s[13]) * 4.0))
49 #define VIEWPORT_Z(z) (((GLuint) (s[10] * (z) + s[14])) << 15)
55 static void TAG(emit)( struct gl_context *ctx,
56 GLuint start, GLuint end,
61 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
90 VERTEX *v = (VERTEX *)dest;
91 const GLfloat *s = GET_VIEWPORT_MAT();
92 #if DO_TEX1 || DO_TEX0 || DO_XYZW
93 const GLubyte *mask = VB->ClipMask;
98 (void) s; /* Quiet compiler */
100 /* fprintf(stderr, "%s(big) importable %d %d..%d\n", */
101 /* __FUNCTION__, VB->importable_data, start, end); */
105 const GLuint t1 = GET_TEXSOURCE(1);
106 tc1 = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->data;
107 tc1_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->stride;
109 tc1_size = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->size;
116 const GLuint t0 = GET_TEXSOURCE(0);
117 tc0 = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->data;
118 tc0_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->stride;
120 tc0_size = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->size;
126 if (VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
127 spec = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data;
128 spec_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride;
130 spec = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
136 if (VB->AttribPtr[_TNL_ATTRIB_FOG]) {
137 fog = VB->AttribPtr[_TNL_ATTRIB_FOG]->data;
138 fog_stride = VB->AttribPtr[_TNL_ATTRIB_FOG]->stride;
140 static GLfloat tmp[4] = {0, 0, 0, 0};
147 col = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data;
148 col_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride;
151 coord = VB->NdcPtr->data;
152 coord_stride = VB->NdcPtr->stride;
156 STRIDE_4F(tc1, start * tc1_stride);
159 STRIDE_4F(tc0, start * tc0_stride);
162 STRIDE_4F(spec, start * spec_stride);
165 STRIDE_4F(fog, start * fog_stride);
168 STRIDE_4F(col, start * col_stride);
170 STRIDE_4F(coord, start * coord_stride);
173 for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
174 CARD32 *p = (CARD32 *)v;
175 #if DO_TEX1 || DO_TEX0
190 #ifdef MACH64_PREMULT_TEXCOORDS
191 LE32_OUT_FLOAT( p++, w*tc1[0][0] ); /* VERTEX_?_SECONDARY_S */
192 LE32_OUT_FLOAT( p++, w*tc1[0][1] ); /* VERTEX_?_SECONDARY_T */
193 LE32_OUT_FLOAT( p++, w*tc1[0][3] ); /* VERTEX_?_SECONDARY_W */
194 #else /* !MACH64_PREMULT_TEXCOORDS */
195 float rhw = 1.0 / tc1[0][3];
196 LE32_OUT_FLOAT( p++, rhw*tc1[0][0] ); /* VERTEX_?_SECONDARY_S */
197 LE32_OUT_FLOAT( p++, rhw*tc1[0][1] ); /* VERTEX_?_SECONDARY_T */
198 LE32_OUT_FLOAT( p++, w*tc1[0][3] ); /* VERTEX_?_SECONDARY_W */
199 #endif /* !MACH64_PREMULT_TEXCOORDS */
202 #ifdef MACH64_PREMULT_TEXCOORDS
203 LE32_OUT_FLOAT( p++, w*tc1[0][0] ); /* VERTEX_?_SECONDARY_S */
204 LE32_OUT_FLOAT( p++, w*tc1[0][1] ); /* VERTEX_?_SECONDARY_T */
205 LE32_OUT_FLOAT( p++, w ); /* VERTEX_?_SECONDARY_W */
206 #else /* !MACH64_PREMULT_TEXCOORDS */
207 LE32_OUT_FLOAT( p++, tc1[0][0] ); /* VERTEX_?_SECONDARY_S */
208 LE32_OUT_FLOAT( p++, tc1[0][1] ); /* VERTEX_?_SECONDARY_T */
209 LE32_OUT_FLOAT( p++, w ); /* VERTEX_?_SECONDARY_W */
210 #endif /* !MACH64_PREMULT_TEXCOORDS */
214 STRIDE_4F(tc1, tc1_stride);
217 #endif /* !DO_TEX1 */
222 #ifdef MACH64_PREMULT_TEXCOORDS
223 LE32_OUT_FLOAT( p++, w*tc0[0][0] ); /* VERTEX_?_S */
224 LE32_OUT_FLOAT( p++, w*tc0[0][1] ); /* VERTEX_?_T */
225 LE32_OUT_FLOAT( p++, w*tc0[0][3] ); /* VERTEX_?_W */
226 #else /* !MACH64_PREMULT_TEXCOORDS */
227 float rhw = 1.0 / tc0[0][3];
228 LE32_OUT_FLOAT( p++, rhw*tc0[0][0] ); /* VERTEX_?_S */
229 LE32_OUT_FLOAT( p++, rhw*tc0[0][1] ); /* VERTEX_?_T */
230 LE32_OUT_FLOAT( p++, w*tc0[0][3] ); /* VERTEX_?_W */
231 #endif /* !MACH64_PREMULT_TEXCOORDS */
234 #ifdef MACH64_PREMULT_TEXCOORDS
235 LE32_OUT_FLOAT( p++, w*tc0[0][0] ); /* VERTEX_?_S */
236 LE32_OUT_FLOAT( p++, w*tc0[0][1] ); /* VERTEX_?_T */
237 LE32_OUT_FLOAT( p++, w ); /* VERTEX_?_W */
238 #else /* !MACH64_PREMULT_TEXCOORDS */
239 LE32_OUT_FLOAT( p++, tc0[0][0] ); /* VERTEX_?_S */
240 LE32_OUT_FLOAT( p++, tc0[0][1] ); /* VERTEX_?_T */
241 LE32_OUT_FLOAT( p++, w ); /* VERTEX_?_W */
242 #endif /* !MACH64_PREMULT_TEXCOORDS */
246 STRIDE_4F(tc0, tc0_stride);
249 #endif /* !DO_TEX0 */
252 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[0], spec[0][2]); /* VERTEX_?_SPEC_B */
253 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[1], spec[0][1]); /* VERTEX_?_SPEC_G */
254 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[2], spec[0][0]); /* VERTEX_?_SPEC_R */
256 STRIDE_4F(spec, spec_stride);
259 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[3], fog[0][0]); /* VERTEX_?_SPEC_A */
260 /* ((GLubyte *)p)[3] = fog[0][0] * 255.0; */
261 STRIDE_4F(fog, fog_stride);
268 LE32_OUT( p++, VIEWPORT_Z( coord[0][2] ) ); /* VERTEX_?_Z */
277 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[0], col[0][2]);
278 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[1], col[0][1]);
279 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[2], col[0][0]);
280 UNCLAMPED_FLOAT_TO_UBYTE(((GLubyte *)p)[3], col[0][3]);
282 STRIDE_4F(col, col_stride);
291 (VIEWPORT_X( coord[0][0] ) << 16) | /* VERTEX_?_X */
292 (VIEWPORT_Y( coord[0][1] ) & 0xffff) ); /* VERTEX_?_Y */
294 if (MACH64_DEBUG & DEBUG_VERBOSE_PRIMS) {
295 fprintf( stderr, "%s: vert %d: %.2f %.2f %.2f %x\n",
298 (LE32_IN( p ) >> 16)/4.0,
299 (LE32_IN( p ) & 0xffff)/4.0,
300 LE32_IN( p - 2 )/65536.0,
301 *(GLuint *)(p - 1) );
305 #if DO_TEX1 || DO_TEX0 || DO_XYZW
306 STRIDE_4F(coord, coord_stride);
309 assert( p + 1 - (CARD32 *)v == 10 );
313 #if DO_XYZW && DO_RGBA
315 static GLboolean TAG(check_tex_sizes)( struct gl_context *ctx )
318 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
320 /* Force 'missing' texcoords to something valid.
322 if (DO_TEX1 && VB->AttribPtr[_TNL_ATTRIB_TEX0] == 0)
323 VB->AttribPtr[_TNL_ATTRIB_TEX0] = VB->AttribPtr[_TNL_ATTRIB_TEX1];
328 /* No hardware support for projective texture. Can fake it for
331 if ((DO_TEX1 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(1)]->size == 4)) {
336 if (DO_TEX0 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(0)]->size == 4) {
347 static void TAG(interp)( struct gl_context *ctx,
349 GLuint edst, GLuint eout, GLuint ein,
350 GLboolean force_boundary )
353 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
354 GLubyte *ddverts = GET_VERTEX_STORE();
355 GLuint size = GET_VERTEX_SIZE();
356 const GLfloat *dstclip = VB->ClipPtr->data[edst];
358 const GLfloat *s = GET_VIEWPORT_MAT();
360 CARD32 *dst = (CARD32 *)(ddverts + (edst * size));
361 CARD32 *in = (CARD32 *)(ddverts + (ein * size));
362 CARD32 *out = (CARD32 *)(ddverts + (eout * size));
366 w = (dstclip[3] == 0.0F) ? 1.0 : (1.0 / dstclip[3]);
372 GLfloat wout = VB->NdcPtr->data[eout][3];
373 GLfloat win = VB->NdcPtr->data[ein][3];
374 GLfloat qout = LE32_IN_FLOAT( out + 2 ) / wout;
375 GLfloat qin = LE32_IN_FLOAT( in + 2 ) / win;
378 INTERP_F( t, qdst, qout, qin );
381 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
382 LE32_OUT_FLOAT( dst, temp*rqdst ); /* VERTEX_?_SECONDARY_S */
385 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
386 LE32_OUT_FLOAT( dst, temp*rqdst ); /* VERTEX_?_SECONDARY_T */
389 LE32_OUT_FLOAT( dst, w*rqdst ); /* VERTEX_?_SECONDARY_W */
392 #ifdef MACH64_PREMULT_TEXCOORDS
393 GLfloat qout = w / LE32_IN_FLOAT( out + 2 );
394 GLfloat qin = w / LE32_IN_FLOAT( in + 2 );
396 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
397 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_SECONDARY_S */
400 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
401 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_SECONDARY_T */
403 #else /* !MACH64_PREMULT_TEXCOORDS */
404 INTERP_F( t, temp, LE32_IN_FLOAT( out ), LE32_IN_FLOAT( in ) );
405 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_SECONDARY_S */
408 INTERP_F( t, temp, LE32_IN_FLOAT( out ), LE32_IN_FLOAT( in ) );
409 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_SECONDARY_T */
411 #endif /* !MACH64_PREMULT_TEXCOORDS */
412 LE32_OUT_FLOAT( dst, w ); /* VERTEX_?_SECONDARY_W */
414 #endif /* !DO_PTEX */
417 dst += 3; out += 3; in += 3;
418 #endif /* !DO_TEX1 */
424 GLfloat wout = VB->NdcPtr->data[eout][3];
425 GLfloat win = VB->NdcPtr->data[ein][3];
426 GLfloat qout = LE32_IN_FLOAT( out + 2 ) / wout;
427 GLfloat qin = LE32_IN_FLOAT( in + 2 ) / win;
430 INTERP_F( t, qdst, qout, qin );
433 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
434 LE32_OUT_FLOAT( dst, temp*rqdst ); /* VERTEX_?_S */
437 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
438 LE32_OUT_FLOAT( dst, temp*rqdst ); /* VERTEX_?_T */
441 LE32_OUT_FLOAT( dst, w*rqdst ); /* VERTEX_?_W */
444 #ifdef MACH64_PREMULT_TEXCOORDS
445 GLfloat qout = w / LE32_IN_FLOAT( out + 2 );
446 GLfloat qin = w / LE32_IN_FLOAT( in + 2 );
448 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
449 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_S */
452 INTERP_F( t, temp, LE32_IN_FLOAT( out ) * qout, LE32_IN_FLOAT( in ) * qin );
453 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_T */
455 #else /* !MACH64_PREMULT_TEXCOORDS */
456 INTERP_F( t, temp, LE32_IN_FLOAT( out ), LE32_IN_FLOAT( in ) );
457 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_S */
460 INTERP_F( t, temp, LE32_IN_FLOAT( out ), LE32_IN_FLOAT( in ) );
461 LE32_OUT_FLOAT( dst, temp ); /* VERTEX_?_T */
463 #endif /* !MACH64_PREMULT_TEXCOORDS */
464 LE32_OUT_FLOAT( dst, w ); /* VERTEX_?_W */
466 #endif /* !DO_PTEX */
469 dst += 3; out += 3; in += 3;
470 #endif /* !DO_TEX0 */
473 INTERP_UB( t, ((GLubyte *)dst)[0], ((GLubyte *)out)[0], ((GLubyte *)in)[0] ); /* VERTEX_?_SPEC_B */
474 INTERP_UB( t, ((GLubyte *)dst)[1], ((GLubyte *)out)[1], ((GLubyte *)in)[1] ); /* VERTEX_?_SPEC_G */
475 INTERP_UB( t, ((GLubyte *)dst)[2], ((GLubyte *)out)[2], ((GLubyte *)in)[2] ); /* VERTEX_?_SPEC_R */
479 INTERP_UB( t, ((GLubyte *)dst)[3], ((GLubyte *)out)[3], ((GLubyte *)in)[3] ); /* VERTEX_?_SPEC_A */
484 LE32_OUT( dst, VIEWPORT_Z( dstclip[2] * w ) ); /* VERTEX_?_Z */
487 INTERP_UB( t, ((GLubyte *)dst)[0], ((GLubyte *)out)[0], ((GLubyte *)in)[0] ); /* VERTEX_?_B */
488 INTERP_UB( t, ((GLubyte *)dst)[1], ((GLubyte *)out)[1], ((GLubyte *)in)[1] ); /* VERTEX_?_G */
489 INTERP_UB( t, ((GLubyte *)dst)[2], ((GLubyte *)out)[2], ((GLubyte *)in)[2] ); /* VERTEX_?_R */
490 INTERP_UB( t, ((GLubyte *)dst)[3], ((GLubyte *)out)[3], ((GLubyte *)in)[3] ); /* VERTEX_?_A */
491 dst++; /*out++; in++;*/
494 (VIEWPORT_X( dstclip[0] * w ) << 16) | /* VERTEX_?_X */
495 (VIEWPORT_Y( dstclip[1] * w ) & 0xffff) ); /* VERTEX_?_Y */
497 assert( dst + 1 - (CARD32 *)(ddverts + (edst * size)) == 10 );
498 assert( in + 2 - (CARD32 *)(ddverts + (ein * size)) == 10 );
499 assert( out + 2 - (CARD32 *)(ddverts + (eout * size)) == 10 );
501 if (MACH64_DEBUG & DEBUG_VERBOSE_PRIMS) {
502 fprintf( stderr, "%s: dst vert: %.2f %.2f %.2f %x\n",
504 (GLshort)(LE32_IN( dst ) >> 16)/4.0,
505 (GLshort)(LE32_IN( dst ) & 0xffff)/4.0,
506 LE32_IN( dst - 2 )/65536.0,
507 *(GLuint *)(dst - 1) );
511 #endif /* DO_RGBA && DO_XYZW */
514 static void TAG(copy_pv)( struct gl_context *ctx, GLuint edst, GLuint esrc )
516 #if DO_SPEC || DO_FOG || DO_RGBA
518 GLubyte *verts = GET_VERTEX_STORE();
519 GLuint size = GET_VERTEX_SIZE();
520 GLuint *dst = (GLuint *)(verts + (edst * size));
521 GLuint *src = (GLuint *)(verts + (esrc * size));
524 #if DO_SPEC || DO_FOG
525 dst[6] = src[6]; /* VERTEX_?_SPEC_ARGB */
529 dst[8] = src[8]; /* VERTEX_?_ARGB */
533 static void TAG(init)( void )
535 setup_tab[IND].emit = TAG(emit);
537 #if DO_XYZW && DO_RGBA
538 setup_tab[IND].check_tex_sizes = TAG(check_tex_sizes);
539 setup_tab[IND].interp = TAG(interp);
542 setup_tab[IND].copy_pv = TAG(copy_pv);
545 setup_tab[IND].vertex_format = TEX1_VERTEX_FORMAT;
546 setup_tab[IND].vertex_size = 10;
548 setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT;
549 setup_tab[IND].vertex_size = 7;
550 #elif DO_SPEC || DO_FOG
551 setup_tab[IND].vertex_format = NOTEX_VERTEX_FORMAT;
552 setup_tab[IND].vertex_size = 4;
554 setup_tab[IND].vertex_format = TINY_VERTEX_FORMAT;
555 setup_tab[IND].vertex_size = 3;