Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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
  676.