switch to using driFillInModes fix depthbuffer = 0
[mesa.git] / src / mesa / swrast / s_span.c
index 801595d970c008cd03c5a1e7312e2470f7e22497..41db42e2b80726689fe1b1fdf39acdb224fab2f3 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.1
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -126,7 +126,17 @@ _swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span )
 {
    GLuint i;
    for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
-      COPY_4V(span->tex[i], ctx->Current.RasterTexCoords[i]);
+      const GLfloat *tc = ctx->Current.RasterTexCoords[i];
+      if (tc[3] > 0.0F) {
+         /* use (s/q, t/q, r/q, 1) */
+         span->tex[i][0] = tc[0] / tc[3];
+         span->tex[i][1] = tc[1] / tc[3];
+         span->tex[i][2] = tc[2] / tc[3];
+         span->tex[i][3] = 1.0;
+      }
+      else {
+         ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F);
+      }
       ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F);
       ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F);
    }
@@ -340,10 +350,16 @@ _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
    return lambda;
 }
 
-/*
+
+/**
  * Fill in the span.texcoords array from the interpolation values.
- * XXX We could optimize here for the case when dq = 0.  That would
- * usually be the case when using an orthographic projection.
+ * Note: in the places where we divide by Q (or mult by invQ) we're
+ * really doing two things: perspective correction and texcoord
+ * projection.  Remember, for texcoord (s,t,r,q) we need to index
+ * texels with (s/q, t/q, r/q).
+ * If we're using a fragment program, we never do the division
+ * for texcoord projection.  That's done by the TXP instruction
+ * or user-written code.
  */
 static void
 interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
@@ -363,11 +379,12 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
             if (obj) {
                const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
                needLambda = (obj->MinFilter != obj->MagFilter)
-                  || ctx->FragmentProgram.Enabled;
+                  || ctx->FragmentProgram._Enabled;
                texW = img->WidthScale;
                texH = img->HeightScale;
             }
             else {
+               /* using a fragment program */
                texW = 1.0;
                texH = 1.0;
                needLambda = GL_FALSE;
@@ -387,19 +404,42 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
                GLfloat r = span->tex[u][2];
                GLfloat q = span->tex[u][3];
                GLuint i;
-               for (i = 0; i < span->end; i++) {
-                  const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-                  texcoord[i][0] = s * invQ;
-                  texcoord[i][1] = t * invQ;
-                  texcoord[i][2] = r * invQ;
-                  texcoord[i][3] = q;
-                  lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
-                                                   dqdx, dqdy, texW, texH,
-                                                   s, t, q, invQ);
-                  s += dsdx;
-                  t += dtdx;
-                  r += drdx;
-                  q += dqdx;
+               if (ctx->FragmentProgram._Enabled) {
+                  /* do perspective correction but don't divide s, t, r by q */
+                  const GLfloat dwdx = span->dwdx;
+                  GLfloat w = span->w;
+                  for (i = 0; i < span->end; i++) {
+                     const GLfloat invW = 1.0F / w;
+                     texcoord[i][0] = s * invW;
+                     texcoord[i][1] = t * invW;
+                     texcoord[i][2] = r * invW;
+                     texcoord[i][3] = q * invW;
+                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+                                                        dqdx, dqdy, texW, texH,
+                                                        s, t, q, invW);
+                     s += dsdx;
+                     t += dtdx;
+                     r += drdx;
+                     q += dqdx;
+                     w += dwdx;
+                  }
+
+               }
+               else {
+                  for (i = 0; i < span->end; i++) {
+                     const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+                     texcoord[i][0] = s * invQ;
+                     texcoord[i][1] = t * invQ;
+                     texcoord[i][2] = r * invQ;
+                     texcoord[i][3] = q;
+                     lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+                                                        dqdx, dqdy, texW, texH,
+                                                        s, t, q, invQ);
+                     s += dsdx;
+                     t += dtdx;
+                     r += drdx;
+                     q += dqdx;
+                  }
                }
                span->arrayMask |= SPAN_LAMBDA;
             }
@@ -415,7 +455,25 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
                GLfloat r = span->tex[u][2];
                GLfloat q = span->tex[u][3];
                GLuint i;
