summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Scheidegger <[email protected]>2009-03-27 19:39:52 +0100
committerRoland Scheidegger <[email protected]>2009-03-28 02:02:42 +0100
commitc6a6cc191813e8343a17b028146a34f193a6ce44 (patch)
treecb1ecd35ac15c9b2c0cf3740dbdc631c7622233a
parenta9bf5b5ccac2a75f1a2470d4910361e65b2d8eab (diff)
mesa: add new signed rgba texture format
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.
-rw-r--r--docs/MESA_texture_signed_rgba.spec214
-rw-r--r--docs/extensions.html1
-rw-r--r--src/mesa/glapi/gl_API.xml6
-rw-r--r--src/mesa/main/colortab.c2
-rw-r--r--src/mesa/main/convolve.c6
-rw-r--r--src/mesa/main/extensions.c1
-rw-r--r--src/mesa/main/histogram.c2
-rw-r--r--src/mesa/main/image.c17
-rw-r--r--src/mesa/main/image.h2
-rw-r--r--src/mesa/main/macros.h22
-rw-r--r--src/mesa/main/mipmap.c111
-rw-r--r--src/mesa/main/mtypes.h1
-rw-r--r--src/mesa/main/texformat.c44
-rw-r--r--src/mesa/main/texformat.h4
-rw-r--r--src/mesa/main/texformat_tmp.h22
-rw-r--r--src/mesa/main/teximage.c13
-rw-r--r--src/mesa/main/texstore.c127
-rw-r--r--src/mesa/main/texstore.h1
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c2
-rw-r--r--src/mesa/swrast/s_readpix.c4
20 files changed, 557 insertions, 45 deletions
diff --git a/docs/MESA_texture_signed_rgba.spec b/docs/MESA_texture_signed_rgba.spec
new file mode 100644
index 00000000000..49c8e9e5dd4
--- /dev/null
+++ b/docs/MESA_texture_signed_rgba.spec
@@ -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.
diff --git a/docs/extensions.html b/docs/extensions.html
index dbb8ebadaf2..91ed20e5ceb 100644
--- a/docs/extensions.html
+++ b/docs/extensions.html
@@ -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>
diff --git a/src/mesa/glapi/gl_API.xml b/src/mesa/glapi/gl_API.xml
index cc3e3ae6bff..ef774f2e608 100644
--- a/src/mesa/glapi/gl_API.xml
+++ b/src/mesa/glapi/gl_API.xml
@@ -12326,6 +12326,12 @@
</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"/>
diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c
index bd9cf438b4f..b05c0513aa6 100644
--- a/src/mesa/main/colortab.c
+++ b/src/mesa/main/colortab.c
@@ -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,
diff --git a/src/mesa/main/convolve.c b/src/mesa/main/convolve.c
index 814c6a0a5a6..63b652bf705 100644
--- a/src/mesa/main/convolve.c
+++ b/src/mesa/main/convolve.c
@@ -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 */
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 2d2bf517843..147d923e64f 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -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) },
diff --git a/src/mesa/main/histogram.c b/src/mesa/main/histogram.c
index 905c1ad8301..febf8d99c45 100644
--- a/src/mesa/main/histogram.c
+++ b/src/mesa/main/histogram.c
@@ -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) {
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index fa3149d56da..44972ae8e2c 100644
--- a/src/mesa/main/image.c
+++ b/src/mesa/main/image.c
@@ -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;
}
diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h
index b26c27e5a8a..fb7a5c0e903 100644
--- a/src/mesa/main/image.h
+++ b/src/mesa/main/image.h
@@ -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
diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
index bfd740870ec..01d59dd42da 100644
--- a/src/mesa/main/macros.h
+++ b/src/mesa/main/macros.h
@@ -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))
diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index 4a79430c34d..7001211a131 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -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);
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 52930094545..a5d3be3543d 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -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;
diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c
index c372b49398a..0ceaaf3ecec 100644
--- a/src/mesa/main/texformat.c
+++ b/src/mesa/main/texformat.c
@@ -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;
diff --git a/src/mesa/main/texformat.h b/src/mesa/main/texformat.h
index 7fa70ad4fee..3a08339adfd 100644
--- a/src/mesa/main/texformat.h
+++ b/src/mesa/main/texformat.h
@@ -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 */
diff --git a/src/mesa/main/texformat_tmp.h b/src/mesa/main/texformat_tmp.h
index 0f6a172ef00..604b1a744cb 100644
--- a/src/mesa/main/texformat_tmp.h
+++ b/src/mesa/main/texformat_tmp.h
@@ -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 *********************************************************/
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 4f297738df1..8c03c36c753 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -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:
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
index cc3c6958c7d..785fb506220 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -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 */
diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h
index c9e639be4e0..91cb64f377a 100644
--- a/src/mesa/main/texstore.h
+++ b/src/mesa/main/texstore.h
@@ -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,
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index ce7a8cda4e8..c11973cdb3d 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -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;
}
}
diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c
index e901fc6b5dc..524ac4ee219 100644
--- a/src/mesa/swrast/s_readpix.c
+++ b/src/mesa/swrast/s_readpix.c
@@ -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;
}