Merge branch 'mesa_7_5_branch' into dlist-statechange-shortcircuit
[mesa.git] / src / mesa / main / texrender.c
index db720cef6e0089225e245e977d65cecaccde1f3f..cc74d58fbd181de19cf3f6d47d1ff50855f2de3a 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "context.h"
 #include "fbobject.h"
+#include "texformat.h"
 #include "texrender.h"
 #include "renderbuffer.h"
 
  */
 struct texture_renderbuffer
 {
-   struct gl_renderbuffer Base;   /* Base class object */
+   struct gl_renderbuffer Base;   /**< Base class object */
    struct gl_texture_image *TexImage;
    StoreTexelFunc Store;
-   GLint Zoffset;
+   GLint Yoffset;                 /**< Layer for 1D array textures. */
+   GLint Zoffset;                 /**< Layer for 2D array textures, or slice
+                                  * for 3D textures
+                                  */
 };
 
 
@@ -37,12 +41,39 @@ texture_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    ASSERT(trb->TexImage->Width == rb->Width);
    ASSERT(trb->TexImage->Height == rb->Height);
 
+   y += trb->Yoffset;
+
    if (rb->DataType == CHAN_TYPE) {
       GLchan *rgbaOut = (GLchan *) values;
       for (i = 0; i < count; i++) {
          trb->TexImage->FetchTexelc(trb->TexImage, x + i, y, z, rgbaOut + 4 * i);
       }
    }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      GLushort *zValues = (GLushort *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
+         zValues[i] = (GLushort) (flt * 0xffff);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      GLuint *zValues = (GLuint *) values;
+      /*
+      const GLdouble scale = (GLdouble) 0xffffffff;
+      */
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->TexImage->FetchTexelf(trb->TexImage, x + i, y, z, &flt);
+#if 0
+         /* this should work, but doesn't (overflow due to low precision) */
+         zValues[i] = (GLuint) (flt * scale);
+#else
+         /* temporary hack */
+         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+#endif
+      }
+   }
    else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
       GLuint *zValues = (GLuint *) values;
       for (i = 0; i < count; i++) {
@@ -69,15 +100,38 @@ texture_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    if (rb->DataType == CHAN_TYPE) {
       GLchan *rgbaOut = (GLchan *) values;
       for (i = 0; i < count; i++) {
-         trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i], z,
-                                    rgbaOut + 4 * i);
+         trb->TexImage->FetchTexelc(trb->TexImage, x[i], y[i] + trb->Yoffset,
+                                   z, rgbaOut + 4 * i);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      GLushort *zValues = (GLushort *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+                                   z, &flt);
+         zValues[i] = (GLushort) (flt * 0xffff);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      GLuint *zValues = (GLuint *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+                                   z, &flt);
+#if 0
+         zValues[i] = (GLuint) (flt * 0xffffffff);
+#else
+         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+#endif
       }
    }
    else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
       GLuint *zValues = (GLuint *) values;
       for (i = 0; i < count; i++) {
          GLfloat flt;
-         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i], z, &flt);
+         trb->TexImage->FetchTexelf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+                                   z, &flt);
          zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
       }
    }
@@ -99,6 +153,8 @@ texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLint z = trb->Zoffset;
    GLuint i;
 
+   y += trb->Yoffset;
+
    if (rb->DataType == CHAN_TYPE) {
       const GLchan *rgba = (const GLchan *) values;
       for (i = 0; i < count; i++) {
@@ -108,11 +164,80 @@ texture_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
          rgba += 4;
       }
    }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort *zValues = (const GLushort *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
+   }
+}
+
+/**
+ * Put row of RGB values into a renderbuffer that wraps a texture image.
+ */
+static void
+texture_put_row_rgb(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
+                GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   y += trb->Yoffset;
+
+   if (rb->DataType == CHAN_TYPE) {
+      const GLchan *rgb = (const GLchan *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, rgb);
+         }
+         rgb += 3;
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort *zValues = (const GLushort *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
    else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
       const GLuint *zValues = (const GLuint *) values;
       for (i = 0; i < count; i++) {
          if (!mask || mask[i]) {
-            GLfloat flt = (zValues[i] >> 8) * (1.0 / 0xffffff);
+            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
             trb->Store(trb->TexImage, x + i, y, z, &flt);
          }
       }
@@ -132,6 +257,8 @@ texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
    const GLint z = trb->Zoffset;
    GLuint i;
 
+   y += trb->Yoffset;
+
    if (rb->DataType == CHAN_TYPE) {
       const GLchan *rgba = (const GLchan *) value;
       for (i = 0; i < count; i++) {
@@ -140,9 +267,25 @@ texture_put_mono_row(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
          }
       }
    }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort zValue = *((const GLushort *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, &zValue);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint zValue = *((const GLuint *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, &zValue);
+         }
+      }
+   }
    else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
       const GLuint zValue = *((const GLuint *) value);
-      const GLfloat flt = (zValue >> 8) * (1.0 / 0xffffff);
+      const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
       for (i = 0; i < count; i++) {
          if (!mask || mask[i]) {
             trb->Store(trb->TexImage, x + i, y, z, &flt);
@@ -169,17 +312,33 @@ texture_put_values(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint count,
       const GLchan *rgba = (const GLchan *) values;
       for (i = 0; i < count; i++) {
          if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i], z, rgba);
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
          }
          rgba += 4;
       }
    }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort *zValues = (const GLushort *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
+         }
+      }
+   }
    else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
       const GLuint *zValues = (const GLuint *) values;
       for (i = 0; i < count; i++) {
          if (!mask || mask[i]) {
-            GLfloat flt = (zValues[i] >> 8) * (1.0 / 0xffffff);
-            trb->Store(trb->TexImage, x[i], y[i], z, &flt);
+            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
          }
       }
    }