-               if (dqdx == 0.0) {
+               if (ctx->FragmentProgram._Enabled) {
+                  /* do perspective correction but don't divide s, t, r by q */
+                  const GLfloat dwdx = span->dwdx;
+                  GLfloat w = span->w;
+                  for (i = 0; i < span->end; i++) {
+                     const GLfloat invW = 1.0F / w;
+                     texcoord[i][0] = s * invW;
+                     texcoord[i][1] = t * invW;
+                     texcoord[i][2] = r * invW;
+                     texcoord[i][3] = q * invW;
+                     lambda[i] = 0.0;
+                     s += dsdx;
+                     t += dtdx;
+                     r += drdx;
+                     q += dqdx;
+                     w += dwdx;
+                  }
+               }
+               else if (dqdx == 0.0F) {
                   /* Ortho projection or polygon's parallel to window X axis */
                   const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
                   for (i = 0; i < span->end; i++) {
@@ -455,7 +513,7 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
       if (obj) {
          const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
          needLambda = (obj->MinFilter != obj->MagFilter)
-            || ctx->FragmentProgram.Enabled;
+            || ctx->FragmentProgram._Enabled;
          texW = (GLfloat) img->WidthScale;
          texH = (GLfloat) img->HeightScale;
       }
@@ -480,19 +538,42 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
          GLfloat r = span->tex[0][2];
          GLfloat q = span->tex[0][3];
          GLuint i;
-         for (i = 0; i < span->end; i++) {
-            const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
-            lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
-                                             dqdx, dqdy, texW, texH,
-                                             s, t, q, invQ);
-            texcoord[i][0] = s * invQ;
-            texcoord[i][1] = t * invQ;
-            texcoord[i][2] = r * invQ;
-            texcoord[i][3] = q;
-            s += dsdx;
-            t += dtdx;
-            r += drdx;
-            q += dqdx;
+         if (ctx->FragmentProgram._Enabled) {
+            /* do perspective correction but don't divide s, t, r by q */
+            const GLfloat dwdx = span->dwdx;
+            GLfloat w = span->w;
+            for (i = 0; i < span->end; i++) {
+               const GLfloat invW = 1.0F / w;
+               texcoord[i][0] = s * invW;
+               texcoord[i][1] = t * invW;
+               texcoord[i][2] = r * invW;
+               texcoord[i][3] = q * invW;
+               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+                                                  dqdx, dqdy, texW, texH,
+                                                  s, t, q, invW);
+               s += dsdx;
+               t += dtdx;
+               r += drdx;
+               q += dqdx;
+               w += dwdx;
+            }
+         }
+         else {
+            /* tex.c */
+            for (i = 0; i < span->end; i++) {
+               const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
+               lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy,
+                                                dqdx, dqdy, texW, texH,
+                                                s, t, q, invQ);
+               texcoord[i][0] = s * invQ;
+               texcoord[i][1] = t * invQ;
+               texcoord[i][2] = r * invQ;
+               texcoord[i][3] = q;
+               s += dsdx;
+               t += dtdx;
+               r += drdx;
+               q += dqdx;
+            }
          }
          span->arrayMask |= SPAN_LAMBDA;
       }
@@ -508,7 +589,24 @@ interpolate_texcoords(GLcontext *ctx, struct sw_span *span)
          GLfloat r = span->tex[0][2];
          GLfloat q = span->tex[0][3];
          GLuint i;
