mesa: add new signed rgba texture format
authorRoland Scheidegger <sroland@vmware.com>
Fri, 27 Mar 2009 18:39:52 +0000 (19:39 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Sat, 28 Mar 2009 01:02:42 +0000 (02:02 +0100)
This is a (partial) backport of the signed texture format support in OGL 3.1.
Since it wasn't promoted from an existing extension roll our own.

20 files changed:
docs/MESA_texture_signed_rgba.spec [new file with mode: 0644]
docs/extensions.html
src/mesa/glapi/gl_API.xml
src/mesa/main/colortab.c
src/mesa/main/convolve.c
src/mesa/main/extensions.c
src/mesa/main/histogram.c
src/mesa/main/image.c
src/mesa/main/image.h
src/mesa/main/macros.h
src/mesa/main/mipmap.c
src/mesa/main/mtypes.h
src/mesa/main/texformat.c
src/mesa/main/texformat.h
src/mesa/main/texformat_tmp.h
src/mesa/main/teximage.c
src/mesa/main/texstore.c
src/mesa/main/texstore.h
src/mesa/state_tracker/st_cb_readpixels.c
src/mesa/swrast/s_readpix.c

diff --git a/docs/MESA_texture_signed_rgba.spec b/docs/MESA_texture_signed_rgba.spec
new file mode 100644 (file)
index 0000000..49c8e9e
--- /dev/null
@@ -0,0 +1,214 @@
+Name
+
+    MESA_texture_signed_rgba
+
+Name Strings
+
+    GL_MESA_texture_signed_rgba
+
+Contact
+
+
+
+Notice
+
+
+
+IP Status
+
+    No known IP issues
+
+Status
+
+
+
+Version
+
+    0.3, 2009-03-24
+
+Number
+
+    Not assigned ?
+
+Dependencies
+
+    Written based on the wording of the OpenGL 2.0 specification.
+
+    This extension trivially interacts with ARB_texture_float.
+    This extension shares some language with ARB_texture_compression_rgtc
+    but does not depend on it.
+
+Overview
+
+    OpenGL prior to 3.1 does not support any signed texture formats.
+    ARB_texture_compression_rgtc introduces some compressed red and
+    red_green signed formats but no uncompressed ones, which might
+    still be useful. NV_texture_shader adds signed texture formats,
+    but also a lot of functionality which has been superceded by fragment
+    shaders.
+    It is usually possible to get the same functionality
+    using a unsigned format by doing scale and bias in a shader, but this
+    is undesirable since modern hardware has direct support for this.
+    This extension adds a signed 4-channel texture format by backporting
+    the relevant features from OpenGL 3.1, as a means to support this in
+    OpenGL implementations only supporting older versions.
+
+Issues
+
+    1) What should this extension be called?
+
+       RESOLVED: MESA_texture_signed_rgba seems reasonable.
+       The rgba part is there because only 4 channel format is supported.
+
+
+    2) Should the full set of signed formats (alpha, luminance, rgb, etc.)
+       be supported?
+
+       RESOLVED: NO. To keep this extension simple, only add the most
+       universal format, rgba. alpha/luminance can't be trivially supported
+       since OpenGL 3.1 does not support them any longer, and there is some
+       implied dependency on ARB_texture_rg for red/red_green formats so
+       avoid all this. Likewise, only 8 bits per channel is supported.
+
+
+    3) Should this extension use new enums for the texture formats?
+
+       RESOLVED: NO. Same enums as those used in OpenGL 3.1.
+
+
+    4) How are signed integer values mapped to floating-point values?
+
+       RESOLVED: Same as described in issue 5) of
+       ARB_texture_compression_rgtc (quote):
+       A signed 8-bit two's complement value X is computed to
+       a floating-point value Xf with the formula:
+
+                { X / 127.0, X > -128
+           Xf = {
+                { -1.0,      X == -128
+
+       This conversion means -1, 0, and +1 are all exactly representable,
+       however -128 and -127 both map to -1.0.  Mapping -128 to -1.0
+       avoids the numerical awkwardness of have a representable value
+       slightly more negative than -1.0.
+
+       This conversion is intentionally NOT the "byte" conversion listed
+       in Table 2.9 for component conversions.  That conversion says:
+
+           Xf = (2*X + 1) / 255.0
+
+       The Table 2.9 conversion is incapable of exactly representing
+       zero.
+
+       (Difference to ARB_texture_compression_rgtc):
+       This is the same mapping as OpenGL 3.1 uses.
+       This is also different to what NV_texture_shader used.
+       The above mapping should be considered the reference, but there
+       is some leeway so other mappings are allowed for implementations which
+       cannot do this. Particulary the mapping given in NV_texture_shader or
+       the standard OpenGL byte/float mapping is considered acceptable too, as
+       might be a mapping which represents -1.0 by -128, 0.0 by 0 and 1.0 by
+       127 (that is, uses different scale factors for negative and positive
+       numbers).
+       Also, it is ok to store incoming GL_BYTE user data as-is, without
+       converting to GL_FLOAT (using the standard OpenGL float/byte mapping)
+       and converting back (using the mapping described here).
+       Other than those subtle issues there are no other non-standard
+       conversions used, so when using for instance CopyTexImage2D with
+       a framebuffer clamped to [0,1] all converted numbers will be in the range
+       [0, 127] (and not scaled and biased).
+
+
+    5) How will signed components resulting from RGBA8_SNORM texture
+       fetches interact with fragment coloring?
+
+       RESOLVED: Same as described in issue 6) of
+       ARB_texture_compression_rgtc (quote):
+       The specification language for this extension is silent
+       about clamping behavior leaving this to the core specification
+       and other extensions.  The clamping or lack of clamping is left
+       to the core specification and other extensions.
+
+       For assembly program extensions supporting texture fetches
+       (ARB_fragment_program, NV_fragment_program, NV_vertex_program3,
+       etc.) or the OpenGL Shading Language, these signed formats will
+       appear as expected with unclamped signed components as a result
+       of a texture fetch instruction.
+
+       If ARB_color_buffer_float is supported, its clamping controls
+       will apply.
+
+       NV_texture_shader extension, if supported, adds support for
+       fixed-point textures with signed components and relaxed the
+       fixed-function texture environment clamping appropriately.  If the
+       NV_texture_shader extension is supported, its specified behavior
+       for the texture environment applies where intermediate values
+       are clamped to [-1,1] unless stated otherwise as in the case
+       of explicitly clamped to [0,1] for GL_COMBINE.  or clamping the
+       linear interpolation weight to [0,1] for GL_DECAL and GL_BLEND.
+
+       Otherwise, the conventional core texture environment clamps
+       incoming, intermediate, and output color components to [0,1].
+
+       This implies that the conventional texture environment
+       functionality of unextended OpenGL 1.5 or OpenGL 2.0 without
+       using GLSL (and with none of the extensions referred to above)
+       is unable to make proper use of the signed texture formats added
+       by this extension because the conventional texture environment
+       requires texture source colors to be clamped to [0,1].  Texture
+       filtering of these signed formats would be still signed, but
+       negative values generated post-filtering would be clamped to
+       zero by the core texture environment functionality.  The
+       expectation is clearly that this extension would be co-implemented
+       with one of the previously referred to extensions or used with
+       GLSL for the new signed formats to be useful.
+
+
+    6) Should the RGBA_SNORM tokens also be accepted by CopyTexImage
+       functions?
+
+       RESOLVED: YES.
+
+
+    7) What to do with GetTexParameter if ARB_texture_float is supported,
+       in particular what datatype should this return for TEXTURE_RED_TYPE_ARB,
+       TEXTURE_GREEN_TYPE_ARB, TEXTURE_BLUE_TYPE_ARB, TEXTURE_ALPHA_TYPE_ARB?
+
+       RESOLVED: ARB_texture_float states type is either NONE,
+       UNSIGNED_NORMALIZED_ARB, or FLOAT. This extension adds a new enum,
+       SIGNED_NORMALIZED, which will be returned accordingly. This is the
+       same behaviour as in OpenGL 3.1.
+
+
+New Tokens
+
+
+    Accepted by the <internalformat> parameter of
+    TexImage1D, TexImage2D, TexImage3D, CopyTexImage1D, and CopyTexImage2D:
+
+        RGBA_SNORM                                0x8F93
+        RGBA8_SNORM                               0x8F97
+
+    Returned by the <params> parameter of GetTexLevelParameter:
+
+        SIGNED_NORMALIZED                         0x8F9C
+
+
+Additions to Chapter 3 of the OpenGL 2.0 Specification (Rasterization):
+
+ -- Section 3.8.1, Texture Image Specification
+
+    Add to Table 3.16 (page 154): Sized internal formats
+
+    Sized             Base             R    G    B    A    L    I    D
+    Internal Format   Internal Format bits bits bits bits bits bits bits
+    ---------------   --------------- ---- ---- ---- ---- ---- ---- ----
+    RGBA8_SNORM       RGBA             8    8    8    8    0    0    0
+
+
+Dependencies on ARB_texture_float extension:
+
+    If ARB_texture_float is supported, GetTexParameter queries with <value>
+    of TEXTURE_RED_TYPE_ARB, TEXTURE_GREEN_TYPE_ARB, TEXTURE_BLUE_TYPE_ARB or
+    TEXTURE_ALPHA_TYPE_ARB return SIGNED_NORMALIZED if
+    the base internal format is RGBA_SNORM.
index dbb8ebadaf2823ead24824d79168d73a0445a020..91ed20e5ceb79f0fb3fa2e6599bf90e29b2314af 100644 (file)
@@ -24,6 +24,7 @@ The specifications follow.
 <LI><A HREF="MESA_resize_buffers.spec">MESA_resize_buffers.spec</A>
 <LI><A HREF="MESA_set_3dfx_mode.spec">MESA_set_3dfx_mode.spec</A>
 <LI><A HREF="MESA_sprite_point.spec">MESA_sprite_point.spec</A> (obsolete)
