From 0b43e0b4ddbd9fdac70658164f3dbf653067a4de Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 11 Jul 2011 08:47:29 +0200 Subject: mesa update 11 july 2011 --- mesalib/src/gallium/auxiliary/util/u_pack_color.h | 1232 +++--- mesalib/src/gallium/auxiliary/util/u_surface.c | 775 ++-- mesalib/src/gallium/auxiliary/util/u_tile.c | 1345 +++--- mesalib/src/glsl/ir_optimization.h | 2 - mesalib/src/glsl/ir_reader.cpp | 2012 ++++----- mesalib/src/glsl/linker.cpp | 2 +- mesalib/src/glsl/lower_jumps.cpp | 1580 ++++--- mesalib/src/mesa/main/depthstencil.c | 322 +- mesalib/src/mesa/main/depthstencil.h | 119 +- mesalib/src/mesa/main/fbobject.c | 23 + mesalib/src/mesa/main/formats.c | 29 + mesalib/src/mesa/main/formats.h | 3 + mesalib/src/mesa/main/framebuffer.c | 10 +- mesalib/src/mesa/main/image.c | 3884 ++++++++--------- mesalib/src/mesa/main/mipmap.c | 20 + mesalib/src/mesa/main/mtypes.h | 2 +- mesalib/src/mesa/main/pack.c | 83 +- mesalib/src/mesa/main/pack.h | 294 +- mesalib/src/mesa/main/readpix.c | 29 +- mesalib/src/mesa/main/renderbuffer.c | 3 + mesalib/src/mesa/main/samplerobj.c | 2 +- mesalib/src/mesa/main/shaderapi.c | 4 +- mesalib/src/mesa/main/texenv.c | 6 +- mesalib/src/mesa/main/texfetch.c | 2114 ++++----- mesalib/src/mesa/main/texfetch_tmp.h | 4781 +++++++++++---------- mesalib/src/mesa/main/texformat.c | 13 + mesalib/src/mesa/main/texobj.c | 2 +- mesalib/src/mesa/main/texstore.c | 79 +- mesalib/src/mesa/main/uniforms.c | 4 +- mesalib/src/mesa/state_tracker/st_cb_clear.c | 6 +- mesalib/src/mesa/state_tracker/st_cb_drawpixels.c | 64 +- mesalib/src/mesa/state_tracker/st_cb_readpixels.c | 45 +- mesalib/src/mesa/state_tracker/st_extensions.c | 11 + mesalib/src/mesa/state_tracker/st_format.c | 54 +- mesalib/src/mesa/state_tracker/st_manager.c | 9 + mesalib/src/mesa/swrast/s_blit.c | 3 - mesalib/src/mesa/swrast/s_readpix.c | 2 +- 37 files changed, 10139 insertions(+), 8829 deletions(-) (limited to 'mesalib/src') diff --git a/mesalib/src/gallium/auxiliary/util/u_pack_color.h b/mesalib/src/gallium/auxiliary/util/u_pack_color.h index c51cc7bcb..9391f1b80 100644 --- a/mesalib/src/gallium/auxiliary/util/u_pack_color.h +++ b/mesalib/src/gallium/auxiliary/util/u_pack_color.h @@ -1,584 +1,648 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * 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, sub license, 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. - * - **************************************************************************/ - -/** - * @file - * Functions to produce packed colors/Z from floats. - */ - - -#ifndef U_PACK_COLOR_H -#define U_PACK_COLOR_H - - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "util/u_debug.h" -#include "util/u_format.h" -#include "util/u_math.h" - - -/** - * Helper union for packing pixel values. - * Will often contain values in formats which are too complex to be described - * in simple terms, hence might just effectively contain a number of bytes. - * Must be big enough to hold data for all formats (currently 256 bits). - */ -union util_color { - ubyte ub; - ushort us; - uint ui; - float f[4]; - double d[4]; -}; - -/** - * Pack ubyte R,G,B,A into dest pixel. - */ -static INLINE void -util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, - enum pipe_format format, union util_color *uc) -{ - switch (format) { - case PIPE_FORMAT_A8B8G8R8_UNORM: - { - uc->ui = (r << 24) | (g << 16) | (b << 8) | a; - } - return; - case PIPE_FORMAT_X8B8G8R8_UNORM: - { - uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; - } - return; - case PIPE_FORMAT_B8G8R8A8_UNORM: - { - uc->ui = (a << 24) | (r << 16) | (g << 8) | b; - } - return; - case PIPE_FORMAT_B8G8R8X8_UNORM: - { - uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; - } - return; - case PIPE_FORMAT_A8R8G8B8_UNORM: - { - uc->ui = (b << 24) | (g << 16) | (r << 8) | a; - } - return; - case PIPE_FORMAT_X8R8G8B8_UNORM: - { - uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; - } - return; - case PIPE_FORMAT_B5G6R5_UNORM: - { - uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); - } - return; - case PIPE_FORMAT_B5G5R5X1_UNORM: - { - uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); - } - return; - case PIPE_FORMAT_B5G5R5A1_UNORM: - { - uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); - } - return; - case PIPE_FORMAT_B4G4R4A4_UNORM: - { - uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); - } - return; - case PIPE_FORMAT_A8_UNORM: - { - uc->ub = a; - } - return; - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - { - uc->ub = a; - } - return; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - { - uc->f[0] = (float)r / 255.0f; - uc->f[1] = (float)g / 255.0f; - uc->f[2] = (float)b / 255.0f; - uc->f[3] = (float)a / 255.0f; - } - return; - case PIPE_FORMAT_R32G32B32_FLOAT: - { - uc->f[0] = (float)r / 255.0f; - uc->f[1] = (float)g / 255.0f; - uc->f[2] = (float)b / 255.0f; - } - return; - - /* Handle other cases with a generic function. - */ - default: - { - ubyte src[4]; - - src[0] = r; - src[1] = g; - src[2] = b; - src[3] = a; - util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); - } - } -} - - -/** - * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. - */ -static INLINE void -util_unpack_color_ub(enum pipe_format format, union util_color *uc, - ubyte *r, ubyte *g, ubyte *b, ubyte *a) -{ - switch (format) { - case PIPE_FORMAT_A8B8G8R8_UNORM: - { - uint p = uc->ui; - *r = (ubyte) ((p >> 24) & 0xff); - *g = (ubyte) ((p >> 16) & 0xff); - *b = (ubyte) ((p >> 8) & 0xff); - *a = (ubyte) ((p >> 0) & 0xff); - } - return; - case PIPE_FORMAT_X8B8G8R8_UNORM: - { - uint p = uc->ui; - *r = (ubyte) ((p >> 24) & 0xff); - *g = (ubyte) ((p >> 16) & 0xff); - *b = (ubyte) ((p >> 8) & 0xff); - *a = (ubyte) 0xff; - } - return; - case PIPE_FORMAT_B8G8R8A8_UNORM: - { - uint p = uc->ui; - *r = (ubyte) ((p >> 16) & 0xff); - *g = (ubyte) ((p >> 8) & 0xff); - *b = (ubyte) ((p >> 0) & 0xff); - *a = (ubyte) ((p >> 24) & 0xff); - } - return; - case PIPE_FORMAT_B8G8R8X8_UNORM: - { - uint p = uc->ui; - *r = (ubyte) ((p >> 16) & 0xff); - *g = (ubyte) ((p >> 8) & 0xff); - *b = (ubyte) ((p >> 0) & 0xff); - *a = (ubyte) 0xff; - } - return; - case PIPE_FORMAT_A8R8G8B8_UNORM: - { - uint p = uc->ui; - *r = (ubyte) ((p >> 8) & 0xff); - *g = (ubyte) ((p >> 16) & 0xff); - *b = (ubyte) ((p >> 24) & 0xff); - *a = (ubyte) ((p >> 0) & 0xff); - } - return; - case PIPE_FORMAT_X8R8G8B8_UNORM: - { - uint p = uc->ui; - *r = (ubyte) ((p >> 8) & 0xff); - *g = (ubyte) ((p >> 16) & 0xff); - *b = (ubyte) ((p >> 24) & 0xff); - *a = (ubyte) 0xff; - } - return; - case PIPE_FORMAT_B5G6R5_UNORM: - { - ushort p = uc->us; - *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); - *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); - *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); - *a = (ubyte) 0xff; - } - return; - case PIPE_FORMAT_B5G5R5X1_UNORM: - { - ushort p = uc->us; - *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); - *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); - *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); - *a = (ubyte) 0xff; - } - return; - case PIPE_FORMAT_B5G5R5A1_UNORM: - { - ushort p = uc->us; - *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); - *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); - *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); - *a = (ubyte) (0xff * (p >> 15)); - } - return; - case PIPE_FORMAT_B4G4R4A4_UNORM: - { - ushort p = uc->us; - *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); - *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); - *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); - *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); - } - return; - case PIPE_FORMAT_A8_UNORM: - { - ubyte p = uc->ub; - *r = *g = *b = (ubyte) 0xff; - *a = p; - } - return; - case PIPE_FORMAT_L8_UNORM: - { - ubyte p = uc->ub; - *r = *g = *b = p; - *a = (ubyte) 0xff; - } - return; - case PIPE_FORMAT_I8_UNORM: - { - ubyte p = uc->ub; - *r = *g = *b = *a = p; - } - return; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - { - const float *p = &uc->f[0]; - *r = float_to_ubyte(p[0]); - *g = float_to_ubyte(p[1]); - *b = float_to_ubyte(p[2]); - *a = float_to_ubyte(p[3]); - } - return; - case PIPE_FORMAT_R32G32B32_FLOAT: - { - const float *p = &uc->f[0]; - *r = float_to_ubyte(p[0]); - *g = float_to_ubyte(p[1]); - *b = float_to_ubyte(p[2]); - *a = (ubyte) 0xff; - } - return; - - case PIPE_FORMAT_R32G32_FLOAT: - { - const float *p = &uc->f[0]; - *r = float_to_ubyte(p[0]); - *g = float_to_ubyte(p[1]); - *b = *a = (ubyte) 0xff; - } - return; - - case PIPE_FORMAT_R32_FLOAT: - { - const float *p = &uc->f[0]; - *r = float_to_ubyte(p[0]); - *g = *b = *a = (ubyte) 0xff; - } - return; - - /* Handle other cases with a generic function. - */ - default: - { - ubyte dst[4]; - - util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); - *r = dst[0]; - *g = dst[1]; - *b = dst[2]; - *a = dst[3]; - } - } -} - - -/** - * Note rgba outside [0,1] will be clamped for int pixel formats. - */ -static INLINE void -util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) -{ - ubyte r = 0; - ubyte g = 0; - ubyte b = 0; - ubyte a = 0; - - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { - /* format uses 8-bit components or less */ - r = float_to_ubyte(rgba[0]); - g = float_to_ubyte(rgba[1]); - b = float_to_ubyte(rgba[2]); - a = float_to_ubyte(rgba[3]); - } - - switch (format) { - case PIPE_FORMAT_A8B8G8R8_UNORM: - { - uc->ui = (r << 24) | (g << 16) | (b << 8) | a; - } - return; - case PIPE_FORMAT_X8B8G8R8_UNORM: - { - uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; - } - return; - case PIPE_FORMAT_B8G8R8A8_UNORM: - { - uc->ui = (a << 24) | (r << 16) | (g << 8) | b; - } - return; - case PIPE_FORMAT_B8G8R8X8_UNORM: - { - uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; - } - return; - case PIPE_FORMAT_A8R8G8B8_UNORM: - { - uc->ui = (b << 24) | (g << 16) | (r << 8) | a; - } - return; - case PIPE_FORMAT_X8R8G8B8_UNORM: - { - uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; - } - return; - case PIPE_FORMAT_B5G6R5_UNORM: - { - uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); - } - return; - case PIPE_FORMAT_B5G5R5X1_UNORM: - { - uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); - } - return; - case PIPE_FORMAT_B5G5R5A1_UNORM: - { - uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); - } - return; - case PIPE_FORMAT_B4G4R4A4_UNORM: - { - uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); - } - return; - case PIPE_FORMAT_A8_UNORM: - { - uc->ub = a; - } - return; - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - { - uc->ub = r; - } - return; - case PIPE_FORMAT_R32G32B32A32_FLOAT: - { - uc->f[0] = rgba[0]; - uc->f[1] = rgba[1]; - uc->f[2] = rgba[2]; - uc->f[3] = rgba[3]; - } - return; - case PIPE_FORMAT_R32G32B32_FLOAT: - { - uc->f[0] = rgba[0]; - uc->f[1] = rgba[1]; - uc->f[2] = rgba[2]; - } - return; - - /* Handle other cases with a generic function. - */ - default: - util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); - } -} - -/* Integer versions of util_pack_z and util_pack_z_stencil - useful for - * constructing clear masks. - */ -static INLINE uint32_t -util_pack_mask_z(enum pipe_format format, uint32_t z) -{ - switch (format) { - case PIPE_FORMAT_Z16_UNORM: - return z & 0xffff; - case PIPE_FORMAT_Z32_UNORM: - case PIPE_FORMAT_Z32_FLOAT: - return z; - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - case PIPE_FORMAT_Z24X8_UNORM: - return z & 0xffffff; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - return (z & 0xffffff) << 8; - case PIPE_FORMAT_S8_USCALED: - return 0; - default: - debug_print_format("gallium: unhandled format in util_pack_mask_z()", format); - assert(0); - return 0; - } -} - -static INLINE uint32_t -util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) -{ - uint32_t packed = util_pack_mask_z(format, z); - - switch (format) { - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - packed |= (uint32_t)s << 24; - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - packed |= s; - break; - case PIPE_FORMAT_S8_USCALED: - packed |= s; - break; - default: - break; - } - - return packed; -} - - - -/** - * Note: it's assumed that z is in [0,1] - */ -static INLINE uint32_t -util_pack_z(enum pipe_format format, double z) -{ - union fi fui; - - if (z == 0.0) - return 0; - - switch (format) { - case PIPE_FORMAT_Z16_UNORM: - if (z == 1.0) - return 0xffff; - return (uint32_t) (z * 0xffff); - case PIPE_FORMAT_Z32_UNORM: - /* special-case to avoid overflow */ - if (z == 1.0) - return 0xffffffff; - return (uint32_t) (z * 0xffffffff); - case PIPE_FORMAT_Z32_FLOAT: - fui.f = (float)z; - return fui.ui; - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - case PIPE_FORMAT_Z24X8_UNORM: - if (z == 1.0) - return 0xffffff; - return (uint32_t) (z * 0xffffff); - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - if (z == 1.0) - return 0xffffff00; - return ((uint32_t) (z * 0xffffff)) << 8; - case PIPE_FORMAT_S8_USCALED: - /* this case can get it via util_pack_z_stencil() */ - return 0; - default: - debug_print_format("gallium: unhandled format in util_pack_z()", format); - assert(0); - return 0; - } -} - - -/** - * Pack Z and/or stencil values into a 32-bit value described by format. - * Note: it's assumed that z is in [0,1] and s in [0,255] - */ -static INLINE uint32_t -util_pack_z_stencil(enum pipe_format format, double z, uint8_t s) -{ - uint32_t packed = util_pack_z(format, z); - - switch (format) { - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - packed |= (uint32_t)s << 24; - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - packed |= s; - break; - case PIPE_FORMAT_S8_USCALED: - packed |= s; - break; - default: - break; - } - - return packed; -} - - -/** - * Pack 4 ubytes into a 4-byte word - */ -static INLINE unsigned -pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) -{ - return ((((unsigned int)b0) << 0) | - (((unsigned int)b1) << 8) | - (((unsigned int)b2) << 16) | - (((unsigned int)b3) << 24)); -} - - -/** - * Pack/convert 4 floats into one 4-byte word. - */ -static INLINE unsigned -pack_ui32_float4(float a, float b, float c, float d) -{ - return pack_ub4( float_to_ubyte(a), - float_to_ubyte(b), - float_to_ubyte(c), - float_to_ubyte(d) ); -} - - - -#endif /* U_PACK_COLOR_H */ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/** + * @file + * Functions to produce packed colors/Z from floats. + */ + + +#ifndef U_PACK_COLOR_H +#define U_PACK_COLOR_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "util/u_debug.h" +#include "util/u_format.h" +#include "util/u_math.h" + + +/** + * Helper union for packing pixel values. + * Will often contain values in formats which are too complex to be described + * in simple terms, hence might just effectively contain a number of bytes. + * Must be big enough to hold data for all formats (currently 256 bits). + */ +union util_color { + ubyte ub; + ushort us; + uint ui; + float f[4]; + double d[4]; +}; + +/** + * Pack ubyte R,G,B,A into dest pixel. + */ +static INLINE void +util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, + enum pipe_format format, union util_color *uc) +{ + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | a; + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uc->ui = (a << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | a; + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + uc->f[0] = (float)r / 255.0f; + uc->f[1] = (float)g / 255.0f; + uc->f[2] = (float)b / 255.0f; + uc->f[3] = (float)a / 255.0f; + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + uc->f[0] = (float)r / 255.0f; + uc->f[1] = (float)g / 255.0f; + uc->f[2] = (float)b / 255.0f; + } + return; + + /* Handle other cases with a generic function. + */ + default: + { + ubyte src[4]; + + src[0] = r; + src[1] = g; + src[2] = b; + src[3] = a; + util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1); + } + } +} + + +/** + * Unpack RGBA from a packed pixel, returning values as ubytes in [0,255]. + */ +static INLINE void +util_unpack_color_ub(enum pipe_format format, union util_color *uc, + ubyte *r, ubyte *g, ubyte *b, ubyte *a) +{ + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 24) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 8) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) ((p >> 24) & 0xff); + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 16) & 0xff); + *g = (ubyte) ((p >> 8) & 0xff); + *b = (ubyte) ((p >> 0) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) ((p >> 0) & 0xff); + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uint p = uc->ui; + *r = (ubyte) ((p >> 8) & 0xff); + *g = (ubyte) ((p >> 16) & 0xff); + *b = (ubyte) ((p >> 24) & 0xff); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7)); + *g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) (0xff * (p >> 15)); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf)); + *g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf)); + *b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf)); + *a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf)); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = (ubyte) 0xff; + *a = p; + } + return; + case PIPE_FORMAT_L8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = p; + *a = (ubyte) 0xff; + } + return; + case PIPE_FORMAT_I8_UNORM: + { + ubyte p = uc->ub; + *r = *g = *b = *a = p; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = float_to_ubyte(p[3]); + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = float_to_ubyte(p[2]); + *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32G32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = float_to_ubyte(p[1]); + *b = *a = (ubyte) 0xff; + } + return; + + case PIPE_FORMAT_R32_FLOAT: + { + const float *p = &uc->f[0]; + *r = float_to_ubyte(p[0]); + *g = *b = *a = (ubyte) 0xff; + } + return; + + /* Handle other cases with a generic function. + */ + default: + { + ubyte dst[4]; + + util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1); + *r = dst[0]; + *g = dst[1]; + *b = dst[2]; + *a = dst[3]; + } + } +} + + +/** + * Note rgba outside [0,1] will be clamped for int pixel formats. + */ +static INLINE void +util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc) +{ + ubyte r = 0; + ubyte g = 0; + ubyte b = 0; + ubyte a = 0; + + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) { + /* format uses 8-bit components or less */ + r = float_to_ubyte(rgba[0]); + g = float_to_ubyte(rgba[1]); + b = float_to_ubyte(rgba[2]); + a = float_to_ubyte(rgba[3]); + } + + switch (format) { + case PIPE_FORMAT_A8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | a; + } + return; + case PIPE_FORMAT_X8B8G8R8_UNORM: + { + uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff; + } + return; + case PIPE_FORMAT_B8G8R8A8_UNORM: + { + uc->ui = (a << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_B8G8R8X8_UNORM: + { + uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b; + } + return; + case PIPE_FORMAT_A8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | a; + } + return; + case PIPE_FORMAT_X8R8G8B8_UNORM: + { + uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff; + } + return; + case PIPE_FORMAT_B5G6R5_UNORM: + { + uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B5G5R5A1_UNORM: + { + uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; + case PIPE_FORMAT_B4G4R4A4_UNORM: + { + uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4); + } + return; + case PIPE_FORMAT_A8_UNORM: + { + uc->ub = a; + } + return; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_I8_UNORM: + { + uc->ub = r; + } + return; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + { + uc->f[0] = rgba[0]; + uc->f[1] = rgba[1]; + uc->f[2] = rgba[2]; + uc->f[3] = rgba[3]; + } + return; + case PIPE_FORMAT_R32G32B32_FLOAT: + { + uc->f[0] = rgba[0]; + uc->f[1] = rgba[1]; + uc->f[2] = rgba[2]; + } + return; + + /* Handle other cases with a generic function. + */ + default: + util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1); + } +} + +/* Integer versions of util_pack_z and util_pack_z_stencil - useful for + * constructing clear masks. + */ +static INLINE uint32_t +util_pack_mask_z(enum pipe_format format, uint32_t z) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + return z & 0xffff; + case PIPE_FORMAT_Z32_UNORM: + case PIPE_FORMAT_Z32_FLOAT: + return z; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + return z & 0xffffff; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + return (z & 0xffffff) << 8; + case PIPE_FORMAT_S8_USCALED: + return 0; + default: + debug_print_format("gallium: unhandled format in util_pack_mask_z()", format); + assert(0); + return 0; + } +} + + +static INLINE uint64_t +util_pack64_mask_z(enum pipe_format format, uint32_t z) +{ + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + return z; + default: + return util_pack_mask_z(format, z); + } +} + + +static INLINE uint32_t +util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) +{ + uint32_t packed = util_pack_mask_z(format, z); + + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + packed |= (uint32_t)s << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + packed |= s; + break; + case PIPE_FORMAT_S8_USCALED: + packed |= s; + break; + default: + break; + } + + return packed; +} + + +static INLINE uint64_t +util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s) +{ + uint64_t packed; + + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + packed = util_pack64_mask_z(format, z); + packed |= (uint64_t)s << 32ull; + return packed; + default: + return util_pack_mask_z_stencil(format, z, s); + } +} + + +/** + * Note: it's assumed that z is in [0,1] + */ +static INLINE uint32_t +util_pack_z(enum pipe_format format, double z) +{ + union fi fui; + + if (z == 0.0) + return 0; + + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + if (z == 1.0) + return 0xffff; + return (uint32_t) (z * 0xffff); + case PIPE_FORMAT_Z32_UNORM: + /* special-case to avoid overflow */ + if (z == 1.0) + return 0xffffffff; + return (uint32_t) (z * 0xffffffff); + case PIPE_FORMAT_Z32_FLOAT: + fui.f = (float)z; + return fui.ui; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + if (z == 1.0) + return 0xffffff; + return (uint32_t) (z * 0xffffff); + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + if (z == 1.0) + return 0xffffff00; + return ((uint32_t) (z * 0xffffff)) << 8; + case PIPE_FORMAT_S8_USCALED: + /* this case can get it via util_pack_z_stencil() */ + return 0; + default: + debug_print_format("gallium: unhandled format in util_pack_z()", format); + assert(0); + return 0; + } +} + + +static INLINE uint64_t +util_pack64_z(enum pipe_format format, double z) +{ + union fi fui; + + if (z == 0) + return 0; + + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + fui.f = (float)z; + return fui.ui; + default: + return util_pack_z(format, z); + } +} + + +/** + * Pack Z and/or stencil values into a 32-bit value described by format. + * Note: it's assumed that z is in [0,1] and s in [0,255] + */ +static INLINE uint32_t +util_pack_z_stencil(enum pipe_format format, double z, uint8_t s) +{ + uint32_t packed = util_pack_z(format, z); + + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + packed |= (uint32_t)s << 24; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + packed |= s; + break; + case PIPE_FORMAT_S8_USCALED: + packed |= s; + break; + default: + break; + } + + return packed; +} + + +static INLINE uint64_t +util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s) +{ + uint64_t packed; + + switch (format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + packed = util_pack64_z(format, z); + packed |= (uint64_t)s << 32ull; + break; + default: + return util_pack_z_stencil(format, z, s); + } + + return packed; +} + + +/** + * Pack 4 ubytes into a 4-byte word + */ +static INLINE unsigned +pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3) +{ + return ((((unsigned int)b0) << 0) | + (((unsigned int)b1) << 8) | + (((unsigned int)b2) << 16) | + (((unsigned int)b3) << 24)); +} + + +/** + * Pack/convert 4 floats into one 4-byte word. + */ +static INLINE unsigned +pack_ui32_float4(float a, float b, float c, float d) +{ + return pack_ub4( float_to_ubyte(a), + float_to_ubyte(b), + float_to_ubyte(c), + float_to_ubyte(d) ); +} + + + +#endif /* U_PACK_COLOR_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c index 26f2aee99..8e123867d 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.c +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -1,371 +1,404 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. All Rights Reserved. - * - * 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, sub license, 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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. - * - **************************************************************************/ - -/** - * @file - * Surface utility functions. - * - * @author Brian Paul - */ - - -#include "pipe/p_defines.h" -#include "pipe/p_screen.h" -#include "pipe/p_state.h" - -#include "util/u_format.h" -#include "util/u_inlines.h" -#include "util/u_rect.h" -#include "util/u_surface.h" -#include "util/u_pack_color.h" - -void -u_surface_default_template(struct pipe_surface *view, - const struct pipe_resource *texture, - unsigned bind) -{ - view->format = texture->format; - view->u.tex.level = 0; - view->u.tex.first_layer = 0; - view->u.tex.last_layer = 0; - /* XXX should filter out all non-rt/ds bind flags ? */ - view->usage = bind; -} - -/** - * Helper to quickly create an RGBA rendering surface of a certain size. - * \param textureOut returns the new texture - * \param surfaceOut returns the new surface - * \return TRUE for success, FALSE if failure - */ -boolean -util_create_rgba_surface(struct pipe_context *pipe, - uint width, uint height, - uint bind, - struct pipe_resource **textureOut, - struct pipe_surface **surfaceOut) -{ - static const enum pipe_format rgbaFormats[] = { - PIPE_FORMAT_B8G8R8A8_UNORM, - PIPE_FORMAT_A8R8G8B8_UNORM, - PIPE_FORMAT_A8B8G8R8_UNORM, - PIPE_FORMAT_NONE - }; - const uint target = PIPE_TEXTURE_2D; - enum pipe_format format = PIPE_FORMAT_NONE; - struct pipe_resource templ; - struct pipe_surface surf_templ; - struct pipe_screen *screen = pipe->screen; - uint i; - - /* Choose surface format */ - for (i = 0; rgbaFormats[i]; i++) { - if (screen->is_format_supported(screen, rgbaFormats[i], - target, 0, bind)) { - format = rgbaFormats[i]; - break; - } - } - if (format == PIPE_FORMAT_NONE) - return FALSE; /* unable to get an rgba format!?! */ - - /* create texture */ - memset(&templ, 0, sizeof(templ)); - templ.target = target; - templ.format = format; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.bind = bind; - - *textureOut = screen->resource_create(screen, &templ); - if (!*textureOut) - return FALSE; - - /* create surface */ - memset(&surf_templ, 0, sizeof(surf_templ)); - u_surface_default_template(&surf_templ, *textureOut, bind); - /* create surface / view into texture */ - *surfaceOut = pipe->create_surface(pipe, - *textureOut, - &surf_templ); - if (!*surfaceOut) { - pipe_resource_reference(textureOut, NULL); - return FALSE; - } - - return TRUE; -} - - -/** - * Release the surface and texture from util_create_rgba_surface(). - */ -void -util_destroy_rgba_surface(struct pipe_resource *texture, - struct pipe_surface *surface) -{ - pipe_surface_reference(&surface, NULL); - pipe_resource_reference(&texture, NULL); -} - - - -/** - * Fallback function for pipe->resource_copy_region(). - * Note: (X,Y)=(0,0) is always the upper-left corner. - */ -void -util_resource_copy_region(struct pipe_context *pipe, - struct pipe_resource *dst, - unsigned dst_level, - unsigned dst_x, unsigned dst_y, unsigned dst_z, - struct pipe_resource *src, - unsigned src_level, - const struct pipe_box *src_box) -{ - struct pipe_transfer *src_trans, *dst_trans; - void *dst_map; - const void *src_map; - enum pipe_format src_format, dst_format; - unsigned w = src_box->width; - unsigned h = src_box->height; - - assert(src && dst); - assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || - (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); - - if (!src || !dst) - return; - - src_format = src->format; - dst_format = dst->format; - - src_trans = pipe_get_transfer(pipe, - src, - src_level, - src_box->z, - PIPE_TRANSFER_READ, - src_box->x, src_box->y, w, h); - - dst_trans = pipe_get_transfer(pipe, - dst, - dst_level, - dst_z, - PIPE_TRANSFER_WRITE, - dst_x, dst_y, w, h); - - assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); - assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); - assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); - - src_map = pipe->transfer_map(pipe, src_trans); - dst_map = pipe->transfer_map(pipe, dst_trans); - - assert(src_map); - assert(dst_map); - - if (src_map && dst_map) { - if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { - memcpy(dst_map, src_map, w); - } else { - util_copy_rect(dst_map, - dst_format, - dst_trans->stride, - 0, 0, - w, h, - src_map, - src_trans->stride, - 0, - 0); - } - } - - pipe->transfer_unmap(pipe, src_trans); - pipe->transfer_unmap(pipe, dst_trans); - - pipe->transfer_destroy(pipe, src_trans); - pipe->transfer_destroy(pipe, dst_trans); -} - - - -#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) - - -/** - * Fallback for pipe->clear_render_target() function. - * XXX this looks too hackish to be really useful. - * cpp > 4 looks like a gross hack at best... - * Plus can't use these transfer fallbacks when clearing - * multisampled surfaces for instance. - */ -void -util_clear_render_target(struct pipe_context *pipe, - struct pipe_surface *dst, - const float *rgba, - unsigned dstx, unsigned dsty, - unsigned width, unsigned height) -{ - struct pipe_transfer *dst_trans; - void *dst_map; - union util_color uc; - - assert(dst->texture); - if (!dst->texture) - return; - /* XXX: should handle multiple layers */ - dst_trans = pipe_get_transfer(pipe, - dst->texture, - dst->u.tex.level, - dst->u.tex.first_layer, - PIPE_TRANSFER_WRITE, - dstx, dsty, width, height); - - dst_map = pipe->transfer_map(pipe, dst_trans); - - assert(dst_map); - - if (dst_map) { - assert(dst_trans->stride > 0); - - util_pack_color(rgba, dst->texture->format, &uc); - util_fill_rect(dst_map, dst->texture->format, - dst_trans->stride, - 0, 0, width, height, &uc); - } - - pipe->transfer_unmap(pipe, dst_trans); - pipe->transfer_destroy(pipe, dst_trans); -} - -/** - * Fallback for pipe->clear_stencil() function. - * sw fallback doesn't look terribly useful here. - * Plus can't use these transfer fallbacks when clearing - * multisampled surfaces for instance. - */ -void -util_clear_depth_stencil(struct pipe_context *pipe, - struct pipe_surface *dst, - unsigned clear_flags, - double depth, - unsigned stencil, - unsigned dstx, unsigned dsty, - unsigned width, unsigned height) -{ - struct pipe_transfer *dst_trans; - ubyte *dst_map; - boolean need_rmw = FALSE; - - if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && - ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && - util_format_is_depth_and_stencil(dst->format)) - need_rmw = TRUE; - - assert(dst->texture); - if (!dst->texture) - return; - dst_trans = pipe_get_transfer(pipe, - dst->texture, - dst->u.tex.level, - dst->u.tex.first_layer, - (need_rmw ? PIPE_TRANSFER_READ_WRITE : - PIPE_TRANSFER_WRITE), - dstx, dsty, width, height); - - dst_map = pipe->transfer_map(pipe, dst_trans); - - assert(dst_map); - - if (dst_map) { - unsigned dst_stride = dst_trans->stride; - unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil); - unsigned i, j; - assert(dst_trans->stride > 0); - - switch (util_format_get_blocksize(dst->format)) { - case 1: - assert(dst->format == PIPE_FORMAT_S8_USCALED); - if(dst_stride == width) - memset(dst_map, (ubyte) zstencil, height * width); - else { - for (i = 0; i < height; i++) { - memset(dst_map, (ubyte) zstencil, width); - dst_map += dst_stride; - } - } - break; - case 2: - assert(dst->format == PIPE_FORMAT_Z16_UNORM); - for (i = 0; i < height; i++) { - uint16_t *row = (uint16_t *)dst_map; - for (j = 0; j < width; j++) - *row++ = (uint16_t) zstencil; - dst_map += dst_stride; - } - break; - case 4: - if (!need_rmw) { - for (i = 0; i < height; i++) { - uint32_t *row = (uint32_t *)dst_map; - for (j = 0; j < width; j++) - *row++ = zstencil; - dst_map += dst_stride; - } - } - else { - uint32_t dst_mask; - if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) - dst_mask = 0xffffff00; - else { - assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM); - dst_mask = 0xffffff; - } - if (clear_flags & PIPE_CLEAR_DEPTH) - dst_mask = ~dst_mask; - for (i = 0; i < height; i++) { - uint32_t *row = (uint32_t *)dst_map; - for (j = 0; j < width; j++) { - uint32_t tmp = *row & dst_mask; - *row++ = tmp | (zstencil & ~dst_mask); - } - dst_map += dst_stride; - } - } - break; - case 8: - default: - assert(0); - break; - } - } - - pipe->transfer_unmap(pipe, dst_trans); - pipe->transfer_destroy(pipe, dst_trans); -} +/************************************************************************** + * + * Copyright 2009 VMware, Inc. All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/** + * @file + * Surface utility functions. + * + * @author Brian Paul + */ + + +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" + +#include "util/u_format.h" +#include "util/u_inlines.h" +#include "util/u_rect.h" +#include "util/u_surface.h" +#include "util/u_pack_color.h" + +void +u_surface_default_template(struct pipe_surface *view, + const struct pipe_resource *texture, + unsigned bind) +{ + view->format = texture->format; + view->u.tex.level = 0; + view->u.tex.first_layer = 0; + view->u.tex.last_layer = 0; + /* XXX should filter out all non-rt/ds bind flags ? */ + view->usage = bind; +} + +/** + * Helper to quickly create an RGBA rendering surface of a certain size. + * \param textureOut returns the new texture + * \param surfaceOut returns the new surface + * \return TRUE for success, FALSE if failure + */ +boolean +util_create_rgba_surface(struct pipe_context *pipe, + uint width, uint height, + uint bind, + struct pipe_resource **textureOut, + struct pipe_surface **surfaceOut) +{ + static const enum pipe_format rgbaFormats[] = { + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_A8B8G8R8_UNORM, + PIPE_FORMAT_NONE + }; + const uint target = PIPE_TEXTURE_2D; + enum pipe_format format = PIPE_FORMAT_NONE; + struct pipe_resource templ; + struct pipe_surface surf_templ; + struct pipe_screen *screen = pipe->screen; + uint i; + + /* Choose surface format */ + for (i = 0; rgbaFormats[i]; i++) { + if (screen->is_format_supported(screen, rgbaFormats[i], + target, 0, bind)) { + format = rgbaFormats[i]; + break; + } + } + if (format == PIPE_FORMAT_NONE) + return FALSE; /* unable to get an rgba format!?! */ + + /* create texture */ + memset(&templ, 0, sizeof(templ)); + templ.target = target; + templ.format = format; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.bind = bind; + + *textureOut = screen->resource_create(screen, &templ); + if (!*textureOut) + return FALSE; + + /* create surface */ + memset(&surf_templ, 0, sizeof(surf_templ)); + u_surface_default_template(&surf_templ, *textureOut, bind); + /* create surface / view into texture */ + *surfaceOut = pipe->create_surface(pipe, + *textureOut, + &surf_templ); + if (!*surfaceOut) { + pipe_resource_reference(textureOut, NULL); + return FALSE; + } + + return TRUE; +} + + +/** + * Release the surface and texture from util_create_rgba_surface(). + */ +void +util_destroy_rgba_surface(struct pipe_resource *texture, + struct pipe_surface *surface) +{ + pipe_surface_reference(&surface, NULL); + pipe_resource_reference(&texture, NULL); +} + + + +/** + * Fallback function for pipe->resource_copy_region(). + * Note: (X,Y)=(0,0) is always the upper-left corner. + */ +void +util_resource_copy_region(struct pipe_context *pipe, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) +{ + struct pipe_transfer *src_trans, *dst_trans; + void *dst_map; + const void *src_map; + enum pipe_format src_format, dst_format; + unsigned w = src_box->width; + unsigned h = src_box->height; + + assert(src && dst); + assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) || + (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER)); + + if (!src || !dst) + return; + + src_format = src->format; + dst_format = dst->format; + + src_trans = pipe_get_transfer(pipe, + src, + src_level, + src_box->z, + PIPE_TRANSFER_READ, + src_box->x, src_box->y, w, h); + + dst_trans = pipe_get_transfer(pipe, + dst, + dst_level, + dst_z, + PIPE_TRANSFER_WRITE, + dst_x, dst_y, w, h); + + assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); + assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); + assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); + + src_map = pipe->transfer_map(pipe, src_trans); + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(src_map); + assert(dst_map); + + if (src_map && dst_map) { + if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { + memcpy(dst_map, src_map, w); + } else { + util_copy_rect(dst_map, + dst_format, + dst_trans->stride, + 0, 0, + w, h, + src_map, + src_trans->stride, + 0, + 0); + } + } + + pipe->transfer_unmap(pipe, src_trans); + pipe->transfer_unmap(pipe, dst_trans); + + pipe->transfer_destroy(pipe, src_trans); + pipe->transfer_destroy(pipe, dst_trans); +} + + + +#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) + + +/** + * Fallback for pipe->clear_render_target() function. + * XXX this looks too hackish to be really useful. + * cpp > 4 looks like a gross hack at best... + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. + */ +void +util_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct pipe_transfer *dst_trans; + void *dst_map; + union util_color uc; + + assert(dst->texture); + if (!dst->texture) + return; + /* XXX: should handle multiple layers */ + dst_trans = pipe_get_transfer(pipe, + dst->texture, + dst->u.tex.level, + dst->u.tex.first_layer, + PIPE_TRANSFER_WRITE, + dstx, dsty, width, height); + + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(dst_map); + + if (dst_map) { + assert(dst_trans->stride > 0); + + util_pack_color(rgba, dst->texture->format, &uc); + util_fill_rect(dst_map, dst->texture->format, + dst_trans->stride, + 0, 0, width, height, &uc); + } + + pipe->transfer_unmap(pipe, dst_trans); + pipe->transfer_destroy(pipe, dst_trans); +} + +/** + * Fallback for pipe->clear_stencil() function. + * sw fallback doesn't look terribly useful here. + * Plus can't use these transfer fallbacks when clearing + * multisampled surfaces for instance. + */ +void +util_clear_depth_stencil(struct pipe_context *pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct pipe_transfer *dst_trans; + ubyte *dst_map; + boolean need_rmw = FALSE; + + if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && + ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + util_format_is_depth_and_stencil(dst->format)) + need_rmw = TRUE; + + assert(dst->texture); + if (!dst->texture) + return; + dst_trans = pipe_get_transfer(pipe, + dst->texture, + dst->u.tex.level, + dst->u.tex.first_layer, + (need_rmw ? PIPE_TRANSFER_READ_WRITE : + PIPE_TRANSFER_WRITE), + dstx, dsty, width, height); + + dst_map = pipe->transfer_map(pipe, dst_trans); + + assert(dst_map); + + if (dst_map) { + unsigned dst_stride = dst_trans->stride; + unsigned zstencil = util_pack_z_stencil(dst->texture->format, depth, stencil); + unsigned i, j; + assert(dst_trans->stride > 0); + + switch (util_format_get_blocksize(dst->format)) { + case 1: + assert(dst->format == PIPE_FORMAT_S8_USCALED); + if(dst_stride == width) + memset(dst_map, (ubyte) zstencil, height * width); + else { + for (i = 0; i < height; i++) { + memset(dst_map, (ubyte) zstencil, width); + dst_map += dst_stride; + } + } + break; + case 2: + assert(dst->format == PIPE_FORMAT_Z16_UNORM); + for (i = 0; i < height; i++) { + uint16_t *row = (uint16_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = (uint16_t) zstencil; + dst_map += dst_stride; + } + break; + case 4: + if (!need_rmw) { + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = zstencil; + dst_map += dst_stride; + } + } + else { + uint32_t dst_mask; + if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) + dst_mask = 0xffffff00; + else { + assert(dst->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM); + dst_mask = 0xffffff; + } + if (clear_flags & PIPE_CLEAR_DEPTH) + dst_mask = ~dst_mask; + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst_map; + for (j = 0; j < width; j++) { + uint32_t tmp = *row & dst_mask; + *row++ = tmp | (zstencil & ~dst_mask); + } + dst_map += dst_stride; + } + } + break; + case 8: + { + uint64_t zstencil = util_pack64_z_stencil(dst->texture->format, + depth, stencil); + + assert(dst->format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED); + + if (!need_rmw) { + for (i = 0; i < height; i++) { + uint64_t *row = (uint64_t *)dst_map; + for (j = 0; j < width; j++) + *row++ = zstencil; + dst_map += dst_stride; + } + } + else { + uint64_t src_mask; + + if (clear_flags & PIPE_CLEAR_DEPTH) + src_mask = 0x00000000ffffffffull; + else + src_mask = 0x000000ff00000000ull; + + for (i = 0; i < height; i++) { + uint64_t *row = (uint64_t *)dst_map; + for (j = 0; j < width; j++) { + uint64_t tmp = *row & ~src_mask; + *row++ = tmp | (zstencil & src_mask); + } + dst_map += dst_stride; + } + } + break; + } + default: + assert(0); + break; + } + } + + pipe->transfer_unmap(pipe, dst_trans); + pipe->transfer_destroy(pipe, dst_trans); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.c b/mesalib/src/gallium/auxiliary/util/u_tile.c index 54f634948..23f12e5f4 100644 --- a/mesalib/src/gallium/auxiliary/util/u_tile.c +++ b/mesalib/src/gallium/auxiliary/util/u_tile.c @@ -1,655 +1,690 @@ -/************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * 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, sub license, 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. - * - **************************************************************************/ - -/** - * RGBA/float tile get/put functions. - * Usable both by drivers and state trackers. - */ - - -#include "pipe/p_defines.h" -#include "util/u_inlines.h" - -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "util/u_rect.h" -#include "util/u_tile.h" - - -/** - * Move raw block of pixels from transfer object to user memory. - */ -void -pipe_get_tile_raw(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - void *dst, int dst_stride) -{ - const void *src; - - if (dst_stride == 0) - dst_stride = util_format_get_stride(pt->resource->format, w); - - if (u_clip_tile(x, y, &w, &h, &pt->box)) - return; - - src = pipe->transfer_map(pipe, pt); - assert(src); - if(!src) - return; - - util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y); - - pipe->transfer_unmap(pipe, pt); -} - - -/** - * Move raw block of pixels from user memory to transfer object. - */ -void -pipe_put_tile_raw(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - const void *src, int src_stride) -{ - void *dst; - enum pipe_format format = pt->resource->format; - - if (src_stride == 0) - src_stride = util_format_get_stride(format, w); - - if (u_clip_tile(x, y, &w, &h, &pt->box)) - return; - - dst = pipe->transfer_map(pipe, pt); - assert(dst); - if(!dst) - return; - - util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0); - - pipe->transfer_unmap(pipe, pt); -} - - - - -/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */ -#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) - -#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \ - us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) ) - - - -/*** PIPE_FORMAT_Z16_UNORM ***/ - -/** - * Return each Z value as four floats in [0,1]. - */ -static void -z16_get_tile_rgba(const ushort *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - const float scale = 1.0f / 65535.0f; - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = *src++ * scale; - } - p += dst_stride; - } -} - - - - -/*** PIPE_FORMAT_Z32_UNORM ***/ - -/** - * Return each Z value as four floats in [0,1]. - */ -static void -z32_get_tile_rgba(const unsigned *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - const double scale = 1.0 / (double) 0xffffffff; - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = (float) (*src++ * scale); - } - p += dst_stride; - } -} - - -/*** PIPE_FORMAT_Z24_UNORM_S8_USCALED ***/ - -/** - * Return Z component as four float in [0,1]. Stencil part ignored. - */ -static void -s8z24_get_tile_rgba(const unsigned *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - const double scale = 1.0 / ((1 << 24) - 1); - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = (float) (scale * (*src++ & 0xffffff)); - } - p += dst_stride; - } -} - - -/*** PIPE_FORMAT_S8_USCALED_Z24_UNORM ***/ - -/** - * Return Z component as four float in [0,1]. Stencil part ignored. - */ -static void -z24s8_get_tile_rgba(const unsigned *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - const double scale = 1.0 / ((1 << 24) - 1); - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = (float) (scale * (*src++ >> 8)); - } - p += dst_stride; - } -} - -/*** PIPE_FORMAT_S8X24_USCALED ***/ - -/** - * Return S component as four uint32_t in [0..255]. Z part ignored. - */ -static void -s8x24_get_tile_rgba(const unsigned *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = (float)((*src++ >> 24) & 0xff); - } - - p += dst_stride; - } -} - -/*** PIPE_FORMAT_X24S8_USCALED ***/ - -/** - * Return S component as four uint32_t in [0..255]. Z part ignored. - */ -static void -x24s8_get_tile_rgba(const unsigned *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = (float)(*src++ & 0xff); - } - p += dst_stride; - } -} - - -/** - * Return S component as four uint32_t in [0..255]. Z part ignored. - */ -static void -s8_get_tile_rgba(const unsigned char *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = (float)(*src++ & 0xff); - } - p += dst_stride; - } -} - -/*** PIPE_FORMAT_Z32_FLOAT ***/ - -/** - * Return each Z value as four floats in [0,1]. - */ -static void -z32f_get_tile_rgba(const float *src, - unsigned w, unsigned h, - float *p, - unsigned dst_stride) -{ - unsigned i, j; - - for (i = 0; i < h; i++) { - float *pRow = p; - for (j = 0; j < w; j++, pRow += 4) { - pRow[0] = - pRow[1] = - pRow[2] = - pRow[3] = *src++; - } - p += dst_stride; - } -} - - -void -pipe_tile_raw_to_rgba(enum pipe_format format, - void *src, - uint w, uint h, - float *dst, unsigned dst_stride) -{ - switch (format) { - case PIPE_FORMAT_Z16_UNORM: - z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_Z32_UNORM: - z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - case PIPE_FORMAT_Z24X8_UNORM: - s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_S8_USCALED: - s8_get_tile_rgba((unsigned char *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_X24S8_USCALED: - s8x24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_S8X24_USCALED: - x24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); - break; - case PIPE_FORMAT_Z32_FLOAT: - z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride); - break; - default: - util_format_read_4f(format, - dst, dst_stride * sizeof(float), - src, util_format_get_stride(format, w), - 0, 0, w, h); - } -} - - -void -pipe_get_tile_rgba(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - float *p) -{ - pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); -} - - -void -pipe_get_tile_rgba_format(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - enum pipe_format format, - float *p) -{ - unsigned dst_stride = w * 4; - void *packed; - - if (u_clip_tile(x, y, &w, &h, &pt->box)) { - return; - } - - packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); - if (!packed) { - return; - } - - if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { - assert((x & 1) == 0); - } - - pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); - - pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); - - FREE(packed); -} - - -void -pipe_put_tile_rgba(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - const float *p) -{ - pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); -} - - -void -pipe_put_tile_rgba_format(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - enum pipe_format format, - const float *p) -{ - unsigned src_stride = w * 4; - void *packed; - - if (u_clip_tile(x, y, &w, &h, &pt->box)) - return; - - packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); - - if (!packed) - return; - - switch (format) { - case PIPE_FORMAT_Z16_UNORM: - /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/ - break; - case PIPE_FORMAT_Z32_UNORM: - /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ - break; - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - case PIPE_FORMAT_Z24X8_UNORM: - /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ - break; - default: - util_format_write_4f(format, - p, src_stride * sizeof(float), - packed, util_format_get_stride(format, w), - 0, 0, w, h); - } - - pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0); - - FREE(packed); -} - - -/** - * Get a block of Z values, converted to 32-bit range. - */ -void -pipe_get_tile_z(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - uint *z) -{ - const uint dstStride = w; - ubyte *map; - uint *pDest = z; - uint i, j; - enum pipe_format format = pt->resource->format; - - if (u_clip_tile(x, y, &w, &h, &pt->box)) - return; - - map = (ubyte *)pipe->transfer_map(pipe, pt); - if (!map) { - assert(0); - return; - } - - switch (format) { - case PIPE_FORMAT_Z32_UNORM: - { - const uint *ptrc - = (const uint *)(map + y * pt->stride + x*4); - for (i = 0; i < h; i++) { - memcpy(pDest, ptrc, 4 * w); - pDest += dstStride; - ptrc += pt->stride/4; - } - } - break; - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - case PIPE_FORMAT_Z24X8_UNORM: - { - const uint *ptrc - = (const uint *)(map + y * pt->stride + x*4); - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 24-bit Z to 32-bit Z */ - pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff); - } - pDest += dstStride; - ptrc += pt->stride/4; - } - } - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - case PIPE_FORMAT_X8Z24_UNORM: - { - const uint *ptrc - = (const uint *)(map + y * pt->stride + x*4); - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 24-bit Z to 32-bit Z */ - pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff); - } - pDest += dstStride; - ptrc += pt->stride/4; - } - } - break; - case PIPE_FORMAT_Z16_UNORM: - { - const ushort *ptrc - = (const ushort *)(map + y * pt->stride + x*2); - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 16-bit Z to 32-bit Z */ - pDest[j] = (ptrc[j] << 16) | ptrc[j]; - } - pDest += dstStride; - ptrc += pt->stride/2; - } - } - break; - default: - assert(0); - } - - pipe->transfer_unmap(pipe, pt); -} - - -void -pipe_put_tile_z(struct pipe_context *pipe, - struct pipe_transfer *pt, - uint x, uint y, uint w, uint h, - const uint *zSrc) -{ - const uint srcStride = w; - const uint *ptrc = zSrc; - ubyte *map; - uint i, j; - enum pipe_format format = pt->resource->format; - - if (u_clip_tile(x, y, &w, &h, &pt->box)) - return; - - map = (ubyte *)pipe->transfer_map(pipe, pt); - if (!map) { - assert(0); - return; - } - - switch (format) { - case PIPE_FORMAT_Z32_UNORM: - { - uint *pDest = (uint *) (map + y * pt->stride + x*4); - for (i = 0; i < h; i++) { - memcpy(pDest, ptrc, 4 * w); - pDest += pt->stride/4; - ptrc += srcStride; - } - } - break; - case PIPE_FORMAT_Z24_UNORM_S8_USCALED: - { - uint *pDest = (uint *) (map + y * pt->stride + x*4); - /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 32-bit Z to 24-bit Z, preserve stencil */ - pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8; - } - pDest += pt->stride/4; - ptrc += srcStride; - } - } - break; - case PIPE_FORMAT_Z24X8_UNORM: - { - uint *pDest = (uint *) (map + y * pt->stride + x*4); - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 32-bit Z to 24-bit Z (0 stencil) */ - pDest[j] = ptrc[j] >> 8; - } - pDest += pt->stride/4; - ptrc += srcStride; - } - } - break; - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - { - uint *pDest = (uint *) (map + y * pt->stride + x*4); - /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 32-bit Z to 24-bit Z, preserve stencil */ - pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00); - } - pDest += pt->stride/4; - ptrc += srcStride; - } - } - break; - case PIPE_FORMAT_X8Z24_UNORM: - { - uint *pDest = (uint *) (map + y * pt->stride + x*4); - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 32-bit Z to 24-bit Z (0 stencil) */ - pDest[j] = ptrc[j] & 0xffffff00; - } - pDest += pt->stride/4; - ptrc += srcStride; - } - } - break; - case PIPE_FORMAT_Z16_UNORM: - { - ushort *pDest = (ushort *) (map + y * pt->stride + x*2); - for (i = 0; i < h; i++) { - for (j = 0; j < w; j++) { - /* convert 32-bit Z to 16-bit Z */ - pDest[j] = ptrc[j] >> 16; - } - pDest += pt->stride/2; - ptrc += srcStride; - } - } - break; - default: - assert(0); - } - - pipe->transfer_unmap(pipe, pt); -} - - +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * 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, sub license, 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. + * + **************************************************************************/ + +/** + * RGBA/float tile get/put functions. + * Usable both by drivers and state trackers. + */ + + +#include "pipe/p_defines.h" +#include "util/u_inlines.h" + +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_tile.h" + + +/** + * Move raw block of pixels from transfer object to user memory. + */ +void +pipe_get_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + void *dst, int dst_stride) +{ + const void *src; + + if (dst_stride == 0) + dst_stride = util_format_get_stride(pt->resource->format, w); + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + src = pipe->transfer_map(pipe, pt); + assert(src); + if(!src) + return; + + util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y); + + pipe->transfer_unmap(pipe, pt); +} + + +/** + * Move raw block of pixels from user memory to transfer object. + */ +void +pipe_put_tile_raw(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const void *src, int src_stride) +{ + void *dst; + enum pipe_format format = pt->resource->format; + + if (src_stride == 0) + src_stride = util_format_get_stride(format, w); + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + dst = pipe->transfer_map(pipe, pt); + assert(dst); + if(!dst) + return; + + util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0); + + pipe->transfer_unmap(pipe, pt); +} + + + + +/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */ +#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) + +#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \ + us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) ) + + + +/*** PIPE_FORMAT_Z16_UNORM ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z16_get_tile_rgba(const ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const float scale = 1.0f / 65535.0f; + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src++ * scale; + } + p += dst_stride; + } +} + + + + +/*** PIPE_FORMAT_Z32_UNORM ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / (double) 0xffffffff; + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (*src++ * scale); + } + p += dst_stride; + } +} + + +/*** PIPE_FORMAT_Z24_UNORM_S8_USCALED ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +s8z24_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (scale * (*src++ & 0xffffff)); + } + p += dst_stride; + } +} + + +/*** PIPE_FORMAT_S8_USCALED_Z24_UNORM ***/ + +/** + * Return Z component as four float in [0,1]. Stencil part ignored. + */ +static void +z24s8_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + const double scale = 1.0 / ((1 << 24) - 1); + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float) (scale * (*src++ >> 8)); + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_S8X24_USCALED ***/ + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +s8x24_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)((*src++ >> 24) & 0xff); + } + + p += dst_stride; + } +} + +/*** PIPE_FORMAT_X24S8_USCALED ***/ + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +x24s8_get_tile_rgba(const unsigned *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)(*src++ & 0xff); + } + p += dst_stride; + } +} + + +/** + * Return S component as four uint32_t in [0..255]. Z part ignored. + */ +static void +s8_get_tile_rgba(const unsigned char *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = (float)(*src++ & 0xff); + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_Z32_FLOAT ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32f_get_tile_rgba(const float *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src++; + } + p += dst_stride; + } +} + +/*** PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED ***/ + +/** + * Return each Z value as four floats in [0,1]. + */ +static void +z32f_x24s8_get_tile_rgba(const float *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + pRow[0] = + pRow[1] = + pRow[2] = + pRow[3] = *src; + src += 2; + } + p += dst_stride; + } +} + + +void +pipe_tile_raw_to_rgba(enum pipe_format format, + void *src, + uint w, uint h, + float *dst, unsigned dst_stride) +{ + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_UNORM: + z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8_USCALED: + s8_get_tile_rgba((unsigned char *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_X24S8_USCALED: + s8x24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_S8X24_USCALED: + x24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_FLOAT: + z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride); + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + z32f_x24s8_get_tile_rgba((float *) src, w, h, dst, dst_stride); + break; + default: + util_format_read_4f(format, + dst, dst_stride * sizeof(float), + src, util_format_get_stride(format, w), + 0, 0, w, h); + } +} + + +void +pipe_get_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + float *p) +{ + pipe_get_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_get_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + float *p) +{ + unsigned dst_stride = w * 4; + void *packed; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) { + return; + } + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + if (!packed) { + return; + } + + if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { + assert((x & 1) == 0); + } + + pipe_get_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride); + + FREE(packed); +} + + +void +pipe_put_tile_rgba(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const float *p) +{ + pipe_put_tile_rgba_format(pipe, pt, x, y, w, h, pt->resource->format, p); +} + + +void +pipe_put_tile_rgba_format(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + enum pipe_format format, + const float *p) +{ + unsigned src_stride = w * 4; + void *packed; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format)); + + if (!packed) + return; + + switch (format) { + case PIPE_FORMAT_Z16_UNORM: + /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_UNORM: + /*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + /*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + /*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_FLOAT: + /*z32f_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + /*z32f_s8x24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/ + break; + default: + util_format_write_4f(format, + p, src_stride * sizeof(float), + packed, util_format_get_stride(format, w), + 0, 0, w, h); + } + + pipe_put_tile_raw(pipe, pt, x, y, w, h, packed, 0); + + FREE(packed); +} + + +/** + * Get a block of Z values, converted to 32-bit range. + */ +void +pipe_get_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + uint *z) +{ + const uint dstStride = w; + ubyte *map; + uint *pDest = z; + uint i, j; + enum pipe_format format = pt->resource->format; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + map = (ubyte *)pipe->transfer_map(pipe, pt); + if (!map) { + assert(0); + return; + } + + switch (format) { + case PIPE_FORMAT_Z32_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + memcpy(pDest, ptrc, 4 * w); + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_Z24X8_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 24-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff); + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + { + const uint *ptrc + = (const uint *)(map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 24-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff); + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; + case PIPE_FORMAT_Z16_UNORM: + { + const ushort *ptrc + = (const ushort *)(map + y * pt->stride + x*2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 16-bit Z to 32-bit Z */ + pDest[j] = (ptrc[j] << 16) | ptrc[j]; + } + pDest += dstStride; + ptrc += pt->stride/2; + } + } + break; + default: + assert(0); + } + + pipe->transfer_unmap(pipe, pt); +} + + +void +pipe_put_tile_z(struct pipe_context *pipe, + struct pipe_transfer *pt, + uint x, uint y, uint w, uint h, + const uint *zSrc) +{ + const uint srcStride = w; + const uint *ptrc = zSrc; + ubyte *map; + uint i, j; + enum pipe_format format = pt->resource->format; + + if (u_clip_tile(x, y, &w, &h, &pt->box)) + return; + + map = (ubyte *)pipe->transfer_map(pipe, pt); + if (!map) { + assert(0); + return; + } + + switch (format) { + case PIPE_FORMAT_Z32_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + memcpy(pDest, ptrc, 4 * w); + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z24X8_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z (0 stencil) */ + pDest[j] = ptrc[j] >> 8; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + /*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/ + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z, preserve stencil */ + pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00); + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_X8Z24_UNORM: + { + uint *pDest = (uint *) (map + y * pt->stride + x*4); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 24-bit Z (0 stencil) */ + pDest[j] = ptrc[j] & 0xffffff00; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; + case PIPE_FORMAT_Z16_UNORM: + { + ushort *pDest = (ushort *) (map + y * pt->stride + x*2); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit Z to 16-bit Z */ + pDest[j] = ptrc[j] >> 16; + } + pDest += pt->stride/2; + ptrc += srcStride; + } + } + break; + default: + assert(0); + } + + pipe->transfer_unmap(pipe, pt); +} + + diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index dd265673c..59a040751 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -56,10 +56,8 @@ bool do_if_simplification(exec_list *instructions); bool do_discard_simplification(exec_list *instructions); bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth = 0); bool do_mat_op_to_vec(exec_list *instructions); -bool do_mod_to_fract(exec_list *instructions); bool do_noop_swizzle(exec_list *instructions); bool do_structure_splitting(exec_list *instructions); -bool do_sub_to_add_neg(exec_list *instructions); bool do_swizzle_swizzle(exec_list *instructions); bool do_tree_grafting(exec_list *instructions); bool do_vec_index_to_cond_assign(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 201e436be..f3a621734 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -1,1005 +1,1007 @@ -/* - * Copyright © 2010 Intel Corporation - * - * 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. - */ - -#include "ir_reader.h" -#include "glsl_parser_extras.h" -#include "glsl_types.h" -#include "s_expression.h" - -const static bool debug = false; - -class ir_reader { -public: - ir_reader(_mesa_glsl_parse_state *); - - void read(exec_list *instructions, const char *src, bool scan_for_protos); - -private: - void *mem_ctx; - _mesa_glsl_parse_state *state; - - void ir_read_error(s_expression *, const char *fmt, ...); - - const glsl_type *read_type(s_expression *); - - void scan_for_prototypes(exec_list *, s_expression *); - ir_function *read_function(s_expression *, bool skip_body); - void read_function_sig(ir_function *, s_expression *, bool skip_body); - - void read_instructions(exec_list *, s_expression *, ir_loop *); - ir_instruction *read_instruction(s_expression *, ir_loop *); - ir_variable *read_declaration(s_expression *); - ir_if *read_if(s_expression *, ir_loop *); - ir_loop *read_loop(s_expression *); - ir_return *read_return(s_expression *); - ir_rvalue *read_rvalue(s_expression *); - ir_assignment *read_assignment(s_expression *); - ir_expression *read_expression(s_expression *); - ir_call *read_call(s_expression *); - ir_swizzle *read_swizzle(s_expression *); - ir_constant *read_constant(s_expression *); - ir_texture *read_texture(s_expression *); - - ir_dereference *read_dereference(s_expression *); -}; - -ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state) -{ - this->mem_ctx = state; -} - -void -_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions, - const char *src, bool scan_for_protos) -{ - ir_reader r(state); - r.read(instructions, src, scan_for_protos); -} - -void -ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos) -{ - s_expression *expr = s_expression::read_expression(mem_ctx, src); - if (expr == NULL) { - ir_read_error(NULL, "couldn't parse S-Expression."); - return; - } - - if (scan_for_protos) { - scan_for_prototypes(instructions, expr); - if (state->error) - return; - } - - read_instructions(instructions, expr, NULL); - ralloc_free(expr); - - if (debug) - validate_ir_tree(instructions); -} - -void -ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...) -{ - va_list ap; - - state->error = true; - - if (state->current_function != NULL) - ralloc_asprintf_append(&state->info_log, "In function %s:\n", - state->current_function->function_name()); - ralloc_strcat(&state->info_log, "error: "); - - va_start(ap, fmt); - ralloc_vasprintf_append(&state->info_log, fmt, ap); - va_end(ap); - ralloc_strcat(&state->info_log, "\n"); - - if (expr != NULL) { - ralloc_strcat(&state->info_log, "...in this context:\n "); - expr->print(); - ralloc_strcat(&state->info_log, "\n\n"); - } -} - -const glsl_type * -ir_reader::read_type(s_expression *expr) -{ - s_expression *s_base_type; - s_int *s_size; - - s_pattern pat[] = { "array", s_base_type, s_size }; - if (MATCH(expr, pat)) { - const glsl_type *base_type = read_type(s_base_type); - if (base_type == NULL) { - ir_read_error(NULL, "when reading base type of array type"); - return NULL; - } - - return glsl_type::get_array_instance(base_type, s_size->value()); - } - - s_symbol *type_sym = SX_AS_SYMBOL(expr); - if (type_sym == NULL) { - ir_read_error(expr, "expected "); - return NULL; - } - - const glsl_type *type = state->symbols->get_type(type_sym->value()); - if (type == NULL) - ir_read_error(expr, "invalid type: %s", type_sym->value()); - - return type; -} - - -void -ir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr) -{ - s_list *list = SX_AS_LIST(expr); - if (list == NULL) { - ir_read_error(expr, "Expected ( ...); found an atom."); - return; - } - - foreach_iter(exec_list_iterator, it, list->subexpressions) { - s_list *sub = SX_AS_LIST(it.get()); - if (sub == NULL) - continue; // not a (function ...); ignore it. - - s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head()); - if (tag == NULL || strcmp(tag->value(), "function") != 0) - continue; // not a (function ...); ignore it. - - ir_function *f = read_function(sub, true); - if (f == NULL) - return; - instructions->push_tail(f); - } -} - -ir_function * -ir_reader::read_function(s_expression *expr, bool skip_body) -{ - bool added = false; - s_symbol *name; - - s_pattern pat[] = { "function", name }; - if (!PARTIAL_MATCH(expr, pat)) { - ir_read_error(expr, "Expected (function (signature ...) ...)"); - return NULL; - } - - ir_function *f = state->symbols->get_function(name->value()); - if (f == NULL) { - f = new(mem_ctx) ir_function(name->value()); - added = state->symbols->add_function(f); - assert(added); - } - - exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator(); - it.next(); // skip "function" tag - it.next(); // skip function name - for (/* nothing */; it.has_next(); it.next()) { - s_expression *s_sig = (s_expression *) it.get(); - read_function_sig(f, s_sig, skip_body); - } - return added ? f : NULL; -} - -void -ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body) -{ - s_expression *type_expr; - s_list *paramlist; - s_list *body_list; - - s_pattern pat[] = { "signature", type_expr, paramlist, body_list }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "Expected (signature (parameters ...) " - "( ...))"); - return; - } - - const glsl_type *return_type = read_type(type_expr); - if (return_type == NULL) - return; - - s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head()); - if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) { - ir_read_error(paramlist, "Expected (parameters ...)"); - return; - } - - // Read the parameters list into a temporary place. - exec_list hir_parameters; - state->symbols->push_scope(); - - exec_list_iterator it = paramlist->subexpressions.iterator(); - for (it.next() /* skip "parameters" */; it.has_next(); it.next()) { - ir_variable *var = read_declaration((s_expression *) it.get()); - if (var == NULL) - return; - - hir_parameters.push_tail(var); - } - - ir_function_signature *sig = f->exact_matching_signature(&hir_parameters); - if (sig == NULL && skip_body) { - /* If scanning for prototypes, generate a new signature. */ - sig = new(mem_ctx) ir_function_signature(return_type); - sig->is_builtin = true; - f->add_signature(sig); - } else if (sig != NULL) { - const char *badvar = sig->qualifiers_match(&hir_parameters); - if (badvar != NULL) { - ir_read_error(expr, "function `%s' parameter `%s' qualifiers " - "don't match prototype", f->name, badvar); - return; - } - - if (sig->return_type != return_type) { - ir_read_error(expr, "function `%s' return type doesn't " - "match prototype", f->name); - return; - } - } else { - /* No prototype for this body exists - skip it. */ - state->symbols->pop_scope(); - return; - } - assert(sig != NULL); - - sig->replace_parameters(&hir_parameters); - - if (!skip_body && !body_list->subexpressions.is_empty()) { - if (sig->is_defined) { - ir_read_error(expr, "function %s redefined", f->name); - return; - } - state->current_function = sig; - read_instructions(&sig->body, body_list, NULL); - state->current_function = NULL; - sig->is_defined = true; - } - - state->symbols->pop_scope(); -} - -void -ir_reader::read_instructions(exec_list *instructions, s_expression *expr, - ir_loop *loop_ctx) -{ - // Read in a list of instructions - s_list *list = SX_AS_LIST(expr); - if (list == NULL) { - ir_read_error(expr, "Expected ( ...); found an atom."); - return; - } - - foreach_iter(exec_list_iterator, it, list->subexpressions) { - s_expression *sub = (s_expression*) it.get(); - ir_instruction *ir = read_instruction(sub, loop_ctx); - if (ir != NULL) { - /* Global variable declarations should be moved to the top, before - * any functions that might use them. Functions are added to the - * instruction stream when scanning for prototypes, so without this - * hack, they always appear before variable declarations. - */ - if (state->current_function == NULL && ir->as_variable() != NULL) - instructions->push_head(ir); - else - instructions->push_tail(ir); - } - } -} - - -ir_instruction * -ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx) -{ - s_symbol *symbol = SX_AS_SYMBOL(expr); - if (symbol != NULL) { - if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL) - return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); - if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL) - return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); - } - - s_list *list = SX_AS_LIST(expr); - if (list == NULL || list->subexpressions.is_empty()) { - ir_read_error(expr, "Invalid instruction.\n"); - return NULL; - } - - s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); - if (tag == NULL) { - ir_read_error(expr, "expected instruction tag"); - return NULL; - } - - ir_instruction *inst = NULL; - if (strcmp(tag->value(), "declare") == 0) { - inst = read_declaration(list); - } else if (strcmp(tag->value(), "assign") == 0) { - inst = read_assignment(list); - } else if (strcmp(tag->value(), "if") == 0) { - inst = read_if(list, loop_ctx); - } else if (strcmp(tag->value(), "loop") == 0) { - inst = read_loop(list); - } else if (strcmp(tag->value(), "return") == 0) { - inst = read_return(list); - } else if (strcmp(tag->value(), "function") == 0) { - inst = read_function(list, false); - } else { - inst = read_rvalue(list); - if (inst == NULL) - ir_read_error(NULL, "when reading instruction"); - } - return inst; -} - -ir_variable * -ir_reader::read_declaration(s_expression *expr) -{ - s_list *s_quals; - s_expression *s_type; - s_symbol *s_name; - - s_pattern pat[] = { "declare", s_quals, s_type, s_name }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (declare () )"); - return NULL; - } - - const glsl_type *type = read_type(s_type); - if (type == NULL) - return NULL; - - ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(), - ir_var_auto); - - foreach_iter(exec_list_iterator, it, s_quals->subexpressions) { - s_symbol *qualifier = SX_AS_SYMBOL(it.get()); - if (qualifier == NULL) { - ir_read_error(expr, "qualifier list must contain only symbols"); - return NULL; - } - - // FINISHME: Check for duplicate/conflicting qualifiers. - if (strcmp(qualifier->value(), "centroid") == 0) { - var->centroid = 1; - } else if (strcmp(qualifier->value(), "invariant") == 0) { - var->invariant = 1; - } else if (strcmp(qualifier->value(), "uniform") == 0) { - var->mode = ir_var_uniform; - } else if (strcmp(qualifier->value(), "auto") == 0) { - var->mode = ir_var_auto; - } else if (strcmp(qualifier->value(), "in") == 0) { - var->mode = ir_var_in; - } else if (strcmp(qualifier->value(), "const_in") == 0) { - var->mode = ir_var_const_in; - } else if (strcmp(qualifier->value(), "out") == 0) { - var->mode = ir_var_out; - } else if (strcmp(qualifier->value(), "inout") == 0) { - var->mode = ir_var_inout; - } else if (strcmp(qualifier->value(), "smooth") == 0) { - var->interpolation = ir_var_smooth; - } else if (strcmp(qualifier->value(), "flat") == 0) { - var->interpolation = ir_var_flat; - } else if (strcmp(qualifier->value(), "noperspective") == 0) { - var->interpolation = ir_var_noperspective; - } else { - ir_read_error(expr, "unknown qualifier: %s", qualifier->value()); - return NULL; - } - } - - // Add the variable to the symbol table - state->symbols->add_variable(var); - - return var; -} - - -ir_if * -ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) -{ - s_expression *s_cond; - s_expression *s_then; - s_expression *s_else; - - s_pattern pat[] = { "if", s_cond, s_then, s_else }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (if (...) (...))"); - return NULL; - } - - ir_rvalue *condition = read_rvalue(s_cond); - if (condition == NULL) { - ir_read_error(NULL, "when reading condition of (if ...)"); - return NULL; - } - - ir_if *iff = new(mem_ctx) ir_if(condition); - - read_instructions(&iff->then_instructions, s_then, loop_ctx); - read_instructions(&iff->else_instructions, s_else, loop_ctx); - if (state->error) { - delete iff; - iff = NULL; - } - return iff; -} - - -ir_loop * -ir_reader::read_loop(s_expression *expr) -{ - s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body; - - s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (loop " - " )"); - return NULL; - } - - // FINISHME: actually read the count/from/to fields. - - ir_loop *loop = new(mem_ctx) ir_loop; - read_instructions(&loop->body_instructions, s_body, loop); - if (state->error) { - delete loop; - loop = NULL; - } - return loop; -} - - -ir_return * -ir_reader::read_return(s_expression *expr) -{ - s_expression *s_retval; - - s_pattern pat[] = { "return", s_retval}; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (return )"); - return NULL; - } - - ir_rvalue *retval = read_rvalue(s_retval); - if (retval == NULL) { - ir_read_error(NULL, "when reading return value"); - return NULL; - } - - return new(mem_ctx) ir_return(retval); -} - - -ir_rvalue * -ir_reader::read_rvalue(s_expression *expr) -{ - s_list *list = SX_AS_LIST(expr); - if (list == NULL || list->subexpressions.is_empty()) - return NULL; - - s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); - if (tag == NULL) { - ir_read_error(expr, "expected rvalue tag"); - return NULL; - } - - ir_rvalue *rvalue = read_dereference(list); - if (rvalue != NULL || state->error) - return rvalue; - else if (strcmp(tag->value(), "swiz") == 0) { - rvalue = read_swizzle(list); - } else if (strcmp(tag->value(), "expression") == 0) { - rvalue = read_expression(list); - } else if (strcmp(tag->value(), "call") == 0) { - rvalue = read_call(list); - } else if (strcmp(tag->value(), "constant") == 0) { - rvalue = read_constant(list); - } else { - rvalue = read_texture(list); - if (rvalue == NULL && !state->error) - ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value()); - } - - return rvalue; -} - -ir_assignment * -ir_reader::read_assignment(s_expression *expr) -{ - s_expression *cond_expr = NULL; - s_expression *lhs_expr, *rhs_expr; - s_list *mask_list; - - s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr }; - s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr }; - if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) { - ir_read_error(expr, "expected (assign [] () " - " )"); - return NULL; - } - - ir_rvalue *condition = NULL; - if (cond_expr != NULL) { - condition = read_rvalue(cond_expr); - if (condition == NULL) { - ir_read_error(NULL, "when reading condition of assignment"); - return NULL; - } - } - - unsigned mask = 0; - - s_symbol *mask_symbol; - s_pattern mask_pat[] = { mask_symbol }; - if (MATCH(mask_list, mask_pat)) { - const char *mask_str = mask_symbol->value(); - unsigned mask_length = strlen(mask_str); - if (mask_length > 4) { - ir_read_error(expr, "invalid write mask: %s", mask_str); - return NULL; - } - - const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */ - - for (unsigned i = 0; i < mask_length; i++) { - if (mask_str[i] < 'w' || mask_str[i] > 'z') { - ir_read_error(expr, "write mask contains invalid character: %c", - mask_str[i]); - return NULL; - } - mask |= 1 << idx_map[mask_str[i] - 'w']; - } - } else if (!mask_list->subexpressions.is_empty()) { - ir_read_error(mask_list, "expected () or ()"); - return NULL; - } - - ir_dereference *lhs = read_dereference(lhs_expr); - if (lhs == NULL) { - ir_read_error(NULL, "when reading left-hand side of assignment"); - return NULL; - } - - ir_rvalue *rhs = read_rvalue(rhs_expr); - if (rhs == NULL) { - ir_read_error(NULL, "when reading right-hand side of assignment"); - return NULL; - } - - if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) { - ir_read_error(expr, "non-zero write mask required."); - return NULL; - } - - return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask); -} - -ir_call * -ir_reader::read_call(s_expression *expr) -{ - s_symbol *name; - s_list *params; - - s_pattern pat[] = { "call", name, params }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (call ( ...))"); - return NULL; - } - - exec_list parameters; - - foreach_iter(exec_list_iterator, it, params->subexpressions) { - s_expression *expr = (s_expression*) it.get(); - ir_rvalue *param = read_rvalue(expr); - if (param == NULL) { - ir_read_error(expr, "when reading parameter to function call"); - return NULL; - } - parameters.push_tail(param); - } - - ir_function *f = state->symbols->get_function(name->value()); - if (f == NULL) { - ir_read_error(expr, "found call to undefined function %s", - name->value()); - return NULL; - } - - ir_function_signature *callee = f->matching_signature(¶meters); - if (callee == NULL) { - ir_read_error(expr, "couldn't find matching signature for function " - "%s", name->value()); - return NULL; - } - - return new(mem_ctx) ir_call(callee, ¶meters); -} - -ir_expression * -ir_reader::read_expression(s_expression *expr) -{ - s_expression *s_type; - s_symbol *s_op; - s_expression *s_arg1; - - s_pattern pat[] = { "expression", s_type, s_op, s_arg1 }; - if (!PARTIAL_MATCH(expr, pat)) { - ir_read_error(expr, "expected (expression " - " [])"); - return NULL; - } - s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel - - const glsl_type *type = read_type(s_type); - if (type == NULL) - return NULL; - - /* Read the operator */ - ir_expression_operation op = ir_expression::get_operator(s_op->value()); - if (op == (ir_expression_operation) -1) { - ir_read_error(expr, "invalid operator: %s", s_op->value()); - return NULL; - } - - unsigned num_operands = ir_expression::get_num_operands(op); - if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) { - ir_read_error(expr, "expected (expression %s )", - s_op->value()); - return NULL; - } - - ir_rvalue *arg1 = read_rvalue(s_arg1); - ir_rvalue *arg2 = NULL; - if (arg1 == NULL) { - ir_read_error(NULL, "when reading first operand of %s", s_op->value()); - return NULL; - } - - if (num_operands == 2) { - if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) { - ir_read_error(expr, "expected (expression %s " - ")", s_op->value()); - return NULL; - } - arg2 = read_rvalue(s_arg2); - if (arg2 == NULL) { - ir_read_error(NULL, "when reading second operand of %s", - s_op->value()); - return NULL; - } - } - - return new(mem_ctx) ir_expression(op, type, arg1, arg2); -} - -ir_swizzle * -ir_reader::read_swizzle(s_expression *expr) -{ - s_symbol *swiz; - s_expression *sub; - - s_pattern pat[] = { "swiz", swiz, sub }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (swiz )"); - return NULL; - } - - if (strlen(swiz->value()) > 4) { - ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value()); - return NULL; - } - - ir_rvalue *rvalue = read_rvalue(sub); - if (rvalue == NULL) - return NULL; - - ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(), - rvalue->type->vector_elements); - if (ir == NULL) - ir_read_error(expr, "invalid swizzle"); - - return ir; -} - -ir_constant * -ir_reader::read_constant(s_expression *expr) -{ - s_expression *type_expr; - s_list *values; - - s_pattern pat[] = { "constant", type_expr, values }; - if (!MATCH(expr, pat)) { - ir_read_error(expr, "expected (constant (...))"); - return NULL; - } - - const glsl_type *type = read_type(type_expr); - if (type == NULL) - return NULL; - - if (values == NULL) { - ir_read_error(expr, "expected (constant (...))"); - return NULL; - } - - if (type->is_array()) { - unsigned elements_supplied = 0; - exec_list elements; - foreach_iter(exec_list_iterator, it, values->subexpressions) { - s_expression *elt = (s_expression *) it.get(); - ir_constant *ir_elt = read_constant(elt); - if (ir_elt == NULL) - return NULL; - elements.push_tail(ir_elt); - elements_supplied++; - } - - if (elements_supplied != type->length) { - ir_read_error(values, "expected exactly %u array elements, " - "given %u", type->length, elements_supplied); - return NULL; - } - return new(mem_ctx) ir_constant(type, &elements); - } - - const glsl_type *const base_type = type->get_base_type(); - - ir_constant_data data = { { 0 } }; - - // Read in list of values (at most 16). - int k = 0; - foreach_iter(exec_list_iterator, it, values->subexpressions) { - if (k >= 16) { - ir_read_error(values, "expected at most 16 numbers"); - return NULL; - } - - s_expression *expr = (s_expression*) it.get(); - - if (base_type->base_type == GLSL_TYPE_FLOAT) { - s_number *value = SX_AS_NUMBER(expr); - if (value == NULL) { - ir_read_error(values, "expected numbers"); - return NULL; - } - data.f[k] = value->fvalue(); - } else { - s_int *value = SX_AS_INT(expr); - if (value == NULL) { - ir_read_error(values, "expected integers"); - return NULL; - } - - switch (base_type->base_type) { - case GLSL_TYPE_UINT: { - data.u[k] = value->value(); - break; - } - case GLSL_TYPE_INT: { - data.i[k] = value->value(); - break; - } - case GLSL_TYPE_BOOL: { - data.b[k] = value->value(); - break; - } - default: - ir_read_error(values, "unsupported constant type"); - return NULL; - } - } - ++k; - } - - return new(mem_ctx) ir_constant(type, &data); -} - -ir_dereference * -ir_reader::read_dereference(s_expression *expr) -{ - s_symbol *s_var; - s_expression *s_subject; - s_expression *s_index; - s_symbol *s_field; - - s_pattern var_pat[] = { "var_ref", s_var }; - s_pattern array_pat[] = { "array_ref", s_subject, s_index }; - s_pattern record_pat[] = { "record_ref", s_subject, s_field }; - - if (MATCH(expr, var_pat)) { - ir_variable *var = state->symbols->get_variable(s_var->value()); - if (var == NULL) { - ir_read_error(expr, "undeclared variable: %s", s_var->value()); - return NULL; - } - return new(mem_ctx) ir_dereference_variable(var); - } else if (MATCH(expr, array_pat)) { - ir_rvalue *subject = read_rvalue(s_subject); - if (subject == NULL) { - ir_read_error(NULL, "when reading the subject of an array_ref"); - return NULL; - } - - ir_rvalue *idx = read_rvalue(s_index); - if (subject == NULL) { - ir_read_error(NULL, "when reading the index of an array_ref"); - return NULL; - } - return new(mem_ctx) ir_dereference_array(subject, idx); - } else if (MATCH(expr, record_pat)) { - ir_rvalue *subject = read_rvalue(s_subject); - if (subject == NULL) { - ir_read_error(NULL, "when reading the subject of a record_ref"); - return NULL; - } - return new(mem_ctx) ir_dereference_record(subject, s_field->value()); - } - return NULL; -} - -ir_texture * -ir_reader::read_texture(s_expression *expr) -{ - s_symbol *tag = NULL; - s_expression *s_type = NULL; - s_expression *s_sampler = NULL; - s_expression *s_coord = NULL; - s_expression *s_offset = NULL; - s_expression *s_proj = NULL; - s_list *s_shadow = NULL; - s_expression *s_lod = NULL; - - ir_texture_opcode op = ir_tex; /* silence warning */ - - s_pattern tex_pattern[] = - { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; - s_pattern txf_pattern[] = - { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; - s_pattern other_pattern[] = - { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; - - if (MATCH(expr, tex_pattern)) { - op = ir_tex; - } else if (MATCH(expr, txf_pattern)) { - op = ir_txf; - } else if (MATCH(expr, other_pattern)) { - op = ir_texture::get_opcode(tag->value()); - if (op == -1) - return NULL; - } else { - ir_read_error(NULL, "unexpected texture pattern"); - return NULL; - } - - ir_texture *tex = new(mem_ctx) ir_texture(op); - - // Read return type - const glsl_type *type = read_type(s_type); - if (type == NULL) { - ir_read_error(NULL, "when reading type in (%s ...)", - tex->opcode_string()); - return NULL; - } - - // Read sampler (must be a deref) - ir_dereference *sampler = read_dereference(s_sampler); - if (sampler == NULL) { - ir_read_error(NULL, "when reading sampler in (%s ...)", - tex->opcode_string()); - return NULL; - } - tex->set_sampler(sampler, type); - - // Read coordinate (any rvalue) - tex->coordinate = read_rvalue(s_coord); - if (tex->coordinate == NULL) { - ir_read_error(NULL, "when reading coordinate in (%s ...)", - tex->opcode_string()); - return NULL; - } - - // Read texel offset - either 0 or an rvalue. - s_int *si_offset = SX_AS_INT(s_offset); - if (si_offset == NULL || si_offset->value() != 0) { - tex->offset = read_rvalue(s_offset); - if (tex->offset == NULL) { - ir_read_error(s_offset, "expected 0 or an expression"); - return NULL; - } - } - - if (op != ir_txf) { - s_int *proj_as_int = SX_AS_INT(s_proj); - if (proj_as_int && proj_as_int->value() == 1) { - tex->projector = NULL; - } else { - tex->projector = read_rvalue(s_proj); - if (tex->projector == NULL) { - ir_read_error(NULL, "when reading projective divide in (%s ..)", - tex->opcode_string()); - return NULL; - } - } - - if (s_shadow->subexpressions.is_empty()) { - tex->shadow_comparitor = NULL; - } else { - tex->shadow_comparitor = read_rvalue(s_shadow); - if (tex->shadow_comparitor == NULL) { - ir_read_error(NULL, "when reading shadow comparitor in (%s ..)", - tex->opcode_string()); - return NULL; - } - } - } - - switch (op) { - case ir_txb: - tex->lod_info.bias = read_rvalue(s_lod); - if (tex->lod_info.bias == NULL) { - ir_read_error(NULL, "when reading LOD bias in (txb ...)"); - return NULL; - } - break; - case ir_txl: - case ir_txf: - tex->lod_info.lod = read_rvalue(s_lod); - if (tex->lod_info.lod == NULL) { - ir_read_error(NULL, "when reading LOD in (%s ...)", - tex->opcode_string()); - return NULL; - } - break; - case ir_txd: { - s_expression *s_dx, *s_dy; - s_pattern dxdy_pat[] = { s_dx, s_dy }; - if (!MATCH(s_lod, dxdy_pat)) { - ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)"); - return NULL; - } - tex->lod_info.grad.dPdx = read_rvalue(s_dx); - if (tex->lod_info.grad.dPdx == NULL) { - ir_read_error(NULL, "when reading dPdx in (txd ...)"); - return NULL; - } - tex->lod_info.grad.dPdy = read_rvalue(s_dy); - if (tex->lod_info.grad.dPdy == NULL) { - ir_read_error(NULL, "when reading dPdy in (txd ...)"); - return NULL; - } - break; - } - default: - // tex doesn't have any extra parameters. - break; - }; - return tex; -} +/* + * Copyright © 2010 Intel Corporation + * + * 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. + */ + +#include "ir_reader.h" +#include "glsl_parser_extras.h" +#include "glsl_types.h" +#include "s_expression.h" + +const static bool debug = false; + +class ir_reader { +public: + ir_reader(_mesa_glsl_parse_state *); + + void read(exec_list *instructions, const char *src, bool scan_for_protos); + +private: + void *mem_ctx; + _mesa_glsl_parse_state *state; + + void ir_read_error(s_expression *, const char *fmt, ...); + + const glsl_type *read_type(s_expression *); + + void scan_for_prototypes(exec_list *, s_expression *); + ir_function *read_function(s_expression *, bool skip_body); + void read_function_sig(ir_function *, s_expression *, bool skip_body); + + void read_instructions(exec_list *, s_expression *, ir_loop *); + ir_instruction *read_instruction(s_expression *, ir_loop *); + ir_variable *read_declaration(s_expression *); + ir_if *read_if(s_expression *, ir_loop *); + ir_loop *read_loop(s_expression *); + ir_return *read_return(s_expression *); + ir_rvalue *read_rvalue(s_expression *); + ir_assignment *read_assignment(s_expression *); + ir_expression *read_expression(s_expression *); + ir_call *read_call(s_expression *); + ir_swizzle *read_swizzle(s_expression *); + ir_constant *read_constant(s_expression *); + ir_texture *read_texture(s_expression *); + + ir_dereference *read_dereference(s_expression *); +}; + +ir_reader::ir_reader(_mesa_glsl_parse_state *state) : state(state) +{ + this->mem_ctx = state; +} + +void +_mesa_glsl_read_ir(_mesa_glsl_parse_state *state, exec_list *instructions, + const char *src, bool scan_for_protos) +{ + ir_reader r(state); + r.read(instructions, src, scan_for_protos); +} + +void +ir_reader::read(exec_list *instructions, const char *src, bool scan_for_protos) +{ + s_expression *expr = s_expression::read_expression(mem_ctx, src); + if (expr == NULL) { + ir_read_error(NULL, "couldn't parse S-Expression."); + return; + } + + if (scan_for_protos) { + scan_for_prototypes(instructions, expr); + if (state->error) + return; + } + + read_instructions(instructions, expr, NULL); + ralloc_free(expr); + + if (debug) + validate_ir_tree(instructions); +} + +void +ir_reader::ir_read_error(s_expression *expr, const char *fmt, ...) +{ + va_list ap; + + state->error = true; + + if (state->current_function != NULL) + ralloc_asprintf_append(&state->info_log, "In function %s:\n", + state->current_function->function_name()); + ralloc_strcat(&state->info_log, "error: "); + + va_start(ap, fmt); + ralloc_vasprintf_append(&state->info_log, fmt, ap); + va_end(ap); + ralloc_strcat(&state->info_log, "\n"); + + if (expr != NULL) { + ralloc_strcat(&state->info_log, "...in this context:\n "); + expr->print(); + ralloc_strcat(&state->info_log, "\n\n"); + } +} + +const glsl_type * +ir_reader::read_type(s_expression *expr) +{ + s_expression *s_base_type; + s_int *s_size; + + s_pattern pat[] = { "array", s_base_type, s_size }; + if (MATCH(expr, pat)) { + const glsl_type *base_type = read_type(s_base_type); + if (base_type == NULL) { + ir_read_error(NULL, "when reading base type of array type"); + return NULL; + } + + return glsl_type::get_array_instance(base_type, s_size->value()); + } + + s_symbol *type_sym = SX_AS_SYMBOL(expr); + if (type_sym == NULL) { + ir_read_error(expr, "expected "); + return NULL; + } + + const glsl_type *type = state->symbols->get_type(type_sym->value()); + if (type == NULL) + ir_read_error(expr, "invalid type: %s", type_sym->value()); + + return type; +} + + +void +ir_reader::scan_for_prototypes(exec_list *instructions, s_expression *expr) +{ + s_list *list = SX_AS_LIST(expr); + if (list == NULL) { + ir_read_error(expr, "Expected ( ...); found an atom."); + return; + } + + foreach_iter(exec_list_iterator, it, list->subexpressions) { + s_list *sub = SX_AS_LIST(it.get()); + if (sub == NULL) + continue; // not a (function ...); ignore it. + + s_symbol *tag = SX_AS_SYMBOL(sub->subexpressions.get_head()); + if (tag == NULL || strcmp(tag->value(), "function") != 0) + continue; // not a (function ...); ignore it. + + ir_function *f = read_function(sub, true); + if (f == NULL) + return; + instructions->push_tail(f); + } +} + +ir_function * +ir_reader::read_function(s_expression *expr, bool skip_body) +{ + bool added = false; + s_symbol *name; + + s_pattern pat[] = { "function", name }; + if (!PARTIAL_MATCH(expr, pat)) { + ir_read_error(expr, "Expected (function (signature ...) ...)"); + return NULL; + } + + ir_function *f = state->symbols->get_function(name->value()); + if (f == NULL) { + f = new(mem_ctx) ir_function(name->value()); + added = state->symbols->add_function(f); + assert(added); + } + + exec_list_iterator it = ((s_list *) expr)->subexpressions.iterator(); + it.next(); // skip "function" tag + it.next(); // skip function name + for (/* nothing */; it.has_next(); it.next()) { + s_expression *s_sig = (s_expression *) it.get(); + read_function_sig(f, s_sig, skip_body); + } + return added ? f : NULL; +} + +void +ir_reader::read_function_sig(ir_function *f, s_expression *expr, bool skip_body) +{ + s_expression *type_expr; + s_list *paramlist; + s_list *body_list; + + s_pattern pat[] = { "signature", type_expr, paramlist, body_list }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "Expected (signature (parameters ...) " + "( ...))"); + return; + } + + const glsl_type *return_type = read_type(type_expr); + if (return_type == NULL) + return; + + s_symbol *paramtag = SX_AS_SYMBOL(paramlist->subexpressions.get_head()); + if (paramtag == NULL || strcmp(paramtag->value(), "parameters") != 0) { + ir_read_error(paramlist, "Expected (parameters ...)"); + return; + } + + // Read the parameters list into a temporary place. + exec_list hir_parameters; + state->symbols->push_scope(); + + exec_list_iterator it = paramlist->subexpressions.iterator(); + for (it.next() /* skip "parameters" */; it.has_next(); it.next()) { + ir_variable *var = read_declaration((s_expression *) it.get()); + if (var == NULL) + return; + + hir_parameters.push_tail(var); + } + + ir_function_signature *sig = f->exact_matching_signature(&hir_parameters); + if (sig == NULL && skip_body) { + /* If scanning for prototypes, generate a new signature. */ + sig = new(mem_ctx) ir_function_signature(return_type); + sig->is_builtin = true; + f->add_signature(sig); + } else if (sig != NULL) { + const char *badvar = sig->qualifiers_match(&hir_parameters); + if (badvar != NULL) { + ir_read_error(expr, "function `%s' parameter `%s' qualifiers " + "don't match prototype", f->name, badvar); + return; + } + + if (sig->return_type != return_type) { + ir_read_error(expr, "function `%s' return type doesn't " + "match prototype", f->name); + return; + } + } else { + /* No prototype for this body exists - skip it. */ + state->symbols->pop_scope(); + return; + } + assert(sig != NULL); + + sig->replace_parameters(&hir_parameters); + + if (!skip_body && !body_list->subexpressions.is_empty()) { + if (sig->is_defined) { + ir_read_error(expr, "function %s redefined", f->name); + return; + } + state->current_function = sig; + read_instructions(&sig->body, body_list, NULL); + state->current_function = NULL; + sig->is_defined = true; + } + + state->symbols->pop_scope(); +} + +void +ir_reader::read_instructions(exec_list *instructions, s_expression *expr, + ir_loop *loop_ctx) +{ + // Read in a list of instructions + s_list *list = SX_AS_LIST(expr); + if (list == NULL) { + ir_read_error(expr, "Expected ( ...); found an atom."); + return; + } + + foreach_iter(exec_list_iterator, it, list->subexpressions) { + s_expression *sub = (s_expression*) it.get(); + ir_instruction *ir = read_instruction(sub, loop_ctx); + if (ir != NULL) { + /* Global variable declarations should be moved to the top, before + * any functions that might use them. Functions are added to the + * instruction stream when scanning for prototypes, so without this + * hack, they always appear before variable declarations. + */ + if (state->current_function == NULL && ir->as_variable() != NULL) + instructions->push_head(ir); + else + instructions->push_tail(ir); + } + } +} + + +ir_instruction * +ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx) +{ + s_symbol *symbol = SX_AS_SYMBOL(expr); + if (symbol != NULL) { + if (strcmp(symbol->value(), "break") == 0 && loop_ctx != NULL) + return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break); + if (strcmp(symbol->value(), "continue") == 0 && loop_ctx != NULL) + return new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_continue); + } + + s_list *list = SX_AS_LIST(expr); + if (list == NULL || list->subexpressions.is_empty()) { + ir_read_error(expr, "Invalid instruction.\n"); + return NULL; + } + + s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); + if (tag == NULL) { + ir_read_error(expr, "expected instruction tag"); + return NULL; + } + + ir_instruction *inst = NULL; + if (strcmp(tag->value(), "declare") == 0) { + inst = read_declaration(list); + } else if (strcmp(tag->value(), "assign") == 0) { + inst = read_assignment(list); + } else if (strcmp(tag->value(), "if") == 0) { + inst = read_if(list, loop_ctx); + } else if (strcmp(tag->value(), "loop") == 0) { + inst = read_loop(list); + } else if (strcmp(tag->value(), "return") == 0) { + inst = read_return(list); + } else if (strcmp(tag->value(), "function") == 0) { + inst = read_function(list, false); + } else { + inst = read_rvalue(list); + if (inst == NULL) + ir_read_error(NULL, "when reading instruction"); + } + return inst; +} + +ir_variable * +ir_reader::read_declaration(s_expression *expr) +{ + s_list *s_quals; + s_expression *s_type; + s_symbol *s_name; + + s_pattern pat[] = { "declare", s_quals, s_type, s_name }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (declare () )"); + return NULL; + } + + const glsl_type *type = read_type(s_type); + if (type == NULL) + return NULL; + + ir_variable *var = new(mem_ctx) ir_variable(type, s_name->value(), + ir_var_auto); + + foreach_iter(exec_list_iterator, it, s_quals->subexpressions) { + s_symbol *qualifier = SX_AS_SYMBOL(it.get()); + if (qualifier == NULL) { + ir_read_error(expr, "qualifier list must contain only symbols"); + return NULL; + } + + // FINISHME: Check for duplicate/conflicting qualifiers. + if (strcmp(qualifier->value(), "centroid") == 0) { + var->centroid = 1; + } else if (strcmp(qualifier->value(), "invariant") == 0) { + var->invariant = 1; + } else if (strcmp(qualifier->value(), "uniform") == 0) { + var->mode = ir_var_uniform; + } else if (strcmp(qualifier->value(), "auto") == 0) { + var->mode = ir_var_auto; + } else if (strcmp(qualifier->value(), "in") == 0) { + var->mode = ir_var_in; + } else if (strcmp(qualifier->value(), "const_in") == 0) { + var->mode = ir_var_const_in; + } else if (strcmp(qualifier->value(), "out") == 0) { + var->mode = ir_var_out; + } else if (strcmp(qualifier->value(), "inout") == 0) { + var->mode = ir_var_inout; + } else if (strcmp(qualifier->value(), "smooth") == 0) { + var->interpolation = ir_var_smooth; + } else if (strcmp(qualifier->value(), "flat") == 0) { + var->interpolation = ir_var_flat; + } else if (strcmp(qualifier->value(), "noperspective") == 0) { + var->interpolation = ir_var_noperspective; + } else { + ir_read_error(expr, "unknown qualifier: %s", qualifier->value()); + return NULL; + } + } + + // Add the variable to the symbol table + state->symbols->add_variable(var); + + return var; +} + + +ir_if * +ir_reader::read_if(s_expression *expr, ir_loop *loop_ctx) +{ + s_expression *s_cond; + s_expression *s_then; + s_expression *s_else; + + s_pattern pat[] = { "if", s_cond, s_then, s_else }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (if (...) (...))"); + return NULL; + } + + ir_rvalue *condition = read_rvalue(s_cond); + if (condition == NULL) { + ir_read_error(NULL, "when reading condition of (if ...)"); + return NULL; + } + + ir_if *iff = new(mem_ctx) ir_if(condition); + + read_instructions(&iff->then_instructions, s_then, loop_ctx); + read_instructions(&iff->else_instructions, s_else, loop_ctx); + if (state->error) { + delete iff; + iff = NULL; + } + return iff; +} + + +ir_loop * +ir_reader::read_loop(s_expression *expr) +{ + s_expression *s_counter, *s_from, *s_to, *s_inc, *s_body; + + s_pattern pat[] = { "loop", s_counter, s_from, s_to, s_inc, s_body }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (loop " + " )"); + return NULL; + } + + // FINISHME: actually read the count/from/to fields. + + ir_loop *loop = new(mem_ctx) ir_loop; + read_instructions(&loop->body_instructions, s_body, loop); + if (state->error) { + delete loop; + loop = NULL; + } + return loop; +} + + +ir_return * +ir_reader::read_return(s_expression *expr) +{ + s_expression *s_retval; + + s_pattern return_value_pat[] = { "return", s_retval}; + s_pattern return_void_pat[] = { "return" }; + if (MATCH(expr, return_value_pat)) { + ir_rvalue *retval = read_rvalue(s_retval); + if (retval == NULL) { + ir_read_error(NULL, "when reading return value"); + return NULL; + } + return new(mem_ctx) ir_return(retval); + } else if (MATCH(expr, return_void_pat)) { + return new(mem_ctx) ir_return; + } else { + ir_read_error(expr, "expected (return ) or (return)"); + return NULL; + } +} + + +ir_rvalue * +ir_reader::read_rvalue(s_expression *expr) +{ + s_list *list = SX_AS_LIST(expr); + if (list == NULL || list->subexpressions.is_empty()) + return NULL; + + s_symbol *tag = SX_AS_SYMBOL(list->subexpressions.get_head()); + if (tag == NULL) { + ir_read_error(expr, "expected rvalue tag"); + return NULL; + } + + ir_rvalue *rvalue = read_dereference(list); + if (rvalue != NULL || state->error) + return rvalue; + else if (strcmp(tag->value(), "swiz") == 0) { + rvalue = read_swizzle(list); + } else if (strcmp(tag->value(), "expression") == 0) { + rvalue = read_expression(list); + } else if (strcmp(tag->value(), "call") == 0) { + rvalue = read_call(list); + } else if (strcmp(tag->value(), "constant") == 0) { + rvalue = read_constant(list); + } else { + rvalue = read_texture(list); + if (rvalue == NULL && !state->error) + ir_read_error(expr, "unrecognized rvalue tag: %s", tag->value()); + } + + return rvalue; +} + +ir_assignment * +ir_reader::read_assignment(s_expression *expr) +{ + s_expression *cond_expr = NULL; + s_expression *lhs_expr, *rhs_expr; + s_list *mask_list; + + s_pattern pat4[] = { "assign", mask_list, lhs_expr, rhs_expr }; + s_pattern pat5[] = { "assign", cond_expr, mask_list, lhs_expr, rhs_expr }; + if (!MATCH(expr, pat4) && !MATCH(expr, pat5)) { + ir_read_error(expr, "expected (assign [] () " + " )"); + return NULL; + } + + ir_rvalue *condition = NULL; + if (cond_expr != NULL) { + condition = read_rvalue(cond_expr); + if (condition == NULL) { + ir_read_error(NULL, "when reading condition of assignment"); + return NULL; + } + } + + unsigned mask = 0; + + s_symbol *mask_symbol; + s_pattern mask_pat[] = { mask_symbol }; + if (MATCH(mask_list, mask_pat)) { + const char *mask_str = mask_symbol->value(); + unsigned mask_length = strlen(mask_str); + if (mask_length > 4) { + ir_read_error(expr, "invalid write mask: %s", mask_str); + return NULL; + } + + const unsigned idx_map[] = { 3, 0, 1, 2 }; /* w=bit 3, x=0, y=1, z=2 */ + + for (unsigned i = 0; i < mask_length; i++) { + if (mask_str[i] < 'w' || mask_str[i] > 'z') { + ir_read_error(expr, "write mask contains invalid character: %c", + mask_str[i]); + return NULL; + } + mask |= 1 << idx_map[mask_str[i] - 'w']; + } + } else if (!mask_list->subexpressions.is_empty()) { + ir_read_error(mask_list, "expected () or ()"); + return NULL; + } + + ir_dereference *lhs = read_dereference(lhs_expr); + if (lhs == NULL) { + ir_read_error(NULL, "when reading left-hand side of assignment"); + return NULL; + } + + ir_rvalue *rhs = read_rvalue(rhs_expr); + if (rhs == NULL) { + ir_read_error(NULL, "when reading right-hand side of assignment"); + return NULL; + } + + if (mask == 0 && (lhs->type->is_vector() || lhs->type->is_scalar())) { + ir_read_error(expr, "non-zero write mask required."); + return NULL; + } + + return new(mem_ctx) ir_assignment(lhs, rhs, condition, mask); +} + +ir_call * +ir_reader::read_call(s_expression *expr) +{ + s_symbol *name; + s_list *params; + + s_pattern pat[] = { "call", name, params }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (call ( ...))"); + return NULL; + } + + exec_list parameters; + + foreach_iter(exec_list_iterator, it, params->subexpressions) { + s_expression *expr = (s_expression*) it.get(); + ir_rvalue *param = read_rvalue(expr); + if (param == NULL) { + ir_read_error(expr, "when reading parameter to function call"); + return NULL; + } + parameters.push_tail(param); + } + + ir_function *f = state->symbols->get_function(name->value()); + if (f == NULL) { + ir_read_error(expr, "found call to undefined function %s", + name->value()); + return NULL; + } + + ir_function_signature *callee = f->matching_signature(¶meters); + if (callee == NULL) { + ir_read_error(expr, "couldn't find matching signature for function " + "%s", name->value()); + return NULL; + } + + return new(mem_ctx) ir_call(callee, ¶meters); +} + +ir_expression * +ir_reader::read_expression(s_expression *expr) +{ + s_expression *s_type; + s_symbol *s_op; + s_expression *s_arg1; + + s_pattern pat[] = { "expression", s_type, s_op, s_arg1 }; + if (!PARTIAL_MATCH(expr, pat)) { + ir_read_error(expr, "expected (expression " + " [])"); + return NULL; + } + s_expression *s_arg2 = (s_expression *) s_arg1->next; // may be tail sentinel + + const glsl_type *type = read_type(s_type); + if (type == NULL) + return NULL; + + /* Read the operator */ + ir_expression_operation op = ir_expression::get_operator(s_op->value()); + if (op == (ir_expression_operation) -1) { + ir_read_error(expr, "invalid operator: %s", s_op->value()); + return NULL; + } + + unsigned num_operands = ir_expression::get_num_operands(op); + if (num_operands == 1 && !s_arg1->next->is_tail_sentinel()) { + ir_read_error(expr, "expected (expression %s )", + s_op->value()); + return NULL; + } + + ir_rvalue *arg1 = read_rvalue(s_arg1); + ir_rvalue *arg2 = NULL; + if (arg1 == NULL) { + ir_read_error(NULL, "when reading first operand of %s", s_op->value()); + return NULL; + } + + if (num_operands == 2) { + if (s_arg2->is_tail_sentinel() || !s_arg2->next->is_tail_sentinel()) { + ir_read_error(expr, "expected (expression %s " + ")", s_op->value()); + return NULL; + } + arg2 = read_rvalue(s_arg2); + if (arg2 == NULL) { + ir_read_error(NULL, "when reading second operand of %s", + s_op->value()); + return NULL; + } + } + + return new(mem_ctx) ir_expression(op, type, arg1, arg2); +} + +ir_swizzle * +ir_reader::read_swizzle(s_expression *expr) +{ + s_symbol *swiz; + s_expression *sub; + + s_pattern pat[] = { "swiz", swiz, sub }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (swiz )"); + return NULL; + } + + if (strlen(swiz->value()) > 4) { + ir_read_error(expr, "expected a valid swizzle; found %s", swiz->value()); + return NULL; + } + + ir_rvalue *rvalue = read_rvalue(sub); + if (rvalue == NULL) + return NULL; + + ir_swizzle *ir = ir_swizzle::create(rvalue, swiz->value(), + rvalue->type->vector_elements); + if (ir == NULL) + ir_read_error(expr, "invalid swizzle"); + + return ir; +} + +ir_constant * +ir_reader::read_constant(s_expression *expr) +{ + s_expression *type_expr; + s_list *values; + + s_pattern pat[] = { "constant", type_expr, values }; + if (!MATCH(expr, pat)) { + ir_read_error(expr, "expected (constant (...))"); + return NULL; + } + + const glsl_type *type = read_type(type_expr); + if (type == NULL) + return NULL; + + if (values == NULL) { + ir_read_error(expr, "expected (constant (...))"); + return NULL; + } + + if (type->is_array()) { + unsigned elements_supplied = 0; + exec_list elements; + foreach_iter(exec_list_iterator, it, values->subexpressions) { + s_expression *elt = (s_expression *) it.get(); + ir_constant *ir_elt = read_constant(elt); + if (ir_elt == NULL) + return NULL; + elements.push_tail(ir_elt); + elements_supplied++; + } + + if (elements_supplied != type->length) { + ir_read_error(values, "expected exactly %u array elements, " + "given %u", type->length, elements_supplied); + return NULL; + } + return new(mem_ctx) ir_constant(type, &elements); + } + + const glsl_type *const base_type = type->get_base_type(); + + ir_constant_data data = { { 0 } }; + + // Read in list of values (at most 16). + int k = 0; + foreach_iter(exec_list_iterator, it, values->subexpressions) { + if (k >= 16) { + ir_read_error(values, "expected at most 16 numbers"); + return NULL; + } + + s_expression *expr = (s_expression*) it.get(); + + if (base_type->base_type == GLSL_TYPE_FLOAT) { + s_number *value = SX_AS_NUMBER(expr); + if (value == NULL) { + ir_read_error(values, "expected numbers"); + return NULL; + } + data.f[k] = value->fvalue(); + } else { + s_int *value = SX_AS_INT(expr); + if (value == NULL) { + ir_read_error(values, "expected integers"); + return NULL; + } + + switch (base_type->base_type) { + case GLSL_TYPE_UINT: { + data.u[k] = value->value(); + break; + } + case GLSL_TYPE_INT: { + data.i[k] = value->value(); + break; + } + case GLSL_TYPE_BOOL: { + data.b[k] = value->value(); + break; + } + default: + ir_read_error(values, "unsupported constant type"); + return NULL; + } + } + ++k; + } + + return new(mem_ctx) ir_constant(type, &data); +} + +ir_dereference * +ir_reader::read_dereference(s_expression *expr) +{ + s_symbol *s_var; + s_expression *s_subject; + s_expression *s_index; + s_symbol *s_field; + + s_pattern var_pat[] = { "var_ref", s_var }; + s_pattern array_pat[] = { "array_ref", s_subject, s_index }; + s_pattern record_pat[] = { "record_ref", s_subject, s_field }; + + if (MATCH(expr, var_pat)) { + ir_variable *var = state->symbols->get_variable(s_var->value()); + if (var == NULL) { + ir_read_error(expr, "undeclared variable: %s", s_var->value()); + return NULL; + } + return new(mem_ctx) ir_dereference_variable(var); + } else if (MATCH(expr, array_pat)) { + ir_rvalue *subject = read_rvalue(s_subject); + if (subject == NULL) { + ir_read_error(NULL, "when reading the subject of an array_ref"); + return NULL; + } + + ir_rvalue *idx = read_rvalue(s_index); + if (subject == NULL) { + ir_read_error(NULL, "when reading the index of an array_ref"); + return NULL; + } + return new(mem_ctx) ir_dereference_array(subject, idx); + } else if (MATCH(expr, record_pat)) { + ir_rvalue *subject = read_rvalue(s_subject); + if (subject == NULL) { + ir_read_error(NULL, "when reading the subject of a record_ref"); + return NULL; + } + return new(mem_ctx) ir_dereference_record(subject, s_field->value()); + } + return NULL; +} + +ir_texture * +ir_reader::read_texture(s_expression *expr) +{ + s_symbol *tag = NULL; + s_expression *s_type = NULL; + s_expression *s_sampler = NULL; + s_expression *s_coord = NULL; + s_expression *s_offset = NULL; + s_expression *s_proj = NULL; + s_list *s_shadow = NULL; + s_expression *s_lod = NULL; + + ir_texture_opcode op = ir_tex; /* silence warning */ + + s_pattern tex_pattern[] = + { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; + s_pattern txf_pattern[] = + { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; + s_pattern other_pattern[] = + { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; + + if (MATCH(expr, tex_pattern)) { + op = ir_tex; + } else if (MATCH(expr, txf_pattern)) { + op = ir_txf; + } else if (MATCH(expr, other_pattern)) { + op = ir_texture::get_opcode(tag->value()); + if (op == -1) + return NULL; + } else { + ir_read_error(NULL, "unexpected texture pattern"); + return NULL; + } + + ir_texture *tex = new(mem_ctx) ir_texture(op); + + // Read return type + const glsl_type *type = read_type(s_type); + if (type == NULL) { + ir_read_error(NULL, "when reading type in (%s ...)", + tex->opcode_string()); + return NULL; + } + + // Read sampler (must be a deref) + ir_dereference *sampler = read_dereference(s_sampler); + if (sampler == NULL) { + ir_read_error(NULL, "when reading sampler in (%s ...)", + tex->opcode_string()); + return NULL; + } + tex->set_sampler(sampler, type); + + // Read coordinate (any rvalue) + tex->coordinate = read_rvalue(s_coord); + if (tex->coordinate == NULL) { + ir_read_error(NULL, "when reading coordinate in (%s ...)", + tex->opcode_string()); + return NULL; + } + + // Read texel offset - either 0 or an rvalue. + s_int *si_offset = SX_AS_INT(s_offset); + if (si_offset == NULL || si_offset->value() != 0) { + tex->offset = read_rvalue(s_offset); + if (tex->offset == NULL) { + ir_read_error(s_offset, "expected 0 or an expression"); + return NULL; + } + } + + if (op != ir_txf) { + s_int *proj_as_int = SX_AS_INT(s_proj); + if (proj_as_int && proj_as_int->value() == 1) { + tex->projector = NULL; + } else { + tex->projector = read_rvalue(s_proj); + if (tex->projector == NULL) { + ir_read_error(NULL, "when reading projective divide in (%s ..)", + tex->opcode_string()); + return NULL; + } + } + + if (s_shadow->subexpressions.is_empty()) { + tex->shadow_comparitor = NULL; + } else { + tex->shadow_comparitor = read_rvalue(s_shadow); + if (tex->shadow_comparitor == NULL) { + ir_read_error(NULL, "when reading shadow comparitor in (%s ..)", + tex->opcode_string()); + return NULL; + } + } + } + + switch (op) { + case ir_txb: + tex->lod_info.bias = read_rvalue(s_lod); + if (tex->lod_info.bias == NULL) { + ir_read_error(NULL, "when reading LOD bias in (txb ...)"); + return NULL; + } + break; + case ir_txl: + case ir_txf: + tex->lod_info.lod = read_rvalue(s_lod); + if (tex->lod_info.lod == NULL) { + ir_read_error(NULL, "when reading LOD in (%s ...)", + tex->opcode_string()); + return NULL; + } + break; + case ir_txd: { + s_expression *s_dx, *s_dy; + s_pattern dxdy_pat[] = { s_dx, s_dy }; + if (!MATCH(s_lod, dxdy_pat)) { + ir_read_error(s_lod, "expected (dPdx dPdy) in (txd ...)"); + return NULL; + } + tex->lod_info.grad.dPdx = read_rvalue(s_dx); + if (tex->lod_info.grad.dPdx == NULL) { + ir_read_error(NULL, "when reading dPdx in (txd ...)"); + return NULL; + } + tex->lod_info.grad.dPdy = read_rvalue(s_dy); + if (tex->lod_info.grad.dPdy == NULL) { + ir_read_error(NULL, "when reading dPdy in (txd ...)"); + return NULL; + } + break; + } + default: + // tex doesn't have any extra parameters. + break; + }; + return tex; +} diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 265da84e5..34b64837a 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1248,7 +1248,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, */ const int generic_base = (target_index == MESA_SHADER_VERTEX) - ? VERT_ATTRIB_GENERIC0 : FRAG_RESULT_DATA0; + ? (int) VERT_ATTRIB_GENERIC0 : (int) FRAG_RESULT_DATA0; const enum ir_variable_mode direction = (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out; diff --git a/mesalib/src/glsl/lower_jumps.cpp b/mesalib/src/glsl/lower_jumps.cpp index 17be39f5b..61874990a 100644 --- a/mesalib/src/glsl/lower_jumps.cpp +++ b/mesalib/src/glsl/lower_jumps.cpp @@ -1,570 +1,1010 @@ -/* - * Copyright © 2010 Luca Barbieri - * - * 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. - */ - -/** - * \file lower_jumps.cpp - * - * This pass lowers jumps (break, continue, and return) to if/else structures. - * - * It can be asked to: - * 1. Pull jumps out of ifs where possible - * 2. Remove all "continue"s, replacing them with an "execute flag" - * 3. Replace all "break" with a single conditional one at the end of the loop - * 4. Replace all "return"s with a single return at the end of the function, - * for the main function and/or other functions - * - * Applying this pass gives several benefits: - * 1. All functions can be inlined. - * 2. nv40 and other pre-DX10 chips without "continue" can be supported - * 3. nv30 and other pre-DX10 chips with no control flow at all are better - * supported - * - * Continues are lowered by adding a per-loop "execute flag", initialized to - * true, that when cleared inhibits all execution until the end of the loop. - * - * Breaks are lowered to continues, plus setting a "break flag" that is checked - * at the end of the loop, and trigger the unique "break". - * - * Returns are lowered to breaks/continues, plus adding a "return flag" that - * causes loops to break again out of their enclosing loops until all the - * loops are exited: then the "execute flag" logic will ignore everything - * until the end of the function. - * - * Note that "continue" and "return" can also be implemented by adding - * a dummy loop and using break. - * However, this is bad for hardware with limited nesting depth, and - * prevents further optimization, and thus is not currently performed. - */ - -#include "glsl_types.h" -#include -#include "ir.h" - -enum jump_strength -{ - strength_none, - strength_always_clears_execute_flag, - strength_continue, - strength_break, - strength_return -}; - -struct block_record -{ - /* minimum jump strength (of lowered IR, not pre-lowering IR) - * - * If the block ends with a jump, must be the strength of the jump. - * Otherwise, the jump would be dead and have been deleted before) - * - * If the block doesn't end with a jump, it can be different than strength_none if all paths before it lead to some jump - * (e.g. an if with a return in one branch, and a break in the other, while not lowering them) - * Note that identical jumps are usually unified though. - */ - jump_strength min_strength; - - /* can anything clear the execute flag? */ - bool may_clear_execute_flag; - - block_record() - { - this->min_strength = strength_none; - this->may_clear_execute_flag = false; - } -}; - -struct loop_record -{ - ir_function_signature* signature; - ir_loop* loop; - - /* used to avoid lowering the break used to represent lowered breaks */ - unsigned nesting_depth; - bool in_if_at_the_end_of_the_loop; - - bool may_set_return_flag; - - ir_variable* break_flag; - ir_variable* execute_flag; /* cleared to emulate continue */ - - loop_record(ir_function_signature* p_signature = 0, ir_loop* p_loop = 0) - { - this->signature = p_signature; - this->loop = p_loop; - this->nesting_depth = 0; - this->in_if_at_the_end_of_the_loop = false; - this->may_set_return_flag = false; - this->break_flag = 0; - this->execute_flag = 0; - } - - ir_variable* get_execute_flag() - { - /* also supported for the "function loop" */ - if(!this->execute_flag) { - exec_list& list = this->loop ? this->loop->body_instructions : signature->body; - this->execute_flag = new(this->signature) ir_variable(glsl_type::bool_type, "execute_flag", ir_var_temporary); - list.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(execute_flag), new(this->signature) ir_constant(true), 0)); - list.push_head(this->execute_flag); - } - return this->execute_flag; - } - - ir_variable* get_break_flag() - { - assert(this->loop); - if(!this->break_flag) { - this->break_flag = new(this->signature) ir_variable(glsl_type::bool_type, "break_flag", ir_var_temporary); - this->loop->insert_before(this->break_flag); - this->loop->insert_before(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(break_flag), new(this->signature) ir_constant(false), 0)); - } - return this->break_flag; - } -}; - -struct function_record -{ - ir_function_signature* signature; - ir_variable* return_flag; /* used to break out of all loops and then jump to the return instruction */ - ir_variable* return_value; - bool is_main; - unsigned nesting_depth; - - function_record(ir_function_signature* p_signature = 0) - { - this->signature = p_signature; - this->return_flag = 0; - this->return_value = 0; - this->nesting_depth = 0; - this->is_main = this->signature && (strcmp(this->signature->function_name(), "main") == 0); - } - - ir_variable* get_return_flag() - { - if(!this->return_flag) { - this->return_flag = new(this->signature) ir_variable(glsl_type::bool_type, "return_flag", ir_var_temporary); - this->signature->body.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(return_flag), new(this->signature) ir_constant(false), 0)); - this->signature->body.push_head(this->return_flag); - } - return this->return_flag; - } - - ir_variable* get_return_value() - { - if(!this->return_value) { - assert(!this->signature->return_type->is_void()); - return_value = new(this->signature) ir_variable(this->signature->return_type, "return_value", ir_var_temporary); - this->signature->body.push_head(this->return_value); - } - return this->return_value; - } -}; - -struct ir_lower_jumps_visitor : public ir_control_flow_visitor { - bool progress; - - struct function_record function; - struct loop_record loop; - struct block_record block; - - bool pull_out_jumps; - bool lower_continue; - bool lower_break; - bool lower_sub_return; - bool lower_main_return; - - ir_lower_jumps_visitor() - { - this->progress = false; - } - - void truncate_after_instruction(exec_node *ir) - { - if (!ir) - return; - - while (!ir->get_next()->is_tail_sentinel()) { - ((ir_instruction *)ir->get_next())->remove(); - this->progress = true; - } - } - - void move_outer_block_inside(ir_instruction *ir, exec_list *inner_block) - { - while (!ir->get_next()->is_tail_sentinel()) { - ir_instruction *move_ir = (ir_instruction *)ir->get_next(); - - move_ir->remove(); - inner_block->push_tail(move_ir); - } - } - - virtual void visit(class ir_loop_jump * ir) - { - truncate_after_instruction(ir); - this->block.min_strength = ir->is_break() ? strength_break : strength_continue; - } - - virtual void visit(class ir_return * ir) - { - truncate_after_instruction(ir); - this->block.min_strength = strength_return; - } - - virtual void visit(class ir_discard * ir) - { - } - - enum jump_strength get_jump_strength(ir_instruction* ir) - { - if(!ir) - return strength_none; - else if(ir->ir_type == ir_type_loop_jump) { - if(((ir_loop_jump*)ir)->is_break()) - return strength_break; - else - return strength_continue; - } else if(ir->ir_type == ir_type_return) - return strength_return; - else - return strength_none; - } - - bool should_lower_jump(ir_jump* ir) - { - unsigned strength = get_jump_strength(ir); - bool lower; - switch(strength) - { - case strength_none: - lower = false; /* don't change this, code relies on it */ - break; - case strength_continue: - lower = lower_continue; - break; - case strength_break: - assert(this->loop.loop); - /* never lower "canonical break" */ - if(ir->get_next()->is_tail_sentinel() && (this->loop.nesting_depth == 0 - || (this->loop.nesting_depth == 1 && this->loop.in_if_at_the_end_of_the_loop))) - lower = false; - else - lower = lower_break; - break; - case strength_return: - /* never lower return at the end of a this->function */ - if(this->function.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) - lower = false; - else if (this->function.is_main) - lower = lower_main_return; - else - lower = lower_sub_return; - break; - } - return lower; - } - - block_record visit_block(exec_list* list) - { - block_record saved_block = this->block; - this->block = block_record(); - visit_exec_list(list, this); - block_record ret = this->block; - this->block = saved_block; - return ret; - } - - virtual void visit(ir_if *ir) - { - if(this->loop.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) - this->loop.in_if_at_the_end_of_the_loop = true; - - ++this->function.nesting_depth; - ++this->loop.nesting_depth; - - block_record block_records[2]; - ir_jump* jumps[2]; - - block_records[0] = visit_block(&ir->then_instructions); - block_records[1] = visit_block(&ir->else_instructions); - -retry: /* we get here if we put code after the if inside a branch */ - for(unsigned i = 0; i < 2; ++i) { - exec_list& list = i ? ir->else_instructions : ir->then_instructions; - jumps[i] = 0; - if(!list.is_empty() && get_jump_strength((ir_instruction*)list.get_tail())) - jumps[i] = (ir_jump*)list.get_tail(); - } - - for(;;) { - jump_strength jump_strengths[2]; - - for(unsigned i = 0; i < 2; ++i) { - if(jumps[i]) { - jump_strengths[i] = block_records[i].min_strength; - assert(jump_strengths[i] == get_jump_strength(jumps[i])); - } else - jump_strengths[i] = strength_none; - } - - /* move both jumps out if possible */ - if(pull_out_jumps && jump_strengths[0] == jump_strengths[1]) { - bool unify = true; - if(jump_strengths[0] == strength_continue) - ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_continue)); - else if(jump_strengths[0] == strength_break) - ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); - /* FINISHME: unify returns with identical expressions */ - else if(jump_strengths[0] == strength_return && this->function.signature->return_type->is_void()) - ir->insert_after(new(ir) ir_return(NULL)); - else - unify = false; - - if(unify) { - jumps[0]->remove(); - jumps[1]->remove(); - this->progress = true; - - jumps[0] = 0; - jumps[1] = 0; - block_records[0].min_strength = strength_none; - block_records[1].min_strength = strength_none; - break; - } - } - - /* lower a jump: if both need to lowered, start with the strongest one, so that - * we might later unify the lowered version with the other one - */ - bool should_lower[2]; - for(unsigned i = 0; i < 2; ++i) - should_lower[i] = should_lower_jump(jumps[i]); - - int lower; - if(should_lower[1] && should_lower[0]) - lower = jump_strengths[1] > jump_strengths[0]; - else if(should_lower[0]) - lower = 0; - else if(should_lower[1]) - lower = 1; - else - break; - - if(jump_strengths[lower] == strength_return) { - ir_variable* return_flag = this->function.get_return_flag(); - if(!this->function.signature->return_type->is_void()) { - ir_variable* return_value = this->function.get_return_value(); - jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(return_value), ((ir_return*)jumps[lower])->value, NULL)); - } - jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(return_flag), new (ir) ir_constant(true), NULL)); - this->loop.may_set_return_flag = true; - if(this->loop.loop) { - ir_loop_jump* lowered = 0; - lowered = new(ir) ir_loop_jump(ir_loop_jump::jump_break); - block_records[lower].min_strength = strength_break; - jumps[lower]->replace_with(lowered); - jumps[lower] = lowered; - } else - goto lower_continue; - this->progress = true; - } else if(jump_strengths[lower] == strength_break) { - /* We can't lower to an actual continue because that would execute the increment. - * - * In the lowered code, we instead put the break check between the this->loop body and the increment, - * which is impossible with a real continue as defined by the GLSL IR currently. - * - * Smarter options (such as undoing the increment) are possible but it's not worth implementing them, - * because if break is lowered, continue is almost surely lowered too. - */ - jumps[lower]->insert_before(new(ir) ir_assignment(new (ir) ir_dereference_variable(this->loop.get_break_flag()), new (ir) ir_constant(true), 0)); - goto lower_continue; - } else if(jump_strengths[lower] == strength_continue) { -lower_continue: - ir_variable* execute_flag = this->loop.get_execute_flag(); - jumps[lower]->replace_with(new(ir) ir_assignment(new (ir) ir_dereference_variable(execute_flag), new (ir) ir_constant(false), 0)); - jumps[lower] = 0; - block_records[lower].min_strength = strength_always_clears_execute_flag; - block_records[lower].may_clear_execute_flag = true; - this->progress = true; - break; - } - } - - /* move out a jump out if possible */ - if(pull_out_jumps) { - int move_out = -1; - if(jumps[0] && block_records[1].min_strength >= strength_continue) - move_out = 0; - else if(jumps[1] && block_records[0].min_strength >= strength_continue) - move_out = 1; - - if(move_out >= 0) - { - jumps[move_out]->remove(); - ir->insert_after(jumps[move_out]); - jumps[move_out] = 0; - block_records[move_out].min_strength = strength_none; - this->progress = true; - } - } - - if(block_records[0].min_strength < block_records[1].min_strength) - this->block.min_strength = block_records[0].min_strength; - else - this->block.min_strength = block_records[1].min_strength; - this->block.may_clear_execute_flag = this->block.may_clear_execute_flag || block_records[0].may_clear_execute_flag || block_records[1].may_clear_execute_flag; - - if(this->block.min_strength) - truncate_after_instruction(ir); - else if(this->block.may_clear_execute_flag) - { - int move_into = -1; - if(block_records[0].min_strength && !block_records[1].may_clear_execute_flag) - move_into = 1; - else if(block_records[1].min_strength && !block_records[0].may_clear_execute_flag) - move_into = 0; - - if(move_into >= 0) { - assert(!block_records[move_into].min_strength && !block_records[move_into].may_clear_execute_flag); /* otherwise, we just truncated */ - - exec_list* list = move_into ? &ir->else_instructions : &ir->then_instructions; - exec_node* next = ir->get_next(); - if(!next->is_tail_sentinel()) { - move_outer_block_inside(ir, list); - - exec_list list; - list.head = next; - block_records[move_into] = visit_block(&list); - - this->progress = true; - goto retry; - } - } else { - ir_instruction* ir_after; - for(ir_after = (ir_instruction*)ir->get_next(); !ir_after->is_tail_sentinel();) - { - ir_if* ir_if = ir_after->as_if(); - if(ir_if && ir_if->else_instructions.is_empty()) { - ir_dereference_variable* ir_if_cond_deref = ir_if->condition->as_dereference_variable(); - if(ir_if_cond_deref && ir_if_cond_deref->var == this->loop.execute_flag) { - ir_instruction* ir_next = (ir_instruction*)ir_after->get_next(); - ir_after->insert_before(&ir_if->then_instructions); - ir_after->remove(); - ir_after = ir_next; - continue; - } - } - ir_after = (ir_instruction*)ir_after->get_next(); - - /* only set this if we find any unprotected instruction */ - this->progress = true; - } - - if(!ir->get_next()->is_tail_sentinel()) { - assert(this->loop.execute_flag); - ir_if* if_execute = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.execute_flag)); - move_outer_block_inside(ir, &if_execute->then_instructions); - ir->insert_after(if_execute); - } - } - } - --this->loop.nesting_depth; - --this->function.nesting_depth; - } - - virtual void visit(ir_loop *ir) - { - ++this->function.nesting_depth; - loop_record saved_loop = this->loop; - this->loop = loop_record(this->function.signature, ir); - - block_record body = visit_block(&ir->body_instructions); - - if(body.min_strength >= strength_break) { - /* FINISHME: turn the this->loop into an if, or replace it with its body */ - } - - if(this->loop.break_flag) { - ir_if* break_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.break_flag)); - break_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); - ir->body_instructions.push_tail(break_if); - } - - if(this->loop.may_set_return_flag) { - assert(this->function.return_flag); - ir_if* return_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->function.return_flag)); - saved_loop.may_set_return_flag = true; - if(saved_loop.loop) - return_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); - else - move_outer_block_inside(ir, &return_if->else_instructions); - ir->insert_after(return_if); - } - - this->loop = saved_loop; - --this->function.nesting_depth; - } - - virtual void visit(ir_function_signature *ir) - { - /* these are not strictly necessary */ - assert(!this->function.signature); - assert(!this->loop.loop); - - function_record saved_function = this->function; - loop_record saved_loop = this->loop; - this->function = function_record(ir); - this->loop = loop_record(ir); - - assert(!this->loop.loop); - visit_block(&ir->body); - - if(this->function.return_value) - ir->body.push_tail(new(ir) ir_return(new (ir) ir_dereference_variable(this->function.return_value))); - - this->loop = saved_loop; - this->function = saved_function; - } - - virtual void visit(class ir_function * ir) - { - visit_block(&ir->signatures); - } -}; - -bool -do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_return, bool lower_main_return, bool lower_continue, bool lower_break) -{ - ir_lower_jumps_visitor v; - v.pull_out_jumps = pull_out_jumps; - v.lower_continue = lower_continue; - v.lower_break = lower_break; - v.lower_sub_return = lower_sub_return; - v.lower_main_return = lower_main_return; - - do { - v.progress = false; - visit_exec_list(instructions, &v); - } while (v.progress); - - return v.progress; -} +/* + * Copyright © 2010 Luca Barbieri + * + * 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. + */ + +/** + * \file lower_jumps.cpp + * + * This pass lowers jumps (break, continue, and return) to if/else structures. + * + * It can be asked to: + * 1. Pull jumps out of ifs where possible + * 2. Remove all "continue"s, replacing them with an "execute flag" + * 3. Replace all "break" with a single conditional one at the end of the loop + * 4. Replace all "return"s with a single return at the end of the function, + * for the main function and/or other functions + * + * Applying this pass gives several benefits: + * 1. All functions can be inlined. + * 2. nv40 and other pre-DX10 chips without "continue" can be supported + * 3. nv30 and other pre-DX10 chips with no control flow at all are better + * supported + * + * Continues are lowered by adding a per-loop "execute flag", initialized to + * true, that when cleared inhibits all execution until the end of the loop. + * + * Breaks are lowered to continues, plus setting a "break flag" that is checked + * at the end of the loop, and trigger the unique "break". + * + * Returns are lowered to breaks/continues, plus adding a "return flag" that + * causes loops to break again out of their enclosing loops until all the + * loops are exited: then the "execute flag" logic will ignore everything + * until the end of the function. + * + * Note that "continue" and "return" can also be implemented by adding + * a dummy loop and using break. + * However, this is bad for hardware with limited nesting depth, and + * prevents further optimization, and thus is not currently performed. + */ + +#include "glsl_types.h" +#include +#include "ir.h" + +/** + * Enum recording the result of analyzing how control flow might exit + * an IR node. + * + * Each possible value of jump_strength indicates a strictly stronger + * guarantee on control flow than the previous value. + * + * The ordering of strengths roughly reflects the way jumps are + * lowered: jumps with higher strength tend to be lowered to jumps of + * lower strength. Accordingly, strength is used as a heuristic to + * determine which lowering to perform first. + * + * This enum is also used by get_jump_strength() to categorize + * instructions as either break, continue, return, or other. When + * used in this fashion, strength_always_clears_execute_flag is not + * used. + * + * The control flow analysis made by this optimization pass makes two + * simplifying assumptions: + * + * - It ignores discard instructions, since they are lowered by a + * separate pass (lower_discard.cpp). + * + * - It assumes it is always possible for control to flow from a loop + * to the instruction immediately following it. Technically, this + * is not true (since all execution paths through the loop might + * jump back to the top, or return from the function). + * + * Both of these simplifying assumtions are safe, since they can never + * cause reachable code to be incorrectly classified as unreachable; + * they can only do the opposite. + */ +enum jump_strength +{ + /** + * Analysis has produced no guarantee on how control flow might + * exit this IR node. It might fall out the bottom (with or + * without clearing the execute flag, if present), or it might + * continue to the top of the innermost enclosing loop, break out + * of it, or return from the function. + */ + strength_none, + + /** + * The only way control can fall out the bottom of this node is + * through a code path that clears the execute flag. It might also + * continue to the top of the innermost enclosing loop, break out + * of it, or return from the function. + */ + strength_always_clears_execute_flag, + + /** + * Control cannot fall out the bottom of this node. It might + * continue to the top of the innermost enclosing loop, break out + * of it, or return from the function. + */ + strength_continue, + + /** + * Control cannot fall out the bottom of this node, or continue the + * top of the innermost enclosing loop. It can only break out of + * it or return from the function. + */ + strength_break, + + /** + * Control cannot fall out the bottom of this node, continue to the + * top of the innermost enclosing loop, or break out of it. It can + * only return from the function. + */ + strength_return +}; + +struct block_record +{ + /* minimum jump strength (of lowered IR, not pre-lowering IR) + * + * If the block ends with a jump, must be the strength of the jump. + * Otherwise, the jump would be dead and have been deleted before) + * + * If the block doesn't end with a jump, it can be different than strength_none if all paths before it lead to some jump + * (e.g. an if with a return in one branch, and a break in the other, while not lowering them) + * Note that identical jumps are usually unified though. + */ + jump_strength min_strength; + + /* can anything clear the execute flag? */ + bool may_clear_execute_flag; + + block_record() + { + this->min_strength = strength_none; + this->may_clear_execute_flag = false; + } +}; + +struct loop_record +{ + ir_function_signature* signature; + ir_loop* loop; + + /* used to avoid lowering the break used to represent lowered breaks */ + unsigned nesting_depth; + bool in_if_at_the_end_of_the_loop; + + bool may_set_return_flag; + + ir_variable* break_flag; + ir_variable* execute_flag; /* cleared to emulate continue */ + + loop_record(ir_function_signature* p_signature = 0, ir_loop* p_loop = 0) + { + this->signature = p_signature; + this->loop = p_loop; + this->nesting_depth = 0; + this->in_if_at_the_end_of_the_loop = false; + this->may_set_return_flag = false; + this->break_flag = 0; + this->execute_flag = 0; + } + + ir_variable* get_execute_flag() + { + /* also supported for the "function loop" */ + if(!this->execute_flag) { + exec_list& list = this->loop ? this->loop->body_instructions : signature->body; + this->execute_flag = new(this->signature) ir_variable(glsl_type::bool_type, "execute_flag", ir_var_temporary); + list.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(execute_flag), new(this->signature) ir_constant(true), 0)); + list.push_head(this->execute_flag); + } + return this->execute_flag; + } + + ir_variable* get_break_flag() + { + assert(this->loop); + if(!this->break_flag) { + this->break_flag = new(this->signature) ir_variable(glsl_type::bool_type, "break_flag", ir_var_temporary); + this->loop->insert_before(this->break_flag); + this->loop->insert_before(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(break_flag), new(this->signature) ir_constant(false), 0)); + } + return this->break_flag; + } +}; + +struct function_record +{ + ir_function_signature* signature; + ir_variable* return_flag; /* used to break out of all loops and then jump to the return instruction */ + ir_variable* return_value; + bool lower_return; + unsigned nesting_depth; + + function_record(ir_function_signature* p_signature = 0, + bool lower_return = false) + { + this->signature = p_signature; + this->return_flag = 0; + this->return_value = 0; + this->nesting_depth = 0; + this->lower_return = lower_return; + } + + ir_variable* get_return_flag() + { + if(!this->return_flag) { + this->return_flag = new(this->signature) ir_variable(glsl_type::bool_type, "return_flag", ir_var_temporary); + this->signature->body.push_head(new(this->signature) ir_assignment(new(this->signature) ir_dereference_variable(return_flag), new(this->signature) ir_constant(false), 0)); + this->signature->body.push_head(this->return_flag); + } + return this->return_flag; + } + + ir_variable* get_return_value() + { + if(!this->return_value) { + assert(!this->signature->return_type->is_void()); + return_value = new(this->signature) ir_variable(this->signature->return_type, "return_value", ir_var_temporary); + this->signature->body.push_head(this->return_value); + } + return this->return_value; + } +}; + +struct ir_lower_jumps_visitor : public ir_control_flow_visitor { + /* Postconditions: on exit of any visit() function: + * + * ANALYSIS: this->block.min_strength, + * this->block.may_clear_execute_flag, and + * this->loop.may_set_return_flag are updated to reflect the + * characteristics of the visited statement. + * + * DEAD_CODE_ELIMINATION: If this->block.min_strength is not + * strength_none, the visited node is at the end of its exec_list. + * In other words, any unreachable statements that follow the + * visited statement in its exec_list have been removed. + * + * CONTAINED_JUMPS_LOWERED: If the visited statement contains other + * statements, then should_lower_jump() is false for all of the + * return, break, or continue statements it contains. + * + * Note that visiting a jump does not lower it. That is the + * responsibility of the statement (or function signature) that + * contains the jump. + */ + + bool progress; + + struct function_record function; + struct loop_record loop; + struct block_record block; + + bool pull_out_jumps; + bool lower_continue; + bool lower_break; + bool lower_sub_return; + bool lower_main_return; + + ir_lower_jumps_visitor() + { + this->progress = false; + } + + void truncate_after_instruction(exec_node *ir) + { + if (!ir) + return; + + while (!ir->get_next()->is_tail_sentinel()) { + ((ir_instruction *)ir->get_next())->remove(); + this->progress = true; + } + } + + void move_outer_block_inside(ir_instruction *ir, exec_list *inner_block) + { + while (!ir->get_next()->is_tail_sentinel()) { + ir_instruction *move_ir = (ir_instruction *)ir->get_next(); + + move_ir->remove(); + inner_block->push_tail(move_ir); + } + } + + /** + * Insert the instructions necessary to lower a return statement, + * before the given return instruction. + */ + void insert_lowered_return(ir_return *ir) + { + ir_variable* return_flag = this->function.get_return_flag(); + if(!this->function.signature->return_type->is_void()) { + ir_variable* return_value = this->function.get_return_value(); + ir->insert_before( + new(ir) ir_assignment( + new (ir) ir_dereference_variable(return_value), + ir->value)); + } + ir->insert_before( + new(ir) ir_assignment( + new (ir) ir_dereference_variable(return_flag), + new (ir) ir_constant(true))); + this->loop.may_set_return_flag = true; + } + + /** + * If the given instruction is a return, lower it to instructions + * that store the return value (if there is one), set the return + * flag, and then break. + * + * It is safe to pass NULL to this function. + */ + void lower_return_unconditionally(ir_instruction *ir) + { + if (get_jump_strength(ir) != strength_return) { + return; + } + insert_lowered_return((ir_return*)ir); + ir->replace_with(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + } + + /** + * Create the necessary instruction to replace a break instruction. + */ + ir_instruction *create_lowered_break() + { + void *ctx = this->function.signature; + return new(ctx) ir_assignment( + new(ctx) ir_dereference_variable(this->loop.get_break_flag()), + new(ctx) ir_constant(true), + 0); + } + + /** + * If the given instruction is a break, lower it to an instruction + * that sets the break flag, without consulting + * should_lower_jump(). + * + * It is safe to pass NULL to this function. + */ + void lower_break_unconditionally(ir_instruction *ir) + { + if (get_jump_strength(ir) != strength_break) { + return; + } + ir->replace_with(create_lowered_break()); + } + + /** + * If the block ends in a conditional or unconditional break, lower + * it, even though should_lower_jump() says it needn't be lowered. + */ + void lower_final_breaks(exec_list *block) + { + ir_instruction *ir = (ir_instruction *) block->get_tail(); + lower_break_unconditionally(ir); + ir_if *ir_if = ir->as_if(); + if (ir_if) { + lower_break_unconditionally( + (ir_instruction *) ir_if->then_instructions.get_tail()); + lower_break_unconditionally( + (ir_instruction *) ir_if->else_instructions.get_tail()); + } + } + + virtual void visit(class ir_loop_jump * ir) + { + /* Eliminate all instructions after each one, since they are + * unreachable. This satisfies the DEAD_CODE_ELIMINATION + * postcondition. + */ + truncate_after_instruction(ir); + + /* Set this->block.min_strength based on this instruction. This + * satisfies the ANALYSIS postcondition. It is not necessary to + * update this->block.may_clear_execute_flag or + * this->loop.may_set_return_flag, because an unlowered jump + * instruction can't change any flags. + */ + this->block.min_strength = ir->is_break() ? strength_break : strength_continue; + + /* The CONTAINED_JUMPS_LOWERED postcondition is already + * satisfied, because jump statements can't contain other + * statements. + */ + } + + virtual void visit(class ir_return * ir) + { + /* Eliminate all instructions after each one, since they are + * unreachable. This satisfies the DEAD_CODE_ELIMINATION + * postcondition. + */ + truncate_after_instruction(ir); + + /* Set this->block.min_strength based on this instruction. This + * satisfies the ANALYSIS postcondition. It is not necessary to + * update this->block.may_clear_execute_flag or + * this->loop.may_set_return_flag, because an unlowered return + * instruction can't change any flags. + */ + this->block.min_strength = strength_return; + + /* The CONTAINED_JUMPS_LOWERED postcondition is already + * satisfied, because jump statements can't contain other + * statements. + */ + } + + virtual void visit(class ir_discard * ir) + { + /* Nothing needs to be done. The ANALYSIS and + * DEAD_CODE_ELIMINATION postconditions are already satisfied, + * because discard statements are ignored by this optimization + * pass. The CONTAINED_JUMPS_LOWERED postcondition is already + * satisfied, because discard statements can't contain other + * statements. + */ + } + + enum jump_strength get_jump_strength(ir_instruction* ir) + { + if(!ir) + return strength_none; + else if(ir->ir_type == ir_type_loop_jump) { + if(((ir_loop_jump*)ir)->is_break()) + return strength_break; + else + return strength_continue; + } else if(ir->ir_type == ir_type_return) + return strength_return; + else + return strength_none; + } + + bool should_lower_jump(ir_jump* ir) + { + unsigned strength = get_jump_strength(ir); + bool lower; + switch(strength) + { + case strength_none: + lower = false; /* don't change this, code relies on it */ + break; + case strength_continue: + lower = lower_continue; + break; + case strength_break: + assert(this->loop.loop); + /* never lower "canonical break" */ + if(ir->get_next()->is_tail_sentinel() && (this->loop.nesting_depth == 0 + || (this->loop.nesting_depth == 1 && this->loop.in_if_at_the_end_of_the_loop))) + lower = false; + else + lower = lower_break; + break; + case strength_return: + /* never lower return at the end of a this->function */ + if(this->function.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) + lower = false; + else + lower = this->function.lower_return; + break; + } + return lower; + } + + block_record visit_block(exec_list* list) + { + /* Note: since visiting a node may change that node's next + * pointer, we can't use visit_exec_list(), because + * visit_exec_list() caches the node's next pointer before + * visiting it. So we use foreach_list() instead. + * + * foreach_list() isn't safe if the node being visited gets + * removed, but fortunately this visitor doesn't do that. + */ + + block_record saved_block = this->block; + this->block = block_record(); + foreach_list(node, list) { + ((ir_instruction *) node)->accept(this); + } + block_record ret = this->block; + this->block = saved_block; + return ret; + } + + virtual void visit(ir_if *ir) + { + if(this->loop.nesting_depth == 0 && ir->get_next()->is_tail_sentinel()) + this->loop.in_if_at_the_end_of_the_loop = true; + + ++this->function.nesting_depth; + ++this->loop.nesting_depth; + + block_record block_records[2]; + ir_jump* jumps[2]; + + /* Recursively lower nested jumps. This satisfies the + * CONTAINED_JUMPS_LOWERED postcondition, except in the case of + * unconditional jumps at the end of ir->then_instructions and + * ir->else_instructions, which are handled below. + */ + block_records[0] = visit_block(&ir->then_instructions); + block_records[1] = visit_block(&ir->else_instructions); + +retry: /* we get here if we put code after the if inside a branch */ + + /* Determine which of ir->then_instructions and + * ir->else_instructions end with an unconditional jump. + */ + for(unsigned i = 0; i < 2; ++i) { + exec_list& list = i ? ir->else_instructions : ir->then_instructions; + jumps[i] = 0; + if(!list.is_empty() && get_jump_strength((ir_instruction*)list.get_tail())) + jumps[i] = (ir_jump*)list.get_tail(); + } + + /* Loop until we have satisfied the CONTAINED_JUMPS_LOWERED + * postcondition by lowering jumps in both then_instructions and + * else_instructions. + */ + for(;;) { + /* Determine the types of the jumps that terminate + * ir->then_instructions and ir->else_instructions. + */ + jump_strength jump_strengths[2]; + + for(unsigned i = 0; i < 2; ++i) { + if(jumps[i]) { + jump_strengths[i] = block_records[i].min_strength; + assert(jump_strengths[i] == get_jump_strength(jumps[i])); + } else + jump_strengths[i] = strength_none; + } + + /* If both code paths end in a jump, and the jumps are the + * same, and we are pulling out jumps, replace them with a + * single jump that comes after the if instruction. The new + * jump will be visited next, and it will be lowered if + * necessary by the loop or conditional that encloses it. + */ + if(pull_out_jumps && jump_strengths[0] == jump_strengths[1]) { + bool unify = true; + if(jump_strengths[0] == strength_continue) + ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_continue)); + else if(jump_strengths[0] == strength_break) + ir->insert_after(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + /* FINISHME: unify returns with identical expressions */ + else if(jump_strengths[0] == strength_return && this->function.signature->return_type->is_void()) + ir->insert_after(new(ir) ir_return(NULL)); + else + unify = false; + + if(unify) { + jumps[0]->remove(); + jumps[1]->remove(); + this->progress = true; + + /* Update jumps[] to reflect the fact that the jumps + * are gone, and update block_records[] to reflect the + * fact that control can now flow to the next + * instruction. + */ + jumps[0] = 0; + jumps[1] = 0; + block_records[0].min_strength = strength_none; + block_records[1].min_strength = strength_none; + + /* The CONTAINED_JUMPS_LOWERED postcondition is now + * satisfied, so we can break out of the loop. + */ + break; + } + } + + /* lower a jump: if both need to lowered, start with the strongest one, so that + * we might later unify the lowered version with the other one + */ + bool should_lower[2]; + for(unsigned i = 0; i < 2; ++i) + should_lower[i] = should_lower_jump(jumps[i]); + + int lower; + if(should_lower[1] && should_lower[0]) + lower = jump_strengths[1] > jump_strengths[0]; + else if(should_lower[0]) + lower = 0; + else if(should_lower[1]) + lower = 1; + else + /* Neither code path ends in a jump that needs to be + * lowered, so the CONTAINED_JUMPS_LOWERED postcondition + * is satisfied and we can break out of the loop. + */ + break; + + if(jump_strengths[lower] == strength_return) { + /* To lower a return, we create a return flag (if the + * function doesn't have one already) and add instructions + * that: 1. store the return value (if this function has a + * non-void return) and 2. set the return flag + */ + insert_lowered_return((ir_return*)jumps[lower]); + if(this->loop.loop) { + /* If we are in a loop, replace the return instruction + * with a break instruction, and then loop so that the + * break instruction can be lowered if necessary. + */ + ir_loop_jump* lowered = 0; + lowered = new(ir) ir_loop_jump(ir_loop_jump::jump_break); + /* Note: we must update block_records and jumps to + * reflect the fact that the control path has been + * altered from a return to a break. + */ + block_records[lower].min_strength = strength_break; + jumps[lower]->replace_with(lowered); + jumps[lower] = lowered; + } else { + /* If we are not in a loop, we then proceed as we would + * for a continue statement (set the execute flag to + * false to prevent the rest of the function from + * executing). + */ + goto lower_continue; + } + this->progress = true; + } else if(jump_strengths[lower] == strength_break) { + /* To lower a break, we create a break flag (if the loop + * doesn't have one already) and add an instruction that + * sets it. + * + * Then we proceed as we would for a continue statement + * (set the execute flag to false to prevent the rest of + * the loop body from executing). + * + * The visit() function for the loop will ensure that the + * break flag is checked after executing the loop body. + */ + jumps[lower]->insert_before(create_lowered_break()); + goto lower_continue; + } else if(jump_strengths[lower] == strength_continue) { +lower_continue: + /* To lower a continue, we create an execute flag (if the + * loop doesn't have one already) and replace the continue + * with an instruction that clears it. + * + * Note that this code path gets exercised when lowering + * return statements that are not inside a loop, so + * this->loop must be initialized even outside of loops. + */ + ir_variable* execute_flag = this->loop.get_execute_flag(); + jumps[lower]->replace_with(new(ir) ir_assignment(new (ir) ir_dereference_variable(execute_flag), new (ir) ir_constant(false), 0)); + /* Note: we must update block_records and jumps to reflect + * the fact that the control path has been altered to an + * instruction that clears the execute flag. + */ + jumps[lower] = 0; + block_records[lower].min_strength = strength_always_clears_execute_flag; + block_records[lower].may_clear_execute_flag = true; + this->progress = true; + + /* Let the loop run again, in case the other branch of the + * if needs to be lowered too. + */ + } + } + + /* move out a jump out if possible */ + if(pull_out_jumps) { + /* If one of the branches ends in a jump, and control cannot + * fall out the bottom of the other branch, then we can move + * the jump after the if. + * + * Set move_out to the branch we are moving a jump out of. + */ + int move_out = -1; + if(jumps[0] && block_records[1].min_strength >= strength_continue) + move_out = 0; + else if(jumps[1] && block_records[0].min_strength >= strength_continue) + move_out = 1; + + if(move_out >= 0) + { + jumps[move_out]->remove(); + ir->insert_after(jumps[move_out]); + /* Note: we must update block_records and jumps to reflect + * the fact that the jump has been moved out of the if. + */ + jumps[move_out] = 0; + block_records[move_out].min_strength = strength_none; + this->progress = true; + } + } + + /* Now satisfy the ANALYSIS postcondition by setting + * this->block.min_strength and + * this->block.may_clear_execute_flag based on the + * characteristics of the two branches. + */ + if(block_records[0].min_strength < block_records[1].min_strength) + this->block.min_strength = block_records[0].min_strength; + else + this->block.min_strength = block_records[1].min_strength; + this->block.may_clear_execute_flag = this->block.may_clear_execute_flag || block_records[0].may_clear_execute_flag || block_records[1].may_clear_execute_flag; + + /* Now we need to clean up the instructions that follow the + * if. + * + * If those instructions are unreachable, then satisfy the + * DEAD_CODE_ELIMINATION postcondition by eliminating them. + * Otherwise that postcondition is already satisfied. + */ + if(this->block.min_strength) + truncate_after_instruction(ir); + else if(this->block.may_clear_execute_flag) + { + /* If the "if" instruction might clear the execute flag, then + * we need to guard any instructions that follow so that they + * are only executed if the execute flag is set. + * + * If one of the branches of the "if" always clears the + * execute flag, and the other branch never clears it, then + * this is easy: just move all the instructions following the + * "if" into the branch that never clears it. + */ + int move_into = -1; + if(block_records[0].min_strength && !block_records[1].may_clear_execute_flag) + move_into = 1; + else if(block_records[1].min_strength && !block_records[0].may_clear_execute_flag) + move_into = 0; + + if(move_into >= 0) { + assert(!block_records[move_into].min_strength && !block_records[move_into].may_clear_execute_flag); /* otherwise, we just truncated */ + + exec_list* list = move_into ? &ir->else_instructions : &ir->then_instructions; + exec_node* next = ir->get_next(); + if(!next->is_tail_sentinel()) { + move_outer_block_inside(ir, list); + + /* If any instructions moved, then we need to visit + * them (since they are now inside the "if"). Since + * block_records[move_into] is in its default state + * (see assertion above), we can safely replace + * block_records[move_into] with the result of this + * analysis. + */ + exec_list list; + list.head = next; + block_records[move_into] = visit_block(&list); + + /* + * Then we need to re-start our jump lowering, since one + * of the instructions we moved might be a jump that + * needs to be lowered. + */ + this->progress = true; + goto retry; + } + } else { + /* If we get here, then the simple case didn't apply; we + * need to actually guard the instructions that follow. + * + * To avoid creating unnecessarily-deep nesting, first + * look through the instructions that follow and unwrap + * any instructions that that are already wrapped in the + * appropriate guard. + */ + ir_instruction* ir_after; + for(ir_after = (ir_instruction*)ir->get_next(); !ir_after->is_tail_sentinel();) + { + ir_if* ir_if = ir_after->as_if(); + if(ir_if && ir_if->else_instructions.is_empty()) { + ir_dereference_variable* ir_if_cond_deref = ir_if->condition->as_dereference_variable(); + if(ir_if_cond_deref && ir_if_cond_deref->var == this->loop.execute_flag) { + ir_instruction* ir_next = (ir_instruction*)ir_after->get_next(); + ir_after->insert_before(&ir_if->then_instructions); + ir_after->remove(); + ir_after = ir_next; + continue; + } + } + ir_after = (ir_instruction*)ir_after->get_next(); + + /* only set this if we find any unprotected instruction */ + this->progress = true; + } + + /* Then, wrap all the instructions that follow in a single + * guard. + */ + if(!ir->get_next()->is_tail_sentinel()) { + assert(this->loop.execute_flag); + ir_if* if_execute = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.execute_flag)); + move_outer_block_inside(ir, &if_execute->then_instructions); + ir->insert_after(if_execute); + } + } + } + --this->loop.nesting_depth; + --this->function.nesting_depth; + } + + virtual void visit(ir_loop *ir) + { + /* Visit the body of the loop, with a fresh data structure in + * this->loop so that the analysis we do here won't bleed into + * enclosing loops. + * + * We assume that all code after a loop is reachable from the + * loop (see comments on enum jump_strength), so the + * DEAD_CODE_ELIMINATION postcondition is automatically + * satisfied, as is the block.min_strength portion of the + * ANALYSIS postcondition. + * + * The block.may_clear_execute_flag portion of the ANALYSIS + * postcondition is automatically satisfied because execute + * flags do not propagate outside of loops. + * + * The loop.may_set_return_flag portion of the ANALYSIS + * postcondition is handled below. + */ + ++this->function.nesting_depth; + loop_record saved_loop = this->loop; + this->loop = loop_record(this->function.signature, ir); + + /* Recursively lower nested jumps. This satisfies the + * CONTAINED_JUMPS_LOWERED postcondition, except in the case of + * an unconditional continue or return at the bottom of the + * loop, which are handled below. + */ + block_record body = visit_block(&ir->body_instructions); + + /* If the loop ends in an unconditional continue, eliminate it + * because it is redundant. + */ + ir_instruction *ir_last + = (ir_instruction *) ir->body_instructions.get_tail(); + if (get_jump_strength(ir_last) == strength_continue) { + ir_last->remove(); + } + + /* If the loop ends in an unconditional return, and we are + * lowering returns, lower it. + */ + if (this->function.lower_return) + lower_return_unconditionally(ir_last); + + if(body.min_strength >= strength_break) { + /* FINISHME: If the min_strength of the loop body is + * strength_break or strength_return, that means that it + * isn't a loop at all, since control flow always leaves the + * body of the loop via break or return. In principle the + * loop could be eliminated in this case. This optimization + * is not implemented yet. + */ + } + + if(this->loop.break_flag) { + /* We only get here if we are lowering breaks */ + assert (lower_break); + + /* If a break flag was generated while visiting the body of + * the loop, then at least one break was lowered, so we need + * to generate an if statement at the end of the loop that + * does a "break" if the break flag is set. The break we + * generate won't violate the CONTAINED_JUMPS_LOWERED + * postcondition, because should_lower_jump() always returns + * false for a break that happens at the end of a loop. + * + * However, if the loop already ends in a conditional or + * unconditional break, then we need to lower that break, + * because it won't be at the end of the loop anymore. + */ + lower_final_breaks(&ir->body_instructions); + + ir_if* break_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->loop.break_flag)); + break_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + ir->body_instructions.push_tail(break_if); + } + + /* If the body of the loop may set the return flag, then at + * least one return was lowered to a break, so we need to ensure + * that the return flag is checked after the body of the loop is + * executed. + */ + if(this->loop.may_set_return_flag) { + assert(this->function.return_flag); + /* Generate the if statement to check the return flag */ + ir_if* return_if = new(ir) ir_if(new(ir) ir_dereference_variable(this->function.return_flag)); + /* Note: we also need to propagate the knowledge that the + * return flag may get set to the outer context. This + * satisfies the loop.may_set_return_flag part of the + * ANALYSIS postcondition. + */ + saved_loop.may_set_return_flag = true; + if(saved_loop.loop) + /* If this loop is nested inside another one, then the if + * statement that we generated should break out of that + * loop if the return flag is set. Caller will lower that + * break statement if necessary. + */ + return_if->then_instructions.push_tail(new(ir) ir_loop_jump(ir_loop_jump::jump_break)); + else + /* Otherwise, all we need to do is ensure that the + * instructions that follow are only executed if the + * return flag is clear. We can do that by moving those + * instructions into the else clause of the generated if + * statement. + */ + move_outer_block_inside(ir, &return_if->else_instructions); + ir->insert_after(return_if); + } + + this->loop = saved_loop; + --this->function.nesting_depth; + } + + virtual void visit(ir_function_signature *ir) + { + /* these are not strictly necessary */ + assert(!this->function.signature); + assert(!this->loop.loop); + + bool lower_return; + if (strcmp(ir->function_name(), "main") == 0) + lower_return = lower_main_return; + else + lower_return = lower_sub_return; + + function_record saved_function = this->function; + loop_record saved_loop = this->loop; + this->function = function_record(ir, lower_return); + this->loop = loop_record(ir); + + assert(!this->loop.loop); + + /* Visit the body of the function to lower any jumps that occur + * in it, except possibly an unconditional return statement at + * the end of it. + */ + visit_block(&ir->body); + + /* If the body ended in an unconditional return of non-void, + * then we don't need to lower it because it's the one canonical + * return. + * + * If the body ended in a return of void, eliminate it because + * it is redundant. + */ + if (ir->return_type->is_void() && + get_jump_strength((ir_instruction *) ir->body.get_tail())) { + ir_jump *jump = (ir_jump *) ir->body.get_tail(); + assert (jump->ir_type == ir_type_return); + jump->remove(); + } + + if(this->function.return_value) + ir->body.push_tail(new(ir) ir_return(new (ir) ir_dereference_variable(this->function.return_value))); + + this->loop = saved_loop; + this->function = saved_function; + } + + virtual void visit(class ir_function * ir) + { + visit_block(&ir->signatures); + } +}; + +bool +do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_return, bool lower_main_return, bool lower_continue, bool lower_break) +{ + ir_lower_jumps_visitor v; + v.pull_out_jumps = pull_out_jumps; + v.lower_continue = lower_continue; + v.lower_break = lower_break; + v.lower_sub_return = lower_sub_return; + v.lower_main_return = lower_main_return; + + do { + v.progress = false; + visit_exec_list(instructions, &v); + } while (v.progress); + + return v.progress; +} diff --git a/mesalib/src/mesa/main/depthstencil.c b/mesalib/src/mesa/main/depthstencil.c index ab62c97fe..4d0600050 100644 --- a/mesalib/src/mesa/main/depthstencil.c +++ b/mesalib/src/mesa/main/depthstencil.c @@ -393,6 +393,217 @@ _mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx, } +static void +get_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + GLint x, GLint y, void *values) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat temp[MAX_WIDTH*2]; + GLfloat *dst = (GLfloat *) values; + const GLfloat *src = (const GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); + GLuint i; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (!src) { + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + src = temp; + } + for (i = 0; i < count; i++) { + dst[i] = src[i*2]; + } +} + +static void +get_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + const GLint x[], const GLint y[], void *values) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat temp[MAX_WIDTH*2]; + GLfloat *dst = (GLfloat *) values; + GLuint i; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(count <= MAX_WIDTH); + /* don't bother trying direct access */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + dst[i] = temp[i*2]; + } +} + +static void +put_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + GLint x, GLint y, const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + const GLfloat *src = (const GLfloat *) values; + GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (dst) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2] = src[i]; + } + } + } + else { + /* get, modify, put */ + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = src[i]; + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_row_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + GLint x, GLint y, const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x, y); + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (dst) { + /* direct access */ + GLuint i; + const GLfloat val = *(GLfloat*)value; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2] = val; + } + } + } + else { + /* get, modify, put */ + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + const GLfloat val = *(GLfloat *)value; + dsrb->GetRow(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = val; + } + } + dsrb->PutRow(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, GLuint count, + const GLint x[], const GLint y[], + const void *values, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + const GLfloat *src = (const GLfloat *) values; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { + /* direct access */ + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLfloat *dst = (GLfloat *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); + *dst = src[i]; + } + } + } + else { + /* get, modify, put */ + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = src[i]; + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); + } +} + +static void +put_mono_values_z32f(struct gl_context *ctx, struct gl_renderbuffer *z32frb, + GLuint count, const GLint x[], const GLint y[], + const void *value, const GLubyte *mask) +{ + struct gl_renderbuffer *dsrb = z32frb->Wrapped; + GLfloat temp[MAX_WIDTH*2]; + GLuint i; + const GLfloat val = *(GLfloat *)value; + ASSERT(z32frb->DataType == GL_FLOAT); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + /* get, modify, put */ + dsrb->GetValues(ctx, dsrb, count, x, y, temp); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2] = val; + } + } + dsrb->PutValues(ctx, dsrb, count, x, y, temp, mask); +} + + +/** + * Wrap the given GL_DEPTH_STENCIL renderbuffer so that it acts like + * a depth renderbuffer. + * \return new depth renderbuffer + */ +struct gl_renderbuffer * +_mesa_new_z32f_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb) +{ + struct gl_renderbuffer *z32frb; + + ASSERT(dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + + z32frb = ctx->Driver.NewRenderbuffer(ctx, 0); + if (!z32frb) + return NULL; + + /* NOTE: need to do manual refcounting here */ + z32frb->Wrapped = dsrb; + dsrb->RefCount++; + + z32frb->Name = dsrb->Name; + z32frb->RefCount = 0; + z32frb->Width = dsrb->Width; + z32frb->Height = dsrb->Height; + z32frb->RowStride = dsrb->RowStride; + z32frb->InternalFormat = GL_DEPTH_COMPONENT32F; + z32frb->Format = MESA_FORMAT_Z32_FLOAT; + z32frb->_BaseFormat = GL_DEPTH_COMPONENT; + z32frb->DataType = GL_FLOAT; + z32frb->Data = NULL; + z32frb->Delete = delete_wrapper; + z32frb->AllocStorage = alloc_wrapper_storage; + z32frb->GetPointer = nop_get_pointer; + z32frb->GetRow = get_row_z32f; + z32frb->GetValues = get_values_z32f; + z32frb->PutRow = put_row_z32f; + z32frb->PutRowRGB = NULL; + z32frb->PutMonoRow = put_mono_row_z32f; + z32frb->PutValues = put_values_z32f; + z32frb->PutMonoValues = put_mono_values_z32f; + + return z32frb; +} + + /*====================================================================== * Stencil wrapper around depth/stencil renderbuffer */ @@ -402,16 +613,22 @@ get_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, GLint x, GLint y, void *values) { struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; GLubyte *dst = (GLubyte *) values; const GLuint *src = (const GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (!src) { dsrb->GetRow(ctx, dsrb, count, x, y, temp); src = temp; } - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + dst[i] = src[i*2+1] & 0xff; + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { dst[i] = src[i] & 0xff; } @@ -429,14 +646,20 @@ get_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count const GLint x[], const GLint y[], void *values) { struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; GLubyte *dst = (GLubyte *) values; ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); ASSERT(count <= MAX_WIDTH); /* don't bother trying direct access */ dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + dst[i] = temp[i*2+1] & 0xff; + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { dst[i] = temp[i] & 0xff; } @@ -457,11 +680,19 @@ put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, const GLubyte *src = (const GLubyte *) values; GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (dst) { /* direct access */ GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2+1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i] = (dst[i] & 0xffffff00) | src[i]; @@ -479,9 +710,16 @@ put_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count, } else { /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; dsrb->GetRow(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | src[i]; @@ -508,11 +746,19 @@ put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint cou const GLubyte val = *((GLubyte *) value); GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x, y); ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (dst) { /* direct access */ GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst[i*2+1] = val; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { dst[i] = (dst[i] & 0xffffff00) | val; @@ -530,9 +776,16 @@ put_mono_row_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint cou } else { /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; dsrb->GetRow(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = val; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | val; @@ -559,11 +812,20 @@ put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count struct gl_renderbuffer *dsrb = s8rb->Wrapped; const GLubyte *src = (const GLubyte *) values; ASSERT(s8rb->DataType == GL_UNSIGNED_BYTE); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); if (dsrb->GetPointer(ctx, dsrb, 0, 0)) { /* direct access */ GLuint i; - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); + dst[1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { GLuint *dst = (GLuint *) dsrb->GetPointer(ctx, dsrb, x[i], y[i]); @@ -583,9 +845,16 @@ put_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint count } else { /* get, modify, put */ - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = src[i]; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | src[i]; @@ -610,11 +879,18 @@ put_mono_values_s8(struct gl_context *ctx, struct gl_renderbuffer *s8rb, GLuint const void *value, const GLubyte *mask) { struct gl_renderbuffer *dsrb = s8rb->Wrapped; - GLuint temp[MAX_WIDTH], i; + GLuint temp[MAX_WIDTH*2], i; const GLubyte val = *((GLubyte *) value); /* get, modify, put */ dsrb->GetValues(ctx, dsrb, count, x, y, temp); - if (dsrb->Format == MESA_FORMAT_Z24_S8) { + if (dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + temp[i*2+1] = val; + } + } + } + else if (dsrb->Format == MESA_FORMAT_Z24_S8) { for (i = 0; i < count; i++) { if (!mask || mask[i]) { temp[i] = (temp[i] & 0xffffff00) | val; @@ -644,8 +920,10 @@ _mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, struct gl_renderbuffer struct gl_renderbuffer *s8rb; ASSERT(dsrb->Format == MESA_FORMAT_Z24_S8 || - dsrb->Format == MESA_FORMAT_S8_Z24); - ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT); + dsrb->Format == MESA_FORMAT_S8_Z24 || + dsrb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(dsrb->DataType == GL_UNSIGNED_INT_24_8_EXT || + dsrb->DataType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); s8rb = ctx->Driver.NewRenderbuffer(ctx, 0); if (!s8rb) diff --git a/mesalib/src/mesa/main/depthstencil.h b/mesalib/src/mesa/main/depthstencil.h index a86f54d96..b47a2e482 100644 --- a/mesalib/src/mesa/main/depthstencil.h +++ b/mesalib/src/mesa/main/depthstencil.h @@ -1,57 +1,62 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * 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 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 - * BRIAN PAUL 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. - */ - - -#ifndef DEPTHSTENCIL_H -#define DEPTHSTENCIL_H - -struct gl_context; - -extern struct gl_renderbuffer * -_mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx, - struct gl_renderbuffer *dsrb); - - -extern struct gl_renderbuffer * -_mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, - struct gl_renderbuffer *dsrb); - - -extern void -_mesa_extract_stencil(struct gl_context *ctx, - struct gl_renderbuffer *dsRb, - struct gl_renderbuffer *stencilRb); - - -extern void -_mesa_insert_stencil(struct gl_context *ctx, - struct gl_renderbuffer *dsRb, - struct gl_renderbuffer *stencilRb); - - -extern void -_mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb); - - -#endif /* DEPTHSTENCIL_H */ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * 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 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 + * BRIAN PAUL 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. + */ + + +#ifndef DEPTHSTENCIL_H +#define DEPTHSTENCIL_H + +struct gl_context; + +extern struct gl_renderbuffer * +_mesa_new_z24_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb); + + +extern struct gl_renderbuffer * +_mesa_new_z32f_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb); + + +extern struct gl_renderbuffer * +_mesa_new_s8_renderbuffer_wrapper(struct gl_context *ctx, + struct gl_renderbuffer *dsrb); + + +extern void +_mesa_extract_stencil(struct gl_context *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb); + + +extern void +_mesa_insert_stencil(struct gl_context *ctx, + struct gl_renderbuffer *dsRb, + struct gl_renderbuffer *stencilRb); + + +extern void +_mesa_promote_stencil(struct gl_context *ctx, struct gl_renderbuffer *stencilRb); + + +#endif /* DEPTHSTENCIL_H */ diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 8cc3fd49a..84969360d 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -1131,6 +1131,16 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) return GL_DEPTH_STENCIL_EXT; else return 0; + case GL_DEPTH_COMPONENT32F: + if (ctx->Extensions.ARB_depth_buffer_float) + return GL_DEPTH_COMPONENT; + else + return 0; + case GL_DEPTH32F_STENCIL8: + if (ctx->Extensions.ARB_depth_buffer_float) + return GL_DEPTH_STENCIL; + else + return 0; case GL_RED: case GL_R8: case GL_R16: @@ -2266,6 +2276,15 @@ _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, /* special cases */ *params = GL_INDEX; } + else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) { + /* depends on the attachment parameter */ + if (attachment == GL_STENCIL_ATTACHMENT) { + *params = GL_INDEX; + } + else { + *params = GL_FLOAT; + } + } else { *params = _mesa_get_format_datatype(format); } @@ -2584,6 +2603,10 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, } } + if (!mask) { + return; + } + ASSERT(ctx->Driver.BlitFramebuffer); ctx->Driver.BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index e88ba4397..f58b19756 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -1091,6 +1091,25 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 0, 0, 0, 0, 0, 1, 1, 4 }, + /* ARB_depth_buffer_float */ + { + MESA_FORMAT_Z32_FLOAT, /* Name */ + "MESA_FORMAT_Z32_FLOAT", /* StrName */ + GL_DEPTH_COMPONENT, /* BaseFormat */ + GL_FLOAT, /* DataType */ + 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ + 0, 0, 0, 32, 0, /* Lum/Int/Index/Depth/StencilBits */ + 1, 1, 4 /* BlockWidth/Height,Bytes */ + }, + { + MESA_FORMAT_Z32_FLOAT_X24S8, /* Name */ + "MESA_FORMAT_Z32_FLOAT_X24S8", /* StrName */ + GL_DEPTH_STENCIL, /* BaseFormat */ + GL_NONE /* XXX */, /* DataType */ + 0, 0, 0, 0, /* Red/Green/Blue/AlphaBits */ + 0, 0, 0, 32, 8, /* Lum/Int/Index/Depth/StencilBits */ + 1, 1, 8 /* BlockWidth/Height,Bytes */ + }, }; @@ -1654,6 +1673,16 @@ _mesa_format_to_type_and_comps(gl_format format, *comps = 1; return; + case MESA_FORMAT_Z32_FLOAT: + *datatype = GL_FLOAT; + *comps = 1; + return; + + case MESA_FORMAT_Z32_FLOAT_X24S8: + *datatype = GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + *comps = 1; + return; + case MESA_FORMAT_DUDV8: *datatype = GL_BYTE; *comps = 2; diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 0640bbc4a..5b8c01781 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -209,6 +209,9 @@ typedef enum MESA_FORMAT_RGB9_E5_FLOAT, MESA_FORMAT_R11_G11_B10_FLOAT, + MESA_FORMAT_Z32_FLOAT, + MESA_FORMAT_Z32_FLOAT_X24S8, + MESA_FORMAT_COUNT } gl_format; diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 66c9bd910..6e2ce7421 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -631,8 +631,14 @@ _mesa_update_depth_buffer(struct gl_context *ctx, || fb->_DepthBuffer->Wrapped != depthRb || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) { /* need to update wrapper */ - struct gl_renderbuffer *wrapper - = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); + struct gl_renderbuffer *wrapper; + + if (depthRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + wrapper = _mesa_new_z32f_renderbuffer_wrapper(ctx, depthRb); + } + else { + wrapper = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); + } _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); ASSERT(fb->_DepthBuffer->Wrapped == depthRb); } diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c index a5cd5ac03..37127dcb7 100644 --- a/mesalib/src/mesa/main/image.c +++ b/mesalib/src/mesa/main/image.c @@ -1,1935 +1,1949 @@ -/* - * Mesa 3-D graphics library - * Version: 7.5 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (C) 2009 VMware, Inc. All Rights Reserved. - * - * 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 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 - * BRIAN PAUL 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. - */ - - -/** - * \file image.c - * Image handling. - */ - - -#include "glheader.h" -#include "colormac.h" -#include "image.h" -#include "imports.h" -#include "macros.h" -#include "mfeatures.h" -#include "mtypes.h" - - -/** - * NOTE: - * Normally, BYTE_TO_FLOAT(0) returns 0.00392 That causes problems when - * we later convert the float to a packed integer value (such as for - * GL_RGB5_A1) because we'll wind up with a non-zero value. - * - * We redefine the macros here so zero is handled correctly. - */ -#undef BYTE_TO_FLOAT -#define BYTE_TO_FLOAT(B) ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F))) - -#undef SHORT_TO_FLOAT -#define SHORT_TO_FLOAT(S) ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))) - - - -/** Compute ceiling of integer quotient of A divided by B. */ -#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) - - -/** - * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise. - */ -GLboolean -_mesa_type_is_packed(GLenum type) -{ - switch (type) { - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - case MESA_UNSIGNED_BYTE_4_4: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_4_4_4_4_REV: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - case GL_UNSIGNED_INT_8_8_8_8: - case GL_UNSIGNED_INT_8_8_8_8_REV: - case GL_UNSIGNED_INT_10_10_10_2: - case GL_UNSIGNED_INT_2_10_10_10_REV: - 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: - case GL_UNSIGNED_INT_10F_11F_11F_REV: - return GL_TRUE; - } - - return GL_FALSE; -} - - - -/** - * Flip the order of the 2 bytes in each word in the given array. - * - * \param p array. - * \param n number of words. - */ -void -_mesa_swap2( GLushort *p, GLuint n ) -{ - GLuint i; - for (i = 0; i < n; i++) { - p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); - } -} - - - -/* - * Flip the order of the 4 bytes in each word in the given array. - */ -void -_mesa_swap4( GLuint *p, GLuint n ) -{ - GLuint i, a, b; - for (i = 0; i < n; i++) { - b = p[i]; - a = (b >> 24) - | ((b >> 8) & 0xff00) - | ((b << 8) & 0xff0000) - | ((b << 24) & 0xff000000); - p[i] = a; - } -} - - -/** - * Get the size of a GL data type. - * - * \param type GL data type. - * - * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1 - * if an invalid type enum. - */ -GLint -_mesa_sizeof_type( GLenum type ) -{ - switch (type) { - case GL_BITMAP: - return 0; - case GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - case GL_BYTE: - return sizeof(GLbyte); - case GL_UNSIGNED_SHORT: - return sizeof(GLushort); - case GL_SHORT: - return sizeof(GLshort); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - case GL_INT: - return sizeof(GLint); - case GL_FLOAT: - return sizeof(GLfloat); - case GL_DOUBLE: - return sizeof(GLdouble); - case GL_HALF_FLOAT_ARB: - return sizeof(GLhalfARB); - case GL_FIXED: - return sizeof(GLfixed); - default: - return -1; - } -} - - -/** - * Same as _mesa_sizeof_type() but also accepting the packed pixel - * format data types. - */ -GLint -_mesa_sizeof_packed_type( GLenum type ) -{ - switch (type) { - case GL_BITMAP: - return 0; - case GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - case GL_BYTE: - return sizeof(GLbyte); - case GL_UNSIGNED_SHORT: - return sizeof(GLushort); - case GL_SHORT: - return sizeof(GLshort); - case GL_UNSIGNED_INT: - return sizeof(GLuint); - case GL_INT: - return sizeof(GLint); - case GL_HALF_FLOAT_ARB: - return sizeof(GLhalfARB); - case GL_FLOAT: - return sizeof(GLfloat); - case GL_UNSIGNED_BYTE_3_3_2: - return sizeof(GLubyte); - case GL_UNSIGNED_BYTE_2_3_3_REV: - return sizeof(GLubyte); - case MESA_UNSIGNED_BYTE_4_4: - return sizeof(GLubyte); - case GL_UNSIGNED_SHORT_5_6_5: - return sizeof(GLushort); - case GL_UNSIGNED_SHORT_5_6_5_REV: - return sizeof(GLushort); - case GL_UNSIGNED_SHORT_4_4_4_4: - return sizeof(GLushort); - case GL_UNSIGNED_SHORT_4_4_4_4_REV: - return sizeof(GLushort); - case GL_UNSIGNED_SHORT_5_5_5_1: - return sizeof(GLushort); - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - return sizeof(GLushort); - case GL_UNSIGNED_INT_8_8_8_8: - return sizeof(GLuint); - case GL_UNSIGNED_INT_8_8_8_8_REV: - return sizeof(GLuint); - case GL_UNSIGNED_INT_10_10_10_2: - return sizeof(GLuint); - case GL_UNSIGNED_INT_2_10_10_10_REV: - return sizeof(GLuint); - case GL_UNSIGNED_SHORT_8_8_MESA: - case GL_UNSIGNED_SHORT_8_8_REV_MESA: - 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); - case GL_UNSIGNED_INT_10F_11F_11F_REV: - return sizeof(GLuint); - default: - return -1; - } -} - - -/** - * Get the number of components in a pixel format. - * - * \param format pixel format. - * - * \return the number of components in the given format, or -1 if a bad format. - */ -GLint -_mesa_components_in_format( GLenum format ) -{ - switch (format) { - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - case GL_STENCIL_INDEX: - case GL_DEPTH_COMPONENT: - case GL_RED: - case GL_RED_INTEGER_EXT: - case GL_GREEN: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA: - case GL_ALPHA_INTEGER_EXT: - case GL_LUMINANCE: - case GL_LUMINANCE_INTEGER_EXT: - case GL_INTENSITY: - return 1; - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - case GL_RG: - return 2; - case GL_RGB: - case GL_RGB_INTEGER_EXT: - return 3; - case GL_RGBA: - case GL_RGBA_INTEGER_EXT: - return 4; - case GL_BGR: - return 3; - case GL_BGRA: - return 4; - case GL_ABGR_EXT: - return 4; - case GL_YCBCR_MESA: - return 2; - case GL_DEPTH_STENCIL_EXT: - return 2; - case GL_DUDV_ATI: - case GL_DU8DV8_ATI: - return 2; - default: - return -1; - } -} - - -/** - * Get the bytes per pixel of pixel format type pair. - * - * \param format pixel format. - * \param type pixel type. - * - * \return bytes per pixel, or -1 if a bad format or type was given. - */ -GLint -_mesa_bytes_per_pixel( GLenum format, GLenum type ) -{ - GLint comps = _mesa_components_in_format( format ); - if (comps < 0) - return -1; - - switch (type) { - case GL_BITMAP: - return 0; /* special case */ - case GL_BYTE: - case GL_UNSIGNED_BYTE: - return comps * sizeof(GLubyte); - case GL_SHORT: - case GL_UNSIGNED_SHORT: - return comps * sizeof(GLshort); - case GL_INT: - case GL_UNSIGNED_INT: - return comps * sizeof(GLint); - case GL_FLOAT: - return comps * sizeof(GLfloat); - case GL_HALF_FLOAT_ARB: - return comps * sizeof(GLhalfARB); - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - if (format == GL_RGB || format == GL_BGR || - format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT) - return sizeof(GLubyte); - else - return -1; /* error */ - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - if (format == GL_RGB || format == GL_BGR || - format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT) - return sizeof(GLushort); - else - return -1; /* error */ - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_4_4_4_4_REV: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT || - format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) - return sizeof(GLushort); - else - return -1; - case GL_UNSIGNED_INT_8_8_8_8: - case GL_UNSIGNED_INT_8_8_8_8_REV: - case GL_UNSIGNED_INT_10_10_10_2: - case GL_UNSIGNED_INT_2_10_10_10_REV: - if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT || - format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) - return sizeof(GLuint); - else - return -1; - case GL_UNSIGNED_SHORT_8_8_MESA: - case GL_UNSIGNED_SHORT_8_8_REV_MESA: - if (format == GL_YCBCR_MESA) - return sizeof(GLushort); - else - return -1; - case GL_UNSIGNED_INT_24_8_EXT: - if (format == GL_DEPTH_STENCIL_EXT) - 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; - case GL_UNSIGNED_INT_10F_11F_11F_REV: - if (format == GL_RGB) - return sizeof(GLuint); - else - return -1; - default: - return -1; - } -} - - -/** - * Test for a legal pixel format and type. - * - * \param format pixel format. - * \param type pixel type. - * - * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE - * otherwise. - */ -GLboolean -_mesa_is_legal_format_and_type(const struct gl_context *ctx, - GLenum format, GLenum type) -{ - switch (format) { - case GL_COLOR_INDEX: - case GL_STENCIL_INDEX: - switch (type) { - case GL_BITMAP: - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - return GL_TRUE; - case GL_HALF_FLOAT_ARB: - return ctx->Extensions.ARB_half_float_pixel; - default: - return GL_FALSE; - } - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: -#if 0 /* not legal! see table 3.6 of the 1.5 spec */ - case GL_INTENSITY: -#endif - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_DEPTH_COMPONENT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - return GL_TRUE; - case GL_HALF_FLOAT_ARB: - return ctx->Extensions.ARB_half_float_pixel; - default: - return GL_FALSE; - } - case GL_RG: - if (!ctx->Extensions.ARB_texture_rg) - return GL_FALSE; - - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - return GL_TRUE; - case GL_HALF_FLOAT_ARB: - return ctx->Extensions.ARB_half_float_pixel; - default: - return GL_FALSE; - } - case GL_RGB: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - 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; - case GL_UNSIGNED_INT_10F_11F_11F_REV: - return ctx->Extensions.EXT_packed_float; - default: - return GL_FALSE; - } - case GL_BGR: - switch (type) { - /* NOTE: no packed types are supported with BGR. That's - * intentional, according to the GL spec. - */ - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - return GL_TRUE; - case GL_HALF_FLOAT_ARB: - return ctx->Extensions.ARB_half_float_pixel; - default: - return GL_FALSE; - } - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_4_4_4_4_REV: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - case GL_UNSIGNED_INT_8_8_8_8: - case GL_UNSIGNED_INT_8_8_8_8_REV: - case GL_UNSIGNED_INT_10_10_10_2: - case GL_UNSIGNED_INT_2_10_10_10_REV: - return GL_TRUE; - case GL_HALF_FLOAT_ARB: - return ctx->Extensions.ARB_half_float_pixel; - default: - return GL_FALSE; - } - case GL_YCBCR_MESA: - if (type == GL_UNSIGNED_SHORT_8_8_MESA || - type == GL_UNSIGNED_SHORT_8_8_REV_MESA) - return GL_TRUE; - else - return GL_FALSE; - case GL_DEPTH_STENCIL_EXT: - if (ctx->Extensions.EXT_packed_depth_stencil - && type == GL_UNSIGNED_INT_24_8_EXT) - return GL_TRUE; - else - return GL_FALSE; - case GL_DUDV_ATI: - case GL_DU8DV8_ATI: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - return GL_TRUE; - default: - return GL_FALSE; - } - - /* integer-valued formats */ - case GL_RED_INTEGER_EXT: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA_INTEGER_EXT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - return ctx->Extensions.EXT_texture_integer; - default: - return GL_FALSE; - } - - case GL_RGB_INTEGER_EXT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - return ctx->Extensions.EXT_texture_integer; - default: - return GL_FALSE; - } - - case GL_BGR_INTEGER_EXT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - /* NOTE: no packed formats w/ BGR format */ - return ctx->Extensions.EXT_texture_integer; - default: - return GL_FALSE; - } - - case GL_RGBA_INTEGER_EXT: - case GL_BGRA_INTEGER_EXT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_4_4_4_4_REV: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - case GL_UNSIGNED_INT_8_8_8_8: - case GL_UNSIGNED_INT_8_8_8_8_REV: - case GL_UNSIGNED_INT_10_10_10_2: - case GL_UNSIGNED_INT_2_10_10_10_REV: - return ctx->Extensions.EXT_texture_integer; - default: - return GL_FALSE; - } - - case GL_LUMINANCE_INTEGER_EXT: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - return ctx->Extensions.EXT_texture_integer; - default: - return GL_FALSE; - } - - default: - ; /* fall-through */ - } - return GL_FALSE; -} - - -/** - * Test if the given image format is a color/RGBA format (i.e., not color - * index, depth, stencil, etc). - * \param format the image format value (may by an internal texture format) - * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. - */ -GLboolean -_mesa_is_color_format(GLenum format) -{ - switch (format) { - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - case GL_R8: - case GL_R16: - case GL_RG: - case GL_RG8: - case GL_RG16: - case 3: - case GL_RGB: - case GL_BGR: - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - case 4: - case GL_ABGR_EXT: - case GL_RGBA: - case GL_BGRA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - /* float texture formats */ - case GL_ALPHA16F_ARB: - case GL_ALPHA32F_ARB: - case GL_LUMINANCE16F_ARB: - case GL_LUMINANCE32F_ARB: - case GL_LUMINANCE_ALPHA16F_ARB: - case GL_LUMINANCE_ALPHA32F_ARB: - case GL_INTENSITY16F_ARB: - case GL_INTENSITY32F_ARB: - case GL_R16F: - case GL_R32F: - case GL_RG16F: - case GL_RG32F: - case GL_RGB16F_ARB: - case GL_RGB32F_ARB: - case GL_RGBA16F_ARB: - case GL_RGBA32F_ARB: - /* compressed formats */ - case GL_COMPRESSED_ALPHA: - case GL_COMPRESSED_LUMINANCE: - case GL_COMPRESSED_LUMINANCE_ALPHA: - case GL_COMPRESSED_INTENSITY: - case GL_COMPRESSED_RED: - case GL_COMPRESSED_RG: - case GL_COMPRESSED_RGB: - case GL_COMPRESSED_RGBA: - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - case GL_COMPRESSED_RGB_FXT1_3DFX: - case GL_COMPRESSED_RGBA_FXT1_3DFX: -#if FEATURE_EXT_texture_sRGB - case GL_SRGB_EXT: - case GL_SRGB8_EXT: - case GL_SRGB_ALPHA_EXT: - case GL_SRGB8_ALPHA8_EXT: - case GL_SLUMINANCE_ALPHA_EXT: - case GL_SLUMINANCE8_ALPHA8_EXT: - case GL_SLUMINANCE_EXT: - case GL_SLUMINANCE8_EXT: - case GL_COMPRESSED_SRGB_EXT: - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - case GL_COMPRESSED_SLUMINANCE_EXT: - case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: -#endif /* FEATURE_EXT_texture_sRGB */ - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_SIGNED_RED_RGTC1: - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SIGNED_RG_RGTC2: - case GL_COMPRESSED_LUMINANCE_LATC1_EXT: - case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: - case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: - /* generic integer formats */ - case GL_RED_INTEGER_EXT: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA_INTEGER_EXT: - case GL_RGB_INTEGER_EXT: - case GL_RGBA_INTEGER_EXT: - case GL_BGR_INTEGER_EXT: - case GL_BGRA_INTEGER_EXT: - case GL_LUMINANCE_INTEGER_EXT: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - /* sized integer formats */ - case GL_RGBA32UI_EXT: - case GL_RGB32UI_EXT: - case GL_ALPHA32UI_EXT: - case GL_INTENSITY32UI_EXT: - case GL_LUMINANCE32UI_EXT: - case GL_LUMINANCE_ALPHA32UI_EXT: - case GL_RGBA16UI_EXT: - case GL_RGB16UI_EXT: - case GL_ALPHA16UI_EXT: - case GL_INTENSITY16UI_EXT: - case GL_LUMINANCE16UI_EXT: - case GL_LUMINANCE_ALPHA16UI_EXT: - case GL_RGBA8UI_EXT: - case GL_RGB8UI_EXT: - case GL_ALPHA8UI_EXT: - case GL_INTENSITY8UI_EXT: - case GL_LUMINANCE8UI_EXT: - case GL_LUMINANCE_ALPHA8UI_EXT: - case GL_RGBA32I_EXT: - case GL_RGB32I_EXT: - case GL_ALPHA32I_EXT: - case GL_INTENSITY32I_EXT: - case GL_LUMINANCE32I_EXT: - case GL_LUMINANCE_ALPHA32I_EXT: - case GL_RGBA16I_EXT: - case GL_RGB16I_EXT: - case GL_ALPHA16I_EXT: - case GL_INTENSITY16I_EXT: - case GL_LUMINANCE16I_EXT: - case GL_LUMINANCE_ALPHA16I_EXT: - case GL_RGBA8I_EXT: - case GL_RGB8I_EXT: - case GL_ALPHA8I_EXT: - case GL_INTENSITY8I_EXT: - case GL_LUMINANCE8I_EXT: - case GL_LUMINANCE_ALPHA8I_EXT: - /* signed, normalized texture formats */ - case GL_RED_SNORM: - case GL_R8_SNORM: - case GL_R16_SNORM: - case GL_RG_SNORM: - case GL_RG8_SNORM: - case GL_RG16_SNORM: - case GL_RGB_SNORM: - case GL_RGB8_SNORM: - case GL_RGB16_SNORM: - case GL_RGBA_SNORM: - case GL_RGBA8_SNORM: - case GL_RGBA16_SNORM: - case GL_ALPHA_SNORM: - case GL_ALPHA8_SNORM: - case GL_ALPHA16_SNORM: - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - case GL_LUMINANCE16_SNORM: - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - case GL_LUMINANCE16_ALPHA16_SNORM: - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - case GL_INTENSITY16_SNORM: - case GL_RGB9_E5: - case GL_R11F_G11F_B10F: - return GL_TRUE; - case GL_YCBCR_MESA: /* not considered to be RGB */ - /* fall-through */ - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a color index format. - */ -GLboolean -_mesa_is_index_format(GLenum format) -{ - switch (format) { - case GL_COLOR_INDEX: - case GL_COLOR_INDEX1_EXT: - case GL_COLOR_INDEX2_EXT: - case GL_COLOR_INDEX4_EXT: - case GL_COLOR_INDEX8_EXT: - case GL_COLOR_INDEX12_EXT: - case GL_COLOR_INDEX16_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a depth component format. - */ -GLboolean -_mesa_is_depth_format(GLenum format) -{ - switch (format) { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a stencil format. - */ -GLboolean -_mesa_is_stencil_format(GLenum format) -{ - switch (format) { - case GL_STENCIL_INDEX: - case GL_DEPTH_STENCIL: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a YCbCr format. - */ -GLboolean -_mesa_is_ycbcr_format(GLenum format) -{ - switch (format) { - case GL_YCBCR_MESA: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a depth+stencil format. - */ -GLboolean -_mesa_is_depthstencil_format(GLenum format) -{ - switch (format) { - case GL_DEPTH24_STENCIL8_EXT: - case GL_DEPTH_STENCIL_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a depth or stencil format. - */ -GLboolean -_mesa_is_depth_or_stencil_format(GLenum format) -{ - switch (format) { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - case GL_STENCIL_INDEX: - case GL_STENCIL_INDEX1_EXT: - case GL_STENCIL_INDEX4_EXT: - case GL_STENCIL_INDEX8_EXT: - case GL_STENCIL_INDEX16_EXT: - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given image format is a dudv format. - */ -GLboolean -_mesa_is_dudv_format(GLenum format) -{ - switch (format) { - case GL_DUDV_ATI: - case GL_DU8DV8_ATI: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if the given format is an integer (non-normalized) format. - */ -GLboolean -_mesa_is_integer_format(GLenum format) -{ - switch (format) { - /* generic integer formats */ - case GL_RED_INTEGER_EXT: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA_INTEGER_EXT: - case GL_RGB_INTEGER_EXT: - case GL_RGBA_INTEGER_EXT: - case GL_BGR_INTEGER_EXT: - case GL_BGRA_INTEGER_EXT: - case GL_LUMINANCE_INTEGER_EXT: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - /* specific integer formats */ - case GL_RGBA32UI_EXT: - case GL_RGB32UI_EXT: - case GL_ALPHA32UI_EXT: - case GL_INTENSITY32UI_EXT: - case GL_LUMINANCE32UI_EXT: - case GL_LUMINANCE_ALPHA32UI_EXT: - case GL_RGBA16UI_EXT: - case GL_RGB16UI_EXT: - case GL_ALPHA16UI_EXT: - case GL_INTENSITY16UI_EXT: - case GL_LUMINANCE16UI_EXT: - case GL_LUMINANCE_ALPHA16UI_EXT: - case GL_RGBA8UI_EXT: - case GL_RGB8UI_EXT: - case GL_ALPHA8UI_EXT: - case GL_INTENSITY8UI_EXT: - case GL_LUMINANCE8UI_EXT: - case GL_LUMINANCE_ALPHA8UI_EXT: - case GL_RGBA32I_EXT: - case GL_RGB32I_EXT: - case GL_ALPHA32I_EXT: - case GL_INTENSITY32I_EXT: - case GL_LUMINANCE32I_EXT: - case GL_LUMINANCE_ALPHA32I_EXT: - case GL_RGBA16I_EXT: - case GL_RGB16I_EXT: - case GL_ALPHA16I_EXT: - case GL_INTENSITY16I_EXT: - case GL_LUMINANCE16I_EXT: - case GL_LUMINANCE_ALPHA16I_EXT: - case GL_RGBA8I_EXT: - case GL_RGB8I_EXT: - case GL_ALPHA8I_EXT: - case GL_INTENSITY8I_EXT: - case GL_LUMINANCE8I_EXT: - case GL_LUMINANCE_ALPHA8I_EXT: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -/** - * Test if an image format is a supported compressed format. - * \param format the internal format token provided by the user. - * \return GL_TRUE if compressed, GL_FALSE if uncompressed - */ -GLboolean -_mesa_is_compressed_format(struct gl_context *ctx, GLenum format) -{ - switch (format) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - return ctx->Extensions.EXT_texture_compression_s3tc; - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - return ctx->Extensions.S3_s3tc; - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - return ctx->Extensions.EXT_texture_sRGB - && ctx->Extensions.EXT_texture_compression_s3tc; - case GL_COMPRESSED_RGB_FXT1_3DFX: - case GL_COMPRESSED_RGBA_FXT1_3DFX: - return ctx->Extensions.TDFX_texture_compression_FXT1; - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_SIGNED_RED_RGTC1: - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SIGNED_RG_RGTC2: - return ctx->Extensions.ARB_texture_compression_rgtc; - case GL_COMPRESSED_LUMINANCE_LATC1_EXT: - case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: - return ctx->Extensions.EXT_texture_compression_latc; - case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: - return ctx->Extensions.ATI_texture_compression_3dc; - default: - return GL_FALSE; - } -} - - -/** - * Return the address of a specific pixel in an image (1D, 2D or 3D). - * - * Pixel unpacking/packing parameters are observed according to \p packing. - * - * \param dimensions either 1, 2 or 3 to indicate dimensionality of image - * \param image starting address of image data - * \param width the image width - * \param height theimage height - * \param format the pixel format - * \param type the pixel data type - * \param packing the pixelstore attributes - * \param img which image in the volume (0 for 1D or 2D images) - * \param row row of pixel in the image (0 for 1D images) - * \param column column of pixel in the image - * - * \return address of pixel on success, or NULL on error. - * - * \sa gl_pixelstore_attrib. - */ -GLvoid * -_mesa_image_address( GLuint dimensions, - const struct gl_pixelstore_attrib *packing, - const GLvoid *image, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - GLint img, GLint row, GLint column ) -{ - GLint alignment; /* 1, 2 or 4 */ - GLint pixels_per_row; - GLint rows_per_image; - GLint skiprows; - GLint skippixels; - GLint skipimages; /* for 3-D volume images */ - GLubyte *pixel_addr; - - ASSERT(dimensions >= 1 && dimensions <= 3); - - alignment = packing->Alignment; - if (packing->RowLength > 0) { - pixels_per_row = packing->RowLength; - } - else { - pixels_per_row = width; - } - if (packing->ImageHeight > 0) { - rows_per_image = packing->ImageHeight; - } - else { - rows_per_image = height; - } - - skippixels = packing->SkipPixels; - /* Note: SKIP_ROWS _is_ used for 1D images */ - skiprows = packing->SkipRows; - /* Note: SKIP_IMAGES is only used for 3D images */ - skipimages = (dimensions == 3) ? packing->SkipImages : 0; - - if (type == GL_BITMAP) { - /* BITMAP data */ - GLint comp_per_pixel; /* components per pixel */ - GLint bytes_per_comp; /* bytes per component */ - GLint bytes_per_row; - GLint bytes_per_image; - - /* Compute bytes per component */ - bytes_per_comp = _mesa_sizeof_packed_type( type ); - if (bytes_per_comp < 0) { - return NULL; - } - - /* Compute number of components per pixel */ - comp_per_pixel = _mesa_components_in_format( format ); - if (comp_per_pixel < 0) { - return NULL; - } - - bytes_per_row = alignment - * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); - - bytes_per_image = bytes_per_row * rows_per_image; - - pixel_addr = (GLubyte *) image - + (skipimages + img) * bytes_per_image - + (skiprows + row) * bytes_per_row - + (skippixels + column) / 8; - } - else { - /* Non-BITMAP data */ - GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; - GLint topOfImage; - - bytes_per_pixel = _mesa_bytes_per_pixel( format, type ); - - /* The pixel type and format should have been error checked earlier */ - assert(bytes_per_pixel > 0); - - bytes_per_row = pixels_per_row * bytes_per_pixel; - remainder = bytes_per_row % alignment; - if (remainder > 0) - bytes_per_row += (alignment - remainder); - - ASSERT(bytes_per_row % alignment == 0); - - bytes_per_image = bytes_per_row * rows_per_image; - - if (packing->Invert) { - /* set pixel_addr to the last row */ - topOfImage = bytes_per_row * (height - 1); - bytes_per_row = -bytes_per_row; - } - else { - topOfImage = 0; - } - - /* compute final pixel address */ - pixel_addr = (GLubyte *) image - + (skipimages + img) * bytes_per_image - + topOfImage - + (skiprows + row) * bytes_per_row - + (skippixels + column) * bytes_per_pixel; - } - - return (GLvoid *) pixel_addr; -} - - -GLvoid * -_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, - const GLvoid *image, - GLsizei width, - GLenum format, GLenum type, - GLint column ) -{ - return _mesa_image_address(1, packing, image, width, 1, - format, type, 0, 0, column); -} - - -GLvoid * -_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, - const GLvoid *image, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - GLint row, GLint column ) -{ - return _mesa_image_address(2, packing, image, width, height, - format, type, 0, row, column); -} - - -GLvoid * -_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, - const GLvoid *image, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - GLint img, GLint row, GLint column ) -{ - return _mesa_image_address(3, packing, image, width, height, - format, type, img, row, column); -} - - - -/** - * Compute the stride (in bytes) between image rows. - * - * \param packing the pixelstore attributes - * \param width image width. - * \param format pixel format. - * \param type pixel data type. - * - * \return the stride in bytes for the given parameters, or -1 if error - */ -GLint -_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, - GLint width, GLenum format, GLenum type ) -{ - GLint bytesPerRow, remainder; - - ASSERT(packing); - - if (type == GL_BITMAP) { - if (packing->RowLength == 0) { - bytesPerRow = (width + 7) / 8; - } - else { - bytesPerRow = (packing->RowLength + 7) / 8; - } - } - else { - /* Non-BITMAP data */ - const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); - if (bytesPerPixel <= 0) - return -1; /* error */ - if (packing->RowLength == 0) { - bytesPerRow = bytesPerPixel * width; - } - else { - bytesPerRow = bytesPerPixel * packing->RowLength; - } - } - - remainder = bytesPerRow % packing->Alignment; - if (remainder > 0) { - bytesPerRow += (packing->Alignment - remainder); - } - - if (packing->Invert) { - /* negate the bytes per row (negative row stride) */ - bytesPerRow = -bytesPerRow; - } - - return bytesPerRow; -} - - -/* - * Compute the stride between images in a 3D texture (in bytes) for the given - * pixel packing parameters and image width, format and type. - */ -GLint -_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, - GLint width, GLint height, - GLenum format, GLenum type ) -{ - GLint bytesPerRow, bytesPerImage, remainder; - - ASSERT(packing); - - if (type == GL_BITMAP) { - if (packing->RowLength == 0) { - bytesPerRow = (width + 7) / 8; - } - else { - bytesPerRow = (packing->RowLength + 7) / 8; - } - } - else { - const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); - - if (bytesPerPixel <= 0) - return -1; /* error */ - if (packing->RowLength == 0) { - bytesPerRow = bytesPerPixel * width; - } - else { - bytesPerRow = bytesPerPixel * packing->RowLength; - } - } - - remainder = bytesPerRow % packing->Alignment; - if (remainder > 0) - bytesPerRow += (packing->Alignment - remainder); - - if (packing->ImageHeight == 0) - bytesPerImage = bytesPerRow * height; - else - bytesPerImage = bytesPerRow * packing->ImageHeight; - - return bytesPerImage; -} - - - -/** - * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel. - * This is typically used to convert a bitmap into a GLubyte/pixel texture. - * "On" bits will set texels to \p onValue. - * "Off" bits will not modify texels. - * \param width src bitmap width in pixels - * \param height src bitmap height in pixels - * \param unpack bitmap unpacking state - * \param bitmap the src bitmap data - * \param destBuffer start of dest buffer - * \param destStride row stride in dest buffer - * \param onValue if bit is 1, set destBuffer pixel to this value - */ -void -_mesa_expand_bitmap(GLsizei width, GLsizei height, - const struct gl_pixelstore_attrib *unpack, - const GLubyte *bitmap, - GLubyte *destBuffer, GLint destStride, - GLubyte onValue) -{ - const GLubyte *srcRow = (const GLubyte *) - _mesa_image_address2d(unpack, bitmap, width, height, - GL_COLOR_INDEX, GL_BITMAP, 0, 0); - const GLint srcStride = _mesa_image_row_stride(unpack, width, - GL_COLOR_INDEX, GL_BITMAP); - GLint row, col; - -#define SET_PIXEL(COL, ROW) \ - destBuffer[(ROW) * destStride + (COL)] = onValue; - - for (row = 0; row < height; row++) { - const GLubyte *src = srcRow; - - if (unpack->LsbFirst) { - /* Lsb first */ - GLubyte mask = 1U << (unpack->SkipPixels & 0x7); - for (col = 0; col < width; col++) { - - if (*src & mask) { - SET_PIXEL(col, row); - } - - if (mask == 128U) { - src++; - mask = 1U; - } - else { - mask = mask << 1; - } - } - - /* get ready for next row */ - if (mask != 1) - src++; - } - else { - /* Msb first */ - GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); - for (col = 0; col < width; col++) { - - if (*src & mask) { - SET_PIXEL(col, row); - } - - if (mask == 1U) { - src++; - mask = 128U; - } - else { - mask = mask >> 1; - } - } - - /* get ready for next row */ - if (mask != 128) - src++; - } - - srcRow += srcStride; - } /* row */ - -#undef SET_PIXEL -} - - - - -/** - * Convert an array of RGBA colors from one datatype to another. - * NOTE: src may equal dst. In that case, we use a temporary buffer. - */ -void -_mesa_convert_colors(GLenum srcType, const GLvoid *src, - GLenum dstType, GLvoid *dst, - GLuint count, const GLubyte mask[]) -{ - GLuint tempBuffer[MAX_WIDTH][4]; - const GLboolean useTemp = (src == dst); - - ASSERT(srcType != dstType); - - switch (srcType) { - case GL_UNSIGNED_BYTE: - if (dstType == GL_UNSIGNED_SHORT) { - const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; - GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); - GLuint i; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]); - dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]); - dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]); - dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]); - } - } - if (useTemp) - memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); - } - else { - const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; - GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); - GLuint i; - ASSERT(dstType == GL_FLOAT); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]); - dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]); - dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]); - dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]); - } - } - if (useTemp) - memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); - } - break; - case GL_UNSIGNED_SHORT: - if (dstType == GL_UNSIGNED_BYTE) { - const GLushort (*src2)[4] = (const GLushort (*)[4]) src; - GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); - GLuint i; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]); - dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]); - dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]); - dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]); - } - } - if (useTemp) - memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); - } - else { - const GLushort (*src2)[4] = (const GLushort (*)[4]) src; - GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); - GLuint i; - ASSERT(dstType == GL_FLOAT); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]); - dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]); - dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]); - dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]); - } - } - if (useTemp) - memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); - } - break; - case GL_FLOAT: - if (dstType == GL_UNSIGNED_BYTE) { - const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; - GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); - GLuint i; - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]); - UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]); - } - } - if (useTemp) - memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); - } - else { - const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; - GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); - GLuint i; - ASSERT(dstType == GL_UNSIGNED_SHORT); - for (i = 0; i < count; i++) { - if (!mask || mask[i]) { - UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]); - UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]); - } - } - if (useTemp) - memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); - } - break; - default: - _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors"); - } -} - - - - -/** - * Perform basic clipping for glDrawPixels. The image's position and size - * and the unpack SkipPixels and SkipRows are adjusted so that the image - * region is entirely within the window and scissor bounds. - * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1). - * If Pixel.ZoomY is -1, *destY will be changed to be the first row which - * we'll actually write. Beforehand, *destY-1 is the first drawing row. - * - * \return GL_TRUE if image is ready for drawing or - * GL_FALSE if image was completely clipped away (draw nothing) - */ -GLboolean -_mesa_clip_drawpixels(const struct gl_context *ctx, - GLint *destX, GLint *destY, - GLsizei *width, GLsizei *height, - struct gl_pixelstore_attrib *unpack) -{ - const struct gl_framebuffer *buffer = ctx->DrawBuffer; - - if (unpack->RowLength == 0) { - unpack->RowLength = *width; - } - - ASSERT(ctx->Pixel.ZoomX == 1.0F); - ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F); - - /* left clipping */ - if (*destX < buffer->_Xmin) { - unpack->SkipPixels += (buffer->_Xmin - *destX); - *width -= (buffer->_Xmin - *destX); - *destX = buffer->_Xmin; - } - /* right clipping */ - if (*destX + *width > buffer->_Xmax) - *width -= (*destX + *width - buffer->_Xmax); - - if (*width <= 0) - return GL_FALSE; - - if (ctx->Pixel.ZoomY == 1.0F) { - /* bottom clipping */ - if (*destY < buffer->_Ymin) { - unpack->SkipRows += (buffer->_Ymin - *destY); - *height -= (buffer->_Ymin - *destY); - *destY = buffer->_Ymin; - } - /* top clipping */ - if (*destY + *height > buffer->_Ymax) - *height -= (*destY + *height - buffer->_Ymax); - } - else { /* upside down */ - /* top clipping */ - if (*destY > buffer->_Ymax) { - unpack->SkipRows += (*destY - buffer->_Ymax); - *height -= (*destY - buffer->_Ymax); - *destY = buffer->_Ymax; - } - /* bottom clipping */ - if (*destY - *height < buffer->_Ymin) - *height -= (buffer->_Ymin - (*destY - *height)); - /* adjust destY so it's the first row to write to */ - (*destY)--; - } - - if (*height <= 0) - return GL_FALSE; - - return GL_TRUE; -} - - -/** - * Perform clipping for glReadPixels. The image's window position - * and size, and the pack skipPixels, skipRows and rowLength are adjusted - * so that the image region is entirely within the window bounds. - * Note: this is different from _mesa_clip_drawpixels() in that the - * scissor box is ignored, and we use the bounds of the current readbuffer - * surface. - * - * \return GL_TRUE if region to read is in bounds - * GL_FALSE if region is completely out of bounds (nothing to read) - */ -GLboolean -_mesa_clip_readpixels(const struct gl_context *ctx, - GLint *srcX, GLint *srcY, - GLsizei *width, GLsizei *height, - struct gl_pixelstore_attrib *pack) -{ - const struct gl_framebuffer *buffer = ctx->ReadBuffer; - - if (pack->RowLength == 0) { - pack->RowLength = *width; - } - - /* left clipping */ - if (*srcX < 0) { - pack->SkipPixels += (0 - *srcX); - *width -= (0 - *srcX); - *srcX = 0; - } - /* right clipping */ - if (*srcX + *width > (GLsizei) buffer->Width) - *width -= (*srcX + *width - buffer->Width); - - if (*width <= 0) - return GL_FALSE; - - /* bottom clipping */ - if (*srcY < 0) { - pack->SkipRows += (0 - *srcY); - *height -= (0 - *srcY); - *srcY = 0; - } - /* top clipping */ - if (*srcY + *height > (GLsizei) buffer->Height) - *height -= (*srcY + *height - buffer->Height); - - if (*height <= 0) - return GL_FALSE; - - return GL_TRUE; -} - - -/** - * Do clipping for a glCopyTexSubImage call. - * The framebuffer source region might extend outside the framebuffer - * bounds. Clip the source region against the framebuffer bounds and - * adjust the texture/dest position and size accordingly. - * - * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise. - */ -GLboolean -_mesa_clip_copytexsubimage(const struct gl_context *ctx, - GLint *destX, GLint *destY, - GLint *srcX, GLint *srcY, - GLsizei *width, GLsizei *height) -{ - const struct gl_framebuffer *fb = ctx->ReadBuffer; - const GLint srcX0 = *srcX, srcY0 = *srcY; - - if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height, - srcX, srcY, width, height)) { - *destX = *destX + *srcX - srcX0; - *destY = *destY + *srcY - srcY0; - - return GL_TRUE; - } - else { - return GL_FALSE; - } -} - - - -/** - * Clip the rectangle defined by (x, y, width, height) against the bounds - * specified by [xmin, xmax) and [ymin, ymax). - * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise. - */ -GLboolean -_mesa_clip_to_region(GLint xmin, GLint ymin, - GLint xmax, GLint ymax, - GLint *x, GLint *y, - GLsizei *width, GLsizei *height ) -{ - /* left clipping */ - if (*x < xmin) { - *width -= (xmin - *x); - *x = xmin; - } - - /* right clipping */ - if (*x + *width > xmax) - *width -= (*x + *width - xmax); - - if (*width <= 0) - return GL_FALSE; - - /* bottom (or top) clipping */ - if (*y < ymin) { - *height -= (ymin - *y); - *y = ymin; - } - - /* top (or bottom) clipping */ - if (*y + *height > ymax) - *height -= (*y + *height - ymax); - - if (*height <= 0) - return GL_FALSE; - - return GL_TRUE; -} - - -/** - * Clip dst coords against Xmax (or Ymax). - */ -static INLINE void -clip_right_or_top(GLint *srcX0, GLint *srcX1, - GLint *dstX0, GLint *dstX1, - GLint maxValue) -{ - GLfloat t, bias; - - if (*dstX1 > maxValue) { - /* X1 outside right edge */ - ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ - t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); - /* chop off [t, 1] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX1 = maxValue; - bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; - *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); - } - else if (*dstX0 > maxValue) { - /* X0 outside right edge */ - ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ - t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); - /* chop off [t, 1] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX0 = maxValue; - bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; - *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); - } -} - - -/** - * Clip dst coords against Xmin (or Ymin). - */ -static INLINE void -clip_left_or_bottom(GLint *srcX0, GLint *srcX1, - GLint *dstX0, GLint *dstX1, - GLint minValue) -{ - GLfloat t, bias; - - if (*dstX0 < minValue) { - /* X0 outside left edge */ - ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ - t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); - /* chop off [0, t] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX0 = minValue; - bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; /* flipped??? */ - *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); - } - else if (*dstX1 < minValue) { - /* X1 outside left edge */ - ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ - t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); - /* chop off [0, t] part */ - ASSERT(t >= 0.0 && t <= 1.0); - *dstX1 = minValue; - bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; - *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); - } -} - - -/** - * Do clipping of blit src/dest rectangles. - * The dest rect is clipped against both the buffer bounds and scissor bounds. - * The src rect is just clipped against the buffer bounds. - * - * When either the src or dest rect is clipped, the other is also clipped - * proportionately! - * - * Note that X0 need not be less than X1 (same for Y) for either the source - * and dest rects. That makes the clipping a little trickier. - * - * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped - */ -GLboolean -_mesa_clip_blit(struct gl_context *ctx, - GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, - GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) -{ - const GLint srcXmin = 0; - const GLint srcXmax = ctx->ReadBuffer->Width; - const GLint srcYmin = 0; - const GLint srcYmax = ctx->ReadBuffer->Height; - - /* these include scissor bounds */ - const GLint dstXmin = ctx->DrawBuffer->_Xmin; - const GLint dstXmax = ctx->DrawBuffer->_Xmax; - const GLint dstYmin = ctx->DrawBuffer->_Ymin; - const GLint dstYmax = ctx->DrawBuffer->_Ymax; - - /* - printf("PreClipX: src: %d .. %d dst: %d .. %d\n", - *srcX0, *srcX1, *dstX0, *dstX1); - printf("PreClipY: src: %d .. %d dst: %d .. %d\n", - *srcY0, *srcY1, *dstY0, *dstY1); - */ - - /* trivial rejection tests */ - if (*dstX0 == *dstX1) - return GL_FALSE; /* no width */ - if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) - return GL_FALSE; /* totally out (left) of bounds */ - if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) - return GL_FALSE; /* totally out (right) of bounds */ - - if (*dstY0 == *dstY1) - return GL_FALSE; - if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) - return GL_FALSE; - if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) - return GL_FALSE; - - if (*srcX0 == *srcX1) - return GL_FALSE; - if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) - return GL_FALSE; - if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) - return GL_FALSE; - - if (*srcY0 == *srcY1) - return GL_FALSE; - if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) - return GL_FALSE; - if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) - return GL_FALSE; - - /* - * dest clip - */ - clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); - clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); - clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); - clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); - - /* - * src clip (just swap src/dst values from above) - */ - clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); - clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); - clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); - clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); - - /* - printf("PostClipX: src: %d .. %d dst: %d .. %d\n", - *srcX0, *srcX1, *dstX0, *dstX1); - printf("PostClipY: src: %d .. %d dst: %d .. %d\n", - *srcY0, *srcY1, *dstY0, *dstY1); - */ - - ASSERT(*dstX0 >= dstXmin); - ASSERT(*dstX0 <= dstXmax); - ASSERT(*dstX1 >= dstXmin); - ASSERT(*dstX1 <= dstXmax); - - ASSERT(*dstY0 >= dstYmin); - ASSERT(*dstY0 <= dstYmax); - ASSERT(*dstY1 >= dstYmin); - ASSERT(*dstY1 <= dstYmax); - - ASSERT(*srcX0 >= srcXmin); - ASSERT(*srcX0 <= srcXmax); - ASSERT(*srcX1 >= srcXmin); - ASSERT(*srcX1 <= srcXmax); - - ASSERT(*srcY0 >= srcYmin); - ASSERT(*srcY0 <= srcYmax); - ASSERT(*srcY1 >= srcYmin); - ASSERT(*srcY1 <= srcYmax); - - return GL_TRUE; -} +/* + * Mesa 3-D graphics library + * Version: 7.5 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * 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 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 + * BRIAN PAUL 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. + */ + + +/** + * \file image.c + * Image handling. + */ + + +#include "glheader.h" +#include "colormac.h" +#include "image.h" +#include "imports.h" +#include "macros.h" +#include "mfeatures.h" +#include "mtypes.h" + + +/** + * NOTE: + * Normally, BYTE_TO_FLOAT(0) returns 0.00392 That causes problems when + * we later convert the float to a packed integer value (such as for + * GL_RGB5_A1) because we'll wind up with a non-zero value. + * + * We redefine the macros here so zero is handled correctly. + */ +#undef BYTE_TO_FLOAT +#define BYTE_TO_FLOAT(B) ((B) == 0 ? 0.0F : ((2.0F * (B) + 1.0F) * (1.0F/255.0F))) + +#undef SHORT_TO_FLOAT +#define SHORT_TO_FLOAT(S) ((S) == 0 ? 0.0F : ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))) + + + +/** Compute ceiling of integer quotient of A divided by B. */ +#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) + + +/** + * \return GL_TRUE if type is packed pixel type, GL_FALSE otherwise. + */ +GLboolean +_mesa_type_is_packed(GLenum type) +{ + switch (type) { + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case MESA_UNSIGNED_BYTE_4_4: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + 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: + case GL_UNSIGNED_INT_10F_11F_11F_REV: + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + return GL_TRUE; + } + + return GL_FALSE; +} + + + +/** + * Flip the order of the 2 bytes in each word in the given array. + * + * \param p array. + * \param n number of words. + */ +void +_mesa_swap2( GLushort *p, GLuint n ) +{ + GLuint i; + for (i = 0; i < n; i++) { + p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); + } +} + + + +/* + * Flip the order of the 4 bytes in each word in the given array. + */ +void +_mesa_swap4( GLuint *p, GLuint n ) +{ + GLuint i, a, b; + for (i = 0; i < n; i++) { + b = p[i]; + a = (b >> 24) + | ((b >> 8) & 0xff00) + | ((b << 8) & 0xff0000) + | ((b << 24) & 0xff000000); + p[i] = a; + } +} + + +/** + * Get the size of a GL data type. + * + * \param type GL data type. + * + * \return the size, in bytes, of the given data type, 0 if a GL_BITMAP, or -1 + * if an invalid type enum. + */ +GLint +_mesa_sizeof_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_DOUBLE: + return sizeof(GLdouble); + case GL_HALF_FLOAT_ARB: + return sizeof(GLhalfARB); + case GL_FIXED: + return sizeof(GLfixed); + default: + return -1; + } +} + + +/** + * Same as _mesa_sizeof_type() but also accepting the packed pixel + * format data types. + */ +GLint +_mesa_sizeof_packed_type( GLenum type ) +{ + switch (type) { + case GL_BITMAP: + return 0; + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_INT: + return sizeof(GLint); + case GL_HALF_FLOAT_ARB: + return sizeof(GLhalfARB); + case GL_FLOAT: + return sizeof(GLfloat); + case GL_UNSIGNED_BYTE_3_3_2: + return sizeof(GLubyte); + case GL_UNSIGNED_BYTE_2_3_3_REV: + return sizeof(GLubyte); + case MESA_UNSIGNED_BYTE_4_4: + return sizeof(GLubyte); + case GL_UNSIGNED_SHORT_5_6_5: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_5_6_5_REV: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_4_4_4_4: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_5_5_5_1: + return sizeof(GLushort); + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + return sizeof(GLushort); + case GL_UNSIGNED_INT_8_8_8_8: + return sizeof(GLuint); + case GL_UNSIGNED_INT_8_8_8_8_REV: + return sizeof(GLuint); + case GL_UNSIGNED_INT_10_10_10_2: + return sizeof(GLuint); + case GL_UNSIGNED_INT_2_10_10_10_REV: + return sizeof(GLuint); + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + 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); + case GL_UNSIGNED_INT_10F_11F_11F_REV: + return sizeof(GLuint); + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + return 8; + default: + return -1; + } +} + + +/** + * Get the number of components in a pixel format. + * + * \param format pixel format. + * + * \return the number of components in the given format, or -1 if a bad format. + */ +GLint +_mesa_components_in_format( GLenum format ) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_RED_INTEGER_EXT: + case GL_GREEN: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA: + case GL_ALPHA_INTEGER_EXT: + case GL_LUMINANCE: + case GL_LUMINANCE_INTEGER_EXT: + case GL_INTENSITY: + return 1; + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + case GL_RG: + return 2; + case GL_RGB: + case GL_RGB_INTEGER_EXT: + return 3; + case GL_RGBA: + case GL_RGBA_INTEGER_EXT: + return 4; + case GL_BGR: + return 3; + case GL_BGRA: + return 4; + case GL_ABGR_EXT: + return 4; + case GL_YCBCR_MESA: + return 2; + case GL_DEPTH_STENCIL_EXT: + return 2; + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + return 2; + default: + return -1; + } +} + + +/** + * Get the bytes per pixel of pixel format type pair. + * + * \param format pixel format. + * \param type pixel type. + * + * \return bytes per pixel, or -1 if a bad format or type was given. + */ +GLint +_mesa_bytes_per_pixel( GLenum format, GLenum type ) +{ + GLint comps = _mesa_components_in_format( format ); + if (comps < 0) + return -1; + + switch (type) { + case GL_BITMAP: + return 0; /* special case */ + case GL_BYTE: + case GL_UNSIGNED_BYTE: + return comps * sizeof(GLubyte); + case GL_SHORT: + case GL_UNSIGNED_SHORT: + return comps * sizeof(GLshort); + case GL_INT: + case GL_UNSIGNED_INT: + return comps * sizeof(GLint); + case GL_FLOAT: + return comps * sizeof(GLfloat); + case GL_HALF_FLOAT_ARB: + return comps * sizeof(GLhalfARB); + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + if (format == GL_RGB || format == GL_BGR || + format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT) + return sizeof(GLubyte); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + if (format == GL_RGB || format == GL_BGR || + format == GL_RGB_INTEGER_EXT || format == GL_BGR_INTEGER_EXT) + return sizeof(GLushort); + else + return -1; /* error */ + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT || + format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) + return sizeof(GLushort); + else + return -1; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT || + format == GL_RGBA_INTEGER_EXT || format == GL_BGRA_INTEGER_EXT) + return sizeof(GLuint); + else + return -1; + case GL_UNSIGNED_SHORT_8_8_MESA: + case GL_UNSIGNED_SHORT_8_8_REV_MESA: + if (format == GL_YCBCR_MESA) + return sizeof(GLushort); + else + return -1; + case GL_UNSIGNED_INT_24_8_EXT: + if (format == GL_DEPTH_STENCIL_EXT) + 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; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + if (format == GL_RGB) + return sizeof(GLuint); + else + return -1; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + if (format == GL_DEPTH_STENCIL) + return 8; + else + return -1; + default: + return -1; + } +} + + +/** + * Test for a legal pixel format and type. + * + * \param format pixel format. + * \param type pixel type. + * + * \return GL_TRUE if the given pixel format and type are legal, or GL_FALSE + * otherwise. + */ +GLboolean +_mesa_is_legal_format_and_type(const struct gl_context *ctx, + GLenum format, GLenum type) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + switch (type) { + case GL_BITMAP: + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: +#if 0 /* not legal! see table 3.6 of the 1.5 spec */ + case GL_INTENSITY: +#endif + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_DEPTH_COMPONENT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RG: + if (!ctx->Extensions.ARB_texture_rg) + return GL_FALSE; + + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RGB: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + 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; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + return ctx->Extensions.EXT_packed_float; + default: + return GL_FALSE; + } + case GL_BGR: + switch (type) { + /* NOTE: no packed types are supported with BGR. That's + * intentional, according to the GL spec. + */ + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return GL_TRUE; + case GL_HALF_FLOAT_ARB: + return ctx->Extensions.ARB_half_float_pixel; + default: + return GL_FALSE; + } + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_MESA || + type == GL_UNSIGNED_SHORT_8_8_REV_MESA) + return GL_TRUE; + else + return GL_FALSE; + case GL_DEPTH_STENCIL_EXT: + if ((ctx->Extensions.EXT_packed_depth_stencil && + type == GL_UNSIGNED_INT_24_8_EXT) || + (ctx->Extensions.ARB_depth_buffer_float && + type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)) + return GL_TRUE; + else + return GL_FALSE; + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + return GL_TRUE; + default: + return GL_FALSE; + } + + /* integer-valued formats */ + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_RGB_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_BGR_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + /* NOTE: no packed formats w/ BGR format */ + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_RGBA_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + return ctx->Extensions.EXT_texture_integer; + default: + return GL_FALSE; + } + + default: + ; /* fall-through */ + } + return GL_FALSE; +} + + +/** + * Test if the given image format is a color/RGBA format (i.e., not color + * index, depth, stencil, etc). + * \param format the image format value (may by an internal texture format) + * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. + */ +GLboolean +_mesa_is_color_format(GLenum format) +{ + switch (format) { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_R8: + case GL_R16: + case GL_RG: + case GL_RG8: + case GL_RG16: + case 3: + case GL_RGB: + case GL_BGR: + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case 4: + case GL_ABGR_EXT: + case GL_RGBA: + case GL_BGRA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + /* float texture formats */ + case GL_ALPHA16F_ARB: + case GL_ALPHA32F_ARB: + case GL_LUMINANCE16F_ARB: + case GL_LUMINANCE32F_ARB: + case GL_LUMINANCE_ALPHA16F_ARB: + case GL_LUMINANCE_ALPHA32F_ARB: + case GL_INTENSITY16F_ARB: + case GL_INTENSITY32F_ARB: + case GL_R16F: + case GL_R32F: + case GL_RG16F: + case GL_RG32F: + case GL_RGB16F_ARB: + case GL_RGB32F_ARB: + case GL_RGBA16F_ARB: + case GL_RGBA32F_ARB: + /* compressed formats */ + case GL_COMPRESSED_ALPHA: + case GL_COMPRESSED_LUMINANCE: + case GL_COMPRESSED_LUMINANCE_ALPHA: + case GL_COMPRESSED_INTENSITY: + case GL_COMPRESSED_RED: + case GL_COMPRESSED_RG: + case GL_COMPRESSED_RGB: + case GL_COMPRESSED_RGBA: + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: +#if FEATURE_EXT_texture_sRGB + case GL_SRGB_EXT: + case GL_SRGB8_EXT: + case GL_SRGB_ALPHA_EXT: + case GL_SRGB8_ALPHA8_EXT: + case GL_SLUMINANCE_ALPHA_EXT: + case GL_SLUMINANCE8_ALPHA8_EXT: + case GL_SLUMINANCE_EXT: + case GL_SLUMINANCE8_EXT: + case GL_COMPRESSED_SRGB_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SLUMINANCE_EXT: + case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: +#endif /* FEATURE_EXT_texture_sRGB */ + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + case GL_COMPRESSED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: + /* generic integer formats */ + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_RGB_INTEGER_EXT: + case GL_RGBA_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + /* sized integer formats */ + case GL_RGBA32UI_EXT: + case GL_RGB32UI_EXT: + case GL_ALPHA32UI_EXT: + case GL_INTENSITY32UI_EXT: + case GL_LUMINANCE32UI_EXT: + case GL_LUMINANCE_ALPHA32UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGB16UI_EXT: + case GL_ALPHA16UI_EXT: + case GL_INTENSITY16UI_EXT: + case GL_LUMINANCE16UI_EXT: + case GL_LUMINANCE_ALPHA16UI_EXT: + case GL_RGBA8UI_EXT: + case GL_RGB8UI_EXT: + case GL_ALPHA8UI_EXT: + case GL_INTENSITY8UI_EXT: + case GL_LUMINANCE8UI_EXT: + case GL_LUMINANCE_ALPHA8UI_EXT: + case GL_RGBA32I_EXT: + case GL_RGB32I_EXT: + case GL_ALPHA32I_EXT: + case GL_INTENSITY32I_EXT: + case GL_LUMINANCE32I_EXT: + case GL_LUMINANCE_ALPHA32I_EXT: + case GL_RGBA16I_EXT: + case GL_RGB16I_EXT: + case GL_ALPHA16I_EXT: + case GL_INTENSITY16I_EXT: + case GL_LUMINANCE16I_EXT: + case GL_LUMINANCE_ALPHA16I_EXT: + case GL_RGBA8I_EXT: + case GL_RGB8I_EXT: + case GL_ALPHA8I_EXT: + case GL_INTENSITY8I_EXT: + case GL_LUMINANCE8I_EXT: + case GL_LUMINANCE_ALPHA8I_EXT: + /* signed, normalized texture formats */ + case GL_RED_SNORM: + case GL_R8_SNORM: + case GL_R16_SNORM: + case GL_RG_SNORM: + case GL_RG8_SNORM: + case GL_RG16_SNORM: + case GL_RGB_SNORM: + case GL_RGB8_SNORM: + case GL_RGB16_SNORM: + case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: + case GL_RGBA16_SNORM: + case GL_ALPHA_SNORM: + case GL_ALPHA8_SNORM: + case GL_ALPHA16_SNORM: + case GL_LUMINANCE_SNORM: + case GL_LUMINANCE8_SNORM: + case GL_LUMINANCE16_SNORM: + case GL_LUMINANCE_ALPHA_SNORM: + case GL_LUMINANCE8_ALPHA8_SNORM: + case GL_LUMINANCE16_ALPHA16_SNORM: + case GL_INTENSITY_SNORM: + case GL_INTENSITY8_SNORM: + case GL_INTENSITY16_SNORM: + case GL_RGB9_E5: + case GL_R11F_G11F_B10F: + return GL_TRUE; + case GL_YCBCR_MESA: /* not considered to be RGB */ + /* fall-through */ + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a color index format. + */ +GLboolean +_mesa_is_index_format(GLenum format) +{ + switch (format) { + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth component format. + */ +GLboolean +_mesa_is_depth_format(GLenum format) +{ + switch (format) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + case GL_DEPTH_COMPONENT32F: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a stencil format. + */ +GLboolean +_mesa_is_stencil_format(GLenum format) +{ + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_STENCIL: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a YCbCr format. + */ +GLboolean +_mesa_is_ycbcr_format(GLenum format) +{ + switch (format) { + case GL_YCBCR_MESA: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth+stencil format. + */ +GLboolean +_mesa_is_depthstencil_format(GLenum format) +{ + switch (format) { + case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH32F_STENCIL8: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a depth or stencil format. + */ +GLboolean +_mesa_is_depth_or_stencil_format(GLenum format) +{ + switch (format) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1_EXT: + case GL_STENCIL_INDEX4_EXT: + case GL_STENCIL_INDEX8_EXT: + case GL_STENCIL_INDEX16_EXT: + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_COMPONENT32F: + case GL_DEPTH32F_STENCIL8: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given image format is a dudv format. + */ +GLboolean +_mesa_is_dudv_format(GLenum format) +{ + switch (format) { + case GL_DUDV_ATI: + case GL_DU8DV8_ATI: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if the given format is an integer (non-normalized) format. + */ +GLboolean +_mesa_is_integer_format(GLenum format) +{ + switch (format) { + /* generic integer formats */ + case GL_RED_INTEGER_EXT: + case GL_GREEN_INTEGER_EXT: + case GL_BLUE_INTEGER_EXT: + case GL_ALPHA_INTEGER_EXT: + case GL_RGB_INTEGER_EXT: + case GL_RGBA_INTEGER_EXT: + case GL_BGR_INTEGER_EXT: + case GL_BGRA_INTEGER_EXT: + case GL_LUMINANCE_INTEGER_EXT: + case GL_LUMINANCE_ALPHA_INTEGER_EXT: + /* specific integer formats */ + case GL_RGBA32UI_EXT: + case GL_RGB32UI_EXT: + case GL_ALPHA32UI_EXT: + case GL_INTENSITY32UI_EXT: + case GL_LUMINANCE32UI_EXT: + case GL_LUMINANCE_ALPHA32UI_EXT: + case GL_RGBA16UI_EXT: + case GL_RGB16UI_EXT: + case GL_ALPHA16UI_EXT: + case GL_INTENSITY16UI_EXT: + case GL_LUMINANCE16UI_EXT: + case GL_LUMINANCE_ALPHA16UI_EXT: + case GL_RGBA8UI_EXT: + case GL_RGB8UI_EXT: + case GL_ALPHA8UI_EXT: + case GL_INTENSITY8UI_EXT: + case GL_LUMINANCE8UI_EXT: + case GL_LUMINANCE_ALPHA8UI_EXT: + case GL_RGBA32I_EXT: + case GL_RGB32I_EXT: + case GL_ALPHA32I_EXT: + case GL_INTENSITY32I_EXT: + case GL_LUMINANCE32I_EXT: + case GL_LUMINANCE_ALPHA32I_EXT: + case GL_RGBA16I_EXT: + case GL_RGB16I_EXT: + case GL_ALPHA16I_EXT: + case GL_INTENSITY16I_EXT: + case GL_LUMINANCE16I_EXT: + case GL_LUMINANCE_ALPHA16I_EXT: + case GL_RGBA8I_EXT: + case GL_RGB8I_EXT: + case GL_ALPHA8I_EXT: + case GL_INTENSITY8I_EXT: + case GL_LUMINANCE8I_EXT: + case GL_LUMINANCE_ALPHA8I_EXT: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + +/** + * Test if an image format is a supported compressed format. + * \param format the internal format token provided by the user. + * \return GL_TRUE if compressed, GL_FALSE if uncompressed + */ +GLboolean +_mesa_is_compressed_format(struct gl_context *ctx, GLenum format) +{ + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return ctx->Extensions.EXT_texture_compression_s3tc; + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + return ctx->Extensions.S3_s3tc; + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + return ctx->Extensions.EXT_texture_sRGB + && ctx->Extensions.EXT_texture_compression_s3tc; + case GL_COMPRESSED_RGB_FXT1_3DFX: + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return ctx->Extensions.TDFX_texture_compression_FXT1; + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + return ctx->Extensions.ARB_texture_compression_rgtc; + case GL_COMPRESSED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT: + case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: + case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: + return ctx->Extensions.EXT_texture_compression_latc; + case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: + return ctx->Extensions.ATI_texture_compression_3dc; + default: + return GL_FALSE; + } +} + + +/** + * Return the address of a specific pixel in an image (1D, 2D or 3D). + * + * Pixel unpacking/packing parameters are observed according to \p packing. + * + * \param dimensions either 1, 2 or 3 to indicate dimensionality of image + * \param image starting address of image data + * \param width the image width + * \param height theimage height + * \param format the pixel format + * \param type the pixel data type + * \param packing the pixelstore attributes + * \param img which image in the volume (0 for 1D or 2D images) + * \param row row of pixel in the image (0 for 1D images) + * \param column column of pixel in the image + * + * \return address of pixel on success, or NULL on error. + * + * \sa gl_pixelstore_attrib. + */ +GLvoid * +_mesa_image_address( GLuint dimensions, + const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + GLint alignment; /* 1, 2 or 4 */ + GLint pixels_per_row; + GLint rows_per_image; + GLint skiprows; + GLint skippixels; + GLint skipimages; /* for 3-D volume images */ + GLubyte *pixel_addr; + + ASSERT(dimensions >= 1 && dimensions <= 3); + + alignment = packing->Alignment; + if (packing->RowLength > 0) { + pixels_per_row = packing->RowLength; + } + else { + pixels_per_row = width; + } + if (packing->ImageHeight > 0) { + rows_per_image = packing->ImageHeight; + } + else { + rows_per_image = height; + } + + skippixels = packing->SkipPixels; + /* Note: SKIP_ROWS _is_ used for 1D images */ + skiprows = packing->SkipRows; + /* Note: SKIP_IMAGES is only used for 3D images */ + skipimages = (dimensions == 3) ? packing->SkipImages : 0; + + if (type == GL_BITMAP) { + /* BITMAP data */ + GLint comp_per_pixel; /* components per pixel */ + GLint bytes_per_comp; /* bytes per component */ + GLint bytes_per_row; + GLint bytes_per_image; + + /* Compute bytes per component */ + bytes_per_comp = _mesa_sizeof_packed_type( type ); + if (bytes_per_comp < 0) { + return NULL; + } + + /* Compute number of components per pixel */ + comp_per_pixel = _mesa_components_in_format( format ); + if (comp_per_pixel < 0) { + return NULL; + } + + bytes_per_row = alignment + * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); + + bytes_per_image = bytes_per_row * rows_per_image; + + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + (skiprows + row) * bytes_per_row + + (skippixels + column) / 8; + } + else { + /* Non-BITMAP data */ + GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image; + GLint topOfImage; + + bytes_per_pixel = _mesa_bytes_per_pixel( format, type ); + + /* The pixel type and format should have been error checked earlier */ + assert(bytes_per_pixel > 0); + + bytes_per_row = pixels_per_row * bytes_per_pixel; + remainder = bytes_per_row % alignment; + if (remainder > 0) + bytes_per_row += (alignment - remainder); + + ASSERT(bytes_per_row % alignment == 0); + + bytes_per_image = bytes_per_row * rows_per_image; + + if (packing->Invert) { + /* set pixel_addr to the last row */ + topOfImage = bytes_per_row * (height - 1); + bytes_per_row = -bytes_per_row; + } + else { + topOfImage = 0; + } + + /* compute final pixel address */ + pixel_addr = (GLubyte *) image + + (skipimages + img) * bytes_per_image + + topOfImage + + (skiprows + row) * bytes_per_row + + (skippixels + column) * bytes_per_pixel; + } + + return (GLvoid *) pixel_addr; +} + + +GLvoid * +_mesa_image_address1d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, + GLenum format, GLenum type, + GLint column ) +{ + return _mesa_image_address(1, packing, image, width, 1, + format, type, 0, 0, column); +} + + +GLvoid * +_mesa_image_address2d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint row, GLint column ) +{ + return _mesa_image_address(2, packing, image, width, height, + format, type, 0, row, column); +} + + +GLvoid * +_mesa_image_address3d( const struct gl_pixelstore_attrib *packing, + const GLvoid *image, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLint img, GLint row, GLint column ) +{ + return _mesa_image_address(3, packing, image, width, height, + format, type, img, row, column); +} + + + +/** + * Compute the stride (in bytes) between image rows. + * + * \param packing the pixelstore attributes + * \param width image width. + * \param format pixel format. + * \param type pixel data type. + * + * \return the stride in bytes for the given parameters, or -1 if error + */ +GLint +_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLenum format, GLenum type ) +{ + GLint bytesPerRow, remainder; + + ASSERT(packing); + + if (type == GL_BITMAP) { + if (packing->RowLength == 0) { + bytesPerRow = (width + 7) / 8; + } + else { + bytesPerRow = (packing->RowLength + 7) / 8; + } + } + else { + /* Non-BITMAP data */ + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + if (bytesPerPixel <= 0) + return -1; /* error */ + if (packing->RowLength == 0) { + bytesPerRow = bytesPerPixel * width; + } + else { + bytesPerRow = bytesPerPixel * packing->RowLength; + } + } + + remainder = bytesPerRow % packing->Alignment; + if (remainder > 0) { + bytesPerRow += (packing->Alignment - remainder); + } + + if (packing->Invert) { + /* negate the bytes per row (negative row stride) */ + bytesPerRow = -bytesPerRow; + } + + return bytesPerRow; +} + + +/* + * Compute the stride between images in a 3D texture (in bytes) for the given + * pixel packing parameters and image width, format and type. + */ +GLint +_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing, + GLint width, GLint height, + GLenum format, GLenum type ) +{ + GLint bytesPerRow, bytesPerImage, remainder; + + ASSERT(packing); + + if (type == GL_BITMAP) { + if (packing->RowLength == 0) { + bytesPerRow = (width + 7) / 8; + } + else { + bytesPerRow = (packing->RowLength + 7) / 8; + } + } + else { + const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type); + + if (bytesPerPixel <= 0) + return -1; /* error */ + if (packing->RowLength == 0) { + bytesPerRow = bytesPerPixel * width; + } + else { + bytesPerRow = bytesPerPixel * packing->RowLength; + } + } + + remainder = bytesPerRow % packing->Alignment; + if (remainder > 0) + bytesPerRow += (packing->Alignment - remainder); + + if (packing->ImageHeight == 0) + bytesPerImage = bytesPerRow * height; + else + bytesPerImage = bytesPerRow * packing->ImageHeight; + + return bytesPerImage; +} + + + +/** + * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel. + * This is typically used to convert a bitmap into a GLubyte/pixel texture. + * "On" bits will set texels to \p onValue. + * "Off" bits will not modify texels. + * \param width src bitmap width in pixels + * \param height src bitmap height in pixels + * \param unpack bitmap unpacking state + * \param bitmap the src bitmap data + * \param destBuffer start of dest buffer + * \param destStride row stride in dest buffer + * \param onValue if bit is 1, set destBuffer pixel to this value + */ +void +_mesa_expand_bitmap(GLsizei width, GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap, + GLubyte *destBuffer, GLint destStride, + GLubyte onValue) +{ + const GLubyte *srcRow = (const GLubyte *) + _mesa_image_address2d(unpack, bitmap, width, height, + GL_COLOR_INDEX, GL_BITMAP, 0, 0); + const GLint srcStride = _mesa_image_row_stride(unpack, width, + GL_COLOR_INDEX, GL_BITMAP); + GLint row, col; + +#define SET_PIXEL(COL, ROW) \ + destBuffer[(ROW) * destStride + (COL)] = onValue; + + for (row = 0; row < height; row++) { + const GLubyte *src = srcRow; + + if (unpack->LsbFirst) { + /* Lsb first */ + GLubyte mask = 1U << (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + + if (*src & mask) { + SET_PIXEL(col, row); + } + + if (mask == 128U) { + src++; + mask = 1U; + } + else { + mask = mask << 1; + } + } + + /* get ready for next row */ + if (mask != 1) + src++; + } + else { + /* Msb first */ + GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); + for (col = 0; col < width; col++) { + + if (*src & mask) { + SET_PIXEL(col, row); + } + + if (mask == 1U) { + src++; + mask = 128U; + } + else { + mask = mask >> 1; + } + } + + /* get ready for next row */ + if (mask != 128) + src++; + } + + srcRow += srcStride; + } /* row */ + +#undef SET_PIXEL +} + + + + +/** + * Convert an array of RGBA colors from one datatype to another. + * NOTE: src may equal dst. In that case, we use a temporary buffer. + */ +void +_mesa_convert_colors(GLenum srcType, const GLvoid *src, + GLenum dstType, GLvoid *dst, + GLuint count, const GLubyte mask[]) +{ + GLuint tempBuffer[MAX_WIDTH][4]; + const GLboolean useTemp = (src == dst); + + ASSERT(srcType != dstType); + + switch (srcType) { + case GL_UNSIGNED_BYTE: + if (dstType == GL_UNSIGNED_SHORT) { + const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; + GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]); + dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]); + dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]); + dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); + } + else { + const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src; + GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + ASSERT(dstType == GL_FLOAT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]); + dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]); + dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]); + dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); + } + break; + case GL_UNSIGNED_SHORT: + if (dstType == GL_UNSIGNED_BYTE) { + const GLushort (*src2)[4] = (const GLushort (*)[4]) src; + GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]); + dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]); + dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]); + dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); + } + else { + const GLushort (*src2)[4] = (const GLushort (*)[4]) src; + GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + ASSERT(dstType == GL_FLOAT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]); + dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]); + dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]); + dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat)); + } + break; + case GL_FLOAT: + if (dstType == GL_UNSIGNED_BYTE) { + const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; + GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]); + UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte)); + } + else { + const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src; + GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst); + GLuint i; + ASSERT(dstType == GL_UNSIGNED_SHORT); + for (i = 0; i < count; i++) { + if (!mask || mask[i]) { + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]); + UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]); + } + } + if (useTemp) + memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort)); + } + break; + default: + _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors"); + } +} + + + + +/** + * Perform basic clipping for glDrawPixels. The image's position and size + * and the unpack SkipPixels and SkipRows are adjusted so that the image + * region is entirely within the window and scissor bounds. + * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1). + * If Pixel.ZoomY is -1, *destY will be changed to be the first row which + * we'll actually write. Beforehand, *destY-1 is the first drawing row. + * + * \return GL_TRUE if image is ready for drawing or + * GL_FALSE if image was completely clipped away (draw nothing) + */ +GLboolean +_mesa_clip_drawpixels(const struct gl_context *ctx, + GLint *destX, GLint *destY, + GLsizei *width, GLsizei *height, + struct gl_pixelstore_attrib *unpack) +{ + const struct gl_framebuffer *buffer = ctx->DrawBuffer; + + if (unpack->RowLength == 0) { + unpack->RowLength = *width; + } + + ASSERT(ctx->Pixel.ZoomX == 1.0F); + ASSERT(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F); + + /* left clipping */ + if (*destX < buffer->_Xmin) { + unpack->SkipPixels += (buffer->_Xmin - *destX); + *width -= (buffer->_Xmin - *destX); + *destX = buffer->_Xmin; + } + /* right clipping */ + if (*destX + *width > buffer->_Xmax) + *width -= (*destX + *width - buffer->_Xmax); + + if (*width <= 0) + return GL_FALSE; + + if (ctx->Pixel.ZoomY == 1.0F) { + /* bottom clipping */ + if (*destY < buffer->_Ymin) { + unpack->SkipRows += (buffer->_Ymin - *destY); + *height -= (buffer->_Ymin - *destY); + *destY = buffer->_Ymin; + } + /* top clipping */ + if (*destY + *height > buffer->_Ymax) + *height -= (*destY + *height - buffer->_Ymax); + } + else { /* upside down */ + /* top clipping */ + if (*destY > buffer->_Ymax) { + unpack->SkipRows += (*destY - buffer->_Ymax); + *height -= (*destY - buffer->_Ymax); + *destY = buffer->_Ymax; + } + /* bottom clipping */ + if (*destY - *height < buffer->_Ymin) + *height -= (buffer->_Ymin - (*destY - *height)); + /* adjust destY so it's the first row to write to */ + (*destY)--; + } + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Perform clipping for glReadPixels. The image's window position + * and size, and the pack skipPixels, skipRows and rowLength are adjusted + * so that the image region is entirely within the window bounds. + * Note: this is different from _mesa_clip_drawpixels() in that the + * scissor box is ignored, and we use the bounds of the current readbuffer + * surface. + * + * \return GL_TRUE if region to read is in bounds + * GL_FALSE if region is completely out of bounds (nothing to read) + */ +GLboolean +_mesa_clip_readpixels(const struct gl_context *ctx, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height, + struct gl_pixelstore_attrib *pack) +{ + const struct gl_framebuffer *buffer = ctx->ReadBuffer; + + if (pack->RowLength == 0) { + pack->RowLength = *width; + } + + /* left clipping */ + if (*srcX < 0) { + pack->SkipPixels += (0 - *srcX); + *width -= (0 - *srcX); + *srcX = 0; + } + /* right clipping */ + if (*srcX + *width > (GLsizei) buffer->Width) + *width -= (*srcX + *width - buffer->Width); + + if (*width <= 0) + return GL_FALSE; + + /* bottom clipping */ + if (*srcY < 0) { + pack->SkipRows += (0 - *srcY); + *height -= (0 - *srcY); + *srcY = 0; + } + /* top clipping */ + if (*srcY + *height > (GLsizei) buffer->Height) + *height -= (*srcY + *height - buffer->Height); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Do clipping for a glCopyTexSubImage call. + * The framebuffer source region might extend outside the framebuffer + * bounds. Clip the source region against the framebuffer bounds and + * adjust the texture/dest position and size accordingly. + * + * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise. + */ +GLboolean +_mesa_clip_copytexsubimage(const struct gl_context *ctx, + GLint *destX, GLint *destY, + GLint *srcX, GLint *srcY, + GLsizei *width, GLsizei *height) +{ + const struct gl_framebuffer *fb = ctx->ReadBuffer; + const GLint srcX0 = *srcX, srcY0 = *srcY; + + if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height, + srcX, srcY, width, height)) { + *destX = *destX + *srcX - srcX0; + *destY = *destY + *srcY - srcY0; + + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + + + +/** + * Clip the rectangle defined by (x, y, width, height) against the bounds + * specified by [xmin, xmax) and [ymin, ymax). + * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise. + */ +GLboolean +_mesa_clip_to_region(GLint xmin, GLint ymin, + GLint xmax, GLint ymax, + GLint *x, GLint *y, + GLsizei *width, GLsizei *height ) +{ + /* left clipping */ + if (*x < xmin) { + *width -= (xmin - *x); + *x = xmin; + } + + /* right clipping */ + if (*x + *width > xmax) + *width -= (*x + *width - xmax); + + if (*width <= 0) + return GL_FALSE; + + /* bottom (or top) clipping */ + if (*y < ymin) { + *height -= (ymin - *y); + *y = ymin; + } + + /* top (or bottom) clipping */ + if (*y + *height > ymax) + *height -= (*y + *height - ymax); + + if (*height <= 0) + return GL_FALSE; + + return GL_TRUE; +} + + +/** + * Clip dst coords against Xmax (or Ymax). + */ +static INLINE void +clip_right_or_top(GLint *srcX0, GLint *srcX1, + GLint *dstX0, GLint *dstX1, + GLint maxValue) +{ + GLfloat t, bias; + + if (*dstX1 > maxValue) { + /* X1 outside right edge */ + ASSERT(*dstX0 < maxValue); /* X0 should be inside right edge */ + t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); + /* chop off [t, 1] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX1 = maxValue; + bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; + *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); + } + else if (*dstX0 > maxValue) { + /* X0 outside right edge */ + ASSERT(*dstX1 < maxValue); /* X1 should be inside right edge */ + t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); + /* chop off [t, 1] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX0 = maxValue; + bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F; + *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); + } +} + + +/** + * Clip dst coords against Xmin (or Ymin). + */ +static INLINE void +clip_left_or_bottom(GLint *srcX0, GLint *srcX1, + GLint *dstX0, GLint *dstX1, + GLint minValue) +{ + GLfloat t, bias; + + if (*dstX0 < minValue) { + /* X0 outside left edge */ + ASSERT(*dstX1 > minValue); /* X1 should be inside left edge */ + t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0); + /* chop off [0, t] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX0 = minValue; + bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; /* flipped??? */ + *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias); + } + else if (*dstX1 < minValue) { + /* X1 outside left edge */ + ASSERT(*dstX0 > minValue); /* X0 should be inside left edge */ + t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1); + /* chop off [0, t] part */ + ASSERT(t >= 0.0 && t <= 1.0); + *dstX1 = minValue; + bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F; + *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias); + } +} + + +/** + * Do clipping of blit src/dest rectangles. + * The dest rect is clipped against both the buffer bounds and scissor bounds. + * The src rect is just clipped against the buffer bounds. + * + * When either the src or dest rect is clipped, the other is also clipped + * proportionately! + * + * Note that X0 need not be less than X1 (same for Y) for either the source + * and dest rects. That makes the clipping a little trickier. + * + * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped + */ +GLboolean +_mesa_clip_blit(struct gl_context *ctx, + GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1, + GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1) +{ + const GLint srcXmin = 0; + const GLint srcXmax = ctx->ReadBuffer->Width; + const GLint srcYmin = 0; + const GLint srcYmax = ctx->ReadBuffer->Height; + + /* these include scissor bounds */ + const GLint dstXmin = ctx->DrawBuffer->_Xmin; + const GLint dstXmax = ctx->DrawBuffer->_Xmax; + const GLint dstYmin = ctx->DrawBuffer->_Ymin; + const GLint dstYmax = ctx->DrawBuffer->_Ymax; + + /* + printf("PreClipX: src: %d .. %d dst: %d .. %d\n", + *srcX0, *srcX1, *dstX0, *dstX1); + printf("PreClipY: src: %d .. %d dst: %d .. %d\n", + *srcY0, *srcY1, *dstY0, *dstY1); + */ + + /* trivial rejection tests */ + if (*dstX0 == *dstX1) + return GL_FALSE; /* no width */ + if (*dstX0 <= dstXmin && *dstX1 <= dstXmin) + return GL_FALSE; /* totally out (left) of bounds */ + if (*dstX0 >= dstXmax && *dstX1 >= dstXmax) + return GL_FALSE; /* totally out (right) of bounds */ + + if (*dstY0 == *dstY1) + return GL_FALSE; + if (*dstY0 <= dstYmin && *dstY1 <= dstYmin) + return GL_FALSE; + if (*dstY0 >= dstYmax && *dstY1 >= dstYmax) + return GL_FALSE; + + if (*srcX0 == *srcX1) + return GL_FALSE; + if (*srcX0 <= srcXmin && *srcX1 <= srcXmin) + return GL_FALSE; + if (*srcX0 >= srcXmax && *srcX1 >= srcXmax) + return GL_FALSE; + + if (*srcY0 == *srcY1) + return GL_FALSE; + if (*srcY0 <= srcYmin && *srcY1 <= srcYmin) + return GL_FALSE; + if (*srcY0 >= srcYmax && *srcY1 >= srcYmax) + return GL_FALSE; + + /* + * dest clip + */ + clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax); + clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax); + clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin); + clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin); + + /* + * src clip (just swap src/dst values from above) + */ + clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax); + clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax); + clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin); + clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin); + + /* + printf("PostClipX: src: %d .. %d dst: %d .. %d\n", + *srcX0, *srcX1, *dstX0, *dstX1); + printf("PostClipY: src: %d .. %d dst: %d .. %d\n", + *srcY0, *srcY1, *dstY0, *dstY1); + */ + + ASSERT(*dstX0 >= dstXmin); + ASSERT(*dstX0 <= dstXmax); + ASSERT(*dstX1 >= dstXmin); + ASSERT(*dstX1 <= dstXmax); + + ASSERT(*dstY0 >= dstYmin); + ASSERT(*dstY0 <= dstYmax); + ASSERT(*dstY1 >= dstYmin); + ASSERT(*dstY1 <= dstYmax); + + ASSERT(*srcX0 >= srcXmin); + ASSERT(*srcX0 <= srcXmax); + ASSERT(*srcX1 >= srcXmin); + ASSERT(*srcX1 <= srcXmax); + + ASSERT(*srcY0 >= srcYmin); + ASSERT(*srcY0 <= srcYmax); + ASSERT(*srcY1 >= srcYmin); + ASSERT(*srcY1 <= srcYmax); + + return GL_TRUE; +} diff --git a/mesalib/src/mesa/main/mipmap.c b/mesalib/src/mesa/main/mipmap.c index f2724dbca..8a811cb72 100644 --- a/mesalib/src/mesa/main/mipmap.c +++ b/mesalib/src/mesa/main/mipmap.c @@ -706,6 +706,17 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth, } } + else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) { + GLuint i, j, k; + const GLfloat *rowA = (const GLfloat *) srcRowA; + const GLfloat *rowB = (const GLfloat *) srcRowB; + GLfloat *dst = (GLfloat *) dstRow; + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + dst[i*2] = (rowA[j*2] + rowA[k*2] + rowB[j*2] + rowB[k*2]) * 0.25F; + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } @@ -1341,6 +1352,15 @@ do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth, } } + else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) { + DECLARE_ROW_POINTERS(GLfloat, 2); + + for (i = j = 0, k = k0; i < (GLuint) dstWidth; + i++, j += colStride, k += colStride) { + FILTER_F_3D(0); + } + } + else { _mesa_problem(NULL, "bad format in do_row()"); } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index f018c75cc..b88118366 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1856,7 +1856,7 @@ struct gl_program GLbitfield SystemValuesRead; /**< Bitmask of SYSTEM_VALUE_x inputs used */ GLbitfield InputFlags[MAX_PROGRAM_INPUTS]; /**< PROG_PARAM_BIT_x flags */ GLbitfield OutputFlags[MAX_PROGRAM_OUTPUTS]; /**< PROG_PARAM_BIT_x flags */ - GLbitfield TexturesUsed[MAX_TEXTURE_UNITS]; /**< TEXTURE_x_BIT bitmask */ + GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; /**< TEXTURE_x_BIT bitmask */ GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */ GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */ diff --git a/mesalib/src/mesa/main/pack.c b/mesalib/src/mesa/main/pack.c index a232a51c3..7de1d05b9 100644 --- a/mesalib/src/mesa/main/pack.c +++ b/mesalib/src/mesa/main/pack.c @@ -1971,7 +1971,8 @@ extract_uint_indexes(GLuint n, GLuint indexes[], srcType == GL_INT || srcType == GL_UNSIGNED_INT_24_8_EXT || srcType == GL_HALF_FLOAT_ARB || - srcType == GL_FLOAT); + srcType == GL_FLOAT || + srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); switch (srcType) { case GL_BITMAP: @@ -2142,6 +2143,23 @@ extract_uint_indexes(GLuint n, GLuint indexes[], } } break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + GLuint i; + const GLuint *s = (const GLuint *) src; + if (unpack->SwapBytes) { + for (i = 0; i < n; i++) { + GLuint value = s[i*2+1]; + SWAP4BYTE(value); + indexes[i] = value & 0xff; /* lower 8 bits */ + } + } + else { + for (i = 0; i < n; i++) + indexes[i] = s[i*2+1] & 0xff; /* lower 8 bits */ + } + } + break; default: _mesa_problem(NULL, "bad srcType in extract_uint_indexes"); @@ -4412,11 +4430,13 @@ _mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n, srcType == GL_INT || srcType == GL_UNSIGNED_INT_24_8_EXT || srcType == GL_HALF_FLOAT_ARB || - srcType == GL_FLOAT); + srcType == GL_FLOAT || + srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); ASSERT(dstType == GL_UNSIGNED_BYTE || dstType == GL_UNSIGNED_SHORT || - dstType == GL_UNSIGNED_INT); + dstType == GL_UNSIGNED_INT || + dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); /* only shift and offset apply to stencil */ transferOps &= IMAGE_SHIFT_OFFSET_BIT; @@ -4488,6 +4508,15 @@ _mesa_unpack_stencil_span( struct gl_context *ctx, GLuint n, case GL_UNSIGNED_INT: memcpy(dest, indexes, n * sizeof(GLuint)); break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + GLuint *dst = (GLuint *) dest; + GLuint i; + for (i = 0; i < n; i++) { + dst[i*2+1] = indexes[i] & 0xff; /* lower 8 bits */ + } + } + break; default: _mesa_problem(ctx, "bad dstType in _mesa_unpack_stencil_span"); } @@ -4798,6 +4827,20 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, } } break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + GLuint i; + const GLfloat *src = (const GLfloat *)source; + for (i = 0; i < n; i++) { + GLfloat value = src[i * 2]; + if (srcPacking->SwapBytes) { + SWAP4BYTE(value); + } + depthValues[i] = value; + } + needClamp = GL_TRUE; + } + break; case GL_FLOAT: DEPTH_VALUES(GLfloat, 1*); needClamp = GL_TRUE; @@ -4874,9 +4917,18 @@ _mesa_unpack_depth_span( struct gl_context *ctx, GLuint n, zValues[i] = (GLushort) (depthValues[i] * (GLfloat) depthMax); } } + else if (dstType == GL_FLOAT) { + /* Nothing to do. depthValues is pointing to dest. */ + } + else if (dstType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV) { + GLfloat *zValues = (GLfloat*) dest; + GLuint i; + for (i = 0; i < n; i++) { + zValues[i*2] = depthValues[i]; + } + } else { - ASSERT(dstType == GL_FLOAT); - /*ASSERT(depthMax == 1.0F);*/ + ASSERT(0); } free(depthTemp); @@ -5004,10 +5056,11 @@ _mesa_pack_depth_span( struct gl_context *ctx, GLuint n, GLvoid *dest, /** - * Pack depth and stencil values as GL_DEPTH_STENCIL/GL_UNSIGNED_INT_24_8. + * Pack depth and stencil values as GL_DEPTH_STENCIL (GL_UNSIGNED_INT_24_8 etc) */ void -_mesa_pack_depth_stencil_span(struct gl_context *ctx, GLuint n, GLuint *dest, +_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n, + GLenum dstType, GLuint *dest, const GLfloat *depthVals, const GLstencil *stencilVals, const struct gl_pixelstore_attrib *dstPacking) @@ -5037,9 +5090,19 @@ _mesa_pack_depth_stencil_span(struct gl_context *ctx, GLuint n, GLuint *dest, stencilVals = stencilCopy; } - for (i = 0; i < n; i++) { - GLuint z = (GLuint) (depthVals[i] * 0xffffff); - dest[i] = (z << 8) | (stencilVals[i] & 0xff); + switch (dstType) { + case GL_UNSIGNED_INT_24_8: + for (i = 0; i < n; i++) { + GLuint z = (GLuint) (depthVals[i] * 0xffffff); + dest[i] = (z << 8) | (stencilVals[i] & 0xff); + } + break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + for (i = 0; i < n; i++) { + ((GLfloat*)dest)[i*2] = depthVals[i]; + dest[i*2+1] = stencilVals[i] & 0xff; + } + break; } if (dstPacking->SwapBytes) { diff --git a/mesalib/src/mesa/main/pack.h b/mesalib/src/mesa/main/pack.h index 1f19a5a7c..00aab409e 100644 --- a/mesalib/src/mesa/main/pack.h +++ b/mesalib/src/mesa/main/pack.h @@ -1,147 +1,147 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (C) 1999-2010 VMware, Inc. All Rights Reserved. - * - * 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 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 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. - */ - - -#ifndef PACK_H -#define PACK_H - - -#include "mtypes.h" - - -extern void -_mesa_unpack_polygon_stipple(const GLubyte *pattern, GLuint dest[32], - const struct gl_pixelstore_attrib *unpacking); - - -extern void -_mesa_pack_polygon_stipple(const GLuint pattern[32], GLubyte *dest, - const struct gl_pixelstore_attrib *packing); - - -extern GLvoid * -_mesa_unpack_bitmap(GLint width, GLint height, const GLubyte *pixels, - const struct gl_pixelstore_attrib *packing); - -extern void -_mesa_pack_bitmap(GLint width, GLint height, const GLubyte *source, - GLubyte *dest, const struct gl_pixelstore_attrib *packing); - - -extern void -_mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, - GLfloat rgba[][4], - GLenum dstFormat, GLenum dstType, GLvoid *dstAddr, - const struct gl_pixelstore_attrib *dstPacking, - GLbitfield transferOps); - - -extern void -_mesa_unpack_color_span_chan(struct gl_context *ctx, - GLuint n, GLenum dstFormat, GLchan dest[], - GLenum srcFormat, GLenum srcType, - const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking, - GLbitfield transferOps); - - -extern void -_mesa_unpack_color_span_float(struct gl_context *ctx, - GLuint n, GLenum dstFormat, GLfloat dest[], - GLenum srcFormat, GLenum srcType, - const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking, - GLbitfield transferOps); - -extern void -_mesa_unpack_color_span_uint(struct gl_context *ctx, - GLuint n, GLenum dstFormat, GLuint *dest, - GLenum srcFormat, GLenum srcType, - const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking); - -extern void -_mesa_unpack_dudv_span_byte(struct gl_context *ctx, - GLuint n, GLenum dstFormat, GLbyte dest[], - GLenum srcFormat, GLenum srcType, - const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking, - GLbitfield transferOps); - -extern void -_mesa_unpack_index_span(struct gl_context *ctx, GLuint n, - GLenum dstType, GLvoid *dest, - GLenum srcType, const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking, - GLbitfield transferOps); - - -extern void -_mesa_pack_index_span(struct gl_context *ctx, GLuint n, - GLenum dstType, GLvoid *dest, const GLuint *source, - const struct gl_pixelstore_attrib *dstPacking, - GLbitfield transferOps); - - -extern void -_mesa_unpack_stencil_span(struct gl_context *ctx, GLuint n, - GLenum dstType, GLvoid *dest, - GLenum srcType, const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking, - GLbitfield transferOps); - -extern void -_mesa_pack_stencil_span(struct gl_context *ctx, GLuint n, - GLenum dstType, GLvoid *dest, const GLstencil *source, - const struct gl_pixelstore_attrib *dstPacking); - - -extern void -_mesa_unpack_depth_span(struct gl_context *ctx, GLuint n, - GLenum dstType, GLvoid *dest, GLuint depthMax, - GLenum srcType, const GLvoid *source, - const struct gl_pixelstore_attrib *srcPacking); - -extern void -_mesa_pack_depth_span(struct gl_context *ctx, GLuint n, GLvoid *dest, - GLenum dstType, const GLfloat *depthSpan, - const struct gl_pixelstore_attrib *dstPacking); - - -extern void -_mesa_pack_depth_stencil_span(struct gl_context *ctx, - GLuint n, GLuint *dest, - const GLfloat *depthVals, - const GLstencil *stencilVals, - const struct gl_pixelstore_attrib *dstPacking); - - -extern void * -_mesa_unpack_image(GLuint dimensions, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *unpack); - - -#endif +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2010 VMware, Inc. All Rights Reserved. + * + * 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 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 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. + */ + + +#ifndef PACK_H +#define PACK_H + + +#include "mtypes.h" + + +extern void +_mesa_unpack_polygon_stipple(const GLubyte *pattern, GLuint dest[32], + const struct gl_pixelstore_attrib *unpacking); + + +extern void +_mesa_pack_polygon_stipple(const GLuint pattern[32], GLubyte *dest, + const struct gl_pixelstore_attrib *packing); + + +extern GLvoid * +_mesa_unpack_bitmap(GLint width, GLint height, const GLubyte *pixels, + const struct gl_pixelstore_attrib *packing); + +extern void +_mesa_pack_bitmap(GLint width, GLint height, const GLubyte *source, + GLubyte *dest, const struct gl_pixelstore_attrib *packing); + + +extern void +_mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, + GLfloat rgba[][4], + GLenum dstFormat, GLenum dstType, GLvoid *dstAddr, + const struct gl_pixelstore_attrib *dstPacking, + GLbitfield transferOps); + + +extern void +_mesa_unpack_color_span_chan(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLchan dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + + +extern void +_mesa_unpack_color_span_float(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLfloat dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + +extern void +_mesa_unpack_color_span_uint(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLuint *dest, + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking); + +extern void +_mesa_unpack_dudv_span_byte(struct gl_context *ctx, + GLuint n, GLenum dstFormat, GLbyte dest[], + GLenum srcFormat, GLenum srcType, + const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + +extern void +_mesa_unpack_index_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + + +extern void +_mesa_pack_index_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLuint *source, + const struct gl_pixelstore_attrib *dstPacking, + GLbitfield transferOps); + + +extern void +_mesa_unpack_stencil_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking, + GLbitfield transferOps); + +extern void +_mesa_pack_stencil_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, const GLstencil *source, + const struct gl_pixelstore_attrib *dstPacking); + + +extern void +_mesa_unpack_depth_span(struct gl_context *ctx, GLuint n, + GLenum dstType, GLvoid *dest, GLuint depthMax, + GLenum srcType, const GLvoid *source, + const struct gl_pixelstore_attrib *srcPacking); + +extern void +_mesa_pack_depth_span(struct gl_context *ctx, GLuint n, GLvoid *dest, + GLenum dstType, const GLfloat *depthSpan, + const struct gl_pixelstore_attrib *dstPacking); + + +extern void +_mesa_pack_depth_stencil_span(struct gl_context *ctx,GLuint n, + GLenum dstType, GLuint *dest, + const GLfloat *depthVals, + const GLstencil *stencilVals, + const struct gl_pixelstore_attrib *dstPacking); + + +extern void * +_mesa_unpack_image(GLuint dimensions, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *unpack); + + +#endif diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index 0331a8ca2..84c5b2228 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -61,6 +61,14 @@ _mesa_error_check_format_type(struct gl_context *ctx, GLenum format, return GL_TRUE; } + if (ctx->Extensions.ARB_depth_buffer_float + && type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV + && format != GL_DEPTH_STENCIL_EXT) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw); + return GL_TRUE; + } + /* basic combinations test */ if (!_mesa_is_legal_format_and_type(ctx, format, type)) { _mesa_error(ctx, GL_INVALID_ENUM, @@ -142,10 +150,23 @@ _mesa_error_check_format_type(struct gl_context *ctx, GLenum format, } break; case GL_DEPTH_STENCIL_EXT: - if (!ctx->Extensions.EXT_packed_depth_stencil || - type != GL_UNSIGNED_INT_24_8_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); - return GL_TRUE; + /* Check validity of the type first. */ + switch (type) { + case GL_UNSIGNED_INT_24_8_EXT: + if (!ctx->Extensions.EXT_packed_depth_stencil) { + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); + return GL_TRUE; + } + break; + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + if (!ctx->Extensions.ARB_depth_buffer_float) { + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); + return GL_TRUE; + } + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); + return GL_TRUE; } if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) || (reading && !_mesa_source_buffer_exists(ctx, format))) { diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index c36175c60..f5b20020d 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -66,6 +66,9 @@ get_datatype_bytes(struct gl_renderbuffer *rb) int component_size; switch (rb->DataType) { + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + component_size = 8; + break; case GL_FLOAT: case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_24_8_EXT: diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index f7774fdd7..8f8d87b90 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -251,7 +251,7 @@ _mesa_BindSampler(GLuint unit, GLuint sampler) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); - if (unit >= ctx->Const.MaxTextureImageUnits) { + if (unit >= ctx->Const.MaxCombinedTextureImageUnits) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindSampler(unit %u)", unit); return; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index b58e30de9..8df25c3f9 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -1032,7 +1032,7 @@ validate_samplers(const struct gl_program *prog, char *errMsg) "TEXTURE_2D", "TEXTURE_1D", }; - GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS]; + GLint targetUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; GLbitfield samplersUsed = prog->SamplersUsed; GLuint i; @@ -1050,7 +1050,7 @@ validate_samplers(const struct gl_program *prog, char *errMsg) gl_texture_index target; GLint sampler = _mesa_ffs(samplersUsed) - 1; assert(sampler >= 0); - assert(sampler < MAX_TEXTURE_IMAGE_UNITS); + assert(sampler < Elements(prog->SamplerUnits)); unit = prog->SamplerUnits[sampler]; target = prog->SamplerTargets[sampler]; if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) { diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c index 9228e354a..c0d0f3779 100644 --- a/mesalib/src/mesa/main/texenv.c +++ b/mesalib/src/mesa/main/texenv.c @@ -419,7 +419,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) - ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; + ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glTexEnvfv(current unit)"); return; @@ -748,7 +748,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) - ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; + ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnvfv(current unit)"); return; @@ -817,7 +817,7 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params ) ASSERT_OUTSIDE_BEGIN_END(ctx); maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV) - ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxTextureImageUnits; + ? ctx->Const.MaxTextureCoordUnits : ctx->Const.MaxCombinedTextureImageUnits; if (ctx->Texture.CurrentUnit >= maxUnit) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexEnviv(current unit)"); return; diff --git a/mesalib/src/mesa/main/texfetch.c b/mesalib/src/mesa/main/texfetch.c index ab3abf657..72283eb68 100644 --- a/mesalib/src/mesa/main/texfetch.c +++ b/mesalib/src/mesa/main/texfetch.c @@ -1,1050 +1,1064 @@ -/* - * Mesa 3-D graphics library - * Version: 7.7 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (c) 2009 VMware, Inc. - * - * 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 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 - * BRIAN PAUL 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. - */ - - -/** - * \file texfetch.c - * - * Texel fetch/store functions - * - * \author Gareth Hughes - */ - - -#include "colormac.h" -#include "macros.h" -#include "texcompress.h" -#include "texcompress_fxt1.h" -#include "texcompress_s3tc.h" -#include "texcompress_rgtc.h" -#include "texfetch.h" -#include "teximage.h" -#include "../../gallium/auxiliary/util/u_format_rgb9e5.h" -#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" - - -/** - * Convert an 8-bit sRGB value from non-linear space to a - * linear RGB value in [0, 1]. - * Implemented with a 256-entry lookup table. - */ -static INLINE GLfloat -nonlinear_to_linear(GLubyte cs8) -{ - static GLfloat table[256]; - static GLboolean tableReady = GL_FALSE; - if (!tableReady) { - /* compute lookup table now */ - GLuint i; - for (i = 0; i < 256; i++) { - const GLfloat cs = UBYTE_TO_FLOAT(i); - if (cs <= 0.04045) { - table[i] = cs / 12.92f; - } - else { - table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4); - } - } - tableReady = GL_TRUE; - } - return table[cs8]; -} - - - -/* Texel fetch routines for all supported formats - */ -#define DIM 1 -#include "texfetch_tmp.h" - -#define DIM 2 -#include "texfetch_tmp.h" - -#define DIM 3 -#include "texfetch_tmp.h" - -/** - * Null texel fetch function. - * - * Have to have this so the FetchTexel function pointer is never NULL. - */ -static void fetch_null_texelf( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - (void) texImage; (void) i; (void) j; (void) k; - texel[RCOMP] = 0.0; - texel[GCOMP] = 0.0; - texel[BCOMP] = 0.0; - texel[ACOMP] = 0.0; - _mesa_warning(NULL, "fetch_null_texelf() called!"); -} - -static void store_null_texel(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - (void) texImage; - (void) i; - (void) j; - (void) k; - (void) texel; - /* no-op */ -} - - - -/** - * Table to map MESA_FORMAT_ to texel fetch/store funcs. - * XXX this is somewhat temporary. - */ -static struct { - gl_format Name; - FetchTexelFuncF Fetch1D; - FetchTexelFuncF Fetch2D; - FetchTexelFuncF Fetch3D; - StoreTexelFunc StoreTexel; -} -texfetch_funcs[MESA_FORMAT_COUNT] = -{ - { - MESA_FORMAT_NONE, - fetch_null_texelf, - fetch_null_texelf, - fetch_null_texelf, - store_null_texel - }, - - { - MESA_FORMAT_RGBA8888, - fetch_texel_1d_f_rgba8888, - fetch_texel_2d_f_rgba8888, - fetch_texel_3d_f_rgba8888, - store_texel_rgba8888 - }, - { - MESA_FORMAT_RGBA8888_REV, - fetch_texel_1d_f_rgba8888_rev, - fetch_texel_2d_f_rgba8888_rev, - fetch_texel_3d_f_rgba8888_rev, - store_texel_rgba8888_rev - }, - { - MESA_FORMAT_ARGB8888, - fetch_texel_1d_f_argb8888, - fetch_texel_2d_f_argb8888, - fetch_texel_3d_f_argb8888, - store_texel_argb8888 - }, - { - MESA_FORMAT_ARGB8888_REV, - fetch_texel_1d_f_argb8888_rev, - fetch_texel_2d_f_argb8888_rev, - fetch_texel_3d_f_argb8888_rev, - store_texel_argb8888_rev - }, - { - MESA_FORMAT_XRGB8888, - fetch_texel_1d_f_xrgb8888, - fetch_texel_2d_f_xrgb8888, - fetch_texel_3d_f_xrgb8888, - store_texel_xrgb8888 - }, - { - MESA_FORMAT_XRGB8888_REV, - fetch_texel_1d_f_xrgb8888_rev, - fetch_texel_2d_f_xrgb8888_rev, - fetch_texel_3d_f_xrgb8888_rev, - store_texel_xrgb8888_rev, - }, - { - MESA_FORMAT_RGB888, - fetch_texel_1d_f_rgb888, - fetch_texel_2d_f_rgb888, - fetch_texel_3d_f_rgb888, - store_texel_rgb888 - }, - { - MESA_FORMAT_BGR888, - fetch_texel_1d_f_bgr888, - fetch_texel_2d_f_bgr888, - fetch_texel_3d_f_bgr888, - store_texel_bgr888 - }, - { - MESA_FORMAT_RGB565, - fetch_texel_1d_f_rgb565, - fetch_texel_2d_f_rgb565, - fetch_texel_3d_f_rgb565, - store_texel_rgb565 - }, - { - MESA_FORMAT_RGB565_REV, - fetch_texel_1d_f_rgb565_rev, - fetch_texel_2d_f_rgb565_rev, - fetch_texel_3d_f_rgb565_rev, - store_texel_rgb565_rev - }, - { - MESA_FORMAT_ARGB4444, - fetch_texel_1d_f_argb4444, - fetch_texel_2d_f_argb4444, - fetch_texel_3d_f_argb4444, - store_texel_argb4444 - }, - { - MESA_FORMAT_ARGB4444_REV, - fetch_texel_1d_f_argb4444_rev, - fetch_texel_2d_f_argb4444_rev, - fetch_texel_3d_f_argb4444_rev, - store_texel_argb4444_rev - }, - { - MESA_FORMAT_RGBA5551, - fetch_texel_1d_f_rgba5551, - fetch_texel_2d_f_rgba5551, - fetch_texel_3d_f_rgba5551, - store_texel_rgba5551 - }, - { - MESA_FORMAT_ARGB1555, - fetch_texel_1d_f_argb1555, - fetch_texel_2d_f_argb1555, - fetch_texel_3d_f_argb1555, - store_texel_argb1555 - }, - { - MESA_FORMAT_ARGB1555_REV, - fetch_texel_1d_f_argb1555_rev, - fetch_texel_2d_f_argb1555_rev, - fetch_texel_3d_f_argb1555_rev, - store_texel_argb1555_rev - }, - { - MESA_FORMAT_AL44, - fetch_texel_1d_f_al44, - fetch_texel_2d_f_al44, - fetch_texel_3d_f_al44, - store_texel_al44 - }, - { - MESA_FORMAT_AL88, - fetch_texel_1d_f_al88, - fetch_texel_2d_f_al88, - fetch_texel_3d_f_al88, - store_texel_al88 - }, - { - MESA_FORMAT_AL88_REV, - fetch_texel_1d_f_al88_rev, - fetch_texel_2d_f_al88_rev, - fetch_texel_3d_f_al88_rev, - store_texel_al88_rev - }, - { - MESA_FORMAT_AL1616, - fetch_texel_1d_f_al1616, - fetch_texel_2d_f_al1616, - fetch_texel_3d_f_al1616, - store_texel_al1616 - }, - { - MESA_FORMAT_AL1616_REV, - fetch_texel_1d_f_al1616_rev, - fetch_texel_2d_f_al1616_rev, - fetch_texel_3d_f_al1616_rev, - store_texel_al1616_rev - }, - { - MESA_FORMAT_RGB332, - fetch_texel_1d_f_rgb332, - fetch_texel_2d_f_rgb332, - fetch_texel_3d_f_rgb332, - store_texel_rgb332 - }, - { - MESA_FORMAT_A8, - fetch_texel_1d_f_a8, - fetch_texel_2d_f_a8, - fetch_texel_3d_f_a8, - store_texel_a8 - }, - { - MESA_FORMAT_A16, - fetch_texel_1d_f_a16, - fetch_texel_2d_f_a16, - fetch_texel_3d_f_a16, - store_texel_a16 - }, - { - MESA_FORMAT_L8, - fetch_texel_1d_f_l8, - fetch_texel_2d_f_l8, - fetch_texel_3d_f_l8, - store_texel_l8 - }, - { - MESA_FORMAT_L16, - fetch_texel_1d_f_l16, - fetch_texel_2d_f_l16, - fetch_texel_3d_f_l16, - store_texel_l16 - }, - { - MESA_FORMAT_I8, - fetch_texel_1d_f_i8, - fetch_texel_2d_f_i8, - fetch_texel_3d_f_i8, - store_texel_i8 - }, - { - MESA_FORMAT_I16, - fetch_texel_1d_f_i16, - fetch_texel_2d_f_i16, - fetch_texel_3d_f_i16, - store_texel_i16 - }, - { - MESA_FORMAT_CI8, - fetch_texel_1d_f_ci8, - fetch_texel_2d_f_ci8, - fetch_texel_3d_f_ci8, - store_texel_ci8 - }, - { - MESA_FORMAT_YCBCR, - fetch_texel_1d_f_ycbcr, - fetch_texel_2d_f_ycbcr, - fetch_texel_3d_f_ycbcr, - store_texel_ycbcr - }, - { - MESA_FORMAT_YCBCR_REV, - fetch_texel_1d_f_ycbcr_rev, - fetch_texel_2d_f_ycbcr_rev, - fetch_texel_3d_f_ycbcr_rev, - store_texel_ycbcr_rev - }, - { - MESA_FORMAT_R8, - fetch_texel_1d_f_r8, - fetch_texel_2d_f_r8, - fetch_texel_3d_f_r8, - store_texel_r8, - }, - { - MESA_FORMAT_RG88, - fetch_texel_1d_f_rg88, - fetch_texel_2d_f_rg88, - fetch_texel_3d_f_rg88, - store_texel_rg88, - }, - { - MESA_FORMAT_RG88_REV, - fetch_texel_1d_f_rg88_rev, - fetch_texel_2d_f_rg88_rev, - fetch_texel_3d_f_rg88_rev, - store_texel_rg88_rev, - }, - { - MESA_FORMAT_R16, - fetch_texel_1d_f_r16, - fetch_texel_2d_f_r16, - fetch_texel_3d_f_r16, - store_texel_r16, - }, - { - MESA_FORMAT_RG1616, - fetch_texel_1d_f_rg1616, - fetch_texel_2d_f_rg1616, - fetch_texel_3d_f_rg1616, - store_texel_rg1616, - }, - { - MESA_FORMAT_RG1616_REV, - fetch_texel_1d_f_rg1616_rev, - fetch_texel_2d_f_rg1616_rev, - fetch_texel_3d_f_rg1616_rev, - store_texel_rg1616_rev, - }, - { - MESA_FORMAT_ARGB2101010, - fetch_texel_1d_f_argb2101010, - fetch_texel_2d_f_argb2101010, - fetch_texel_3d_f_argb2101010, - store_texel_argb2101010 - }, - { - MESA_FORMAT_Z24_S8, - fetch_texel_1d_f_z24_s8, - fetch_texel_2d_f_z24_s8, - fetch_texel_3d_f_z24_s8, - store_texel_z24_s8 - }, - { - MESA_FORMAT_S8_Z24, - fetch_texel_1d_f_s8_z24, - fetch_texel_2d_f_s8_z24, - fetch_texel_3d_f_s8_z24, - store_texel_s8_z24 - }, - { - MESA_FORMAT_Z16, - fetch_texel_1d_f_z16, - fetch_texel_2d_f_z16, - fetch_texel_3d_f_z16, - store_texel_z16 - }, - { - MESA_FORMAT_X8_Z24, - fetch_texel_1d_f_s8_z24, - fetch_texel_2d_f_s8_z24, - fetch_texel_3d_f_s8_z24, - store_texel_s8_z24 - }, - { - MESA_FORMAT_Z24_X8, - fetch_texel_1d_f_z24_s8, - fetch_texel_2d_f_z24_s8, - fetch_texel_3d_f_z24_s8, - store_texel_z24_s8 - }, - { - MESA_FORMAT_Z32, - fetch_texel_1d_f_z32, - fetch_texel_2d_f_z32, - fetch_texel_3d_f_z32, - store_texel_z32 - }, - { - MESA_FORMAT_S8, - NULL, - NULL, - NULL, - NULL - }, - { - MESA_FORMAT_SRGB8, - fetch_texel_1d_srgb8, - fetch_texel_2d_srgb8, - fetch_texel_3d_srgb8, - store_texel_srgb8 - }, - { - MESA_FORMAT_SRGBA8, - fetch_texel_1d_srgba8, - fetch_texel_2d_srgba8, - fetch_texel_3d_srgba8, - store_texel_srgba8 - }, - { - MESA_FORMAT_SARGB8, - fetch_texel_1d_sargb8, - fetch_texel_2d_sargb8, - fetch_texel_3d_sargb8, - store_texel_sargb8 - }, - { - MESA_FORMAT_SL8, - fetch_texel_1d_sl8, - fetch_texel_2d_sl8, - fetch_texel_3d_sl8, - store_texel_sl8 - }, - { - MESA_FORMAT_SLA8, - fetch_texel_1d_sla8, - fetch_texel_2d_sla8, - fetch_texel_3d_sla8, - store_texel_sla8 - }, - { - MESA_FORMAT_SRGB_DXT1, - NULL, - _mesa_fetch_texel_2d_f_srgb_dxt1, - NULL, - NULL - }, - { - MESA_FORMAT_SRGBA_DXT1, - NULL, - _mesa_fetch_texel_2d_f_srgba_dxt1, - NULL, - NULL - }, - { - MESA_FORMAT_SRGBA_DXT3, - NULL, - _mesa_fetch_texel_2d_f_srgba_dxt3, - NULL, - NULL - }, - { - MESA_FORMAT_SRGBA_DXT5, - NULL, - _mesa_fetch_texel_2d_f_srgba_dxt5, - NULL, - NULL - }, - - { - MESA_FORMAT_RGB_FXT1, - NULL, - _mesa_fetch_texel_2d_f_rgb_fxt1, - NULL, - NULL - }, - { - MESA_FORMAT_RGBA_FXT1, - NULL, - _mesa_fetch_texel_2d_f_rgba_fxt1, - NULL, - NULL - }, - { - MESA_FORMAT_RGB_DXT1, - NULL, - _mesa_fetch_texel_2d_f_rgb_dxt1, - NULL, - NULL - }, - { - MESA_FORMAT_RGBA_DXT1, - NULL, - _mesa_fetch_texel_2d_f_rgba_dxt1, - NULL, - NULL - }, - { - MESA_FORMAT_RGBA_DXT3, - NULL, - _mesa_fetch_texel_2d_f_rgba_dxt3, - NULL, - NULL - }, - { - MESA_FORMAT_RGBA_DXT5, - NULL, - _mesa_fetch_texel_2d_f_rgba_dxt5, - NULL, - NULL - }, - { - MESA_FORMAT_RGBA_FLOAT32, - fetch_texel_1d_f_rgba_f32, - fetch_texel_2d_f_rgba_f32, - fetch_texel_3d_f_rgba_f32, - store_texel_rgba_f32 - }, - { - MESA_FORMAT_RGBA_FLOAT16, - fetch_texel_1d_f_rgba_f16, - fetch_texel_2d_f_rgba_f16, - fetch_texel_3d_f_rgba_f16, - store_texel_rgba_f16 - }, - { - MESA_FORMAT_RGB_FLOAT32, - fetch_texel_1d_f_rgb_f32, - fetch_texel_2d_f_rgb_f32, - fetch_texel_3d_f_rgb_f32, - store_texel_rgb_f32 - }, - { - MESA_FORMAT_RGB_FLOAT16, - fetch_texel_1d_f_rgb_f16, - fetch_texel_2d_f_rgb_f16, - fetch_texel_3d_f_rgb_f16, - store_texel_rgb_f16 - }, - { - MESA_FORMAT_ALPHA_FLOAT32, - fetch_texel_1d_f_alpha_f32, - fetch_texel_2d_f_alpha_f32, - fetch_texel_3d_f_alpha_f32, - store_texel_alpha_f32 - }, - { - MESA_FORMAT_ALPHA_FLOAT16, - fetch_texel_1d_f_alpha_f16, - fetch_texel_2d_f_alpha_f16, - fetch_texel_3d_f_alpha_f16, - store_texel_alpha_f16 - }, - { - MESA_FORMAT_LUMINANCE_FLOAT32, - fetch_texel_1d_f_luminance_f32, - fetch_texel_2d_f_luminance_f32, - fetch_texel_3d_f_luminance_f32, - store_texel_luminance_f32 - }, - { - MESA_FORMAT_LUMINANCE_FLOAT16, - fetch_texel_1d_f_luminance_f16, - fetch_texel_2d_f_luminance_f16, - fetch_texel_3d_f_luminance_f16, - store_texel_luminance_f16 - }, - { - MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, - fetch_texel_1d_f_luminance_alpha_f32, - fetch_texel_2d_f_luminance_alpha_f32, - fetch_texel_3d_f_luminance_alpha_f32, - store_texel_luminance_alpha_f32 - }, - { - MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, - fetch_texel_1d_f_luminance_alpha_f16, - fetch_texel_2d_f_luminance_alpha_f16, - fetch_texel_3d_f_luminance_alpha_f16, - store_texel_luminance_alpha_f16 - }, - { - MESA_FORMAT_INTENSITY_FLOAT32, - fetch_texel_1d_f_intensity_f32, - fetch_texel_2d_f_intensity_f32, - fetch_texel_3d_f_intensity_f32, - store_texel_intensity_f32 - }, - { - MESA_FORMAT_INTENSITY_FLOAT16, - fetch_texel_1d_f_intensity_f16, - fetch_texel_2d_f_intensity_f16, - fetch_texel_3d_f_intensity_f16, - store_texel_intensity_f16 - }, - { - MESA_FORMAT_R_FLOAT32, - fetch_texel_1d_f_r_f32, - fetch_texel_2d_f_r_f32, - fetch_texel_3d_f_r_f32, - store_texel_r_f32 - }, - { - MESA_FORMAT_R_FLOAT16, - fetch_texel_1d_f_r_f16, - fetch_texel_2d_f_r_f16, - fetch_texel_3d_f_r_f16, - store_texel_r_f16 - }, - { - MESA_FORMAT_RG_FLOAT32, - fetch_texel_1d_f_rg_f32, - fetch_texel_2d_f_rg_f32, - fetch_texel_3d_f_rg_f32, - store_texel_rg_f32 - }, - { - MESA_FORMAT_RG_FLOAT16, - fetch_texel_1d_f_rg_f16, - fetch_texel_2d_f_rg_f16, - fetch_texel_3d_f_rg_f16, - store_texel_rg_f16 - }, - - /* non-normalized, signed int */ - { - MESA_FORMAT_RGBA_INT8, - fetch_texel_1d_rgba_int8, - fetch_texel_2d_rgba_int8, - fetch_texel_3d_rgba_int8, - store_texel_rgba_int8 - }, - { - MESA_FORMAT_RGBA_INT16, - fetch_texel_1d_rgba_int16, - fetch_texel_2d_rgba_int16, - fetch_texel_3d_rgba_int16, - store_texel_rgba_int16 - }, - { - MESA_FORMAT_RGBA_INT32, - fetch_texel_1d_rgba_int32, - fetch_texel_2d_rgba_int32, - fetch_texel_3d_rgba_int32, - store_texel_rgba_int32 - }, - - /* non-normalized, unsigned int */ - { - MESA_FORMAT_RGBA_UINT8, - fetch_texel_1d_rgba_uint8, - fetch_texel_2d_rgba_uint8, - fetch_texel_3d_rgba_uint8, - store_texel_rgba_uint8 - }, - { - MESA_FORMAT_RGBA_UINT16, - fetch_texel_1d_rgba_uint16, - fetch_texel_2d_rgba_uint16, - fetch_texel_3d_rgba_uint16, - store_texel_rgba_uint16 - }, - { - MESA_FORMAT_RGBA_UINT32, - fetch_texel_1d_rgba_uint32, - fetch_texel_2d_rgba_uint32, - fetch_texel_3d_rgba_uint32, - store_texel_rgba_uint32 - }, - - /* dudv */ - { - MESA_FORMAT_DUDV8, - fetch_texel_1d_dudv8, - fetch_texel_2d_dudv8, - fetch_texel_3d_dudv8, - NULL - }, - - /* signed, normalized */ - { - MESA_FORMAT_SIGNED_R8, - fetch_texel_1d_signed_r8, - fetch_texel_2d_signed_r8, - fetch_texel_3d_signed_r8, - store_texel_signed_r8 - }, - { - MESA_FORMAT_SIGNED_RG88_REV, - fetch_texel_1d_signed_rg88_rev, - fetch_texel_2d_signed_rg88_rev, - fetch_texel_3d_signed_rg88_rev, - store_texel_signed_rg88_rev - }, - { - MESA_FORMAT_SIGNED_RGBX8888, - fetch_texel_1d_signed_rgbx8888, - fetch_texel_2d_signed_rgbx8888, - fetch_texel_3d_signed_rgbx8888, - store_texel_signed_rgbx8888 - }, - { - MESA_FORMAT_SIGNED_RGBA8888, - fetch_texel_1d_signed_rgba8888, - fetch_texel_2d_signed_rgba8888, - fetch_texel_3d_signed_rgba8888, - store_texel_signed_rgba8888 - }, - { - MESA_FORMAT_SIGNED_RGBA8888_REV, - fetch_texel_1d_signed_rgba8888_rev, - fetch_texel_2d_signed_rgba8888_rev, - fetch_texel_3d_signed_rgba8888_rev, - store_texel_signed_rgba8888_rev - }, - { - MESA_FORMAT_SIGNED_R16, - fetch_texel_1d_signed_r16, - fetch_texel_2d_signed_r16, - fetch_texel_3d_signed_r16, - store_texel_signed_r16 - }, - { - MESA_FORMAT_SIGNED_GR1616, - fetch_texel_1d_signed_rg1616, - fetch_texel_2d_signed_rg1616, - fetch_texel_3d_signed_rg1616, - store_texel_signed_rg1616 - }, - { - MESA_FORMAT_SIGNED_RGB_16, - fetch_texel_1d_signed_rgb_16, - fetch_texel_2d_signed_rgb_16, - fetch_texel_3d_signed_rgb_16, - store_texel_signed_rgb_16 - }, - { - MESA_FORMAT_SIGNED_RGBA_16, - fetch_texel_1d_signed_rgba_16, - fetch_texel_2d_signed_rgba_16, - fetch_texel_3d_signed_rgba_16, - store_texel_signed_rgba_16 - }, - { - MESA_FORMAT_RGBA_16, - fetch_texel_1d_rgba_16, - fetch_texel_2d_rgba_16, - fetch_texel_3d_rgba_16, - store_texel_rgba_16 - }, - { - MESA_FORMAT_RED_RGTC1, - NULL, - _mesa_fetch_texel_2d_f_red_rgtc1, - NULL, - NULL - }, - { - MESA_FORMAT_SIGNED_RED_RGTC1, - NULL, - _mesa_fetch_texel_2d_f_signed_red_rgtc1, - NULL, - NULL - }, - { - MESA_FORMAT_RG_RGTC2, - NULL, - _mesa_fetch_texel_2d_f_rg_rgtc2, - NULL, - NULL - }, - { - MESA_FORMAT_SIGNED_RG_RGTC2, - NULL, - _mesa_fetch_texel_2d_f_signed_rg_rgtc2, - NULL, - NULL - }, - { - MESA_FORMAT_L_LATC1, - NULL, - _mesa_fetch_texel_2d_f_l_latc1, - NULL, - NULL - }, - { - MESA_FORMAT_SIGNED_L_LATC1, - NULL, - _mesa_fetch_texel_2d_f_signed_l_latc1, - NULL, - NULL - }, - { - MESA_FORMAT_LA_LATC2, - NULL, - _mesa_fetch_texel_2d_f_la_latc2, - NULL, - NULL - }, - { - MESA_FORMAT_SIGNED_LA_LATC2, - NULL, - _mesa_fetch_texel_2d_f_signed_la_latc2, - NULL, - NULL - }, - { - MESA_FORMAT_SIGNED_A8, - fetch_texel_1d_signed_a8, - fetch_texel_2d_signed_a8, - fetch_texel_3d_signed_a8, - store_texel_signed_a8 - }, - { - MESA_FORMAT_SIGNED_L8, - fetch_texel_1d_signed_l8, - fetch_texel_2d_signed_l8, - fetch_texel_3d_signed_l8, - store_texel_signed_l8 - }, - { - MESA_FORMAT_SIGNED_AL88, - fetch_texel_1d_signed_al88, - fetch_texel_2d_signed_al88, - fetch_texel_3d_signed_al88, - store_texel_signed_al88 - }, - { - MESA_FORMAT_SIGNED_I8, - fetch_texel_1d_signed_i8, - fetch_texel_2d_signed_i8, - fetch_texel_3d_signed_i8, - store_texel_signed_i8 - }, - { - MESA_FORMAT_SIGNED_A16, - fetch_texel_1d_signed_a16, - fetch_texel_2d_signed_a16, - fetch_texel_3d_signed_a16, - store_texel_signed_a16 - }, - { - MESA_FORMAT_SIGNED_L16, - fetch_texel_1d_signed_l16, - fetch_texel_2d_signed_l16, - fetch_texel_3d_signed_l16, - store_texel_signed_l16 - }, - { - MESA_FORMAT_SIGNED_AL1616, - fetch_texel_1d_signed_al1616, - fetch_texel_2d_signed_al1616, - fetch_texel_3d_signed_al1616, - store_texel_signed_al1616 - }, - { - MESA_FORMAT_SIGNED_I16, - fetch_texel_1d_signed_i16, - fetch_texel_2d_signed_i16, - 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 - }, - { - MESA_FORMAT_R11_G11_B10_FLOAT, - fetch_texel_1d_r11_g11_b10f, - fetch_texel_2d_r11_g11_b10f, - fetch_texel_3d_r11_g11_b10f, - store_texel_r11_g11_b10f - } -}; - - -FetchTexelFuncF -_mesa_get_texel_fetch_func(gl_format format, GLuint dims) -{ -#ifdef DEBUG - /* check that the table entries are sorted by format name */ - gl_format fmt; - for (fmt = 0; fmt < MESA_FORMAT_COUNT; fmt++) { - assert(texfetch_funcs[fmt].Name == fmt); - } -#endif - - assert(Elements(texfetch_funcs) == MESA_FORMAT_COUNT); - assert(format < MESA_FORMAT_COUNT); - - switch (dims) { - case 1: - return texfetch_funcs[format].Fetch1D; - case 2: - return texfetch_funcs[format].Fetch2D; - case 3: - return texfetch_funcs[format].Fetch3D; - default: - assert(0 && "bad dims in _mesa_get_texel_fetch_func"); - return NULL; - } -} - - -StoreTexelFunc -_mesa_get_texel_store_func(gl_format format) -{ - assert(format < MESA_FORMAT_COUNT); - return texfetch_funcs[format].StoreTexel; -} - - -/** - * Adaptor for fetching a GLchan texel from a float-valued texture. - */ -static void -fetch_texel_float_to_chan(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLchan *texelOut) -{ - GLfloat temp[4]; - GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat); - - ASSERT(texImage->FetchTexelf); - texImage->FetchTexelf(texImage, i, j, k, temp); - if (baseFormat == GL_DEPTH_COMPONENT || - baseFormat == GL_DEPTH_STENCIL_EXT) { - /* just one channel */ - UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); - } - else { - /* four channels */ - UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); - UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]); - UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]); - UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]); - } -} - - -#if 0 -/** - * Adaptor for fetching a float texel from a GLchan-valued texture. - */ -static void -fetch_texel_chan_to_float(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texelOut) -{ - GLchan temp[4]; - GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat); - - ASSERT(texImage->FetchTexelc); - texImage->FetchTexelc(texImage, i, j, k, temp); - if (baseFormat == GL_DEPTH_COMPONENT || - baseFormat == GL_DEPTH_STENCIL_EXT) { - /* just one channel */ - texelOut[0] = CHAN_TO_FLOAT(temp[0]); - } - else { - /* four channels */ - texelOut[0] = CHAN_TO_FLOAT(temp[0]); - texelOut[1] = CHAN_TO_FLOAT(temp[1]); - texelOut[2] = CHAN_TO_FLOAT(temp[2]); - texelOut[3] = CHAN_TO_FLOAT(temp[3]); - } -} -#endif - - -/** - * Initialize the texture image's FetchTexelc and FetchTexelf methods. - */ -void -_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) -{ - gl_format format = texImage->TexFormat; - - ASSERT(dims == 1 || dims == 2 || dims == 3); - - if (texImage->TexObject->Sampler.sRGBDecode == GL_SKIP_DECODE_EXT && - _mesa_get_format_color_encoding(format) == GL_SRGB) { - format = _mesa_get_srgb_format_linear(format); - } - - texImage->FetchTexelf = _mesa_get_texel_fetch_func(format, dims); - - texImage->FetchTexelc = fetch_texel_float_to_chan; - - ASSERT(texImage->FetchTexelc); - ASSERT(texImage->FetchTexelf); -} - -void -_mesa_update_fetch_functions(struct gl_texture_object *texObj) -{ - GLuint face, i; - GLuint dims; - - dims = _mesa_get_texture_dimensions(texObj->Target); - - for (face = 0; face < 6; face++) { - for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { - if (texObj->Image[face][i]) { - _mesa_set_fetch_functions(texObj->Image[face][i], dims); - } - } - } -} +/* + * Mesa 3-D graphics library + * Version: 7.7 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (c) 2009 VMware, Inc. + * + * 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 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 + * BRIAN PAUL 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. + */ + + +/** + * \file texfetch.c + * + * Texel fetch/store functions + * + * \author Gareth Hughes + */ + + +#include "colormac.h" +#include "macros.h" +#include "texcompress.h" +#include "texcompress_fxt1.h" +#include "texcompress_s3tc.h" +#include "texcompress_rgtc.h" +#include "texfetch.h" +#include "teximage.h" +#include "../../gallium/auxiliary/util/u_format_rgb9e5.h" +#include "../../gallium/auxiliary/util/u_format_r11g11b10f.h" + + +/** + * Convert an 8-bit sRGB value from non-linear space to a + * linear RGB value in [0, 1]. + * Implemented with a 256-entry lookup table. + */ +static INLINE GLfloat +nonlinear_to_linear(GLubyte cs8) +{ + static GLfloat table[256]; + static GLboolean tableReady = GL_FALSE; + if (!tableReady) { + /* compute lookup table now */ + GLuint i; + for (i = 0; i < 256; i++) { + const GLfloat cs = UBYTE_TO_FLOAT(i); + if (cs <= 0.04045) { + table[i] = cs / 12.92f; + } + else { + table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4); + } + } + tableReady = GL_TRUE; + } + return table[cs8]; +} + + + +/* Texel fetch routines for all supported formats + */ +#define DIM 1 +#include "texfetch_tmp.h" + +#define DIM 2 +#include "texfetch_tmp.h" + +#define DIM 3 +#include "texfetch_tmp.h" + +/** + * Null texel fetch function. + * + * Have to have this so the FetchTexel function pointer is never NULL. + */ +static void fetch_null_texelf( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + (void) texImage; (void) i; (void) j; (void) k; + texel[RCOMP] = 0.0; + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 0.0; + _mesa_warning(NULL, "fetch_null_texelf() called!"); +} + +static void store_null_texel(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + (void) texImage; + (void) i; + (void) j; + (void) k; + (void) texel; + /* no-op */ +} + + + +/** + * Table to map MESA_FORMAT_ to texel fetch/store funcs. + * XXX this is somewhat temporary. + */ +static struct { + gl_format Name; + FetchTexelFuncF Fetch1D; + FetchTexelFuncF Fetch2D; + FetchTexelFuncF Fetch3D; + StoreTexelFunc StoreTexel; +} +texfetch_funcs[MESA_FORMAT_COUNT] = +{ + { + MESA_FORMAT_NONE, + fetch_null_texelf, + fetch_null_texelf, + fetch_null_texelf, + store_null_texel + }, + + { + MESA_FORMAT_RGBA8888, + fetch_texel_1d_f_rgba8888, + fetch_texel_2d_f_rgba8888, + fetch_texel_3d_f_rgba8888, + store_texel_rgba8888 + }, + { + MESA_FORMAT_RGBA8888_REV, + fetch_texel_1d_f_rgba8888_rev, + fetch_texel_2d_f_rgba8888_rev, + fetch_texel_3d_f_rgba8888_rev, + store_texel_rgba8888_rev + }, + { + MESA_FORMAT_ARGB8888, + fetch_texel_1d_f_argb8888, + fetch_texel_2d_f_argb8888, + fetch_texel_3d_f_argb8888, + store_texel_argb8888 + }, + { + MESA_FORMAT_ARGB8888_REV, + fetch_texel_1d_f_argb8888_rev, + fetch_texel_2d_f_argb8888_rev, + fetch_texel_3d_f_argb8888_rev, + store_texel_argb8888_rev + }, + { + MESA_FORMAT_XRGB8888, + fetch_texel_1d_f_xrgb8888, + fetch_texel_2d_f_xrgb8888, + fetch_texel_3d_f_xrgb8888, + store_texel_xrgb8888 + }, + { + MESA_FORMAT_XRGB8888_REV, + fetch_texel_1d_f_xrgb8888_rev, + fetch_texel_2d_f_xrgb8888_rev, + fetch_texel_3d_f_xrgb8888_rev, + store_texel_xrgb8888_rev, + }, + { + MESA_FORMAT_RGB888, + fetch_texel_1d_f_rgb888, + fetch_texel_2d_f_rgb888, + fetch_texel_3d_f_rgb888, + store_texel_rgb888 + }, + { + MESA_FORMAT_BGR888, + fetch_texel_1d_f_bgr888, + fetch_texel_2d_f_bgr888, + fetch_texel_3d_f_bgr888, + store_texel_bgr888 + }, + { + MESA_FORMAT_RGB565, + fetch_texel_1d_f_rgb565, + fetch_texel_2d_f_rgb565, + fetch_texel_3d_f_rgb565, + store_texel_rgb565 + }, + { + MESA_FORMAT_RGB565_REV, + fetch_texel_1d_f_rgb565_rev, + fetch_texel_2d_f_rgb565_rev, + fetch_texel_3d_f_rgb565_rev, + store_texel_rgb565_rev + }, + { + MESA_FORMAT_ARGB4444, + fetch_texel_1d_f_argb4444, + fetch_texel_2d_f_argb4444, + fetch_texel_3d_f_argb4444, + store_texel_argb4444 + }, + { + MESA_FORMAT_ARGB4444_REV, + fetch_texel_1d_f_argb4444_rev, + fetch_texel_2d_f_argb4444_rev, + fetch_texel_3d_f_argb4444_rev, + store_texel_argb4444_rev + }, + { + MESA_FORMAT_RGBA5551, + fetch_texel_1d_f_rgba5551, + fetch_texel_2d_f_rgba5551, + fetch_texel_3d_f_rgba5551, + store_texel_rgba5551 + }, + { + MESA_FORMAT_ARGB1555, + fetch_texel_1d_f_argb1555, + fetch_texel_2d_f_argb1555, + fetch_texel_3d_f_argb1555, + store_texel_argb1555 + }, + { + MESA_FORMAT_ARGB1555_REV, + fetch_texel_1d_f_argb1555_rev, + fetch_texel_2d_f_argb1555_rev, + fetch_texel_3d_f_argb1555_rev, + store_texel_argb1555_rev + }, + { + MESA_FORMAT_AL44, + fetch_texel_1d_f_al44, + fetch_texel_2d_f_al44, + fetch_texel_3d_f_al44, + store_texel_al44 + }, + { + MESA_FORMAT_AL88, + fetch_texel_1d_f_al88, + fetch_texel_2d_f_al88, + fetch_texel_3d_f_al88, + store_texel_al88 + }, + { + MESA_FORMAT_AL88_REV, + fetch_texel_1d_f_al88_rev, + fetch_texel_2d_f_al88_rev, + fetch_texel_3d_f_al88_rev, + store_texel_al88_rev + }, + { + MESA_FORMAT_AL1616, + fetch_texel_1d_f_al1616, + fetch_texel_2d_f_al1616, + fetch_texel_3d_f_al1616, + store_texel_al1616 + }, + { + MESA_FORMAT_AL1616_REV, + fetch_texel_1d_f_al1616_rev, + fetch_texel_2d_f_al1616_rev, + fetch_texel_3d_f_al1616_rev, + store_texel_al1616_rev + }, + { + MESA_FORMAT_RGB332, + fetch_texel_1d_f_rgb332, + fetch_texel_2d_f_rgb332, + fetch_texel_3d_f_rgb332, + store_texel_rgb332 + }, + { + MESA_FORMAT_A8, + fetch_texel_1d_f_a8, + fetch_texel_2d_f_a8, + fetch_texel_3d_f_a8, + store_texel_a8 + }, + { + MESA_FORMAT_A16, + fetch_texel_1d_f_a16, + fetch_texel_2d_f_a16, + fetch_texel_3d_f_a16, + store_texel_a16 + }, + { + MESA_FORMAT_L8, + fetch_texel_1d_f_l8, + fetch_texel_2d_f_l8, + fetch_texel_3d_f_l8, + store_texel_l8 + }, + { + MESA_FORMAT_L16, + fetch_texel_1d_f_l16, + fetch_texel_2d_f_l16, + fetch_texel_3d_f_l16, + store_texel_l16 + }, + { + MESA_FORMAT_I8, + fetch_texel_1d_f_i8, + fetch_texel_2d_f_i8, + fetch_texel_3d_f_i8, + store_texel_i8 + }, + { + MESA_FORMAT_I16, + fetch_texel_1d_f_i16, + fetch_texel_2d_f_i16, + fetch_texel_3d_f_i16, + store_texel_i16 + }, + { + MESA_FORMAT_CI8, + fetch_texel_1d_f_ci8, + fetch_texel_2d_f_ci8, + fetch_texel_3d_f_ci8, + store_texel_ci8 + }, + { + MESA_FORMAT_YCBCR, + fetch_texel_1d_f_ycbcr, + fetch_texel_2d_f_ycbcr, + fetch_texel_3d_f_ycbcr, + store_texel_ycbcr + }, + { + MESA_FORMAT_YCBCR_REV, + fetch_texel_1d_f_ycbcr_rev, + fetch_texel_2d_f_ycbcr_rev, + fetch_texel_3d_f_ycbcr_rev, + store_texel_ycbcr_rev + }, + { + MESA_FORMAT_R8, + fetch_texel_1d_f_r8, + fetch_texel_2d_f_r8, + fetch_texel_3d_f_r8, + store_texel_r8, + }, + { + MESA_FORMAT_RG88, + fetch_texel_1d_f_rg88, + fetch_texel_2d_f_rg88, + fetch_texel_3d_f_rg88, + store_texel_rg88, + }, + { + MESA_FORMAT_RG88_REV, + fetch_texel_1d_f_rg88_rev, + fetch_texel_2d_f_rg88_rev, + fetch_texel_3d_f_rg88_rev, + store_texel_rg88_rev, + }, + { + MESA_FORMAT_R16, + fetch_texel_1d_f_r16, + fetch_texel_2d_f_r16, + fetch_texel_3d_f_r16, + store_texel_r16, + }, + { + MESA_FORMAT_RG1616, + fetch_texel_1d_f_rg1616, + fetch_texel_2d_f_rg1616, + fetch_texel_3d_f_rg1616, + store_texel_rg1616, + }, + { + MESA_FORMAT_RG1616_REV, + fetch_texel_1d_f_rg1616_rev, + fetch_texel_2d_f_rg1616_rev, + fetch_texel_3d_f_rg1616_rev, + store_texel_rg1616_rev, + }, + { + MESA_FORMAT_ARGB2101010, + fetch_texel_1d_f_argb2101010, + fetch_texel_2d_f_argb2101010, + fetch_texel_3d_f_argb2101010, + store_texel_argb2101010 + }, + { + MESA_FORMAT_Z24_S8, + fetch_texel_1d_f_z24_s8, + fetch_texel_2d_f_z24_s8, + fetch_texel_3d_f_z24_s8, + store_texel_z24_s8 + }, + { + MESA_FORMAT_S8_Z24, + fetch_texel_1d_f_s8_z24, + fetch_texel_2d_f_s8_z24, + fetch_texel_3d_f_s8_z24, + store_texel_s8_z24 + }, + { + MESA_FORMAT_Z16, + fetch_texel_1d_f_z16, + fetch_texel_2d_f_z16, + fetch_texel_3d_f_z16, + store_texel_z16 + }, + { + MESA_FORMAT_X8_Z24, + fetch_texel_1d_f_s8_z24, + fetch_texel_2d_f_s8_z24, + fetch_texel_3d_f_s8_z24, + store_texel_s8_z24 + }, + { + MESA_FORMAT_Z24_X8, + fetch_texel_1d_f_z24_s8, + fetch_texel_2d_f_z24_s8, + fetch_texel_3d_f_z24_s8, + store_texel_z24_s8 + }, + { + MESA_FORMAT_Z32, + fetch_texel_1d_f_z32, + fetch_texel_2d_f_z32, + fetch_texel_3d_f_z32, + store_texel_z32 + }, + { + MESA_FORMAT_S8, + NULL, + NULL, + NULL, + NULL + }, + { + MESA_FORMAT_SRGB8, + fetch_texel_1d_srgb8, + fetch_texel_2d_srgb8, + fetch_texel_3d_srgb8, + store_texel_srgb8 + }, + { + MESA_FORMAT_SRGBA8, + fetch_texel_1d_srgba8, + fetch_texel_2d_srgba8, + fetch_texel_3d_srgba8, + store_texel_srgba8 + }, + { + MESA_FORMAT_SARGB8, + fetch_texel_1d_sargb8, + fetch_texel_2d_sargb8, + fetch_texel_3d_sargb8, + store_texel_sargb8 + }, + { + MESA_FORMAT_SL8, + fetch_texel_1d_sl8, + fetch_texel_2d_sl8, + fetch_texel_3d_sl8, + store_texel_sl8 + }, + { + MESA_FORMAT_SLA8, + fetch_texel_1d_sla8, + fetch_texel_2d_sla8, + fetch_texel_3d_sla8, + store_texel_sla8 + }, + { + MESA_FORMAT_SRGB_DXT1, + NULL, + _mesa_fetch_texel_2d_f_srgb_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_SRGBA_DXT1, + NULL, + _mesa_fetch_texel_2d_f_srgba_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_SRGBA_DXT3, + NULL, + _mesa_fetch_texel_2d_f_srgba_dxt3, + NULL, + NULL + }, + { + MESA_FORMAT_SRGBA_DXT5, + NULL, + _mesa_fetch_texel_2d_f_srgba_dxt5, + NULL, + NULL + }, + + { + MESA_FORMAT_RGB_FXT1, + NULL, + _mesa_fetch_texel_2d_f_rgb_fxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_FXT1, + NULL, + _mesa_fetch_texel_2d_f_rgba_fxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGB_DXT1, + NULL, + _mesa_fetch_texel_2d_f_rgb_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_DXT1, + NULL, + _mesa_fetch_texel_2d_f_rgba_dxt1, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_DXT3, + NULL, + _mesa_fetch_texel_2d_f_rgba_dxt3, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_DXT5, + NULL, + _mesa_fetch_texel_2d_f_rgba_dxt5, + NULL, + NULL + }, + { + MESA_FORMAT_RGBA_FLOAT32, + fetch_texel_1d_f_rgba_f32, + fetch_texel_2d_f_rgba_f32, + fetch_texel_3d_f_rgba_f32, + store_texel_rgba_f32 + }, + { + MESA_FORMAT_RGBA_FLOAT16, + fetch_texel_1d_f_rgba_f16, + fetch_texel_2d_f_rgba_f16, + fetch_texel_3d_f_rgba_f16, + store_texel_rgba_f16 + }, + { + MESA_FORMAT_RGB_FLOAT32, + fetch_texel_1d_f_rgb_f32, + fetch_texel_2d_f_rgb_f32, + fetch_texel_3d_f_rgb_f32, + store_texel_rgb_f32 + }, + { + MESA_FORMAT_RGB_FLOAT16, + fetch_texel_1d_f_rgb_f16, + fetch_texel_2d_f_rgb_f16, + fetch_texel_3d_f_rgb_f16, + store_texel_rgb_f16 + }, + { + MESA_FORMAT_ALPHA_FLOAT32, + fetch_texel_1d_f_alpha_f32, + fetch_texel_2d_f_alpha_f32, + fetch_texel_3d_f_alpha_f32, + store_texel_alpha_f32 + }, + { + MESA_FORMAT_ALPHA_FLOAT16, + fetch_texel_1d_f_alpha_f16, + fetch_texel_2d_f_alpha_f16, + fetch_texel_3d_f_alpha_f16, + store_texel_alpha_f16 + }, + { + MESA_FORMAT_LUMINANCE_FLOAT32, + fetch_texel_1d_f_luminance_f32, + fetch_texel_2d_f_luminance_f32, + fetch_texel_3d_f_luminance_f32, + store_texel_luminance_f32 + }, + { + MESA_FORMAT_LUMINANCE_FLOAT16, + fetch_texel_1d_f_luminance_f16, + fetch_texel_2d_f_luminance_f16, + fetch_texel_3d_f_luminance_f16, + store_texel_luminance_f16 + }, + { + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, + fetch_texel_1d_f_luminance_alpha_f32, + fetch_texel_2d_f_luminance_alpha_f32, + fetch_texel_3d_f_luminance_alpha_f32, + store_texel_luminance_alpha_f32 + }, + { + MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, + fetch_texel_1d_f_luminance_alpha_f16, + fetch_texel_2d_f_luminance_alpha_f16, + fetch_texel_3d_f_luminance_alpha_f16, + store_texel_luminance_alpha_f16 + }, + { + MESA_FORMAT_INTENSITY_FLOAT32, + fetch_texel_1d_f_intensity_f32, + fetch_texel_2d_f_intensity_f32, + fetch_texel_3d_f_intensity_f32, + store_texel_intensity_f32 + }, + { + MESA_FORMAT_INTENSITY_FLOAT16, + fetch_texel_1d_f_intensity_f16, + fetch_texel_2d_f_intensity_f16, + fetch_texel_3d_f_intensity_f16, + store_texel_intensity_f16 + }, + { + MESA_FORMAT_R_FLOAT32, + fetch_texel_1d_f_r_f32, + fetch_texel_2d_f_r_f32, + fetch_texel_3d_f_r_f32, + store_texel_r_f32 + }, + { + MESA_FORMAT_R_FLOAT16, + fetch_texel_1d_f_r_f16, + fetch_texel_2d_f_r_f16, + fetch_texel_3d_f_r_f16, + store_texel_r_f16 + }, + { + MESA_FORMAT_RG_FLOAT32, + fetch_texel_1d_f_rg_f32, + fetch_texel_2d_f_rg_f32, + fetch_texel_3d_f_rg_f32, + store_texel_rg_f32 + }, + { + MESA_FORMAT_RG_FLOAT16, + fetch_texel_1d_f_rg_f16, + fetch_texel_2d_f_rg_f16, + fetch_texel_3d_f_rg_f16, + store_texel_rg_f16 + }, + + /* non-normalized, signed int */ + { + MESA_FORMAT_RGBA_INT8, + fetch_texel_1d_rgba_int8, + fetch_texel_2d_rgba_int8, + fetch_texel_3d_rgba_int8, + store_texel_rgba_int8 + }, + { + MESA_FORMAT_RGBA_INT16, + fetch_texel_1d_rgba_int16, + fetch_texel_2d_rgba_int16, + fetch_texel_3d_rgba_int16, + store_texel_rgba_int16 + }, + { + MESA_FORMAT_RGBA_INT32, + fetch_texel_1d_rgba_int32, + fetch_texel_2d_rgba_int32, + fetch_texel_3d_rgba_int32, + store_texel_rgba_int32 + }, + + /* non-normalized, unsigned int */ + { + MESA_FORMAT_RGBA_UINT8, + fetch_texel_1d_rgba_uint8, + fetch_texel_2d_rgba_uint8, + fetch_texel_3d_rgba_uint8, + store_texel_rgba_uint8 + }, + { + MESA_FORMAT_RGBA_UINT16, + fetch_texel_1d_rgba_uint16, + fetch_texel_2d_rgba_uint16, + fetch_texel_3d_rgba_uint16, + store_texel_rgba_uint16 + }, + { + MESA_FORMAT_RGBA_UINT32, + fetch_texel_1d_rgba_uint32, + fetch_texel_2d_rgba_uint32, + fetch_texel_3d_rgba_uint32, + store_texel_rgba_uint32 + }, + + /* dudv */ + { + MESA_FORMAT_DUDV8, + fetch_texel_1d_dudv8, + fetch_texel_2d_dudv8, + fetch_texel_3d_dudv8, + NULL + }, + + /* signed, normalized */ + { + MESA_FORMAT_SIGNED_R8, + fetch_texel_1d_signed_r8, + fetch_texel_2d_signed_r8, + fetch_texel_3d_signed_r8, + store_texel_signed_r8 + }, + { + MESA_FORMAT_SIGNED_RG88_REV, + fetch_texel_1d_signed_rg88_rev, + fetch_texel_2d_signed_rg88_rev, + fetch_texel_3d_signed_rg88_rev, + store_texel_signed_rg88_rev + }, + { + MESA_FORMAT_SIGNED_RGBX8888, + fetch_texel_1d_signed_rgbx8888, + fetch_texel_2d_signed_rgbx8888, + fetch_texel_3d_signed_rgbx8888, + store_texel_signed_rgbx8888 + }, + { + MESA_FORMAT_SIGNED_RGBA8888, + fetch_texel_1d_signed_rgba8888, + fetch_texel_2d_signed_rgba8888, + fetch_texel_3d_signed_rgba8888, + store_texel_signed_rgba8888 + }, + { + MESA_FORMAT_SIGNED_RGBA8888_REV, + fetch_texel_1d_signed_rgba8888_rev, + fetch_texel_2d_signed_rgba8888_rev, + fetch_texel_3d_signed_rgba8888_rev, + store_texel_signed_rgba8888_rev + }, + { + MESA_FORMAT_SIGNED_R16, + fetch_texel_1d_signed_r16, + fetch_texel_2d_signed_r16, + fetch_texel_3d_signed_r16, + store_texel_signed_r16 + }, + { + MESA_FORMAT_SIGNED_GR1616, + fetch_texel_1d_signed_rg1616, + fetch_texel_2d_signed_rg1616, + fetch_texel_3d_signed_rg1616, + store_texel_signed_rg1616 + }, + { + MESA_FORMAT_SIGNED_RGB_16, + fetch_texel_1d_signed_rgb_16, + fetch_texel_2d_signed_rgb_16, + fetch_texel_3d_signed_rgb_16, + store_texel_signed_rgb_16 + }, + { + MESA_FORMAT_SIGNED_RGBA_16, + fetch_texel_1d_signed_rgba_16, + fetch_texel_2d_signed_rgba_16, + fetch_texel_3d_signed_rgba_16, + store_texel_signed_rgba_16 + }, + { + MESA_FORMAT_RGBA_16, + fetch_texel_1d_rgba_16, + fetch_texel_2d_rgba_16, + fetch_texel_3d_rgba_16, + store_texel_rgba_16 + }, + { + MESA_FORMAT_RED_RGTC1, + NULL, + _mesa_fetch_texel_2d_f_red_rgtc1, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_RED_RGTC1, + NULL, + _mesa_fetch_texel_2d_f_signed_red_rgtc1, + NULL, + NULL + }, + { + MESA_FORMAT_RG_RGTC2, + NULL, + _mesa_fetch_texel_2d_f_rg_rgtc2, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_RG_RGTC2, + NULL, + _mesa_fetch_texel_2d_f_signed_rg_rgtc2, + NULL, + NULL + }, + { + MESA_FORMAT_L_LATC1, + NULL, + _mesa_fetch_texel_2d_f_l_latc1, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_L_LATC1, + NULL, + _mesa_fetch_texel_2d_f_signed_l_latc1, + NULL, + NULL + }, + { + MESA_FORMAT_LA_LATC2, + NULL, + _mesa_fetch_texel_2d_f_la_latc2, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_LA_LATC2, + NULL, + _mesa_fetch_texel_2d_f_signed_la_latc2, + NULL, + NULL + }, + { + MESA_FORMAT_SIGNED_A8, + fetch_texel_1d_signed_a8, + fetch_texel_2d_signed_a8, + fetch_texel_3d_signed_a8, + store_texel_signed_a8 + }, + { + MESA_FORMAT_SIGNED_L8, + fetch_texel_1d_signed_l8, + fetch_texel_2d_signed_l8, + fetch_texel_3d_signed_l8, + store_texel_signed_l8 + }, + { + MESA_FORMAT_SIGNED_AL88, + fetch_texel_1d_signed_al88, + fetch_texel_2d_signed_al88, + fetch_texel_3d_signed_al88, + store_texel_signed_al88 + }, + { + MESA_FORMAT_SIGNED_I8, + fetch_texel_1d_signed_i8, + fetch_texel_2d_signed_i8, + fetch_texel_3d_signed_i8, + store_texel_signed_i8 + }, + { + MESA_FORMAT_SIGNED_A16, + fetch_texel_1d_signed_a16, + fetch_texel_2d_signed_a16, + fetch_texel_3d_signed_a16, + store_texel_signed_a16 + }, + { + MESA_FORMAT_SIGNED_L16, + fetch_texel_1d_signed_l16, + fetch_texel_2d_signed_l16, + fetch_texel_3d_signed_l16, + store_texel_signed_l16 + }, + { + MESA_FORMAT_SIGNED_AL1616, + fetch_texel_1d_signed_al1616, + fetch_texel_2d_signed_al1616, + fetch_texel_3d_signed_al1616, + store_texel_signed_al1616 + }, + { + MESA_FORMAT_SIGNED_I16, + fetch_texel_1d_signed_i16, + fetch_texel_2d_signed_i16, + 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 + }, + { + MESA_FORMAT_R11_G11_B10_FLOAT, + fetch_texel_1d_r11_g11_b10f, + fetch_texel_2d_r11_g11_b10f, + fetch_texel_3d_r11_g11_b10f, + store_texel_r11_g11_b10f + }, + { + MESA_FORMAT_Z32_FLOAT, + fetch_texel_1d_f_r_f32, /* Reuse the R32F functions. */ + fetch_texel_2d_f_r_f32, + fetch_texel_3d_f_r_f32, + store_texel_r_f32 + }, + { + MESA_FORMAT_Z32_FLOAT_X24S8, + fetch_texel_1d_z32f_x24s8, + fetch_texel_2d_z32f_x24s8, + fetch_texel_3d_z32f_x24s8, + store_texel_z32f_x24s8 + } +}; + + +FetchTexelFuncF +_mesa_get_texel_fetch_func(gl_format format, GLuint dims) +{ +#ifdef DEBUG + /* check that the table entries are sorted by format name */ + gl_format fmt; + for (fmt = 0; fmt < MESA_FORMAT_COUNT; fmt++) { + assert(texfetch_funcs[fmt].Name == fmt); + } +#endif + + assert(Elements(texfetch_funcs) == MESA_FORMAT_COUNT); + assert(format < MESA_FORMAT_COUNT); + + switch (dims) { + case 1: + return texfetch_funcs[format].Fetch1D; + case 2: + return texfetch_funcs[format].Fetch2D; + case 3: + return texfetch_funcs[format].Fetch3D; + default: + assert(0 && "bad dims in _mesa_get_texel_fetch_func"); + return NULL; + } +} + + +StoreTexelFunc +_mesa_get_texel_store_func(gl_format format) +{ + assert(format < MESA_FORMAT_COUNT); + return texfetch_funcs[format].StoreTexel; +} + + +/** + * Adaptor for fetching a GLchan texel from a float-valued texture. + */ +static void +fetch_texel_float_to_chan(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texelOut) +{ + GLfloat temp[4]; + GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat); + + ASSERT(texImage->FetchTexelf); + texImage->FetchTexelf(texImage, i, j, k, temp); + if (baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* just one channel */ + UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); + } + else { + /* four channels */ + UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); + UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]); + UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]); + UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]); + } +} + + +#if 0 +/** + * Adaptor for fetching a float texel from a GLchan-valued texture. + */ +static void +fetch_texel_chan_to_float(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texelOut) +{ + GLchan temp[4]; + GLenum baseFormat = _mesa_get_format_base_format(texImage->TexFormat); + + ASSERT(texImage->FetchTexelc); + texImage->FetchTexelc(texImage, i, j, k, temp); + if (baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL_EXT) { + /* just one channel */ + texelOut[0] = CHAN_TO_FLOAT(temp[0]); + } + else { + /* four channels */ + texelOut[0] = CHAN_TO_FLOAT(temp[0]); + texelOut[1] = CHAN_TO_FLOAT(temp[1]); + texelOut[2] = CHAN_TO_FLOAT(temp[2]); + texelOut[3] = CHAN_TO_FLOAT(temp[3]); + } +} +#endif + + +/** + * Initialize the texture image's FetchTexelc and FetchTexelf methods. + */ +void +_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) +{ + gl_format format = texImage->TexFormat; + + ASSERT(dims == 1 || dims == 2 || dims == 3); + + if (texImage->TexObject->Sampler.sRGBDecode == GL_SKIP_DECODE_EXT && + _mesa_get_format_color_encoding(format) == GL_SRGB) { + format = _mesa_get_srgb_format_linear(format); + } + + texImage->FetchTexelf = _mesa_get_texel_fetch_func(format, dims); + + texImage->FetchTexelc = fetch_texel_float_to_chan; + + ASSERT(texImage->FetchTexelc); + ASSERT(texImage->FetchTexelf); +} + +void +_mesa_update_fetch_functions(struct gl_texture_object *texObj) +{ + GLuint face, i; + GLuint dims; + + dims = _mesa_get_texture_dimensions(texObj->Target); + + for (face = 0; face < 6; face++) { + for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { + if (texObj->Image[face][i]) { + _mesa_set_fetch_functions(texObj->Image[face][i], dims); + } + } + } +} diff --git a/mesalib/src/mesa/main/texfetch_tmp.h b/mesalib/src/mesa/main/texfetch_tmp.h index 278becc11..3b1eedf39 100644 --- a/mesalib/src/mesa/main/texfetch_tmp.h +++ b/mesalib/src/mesa/main/texfetch_tmp.h @@ -1,2379 +1,2402 @@ -/* - * Mesa 3-D graphics library - * Version: 7.7 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (c) 2008-2009 VMware, Inc. - * - * 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 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 - * BRIAN PAUL 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. - */ - - -/** - * \file texfetch_tmp.h - * Texel fetch functions template. - * - * This template file is used by texfetch.c to generate texel fetch functions - * for 1-D, 2-D and 3-D texture images. - * - * It should be expanded by defining \p DIM as the number texture dimensions - * (1, 2 or 3). According to the value of \p DIM a series of macros is defined - * for the texel lookup in the gl_texture_image::Data. - * - * \author Gareth Hughes - * \author Brian Paul - */ - - -#if DIM == 1 - -#define TEXEL_ADDR( type, image, i, j, k, size ) \ - ((void) (j), (void) (k), ((type *)(image)->Data + (i) * (size))) - -#define FETCH(x) fetch_texel_1d_##x - -#elif DIM == 2 - -#define TEXEL_ADDR( type, image, i, j, k, size ) \ - ((void) (k), \ - ((type *)(image)->Data + ((image)->RowStride * (j) + (i)) * (size))) - -#define FETCH(x) fetch_texel_2d_##x - -#elif DIM == 3 - -#define TEXEL_ADDR( type, image, i, j, k, size ) \ - ((type *)(image)->Data + ((image)->ImageOffsets[k] \ - + (image)->RowStride * (j) + (i)) * (size)) - -#define FETCH(x) fetch_texel_3d_##x - -#else -#error illegal number of texture dimensions -#endif - - -/* MESA_FORMAT_Z32 ***********************************************************/ - -/* Fetch depth texel from 1D, 2D or 3D 32-bit depth texture, - * returning 1 GLfloat. - * Note: no GLchan version of this function. - */ -static void FETCH(f_z32)( 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); - texel[0] = src[0] * (1.0F / 0xffffffff); -} - -#if DIM == 3 -static void store_texel_z32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLuint *depth = (const GLuint *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - dst[0] = *depth; -} -#endif - - -/* MESA_FORMAT_Z16 ***********************************************************/ - -/* Fetch depth texel from 1D, 2D or 3D 16-bit depth texture, - * returning 1 GLfloat. - * Note: no GLchan version of this function. - */ -static void FETCH(f_z16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[0] = src[0] * (1.0F / 65535.0F); -} - -#if DIM == 3 -static void store_texel_z16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *depth = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - dst[0] = *depth; -} -#endif - - -/* MESA_FORMAT_RGBA_F32 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLfloats. - */ -static void FETCH(f_rgba_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4); - texel[RCOMP] = src[0]; - texel[GCOMP] = src[1]; - texel[BCOMP] = src[2]; - texel[ACOMP] = src[3]; -} - -#if DIM == 3 -static void store_texel_rgba_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *depth = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4); - dst[0] = depth[RCOMP]; - dst[1] = depth[GCOMP]; - dst[2] = depth[BCOMP]; - dst[3] = depth[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_F16 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_rgba_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4); - texel[RCOMP] = _mesa_half_to_float(src[0]); - texel[GCOMP] = _mesa_half_to_float(src[1]); - texel[BCOMP] = _mesa_half_to_float(src[2]); - texel[ACOMP] = _mesa_half_to_float(src[3]); -} - -#if DIM == 3 -static void store_texel_rgba_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *src = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4); - dst[0] = _mesa_float_to_half(src[RCOMP]); - dst[1] = _mesa_float_to_half(src[GCOMP]); - dst[2] = _mesa_float_to_half(src[BCOMP]); - dst[3] = _mesa_float_to_half(src[ACOMP]); -} -#endif - -/* MESA_FORMAT_RGB_F32 *******************************************************/ - -/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_rgb_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3); - texel[RCOMP] = src[0]; - texel[GCOMP] = src[1]; - texel[BCOMP] = src[2]; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rgb_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *src = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3); - dst[0] = src[RCOMP]; - dst[1] = src[GCOMP]; - dst[2] = src[BCOMP]; -} -#endif - - -/* MESA_FORMAT_RGB_F16 *******************************************************/ - -/* Fetch texel from 1D, 2D or 3D RGB_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_rgb_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3); - texel[RCOMP] = _mesa_half_to_float(src[0]); - texel[GCOMP] = _mesa_half_to_float(src[1]); - texel[BCOMP] = _mesa_half_to_float(src[2]); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rgb_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *src = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3); - dst[0] = _mesa_float_to_half(src[RCOMP]); - dst[1] = _mesa_float_to_half(src[GCOMP]); - dst[2] = _mesa_float_to_half(src[BCOMP]); -} -#endif - - -/* MESA_FORMAT_ALPHA_F32 *****************************************************/ - -/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_alpha_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = 0.0F; - texel[ACOMP] = src[0]; -} - -#if DIM == 3 -static void store_texel_alpha_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - dst[0] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_ALPHA_F32 *****************************************************/ - -/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_alpha_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = 0.0F; - texel[ACOMP] = _mesa_half_to_float(src[0]); -} - -#if DIM == 3 -static void store_texel_alpha_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - dst[0] = _mesa_float_to_half(rgba[ACOMP]); -} -#endif - - -/* MESA_FORMAT_LUMINANCE_F32 *************************************************/ - -/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_luminance_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = src[0]; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_luminance_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - dst[0] = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_LUMINANCE_F16 *************************************************/ - -/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_luminance_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = _mesa_half_to_float(src[0]); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_luminance_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - dst[0] = _mesa_float_to_half(rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_LUMINANCE_ALPHA_F32 *******************************************/ - -/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_luminance_alpha_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = src[0]; - texel[ACOMP] = src[1]; -} - -#if DIM == 3 -static void store_texel_luminance_alpha_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_LUMINANCE_ALPHA_F16 *******************************************/ - -/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_luminance_alpha_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = _mesa_half_to_float(src[0]); - texel[ACOMP] = _mesa_half_to_float(src[1]); -} - -#if DIM == 3 -static void store_texel_luminance_alpha_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); - dst[0] = _mesa_float_to_half(rgba[RCOMP]); - dst[1] = _mesa_float_to_half(rgba[ACOMP]); -} -#endif - - -/* MESA_FORMAT_INTENSITY_F32 *************************************************/ - -/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_intensity_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = src[0]; -} - -#if DIM == 3 -static void store_texel_intensity_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - dst[0] = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_INTENSITY_F16 *************************************************/ - -/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_intensity_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = _mesa_half_to_float(src[0]); -} - -#if DIM == 3 -static void store_texel_intensity_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - dst[0] = _mesa_float_to_half(rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_R_FLOAT32 *****************************************************/ - -/* Fetch texel from 1D, 2D or 3D R_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_r_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - texel[RCOMP] = src[0]; - texel[GCOMP] = 0.0F; - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_r_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); - dst[0] = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_R_FLOAT16 *****************************************************/ - -/* Fetch texel from 1D, 2D or 3D R_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_r_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - texel[RCOMP] = _mesa_half_to_float(src[0]); - texel[GCOMP] = 0.0F; - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_r_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); - dst[0] = _mesa_float_to_half(rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_RG_FLOAT32 ****************************************************/ - -/* Fetch texel from 1D, 2D or 3D RG_FLOAT32 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_rg_f32)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); - texel[RCOMP] = src[0]; - texel[GCOMP] = src[1]; - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rg_f32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; -} -#endif - - -/* MESA_FORMAT_RG_FLOAT16 ****************************************************/ - -/* Fetch texel from 1D, 2D or 3D RG_FLOAT16 texture, - * returning 4 GLfloats. - */ -static void FETCH(f_rg_f16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); - texel[RCOMP] = _mesa_half_to_float(src[0]); - texel[GCOMP] = _mesa_half_to_float(src[1]); - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rg_f16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLfloat *rgba = (const GLfloat *) texel; - GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); - dst[0] = _mesa_float_to_half(rgba[RCOMP]); - dst[1] = _mesa_float_to_half(rgba[GCOMP]); -} -#endif - - -/* - * Begin Hardware formats - */ - -/* MESA_FORMAT_RGBA8888 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */ -static void FETCH(f_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] = UBYTE_TO_FLOAT( (s >> 24) ); - texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); - texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); - texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); -} - - - -#if DIM == 3 -static void store_texel_rgba8888(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) 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_RGBA888_REV ***************************************************/ - -/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */ -static void FETCH(f_rgba8888_rev)( 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] = UBYTE_TO_FLOAT( (s ) & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); - texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); - texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); -} - -#if DIM == 3 -static void store_texel_rgba8888_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); -} -#endif - - -/* MESA_FORMAT_ARGB8888 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */ -static void FETCH(f_argb8888)( 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] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); - texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); - texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); -} - -#if DIM == 3 -static void store_texel_argb8888(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_ARGB8888_REV **************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */ -static void FETCH(f_argb8888_rev)( 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] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); - texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); - texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); -} - -#if DIM == 3 -static void store_texel_argb8888_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], rgba[ACOMP]); -} -#endif - - -/* MESA_FORMAT_XRGB8888 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D xrgb8888 texture, return 4 GLchans */ -static void FETCH(f_xrgb8888)( 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] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); - texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); - texel[ACOMP] = 1.0f; -} - -#if DIM == 3 -static void store_texel_xrgb8888(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888(0xff, rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_XRGB8888_REV **************************************************/ - -/* Fetch texel from 1D, 2D or 3D xrgb8888_rev texture, return 4 GLfloats */ -static void FETCH(f_xrgb8888_rev)( 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] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); - texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); - texel[ACOMP] = 1.0f; -} - -#if DIM == 3 -static void store_texel_xrgb8888_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], 0xff); -} -#endif - - -/* MESA_FORMAT_RGB888 ********************************************************/ - -/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */ -static void FETCH(f_rgb888)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - texel[RCOMP] = UBYTE_TO_FLOAT( src[2] ); - texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); - texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rgb888(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - dst[0] = rgba[BCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_BGR888 ********************************************************/ - -/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */ -static void FETCH(f_bgr888)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - texel[RCOMP] = UBYTE_TO_FLOAT( src[0] ); - texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); - texel[BCOMP] = UBYTE_TO_FLOAT( src[2] ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_bgr888(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; -} -#endif - - -/* use color expansion like (g << 2) | (g >> 4) (does somewhat random rounding) - instead of slow (g << 2) * 255 / 252 (always rounds down) */ - -/* MESA_FORMAT_RGB565 ********************************************************/ - -/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */ -static void FETCH(f_rgb565)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - const GLushort s = *src; - texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F); - texel[GCOMP] = ((s >> 5 ) & 0x3f) * (1.0F / 63.0F); - texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rgb565(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_565(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_RGB565_REV ****************************************************/ - -/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */ -static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */ - texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) ); - texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) ); - texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rgb565_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_565(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_ARGB4444 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */ -static void FETCH(f_argb4444)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - const GLushort s = *src; - texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); - texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); - texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); - texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); -} - -#if DIM == 3 -static void store_texel_argb4444(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_ARGB4444_REV **************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */ -static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); - texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); - texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); - texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); -} - -#if DIM == 3 -static void store_texel_argb4444_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); -} -#endif - -/* MESA_FORMAT_RGBA5551 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ -static void FETCH(f_rgba5551)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - const GLushort s = *src; - texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F); - texel[GCOMP] = ((s >> 6) & 0x1f) * (1.0F / 31.0F); - texel[BCOMP] = ((s >> 1) & 0x1f) * (1.0F / 31.0F); - texel[ACOMP] = ((s ) & 0x01) * 1.0F; -} - -#if DIM == 3 -static void store_texel_rgba5551(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_5551(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); -} -#endif - -/* MESA_FORMAT_ARGB1555 ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ -static void FETCH(f_argb1555)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - const GLushort s = *src; - texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F); - texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F); - texel[BCOMP] = ((s >> 0) & 0x1f) * (1.0F / 31.0F); - texel[ACOMP] = ((s >> 15) & 0x01) * 1.0F; -} - -#if DIM == 3 -static void store_texel_argb1555(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_1555(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_ARGB1555_REV **************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */ -static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */ - texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) ); - texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) ); - texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); - texel[ACOMP] = UBYTE_TO_FLOAT( ((s >> 15) & 0x01) * 255 ); -} - -#if DIM == 3 -static void store_texel_argb1555_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_1555_REV(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_ARGB2101010 ***************************************************/ - -/* Fetch texel from 1D, 2D or 3D argb2101010 texture, return 4 GLchans */ -static void FETCH(f_argb2101010)( 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); - const GLuint s = *src; - texel[RCOMP] = ((s >> 20) & 0x3ff) * (1.0F / 1023.0F); - texel[GCOMP] = ((s >> 10) & 0x3ff) * (1.0F / 1023.0F); - texel[BCOMP] = ((s >> 0) & 0x3ff) * (1.0F / 1023.0F); - texel[ACOMP] = ((s >> 30) & 0x03) * (1.0F / 3.0F); -} - -#if DIM == 3 -static void store_texel_argb2101010(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_2101010_UB(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_RG88 **********************************************************/ - -/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */ -static void FETCH(f_rg88)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 ); - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -#if DIM == 3 -static void store_texel_rg88(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_88(rgba[RCOMP], rgba[GCOMP]); -} -#endif - - -/* MESA_FORMAT_RG88_REV ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D rg88_rev texture, return 4 GLchans */ -static void FETCH(f_rg88_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff ); - texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 ); - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -#if DIM == 3 -static void store_texel_rg88_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_88(rgba[GCOMP], rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_AL44 **********************************************************/ - -/* Fetch texel from 1D, 2D or 3D al44 texture, return 4 GLchans */ -static void FETCH(f_al44)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = (s & 0xf) * (1.0F / 15.0F); - texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); -} - -#if DIM == 3 -static void store_texel_al44(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = PACK_COLOR_44(rgba[ACOMP], rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_AL88 **********************************************************/ - -/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */ -static void FETCH(f_al88)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff ); - texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 ); -} - -#if DIM == 3 -static void store_texel_al88(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_88(rgba[ACOMP], rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_R8 ************************************************************/ - -/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */ -static void FETCH(f_r8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - texel[RCOMP] = UBYTE_TO_FLOAT(s); - texel[GCOMP] = 0.0; - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -#if DIM == 3 -static void store_texel_r8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_R16 ***********************************************************/ - -/* Fetch texel from 1D, 2D or 3D r16 texture, return 4 GLchans */ -static void FETCH(f_r16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = USHORT_TO_FLOAT(s); - texel[GCOMP] = 0.0; - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -#if DIM == 3 -static void store_texel_r16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_AL88_REV ******************************************************/ - -/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */ -static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 ); - texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff ); -} - -#if DIM == 3 -static void store_texel_al88_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_88(rgba[RCOMP], rgba[ACOMP]); -} -#endif - - -/* MESA_FORMAT_RG1616 ********************************************************/ - -/* Fetch texel from 1D, 2D or 3D rg1616 texture, return 4 GLchans */ -static void FETCH(f_rg1616)( 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] = USHORT_TO_FLOAT( s & 0xffff ); - texel[GCOMP] = USHORT_TO_FLOAT( s >> 16 ); - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -#if DIM == 3 -static void store_texel_rg1616(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[GCOMP]); -} -#endif - - -/* MESA_FORMAT_RG1616_REV ****************************************************/ - -/* Fetch texel from 1D, 2D or 3D rg1616_rev texture, return 4 GLchans */ -static void FETCH(f_rg1616_rev)( 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] = USHORT_TO_FLOAT( s >> 16 ); - texel[GCOMP] = USHORT_TO_FLOAT( s & 0xffff ); - texel[BCOMP] = 0.0; - texel[ACOMP] = 1.0; -} - -#if DIM == 3 -static void store_texel_rg1616_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = PACK_COLOR_1616(rgba[GCOMP], rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_AL1616 ********************************************************/ - -/* Fetch texel from 1D, 2D or 3D al1616 texture, return 4 GLchans */ -static void FETCH(f_al1616)( 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] = - texel[GCOMP] = - texel[BCOMP] = USHORT_TO_FLOAT( s & 0xffff ); - texel[ACOMP] = USHORT_TO_FLOAT( s >> 16 ); -} - -#if DIM == 3 -static void store_texel_al1616(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_1616(rgba[ACOMP], rgba[RCOMP]); -} -#endif - - -/* MESA_FORMAT_AL1616_REV ****************************************************/ - -/* Fetch texel from 1D, 2D or 3D al1616_rev texture, return 4 GLchans */ -static void FETCH(f_al1616_rev)( 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] = - texel[GCOMP] = - texel[BCOMP] = USHORT_TO_FLOAT( s >> 16 ); - texel[ACOMP] = USHORT_TO_FLOAT( s & 0xffff ); -} - -#if DIM == 3 -static void store_texel_al1616_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[ACOMP]); -} -#endif - - -/* MESA_FORMAT_RGB332 ********************************************************/ - -/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */ -static void FETCH(f_rgb332)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - const GLubyte s = *src; - texel[RCOMP] = ((s >> 5) & 0x7) * (1.0F / 7.0F); - texel[GCOMP] = ((s >> 2) & 0x7) * (1.0F / 7.0F); - texel[BCOMP] = ((s ) & 0x3) * (1.0F / 3.0F); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_rgb332(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = PACK_COLOR_332(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - - -/* MESA_FORMAT_A8 ************************************************************/ - -/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ -static void FETCH(f_a8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = 0.0F; - texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); -} - -#if DIM == 3 -static void store_texel_a8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_A16 ************************************************************/ - -/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ -static void FETCH(f_a16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = 0.0F; - texel[ACOMP] = USHORT_TO_FLOAT( src[0] ); -} - -#if DIM == 3 -static void store_texel_a16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_L8 ************************************************************/ - -/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */ -static void FETCH(f_l8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_l8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_L16 ***********************************************************/ - -/* Fetch texel from 1D, 2D or 3D l16 texture, return 4 GLchans */ -static void FETCH(f_l16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = USHORT_TO_FLOAT( src[0] ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_l16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_I8 ************************************************************/ - -/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */ -static void FETCH(f_i8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); -} - -#if DIM == 3 -static void store_texel_i8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_I16 ***********************************************************/ - -/* Fetch texel from 1D, 2D or 3D i16 texture, return 4 GLchans */ -static void FETCH(f_i16)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = USHORT_TO_FLOAT( src[0] ); -} - -#if DIM == 3 -static void store_texel_i16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_CI8 ***********************************************************/ - -/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a - * color table, and return 4 GLchans. - */ -static void FETCH(f_ci8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - const struct gl_color_table *palette; - GLuint index; - GET_CURRENT_CONTEXT(ctx); - - if (ctx->Texture.SharedPalette) { - palette = &ctx->Texture.Palette; - } - else { - palette = &texImage->TexObject->Palette; - } - if (palette->Size == 0) - return; /* undefined results */ - - /* Mask the index against size of palette to avoid going out of bounds */ - index = (*src) & (palette->Size - 1); - - { - const GLfloat *table = palette->TableF; - switch (palette->_BaseFormat) { - case GL_ALPHA: - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = 0.0F; - texel[ACOMP] = table[index]; - break; - case GL_LUMINANCE: - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = table[index]; - texel[ACOMP] = 1.0F; - break; - case GL_INTENSITY: - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = table[index]; - break; - case GL_LUMINANCE_ALPHA: - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = table[index * 2 + 0]; - texel[ACOMP] = table[index * 2 + 1]; - break; - case GL_RGB: - texel[RCOMP] = table[index * 3 + 0]; - texel[GCOMP] = table[index * 3 + 1]; - texel[BCOMP] = table[index * 3 + 2]; - texel[ACOMP] = 1.0F; - break; - case GL_RGBA: - texel[RCOMP] = table[index * 4 + 0]; - texel[GCOMP] = table[index * 4 + 1]; - texel[BCOMP] = table[index * 4 + 2]; - texel[ACOMP] = table[index * 4 + 3]; - break; - default: - _mesa_problem(ctx, "Bad palette format in fetch_texel_ci8"); - return; - } - } -} - -#if DIM == 3 -static void store_texel_ci8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *index = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - *dst = *index; -} -#endif - - -/* Fetch texel from 1D, 2D or 3D srgb8 texture, return 4 GLfloats */ -/* Note: component order is same as for MESA_FORMAT_RGB888 */ -static void FETCH(srgb8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - texel[RCOMP] = nonlinear_to_linear(src[2]); - texel[GCOMP] = nonlinear_to_linear(src[1]); - texel[BCOMP] = nonlinear_to_linear(src[0]); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_srgb8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); - dst[0] = rgba[BCOMP]; /* no conversion */ - dst[1] = rgba[GCOMP]; - dst[2] = rgba[RCOMP]; -} -#endif - -/* Fetch texel from 1D, 2D or 3D srgba8 texture, return 4 GLfloats */ -static void FETCH(srgba8)(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] = nonlinear_to_linear( (s >> 24) ); - texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); - texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); - texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */ -} - -#if DIM == 3 -static void store_texel_srgba8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); -} -#endif - -/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */ -static void FETCH(sargb8)(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] = nonlinear_to_linear( (s >> 16) & 0xff ); - texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); - texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff ); - texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */ -} - -#if DIM == 3 -static void store_texel_sargb8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); -} -#endif - -/* Fetch texel from 1D, 2D or 3D sl8 texture, return 4 GLfloats */ -static void FETCH(sl8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = nonlinear_to_linear(src[0]); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_sl8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); - dst[0] = rgba[RCOMP]; -} -#endif - -/* Fetch texel from 1D, 2D or 3D sla8 texture, return 4 GLfloats */ -static void FETCH(sla8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = nonlinear_to_linear(src[0]); - texel[ACOMP] = UBYTE_TO_FLOAT(src[1]); /* linear */ -} - -#if DIM == 3 -static void store_texel_sla8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_INT8 **************************************************/ - -static void -FETCH(rgba_int8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4); - texel[RCOMP] = (GLfloat) src[0]; - texel[GCOMP] = (GLfloat) src[1]; - texel[BCOMP] = (GLfloat) src[2]; - texel[ACOMP] = (GLfloat) src[3]; -} - -#if DIM == 3 -static void -store_texel_rgba_int8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rgba = (const GLbyte *) texel; - GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_INT16 **************************************************/ - -static void -FETCH(rgba_int16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLshort *src = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); - texel[RCOMP] = (GLfloat) src[0]; - texel[GCOMP] = (GLfloat) src[1]; - texel[BCOMP] = (GLfloat) src[2]; - texel[ACOMP] = (GLfloat) src[3]; -} - -#if DIM == 3 -static void -store_texel_rgba_int16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_INT32 **************************************************/ - -static void -FETCH(rgba_int32)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLint *src = TEXEL_ADDR(GLint, texImage, i, j, k, 4); - texel[RCOMP] = (GLfloat) src[0]; - texel[GCOMP] = (GLfloat) src[1]; - texel[BCOMP] = (GLfloat) src[2]; - texel[ACOMP] = (GLfloat) src[3]; -} - -#if DIM == 3 -static void -store_texel_rgba_int32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLint *rgba = (const GLint *) texel; - GLint *dst = TEXEL_ADDR(GLint, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_UINT8 **************************************************/ - -static void -FETCH(rgba_uint8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4); - texel[RCOMP] = (GLfloat) src[0]; - texel[GCOMP] = (GLfloat) src[1]; - texel[BCOMP] = (GLfloat) src[2]; - texel[ACOMP] = (GLfloat) src[3]; -} - -#if DIM == 3 -static void -store_texel_rgba_uint8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_UINT16 **************************************************/ - -static void -FETCH(rgba_uint16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); - texel[RCOMP] = (GLfloat) src[0]; - texel[GCOMP] = (GLfloat) src[1]; - texel[BCOMP] = (GLfloat) src[2]; - texel[ACOMP] = (GLfloat) src[3]; -} - -#if DIM == 3 -static void -store_texel_rgba_uint16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_RGBA_UINT32 **************************************************/ - -static void -FETCH(rgba_uint32)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 4); - texel[RCOMP] = (GLfloat) src[0]; - texel[GCOMP] = (GLfloat) src[1]; - texel[BCOMP] = (GLfloat) src[2]; - texel[ACOMP] = (GLfloat) src[3]; -} - -#if DIM == 3 -static void -store_texel_rgba_uint32(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLuint *rgba = (const GLuint *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_DUDV8 ********************************************************/ - -/* this format by definition produces 0,0,0,1 as rgba values, - however we'll return the dudv values as rg and fix up elsewhere */ -static void FETCH(dudv8)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2); - texel[RCOMP] = BYTE_TO_FLOAT(src[0]); - texel[GCOMP] = BYTE_TO_FLOAT(src[1]); - texel[BCOMP] = 0; - texel[ACOMP] = 0; -} - - -/* MESA_FORMAT_SIGNED_R8 ***********************************************/ - -static void FETCH(signed_r8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - texel[RCOMP] = BYTE_TO_FLOAT_TEX( s ); - texel[GCOMP] = 0.0F; - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_signed_r8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rgba = (const GLbyte *) texel; - GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_A8 ***********************************************/ - -static void FETCH(signed_a8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - texel[RCOMP] = 0.0F; - texel[GCOMP] = 0.0F; - texel[BCOMP] = 0.0F; - texel[ACOMP] = BYTE_TO_FLOAT_TEX( s ); -} - -#if DIM == 3 -static void store_texel_signed_a8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rgba = (const GLbyte *) texel; - GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - *dst = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_L8 ***********************************************/ - -static void FETCH(signed_l8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = BYTE_TO_FLOAT_TEX( s ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_signed_l8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rgba = (const GLbyte *) texel; - GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_I8 ***********************************************/ - -static void FETCH(signed_i8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = BYTE_TO_FLOAT_TEX( s ); -} - -#if DIM == 3 -static void store_texel_signed_i8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rgba = (const GLbyte *) texel; - GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_RG88_REV ***********************************************/ - -static void FETCH(signed_rg88_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) ); - texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_signed_rg88_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rg = (const GLbyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - dst[0] = PACK_COLOR_88(rg[GCOMP], rg[RCOMP]); -} -#endif - - -/* MESA_FORMAT_SIGNED_AL88 ***********************************************/ - -static void FETCH(signed_al88)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) ); - texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); -} - -#if DIM == 3 -static void store_texel_signed_al88(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLbyte *rg = (const GLbyte *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); - dst[0] = PACK_COLOR_88(rg[ACOMP], rg[RCOMP]); -} -#endif - - -/* MESA_FORMAT_SIGNED_RGBX8888 ***********************************************/ - -static void FETCH(signed_rgbx8888)( 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( (GLbyte) (s >> 24) ); - texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); - texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); - texel[ACOMP] = 1.0f; -} - -#if DIM == 3 -static void store_texel_signed_rgbx8888(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], 255); -} -#endif - - -/* MESA_FORMAT_SIGNED_RGBA8888 ***********************************************/ - -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( (GLbyte) (s >> 24) ); - texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); - texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); - texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s ) ); -} - -#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 - -static void FETCH(signed_rgba8888_rev)( 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( (GLbyte) (s ) ); - texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); - texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); - texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) ); -} - -#if DIM == 3 -static void store_texel_signed_rgba8888_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLubyte *rgba = (const GLubyte *) texel; - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); -} -#endif - - - -/* MESA_FORMAT_SIGNED_R16 ***********************************************/ - -static void -FETCH(signed_r16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - texel[RCOMP] = SHORT_TO_FLOAT_TEX( s ); - texel[GCOMP] = 0.0F; - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void -store_texel_signed_r16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - *dst = rgba[0]; -} -#endif - - -/* MESA_FORMAT_SIGNED_A16 ***********************************************/ - -static void -FETCH(signed_a16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - texel[RCOMP] = 0.0F; - texel[GCOMP] = 0.0F; - texel[BCOMP] = 0.0F; - texel[ACOMP] = SHORT_TO_FLOAT_TEX( s ); -} - -#if DIM == 3 -static void -store_texel_signed_a16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - *dst = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_L16 ***********************************************/ - -static void -FETCH(signed_l16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = SHORT_TO_FLOAT_TEX( s ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void -store_texel_signed_l16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_I16 ***********************************************/ - -static void -FETCH(signed_i16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = - texel[ACOMP] = SHORT_TO_FLOAT_TEX( s ); -} - -#if DIM == 3 -static void -store_texel_signed_i16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); - *dst = rgba[RCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_RG1616 ***********************************************/ - -static void -FETCH(signed_rg1616)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); - texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); - texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); - texel[BCOMP] = 0.0F; - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void -store_texel_signed_rg1616(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_AL1616 ***********************************************/ - -static void -FETCH(signed_al1616)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); - texel[RCOMP] = - texel[GCOMP] = - texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); - texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[1] ); -} - -#if DIM == 3 -static void -store_texel_signed_al1616(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[ACOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_RGB_16 ***********************************************/ - -static void -FETCH(signed_rgb_16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 3); - texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); - texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); - texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] ); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void -store_texel_signed_rgb_16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 3); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; -} -#endif - - -/* MESA_FORMAT_SIGNED_RGBA_16 ***********************************************/ - -static void -FETCH(signed_rgba_16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); - texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); - texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); - texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] ); - texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[3] ); -} - -#if DIM == 3 -static void -store_texel_signed_rgba_16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLshort *rgba = (const GLshort *) texel; - GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - - -/* MESA_FORMAT_RGBA_16 ***********************************************/ - -static void -FETCH(rgba_16)(const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel) -{ - const GLushort *s = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); - texel[RCOMP] = USHORT_TO_FLOAT( s[0] ); - texel[GCOMP] = USHORT_TO_FLOAT( s[1] ); - texel[BCOMP] = USHORT_TO_FLOAT( s[2] ); - texel[ACOMP] = USHORT_TO_FLOAT( s[3] ); -} - -#if DIM == 3 -static void -store_texel_rgba_16(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - const GLushort *rgba = (const GLushort *) texel; - GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); - dst[0] = rgba[RCOMP]; - dst[1] = rgba[GCOMP]; - dst[2] = rgba[BCOMP]; - dst[3] = rgba[ACOMP]; -} -#endif - - - -/* MESA_FORMAT_YCBCR *********************************************************/ - -/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats. - * We convert YCbCr to RGB here. - */ -static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */ - const GLushort *src1 = src0 + 1; /* odd */ - const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */ - const GLubyte cb = *src0 & 0xff; /* chroma U */ - const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */ - const GLubyte cr = *src1 & 0xff; /* chroma V */ - const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */ - GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128); - GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128); - GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128); - r *= (1.0F / 255.0F); - g *= (1.0F / 255.0F); - b *= (1.0F / 255.0F); - texel[RCOMP] = CLAMP(r, 0.0F, 1.0F); - texel[GCOMP] = CLAMP(g, 0.0F, 1.0F); - texel[BCOMP] = CLAMP(b, 0.0F, 1.0F); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_ycbcr(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - (void) texImage; - (void) i; - (void) j; - (void) k; - (void) texel; - /* XXX to do */ -} -#endif - - -/* MESA_FORMAT_YCBCR_REV *****************************************************/ - -/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats. - * We convert YCbCr to RGB here. - */ -static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */ - const GLushort *src1 = src0 + 1; /* odd */ - const GLubyte y0 = *src0 & 0xff; /* luminance */ - const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */ - const GLubyte y1 = *src1 & 0xff; /* luminance */ - const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */ - const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */ - GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128); - GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128); - GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128); - r *= (1.0F / 255.0F); - g *= (1.0F / 255.0F); - b *= (1.0F / 255.0F); - texel[RCOMP] = CLAMP(r, 0.0F, 1.0F); - texel[GCOMP] = CLAMP(g, 0.0F, 1.0F); - texel[BCOMP] = CLAMP(b, 0.0F, 1.0F); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_ycbcr_rev(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - (void) texImage; - (void) i; - (void) j; - (void) k; - (void) texel; - /* XXX to do */ -} -#endif - - -/* MESA_TEXFORMAT_Z24_S8 ***************************************************/ - -static void FETCH(f_z24_s8)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - /* only return Z, not stencil data */ - const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - const GLfloat scale = 1.0F / (GLfloat) 0xffffff; - texel[0] = ((*src) >> 8) * scale; - ASSERT(texImage->TexFormat == MESA_FORMAT_Z24_S8); - ASSERT(texel[0] >= 0.0F); - ASSERT(texel[0] <= 1.0F); -} - -#if DIM == 3 -static void store_texel_z24_s8(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - /* only store Z, not stencil */ - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - GLfloat depth = *((GLfloat *) texel); - GLuint zi = ((GLuint) (depth * 0xffffff)) << 8; - *dst = zi | (*dst & 0xff); -} -#endif - - -/* MESA_TEXFORMAT_S8_Z24 ***************************************************/ - -static void FETCH(f_s8_z24)( const struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, GLfloat *texel ) -{ - /* only return Z, not stencil data */ - const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - const GLfloat scale = 1.0F / (GLfloat) 0xffffff; - texel[0] = ((*src) & 0x00ffffff) * scale; - ASSERT(texImage->TexFormat == MESA_FORMAT_S8_Z24); - ASSERT(texel[0] >= 0.0F); - ASSERT(texel[0] <= 1.0F); -} - -#if DIM == 3 -static void store_texel_s8_z24(struct gl_texture_image *texImage, - GLint i, GLint j, GLint k, const void *texel) -{ - /* only store Z, not stencil */ - GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); - GLfloat depth = *((GLfloat *) texel); - GLuint zi = (GLuint) (depth * 0xffffff); - *dst = zi | (*dst & 0xff000000); -} -#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 - - -/* MESA_FORMAT_R11_G11_B10_FLOAT *********************************************/ - -static void FETCH(r11_g11_b10f)( 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); - r11g11b10f_to_float3(*src, texel); - texel[ACOMP] = 1.0F; -} - -#if DIM == 3 -static void store_texel_r11_g11_b10f(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_r11g11b10f(src); -} -#endif - - -#undef TEXEL_ADDR -#undef DIM -#undef FETCH +/* + * Mesa 3-D graphics library + * Version: 7.7 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (c) 2008-2009 VMware, Inc. + * + * 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 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 + * BRIAN PAUL 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. + */ + + +/** + * \file texfetch_tmp.h + * Texel fetch functions template. + * + * This template file is used by texfetch.c to generate texel fetch functions + * for 1-D, 2-D and 3-D texture images. + * + * It should be expanded by defining \p DIM as the number texture dimensions + * (1, 2 or 3). According to the value of \p DIM a series of macros is defined + * for the texel lookup in the gl_texture_image::Data. + * + * \author Gareth Hughes + * \author Brian Paul + */ + + +#if DIM == 1 + +#define TEXEL_ADDR( type, image, i, j, k, size ) \ + ((void) (j), (void) (k), ((type *)(image)->Data + (i) * (size))) + +#define FETCH(x) fetch_texel_1d_##x + +#elif DIM == 2 + +#define TEXEL_ADDR( type, image, i, j, k, size ) \ + ((void) (k), \ + ((type *)(image)->Data + ((image)->RowStride * (j) + (i)) * (size))) + +#define FETCH(x) fetch_texel_2d_##x + +#elif DIM == 3 + +#define TEXEL_ADDR( type, image, i, j, k, size ) \ + ((type *)(image)->Data + ((image)->ImageOffsets[k] \ + + (image)->RowStride * (j) + (i)) * (size)) + +#define FETCH(x) fetch_texel_3d_##x + +#else +#error illegal number of texture dimensions +#endif + + +/* MESA_FORMAT_Z32 ***********************************************************/ + +/* Fetch depth texel from 1D, 2D or 3D 32-bit depth texture, + * returning 1 GLfloat. + * Note: no GLchan version of this function. + */ +static void FETCH(f_z32)( 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); + texel[0] = src[0] * (1.0F / 0xffffffff); +} + +#if DIM == 3 +static void store_texel_z32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLuint *depth = (const GLuint *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + dst[0] = *depth; +} +#endif + + +/* MESA_FORMAT_Z16 ***********************************************************/ + +/* Fetch depth texel from 1D, 2D or 3D 16-bit depth texture, + * returning 1 GLfloat. + * Note: no GLchan version of this function. + */ +static void FETCH(f_z16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[0] = src[0] * (1.0F / 65535.0F); +} + +#if DIM == 3 +static void store_texel_z16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *depth = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + dst[0] = *depth; +} +#endif + + +/* MESA_FORMAT_RGBA_F32 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT32 texture, returning 4 GLfloats. + */ +static void FETCH(f_rgba_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = src[3]; +} + +#if DIM == 3 +static void store_texel_rgba_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *depth = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 4); + dst[0] = depth[RCOMP]; + dst[1] = depth[GCOMP]; + dst[2] = depth[BCOMP]; + dst[3] = depth[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_F16 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGBA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgba_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = _mesa_half_to_float(src[2]); + texel[ACOMP] = _mesa_half_to_float(src[3]); +} + +#if DIM == 3 +static void store_texel_rgba_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 4); + dst[0] = _mesa_float_to_half(src[RCOMP]); + dst[1] = _mesa_float_to_half(src[GCOMP]); + dst[2] = _mesa_float_to_half(src[BCOMP]); + dst[3] = _mesa_float_to_half(src[ACOMP]); +} +#endif + +/* MESA_FORMAT_RGB_F32 *******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgb_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = src[2]; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 3); + dst[0] = src[RCOMP]; + dst[1] = src[GCOMP]; + dst[2] = src[BCOMP]; +} +#endif + + +/* MESA_FORMAT_RGB_F16 *******************************************************/ + +/* Fetch texel from 1D, 2D or 3D RGB_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rgb_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = _mesa_half_to_float(src[2]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 3); + dst[0] = _mesa_float_to_half(src[RCOMP]); + dst[1] = _mesa_float_to_half(src[GCOMP]); + dst[2] = _mesa_float_to_half(src[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ALPHA_F32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = src[0]; +} + +#if DIM == 3 +static void store_texel_alpha_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_ALPHA_F32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = _mesa_half_to_float(src[0]); +} + +#if DIM == 3 +static void store_texel_alpha_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_LUMINANCE_F32 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_LUMINANCE_F16 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = _mesa_half_to_float(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_luminance_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_LUMINANCE_ALPHA_F32 *******************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_alpha_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = src[0]; + texel[ACOMP] = src[1]; +} + +#if DIM == 3 +static void store_texel_luminance_alpha_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_LUMINANCE_ALPHA_F16 *******************************************/ + +/* Fetch texel from 1D, 2D or 3D LUMINANCE_ALPHA_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_luminance_alpha_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = _mesa_half_to_float(src[0]); + texel[ACOMP] = _mesa_half_to_float(src[1]); +} + +#if DIM == 3 +static void store_texel_luminance_alpha_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); + dst[1] = _mesa_float_to_half(rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_INTENSITY_F32 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_intensity_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = src[0]; +} + +#if DIM == 3 +static void store_texel_intensity_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_INTENSITY_F16 *************************************************/ + +/* Fetch texel from 1D, 2D or 3D INTENSITY_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_intensity_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = _mesa_half_to_float(src[0]); +} + +#if DIM == 3 +static void store_texel_intensity_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_R_FLOAT32 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D R_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_r_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + texel[RCOMP] = src[0]; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_R_FLOAT16 *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D R_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_r_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 1); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_RG_FLOAT32 ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D RG_FLOAT32 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rg_f32)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = src[0]; + texel[GCOMP] = src[1]; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rg_f32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; +} +#endif + + +/* MESA_FORMAT_RG_FLOAT16 ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D RG_FLOAT16 texture, + * returning 4 GLfloats. + */ +static void FETCH(f_rg_f16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLhalfARB *src = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + texel[RCOMP] = _mesa_half_to_float(src[0]); + texel[GCOMP] = _mesa_half_to_float(src[1]); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rg_f16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *rgba = (const GLfloat *) texel; + GLhalfARB *dst = TEXEL_ADDR(GLhalfARB, texImage, i, j, k, 2); + dst[0] = _mesa_float_to_half(rgba[RCOMP]); + dst[1] = _mesa_float_to_half(rgba[GCOMP]); +} +#endif + + +/* + * Begin Hardware formats + */ + +/* MESA_FORMAT_RGBA8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgba8888 texture, return 4 GLfloats */ +static void FETCH(f_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] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); +} + + + +#if DIM == 3 +static void store_texel_rgba8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) 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_RGBA888_REV ***************************************************/ + +/* Fetch texel from 1D, 2D or 3D abgr8888 texture, return 4 GLchans */ +static void FETCH(f_rgba8888_rev)( 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] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_rgba8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb8888 texture, return 4 GLchans */ +static void FETCH(f_argb8888)( 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] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_argb8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB8888_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb8888_rev texture, return 4 GLfloats */ +static void FETCH(f_argb8888_rev)( 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] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); +} + +#if DIM == 3 +static void store_texel_argb8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_XRGB8888 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D xrgb8888 texture, return 4 GLchans */ +static void FETCH(f_xrgb8888)( 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] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); + texel[ACOMP] = 1.0f; +} + +#if DIM == 3 +static void store_texel_xrgb8888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(0xff, rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_XRGB8888_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D xrgb8888_rev texture, return 4 GLfloats */ +static void FETCH(f_xrgb8888_rev)( 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] = UBYTE_TO_FLOAT( (s >> 8) & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( (s >> 16) & 0xff ); + texel[BCOMP] = UBYTE_TO_FLOAT( (s >> 24) ); + texel[ACOMP] = 1.0f; +} + +#if DIM == 3 +static void store_texel_xrgb8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP], 0xff); +} +#endif + + +/* MESA_FORMAT_RGB888 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb888 texture, return 4 GLchans */ +static void FETCH(f_rgb888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + texel[RCOMP] = UBYTE_TO_FLOAT( src[2] ); + texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); + texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + dst[0] = rgba[BCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_BGR888 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D bgr888 texture, return 4 GLchans */ +static void FETCH(f_bgr888)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + texel[RCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[GCOMP] = UBYTE_TO_FLOAT( src[1] ); + texel[BCOMP] = UBYTE_TO_FLOAT( src[2] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_bgr888(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; +} +#endif + + +/* use color expansion like (g << 2) | (g >> 4) (does somewhat random rounding) + instead of slow (g << 2) * 255 / 252 (always rounds down) */ + +/* MESA_FORMAT_RGB565 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb565 texture, return 4 GLchans */ +static void FETCH(f_rgb565)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 5 ) & 0x3f) * (1.0F / 63.0F); + texel[BCOMP] = ((s ) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb565(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_565(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_RGB565_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb565_rev texture, return 4 GLchans */ +static void FETCH(f_rgb565_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = (*src >> 8) | (*src << 8); /* byte swap */ + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf8) | ((s >> 13) & 0x7) ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 3) & 0xfc) | ((s >> 9) & 0x3) ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb565_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_565(rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB4444 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb444 texture, return 4 GLchans */ +static void FETCH(f_argb4444)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); + texel[GCOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); + texel[BCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_argb4444(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB4444_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb4444_rev texture, return 4 GLchans */ +static void FETCH(f_argb4444_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = ((s ) & 0xf) * (1.0F / 15.0F); + texel[GCOMP] = ((s >> 12) & 0xf) * (1.0F / 15.0F); + texel[BCOMP] = ((s >> 8) & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_argb4444_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_4444(rgba[ACOMP], rgba[BCOMP], rgba[GCOMP], rgba[RCOMP]); +} +#endif + +/* MESA_FORMAT_RGBA5551 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ +static void FETCH(f_rgba5551)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 11) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 6) & 0x1f) * (1.0F / 31.0F); + texel[BCOMP] = ((s >> 1) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = ((s ) & 0x01) * 1.0F; +} + +#if DIM == 3 +static void store_texel_rgba5551(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_5551(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + +/* MESA_FORMAT_ARGB1555 ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555 texture, return 4 GLchans */ +static void FETCH(f_argb1555)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = *src; + texel[RCOMP] = ((s >> 10) & 0x1f) * (1.0F / 31.0F); + texel[GCOMP] = ((s >> 5) & 0x1f) * (1.0F / 31.0F); + texel[BCOMP] = ((s >> 0) & 0x1f) * (1.0F / 31.0F); + texel[ACOMP] = ((s >> 15) & 0x01) * 1.0F; +} + +#if DIM == 3 +static void store_texel_argb1555(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1555(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB1555_REV **************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb1555_rev texture, return 4 GLchans */ +static void FETCH(f_argb1555_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + const GLushort s = (*src << 8) | (*src >> 8); /* byteswap */ + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 7) & 0xf8) | ((s >> 12) & 0x7) ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 2) & 0xf8) | ((s >> 7) & 0x7) ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s << 3) & 0xf8) | ((s >> 2) & 0x7) ); + texel[ACOMP] = UBYTE_TO_FLOAT( ((s >> 15) & 0x01) * 255 ); +} + +#if DIM == 3 +static void store_texel_argb1555_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1555_REV(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_ARGB2101010 ***************************************************/ + +/* Fetch texel from 1D, 2D or 3D argb2101010 texture, return 4 GLchans */ +static void FETCH(f_argb2101010)( 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); + const GLuint s = *src; + texel[RCOMP] = ((s >> 20) & 0x3ff) * (1.0F / 1023.0F); + texel[GCOMP] = ((s >> 10) & 0x3ff) * (1.0F / 1023.0F); + texel[BCOMP] = ((s >> 0) & 0x3ff) * (1.0F / 1023.0F); + texel[ACOMP] = ((s >> 30) & 0x03) * (1.0F / 3.0F); +} + +#if DIM == 3 +static void store_texel_argb2101010(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_2101010_UB(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_RG88 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */ +static void FETCH(f_rg88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[RCOMP], rgba[GCOMP]); +} +#endif + + +/* MESA_FORMAT_RG88_REV ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg88_rev texture, return 4 GLchans */ +static void FETCH(f_rg88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[GCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL44 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al44 texture, return 4 GLchans */ +static void FETCH(f_al44)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = (s & 0xf) * (1.0F / 15.0F); + texel[ACOMP] = ((s >> 4) & 0xf) * (1.0F / 15.0F); +} + +#if DIM == 3 +static void store_texel_al44(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = PACK_COLOR_44(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL88 **********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al88 texture, return 4 GLchans */ +static void FETCH(f_al88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( s & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( s >> 8 ); +} + +#if DIM == 3 +static void store_texel_al88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_R8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg88 texture, return 4 GLchans */ +static void FETCH(f_r8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLubyte s = *TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = UBYTE_TO_FLOAT(s); + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_r8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_R16 ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D r16 texture, return 4 GLchans */ +static void FETCH(f_r16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = USHORT_TO_FLOAT(s); + texel[GCOMP] = 0.0; + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_r16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_AL88_REV ******************************************************/ + +/* Fetch texel from 1D, 2D or 3D al88_rev texture, return 4 GLchans */ +static void FETCH(f_al88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( s >> 8 ); + texel[ACOMP] = UBYTE_TO_FLOAT( s & 0xff ); +} + +#if DIM == 3 +static void store_texel_al88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_88(rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RG1616 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg1616 texture, return 4 GLchans */ +static void FETCH(f_rg1616)( 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] = USHORT_TO_FLOAT( s & 0xffff ); + texel[GCOMP] = USHORT_TO_FLOAT( s >> 16 ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[GCOMP]); +} +#endif + + +/* MESA_FORMAT_RG1616_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D rg1616_rev texture, return 4 GLchans */ +static void FETCH(f_rg1616_rev)( 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] = USHORT_TO_FLOAT( s >> 16 ); + texel[GCOMP] = USHORT_TO_FLOAT( s & 0xffff ); + texel[BCOMP] = 0.0; + texel[ACOMP] = 1.0; +} + +#if DIM == 3 +static void store_texel_rg1616_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[GCOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL1616 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D al1616 texture, return 4 GLchans */ +static void FETCH(f_al1616)( 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] = + texel[GCOMP] = + texel[BCOMP] = USHORT_TO_FLOAT( s & 0xffff ); + texel[ACOMP] = USHORT_TO_FLOAT( s >> 16 ); +} + +#if DIM == 3 +static void store_texel_al1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[ACOMP], rgba[RCOMP]); +} +#endif + + +/* MESA_FORMAT_AL1616_REV ****************************************************/ + +/* Fetch texel from 1D, 2D or 3D al1616_rev texture, return 4 GLchans */ +static void FETCH(f_al1616_rev)( 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] = + texel[GCOMP] = + texel[BCOMP] = USHORT_TO_FLOAT( s >> 16 ); + texel[ACOMP] = USHORT_TO_FLOAT( s & 0xffff ); +} + +#if DIM == 3 +static void store_texel_al1616_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_1616(rgba[RCOMP], rgba[ACOMP]); +} +#endif + + +/* MESA_FORMAT_RGB332 ********************************************************/ + +/* Fetch texel from 1D, 2D or 3D rgb332 texture, return 4 GLchans */ +static void FETCH(f_rgb332)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + const GLubyte s = *src; + texel[RCOMP] = ((s >> 5) & 0x7) * (1.0F / 7.0F); + texel[GCOMP] = ((s >> 2) & 0x7) * (1.0F / 7.0F); + texel[BCOMP] = ((s ) & 0x3) * (1.0F / 3.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_rgb332(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = PACK_COLOR_332(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + + +/* MESA_FORMAT_A8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ +static void FETCH(f_a8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_a8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_A16 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D a8 texture, return 4 GLchans */ +static void FETCH(f_a16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = USHORT_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_a16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_L8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D l8 texture, return 4 GLchans */ +static void FETCH(f_l8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = UBYTE_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_l8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_L16 ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D l16 texture, return 4 GLchans */ +static void FETCH(f_l16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = USHORT_TO_FLOAT( src[0] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_l16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_I8 ************************************************************/ + +/* Fetch texel from 1D, 2D or 3D i8 texture, return 4 GLchans */ +static void FETCH(f_i8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = UBYTE_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_i8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_I16 ***********************************************************/ + +/* Fetch texel from 1D, 2D or 3D i16 texture, return 4 GLchans */ +static void FETCH(f_i16)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = USHORT_TO_FLOAT( src[0] ); +} + +#if DIM == 3 +static void store_texel_i16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_CI8 ***********************************************************/ + +/* Fetch CI texel from 1D, 2D or 3D ci8 texture, lookup the index in a + * color table, and return 4 GLchans. + */ +static void FETCH(f_ci8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + const struct gl_color_table *palette; + GLuint index; + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Texture.SharedPalette) { + palette = &ctx->Texture.Palette; + } + else { + palette = &texImage->TexObject->Palette; + } + if (palette->Size == 0) + return; /* undefined results */ + + /* Mask the index against size of palette to avoid going out of bounds */ + index = (*src) & (palette->Size - 1); + + { + const GLfloat *table = palette->TableF; + switch (palette->_BaseFormat) { + case GL_ALPHA: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = 0.0F; + texel[ACOMP] = table[index]; + break; + case GL_LUMINANCE: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = table[index]; + texel[ACOMP] = 1.0F; + break; + case GL_INTENSITY: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = table[index]; + break; + case GL_LUMINANCE_ALPHA: + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = table[index * 2 + 0]; + texel[ACOMP] = table[index * 2 + 1]; + break; + case GL_RGB: + texel[RCOMP] = table[index * 3 + 0]; + texel[GCOMP] = table[index * 3 + 1]; + texel[BCOMP] = table[index * 3 + 2]; + texel[ACOMP] = 1.0F; + break; + case GL_RGBA: + texel[RCOMP] = table[index * 4 + 0]; + texel[GCOMP] = table[index * 4 + 1]; + texel[BCOMP] = table[index * 4 + 2]; + texel[ACOMP] = table[index * 4 + 3]; + break; + default: + _mesa_problem(ctx, "Bad palette format in fetch_texel_ci8"); + return; + } + } +} + +#if DIM == 3 +static void store_texel_ci8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *index = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + *dst = *index; +} +#endif + + +/* Fetch texel from 1D, 2D or 3D srgb8 texture, return 4 GLfloats */ +/* Note: component order is same as for MESA_FORMAT_RGB888 */ +static void FETCH(srgb8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + texel[RCOMP] = nonlinear_to_linear(src[2]); + texel[GCOMP] = nonlinear_to_linear(src[1]); + texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_srgb8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 3); + dst[0] = rgba[BCOMP]; /* no conversion */ + dst[1] = rgba[GCOMP]; + dst[2] = rgba[RCOMP]; +} +#endif + +/* Fetch texel from 1D, 2D or 3D srgba8 texture, return 4 GLfloats */ +static void FETCH(srgba8)(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] = nonlinear_to_linear( (s >> 24) ); + texel[GCOMP] = nonlinear_to_linear( (s >> 16) & 0xff ); + texel[BCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s ) & 0xff ); /* linear! */ +} + +#if DIM == 3 +static void store_texel_srgba8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + +/* Fetch texel from 1D, 2D or 3D sargb8 texture, return 4 GLfloats */ +static void FETCH(sargb8)(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] = nonlinear_to_linear( (s >> 16) & 0xff ); + texel[GCOMP] = nonlinear_to_linear( (s >> 8) & 0xff ); + texel[BCOMP] = nonlinear_to_linear( (s ) & 0xff ); + texel[ACOMP] = UBYTE_TO_FLOAT( (s >> 24) ); /* linear! */ +} + +#if DIM == 3 +static void store_texel_sargb8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888(rgba[ACOMP], rgba[RCOMP], rgba[GCOMP], rgba[BCOMP]); +} +#endif + +/* Fetch texel from 1D, 2D or 3D sl8 texture, return 4 GLfloats */ +static void FETCH(sl8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_sl8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 1); + dst[0] = rgba[RCOMP]; +} +#endif + +/* Fetch texel from 1D, 2D or 3D sla8 texture, return 4 GLfloats */ +static void FETCH(sla8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = nonlinear_to_linear(src[0]); + texel[ACOMP] = UBYTE_TO_FLOAT(src[1]); /* linear */ +} + +#if DIM == 3 +static void store_texel_sla8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_INT8 **************************************************/ + +static void +FETCH(rgba_int8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_int8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_INT16 **************************************************/ + +static void +FETCH(rgba_int16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLshort *src = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_int16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_INT32 **************************************************/ + +static void +FETCH(rgba_int32)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLint *src = TEXEL_ADDR(GLint, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_int32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLint *rgba = (const GLint *) texel; + GLint *dst = TEXEL_ADDR(GLint, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_UINT8 **************************************************/ + +static void +FETCH(rgba_uint8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLubyte *src = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_uint8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLubyte *dst = TEXEL_ADDR(GLubyte, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_UINT16 **************************************************/ + +static void +FETCH(rgba_uint16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_uint16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_RGBA_UINT32 **************************************************/ + +static void +FETCH(rgba_uint32)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 4); + texel[RCOMP] = (GLfloat) src[0]; + texel[GCOMP] = (GLfloat) src[1]; + texel[BCOMP] = (GLfloat) src[2]; + texel[ACOMP] = (GLfloat) src[3]; +} + +#if DIM == 3 +static void +store_texel_rgba_uint32(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLuint *rgba = (const GLuint *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_DUDV8 ********************************************************/ + +/* this format by definition produces 0,0,0,1 as rgba values, + however we'll return the dudv values as rg and fix up elsewhere */ +static void FETCH(dudv8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2); + texel[RCOMP] = BYTE_TO_FLOAT(src[0]); + texel[GCOMP] = BYTE_TO_FLOAT(src[1]); + texel[BCOMP] = 0; + texel[ACOMP] = 0; +} + + +/* MESA_FORMAT_SIGNED_R8 ***********************************************/ + +static void FETCH(signed_r8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( s ); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_signed_r8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_A8 ***********************************************/ + +static void FETCH(signed_a8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = 0.0F; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = BYTE_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void store_texel_signed_a8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_L8 ***********************************************/ + +static void FETCH(signed_l8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = BYTE_TO_FLOAT_TEX( s ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_signed_l8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_I8 ***********************************************/ + +static void FETCH(signed_i8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLbyte s = *TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = BYTE_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void store_texel_signed_i8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rgba = (const GLbyte *) texel; + GLbyte *dst = TEXEL_ADDR(GLbyte, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RG88_REV ***********************************************/ + +static void FETCH(signed_rg88_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_signed_rg88_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rg = (const GLbyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + dst[0] = PACK_COLOR_88(rg[GCOMP], rg[RCOMP]); +} +#endif + + +/* MESA_FORMAT_SIGNED_AL88 ***********************************************/ + +static void FETCH(signed_al88)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s & 0xff) ); + texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); +} + +#if DIM == 3 +static void store_texel_signed_al88(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLbyte *rg = (const GLbyte *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 1); + dst[0] = PACK_COLOR_88(rg[ACOMP], rg[RCOMP]); +} +#endif + + +/* MESA_FORMAT_SIGNED_RGBX8888 ***********************************************/ + +static void FETCH(signed_rgbx8888)( 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( (GLbyte) (s >> 24) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[ACOMP] = 1.0f; +} + +#if DIM == 3 +static void store_texel_signed_rgbx8888(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], 255); +} +#endif + + +/* MESA_FORMAT_SIGNED_RGBA8888 ***********************************************/ + +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( (GLbyte) (s >> 24) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s ) ); +} + +#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 + +static void FETCH(signed_rgba8888_rev)( 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( (GLbyte) (s ) ); + texel[GCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 8) ); + texel[BCOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 16) ); + texel[ACOMP] = BYTE_TO_FLOAT_TEX( (GLbyte) (s >> 24) ); +} + +#if DIM == 3 +static void store_texel_signed_rgba8888_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLubyte *rgba = (const GLubyte *) texel; + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + *dst = PACK_COLOR_8888_REV(rgba[RCOMP], rgba[GCOMP], rgba[BCOMP], rgba[ACOMP]); +} +#endif + + + +/* MESA_FORMAT_SIGNED_R16 ***********************************************/ + +static void +FETCH(signed_r16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s ); + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_r16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[0]; +} +#endif + + +/* MESA_FORMAT_SIGNED_A16 ***********************************************/ + +static void +FETCH(signed_a16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = 0.0F; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void +store_texel_signed_a16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_L16 ***********************************************/ + +static void +FETCH(signed_l16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_l16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_I16 ***********************************************/ + +static void +FETCH(signed_i16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort s = *TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s ); +} + +#if DIM == 3 +static void +store_texel_signed_i16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 1); + *dst = rgba[RCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RG1616 ***********************************************/ + +static void +FETCH(signed_rg1616)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_rg1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_AL1616 ***********************************************/ + +static void +FETCH(signed_al1616)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + texel[RCOMP] = + texel[GCOMP] = + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[1] ); +} + +#if DIM == 3 +static void +store_texel_signed_al1616(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 2); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[ACOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RGB_16 ***********************************************/ + +static void +FETCH(signed_rgb_16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 3); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] ); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void +store_texel_signed_rgb_16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 3); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; +} +#endif + + +/* MESA_FORMAT_SIGNED_RGBA_16 ***********************************************/ + +static void +FETCH(signed_rgba_16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLshort *s = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + texel[RCOMP] = SHORT_TO_FLOAT_TEX( s[0] ); + texel[GCOMP] = SHORT_TO_FLOAT_TEX( s[1] ); + texel[BCOMP] = SHORT_TO_FLOAT_TEX( s[2] ); + texel[ACOMP] = SHORT_TO_FLOAT_TEX( s[3] ); +} + +#if DIM == 3 +static void +store_texel_signed_rgba_16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLshort *rgba = (const GLshort *) texel; + GLshort *dst = TEXEL_ADDR(GLshort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + + +/* MESA_FORMAT_RGBA_16 ***********************************************/ + +static void +FETCH(rgba_16)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLushort *s = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + texel[RCOMP] = USHORT_TO_FLOAT( s[0] ); + texel[GCOMP] = USHORT_TO_FLOAT( s[1] ); + texel[BCOMP] = USHORT_TO_FLOAT( s[2] ); + texel[ACOMP] = USHORT_TO_FLOAT( s[3] ); +} + +#if DIM == 3 +static void +store_texel_rgba_16(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLushort *rgba = (const GLushort *) texel; + GLushort *dst = TEXEL_ADDR(GLushort, texImage, i, j, k, 4); + dst[0] = rgba[RCOMP]; + dst[1] = rgba[GCOMP]; + dst[2] = rgba[BCOMP]; + dst[3] = rgba[ACOMP]; +} +#endif + + + +/* MESA_FORMAT_YCBCR *********************************************************/ + +/* Fetch texel from 1D, 2D or 3D ycbcr texture, return 4 GLfloats. + * We convert YCbCr to RGB here. + */ +static void FETCH(f_ycbcr)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = (*src0 >> 8) & 0xff; /* luminance */ + const GLubyte cb = *src0 & 0xff; /* chroma U */ + const GLubyte y1 = (*src1 >> 8) & 0xff; /* luminance */ + const GLubyte cr = *src1 & 0xff; /* chroma V */ + const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */ + GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128); + GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128); + GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128); + r *= (1.0F / 255.0F); + g *= (1.0F / 255.0F); + b *= (1.0F / 255.0F); + texel[RCOMP] = CLAMP(r, 0.0F, 1.0F); + texel[GCOMP] = CLAMP(g, 0.0F, 1.0F); + texel[BCOMP] = CLAMP(b, 0.0F, 1.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_ycbcr(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + (void) texImage; + (void) i; + (void) j; + (void) k; + (void) texel; + /* XXX to do */ +} +#endif + + +/* MESA_FORMAT_YCBCR_REV *****************************************************/ + +/* Fetch texel from 1D, 2D or 3D ycbcr_rev texture, return 4 GLfloats. + * We convert YCbCr to RGB here. + */ +static void FETCH(f_ycbcr_rev)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src0 = TEXEL_ADDR(GLushort, texImage, (i & ~1), j, k, 1); /* even */ + const GLushort *src1 = src0 + 1; /* odd */ + const GLubyte y0 = *src0 & 0xff; /* luminance */ + const GLubyte cr = (*src0 >> 8) & 0xff; /* chroma V */ + const GLubyte y1 = *src1 & 0xff; /* luminance */ + const GLubyte cb = (*src1 >> 8) & 0xff; /* chroma U */ + const GLubyte y = (i & 1) ? y1 : y0; /* choose even/odd luminance */ + GLfloat r = 1.164F * (y - 16) + 1.596F * (cr - 128); + GLfloat g = 1.164F * (y - 16) - 0.813F * (cr - 128) - 0.391F * (cb - 128); + GLfloat b = 1.164F * (y - 16) + 2.018F * (cb - 128); + r *= (1.0F / 255.0F); + g *= (1.0F / 255.0F); + b *= (1.0F / 255.0F); + texel[RCOMP] = CLAMP(r, 0.0F, 1.0F); + texel[GCOMP] = CLAMP(g, 0.0F, 1.0F); + texel[BCOMP] = CLAMP(b, 0.0F, 1.0F); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_ycbcr_rev(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + (void) texImage; + (void) i; + (void) j; + (void) k; + (void) texel; + /* XXX to do */ +} +#endif + + +/* MESA_TEXFORMAT_Z24_S8 ***************************************************/ + +static void FETCH(f_z24_s8)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* only return Z, not stencil data */ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + const GLfloat scale = 1.0F / (GLfloat) 0xffffff; + texel[0] = ((*src) >> 8) * scale; + ASSERT(texImage->TexFormat == MESA_FORMAT_Z24_S8); + ASSERT(texel[0] >= 0.0F); + ASSERT(texel[0] <= 1.0F); +} + +#if DIM == 3 +static void store_texel_z24_s8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* only store Z, not stencil */ + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + GLfloat depth = *((GLfloat *) texel); + GLuint zi = ((GLuint) (depth * 0xffffff)) << 8; + *dst = zi | (*dst & 0xff); +} +#endif + + +/* MESA_TEXFORMAT_S8_Z24 ***************************************************/ + +static void FETCH(f_s8_z24)( const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + /* only return Z, not stencil data */ + const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + const GLfloat scale = 1.0F / (GLfloat) 0xffffff; + texel[0] = ((*src) & 0x00ffffff) * scale; + ASSERT(texImage->TexFormat == MESA_FORMAT_S8_Z24); + ASSERT(texel[0] >= 0.0F); + ASSERT(texel[0] <= 1.0F); +} + +#if DIM == 3 +static void store_texel_s8_z24(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + /* only store Z, not stencil */ + GLuint *dst = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); + GLfloat depth = *((GLfloat *) texel); + GLuint zi = (GLuint) (depth * 0xffffff); + *dst = zi | (*dst & 0xff000000); +} +#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 + + +/* MESA_FORMAT_R11_G11_B10_FLOAT *********************************************/ + +static void FETCH(r11_g11_b10f)( 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); + r11g11b10f_to_float3(*src, texel); + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_r11_g11_b10f(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_r11g11b10f(src); +} +#endif + + +/* MESA_FORMAT_Z32_FLOAT_X24S8 ***********************************************/ + +static void FETCH(z32f_x24s8)(const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + const GLfloat *src = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + texel[RCOMP] = src[0]; + texel[GCOMP] = 0.0F; + texel[BCOMP] = 0.0F; + texel[ACOMP] = 1.0F; +} + +#if DIM == 3 +static void store_texel_z32f_x24s8(struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, const void *texel) +{ + const GLfloat *src = (const GLfloat *) texel; + GLfloat *dst = TEXEL_ADDR(GLfloat, texImage, i, j, k, 2); + dst[0] = src[0]; +} +#endif + + +#undef TEXEL_ADDR +#undef DIM +#undef FETCH diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index 8cbb021d8..c919a74e0 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -416,6 +416,19 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat, } } + if (ctx->Extensions.ARB_depth_buffer_float) { + switch (internalFormat) { + case GL_DEPTH_COMPONENT32F: + ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT]); + return MESA_FORMAT_Z32_FLOAT; + case GL_DEPTH32F_STENCIL8: + ASSERT(ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_X24S8]); + return MESA_FORMAT_Z32_FLOAT_X24S8; + default: + ; /* fallthrough */ + } + } + if (ctx->Extensions.ATI_envmap_bumpmap) { switch (internalFormat) { case GL_DUDV_ATI: diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 565a3a2d8..0e84b8744 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -899,7 +899,7 @@ unbind_texobj_from_texunits(struct gl_context *ctx, { GLuint u, tex; - for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) { + for (u = 0; u < Elements(ctx->Texture.Unit); u++) { struct gl_texture_unit *unit = &ctx->Texture.Unit[u]; for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { if (texObj == unit->CurrentTex[tex]) { diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index e527981ff..6e1e63bdf 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -1002,15 +1002,17 @@ memcpy_texture(struct gl_context *ctx, /** - * Store a 32-bit integer depth component texture image. + * Store a 32-bit integer or float depth component texture image. */ static GLboolean _mesa_texstore_z32(TEXSTORE_PARAMS) { const GLuint depthScale = 0xffffffff; const GLuint texelBytes = _mesa_get_format_bytes(dstFormat); + const GLenum dstType = _mesa_get_format_datatype(dstFormat); (void) dims; - ASSERT(dstFormat == MESA_FORMAT_Z32); + ASSERT(dstFormat == MESA_FORMAT_Z32 || + dstFormat == MESA_FORMAT_Z32_FLOAT); ASSERT(texelBytes == sizeof(GLuint)); if (ctx->Pixel.DepthScale == 1.0f && @@ -1018,7 +1020,7 @@ _mesa_texstore_z32(TEXSTORE_PARAMS) !srcPacking->SwapBytes && baseInternalFormat == GL_DEPTH_COMPONENT && srcFormat == GL_DEPTH_COMPONENT && - srcType == GL_UNSIGNED_INT) { + srcType == dstType) { /* simple memcpy path */ memcpy_texture(ctx, dims, dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, @@ -1039,7 +1041,7 @@ _mesa_texstore_z32(TEXSTORE_PARAMS) const GLvoid *src = _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); _mesa_unpack_depth_span(ctx, srcWidth, - GL_UNSIGNED_INT, (GLuint *) dstRow, + dstType, dstRow, depthScale, srcType, src, srcPacking); dstRow += dstRowStride; } @@ -4285,6 +4287,72 @@ _mesa_texstore_r11_g11_b10f(TEXSTORE_PARAMS) } +static GLboolean +_mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS) +{ + ASSERT(dstFormat == MESA_FORMAT_Z32_FLOAT_X24S8); + ASSERT(srcFormat == GL_DEPTH_STENCIL || + srcFormat == GL_DEPTH_COMPONENT || + srcFormat == GL_STENCIL_INDEX); + ASSERT(srcFormat != GL_DEPTH_STENCIL || + srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + + if (srcFormat == GL_DEPTH_STENCIL && + ctx->Pixel.DepthScale == 1.0f && + ctx->Pixel.DepthBias == 0.0f && + !srcPacking->SwapBytes) { + /* simple path */ + memcpy_texture(ctx, dims, + dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, + dstRowStride, + dstImageOffsets, + srcWidth, srcHeight, srcDepth, srcFormat, srcType, + srcAddr, srcPacking); + } + else if (srcFormat == GL_DEPTH_COMPONENT || + srcFormat == GL_STENCIL_INDEX) { + GLint img, row; + const GLint srcRowStride + = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) + / sizeof(uint64_t); + + /* In case we only upload depth we need to preserve the stencil */ + for (img = 0; img < srcDepth; img++) { + uint64_t *dstRow = (uint64_t *) dstAddr + + dstImageOffsets[dstZoffset + img] + + dstYoffset * dstRowStride / sizeof(uint64_t) + + dstXoffset; + const uint64_t *src + = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr, + srcWidth, srcHeight, + srcFormat, srcType, + img, 0, 0); + for (row = 0; row < srcHeight; row++) { + /* The unpack functions with: + * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV + * only write their own dword, so the other dword (stencil + * or depth) is preserved. */ + if (srcFormat != GL_STENCIL_INDEX) + _mesa_unpack_depth_span(ctx, srcWidth, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ + dstRow, /* dst addr */ + 1.0f, srcType, src, srcPacking); + + if (srcFormat != GL_DEPTH_COMPONENT) + _mesa_unpack_stencil_span(ctx, srcWidth, + GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */ + dstRow, /* dst addr */ + srcType, src, srcPacking, + ctx->_ImageTransferState); + + src += srcRowStride; + dstRow += dstRowStride / sizeof(uint64_t); + } + } + } + return GL_TRUE; +} + /** * Table mapping MESA_FORMAT_* to _mesa_texstore_*() @@ -4419,6 +4487,9 @@ texstore_funcs[MESA_FORMAT_COUNT] = { MESA_FORMAT_RGB9_E5_FLOAT, _mesa_texstore_rgb9_e5 }, { MESA_FORMAT_R11_G11_B10_FLOAT, _mesa_texstore_r11_g11_b10f }, + + { MESA_FORMAT_Z32_FLOAT, _mesa_texstore_z32 }, + { MESA_FORMAT_Z32_FLOAT_X24S8, _mesa_texstore_z32f_x24s8 }, }; diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 1c4fd82ba..dd069a3a4 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -580,7 +580,7 @@ _mesa_update_shader_textures_used(struct gl_program *prog) if (prog->SamplersUsed & (1 << s)) { GLuint unit = prog->SamplerUnits[s]; GLuint tgt = prog->SamplerTargets[s]; - assert(unit < MAX_TEXTURE_IMAGE_UNITS); + assert(unit < Elements(prog->TexturesUsed)); assert(tgt < NUM_TEXTURE_TARGETS); prog->TexturesUsed[unit] |= (1 << tgt); } @@ -674,7 +674,7 @@ set_program_uniform(struct gl_context *ctx, struct gl_program *program, GLuint texUnit = ((GLuint *) values)[i]; /* check that the sampler (tex unit index) is legal */ - if (texUnit >= ctx->Const.MaxTextureImageUnits) { + if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) { _mesa_error(ctx, GL_INVALID_VALUE, "glUniform1(invalid sampler/tex unit index for '%s')", param->Name); diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c index 181fedd2b..117000ba7 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_clear.c +++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c @@ -381,7 +381,8 @@ check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuff assert(rb->Format == MESA_FORMAT_S8 || rb->Format == MESA_FORMAT_Z24_S8 || - rb->Format == MESA_FORMAT_S8_Z24); + rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); if (ctx->Scissor.Enabled && (ctx->Scissor.X != 0 || @@ -436,7 +437,8 @@ check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb assert(rb->Format == MESA_FORMAT_S8 || rb->Format == MESA_FORMAT_Z24_S8 || - rb->Format == MESA_FORMAT_S8_Z24); + rb->Format == MESA_FORMAT_S8_Z24 || + rb->Format == MESA_FORMAT_Z32_FLOAT_X24S8); if (maskStencil) return GL_TRUE; diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index d61d7ac22..dca332464 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -812,6 +812,7 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, for (row = 0; row < height; row++) { GLubyte sValues[MAX_WIDTH]; GLuint zValues[MAX_WIDTH]; + GLfloat *zValuesFloat = (GLfloat*)zValues; GLenum destType = GL_UNSIGNED_BYTE; const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, width, height, @@ -822,7 +823,11 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, ctx->_ImageTransferState); if (format == GL_DEPTH_STENCIL) { - _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, + GLenum ztype = + pt->resource->format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED ? + GL_FLOAT : GL_UNSIGNED_INT; + + _mesa_unpack_depth_span(ctx, spanWidth, ztype, zValues, (1 << 24) - 1, type, source, &clippedUnpack); } @@ -887,6 +892,26 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, } } break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + if (format == GL_DEPTH_STENCIL) { + uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); + GLfloat *destf = (GLfloat*)dest; + GLint k; + assert(usage == PIPE_TRANSFER_WRITE); + for (k = 0; k < spanWidth; k++) { + destf[k*2] = zValuesFloat[k]; + dest[k*2+1] = sValues[k] & 0xff; + } + } + else { + uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); + GLint k; + assert(usage == PIPE_TRANSFER_READ_WRITE); + for (k = 0; k < spanWidth; k++) { + dest[k*2+1] = sValues[k] & 0xff; + } + } + break; default: assert(0); } @@ -994,14 +1019,23 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, GL_NONE, GL_NONE, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW); - if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED) - stencil_format = PIPE_FORMAT_X24S8_USCALED; - else if (tex_format == PIPE_FORMAT_S8_USCALED_Z24_UNORM) - stencil_format = PIPE_FORMAT_S8X24_USCALED; - else - stencil_format = PIPE_FORMAT_S8_USCALED; - if (stencil_format == PIPE_FORMAT_NONE) - goto stencil_fallback; + + switch (tex_format) { + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + stencil_format = PIPE_FORMAT_X24S8_USCALED; + break; + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + stencil_format = PIPE_FORMAT_S8X24_USCALED; + break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + stencil_format = PIPE_FORMAT_X32_S8X24_USCALED; + break; + case PIPE_FORMAT_S8_USCALED: + stencil_format = PIPE_FORMAT_S8_USCALED; + break; + default: + goto stencil_fallback; + } } /* Mesa state should be up to date by now */ @@ -1188,6 +1222,18 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, assert(usage == PIPE_TRANSFER_WRITE); memcpy(dst, src, width); break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + { + uint *dst4 = (uint *) dst; + int j; + dst4++; + assert(usage == PIPE_TRANSFER_READ_WRITE); + for (j = 0; j < width; j++) { + *dst4 = src[j] & 0xff; + dst4 += 2; + } + } + break; default: assert(0); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index 67926e392..e2b29fe30 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -151,6 +151,24 @@ st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, } } break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + if (format == GL_DEPTH_STENCIL) { + const uint *src = (uint *) (stmap + srcY * pt->stride); + const GLfloat *srcf = (const GLfloat*)src; + GLint k; + for (k = 0; k < width; k++) { + zValues[k] = srcf[k*2]; + sValues[k] = src[k*2+1] & 0xff; + } + } + else { + const uint *src = (uint *) (stmap + srcY * pt->stride); + GLint k; + for (k = 0; k < width; k++) { + sValues[k] = src[k*2+1] & 0xff; + } + } + break; default: assert(0); } @@ -159,7 +177,7 @@ st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, dest = _mesa_image_address2d(packing, pixels, width, height, format, type, j, 0); if (format == GL_DEPTH_STENCIL) { - _mesa_pack_depth_stencil_span(ctx, width, dest, + _mesa_pack_depth_stencil_span(ctx, width, type, dest, zValues, sValues, packing); } else { @@ -568,6 +586,31 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h dst += dstStride; } } + else if (pformat == PIPE_FORMAT_Z32_FLOAT) { + for (i = 0; i < height; i++) { + GLfloat zfloat[MAX_WIDTH]; + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, zfloat, 0); + y += yStep; + _mesa_pack_depth_span(ctx, width, dst, type, + zfloat, &clippedPacking); + dst += dstStride; + } + } + else if (pformat == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED) { + assert(format == GL_DEPTH_COMPONENT); + for (i = 0; i < height; i++) { + GLfloat zfloat[MAX_WIDTH]; /* Z32 */ + GLfloat zfloat2[MAX_WIDTH*2]; /* Z32X32 */ + pipe_get_tile_raw(pipe, trans, 0, y, width, 1, zfloat2, 0); + y += yStep; + for (j = 0; j < width; j++) { + zfloat[j] = zfloat2[j*2]; + } + _mesa_pack_depth_span(ctx, width, dst, type, + zfloat, &clippedPacking); + dst += dstStride; + } + } else { /* RGBA format */ /* Do a row at a time to flip image data vertically */ diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index d3aebe526..99b231d97 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -607,4 +607,15 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_SM3)) { ctx->Extensions.ARB_shader_texture_lod = GL_TRUE; } + + if (screen->is_format_supported(screen, PIPE_FORMAT_Z32_FLOAT, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_SAMPLER_VIEW) && + screen->is_format_supported(screen, PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_SAMPLER_VIEW)) { + ctx->Extensions.ARB_depth_buffer_float = GL_TRUE; + } } diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c index fa5d8f505..bd4f0860c 100644 --- a/mesalib/src/mesa/state_tracker/st_format.c +++ b/mesalib/src/mesa/state_tracker/st_format.c @@ -68,42 +68,70 @@ GLenum st_format_datatype(enum pipe_format format) { const struct util_format_description *desc; + int i; desc = util_format_description(format); assert(desc); + /* Find the first non-VOID channel. */ + for (i = 0; i < 4; i++) { + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { + break; + } + } + if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) { if (format == PIPE_FORMAT_B5G5R5A1_UNORM || format == PIPE_FORMAT_B5G6R5_UNORM) { return GL_UNSIGNED_SHORT; } + else if (format == PIPE_FORMAT_R11G11B10_FLOAT || + format == PIPE_FORMAT_R9G9B9E5_FLOAT) { + return GL_FLOAT; + } else if (format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || format == PIPE_FORMAT_S8_USCALED_Z24_UNORM || format == PIPE_FORMAT_Z24X8_UNORM || format == PIPE_FORMAT_X8Z24_UNORM) { return GL_UNSIGNED_INT_24_8; } + else if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED) { + return GL_FLOAT_32_UNSIGNED_INT_24_8_REV; + } else { const GLuint size = format_max_bits(format); + + assert(i < 4); + if (i == 4) + return GL_NONE; + if (size == 8) { - if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) + if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) return GL_UNSIGNED_BYTE; else return GL_BYTE; } else if (size == 16) { - if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) + return GL_HALF_FLOAT; + if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) return GL_UNSIGNED_SHORT; else return GL_SHORT; } - else { - assert( size <= 32 ); - if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED) + else if (size <= 32) { + if (desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT) + return GL_FLOAT; + if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) return GL_UNSIGNED_INT; else return GL_INT; } + else { + assert(size == 64); + assert(desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT); + return GL_DOUBLE; + } } } else if (format == PIPE_FORMAT_UYVY) { @@ -180,6 +208,10 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) return PIPE_FORMAT_Z24X8_UNORM; case MESA_FORMAT_S8: return PIPE_FORMAT_S8_USCALED; + case MESA_FORMAT_Z32_FLOAT: + return PIPE_FORMAT_Z32_FLOAT; + case MESA_FORMAT_Z32_FLOAT_X24S8: + return PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED; case MESA_FORMAT_YCBCR: return PIPE_FORMAT_UYVY; #if FEATURE_texture_s3tc @@ -402,6 +434,10 @@ st_pipe_format_to_mesa_format(enum pipe_format format) return MESA_FORMAT_X8_Z24; case PIPE_FORMAT_Z24_UNORM_S8_USCALED: return MESA_FORMAT_S8_Z24; + case PIPE_FORMAT_Z32_FLOAT: + return MESA_FORMAT_Z32_FLOAT; + case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED: + return MESA_FORMAT_Z32_FLOAT_X24S8; case PIPE_FORMAT_UYVY: return MESA_FORMAT_YCBCR; @@ -759,6 +795,10 @@ static const struct format_mapping format_map[] = { { GL_DEPTH_COMPONENT, 0 }, { DEFAULT_DEPTH_FORMATS } }, + { + { GL_DEPTH_COMPONENT32F, 0 }, + { PIPE_FORMAT_Z32_FLOAT, 0 } + }, /* stencil formats */ { @@ -775,6 +815,10 @@ static const struct format_mapping format_map[] = { { GL_DEPTH_STENCIL_EXT, GL_DEPTH24_STENCIL8_EXT, 0 }, { PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, 0 } }, + { + { GL_DEPTH32F_STENCIL8, 0 }, + { PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED, 0 } + }, /* sRGB formats */ { diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index a8c4b5c3f..7bd82aae2 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -918,6 +918,15 @@ st_manager_add_color_renderbuffer(struct st_context *st, return FALSE; st_framebuffer_update_attachments(stfb); + + /* + * Force a call to the state tracker manager to validate the + * new renderbuffer. It might be that there is a window system + * renderbuffer available. + */ + if(stfb->iface) + stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; + st_invalidate_state(st->ctx, _NEW_BUFFERS); return TRUE; diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 3516a41bf..7f53f19eb 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -568,9 +568,6 @@ _swrast_BlitFramebuffer(struct gl_context *ctx, }; GLint i; - if (!ctx->DrawBuffer->_NumColorDrawBuffers) - return; - if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, &dstX0, &dstY0, &dstX1, &dstY1)) { return; diff --git a/mesalib/src/mesa/swrast/s_readpix.c b/mesalib/src/mesa/swrast/s_readpix.c index 214f2ea1a..66ca39293 100644 --- a/mesalib/src/mesa/swrast/s_readpix.c +++ b/mesalib/src/mesa/swrast/s_readpix.c @@ -446,7 +446,7 @@ read_depth_stencil_pixels(struct gl_context *ctx, GLfloat depthVals[MAX_WIDTH]; _swrast_read_depth_span_float(ctx, depthRb, width, x, y + i, depthVals); - _mesa_pack_depth_stencil_span(ctx, width, depthStencilDst, + _mesa_pack_depth_stencil_span(ctx, width, type, depthStencilDst, depthVals, stencilVals, packing); } } -- cgit v1.2.3