-         if (dqdx == 0.0) {
+         if (ctx->FragmentProgram._Enabled) {
+            /* do perspective correction but don't divide s, t, r by q */
+            const GLfloat dwdx = span->dwdx;
+            GLfloat w = span->w;
+            for (i = 0; i < span->end; i++) {
+               const GLfloat invW = 1.0F / w;
+               texcoord[i][0] = s * invW;
+               texcoord[i][1] = t * invW;
+               texcoord[i][2] = r * invW;
+               texcoord[i][3] = q * invW;
+               s += dsdx;
+               t += dtdx;
+               r += drdx;
+               q += dqdx;
+               w += dwdx;
+            }
+         }
+         else if (dqdx == 0.0F) {
             /* Ortho projection or polygon's parallel to window X axis */
             const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q);
             for (i = 0; i < span->end; i++) {
@@ -653,7 +751,7 @@ multi_write_index_span( GLcontext *ctx, struct sw_span *span )
          ASSERT(span->end < MAX_WIDTH);
 
          /* Set the current read/draw buffer */
-         swrast->CurrentBuffer = bufferBit;
+         swrast->CurrentBufferBit = bufferBit;
          (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
 
          /* make copy of incoming indexes */
@@ -710,7 +808,7 @@ multi_write_rgba_span( GLcontext *ctx, struct sw_span *span )
          ASSERT(span->end < MAX_WIDTH);
 
          /* Set the current read/draw buffer */
-         swrast->CurrentBuffer = bufferBit;
+         swrast->CurrentBufferBit = bufferBit;
          (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit);
 
          /* make copy of incoming colors */
@@ -1006,8 +1104,8 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
    }
 
    /* Fragment program */
-   if (ctx->FragmentProgram.Enabled) {
-      /* Now we may need to interpolate the colors */
+   if (ctx->FragmentProgram._Enabled) {
+      /* Now we may need to interpolate the colors and texcoords */
       if ((span->interpMask & SPAN_RGBA) &&
           (span->arrayMask & SPAN_RGBA) == 0) {
          interpolate_colors(ctx, span);
@@ -1016,6 +1114,9 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
       if (span->interpMask & SPAN_SPEC) {
          interpolate_specular(ctx, span);
       }
+      if ((span->interpMask & SPAN_TEXTURE)
+          && (span->arrayMask & SPAN_TEXTURE) == 0)
+         interpolate_texcoords(ctx, span);
       _swrast_exec_fragment_program(ctx, span);
       monoColor = GL_FALSE;
    }
@@ -1118,14 +1219,32 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
       /* write pixels */
       if (span->arrayMask & SPAN_XY) {
          /* array of pixel coords */
-         /* XXX test for mono color */
-         (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
-             span->array->y, (const GLchan (*)[4]) span->array->rgba, span->array->mask);
-         if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
-            _swrast_write_alpha_pixels(ctx, span->end,
-                                     span->array->x, span->array->y,
-                                     (const GLchan (*)[4]) span->array->rgba,
-                                     span->array->mask);
+         if (monoColor) {
+            /* all pixels have same color */
+            GLchan color[4];
+            color[RCOMP] = FixedToChan(span->red);
+            color[GCOMP] = FixedToChan(span->green);
+            color[BCOMP] = FixedToChan(span->blue);
+            color[ACOMP] = FixedToChan(span->alpha);
+            (*swrast->Driver.WriteMonoRGBAPixels)(ctx, span->end,
+                     span->array->x, span->array->y, color, span->array->mask);
+            if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
+               _swrast_write_mono_alpha_pixels(ctx, span->end,
+                                              span->array->x, span->array->y,
+                                              color[ACOMP], span->array->mask);
+            }
+         }
+         else {
+            (*swrast->Driver.WriteRGBAPixels)(ctx, span->end,
+                                       span->array->x, span->array->y,
+                                       (const GLchan (*)[4]) span->array->rgba,
+                                       span->array->mask);
+            if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
+               _swrast_write_alpha_pixels(ctx, span->end,
+                                       span->array->x, span->array->y,
+                                       (const GLchan (*)[4]) span->array->rgba,
+                                       span->array->mask);
+            }
          }
       }
       else {
@@ -1138,7 +1257,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
             color[BCOMP] = FixedToChan(span->blue);
             color[ACOMP] = FixedToChan(span->alpha);
             (*swrast->Driver.WriteMonoRGBASpan)(ctx, span->end, span->x,
-                                                span->y, color, span->array->mask);
+                                           span->y, color, span->array->mask);
             if (swrast->_RasterMask & ALPHABUF_BIT) {
                _swrast_write_mono_alpha_span(ctx, span->end, span->x, span->y,
                       color[ACOMP],
@@ -1207,7 +1326,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
          span->primitive == GL_POLYGON  ||  span->primitive == GL_BITMAP);
    ASSERT(span->end <= MAX_WIDTH);
    ASSERT((span->interpMask & span->arrayMask) == 0);
-   ASSERT(ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram.Enabled);
+   ASSERT(ctx->Texture._EnabledCoordUnits || ctx->FragmentProgram._Enabled);
 
    /*
    printf("%s()  interp 0x%x  array 0x%x\n", __FUNCTION__, span->interpMask, span->arrayMask);
@@ -1267,7 +1386,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
       /* Texturing without alpha is done after depth-testing which
        * gives a potential speed-up.
        */
-      if (ctx->FragmentProgram.Enabled)
+      if (ctx->FragmentProgram._Enabled)
          _swrast_exec_fragment_program( ctx, span );
       else
          _swrast_texture_span( ctx, span );
@@ -1334,7 +1453,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
          interpolate_specular(ctx, span);
       }
 
-      if (ctx->FragmentProgram.Enabled)
+      if (ctx->FragmentProgram._Enabled)
          _swrast_exec_fragment_program( ctx, span );
       else
          _swrast_texture_span( ctx, span );