+<LI><A HREF="MESA_texture_signed_rgba.spec">MESA_texture_signed_rgba.spec</A>
 <LI><A HREF="MESA_trace.spec">MESA_trace.spec</A> (obsolete)
 <LI><A HREF="MESA_window_pos.spec">MESA_window_pos.spec</A>
 <LI><A HREF="MESA_ycbcr_texture.spec">MESA_ycbcr_texture.spec</A>
index cc3e3ae6bffbcffe9397007f8e1c5faf38bf7c3a..ef774f2e6084c3f4ee92ec1d81af2b02eabe552e 100644 (file)
     </function>
 </category>
 
+<category name="GL_MESA_texture_signed_rgba">
+    <enum name="SIGNED_NORMALIZED"                        value="0x8F9C"/>
+    <enum name="RGBA_SNORM"                               value="0x8F93"/>
+    <enum name="RGBA8_SNORM"                              value="0x8F97"/>
+</category>
+
 <category name="GL_MESA_shader_debug">
     <enum name="DEBUG_OBJECT_MESA"                        value="0x8759"/>
     <enum name="DEBUG_PRINT_MESA"                         value="0x875A"/>
index bd9cf438b4f5f9ed223462da5267a1187cadaff0..b05c0513aa6cff2765084fb38ebb765d75f9d2a0 100644 (file)
@@ -718,7 +718,7 @@ _mesa_GetColorTable( GLenum target, GLenum format,
    }
 
    _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
