Home | History | Annotate | Download | only in swrast_setup
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Keith Whitwell <keithw (at) vmware.com>
     26  */
     27 
     28 
     29 /**
     30  * This is where we handle assigning vertex colors based on front/back
     31  * facing, compute polygon offset and handle glPolygonMode().
     32  */
     33 static void TAG(triangle)(struct gl_context *ctx, GLuint e0, GLuint e1, GLuint e2 )
     34 {
     35    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
     36    SScontext *swsetup = SWSETUP_CONTEXT(ctx);
     37    SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
     38    SWvertex *v[3];
     39    GLfloat z[3];
     40    GLfloat offset, oz0, oz1, oz2;
     41    GLenum mode = GL_FILL;
     42    GLuint facing = 0;
     43    GLchan saved_color[3][4] = { { 0 } };
     44    GLfloat saved_col0[3][4] = { { 0 } };
     45    GLfloat saved_spec[3][4] = { { 0 } };
     46 
     47    v[0] = &verts[e0];
     48    v[1] = &verts[e1];
     49    v[2] = &verts[e2];
     50 
     51    if (IND & (SS_TWOSIDE_BIT | SS_OFFSET_BIT | SS_UNFILLED_BIT))
     52    {
     53       GLfloat ex = v[0]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
     54       GLfloat ey = v[0]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
     55       GLfloat fx = v[1]->attrib[VARYING_SLOT_POS][0] - v[2]->attrib[VARYING_SLOT_POS][0];
     56       GLfloat fy = v[1]->attrib[VARYING_SLOT_POS][1] - v[2]->attrib[VARYING_SLOT_POS][1];
     57       GLfloat cc  = ex*fy - ey*fx;
     58 
     59       if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
     60       {
     61 	 facing = (cc < 0.0F) ^ ctx->Polygon._FrontBit;
     62 
     63 	 if (IND & SS_UNFILLED_BIT)
     64 	    mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
     65 
     66 	 if (facing == 1) {
     67 	    if (IND & SS_TWOSIDE_BIT) {
     68                if (VB->BackfaceColorPtr) {
     69                   GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
     70 
     71                   if (swsetup->intColors) {
     72                      COPY_CHAN4(saved_color[0], v[0]->color);
     73                      COPY_CHAN4(saved_color[1], v[1]->color);
     74                      COPY_CHAN4(saved_color[2], v[2]->color);
     75                   }
     76                   else {
     77                      COPY_4V(saved_col0[0], v[0]->attrib[VARYING_SLOT_COL0]);
     78                      COPY_4V(saved_col0[1], v[1]->attrib[VARYING_SLOT_COL0]);
     79                      COPY_4V(saved_col0[2], v[2]->attrib[VARYING_SLOT_COL0]);
     80                   }
     81 
     82                   if (VB->BackfaceColorPtr->stride) {
     83                      if (swsetup->intColors) {
     84                         SS_COLOR(v[0]->color, vbcolor[e0]);
     85                         SS_COLOR(v[1]->color, vbcolor[e1]);
     86                         SS_COLOR(v[2]->color, vbcolor[e2]);
     87                      }
     88                      else {
     89                         COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[e0]);
     90                         COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[e1]);
     91                         COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[e2]);
     92                      }
     93                   }
     94                   else {
     95                      /* flat shade */
     96                      if (swsetup->intColors) {
     97                         SS_COLOR(v[0]->color, vbcolor[0]);
     98                         SS_COLOR(v[1]->color, vbcolor[0]);
     99                         SS_COLOR(v[2]->color, vbcolor[0]);
    100                      }
    101                      else {
    102                         COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
    103                         COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
    104                         COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], vbcolor[0]);
    105                      }
    106                   }
    107                }
    108 
    109                if (VB->BackfaceSecondaryColorPtr) {
    110 		  GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
    111 
    112 		  COPY_4V(saved_spec[0], v[0]->attrib[VARYING_SLOT_COL1]);
    113 		  COPY_4V(saved_spec[1], v[1]->attrib[VARYING_SLOT_COL1]);
    114 		  COPY_4V(saved_spec[2], v[2]->attrib[VARYING_SLOT_COL1]);
    115 
    116 		  if (VB->BackfaceSecondaryColorPtr->stride) {
    117 		    SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[e0]);
    118 		    SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[e1]);
    119 		    SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[e2]);
    120 		  }
    121 		  else {
    122 		    SS_SPEC(v[0]->attrib[VARYING_SLOT_COL1], vbspec[0]);
    123 		    SS_SPEC(v[1]->attrib[VARYING_SLOT_COL1], vbspec[0]);
    124 		    SS_SPEC(v[2]->attrib[VARYING_SLOT_COL1], vbspec[0]);
    125 		  }
    126 	       }
    127 	    }
    128 	 }
    129       }
    130 
    131       if (IND & SS_OFFSET_BIT) {
    132          const GLfloat max = ctx->DrawBuffer->_DepthMaxF;
    133          /* save original Z values (restored later) */
    134 	 z[0] = v[0]->attrib[VARYING_SLOT_POS][2];
    135 	 z[1] = v[1]->attrib[VARYING_SLOT_POS][2];
    136 	 z[2] = v[2]->attrib[VARYING_SLOT_POS][2];
    137          /* Note that Z values are already scaled to [0,65535] (for example)
    138           * so no MRD value is used here.
    139           */
    140 	 offset = ctx->Polygon.OffsetUnits;
    141 	 if (cc * cc > 1e-16F) {
    142 	    const GLfloat ez = z[0] - z[2];
    143 	    const GLfloat fz = z[1] - z[2];
    144 	    const GLfloat oneOverArea = 1.0F / cc;
    145 	    const GLfloat dzdx = fabsf((ey * fz - ez * fy) * oneOverArea);
    146 	    const GLfloat dzdy = fabsf((ez * fx - ex * fz) * oneOverArea);
    147 	    offset += MAX2(dzdx, dzdy) * ctx->Polygon.OffsetFactor;
    148 	 }
    149          /* new Z values */
    150          oz0 = CLAMP(v[0]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
    151          oz1 = CLAMP(v[1]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
    152          oz2 = CLAMP(v[2]->attrib[VARYING_SLOT_POS][2] + offset, 0.0F, max);
    153       }
    154    }
    155 
    156    if (mode == GL_POINT) {
    157       if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetPoint) {
    158 	 v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
    159 	 v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
    160 	 v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
    161       }
    162       _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_point_tri);
    163    } else if (mode == GL_LINE) {
    164       if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetLine) {
    165 	 v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
    166 	 v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
    167 	 v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
    168       }
    169       _swsetup_render_tri(ctx, e0, e1, e2, facing, _swsetup_edge_render_line_tri);
    170    } else {
    171       if ((IND & SS_OFFSET_BIT) && ctx->Polygon.OffsetFill) {
    172 	 v[0]->attrib[VARYING_SLOT_POS][2] = oz0;
    173 	 v[1]->attrib[VARYING_SLOT_POS][2] = oz1;
    174 	 v[2]->attrib[VARYING_SLOT_POS][2] = oz2;
    175       }
    176       _swrast_Triangle( ctx, v[0], v[1], v[2] );
    177    }
    178 
    179    /*
    180     * Restore original vertex colors, etc.
    181     */
    182    if (IND & SS_OFFSET_BIT) {
    183       v[0]->attrib[VARYING_SLOT_POS][2] = z[0];
    184       v[1]->attrib[VARYING_SLOT_POS][2] = z[1];
    185       v[2]->attrib[VARYING_SLOT_POS][2] = z[2];
    186    }
    187 
    188    if (IND & SS_TWOSIDE_BIT) {
    189       if (facing == 1) {
    190 	if (VB->BackfaceColorPtr) {
    191 	  if (swsetup->intColors) {
    192 	    COPY_CHAN4(v[0]->color, saved_color[0]);
    193 	    COPY_CHAN4(v[1]->color, saved_color[1]);
    194 	    COPY_CHAN4(v[2]->color, saved_color[2]);
    195 	  }
    196 	  else {
    197 	    COPY_4V(v[0]->attrib[VARYING_SLOT_COL0], saved_col0[0]);
    198 	    COPY_4V(v[1]->attrib[VARYING_SLOT_COL0], saved_col0[1]);
    199 	    COPY_4V(v[2]->attrib[VARYING_SLOT_COL0], saved_col0[2]);
    200 	  }
    201 	}
    202 
    203 	if (VB->BackfaceSecondaryColorPtr) {
    204 	  COPY_4V(v[0]->attrib[VARYING_SLOT_COL1], saved_spec[0]);
    205 	  COPY_4V(v[1]->attrib[VARYING_SLOT_COL1], saved_spec[1]);
    206 	  COPY_4V(v[2]->attrib[VARYING_SLOT_COL1], saved_spec[2]);
    207 	}
    208       }
    209    }
    210 }
    211 
    212 
    213 
    214 /* Need to fixup edgeflags when decomposing to triangles:
    215  */
    216 static void TAG(quadfunc)( struct gl_context *ctx, GLuint v0,
    217 		       GLuint v1, GLuint v2, GLuint v3 )
    218 {
    219    if (IND & SS_UNFILLED_BIT) {
    220       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    221       if (VB->EdgeFlag) { /* XXX this test shouldn't be needed (bug 12614) */
    222          GLubyte ef1 = VB->EdgeFlag[v1];
    223          GLubyte ef3 = VB->EdgeFlag[v3];
    224          VB->EdgeFlag[v1] = 0;
    225          TAG(triangle)( ctx, v0, v1, v3 );
    226          VB->EdgeFlag[v1] = ef1;
    227          VB->EdgeFlag[v3] = 0;
    228          TAG(triangle)( ctx, v1, v2, v3 );
    229          VB->EdgeFlag[v3] = ef3;
    230       }
    231    } else {
    232       TAG(triangle)( ctx, v0, v1, v3 );
    233       TAG(triangle)( ctx, v1, v2, v3 );
    234    }
    235 }
    236 
    237 
    238 
    239 
    240 static void TAG(init)( void )
    241 {
    242    tri_tab[IND] = TAG(triangle);
    243    quad_tab[IND] = TAG(quadfunc);
    244 }
    245 
    246 
    247 #undef IND
    248 #undef TAG
    249