/************************************************************************** * * Copyright 2014 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 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 "glstate_internal.hpp" #include #include #include #include #include "glsize.hpp" #include "glstate.hpp" namespace glstate { /** * Sames as enumToString, but with special provision to handle luminance/alpha * formats. * * OpenGL 2.1 specification states that "internalFormat may (for backwards * compatibility with the 1.0 version of the GL) also take on the integer * values 1, 2, 3, and 4, which are equivalent to symbolic constants LUMINANCE, * LUMINANCE ALPHA, RGB, and RGBA respectively". */ const char * formatToString(GLenum internalFormat) { switch (internalFormat) { case 1: return "GL_LUMINANCE"; case 2: return "GL_LUMINANCE_ALPHA"; case 3: return "GL_RGB"; case 4: return "GL_RGBA"; default: return enumToString(internalFormat); } } static const InternalFormatDesc internalFormatDescs[] = { // GLenum internalFormat, GLenum format, GLenum type, GLenum readType // Unsized UNORM { 1, GL_RED, GL_NONE, GL_UNSIGNED_BYTE }, { 2, GL_RG, GL_NONE, GL_UNSIGNED_BYTE }, { 3, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { 4, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RED, GL_RED, GL_NONE, GL_UNSIGNED_BYTE }, { GL_GREEN, GL_GREEN, GL_NONE, GL_UNSIGNED_BYTE }, { GL_BLUE, GL_BLUE, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RG, GL_RG, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGB, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_BGR, GL_BGR, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGBA, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_BGRA, GL_BGRA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE }, { GL_ALPHA, GL_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_INTENSITY, GL_INTENSITY, GL_NONE, GL_UNSIGNED_BYTE }, // Unsized SNORM { GL_RED_SNORM, GL_RED, GL_NONE, GL_FLOAT }, { GL_RG_SNORM, GL_RG, GL_NONE, GL_FLOAT }, { GL_RGB_SNORM, GL_RGB, GL_NONE, GL_FLOAT }, { GL_RGBA_SNORM, GL_RGBA, GL_NONE, GL_FLOAT }, { GL_LUMINANCE_SNORM, GL_LUMINANCE, GL_NONE, GL_FLOAT }, { GL_ALPHA_SNORM, GL_ALPHA, GL_NONE, GL_FLOAT }, { GL_LUMINANCE_ALPHA_SNORM, GL_LUMINANCE_ALPHA, GL_NONE, GL_FLOAT }, { GL_INTENSITY_SNORM, GL_INTENSITY, GL_NONE, GL_FLOAT }, // 4-bit UNORM { GL_RGB4, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGBA4, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE4, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE }, { GL_ALPHA4, GL_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_INTENSITY4, GL_INTENSITY, GL_NONE, GL_UNSIGNED_BYTE }, // 8-bit UNORM { GL_R8, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_RG8, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_BGRA8_EXT, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_BYTE }, { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_INTENSITY8, GL_INTENSITY, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, // 8-bit SNORM { GL_R8_SNORM, GL_RED, GL_BYTE, GL_FLOAT }, { GL_RG8_SNORM, GL_RG, GL_BYTE, GL_FLOAT }, { GL_RGB8_SNORM, GL_RGB, GL_BYTE, GL_FLOAT }, { GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, GL_FLOAT }, { GL_LUMINANCE8_SNORM, GL_LUMINANCE, GL_BYTE, GL_FLOAT }, { GL_ALPHA8_SNORM, GL_ALPHA, GL_BYTE, GL_FLOAT }, { GL_LUMINANCE8_ALPHA8_SNORM, GL_LUMINANCE_ALPHA, GL_BYTE, GL_FLOAT }, { GL_INTENSITY8_SNORM, GL_INTENSITY, GL_BYTE, GL_FLOAT }, // Other UNORM { GL_R3_G3_B2, GL_RGB, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_BYTE }, { GL_RGB4, GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_BYTE }, { GL_RGB5, GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_BYTE }, { GL_RGB10, GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE }, { GL_RGB12, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGBA2, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_BYTE }, { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_BYTE }, { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE }, { GL_RGBA12, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, // 16-bit UNORM { GL_R16, GL_RED, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_RG16, GL_RG, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_LUMINANCE16, GL_LUMINANCE, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_ALPHA16, GL_ALPHA, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_INTENSITY16, GL_INTENSITY, GL_UNSIGNED_SHORT, GL_FLOAT }, // 16-bit SNORM { GL_R16_SNORM, GL_RED, GL_SHORT, GL_FLOAT }, { GL_RG16_SNORM, GL_RG, GL_SHORT, GL_FLOAT }, { GL_RGB16_SNORM, GL_RGB, GL_SHORT, GL_FLOAT }, { GL_RGBA16_SNORM, GL_RGBA, GL_SHORT, GL_FLOAT }, { GL_LUMINANCE16_SNORM, GL_LUMINANCE, GL_SHORT, GL_FLOAT }, { GL_ALPHA16_SNORM, GL_ALPHA, GL_SHORT, GL_FLOAT }, { GL_LUMINANCE16_ALPHA16_SNORM, GL_LUMINANCE_ALPHA, GL_SHORT, GL_FLOAT }, { GL_INTENSITY16_SNORM, GL_INTENSITY, GL_SHORT, GL_FLOAT }, // 16-bit float { GL_R16F, GL_RED, GL_HALF_FLOAT, GL_FLOAT }, { GL_RG16F, GL_RG, GL_HALF_FLOAT, GL_FLOAT }, { GL_RGB16F, GL_RGB, GL_HALF_FLOAT, GL_FLOAT }, { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT }, { GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT }, { GL_ALPHA16F_ARB, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT }, { GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT }, { GL_INTENSITY16F_ARB, GL_INTENSITY, GL_HALF_FLOAT, GL_FLOAT }, // 32-bit float { GL_R32F, GL_RED, GL_FLOAT, GL_FLOAT }, { GL_RG32F, GL_RG, GL_FLOAT, GL_FLOAT }, { GL_RGB32F, GL_RGB, GL_FLOAT, GL_FLOAT }, { GL_RGBA32F, GL_RGBA, GL_FLOAT, GL_FLOAT }, { GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, GL_FLOAT }, { GL_ALPHA32F_ARB, GL_ALPHA, GL_FLOAT, GL_FLOAT }, { GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT }, { GL_INTENSITY32F_ARB, GL_INTENSITY, GL_FLOAT, GL_FLOAT }, // Other float { GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT }, { GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT }, // Unsized integer // FIXME: currently we can only dump integers as GL_UNSIGNED_BYTE { GL_RED_INTEGER, GL_RED_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_GREEN_INTEGER, GL_GREEN_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_BLUE_INTEGER, GL_BLUE_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_ALPHA_INTEGER, GL_ALPHA_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RG_INTEGER, GL_RG_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGB_INTEGER, GL_RGB_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_BGR_INTEGER, GL_BGR_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_RGBA_INTEGER, GL_RGBA_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_BGRA_INTEGER, GL_BGRA_INTEGER, GL_NONE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_INTEGER_EXT, GL_LUMINANCE_INTEGER_EXT, GL_NONE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_NONE, GL_UNSIGNED_BYTE }, // 8-bit unsigned integer { GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE8UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_ALPHA8UI_EXT, GL_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_INTENSITY8UI_EXT, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, // 8-bit signed integer { GL_R8I, GL_RED_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_RG8I, GL_RG_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_RGB8I, GL_RGB_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE8I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_ALPHA8I_EXT, GL_ALPHA_INTEGER_EXT, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA8I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_BYTE, GL_UNSIGNED_BYTE }, { GL_INTENSITY8I_EXT, GL_RED_INTEGER, GL_BYTE, GL_UNSIGNED_BYTE }, // 10-bit unsigned integer { GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_BYTE }, // 16-bit unsigned integer { GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE16UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_ALPHA16UI_EXT, GL_ALPHA_INTEGER_EXT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA16UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, { GL_INTENSITY16UI_EXT, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, // 16-bit signed integer { GL_R16I, GL_RED_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_RG16I, GL_RG_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_RGB16I, GL_RGB_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE16I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_ALPHA16I_EXT, GL_ALPHA_INTEGER_EXT, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA16I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_SHORT, GL_UNSIGNED_BYTE }, { GL_INTENSITY16I_EXT, GL_RED_INTEGER, GL_SHORT, GL_UNSIGNED_BYTE }, // 32-bit unsigned integer { GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE32UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_ALPHA32UI_EXT, GL_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA32UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, { GL_INTENSITY32UI_EXT, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_BYTE }, // 32-bit signed integer { GL_R32I, GL_RED_INTEGER, GL_INT, GL_UNSIGNED_BYTE }, { GL_RG32I, GL_RG_INTEGER, GL_INT, GL_UNSIGNED_BYTE }, { GL_RGB32I, GL_RGB_INTEGER, GL_INT, GL_UNSIGNED_BYTE }, { GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE32I_EXT, GL_LUMINANCE_INTEGER_EXT, GL_INT, GL_UNSIGNED_BYTE }, { GL_ALPHA32I_EXT, GL_ALPHA_INTEGER_EXT, GL_INT, GL_UNSIGNED_BYTE }, { GL_LUMINANCE_ALPHA32I_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_INT, GL_UNSIGNED_BYTE }, { GL_INTENSITY32I_EXT, GL_RED_INTEGER, GL_INT, GL_UNSIGNED_BYTE }, // Compressed { GL_COMPRESSED_RED, GL_RED, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RED_RGTC1, GL_RED, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_R11_EAC, GL_RED, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RG, GL_RG, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RG_RGTC2, GL_RG, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RG11_EAC, GL_RG, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGB, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGB8_ETC2, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGBA, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_LUMINANCE, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, // Compressed signed { GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_NONE, GL_FLOAT }, { GL_COMPRESSED_SIGNED_R11_EAC, GL_RED, GL_NONE, GL_FLOAT }, { GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_NONE, GL_FLOAT }, { GL_COMPRESSED_SIGNED_RG11_EAC, GL_RG, GL_NONE, GL_FLOAT }, { GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT, GL_LUMINANCE, GL_NONE, GL_FLOAT }, { GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT, GL_LUMINANCE_ALPHA, GL_NONE, GL_FLOAT }, // SRGB { GL_SRGB, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SRGB_ALPHA, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SLUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SLUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_SLUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SRGB, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SRGB_ALPHA, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SLUMINANCE, GL_LUMINANCE, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SLUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_NONE, GL_UNSIGNED_BYTE }, // depth-stencil { GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_NONE, GL_FLOAT }, { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_FLOAT }, { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_NONE, GL_FLOAT }, { GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_FLOAT }, { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT }, { GL_DEPTH_COMPONENT32F_NV, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT }, { GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_NONE, GL_FLOAT }, { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_EXT, GL_FLOAT }, { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT }, { GL_DEPTH32F_STENCIL8_NV, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT }, { GL_STENCIL_INDEX, GL_STENCIL_INDEX, GL_NONE, GL_UNSIGNED_BYTE }, { GL_STENCIL_INDEX1, GL_STENCIL_INDEX, GL_NONE, GL_UNSIGNED_BYTE }, { GL_STENCIL_INDEX4, GL_STENCIL_INDEX, GL_NONE, GL_UNSIGNED_BYTE }, { GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }, { GL_STENCIL_INDEX16, GL_STENCIL_INDEX, GL_UNSIGNED_SHORT, GL_UNSIGNED_BYTE }, }; static const InternalFormatDesc defaultInternalFormatDesc = { GL_RGBA, GL_RGBA, GL_NONE, GL_FLOAT }; const InternalFormatDesc & getInternalFormatDesc(GLenum internalFormat) { for (auto & internalFormatDesc : internalFormatDescs) { if (internalFormatDesc.internalFormat == internalFormat) { return internalFormatDesc; } } std::cerr << "warning: unexpected internalFormat " << enumToString(internalFormat) << "\n"; return defaultInternalFormatDesc; } /** * Choose appropriate format/type for glReadPixels()/glGetTexImage() */ void chooseReadBackFormat(const InternalFormatDesc &formatDesc, GLenum &format, GLenum &type) { /* TODO: leverage glGetInternalformat where available */ type = formatDesc.readType; assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT); switch (formatDesc.format) { case GL_RED: case GL_GREEN: case GL_BLUE: case GL_RG: case GL_RGB: case GL_BGR: format = GL_RGB; break; case GL_ALPHA: case GL_RGBA: case GL_BGRA: case GL_INTENSITY: format = GL_RGBA; break; case GL_LUMINANCE: format = GL_LUMINANCE; break; case GL_LUMINANCE_ALPHA: format = GL_LUMINANCE_ALPHA; break; case GL_RED_INTEGER: case GL_GREEN_INTEGER: case GL_BLUE_INTEGER: case GL_RG_INTEGER: case GL_RGB_INTEGER: case GL_BGR_INTEGER: case GL_ALPHA_INTEGER: case GL_RGBA_INTEGER: case GL_BGRA_INTEGER: format = GL_RGBA_INTEGER; break; case GL_LUMINANCE_INTEGER_EXT: format = GL_LUMINANCE_INTEGER_EXT; break; case GL_LUMINANCE_ALPHA_INTEGER_EXT: format = GL_LUMINANCE_ALPHA_INTEGER_EXT; break; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: /* TODO: allow pick stencil component too*/ format = GL_DEPTH_COMPONENT; type = GL_FLOAT; break; case GL_STENCIL_INDEX: format = GL_STENCIL_INDEX; type = GL_UNSIGNED_BYTE; break; default: assert(0); format = GL_RGBA; type = GL_FLOAT; break; } } void getImageFormat(GLenum format, GLenum type, GLuint & channels, image::ChannelType & channelType) { channels = _gl_format_channels(format); switch (type) { case GL_UNSIGNED_BYTE: channelType = image::TYPE_UNORM8; break; case GL_FLOAT: channelType = image::TYPE_FLOAT; break; default: assert(0); } } // Macros for describing arbitrary swizzles #define SWIZZLE_X 0 #define SWIZZLE_Y 1 #define SWIZZLE_Z 2 #define SWIZZLE_W 3 #define SWIZZLE_0 4 #define SWIZZLE_1 5 #define SWIZZLE_COUNT 6 #define SWIZZLE_BITS 4 #define SWIZZLE_MASK ((1 << SWIZZLE_BITS) - 1) #define SWIZZLE(x, y, z, w) \ (((SWIZZLE_##x) << (SWIZZLE_BITS*0)) | \ ((SWIZZLE_##y) << (SWIZZLE_BITS*1)) | \ ((SWIZZLE_##z) << (SWIZZLE_BITS*2)) | \ ((SWIZZLE_##w) << (SWIZZLE_BITS*3))) #define SWIZZLE_RGBA SWIZZLE(X,Y,Z,W) #define SWIZZLE_RGB SWIZZLE(X,Y,Z,1) #define SWIZZLE_RG SWIZZLE(X,Y,0,1) #define SWIZZLE_R SWIZZLE(X,0,0,1) #define SWIZZLE_LA SWIZZLE(X,X,X,Y) #define SWIZZLE_L SWIZZLE(X,X,X,1) #define SWIZZLE_A SWIZZLE(0,0,0,X) #define SWIZZLE_I SWIZZLE(X,X,X,X) #define SWIZZLE_EXTRACT(swizzle, channel) \ ((swizzle) >> (SWIZZLE_BITS * (channel)) & SWIZZLE_MASK) // Template that can describe all regular array-based pixel formats template< typename Type, unsigned components, bool normalized, uint16_t swizzle > class PixelTemplate : public PixelFormat { protected: static_assert( 1 <= components && components <= 4, "invalid number of components" ); static const unsigned swizzle_r = SWIZZLE_EXTRACT(swizzle, 0); static const unsigned swizzle_g = SWIZZLE_EXTRACT(swizzle, 1); static const unsigned swizzle_b = SWIZZLE_EXTRACT(swizzle, 2); static const unsigned swizzle_a = SWIZZLE_EXTRACT(swizzle, 3); static_assert( swizzle_r < components || swizzle_r == SWIZZLE_0 || swizzle_r == SWIZZLE_1, "invalid R swizzle" ); static_assert( swizzle_g < components || swizzle_g == SWIZZLE_0 || swizzle_g == SWIZZLE_1, "invalid G swizzle" ); static_assert( swizzle_b < components || swizzle_b == SWIZZLE_0 || swizzle_b == SWIZZLE_1, "invalid B swizzle" ); static_assert( swizzle_a < components || swizzle_a == SWIZZLE_0 || swizzle_a == SWIZZLE_1, "invalid A swizzle" ); // We must use double precision intermediate values when normalizing 32bits integers. typedef typename std::conditional< normalized && sizeof(Type) >= 4 , double , float >::type Scale; // Scale normalized types template static inline Scale scale(Scale value, typename std::enable_if::type* = 0) { static_assert( normalized, "should only be instantiated for normalized types" ); static constexpr Type typeMax = std::numeric_limits::max(); static_assert( static_cast(static_cast(typeMax)) == typeMax, "intermediate type cannot represent maximum value without loss of precission" ); static constexpr Scale scaleFactor = Scale(1) / Scale(typeMax); static_assert( Scale(typeMax) * scaleFactor == Scale(1), "cannot represent unity" ); static_assert( Scale(0) * scaleFactor == Scale(0), "cannot represent zero" ); return value * scaleFactor; } // No-op for unormalized types template static inline Scale scale(Scale value, typename std::enable_if::type* = 0) { static_assert( !normalized, "should only be instantiated for non-normalized types" ); return value; } // Unpack a single pixel static inline void unpackPixel(const Type *inPixel, float outPixel[4]) { float scaledComponents[SWIZZLE_COUNT]; for (unsigned component = 0; component < components; ++component) { Scale scaledComponent = scale(static_cast(inPixel[component])); scaledComponents[component] = static_cast(scaledComponent); } scaledComponents[SWIZZLE_0] = 0.0f; scaledComponents[SWIZZLE_1] = 1.0f; outPixel[0] = scaledComponents[swizzle_r]; outPixel[1] = scaledComponents[swizzle_g]; outPixel[2] = scaledComponents[swizzle_b]; outPixel[3] = scaledComponents[swizzle_a]; } public: inline PixelTemplate(void) { } size_t size(void) const override { return sizeof(Type) * components; } void unpackSpan(const uint8_t *inSpan, float *outSpan, unsigned width) const override { const Type *inPixel = reinterpret_cast(inSpan); for (unsigned x = 0; x < width; ++x) { unpackPixel(inPixel, outSpan); inPixel += components; outSpan += 4; } } }; const PixelFormat * getPixelFormat(GLenum internalFormat) { static const bool Y = true; static const bool N = false; #define CASE(internalFormat, type, components, norm, swizzle) \ case GL_##internalFormat: \ { \ static const PixelTemplate< GL##type, components, norm, SWIZZLE_##swizzle > pixel; \ return &pixel; \ } switch (internalFormat) { CASE(ALPHA8, ubyte, 1, Y, A); CASE(ALPHA16, ushort, 1, Y, A); CASE(ALPHA16F_ARB, half, 1, N, A); CASE(ALPHA32F_ARB, float, 1, N, A); CASE(ALPHA8I_EXT, byte, 1, N, A); CASE(ALPHA16I_EXT, short, 1, N, A); CASE(ALPHA32I_EXT, int, 1, N, A); CASE(ALPHA8UI_EXT, ubyte, 1, N, A); CASE(ALPHA16UI_EXT, ushort, 1, N, A); CASE(ALPHA32UI_EXT, uint, 1, N, A); CASE(LUMINANCE8, ubyte, 1, Y, L); CASE(LUMINANCE16, ushort, 1, Y, L); CASE(LUMINANCE16F_ARB, half, 1, N, L); CASE(LUMINANCE32F_ARB, float, 1, N, L); CASE(LUMINANCE8I_EXT, byte, 1, N, L); CASE(LUMINANCE16I_EXT, short, 1, N, L); CASE(LUMINANCE32I_EXT, int, 1, N, L); CASE(LUMINANCE8UI_EXT, ubyte, 1, N, L); CASE(LUMINANCE16UI_EXT, ushort, 1, N, L); CASE(LUMINANCE32UI_EXT, uint, 1, N, L); CASE(LUMINANCE8_ALPHA8, ubyte, 2, Y, LA); CASE(LUMINANCE16_ALPHA16, ushort, 2, Y, LA); CASE(LUMINANCE_ALPHA16F_ARB, half, 2, N, LA); CASE(LUMINANCE_ALPHA32F_ARB, float, 2, N, LA); CASE(LUMINANCE_ALPHA8I_EXT, byte, 2, N, LA); CASE(LUMINANCE_ALPHA16I_EXT, short, 2, N, LA); CASE(LUMINANCE_ALPHA32I_EXT, int, 2, N, LA); CASE(LUMINANCE_ALPHA8UI_EXT, ubyte, 2, N, LA); CASE(LUMINANCE_ALPHA16UI_EXT, ushort, 2, N, LA); CASE(LUMINANCE_ALPHA32UI_EXT, uint, 2, N, LA); CASE(INTENSITY8, ubyte, 1, Y, I); CASE(INTENSITY16, ushort, 1, Y, I); CASE(INTENSITY16F_ARB, half, 1, N, I); CASE(INTENSITY32F_ARB, float, 1, N, I); CASE(INTENSITY8I_EXT, byte, 1, N, I); CASE(INTENSITY16I_EXT, short, 1, N, I); CASE(INTENSITY32I_EXT, int, 1, N, I); CASE(INTENSITY8UI_EXT, ubyte, 1, N, I); CASE(INTENSITY16UI_EXT, ushort, 1, N, I); CASE(INTENSITY32UI_EXT, uint, 1, N, I); CASE(RGBA8, ubyte, 4, Y, RGBA); CASE(RGBA16, ushort, 4, Y, RGBA); CASE(RGBA16F, half, 4, N, RGBA); CASE(RGBA32F, float, 4, N, RGBA); CASE(RGBA8I, byte, 4, N, RGBA); CASE(RGBA16I, short, 4, N, RGBA); CASE(RGBA32I, int, 4, N, RGBA); CASE(RGBA8UI, ubyte, 4, N, RGBA); CASE(RGBA16UI, ushort, 4, N, RGBA); CASE(RGBA32UI, uint, 4, N, RGBA); CASE(RGB8, ubyte, 3, Y, RGB); CASE(RGB16, ushort, 3, Y, RGB); CASE(RGB16F, half, 3, N, RGB); CASE(RGB32F, float, 3, N, RGB); CASE(RGB8I, byte, 3, N, RGB); CASE(RGB16I, short, 3, N, RGB); CASE(RGB32I, int, 3, N, RGB); CASE(RGB8UI, ubyte, 3, N, RGB); CASE(RGB16UI, ushort, 3, N, RGB); CASE(RGB32UI, uint, 3, N, RGB); CASE(RG8, ubyte, 2, Y, RG); CASE(RG16, ushort, 2, Y, RG); CASE(RG16F, half, 2, N, RG); CASE(RG32F, float, 2, N, RG); CASE(RG8I, byte, 2, N, RG); CASE(RG16I, short, 2, N, RG); CASE(RG32I, int, 2, N, RG); CASE(RG8UI, ubyte, 2, N, RG); CASE(RG16UI, ushort, 2, N, RG); CASE(RG32UI, uint, 2, N, RG); CASE(R8, ubyte, 1, Y, R); CASE(R16, ushort, 1, Y, R); CASE(R16F, half, 1, N, R); CASE(R32F, float, 1, N, R); CASE(R8I, byte, 1, N, R); CASE(R16I, short, 1, N, R); CASE(R32I, int, 1, N, R); CASE(R8UI, ubyte, 1, N, R); CASE(R16UI, ushort, 1, N, R); CASE(R32UI, uint, 1, N, R); default: return nullptr; } #undef CASE } } /* namespace glstate */