-                              format, type, data, &ctx->Pack, 0x0);
+                              format, type, data, &ctx->Pack, 0x0, GL_FALSE);
 
    if (ctx->Pack.BufferObj->Name) {
       ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
index 814c6a0a5a6b13d24d8f7b4d7b58bf32cd589dee..63b652bf7050b1c3e418548d19ceefbe6ddfa96b 100644 (file)
@@ -626,7 +626,7 @@ _mesa_GetConvolutionFilter(GLenum target, GLenum format, GLenum type,
                                           row, 0);
       GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + row * filter->Width * 4);
       _mesa_pack_rgba_span_float(ctx, filter->Width, src,
-                                 format, type, dst, &ctx->Pack, 0x0);
+                                 format, type, dst, &ctx->Pack, 0x0, GL_FALSE);
    }
 
    if (ctx->Pack.BufferObj->Name) {
@@ -836,7 +836,7 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type,
                                           format, type, 0);
       _mesa_pack_rgba_span_float(ctx, filter->Width,
                                  (GLfloat (*)[4]) filter->Filter,
-                                 format, type, dst, &ctx->Pack, 0x0);
+                                 format, type, dst, &ctx->Pack, 0x0, GL_FALSE);
    }
 
    /* Column filter */
@@ -845,7 +845,7 @@ _mesa_GetSeparableFilter(GLenum target, GLenum format, GLenum type,
                                           format, type, 0);
       GLfloat (*src)[4] = (GLfloat (*)[4]) (filter->Filter + colStart);
       _mesa_pack_rgba_span_float(ctx, filter->Height, src,
-                                 format, type, dst, &ctx->Pack, 0x0);
+                                 format, type, dst, &ctx->Pack, 0x0, GL_FALSE);
    }
 
    (void) span;  /* unused at this time */
