Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / mach64 / mach64_vbtmp.h
1 /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3  * Mesa 3-D graphics library
4  * Version:  3.5
5  *
6  * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
7  *
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:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
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.
24  *
25  * Authors:
26  *    Keith Whitwell <keithw@valinux.com>
27  *
28  * Modified for mach64 by:
29  *    Leif Delgass <ldelgass@retinalburn.net>
30  *    José Fonseca <j_r_fonseca@yahoo.co.uk>
31  */
32
33
34 /* Unlike the other templates here, this assumes quite a bit about the
35  * underlying hardware.  Specifically it assumes a d3d-like vertex
36  * format, with a layout more or less constrained to look like the
37  * following:
38  *
39  * union {
40  *    struct {
41  *        float x, y, z, w;
42  *        struct { char r, g, b, a; } color;
43  *        struct { char r, g, b, fog; } spec;
44  *        float u0, v0;
45  *        float u1, v1;
46  *        float u2, v2;
47  *        float u3, v3;
48  *    } v;
49  *    struct {
50  *        float x, y, z, w;
51  *        struct { char r, g, b, a; } color;
52  *        struct { char r, g, b, fog; } spec;
53  *        float u0, v0, q0;
54  *        float u1, v1, q1;
55  *        float u2, v2, q2;
56  *        float u3, v3, q3;
57  *    } pv;
58  *    struct {
59  *        float x, y, z;
60  *        struct { char r, g, b, a; } color;
61  *    } tv;
62  *    float f[16];
63  *    unsigned int ui[16];
64  *    unsigned char ub4[4][16];
65  * }
66  *
67
68  * DO_XYZW:  Emit xyz and maybe w coordinates.
69  * DO_RGBA:  Emit color.
70  * DO_SPEC:  Emit specular color.
71  * DO_FOG:   Emit fog coordinate in specular alpha.
72  * DO_TEX0:  Emit tex0 u,v coordinates.
73  * DO_TEX1:  Emit tex1 u,v coordinates.
74  * DO_TEX2:  Emit tex2 u,v coordinates.
75  * DO_TEX3:  Emit tex3 u,v coordinates.
76  * DO_PTEX:  Emit tex0,1,2,3 q coordinates where possible.
77  *
78  * HAVE_RGBA_COLOR: Hardware takes color in rgba order (else bgra).
79  *
80  * HAVE_HW_VIEWPORT:  Hardware performs viewport transform.
81  * HAVE_HW_DIVIDE:  Hardware performs perspective divide.
82  *
83  * HAVE_TINY_VERTICES:  Hardware understands v.tv format.
84  * HAVE_PTEX_VERTICES:  Hardware understands v.pv format.
85  * HAVE_NOTEX_VERTICES:  Hardware understands v.v format with texcount 0.
86  *
87  * Additionally, this template assumes it is emitting *transformed*
88  * vertices; the modifications to emit untransformed vertices (ie. to
89  * t&l hardware) are probably too great to cooexist with the code
90  * already in this file.
91  *
92  * NOTE: The PTEX vertex format always includes TEX0 and TEX1, even if
93  * only TEX0 is enabled, in order to maintain a vertex size which is
94  * an exact number of quadwords.
95  */
96
97 #if (HAVE_HW_VIEWPORT)
98 #define VIEWPORT_X(dst,x) dst = x
99 #define VIEWPORT_Y(dst,y) dst = y
100 #define VIEWPORT_Z(dst,z) dst = z
101 #else
102 #define VIEWPORT_X(dst,x) dst = s[0]  * x + s[12]
103 #define VIEWPORT_Y(dst,y) dst = s[5]  * y + s[13]
104 #define VIEWPORT_Z(dst,z) dst = s[10] * z + s[14]
105 #endif
106
107 #if (HAVE_HW_DIVIDE && !HAVE_PTEX_VERTICES)
108 #error "can't cope with this combination" 
109 #endif 
110
111 #ifndef LOCALVARS
112 #define LOCALVARS
113 #endif
114
115 #ifndef CHECK_HW_DIVIDE
116 #define CHECK_HW_DIVIDE 1
117 #endif
118
119 #if (HAVE_HW_DIVIDE || DO_SPEC || DO_TEX0 || DO_FOG || !HAVE_TINY_VERTICES)
120
121 static void TAG(emit)( struct gl_context *ctx,
122                        GLuint start, GLuint end,
123                        void *dest,
124                        GLuint stride )
125 {
126    LOCALVARS
127    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
128    GLfloat (*tc0)[4], (*tc1)[4], (*fog)[4];
129    GLfloat (*tc2)[4], (*tc3)[4];
130    GLfloat (*spec)[4];
131    GLfloat (*col)[4];
132    GLuint col_stride;
133    GLuint tc0_stride, tc1_stride, spec_stride, fog_stride;
134    GLuint tc2_stride, tc3_stride;
135    GLuint tc0_size, tc1_size;
136    GLuint tc2_size, tc3_size;
137    GLfloat (*coord)[4];
138    GLuint coord_stride;
139    VERTEX *v = (VERTEX *)dest;
140    const GLfloat *s = GET_VIEWPORT_MAT();
141    const GLubyte *mask = VB->ClipMask;
142    int i;
143
144 /*     fprintf(stderr, "%s(big) importable %d %d..%d\n",  */
145 /*         __FUNCTION__, VB->importable_data, start, end); */
146
147    if (HAVE_HW_VIEWPORT && HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) {
148       (void) s;
149       coord = VB->ClipPtr->data;
150       coord_stride = VB->ClipPtr->stride;
151    }
152    else {
153       coord = VB->NdcPtr->data;
154       coord_stride = VB->NdcPtr->stride;
155    }
156
157    if (DO_TEX3) {
158       const GLuint t3 = GET_TEXSOURCE(3);
159       tc3 = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t3]->data;
160       tc3_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t3]->stride;
161       if (DO_PTEX)
162          tc3_size = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t3]->size;
163    }
164
165    if (DO_TEX2) {
166       const GLuint t2 = GET_TEXSOURCE(2);
167       tc2 = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->data;
168       tc2_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->stride;
169       if (DO_PTEX)
170          tc2_size = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->size;
171    }
172
173    if (DO_TEX1) {
174       const GLuint t1 = GET_TEXSOURCE(1);
175       tc1 = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->data;
176       tc1_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->stride;
177       if (DO_PTEX)
178          tc1_size = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->size;
179    }
180
181    if (DO_TEX0) {
182       const GLuint t0 = GET_TEXSOURCE(0);
183       tc0_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->stride;
184       tc0 = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->data;
185       if (DO_PTEX) 
186          tc0_size = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->size;
187    }
188
189    if (DO_RGBA) {
190       col = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data;
191       col_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride;
192    }
193
194    if (DO_SPEC) {
195       spec = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data;
196       spec_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride;
197    } else {
198       spec = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
199       spec_stride = 0;
200    }
201
202    if (DO_FOG) {
203       if (VB->AttribPtr[_TNL_ATTRIB_FOG]) {
204          fog = VB->AttribPtr[_TNL_ATTRIB_FOG]->data;
205          fog_stride = VB->AttribPtr[_TNL_ATTRIB_FOG]->stride;
206       } else {
207          static GLfloat tmp[4] = {0, 0, 0, 0};
208          fog = &tmp;
209          fog_stride = 0;
210       }
211    }
212
213    /* May have nonstandard strides:
214     */
215    if (start) {
216       coord =  (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
217       if (DO_TEX0)
218          tc0 =  (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride);
219       if (DO_TEX1) 
220          tc1 =  (GLfloat (*)[4])((GLubyte *)tc1 + start * tc1_stride);
221       if (DO_TEX2) 
222          tc2 =  (GLfloat (*)[4])((GLubyte *)tc2 + start * tc2_stride);
223       if (DO_TEX3) 
224          tc3 =  (GLfloat (*)[4])((GLubyte *)tc3 + start * tc3_stride);
225       if (DO_RGBA) 
226          STRIDE_4F(col, start * col_stride);
227       if (DO_SPEC)
228          STRIDE_4F(spec, start * spec_stride);
229       if (DO_FOG)
230          STRIDE_4F(fog, start * fog_stride);
231       //         fog =  (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
232       /*  STRIDE_F(fog, start * fog_stride); */
233    }
234    
235    for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
236       if (DO_XYZW) {
237          if (HAVE_HW_VIEWPORT || mask[i] == 0) {
238             /* unclipped */
239             VIEWPORT_X(v->v.x, coord[0][0]);
240             VIEWPORT_Y(v->v.y, coord[0][1]);
241             VIEWPORT_Z(v->v.z, coord[0][2]);
242             v->v.w = coord[0][3];
243          } else {
244             /* clipped */
245             v->v.w = 1.0;
246          }
247          if (MACH64_DEBUG & DEBUG_VERBOSE_PRIMS) {
248             fprintf(stderr, "%s: vert (importable) %d: %.2f %.2f %.2f %f\n", 
249                     __FUNCTION__, i, v->v.x, v->v.y, v->v.z, v->v.w);
250          }
251          coord =  (GLfloat (*)[4])((GLubyte *)coord +  coord_stride);
252       }
253       if (DO_RGBA) {
254          if (HAVE_RGBA_COLOR) {
255             *(GLuint *)&v->v.color = *(GLuint *)&col[0];
256             STRIDE_4F(col, col_stride);
257          } else {
258             v->v.color.blue  = col[0][2];
259             v->v.color.green = col[0][1];
260             v->v.color.red   = col[0][0];
261             v->v.color.alpha = col[0][3];
262             STRIDE_4F(col, col_stride);
263          }
264       }
265       if (DO_SPEC) {
266          v->v.specular.red = spec[0][0];
267          v->v.specular.green = spec[0][1];
268          v->v.specular.blue = spec[0][2];
269          STRIDE_4F(spec, spec_stride);
270       }
271       if (DO_FOG) {
272          v->v.specular.alpha = fog[0][0] * 255.0;
273          /*  STRIDE_F(fog, fog_stride); */
274          fog =  (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
275       }
276       if (DO_TEX0) {
277          v->v.u0 = tc0[0][0];
278          v->v.v0 = tc0[0][1];
279          if (MACH64_DEBUG & DEBUG_VERBOSE_PRIMS) {
280             fprintf(stderr, "%s: vert (importable) %d: u0: %.2f, v0: %.2f, w: %f\n", 
281                     __FUNCTION__, i, v->v.u0, v->v.v0, v->v.w);
282          }
283 #ifdef MACH64_PREMULT_TEXCOORDS
284          v->v.u0 *= v->v.w;
285          v->v.v0 *= v->v.w;
286 #endif
287          if (DO_PTEX) {
288             if (HAVE_PTEX_VERTICES) {
289                if (tc0_size == 4) 
290                   v->pv.q0 = tc0[0][3];
291                else
292                   v->pv.q0 = 1.0;
293             } 
294             else if (tc0_size == 4) {
295 #ifdef MACH64_PREMULT_TEXCOORDS
296                v->v.w *= tc0[0][3];
297 #else
298                float rhw = 1.0 / tc0[0][3];
299                v->v.w *= tc0[0][3];
300                v->v.u0 *= rhw;
301                v->v.v0 *= rhw;
302 #endif
303             } 
304          } 
305          tc0 =  (GLfloat (*)[4])((GLubyte *)tc0 +  tc0_stride);
306       }
307       if (DO_TEX1) {
308          if (DO_PTEX) {
309             v->pv.u1 = tc1[0][0];
310             v->pv.v1 = tc1[0][1];
311             if (tc1_size == 4) 
312                v->pv.q1 = tc1[0][3];
313             else
314                v->pv.q1 = 1.0;
315          } 
316          else {
317             v->v.u1 = tc1[0][0];
318             v->v.v1 = tc1[0][1];
319          }
320 #ifdef MACH64_PREMULT_TEXCOORDS
321          v->v.u1 *= v->v.w;
322          v->v.v1 *= v->v.w;
323 #endif
324          tc1 =  (GLfloat (*)[4])((GLubyte *)tc1 +  tc1_stride);
325       } 
326       else if (DO_PTEX) {
327          *(GLuint *)&v->pv.q1 = 0;      /* avoid culling on radeon */
328       }
329       if (DO_TEX2) {
330          if (DO_PTEX) {
331             v->pv.u2 = tc2[0][0];
332             v->pv.v2 = tc2[0][1];
333             if (tc2_size == 4) 
334                v->pv.q2 = tc2[0][3];
335             else
336                v->pv.q2 = 1.0;
337          } 
338          else {
339             v->v.u2 = tc2[0][0];
340             v->v.v2 = tc2[0][1];
341          }
342          tc2 =  (GLfloat (*)[4])((GLubyte *)tc2 +  tc2_stride);
343       } 
344       if (DO_TEX3) {
345          if (DO_PTEX) {
346             v->pv.u3 = tc3[0][0];
347             v->pv.v3 = tc3[0][1];
348             if (tc3_size == 4) 
349                v->pv.q3 = tc3[0][3];
350             else
351                v->pv.q3 = 1.0;
352             } 
353          else {
354             v->v.u3 = tc3[0][0];
355             v->v.v3 = tc3[0][1];
356          }
357          tc3 =  (GLfloat (*)[4])((GLubyte *)tc3 +  tc3_stride);
358       } 
359    }
360 }
361
362 #else
363 #if DO_XYZW
364
365 #if HAVE_HW_DIVIDE
366 #error "cannot use tiny vertices with hw perspective divide"
367 #endif
368
369 static void TAG(emit)( struct gl_context *ctx, GLuint start, GLuint end,
370                        void *dest, GLuint stride )
371 {
372    LOCALVARS
373    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
374    GLfloat (*col)[4];
375    GLuint col_stride;
376    GLfloat (*coord)[4] = VB->NdcPtr->data;
377    GLuint coord_stride = VB->NdcPtr->stride;
378    GLfloat *v = (GLfloat *)dest;
379    const GLubyte *mask = VB->ClipMask;
380    const GLfloat *s = GET_VIEWPORT_MAT();
381    int i;
382
383    (void) s;
384
385    ASSERT(stride == 4);
386
387    col = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data;
388    col_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride;
389
390    /* Pack what's left into a 4-dword vertex.  Color is in a different
391     * place, and there is no 'w' coordinate.
392     */
393    if (start) {
394       coord =  (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
395       STRIDE_4F(col, start * col_stride);
396    }
397    
398    for (i=start; i < end; i++, v+=4) {
399       if (HAVE_HW_VIEWPORT || mask[i] == 0) {
400          VIEWPORT_X(v[0], coord[0][0]);
401          VIEWPORT_Y(v[1], coord[0][1]);
402          VIEWPORT_Z(v[2], coord[0][2]);
403       }
404       coord =  (GLfloat (*)[4])((GLubyte *)coord +  coord_stride);
405       if (DO_RGBA) {
406          if (HAVE_RGBA_COLOR) {
407             *(GLuint *)&v[3] = *(GLuint *)col;
408          }
409          else {
410             GLubyte *b = (GLubyte *)&v[3];
411             UNCLAMPED_FLOAT_TO_UBYTE(b[0], col[0][2]);
412             UNCLAMPED_FLOAT_TO_UBYTE(b[1], col[0][1]);
413             UNCLAMPED_FLOAT_TO_UBYTE(b[2], col[0][0]);
414             UNCLAMPED_FLOAT_TO_UBYTE(b[3], col[0][3]);
415          }
416          STRIDE_4F( col, col_stride );
417       }
418       if (MACH64_DEBUG & DEBUG_VERBOSE_PRIMS) {
419          fprintf(stderr, "vert (importable) %d: %.2f %.2f %.2f %x\n",
420                  i, v[0], v[1], v[2], *(int *)&v[3]);
421       }
422    }
423 }
424 #else
425 static void TAG(emit)( struct gl_context *ctx, GLuint start, GLuint end,
426                        void *dest, GLuint stride )
427 {
428    LOCALVARS
429    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
430    GLfloat (*col)[4];
431    GLuint col_stride;
432    GLfloat *v = (GLfloat *)dest;
433    int i;
434
435    col = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data;
436    col_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride;
437
438    if (start)
439       STRIDE_4F(col, col_stride * start);
440
441    /* Need to figure out where color is:
442     */
443    if (GET_VERTEX_FORMAT() == TINY_VERTEX_FORMAT)
444       v += 3;
445    else
446       v += 4;
447
448    for (i=start; i < end; i++, STRIDE_F(v, stride)) {
449       if (HAVE_RGBA_COLOR) {
450          *(GLuint *)v = *(GLuint *)col[0];
451       }
452       else {
453          GLubyte *b = (GLubyte *)v;
454          UNCLAMPED_FLOAT_TO_UBYTE(b[0], col[0][2]);
455          UNCLAMPED_FLOAT_TO_UBYTE(b[1], col[0][1]);
456          UNCLAMPED_FLOAT_TO_UBYTE(b[2], col[0][0]);
457          UNCLAMPED_FLOAT_TO_UBYTE(b[3], col[0][3]);
458       }
459       STRIDE_4F( col, col_stride );
460    }
461 }
462 #endif /* emit */
463 #endif /* emit */
464
465 #if (DO_XYZW) && (DO_RGBA)
466
467
468 #if (HAVE_PTEX_VERTICES)
469 static GLboolean TAG(check_tex_sizes)( struct gl_context *ctx )
470 {
471    LOCALVARS
472    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
473
474    /* Force 'missing' texcoords to something valid.
475     */
476    if (DO_TEX3 && VB->AttribPtr[_TNL_ATTRIB_TEX2] == 0)
477       VB->AttribPtr[_TNL_ATTRIB_TEX2] = VB->AttribPtr[_TNL_ATTRIB_TEX3];
478
479    if (DO_TEX2 && VB->AttribPtr[_TNL_ATTRIB_TEX1] == 0)
480       VB->AttribPtr[_TNL_ATTRIB_TEX1] = VB->AttribPtr[_TNL_ATTRIB_TEX2];
481
482    if (DO_TEX1 && VB->AttribPtr[_TNL_ATTRIB_TEX0] == 0)
483       VB->AttribPtr[_TNL_ATTRIB_TEX0] = VB->AttribPtr[_TNL_ATTRIB_TEX1];
484
485    if (DO_PTEX)
486       return GL_TRUE;
487    
488    if ((DO_TEX3 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(3)]->size == 4) ||
489        (DO_TEX2 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(2)]->size == 4) ||
490        (DO_TEX1 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(1)]->size == 4) ||
491        (DO_TEX0 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(0)]->size == 4))
492       return GL_FALSE;
493
494    return GL_TRUE;
495 }
496 #else
497 static GLboolean TAG(check_tex_sizes)( struct gl_context *ctx )
498 {
499    LOCALVARS
500    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
501
502    /* Force 'missing' texcoords to something valid.
503     */
504    if (DO_TEX3 && VB->AttribPtr[_TNL_ATTRIB_TEX2] == 0)
505       VB->AttribPtr[_TNL_ATTRIB_TEX2] = VB->AttribPtr[_TNL_ATTRIB_TEX3];
506
507    if (DO_TEX2 && VB->AttribPtr[_TNL_ATTRIB_TEX1] == 0)
508       VB->AttribPtr[_TNL_ATTRIB_TEX1] = VB->AttribPtr[_TNL_ATTRIB_TEX2];
509
510    if (DO_TEX1 && VB->AttribPtr[_TNL_ATTRIB_TEX0] == 0)
511       VB->AttribPtr[_TNL_ATTRIB_TEX0] = VB->AttribPtr[_TNL_ATTRIB_TEX1];
512
513    if (DO_PTEX)
514       return GL_TRUE;
515
516    /* No hardware support for projective texture.  Can fake it for
517     * TEX0 only.
518     */
519    if ((DO_TEX3 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(3)]->size == 4) ||
520        (DO_TEX2 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(2)]->size == 4) ||
521        (DO_TEX1 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(1)]->size == 4)) {
522       PTEX_FALLBACK();
523       return GL_FALSE;
524    }
525
526    if (DO_TEX0 && VB->AttribPtr[_TNL_ATTRIB_TEX0 + GET_TEXSOURCE(0)]->size == 4) {
527       if (DO_TEX1 || DO_TEX2 || DO_TEX3) {
528          PTEX_FALLBACK();
529       }
530       return GL_FALSE;
531    }
532
533    return GL_TRUE;
534 }
535 #endif /* ptex */
536
537
538 static void TAG(interp)( struct gl_context *ctx,
539                          GLfloat t,
540                          GLuint edst, GLuint eout, GLuint ein,
541                          GLboolean force_boundary )
542 {
543    LOCALVARS
544    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
545    GLubyte *ddverts = GET_VERTEX_STORE();
546    GLuint size = GET_VERTEX_SIZE();
547    const GLfloat *dstclip = VB->ClipPtr->data[edst];
548    GLfloat w;
549    const GLfloat *s = GET_VIEWPORT_MAT();
550
551    VERTEX *dst = (VERTEX *)(ddverts + (edst * size));
552    VERTEX *in  = (VERTEX *)(ddverts + (ein * size));
553    VERTEX *out = (VERTEX *)(ddverts + (eout * size));
554
555    (void)s;
556
557    if (HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) {
558       VIEWPORT_X( dst->v.x, dstclip[0] );
559       VIEWPORT_Y( dst->v.y, dstclip[1] );
560       VIEWPORT_Z( dst->v.z, dstclip[2] );
561       w = dstclip[3];
562    }
563    else {
564       w = (dstclip[3] == 0.0F) ? 1.0 : (1.0 / dstclip[3]);
565       VIEWPORT_X( dst->v.x, dstclip[0] * w );
566       VIEWPORT_Y( dst->v.y, dstclip[1] * w );
567       VIEWPORT_Z( dst->v.z, dstclip[2] * w );
568    }
569
570    if (MACH64_DEBUG & DEBUG_VERBOSE_PRIMS) {
571       fprintf( stderr, "%s: dst vert: %.2f %.2f %.2f %f\n",
572                __FUNCTION__,
573                dst->v.x,
574                dst->v.y,
575                dst->v.z,
576                w );
577    }
578
579    if ((HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) || 
580        DO_FOG || DO_SPEC || DO_TEX0 || DO_TEX1 ||
581        DO_TEX2 || DO_TEX3 || !HAVE_TINY_VERTICES) {
582
583       dst->v.w = w;
584
585       INTERP_UB( t, dst->ub4[4][0], out->ub4[4][0], in->ub4[4][0] );
586       INTERP_UB( t, dst->ub4[4][1], out->ub4[4][1], in->ub4[4][1] );
587       INTERP_UB( t, dst->ub4[4][2], out->ub4[4][2], in->ub4[4][2] );
588       INTERP_UB( t, dst->ub4[4][3], out->ub4[4][3], in->ub4[4][3] );
589
590       if (DO_SPEC) {
591          INTERP_UB( t, dst->ub4[5][0], out->ub4[5][0], in->ub4[5][0] );
592          INTERP_UB( t, dst->ub4[5][1], out->ub4[5][1], in->ub4[5][1] );
593          INTERP_UB( t, dst->ub4[5][2], out->ub4[5][2], in->ub4[5][2] );
594       }
595       if (DO_FOG) {
596          INTERP_UB( t, dst->ub4[5][3], out->ub4[5][3], in->ub4[5][3] );
597       }
598       if (DO_TEX0) {
599          if (DO_PTEX) {
600             if (HAVE_PTEX_VERTICES) {
601                INTERP_F( t, dst->pv.u0, out->pv.u0, in->pv.u0 );
602                INTERP_F( t, dst->pv.v0, out->pv.v0, in->pv.v0 );
603                INTERP_F( t, dst->pv.q0, out->pv.q0, in->pv.q0 );
604             } else {
605                GLfloat wout = VB->NdcPtr->data[eout][3];
606                GLfloat win = VB->NdcPtr->data[ein][3];
607                GLfloat qout = out->pv.w / wout;
608                GLfloat qin = in->pv.w / win;
609                GLfloat qdst, rqdst;
610
611                ASSERT( !HAVE_HW_DIVIDE );
612
613                INTERP_F( t, dst->v.u0, out->v.u0 * qout, in->v.u0 * qin );
614                INTERP_F( t, dst->v.v0, out->v.v0 * qout, in->v.v0 * qin );
615                INTERP_F( t, qdst, qout, qin );
616
617                rqdst = 1.0 / qdst;
618                dst->v.u0 *= rqdst;
619                dst->v.v0 *= rqdst;
620                dst->v.w *= rqdst;
621             }
622          }
623          else {
624 #ifdef MACH64_PREMULT_TEXCOORDS
625             GLfloat qout = 1 / out->v.w;
626             GLfloat qin = 1 / in->v.w;
627             
628             INTERP_F( t, dst->v.u0, out->v.u0 * qout, in->v.u0 * qin);
629             INTERP_F( t, dst->v.v0, out->v.v0 * qout, in->v.v0 * qin);
630
631             dst->v.u0 *= w;
632             dst->v.v0 *= w;
633 #else
634             INTERP_F( t, dst->v.u0, out->v.u0, in->v.u0 );
635             INTERP_F( t, dst->v.v0, out->v.v0, in->v.v0 );
636 #endif
637          }
638       }
639       if (DO_TEX1) {
640          if (DO_PTEX) {
641             INTERP_F( t, dst->pv.u1, out->pv.u1, in->pv.u1 );
642             INTERP_F( t, dst->pv.v1, out->pv.v1, in->pv.v1 );
643             INTERP_F( t, dst->pv.q1, out->pv.q1, in->pv.q1 );
644          } else {
645 #ifdef MACH64_PREMULT_TEXCOORDS
646             GLfloat qout = 1 / out->v.w;
647             GLfloat qin = 1 / in->v.w;
648             
649             INTERP_F( t, dst->v.u1, out->v.u1 * qout, in->v.u1 * qin );
650             INTERP_F( t, dst->v.v1, out->v.v1 * qout, in->v.v1 * qin );
651
652             dst->v.u1 *= w;
653             dst->v.v1 *= w;
654 #else
655             INTERP_F( t, dst->v.u1, out->v.u1, in->v.u1 );
656             INTERP_F( t, dst->v.v1, out->v.v1, in->v.v1 );
657 #endif
658          }
659       }
660       else if (DO_PTEX) {
661          dst->pv.q0 = 0.0;      /* must be a valid float on radeon */
662       }
663       if (DO_TEX2) {
664          if (DO_PTEX) {
665             INTERP_F( t, dst->pv.u2, out->pv.u2, in->pv.u2 );
666             INTERP_F( t, dst->pv.v2, out->pv.v2, in->pv.v2 );
667             INTERP_F( t, dst->pv.q2, out->pv.q2, in->pv.q2 );
668          } else {
669             INTERP_F( t, dst->v.u2, out->v.u2, in->v.u2 );
670             INTERP_F( t, dst->v.v2, out->v.v2, in->v.v2 );
671          }
672       }
673       if (DO_TEX3) {
674          if (DO_PTEX) {
675             INTERP_F( t, dst->pv.u3, out->pv.u3, in->pv.u3 );
676             INTERP_F( t, dst->pv.v3, out->pv.v3, in->pv.v3 );
677             INTERP_F( t, dst->pv.q3, out->pv.q3, in->pv.q3 );
678          } else {
679             INTERP_F( t, dst->v.u3, out->v.u3, in->v.u3 );
680             INTERP_F( t, dst->v.v3, out->v.v3, in->v.v3 );
681          }
682       }
683    } else {
684       /* 4-dword vertex.  Color is in v[3] and there is no oow coordinate.
685        */
686       INTERP_UB( t, dst->ub4[3][0], out->ub4[3][0], in->ub4[3][0] );
687       INTERP_UB( t, dst->ub4[3][1], out->ub4[3][1], in->ub4[3][1] );
688       INTERP_UB( t, dst->ub4[3][2], out->ub4[3][2], in->ub4[3][2] );
689       INTERP_UB( t, dst->ub4[3][3], out->ub4[3][3], in->ub4[3][3] );
690    }
691 }
692
693 #endif /* rgba && xyzw */
694
695
696 static void TAG(init)( void )
697 {
698    setup_tab[IND].emit = TAG(emit);
699
700 #if (DO_XYZW && DO_RGBA)
701    setup_tab[IND].check_tex_sizes = TAG(check_tex_sizes);
702    setup_tab[IND].interp = TAG(interp);
703 #endif
704
705    if (DO_SPEC)
706       setup_tab[IND].copy_pv = copy_pv_rgba4_spec5;
707    else if (HAVE_HW_DIVIDE || DO_SPEC || DO_FOG || DO_TEX0 || DO_TEX1 ||
708             DO_TEX2 || DO_TEX3 || !HAVE_TINY_VERTICES)
709       setup_tab[IND].copy_pv = copy_pv_rgba4;
710    else
711       setup_tab[IND].copy_pv = copy_pv_rgba3;
712
713    if (DO_TEX3) {
714       if (DO_PTEX) {
715          ASSERT(HAVE_PTEX_VERTICES);
716          setup_tab[IND].vertex_format = PROJ_TEX3_VERTEX_FORMAT;
717          setup_tab[IND].vertex_size = 18;
718       }
719       else {
720          setup_tab[IND].vertex_format = TEX3_VERTEX_FORMAT;
721          setup_tab[IND].vertex_size = 14;
722       }
723    }
724    else if (DO_TEX2) {
725       if (DO_PTEX) {
726          ASSERT(HAVE_PTEX_VERTICES);
727          setup_tab[IND].vertex_format = PROJ_TEX3_VERTEX_FORMAT;
728          setup_tab[IND].vertex_size = 18;
729       }
730       else {
731          setup_tab[IND].vertex_format = TEX2_VERTEX_FORMAT;
732          setup_tab[IND].vertex_size = 12;
733       }
734    }
735    else if (DO_TEX1) {
736       if (DO_PTEX) {
737          ASSERT(HAVE_PTEX_VERTICES);
738          setup_tab[IND].vertex_format = PROJ_TEX1_VERTEX_FORMAT;
739          setup_tab[IND].vertex_size = 12;
740       }
741       else {
742          setup_tab[IND].vertex_format = TEX1_VERTEX_FORMAT;
743          setup_tab[IND].vertex_size = 10;
744       }
745    }
746    else if (DO_TEX0) {
747       if (DO_PTEX && HAVE_PTEX_VERTICES) {
748          setup_tab[IND].vertex_format = PROJ_TEX1_VERTEX_FORMAT;
749          setup_tab[IND].vertex_size = 12;
750       } else {
751          setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT;
752          setup_tab[IND].vertex_size = 8;
753       }
754    }
755    else if (!HAVE_HW_DIVIDE && !DO_SPEC && !DO_FOG && HAVE_TINY_VERTICES) {
756       setup_tab[IND].vertex_format = TINY_VERTEX_FORMAT;
757       setup_tab[IND].vertex_size = 4;
758    } else if (HAVE_NOTEX_VERTICES) {
759       setup_tab[IND].vertex_format = NOTEX_VERTEX_FORMAT;
760       setup_tab[IND].vertex_size = 6;
761    } else {
762       setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT;
763       setup_tab[IND].vertex_size = 8;
764    }
765
766 }
767
768
769 #undef IND
770 #undef TAG