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.
This commit is contained in:
Roland Scheidegger
2009-03-27 19:39:52 +01:00
parent a9bf5b5cca
commit c6a6cc1918
20 changed files with 557 additions and 45 deletions

View File

@@ -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.

View 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>

View File

@@ -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"/>

View 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,

View 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 */

View 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) },

View 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) {

View 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;
}

View 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

View 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))

View 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);

View 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;

View 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;

View 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 */

View 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 *********************************************************/

View 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:

View 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 */

View 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,

View 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;
}
}

View 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;
}