index 2d2bf517843152cdeeb34de3c0d85a6f929363a5..147d923e64fad8a847a9663850d5ada7bbf6a95b 100644 (file)
@@ -150,6 +150,7 @@ static const struct {
    { OFF, "GL_MESA_packed_depth_stencil",      F(MESA_packed_depth_stencil) },
    { OFF, "GL_MESA_resize_buffers",            F(MESA_resize_buffers) },
    { OFF, "GL_MESA_texture_array",             F(MESA_texture_array) },
+   { OFF, "GL_MESA_texture_signed_rgba",       F(MESA_texture_signed_rgba) },
    { OFF, "GL_MESA_ycbcr_texture",             F(MESA_ycbcr_texture) },
    { ON,  "GL_MESA_window_pos",                F(ARB_window_pos) },
    { OFF, "GL_NV_blend_square",                F(NV_blend_square) },
index 905c1ad830107f044a13e5360bfeec7d4d586424..febf8d99c456b745869ae6d58d11f2271aca050b 100644 (file)
@@ -684,7 +684,7 @@ _mesa_GetMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvo
       minmax[1][BCOMP] = CLAMP(ctx->MinMax.Max[BCOMP], 0.0F, 1.0F);
       minmax[1][ACOMP] = CLAMP(ctx->MinMax.Max[ACOMP], 0.0F, 1.0F);
       _mesa_pack_rgba_span_float(ctx, 2, minmax,
-                                 format, type, values, &ctx->Pack, 0x0);
+                                 format, type, values, &ctx->Pack, 0x0, GL_FALSE);
    }
 
    if (ctx->Pack.BufferObj->Name) {
index fa3149d56dad1522d47df0adaa72b30a5858a563..44972ae8e2cfab77a40174a7c4b0b986e5c95cd1 100644 (file)
@@ -1686,24 +1686,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
                            GLenum dstFormat, GLenum dstType,
                            GLvoid *dstAddr,
                            const struct gl_pixelstore_attrib *dstPacking,
-                           GLbitfield transferOps)
+                           GLbitfield transferOps, GLboolean noClamp)
 {
    GLfloat luminance[MAX_WIDTH];
    const GLint comps = _mesa_components_in_format(dstFormat);
    GLuint i;
-   /* clamping only applies to colors, not the dudv values, but still need
-      it if converting to unsigned values (which doesn't make much sense) */
-   if (dstFormat == GL_DUDV_ATI || dstFormat == GL_DU8DV8_ATI) {
-      switch (dstType) {
-         case GL_UNSIGNED_BYTE:
-         case GL_UNSIGNED_SHORT:
-         case GL_UNSIGNED_INT:
-            transferOps |= IMAGE_CLAMP_BIT;
-            break;
-            /* actually might want clamp to [-1,1] otherwise but shouldn't matter? */
-      }
-   }
-   else if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
+
+   if ((!noClamp) && (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE)) {
       /* need to clamp to [0, 1] */
       transferOps |= IMAGE_CLAMP_BIT;
    }
index b26c27e5a8ac7976781a076440e00b8ba66267cb..fb7a5c0e9031a29f651bba3c954869e8beba7f07 100644 (file)
@@ -178,7 +178,7 @@ extern void
 _mesa_pack_rgba_span_float( GLcontext *ctx, GLuint n, GLfloat rgba[][4],
                             GLenum dstFormat, GLenum dstType, GLvoid *dstAddr,
                             const struct gl_pixelstore_attrib *dstPacking,
-                            GLbitfield transferOps );
+                            GLbitfield transferOps, GLboolean noClamp );
 
 
 extern void
index bfd740870ec7dd0263856dd3396c8469a6c576c5..01d59dd42da9b0c49adbb4402858aec7894c2d4e 100644 (file)
@@ -54,12 +54,20 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
 #define FLOAT_TO_BYTE(X)    ( (((GLint) (255.0F * (X))) - 1) / 2 )
 
 
+/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0], texture/fb data */
+#define BYTE_TO_FLOAT_TEX(B)    ((B) == -128 ? -1.0 : (B) * (1.0F/127.0F))
+
+/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127], texture/fb data */
+#define FLOAT_TO_BYTE_TEX(X)    ( (GLint) (127.0F * (X)) )
+
+
 /** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */
 #define USHORT_TO_FLOAT(S)  ((GLfloat) (S) * (1.0F / 65535.0F))
 
 /** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */
 #define FLOAT_TO_USHORT(X)   ((GLuint) ((X) * 65535.0))
 
+
 /** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
 #define SHORT_TO_FLOAT(S)   ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
 
@@ -67,6 +75,13 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
 #define FLOAT_TO_SHORT(X)   ( (((GLint) (65535.0F * (X))) - 1) / 2 )
 
 
+/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0], texture/fb data */
+#define SHORT_TO_FLOAT_TEX(S)    ((S) == -32768 ? -1.0 : (S) * (1.0F/32767.0F))
+
+/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767], texture/fb data */
+#define FLOAT_TO_SHORT_TEX(X)    ( (GLint) (32767.0F * (X)) )
+
+
 /** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */
 #define UINT_TO_FLOAT(U)    ((GLfloat) (U) * (1.0F / 4294967295.0F))
 
@@ -85,6 +100,13 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
 #define FLOAT_TO_INT(X)     ( (GLint) (2147483647.0 * (X)) )
 
 
+/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0], texture/fb data */
+#define INT_TO_FLOAT_TEX(I)    ((I) == -2147483648 ? -1.0 : (I) * (1.0F/2147483647.0))
+
+/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647], texture/fb data */
+#define FLOAT_TO_INT_TEX(X)    ( (GLint) (2147483647.0F * (X)) )
+
+
 #define BYTE_TO_UBYTE(b)   ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b)))
 #define SHORT_TO_UBYTE(s)  ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7)))
 #define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8))
index 4a79430c34d39b82b2b25ac96326a9f565eb6c38..7001211a1313771a7b7e4378a0510461c6ab2f07 100644 (file)
@@ -86,6 +86,21 @@ bytes_per_pixel(GLenum datatype, GLuint comps)
                                 rowD[j][e], rowD[k][e]); \
    } while(0)
 