@@ -203,16 +362,32 @@ texture_put_mono_values(GLcontext *ctx, struct gl_renderbuffer *rb,
       const GLchan *rgba = (const GLchan *) value;
       for (i = 0; i < count; i++) {
          if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i], z, rgba);
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint zValue = *((const GLuint *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort zValue = *((const GLushort *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
          }
       }
    }
    else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
       const GLuint zValue = *((const GLuint *) value);
-      const GLfloat flt = (zValue >> 8) * (1.0 / 0xffffff);
+      const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
       for (i = 0; i < count; i++) {
          if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i], z, &flt);
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
          }
       }
    }
@@ -258,12 +433,13 @@ wrap_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
    trb->Base.GetRow = texture_get_row;
    trb->Base.GetValues = texture_get_values;
    trb->Base.PutRow = texture_put_row;
+   trb->Base.PutRowRGB = texture_put_row_rgb;
    trb->Base.PutMonoRow = texture_put_mono_row;
    trb->Base.PutValues = texture_put_values;
    trb->Base.PutMonoValues = texture_put_mono_values;
 
    /* update attachment point */
-   att->Renderbuffer = &(trb->Base);
+   _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
 }
 
 
@@ -279,6 +455,7 @@ update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
    struct texture_renderbuffer *trb
       = (struct texture_renderbuffer *) att->Renderbuffer;
 
+   (void) ctx;
    ASSERT(trb);
 
    trb->TexImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
@@ -287,19 +464,30 @@ update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
    trb->Store = trb->TexImage->TexFormat->StoreTexel;
    ASSERT(trb->Store);
 
-   trb->Zoffset = att->Zoffset;
+   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
+      trb->Yoffset = att->Zoffset;
+      trb->Zoffset = 0;
+   }
+   else {
+      trb->Yoffset = 0;
+      trb->Zoffset = att->Zoffset;
+   }
 
    trb->Base.Width = trb->TexImage->Width;
    trb->Base.Height = trb->TexImage->Height;
    trb->Base.InternalFormat = trb->TexImage->InternalFormat;
    /* XXX may need more special cases here */
-   if (trb->TexImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) {
+   if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z24_S8) {
       trb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
       trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
    }
-   else if (trb->TexImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
+   else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z16) {
       trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
-      trb->Base.DataType = GL_FLOAT;
+      trb->Base.DataType = GL_UNSIGNED_SHORT;
+   }
+   else if (trb->TexImage->TexFormat->MesaFormat == MESA_FORMAT_Z32) {
+      trb->Base._ActualFormat = GL_DEPTH_COMPONENT;
+      trb->Base.DataType = GL_UNSIGNED_INT;
    }
    else {
       trb->Base._ActualFormat = trb->TexImage->InternalFormat;
@@ -319,6 +507,7 @@ update_wrapper(GLcontext *ctx, const struct gl_renderbuffer_attachment *att)
    trb->Base.BlueBits = trb->TexImage->TexFormat->BlueBits;
    trb->Base.AlphaBits = trb->TexImage->TexFormat->AlphaBits;
    trb->Base.DepthBits = trb->TexImage->TexFormat->DepthBits;
+   trb->Base.StencilBits = trb->TexImage->TexFormat->StencilBits;
 }
 
 
@@ -345,6 +534,8 @@ _mesa_render_texture(GLcontext *ctx,
                      struct gl_framebuffer *fb,
                      struct gl_renderbuffer_attachment *att)
 {
+   (void) fb;
+
    if (!att->Renderbuffer) {
       wrap_texture(ctx, att);
    }
@@ -360,4 +551,6 @@ _mesa_finish_render_texture(GLcontext *ctx,
    /* The renderbuffer texture wrapper will get deleted by the
     * normal mechanism for deleting renderbuffers.
     */
+   (void) ctx;
+   (void) att;
 }