From c6a6cc191813e8343a17b028146a34f193a6ce44 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Fri, 27 Mar 2009 19:39:52 +0100 Subject: 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. --- docs/MESA_texture_signed_rgba.spec | 214 ++++++++++++++++++++++++++++++ docs/extensions.html | 1 + src/mesa/glapi/gl_API.xml | 6 + src/mesa/main/colortab.c | 2 +- src/mesa/main/convolve.c | 6 +- src/mesa/main/extensions.c | 1 + src/mesa/main/histogram.c | 2 +- src/mesa/main/image.c | 17 +-- src/mesa/main/image.h | 2 +- src/mesa/main/macros.h | 22 +++ src/mesa/main/mipmap.c | 111 ++++++++++++++-- src/mesa/main/mtypes.h | 1 + src/mesa/main/texformat.c | 44 +++++- src/mesa/main/texformat.h | 4 +- src/mesa/main/texformat_tmp.h | 22 +++ src/mesa/main/teximage.c | 13 ++ src/mesa/main/texstore.c | 127 +++++++++++++++++- src/mesa/main/texstore.h | 1 + src/mesa/state_tracker/st_cb_readpixels.c | 2 +- src/mesa/swrast/s_readpix.c | 4 +- 20 files changed, 557 insertions(+), 45 deletions(-) create mode 100644 docs/MESA_texture_signed_rgba.spec diff --git a/docs/MESA_texture_signed_rgba.spec b/docs/MESA_texture_signed_rgba.spec new file mode 100644 index 0000000000..49c8e9e5dd --- /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 parameter of + TexImage1D, TexImage2D, TexImage3D, CopyTexImage1D, and CopyTexImage2D: + + RGBA_SNORM 0x8F93 + RGBA8_SNORM 0x8F97 + + Returned by the 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 + 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 dbb8ebadaf..91ed20e5ce 100644 --- a/docs/extensions.html +++ b/docs/extensions.html @@ -24,6 +24,7 @@ The specifications follow.
  • MESA_resize_buffers.spec
  • MESA_set_3dfx_mode.spec
  • MESA_sprite_point.spec (obsolete) +
  • MESA_texture_signed_rgba.spec
  • MESA_trace.spec (obsolete)
  • MESA_window_pos.spec
  • MESA_ycbcr_texture.spec diff --git a/src/mesa/glapi/gl_API.xml b/src/mesa/glapi/gl_API.xml index cc3e3ae6bf..ef774f2e60 100644 --- a/src/mesa/glapi/gl_API.xml +++ b/src/mesa/glapi/gl_API.xml @@ -12326,6 +12326,12 @@ + + + + + + diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c index bd9cf438b4..b05c0513aa 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 814c6a0a5a..63b652bf70 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 2d2bf51784..147d923e64 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 905c1ad830..febf8d99c4 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 fa3149d56d..44972ae8e2 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 b26c27e5a8..fb7a5c0e90 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 bfd740870e..01d59dd42d 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 4a79430c34..7001211a13 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 5293009454..a5d3be3543 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 c372b49398..0ceaaf3ece 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 7fa70ad4fe..3a08339adf 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 0f6a172ef0..604b1a744c 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 4f297738df..8c03c36c75 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 cc3c6958c7..785fb50622 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 c9e639be4e..91cb64f377 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 ce7a8cda4e..c11973cdb3 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 e901fc6b5d..524ac4ee21 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; } -- cgit v1.2.3