+#define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
+   (Aj + Ak \
+    + Bj + Bk \
+    + Cj + Ck \
+    + Dj + Dk \
+    + 4) / 8
+
+#define FILTER_3D_SIGNED(e) \
+   do { \
+      dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
+                                       rowB[j][e], rowB[k][e], \
+                                       rowC[j][e], rowC[k][e], \
+                                       rowD[j][e], rowD[k][e]); \
+   } while(0)
+
 #define FILTER_F_3D(e) \
    do { \
       dst[i][e] = (rowA[j][e] + rowA[k][e] \
@@ -180,6 +195,53 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
       }
    }
 
+   if (datatype == GL_BYTE && comps == 4) {
+      GLuint i, j, k;
+      const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA;
+      const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB;
+      GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow;
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+         dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+         dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+         dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
+      }
+   }
+   else if (datatype == GL_BYTE && comps == 3) {
+      GLuint i, j, k;
+      const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA;
+      const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB;
+      GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow;
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+         dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+         dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
+      }
+   }
+   else if (datatype == GL_BYTE && comps == 2) {
+      GLuint i, j, k;
+      const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
+      const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
+      GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
+         dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
+      }
+   }
+   else if (datatype == GL_BYTE && comps == 1) {
+      GLuint i, j, k;
+      const GLbyte *rowA = (const GLbyte *) srcRowA;
+      const GLbyte *rowB = (const GLbyte *) srcRowB;
+      GLbyte *dst = (GLbyte *) dstRow;
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
+      }
+   }
+
    else if (datatype == GL_UNSIGNED_SHORT && comps == 4) {
       GLuint i, j, k;
       const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA;
@@ -470,17 +532,6 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
          dst[i] = (blue << 5) | (green << 2) | red;
       }
    }
-   else if (datatype == GL_BYTE && comps == 2) {
-      GLuint i, j, k;
-      const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
-      const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
-      GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
-      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
-           i++, j += colStride, k += colStride) {
-         dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
-         dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
-      }
-   }
    else {
       _mesa_problem(NULL, "bad format in do_row()");
    }
@@ -555,6 +606,44 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
          FILTER_3D(0);
       }
    }
+   if ((datatype == GL_BYTE) && (comps == 4)) {
+      DECLARE_ROW_POINTERS(GLbyte, 4);
+
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         FILTER_3D_SIGNED(0);
+         FILTER_3D_SIGNED(1);
+         FILTER_3D_SIGNED(2);
+         FILTER_3D_SIGNED(3);
+      }
+   }
+   else if ((datatype == GL_BYTE) && (comps == 3)) {
+      DECLARE_ROW_POINTERS(GLbyte, 3);
+
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         FILTER_3D_SIGNED(0);
+         FILTER_3D_SIGNED(1);
+         FILTER_3D_SIGNED(2);
+      }
+   }
+   else if ((datatype == GL_BYTE) && (comps == 2)) {
+      DECLARE_ROW_POINTERS(GLbyte, 2);
+
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         FILTER_3D_SIGNED(0);
+         FILTER_3D_SIGNED(1);
+       }
+   }
+   else if ((datatype == GL_BYTE) && (comps == 1)) {
+      DECLARE_ROW_POINTERS(GLbyte, 1);
+
+      for (i = j = 0, k = k0; i < (GLuint) dstWidth;
+           i++, j += colStride, k += colStride) {
+         FILTER_3D_SIGNED(0);
+      }
+   }
    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
       DECLARE_ROW_POINTERS(GLushort, 4);
 
index 52930094545b57f305871ec96bbc06f9b3f92c6c..a5d3be3543d4faf00ee6ddce230529b71b7085a9 100644 (file)
@@ -2503,6 +2503,7 @@ struct gl_extensions
    GLboolean MESA_resize_buffers;
    GLboolean MESA_ycbcr_texture;
    GLboolean MESA_texture_array;
+   GLboolean MESA_texture_signed_rgba;
    GLboolean NV_blend_square;
    GLboolean NV_fragment_program;
    GLboolean NV_light_max_exponent;
