From 9d7698c468f4ea7da8bb4ec00520c98f11cca0fa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 26 Apr 2011 02:18:24 +0200 Subject: [PATCH] mesa: implement EXT_texture_shared_exponent swrast support done. There is no renderbuffer support in swrast, because it's not required by the extension. Reviewed-by: Brian Paul --- src/mesa/main/extensions.c | 1 + src/mesa/main/fbobject.c | 11 +++ src/mesa/main/formats.c | 16 +++- src/mesa/main/formats.h | 2 + src/mesa/main/image.c | 11 +++ src/mesa/main/mipmap.c | 49 ++++++++++ src/mesa/main/pack.c | 82 ++++++++++++++++- src/mesa/main/rgb9e5.h | 173 +++++++++++++++++++++++++++++++++++ src/mesa/main/texfetch.c | 8 ++ src/mesa/main/texfetch_tmp.h | 21 +++++ src/mesa/main/texformat.c | 10 ++ src/mesa/main/texparam.c | 8 +- src/mesa/main/texstore.c | 57 ++++++++++++ 13 files changed, 438 insertions(+), 11 deletions(-) create mode 100644 src/mesa/main/rgb9e5.h diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 82474cf4124..e0562cc1f45 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -502,6 +502,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE; ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; + ctx->Extensions.EXT_texture_shared_exponent = GL_TRUE; #if FEATURE_EXT_texture_sRGB ctx->Extensions.EXT_texture_sRGB = GL_TRUE; ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE; diff --git a/src/mesa/main/fbobject.c b/src/mesa/main/fbobject.c index 1edb310ea13..b07161e5835 100644 --- a/src/mesa/main/fbobject.c +++ b/src/mesa/main/fbobject.c @@ -418,6 +418,15 @@ _mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) case GL_RG: fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; return; + case GL_RGB: + switch (rb->Format) { + case MESA_FORMAT_RGB9_E5_FLOAT: + fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; + return; + default:; + } + break; + default: /* render buffer format is supported by software rendering */ ; @@ -1175,6 +1184,8 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_INTENSITY32F_ARB: return ctx->Extensions.ARB_texture_float && ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; + case GL_RGB9_E5: + return ctx->Extensions.EXT_texture_shared_exponent ? GL_RGB : 0; /* XXX add integer formats eventually */ default: return 0; diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index 4c31ccb763c..6105ba1929c 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -1072,7 +1072,16 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 0, 0, 0, 0, 0, 16, 0, 0, 0, 1, 1, 2 - } + }, + { + MESA_FORMAT_RGB9_E5_FLOAT, + "MESA_FORMAT_RGB9_E5", + GL_RGB, + GL_FLOAT, + 9, 9, 9, 0, + 0, 0, 0, 0, 0, + 1, 1, 4 + }, }; @@ -1803,6 +1812,11 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 4; return; + case MESA_FORMAT_RGB9_E5_FLOAT: + *datatype = GL_UNSIGNED_INT_5_9_9_9_REV; + *comps = 3; + return; + case MESA_FORMAT_COUNT: assert(0); return; diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h index 15ac62cfef9..68d6e98b174 100644 --- a/src/mesa/main/formats.h +++ b/src/mesa/main/formats.h @@ -206,6 +206,8 @@ typedef enum MESA_FORMAT_SIGNED_AL1616, /* AAAA AAAA AAAA AAAA LLLL LLLL LLLL LLLL */ MESA_FORMAT_SIGNED_I16, /* IIII IIII IIII IIII */ + MESA_FORMAT_RGB9_E5_FLOAT, + MESA_FORMAT_COUNT } gl_format; diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 28841c25102..3e9f99698da 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -82,6 +82,7 @@ _mesa_type_is_packed(GLenum type) case GL_UNSIGNED_SHORT_8_8_MESA: case GL_UNSIGNED_SHORT_8_8_REV_MESA: case GL_UNSIGNED_INT_24_8_EXT: + case GL_UNSIGNED_INT_5_9_9_9_REV: return GL_TRUE; } @@ -222,6 +223,8 @@ _mesa_sizeof_packed_type( GLenum type ) return sizeof(GLushort); case GL_UNSIGNED_INT_24_8_EXT: return sizeof(GLuint); + case GL_UNSIGNED_INT_5_9_9_9_REV: + return sizeof(GLuint); default: return -1; } @@ -363,6 +366,11 @@ _mesa_bytes_per_pixel( GLenum format, GLenum type ) return sizeof(GLuint); else return -1; + case GL_UNSIGNED_INT_5_9_9_9_REV: + if (format == GL_RGB) + return sizeof(GLuint); + else + return -1; default: return -1; } @@ -458,6 +466,8 @@ _mesa_is_legal_format_and_type(const struct gl_context *ctx, return GL_TRUE; case GL_HALF_FLOAT_ARB: return ctx->Extensions.ARB_half_float_pixel; + case GL_UNSIGNED_INT_5_9_9_9_REV: + return ctx->Extensions.EXT_texture_shared_exponent; default: return GL_FALSE; } @@ -821,6 +831,7 @@ _mesa_is_color_format(GLenum format) case GL_INTENSITY_SNORM: case GL_INTENSITY8_SNORM: case GL_INTENSITY16_SNORM: + case GL_RGB9_E5: return GL_TRUE; case GL_YCBCR_MESA: /* not considered to be RGB */ /* fall-through */ diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c index 0578631efb9..88cb5b53bf7 100644 --- a/src/mesa/main/mipmap.c +++ b/src/mesa/main/mipmap.c @@ -34,6 +34,8 @@ #include "teximage.h" #include "texstore.h" #include "image.h" +#include "macros.h" +#include "rgb9e5.h" @@ -665,6 +667,25 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, } } + else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { + GLuint i, j, k; + const GLuint *rowA = (const GLuint*) srcRowA; + const GLuint *rowB = (const GLuint*) srcRowB; + GLuint *dst = (GLuint*)dstRow; + GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3]; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + rgb9e5_to_float3(rowA[j], rowAj); + rgb9e5_to_float3(rowB[j], rowBj); + rgb9e5_to_float3(rowA[k], rowAk); + rgb9e5_to_float3(rowB[k], rowBk); + res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F; + res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F; + res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F; + dst[i] = float3_to_rgb9e5(res); + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } @@ -1245,6 +1266,34 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, dst[i] = (a << 30) | (b << 20) | (g << 10) | r; } } + + else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) { + DECLARE_ROW_POINTERS0(GLuint); + + GLfloat res[3]; + GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3]; + GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3]; + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + rgb9e5_to_float3(rowA[j], rowAj); + rgb9e5_to_float3(rowB[j], rowBj); + rgb9e5_to_float3(rowC[j], rowCj); + rgb9e5_to_float3(rowD[j], rowDj); + rgb9e5_to_float3(rowA[k], rowAk); + rgb9e5_to_float3(rowB[k], rowBk); + rgb9e5_to_float3(rowC[k], rowCk); + rgb9e5_to_float3(rowD[k], rowDk); + res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] + + rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F; + res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] + + rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F; + res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] + + rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F; + dst[i] = float3_to_rgb9e5(res); + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c index ad8ab9d0056..37608f26364 100644 --- a/src/mesa/main/pack.c +++ b/src/mesa/main/pack.c @@ -37,6 +37,8 @@ #include "mtypes.h" #include "pack.h" #include "pixeltransfer.h" +#include "imports.h" +#include "rgb9e5.h" /** @@ -1892,6 +1894,14 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4], } } break; + case GL_UNSIGNED_INT_5_9_9_9_REV: + { + GLuint *dst = (GLuint *) dstAddr; + for (i = 0; i < n; i++) { + dst[i] = float3_to_rgb9e5(rgba[i]); + } + } + break; default: _mesa_problem(ctx, "bad type in _mesa_pack_rgba_span_float"); return; @@ -2330,7 +2340,8 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], srcType == GL_UNSIGNED_INT_8_8_8_8 || srcType == GL_UNSIGNED_INT_8_8_8_8_REV || srcType == GL_UNSIGNED_INT_10_10_10_2 || - srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + srcType == GL_UNSIGNED_INT_2_10_10_10_REV || + srcType == GL_UNSIGNED_INT_5_9_9_9_REV); get_component_mapping(srcFormat, &rSrc, &gSrc, &bSrc, &aSrc, @@ -2800,6 +2811,34 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4], } } break; + case GL_UNSIGNED_INT_5_9_9_9_REV: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + GLfloat f[3]; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + SWAP4BYTE(p); + rgb9e5_to_float3(p, f); + rgba[i][rDst] = f[0]; + rgba[i][gDst] = f[1]; + rgba[i][bDst] = f[2]; + rgba[i][aDst] = 1.0F; + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + GLfloat f[3]; + for (i = 0; i < n; i ++) { + rgb9e5_to_float3(uisrc[i], f); + rgba[i][rDst] = f[0]; + rgba[i][gDst] = f[1]; + rgba[i][bDst] = f[2]; + rgba[i][aDst] = 1.0F; + } + } + break; default: _mesa_problem(NULL, "bad srcType in extract float data"); break; @@ -2902,7 +2941,8 @@ extract_uint_rgba(GLuint n, GLuint rgba[][4], srcType == GL_UNSIGNED_INT_8_8_8_8 || srcType == GL_UNSIGNED_INT_8_8_8_8_REV || srcType == GL_UNSIGNED_INT_10_10_10_2 || - srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + srcType == GL_UNSIGNED_INT_2_10_10_10_REV || + srcType == GL_UNSIGNED_INT_5_9_9_9_REV); get_component_mapping(srcFormat, &rSrc, &gSrc, &bSrc, &aSrc, @@ -3266,6 +3306,35 @@ extract_uint_rgba(GLuint n, GLuint rgba[][4], } } break; + case GL_UNSIGNED_INT_5_9_9_9_REV: + if (swapBytes) { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + float f[3]; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + SWAP4BYTE(p); + rgb9e5_to_float3(p, f); + rgba[i][rDst] = clamp_float_to_uint(f[0]); + rgba[i][gDst] = clamp_float_to_uint(f[1]); + rgba[i][bDst] = clamp_float_to_uint(f[2]); + rgba[i][aDst] = 1; + } + } + else { + const GLuint *uisrc = (const GLuint *) src; + GLuint i; + float f[3]; + for (i = 0; i < n; i ++) { + GLuint p = uisrc[i]; + rgb9e5_to_float3(p, f); + rgba[i][rDst] = clamp_float_to_uint(f[0]); + rgba[i][gDst] = clamp_float_to_uint(f[1]); + rgba[i][bDst] = clamp_float_to_uint(f[2]); + rgba[i][aDst] = 1; + } + } + break; default: _mesa_problem(NULL, "bad srcType in extract uint data"); break; @@ -3345,7 +3414,8 @@ _mesa_unpack_color_span_chan( struct gl_context *ctx, srcType == GL_UNSIGNED_INT_8_8_8_8 || srcType == GL_UNSIGNED_INT_8_8_8_8_REV || srcType == GL_UNSIGNED_INT_10_10_10_2 || - srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + srcType == GL_UNSIGNED_INT_2_10_10_10_REV || + srcType == GL_UNSIGNED_INT_5_9_9_9_REV); /* Try simple cases first */ if (transferOps == 0) { @@ -3667,7 +3737,8 @@ _mesa_unpack_color_span_float( struct gl_context *ctx, srcType == GL_UNSIGNED_INT_8_8_8_8 || srcType == GL_UNSIGNED_INT_8_8_8_8_REV || srcType == GL_UNSIGNED_INT_10_10_10_2 || - srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + srcType == GL_UNSIGNED_INT_2_10_10_10_REV || + srcType == GL_UNSIGNED_INT_5_9_9_9_REV); /* general solution, no special cases, yet */ { @@ -3873,7 +3944,8 @@ _mesa_unpack_color_span_uint(struct gl_context *ctx, srcType == GL_UNSIGNED_INT_8_8_8_8 || srcType == GL_UNSIGNED_INT_8_8_8_8_REV || srcType == GL_UNSIGNED_INT_10_10_10_2 || - srcType == GL_UNSIGNED_INT_2_10_10_10_REV); + srcType == GL_UNSIGNED_INT_2_10_10_10_REV || + srcType == GL_UNSIGNED_INT_5_9_9_9_REV); /* Extract image data as uint[4] pixels */ diff --git a/src/mesa/main/rgb9e5.h b/src/mesa/main/rgb9e5.h new file mode 100644 index 00000000000..9bb431ffe9c --- /dev/null +++ b/src/mesa/main/rgb9e5.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2011 Marek Olšák + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* Copied from EXT_texture_shared_exponent and edited. */ + +#ifndef RGB9E5_H +#define RGB9E5_H + +#include +#include + +#define RGB9E5_EXPONENT_BITS 5 +#define RGB9E5_MANTISSA_BITS 9 +#define RGB9E5_EXP_BIAS 15 +#define RGB9E5_MAX_VALID_BIASED_EXP 31 + +#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS) +#define RGB9E5_MANTISSA_VALUES (1< 0.0) { + if (x >= MAX_RGB9E5) { + return MAX_RGB9E5; + } else { + return x; + } + } else { + /* NaN gets here too since comparisons with NaN always fail! */ + return 0.0; + } +} + +static INLINE float rgb9e5_MaxOf3(float x, float y, float z) +{ + if (x > y) { + return MAX2(x, z); + } else { + return MAX2(y, z); + } +} + +/* Ok, FloorLog2 is not correct for the denorm and zero values, but we + are going to do a max of this value with the minimum rgb9e5 exponent + that will hide these problem cases. */ +static INLINE int rgb9e5_FloorLog2(float x) +{ + float754 f; + + f.value = x; + return (f.field.biasedexponent - 127); +} + +static INLINE unsigned float3_to_rgb9e5(const float rgb[3]) +{ + rgb9e5 retval; + float maxrgb; + int rm, gm, bm; + float rc, gc, bc; + int exp_shared, maxm; + double denom; + + rc = rgb9e5_ClampRange(rgb[0]); + gc = rgb9e5_ClampRange(rgb[1]); + bc = rgb9e5_ClampRange(rgb[2]); + + maxrgb = rgb9e5_MaxOf3(rc, gc, bc); + exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS; + assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); + assert(exp_shared >= 0); + /* This pow function could be replaced by a table. */ + denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS); + + maxm = (int) floor(maxrgb / denom + 0.5); + if (maxm == MAX_RGB9E5_MANTISSA+1) { + denom *= 2; + exp_shared += 1; + assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP); + } else { + assert(maxm <= MAX_RGB9E5_MANTISSA); + } + + rm = (int) floor(rc / denom + 0.5); + gm = (int) floor(gc / denom + 0.5); + bm = (int) floor(bc / denom + 0.5); + + assert(rm <= MAX_RGB9E5_MANTISSA); + assert(gm <= MAX_RGB9E5_MANTISSA); + assert(bm <= MAX_RGB9E5_MANTISSA); + assert(rm >= 0); + assert(gm >= 0); + assert(bm >= 0); + + retval.field.r = rm; + retval.field.g = gm; + retval.field.b = bm; + retval.field.biasedexponent = exp_shared; + + return retval.raw; +} + +static INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3]) +{ + rgb9e5 v; + int exponent; + float scale; + + v.raw = rgb; + exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS; + scale = (float) pow(2, exponent); + + retval[0] = v.field.r * scale; + retval[1] = v.field.g * scale; + retval[2] = v.field.b * scale; +} + +#endif diff --git a/src/mesa/main/texfetch.c b/src/mesa/main/texfetch.c index d091789ff16..4acc938d093 100644 --- a/src/mesa/main/texfetch.c +++ b/src/mesa/main/texfetch.c @@ -41,6 +41,7 @@ #include "texcompress_rgtc.h" #include "texfetch.h" #include "teximage.h" +#include "rgb9e5.h" /** @@ -898,6 +899,13 @@ texfetch_funcs[MESA_FORMAT_COUNT] = fetch_texel_3d_signed_i16, store_texel_signed_i16 }, + { + MESA_FORMAT_RGB9_E5_FLOAT, + fetch_texel_1d_rgb9_e5, + fetch_texel_2d_rgb9_e5, + fetch_texel_3d_rgb9_e5, + store_texel_rgb9_e5 + }, }; diff --git a/src/mesa/main/texfetch_tmp.h b/src/mesa/main/texfetch_tmp.h index 0b9d5da07e8..106b812130b 100644 --- a/src/mesa/main/texfetch_tmp.h +++ b/src/mesa/main/texfetch_tmp.h @@ -2332,6 +2332,27 @@ static void store_texel_s8_z24(struct gl_texture_image *texImage, #endif +/* MESA_FORMAT_RGB9_E5 ******************************************************/ + +static void FETCH(rgb9_e5)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + rgb9e5_to_float3(*src, texel); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb9_e5(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = float3_to_rgb9e5(src); +} +#endif + + #undef TEXEL_ADDR #undef DIM #undef FETCH diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c index cbebec9aa57..3520f24382f 100644 --- a/src/mesa/main/texformat.c +++ b/src/mesa/main/texformat.c @@ -382,6 +382,16 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } + if (ctx->Extensions.EXT_texture_shared_exponent) { + switch (internalFormat) { + case GL_RGB9_E5: + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB9_E5_FLOAT); + break; + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.EXT_packed_depth_stencil) { switch (internalFormat) { case GL_DEPTH_STENCIL_EXT: diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 3d56dac3f91..f86a8cff7a1 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -979,11 +979,9 @@ _mesa_GetTexLevelParameteriv( GLenum target, GLint level, } break; case GL_TEXTURE_SHARED_SIZE: - if (ctx->VersionMajor >= 3) { - /* XXX return number of exponent bits for shared exponent texture - * formats, like GL_RGB9_E5. - */ - *params = 0; + if (ctx->VersionMajor >= 3 || + ctx->Extensions.EXT_texture_shared_exponent) { + *params = texFormat == MESA_FORMAT_RGB9_E5_FLOAT ? 5 : 0; } else { goto invalid_pname; diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index c4fe82a0b94..5cdde4524b2 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -70,6 +70,7 @@ #include "teximage.h" #include "texstore.h" #include "enums.h" +#include "rgb9e5.h" enum { @@ -4176,6 +4177,60 @@ _mesa_texstore_sla8(TEXSTORE_PARAMS) #endif /* FEATURE_EXT_texture_sRGB */ +static GLboolean +_mesa_texstore_rgb9_e5(TEXSTORE_PARAMS) +{ + const GLenum baseFormat = _mesa_get_format_base_format(dstFormat); + + ASSERT(dstFormat == MESA_FORMAT_RGB9_E5_FLOAT); + ASSERT(baseInternalFormat == GL_RGB); + + if (!ctx->_ImageTransferState && + !srcPacking->SwapBytes && + srcFormat == GL_RGB && + srcType == GL_UNSIGNED_INT_5_9_9_9_REV) { + /* simple memcpy path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, + dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else { + /* general path */ + const GLfloat *tempImage = _mesa_make_temp_float_image(ctx, dims, + baseInternalFormat, + baseFormat, + srcWidth, srcHeight, srcDepth, + srcFormat, srcType, srcAddr, + srcPacking, + ctx->_ImageTransferState); + const GLfloat *srcRow = tempImage; + GLint bytesPerRow; + GLint img, row, col; + if (!tempImage) + return GL_FALSE; + bytesPerRow = srcWidth * 3 * sizeof(GLfloat); + for (img = 0; img < srcDepth; img++) { + GLubyte *dstRow = (GLubyte *) dstAddr + + dstImageOffsets[dstZoffset + img] * 4 + + dstYoffset * dstRowStride + + dstXoffset * 4; + for (row = 0; row < srcHeight; row++) { + GLuint *dstUI = (GLuint*)dstRow; + for (col = 0; col < srcWidth; col++) { + dstUI[col] = float3_to_rgb9e5(&srcRow[col * 3]); + } + dstRow += dstRowStride; + srcRow += srcWidth * 3; + } + } + + free((void *) tempImage); + } + return GL_TRUE; +} @@ -4309,6 +4364,8 @@ texstore_funcs[MESA_FORMAT_COUNT] = { MESA_FORMAT_SIGNED_L16, _mesa_texstore_snorm16 }, { MESA_FORMAT_SIGNED_AL1616, _mesa_texstore_snorm1616 }, { MESA_FORMAT_SIGNED_I16, _mesa_texstore_snorm16 }, + + { MESA_FORMAT_RGB9_E5_FLOAT, _mesa_texstore_rgb9_e5 }, }; -- 2.30.2