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