index c372b49398a31dde7c88d079d8efb5b8a310ec05..0ceaaf3ececd802f9f74b27db4319d7ec500d2ec 100644 (file)
@@ -699,9 +699,7 @@ const struct gl_texture_format _mesa_texformat_intensity_float16 = {
 const struct gl_texture_format _mesa_texformat_dudv8 = {
    MESA_FORMAT_DUDV8,                  /* MesaFormat */
    GL_DUDV_ATI,                                /* BaseFormat */
-   /* FIXME: spec doesn't say since that parameter didn't exist then,
-      but this should be something like SIGNED_NORMALIZED */
-   GL_UNSIGNED_NORMALIZED_ARB,         /* DataType */
+   GL_SIGNED_NORMALIZED,               /* DataType */
    /* maybe should add dudvBits field, but spec seems to be
       lacking the ability to query with GetTexLevelParameter anyway */
    0,                                  /* RedBits */
@@ -724,6 +722,30 @@ const struct gl_texture_format _mesa_texformat_dudv8 = {
    NULL                                        /* StoreTexel */
 };
 
+const struct gl_texture_format _mesa_texformat_signed_rgba8888 = {
+   MESA_FORMAT_SIGNED_RGBA8888,                /* MesaFormat */
+   GL_RGBA,                            /* BaseFormat */
+   GL_SIGNED_NORMALIZED,               /* DataType */
+   8,                                  /* RedBits */
+   8,                                  /* GreenBits */
+   8,                                  /* BlueBits */
+   8,                                  /* AlphaBits */
+   0,                                  /* LuminanceBits */
+   0,                                  /* IntensityBits */
+   0,                                  /* IndexBits */
+   0,                                  /* DepthBits */
+   0,                                  /* StencilBits */
+   4,                                  /* TexelBytes */
+   _mesa_texstore_signed_rgba8888,     /* StoreTexImageFunc */
+   NULL,                               /* FetchTexel1D */
+   NULL,                               /* FetchTexel2D */
+   NULL,                               /* FetchTexel3D */
+   fetch_texel_1d_signed_rgba8888,     /* FetchTexel1Df */
+   fetch_texel_2d_signed_rgba8888,     /* FetchTexel2Df */
+   fetch_texel_3d_signed_rgba8888,     /* FetchTexel3Df */
+   store_texel_signed_rgba8888         /* StoreTexel */
+};
+
 /*@}*/
 
 
@@ -1671,6 +1693,17 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
       }
    }
 
+   if (ctx->Extensions.MESA_texture_signed_rgba) {
+      switch (internalFormat) {
+         case GL_RGBA_SNORM:
+         case GL_RGBA8_SNORM:
+            return &_mesa_texformat_signed_rgba8888;
+         default:
+            ; /* fallthrough */
+      }
+   }
+
+
 #if FEATURE_EXT_texture_sRGB
    if (ctx->Extensions.EXT_texture_sRGB) {
       switch (internalFormat) {
@@ -1820,6 +1853,11 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
       *comps = 2;
       return;
 
+   case MESA_FORMAT_SIGNED_RGBA8888:
+      *datatype = GL_BYTE;
+      *comps = 4;
+      return;
+
 #if FEATURE_EXT_texture_sRGB
    case MESA_FORMAT_SRGB8:
       *datatype = GL_UNSIGNED_BYTE;
index 7fa70ad4fee3f8680f03f8a2c225fd0d6e950634..3a08339adfd58b62c57b7a9641fc6b1ccf6529d0 100644 (file)
@@ -168,7 +168,8 @@ enum _format {
     * \name Signed fixed point texture formats.
     */
    /*@{*/
-   MESA_FORMAT_DUDV8
+   MESA_FORMAT_DUDV8,
+   MESA_FORMAT_SIGNED_RGBA8888
    /*@}*/
 };
 
@@ -219,6 +220,7 @@ extern const struct gl_texture_format _mesa_texformat_intensity_float16;
 /** Signed fixed point texture formats */
 /*@{*/
 extern const struct gl_texture_format _mesa_texformat_dudv8;
+extern const struct gl_texture_format _mesa_texformat_signed_rgba8888;
 /*@}*/
 
 /** \name Assorted hardware-friendly formats */
index 0f6a172ef00591a489b547cdeb10a2b1c3cc5e8a..604b1a744cb5ccfe6dbb98057199fb891f1f777d 100644 (file)
@@ -1321,6 +1321,28 @@ static void FETCH(dudv8)(const struct gl_texture_image *texImage,
    texel[ACOMP] = 0;
 }
 
+/* MESA_FORMAT_SIGNED_ARGB8888 ***********************************************/
+
+static void FETCH(signed_rgba8888)( const struct gl_texture_image *texImage,
+                                   GLint i, GLint j, GLint k, GLfloat *texel )
+{
+   const GLuint s = *TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+   texel[RCOMP] = BYTE_TO_FLOAT_TEX( (s >> 24)        );
+   texel[GCOMP] = BYTE_TO_FLOAT_TEX( (s >> 16) & 0xff );
+   texel[BCOMP] = BYTE_TO_FLOAT_TEX( (s >>  8) & 0xff );
+   texel[ACOMP] = BYTE_TO_FLOAT_TEX( (s      ) & 0xff );
+}
+
+#if DIM == 3
+static void store_texel_signed_rgba8888(struct gl_texture_image *texImage,
+                                        GLint i, GLint j, GLint k, const void *texel)
+{
+   const GLbyte *rgba = (const GLbyte *) texel;
+   GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
+   *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]);
+}
+#endif
+
 
 /* MESA_FORMAT_YCBCR *********************************************************/
 
index 4f297738df14757c2e12f03f64ac7bdcbc235c72..8c03c36c753398e8c465a9906efb2993b76430fe 100644 (file)
@@ -349,6 +349,15 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
       }
    }
 
+   if (ctx->Extensions.MESA_texture_signed_rgba) {
+      switch (internalFormat) {
+         case GL_RGBA_SNORM:
+         case GL_RGBA8_SNORM:
+            return GL_RGBA;
+         default:
+            ; /* fallthrough */
+      }
+   }
 
    if (ctx->Extensions.EXT_packed_depth_stencil) {
       switch (internalFormat) {
@@ -502,6 +511,10 @@ _mesa_is_color_format(GLenum format)
       case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
 #endif /* FEATURE_EXT_texture_sRGB */
          return GL_TRUE;
+      /* signed texture formats */
+      case GL_RGBA_SNORM:
+      case GL_RGBA8_SNORM:
+         return GL_TRUE;
       case GL_YCBCR_MESA:  /* not considered to be RGB */
          /* fall-through */
       default:
index cc3c6958c7df16da10e115406ebd58d6b0e8c324..785fb5062200dc37d993a258e3c32183b752c863 100644 (file)
@@ -417,7 +417,7 @@ make_temp_float_image(GLcontext *ctx, GLuint dims,
                                           (GLfloat (*)[4]) src,
                                           logicalBaseFormat, GL_FLOAT,
                                           dst, &ctx->DefaultPacking,
-                                          postConvTransferOps);
+                                          postConvTransferOps, GL_FALSE);
                src += convWidth * 4;
                dst += convWidth * logComponents;
             }
@@ -798,6 +798,7 @@ static const GLubyte *
 type_mapping( GLenum srcType )
 {
    switch (srcType) {
+   case GL_BYTE:
    case GL_UNSIGNED_BYTE:
       return map_identity;
    case GL_UNSIGNED_INT_8_8_8_8:
@@ -819,6 +820,7 @@ byteswap_mapping( GLboolean swapBytes,
       return map_identity;
 
    switch (srcType) {
+   case GL_BYTE:
    case GL_UNSIGNED_BYTE:
       return map_identity;
    case GL_UNSIGNED_INT_8_8_8_8:
@@ -2561,6 +2563,99 @@ _mesa_texstore_dudv8(TEXSTORE_PARAMS)
    return GL_TRUE;
 }
 
+/**
+ * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV.
+ */
+GLboolean
+_mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS)
+{
+   const GLboolean littleEndian = _mesa_little_endian();
+
+   ASSERT(dstFormat == &_mesa_texformat_signed_rgba8888);
+   ASSERT(dstFormat->TexelBytes == 4);
+
+   if (!ctx->_ImageTransferState &&
+       !srcPacking->SwapBytes &&
+       dstFormat == &_mesa_texformat_signed_rgba8888 &&
+       baseInternalFormat == GL_RGBA &&
+      ((srcFormat == GL_RGBA && srcType == GL_BYTE && !littleEndian) ||
+       (srcFormat == GL_ABGR_EXT && srcType == GL_BYTE && littleEndian))) {
+       /* simple memcpy path */
+      memcpy_texture(ctx, dims,
+                     dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                     dstRowStride,
+                     dstImageOffsets,
+                     srcWidth, srcHeight, srcDepth, srcFormat, srcType,
+                     srcAddr, srcPacking);
+   }
+   else if (!ctx->_ImageTransferState &&
+           (srcType == GL_BYTE) &&
+           can_swizzle(baseInternalFormat) &&
+           can_swizzle(srcFormat)) {
+
+      GLubyte dstmap[4];
+
+      /* dstmap - how to swizzle from RGBA to dst format:
+       */
+      if (littleEndian && dstFormat == &_mesa_texformat_signed_rgba8888) {
+        dstmap[3] = 0;
+        dstmap[2] = 1;
+        dstmap[1] = 2;
+        dstmap[0] = 3;
+      }
+      else {
+        dstmap[3] = 3;
+        dstmap[2] = 2;
+        dstmap[1] = 1;
+        dstmap[0] = 0;
+      }
+      
+      _mesa_swizzle_ubyte_image(ctx, dims,
+                               srcFormat,
+                               srcType,
+                               baseInternalFormat,
+                               dstmap, 4,
+                               dstAddr, dstXoffset, dstYoffset, dstZoffset,
+                               dstRowStride, dstImageOffsets,
+                               srcWidth, srcHeight, srcDepth, srcAddr,
+                               srcPacking);      
+   }
+   else {
+      /* general path */
+      const GLfloat *tempImage = make_temp_float_image(ctx, dims,
+                                                 baseInternalFormat,
+                                                 dstFormat->BaseFormat,
+                                                 srcWidth, srcHeight, srcDepth,
+                                                 srcFormat, srcType, srcAddr,
+                                                 srcPacking);
+      const GLfloat *srcRow = tempImage;
+      GLint img, row, col;
+      if (!tempImage)
+         return GL_FALSE;
+      _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
+      for (img = 0; img < srcDepth; img++) {
+         GLubyte *dstRow = (GLubyte *) dstAddr
+            + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+            + dstYoffset * dstRowStride
+            + dstXoffset * dstFormat->TexelBytes;
+         for (row = 0; row < srcHeight; row++) {
+            GLuint *dstUI = (GLuint *) dstRow;
+            if (dstFormat == &_mesa_texformat_signed_rgba8888) {
+               for (col = 0; col < srcWidth; col++) {
+                  dstUI[col] = PACK_COLOR_8888( FLOAT_TO_BYTE_TEX(srcRow[RCOMP]),
+                                                FLOAT_TO_BYTE_TEX(srcRow[GCOMP]),
+                                                FLOAT_TO_BYTE_TEX(srcRow[BCOMP]),
+                                                FLOAT_TO_BYTE_TEX(srcRow[ACOMP]) );
+                  srcRow += 4;
+               }
+            }
+            dstRow += dstRowStride;
+         }
+      }
+      _mesa_free((void *) tempImage);
+   }
+   return GL_TRUE;
+}
 
 /**
  * Store a combined depth/stencil texture image.
@@ -3820,6 +3915,21 @@ linear_to_nonlinear(GLfloat cl)
 
 #endif /* FEATURE_EXT_texture_sRGB */
 
+static INLINE GLboolean
+type_with_negative_values(GLenum type)
+{
+    switch (type) {
+    case GL_BYTE:
+    case GL_SHORT:
+    case GL_INT:
+    case GL_FLOAT:
+    case GL_HALF_FLOAT_ARB:
+       return GL_TRUE;
+   default:
+      return GL_FALSE;
+    }
+}
+
 /**
  * This is the software fallback for Driver.GetTexImage().
  * All error checking will have been done before this routine is called.
@@ -3962,7 +4072,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
                }
                _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                           format, type, dest,
-                                          &ctx->Pack, transferOps /*image xfer ops*/);
+                                          &ctx->Pack, transferOps, GL_TRUE);
             }
 #endif /* FEATURE_EXT_texture_sRGB */
             else {
@@ -3971,10 +4081,13 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
                GLint col;
                GLbitfield transferOps = 0x0;
 
-               if (type == GL_FLOAT && texImage->TexFormat->BaseFormat != GL_DUDV_ATI &&
-                   ((ctx->Color.ClampReadColor == GL_TRUE) ||
-                    (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
-                     texImage->TexFormat->DataType != GL_FLOAT)))
+               /* clamp does not apply to GetTexImage (final conversion)?
+                  Looks like we need clamp though when going from format containing
+                  negative values to unsigned format */
+
+               if (!type_with_negative_values(type) &&
+                   (texImage->TexFormat->DataType == GL_FLOAT ||
+                   texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED))
                   transferOps |= IMAGE_CLAMP_BIT;
 
                for (col = 0; col < width; col++) {
@@ -4001,7 +4114,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
                }
                _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
                                           format, type, dest,
-                                          &ctx->Pack, transferOps /*image xfer ops*/);
+                                          &ctx->Pack, transferOps, GL_TRUE);
             } /* format */
          } /* row */
       } /* img */
index c9e639be4e066ae8c91b104f04c9a1c87474d258..91cb64f377a336c850a1f78c6959a59dfb9c4832 100644 (file)
@@ -79,6 +79,7 @@ extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS);
 extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS);
 #endif
 extern GLboolean _mesa_texstore_dudv8(TEXSTORE_PARAMS);
+extern GLboolean _mesa_texstore_signed_rgba8888(TEXSTORE_PARAMS);
 
 extern GLchan *
 _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
index ce7a8cda4e86e7167b4149c89c190c740f90011d..c11973cdb3d33ae3223e3ac5ba633f8cfad7fa74 100644 (file)
@@ -486,7 +486,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
             df += dfStride;
             if (!dfStride) {
                _mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
-                                          &clippedPacking, transferOps);
+                                          &clippedPacking, transferOps, GL_FALSE);
                dst += dstStride;
             }
          }
index e901fc6b5dcdd2d66fc648f3beda019627ad6d98..524ac4ee2193ce480a576a4036c82b4066368604 100644 (file)
@@ -396,7 +396,7 @@ read_rgba_pixels( GLcontext *ctx,
                                       format, type, row, 0);
          _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) src,
                                     format, type, dest, packing,
-                                    transferOps & IMAGE_POST_CONVOLUTION_BITS);
+                                    transferOps & IMAGE_POST_CONVOLUTION_BITS, GL_FALSE);
          src += width * 4;
       }
       _mesa_free(convImage);
@@ -441,7 +441,7 @@ read_rgba_pixels( GLcontext *ctx,
 
          /* pack the row of RGBA pixels into user's buffer */
          _mesa_pack_rgba_span_float(ctx, width, rgba, format, type, dst,
-                                    packing, transferOps);
+                                    packing, transferOps, GL_FALSE);
 
          dst += dstStride;
       }