Edit

kc3-lang/angle/src/libGLESv2/utilities.cpp

Branch :

  • Show log

    Commit

  • Author : shannon.woods%transgaming.com@gtempaccount.com
    Date : 2013-04-13 03:45:17
    Hash : 875994b3
    Message : Implemented 3D texture entry points. TRAC #22705 Signed-off-by: Jamie Madill Signed-off-by: Shannon Woods Author: Geoff Lang git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2172 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/libGLESv2/utilities.cpp
  • #include "precompiled.h"
    //
    // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // utilities.cpp: Conversion functions and other utility routines.
    
    #include "libGLESv2/utilities.h"
    #include "libGLESv2/mathutil.h"
    
    namespace gl
    {
    
    int UniformComponentCount(GLenum type)
    {
        switch (type)
        {
          case GL_BOOL:
          case GL_FLOAT:
          case GL_INT:
          case GL_SAMPLER_2D:
          case GL_SAMPLER_CUBE:
          case GL_UNSIGNED_INT:
              return 1;
          case GL_BOOL_VEC2:
          case GL_FLOAT_VEC2:
          case GL_INT_VEC2:
          case GL_UNSIGNED_INT_VEC2:
              return 2;
          case GL_INT_VEC3:
          case GL_FLOAT_VEC3:
          case GL_BOOL_VEC3:
          case GL_UNSIGNED_INT_VEC3:
              return 3;
          case GL_BOOL_VEC4:
          case GL_FLOAT_VEC4:
          case GL_INT_VEC4:
          case GL_UNSIGNED_INT_VEC4:
          case GL_FLOAT_MAT2:
              return 4;
          case GL_FLOAT_MAT2x3:
          case GL_FLOAT_MAT3x2:
              return 6;
          case GL_FLOAT_MAT2x4:
          case GL_FLOAT_MAT4x2:
              return 8;
          case GL_FLOAT_MAT3:
              return 9;
          case GL_FLOAT_MAT3x4:
          case GL_FLOAT_MAT4x3:
              return 12;
          case GL_FLOAT_MAT4:
              return 16;
          default:
              UNREACHABLE();
        }
    
        return 0;
    }
    
    GLenum UniformComponentType(GLenum type)
    {
        switch(type)
        {
          case GL_BOOL:
          case GL_BOOL_VEC2:
          case GL_BOOL_VEC3:
          case GL_BOOL_VEC4:
              return GL_BOOL;
          case GL_FLOAT:
          case GL_FLOAT_VEC2:
          case GL_FLOAT_VEC3:
          case GL_FLOAT_VEC4:
          case GL_FLOAT_MAT2:
          case GL_FLOAT_MAT3:
          case GL_FLOAT_MAT4:
          case GL_FLOAT_MAT2x3:
          case GL_FLOAT_MAT3x2:
          case GL_FLOAT_MAT2x4:
          case GL_FLOAT_MAT4x2:
          case GL_FLOAT_MAT3x4:
          case GL_FLOAT_MAT4x3:
              return GL_FLOAT;
          case GL_INT:
          case GL_SAMPLER_2D:
          case GL_SAMPLER_CUBE:
          case GL_INT_VEC2:
          case GL_INT_VEC3:
          case GL_INT_VEC4:
              return GL_INT;
          case GL_UNSIGNED_INT:
          case GL_UNSIGNED_INT_VEC2:
          case GL_UNSIGNED_INT_VEC3:
          case GL_UNSIGNED_INT_VEC4:
              return GL_UNSIGNED_INT;
          default:
              UNREACHABLE();
        }
    
        return GL_NONE;
    }
    
    size_t UniformComponentSize(GLenum type)
    {
        switch(type)
        {
          case GL_BOOL:         return sizeof(GLint);
          case GL_FLOAT:        return sizeof(GLfloat);
          case GL_INT:          return sizeof(GLint);
          case GL_UNSIGNED_INT: return sizeof(GLuint);
          default:       UNREACHABLE();
        }
    
        return 0;
    }
    
    size_t UniformInternalSize(GLenum type)
    {
        // Expanded to 4-element vectors
        return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4;
    }
    
    size_t UniformExternalSize(GLenum type)
    {
        return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type);
    }
    
    GLenum UniformBoolVectorType(GLenum type)
    {
        switch (type)
        {
          case GL_FLOAT:
          case GL_INT:
          case GL_UNSIGNED_INT:
            return GL_BOOL;
          case GL_FLOAT_VEC2:
          case GL_INT_VEC2:
          case GL_UNSIGNED_INT_VEC2:
            return GL_BOOL_VEC2;
          case GL_FLOAT_VEC3:
          case GL_INT_VEC3:
          case GL_UNSIGNED_INT_VEC3:
            return GL_BOOL_VEC3;
          case GL_FLOAT_VEC4:
          case GL_INT_VEC4:
          case GL_UNSIGNED_INT_VEC4:
            return GL_BOOL_VEC4;
    
          default:
            UNREACHABLE();
            return GL_NONE;
        }
    }
    
    int VariableRowCount(GLenum type)
    {
        switch (type)
        {
          case GL_NONE:
            return 0;
          case GL_BOOL:
          case GL_FLOAT:
          case GL_INT:
          case GL_BOOL_VEC2:
          case GL_FLOAT_VEC2:
          case GL_INT_VEC2:
          case GL_INT_VEC3:
          case GL_FLOAT_VEC3:
          case GL_BOOL_VEC3:
          case GL_BOOL_VEC4:
          case GL_FLOAT_VEC4:
          case GL_INT_VEC4:
          case GL_SAMPLER_2D:
          case GL_SAMPLER_CUBE:
            return 1;
          case GL_FLOAT_MAT2:
          case GL_FLOAT_MAT3x2:
          case GL_FLOAT_MAT4x2:
            return 2;
          case GL_FLOAT_MAT3:
          case GL_FLOAT_MAT2x3:
          case GL_FLOAT_MAT4x3:
            return 3;
          case GL_FLOAT_MAT4:
          case GL_FLOAT_MAT2x4:
          case GL_FLOAT_MAT3x4:
            return 4;
          default:
            UNREACHABLE();
        }
    
        return 0;
    }
    
    int VariableColumnCount(GLenum type)
    {
        switch (type)
        {
          case GL_NONE:
            return 0;
          case GL_BOOL:
          case GL_FLOAT:
          case GL_INT:
          case GL_SAMPLER_2D:
          case GL_SAMPLER_CUBE:
            return 1;
          case GL_BOOL_VEC2:
          case GL_FLOAT_VEC2:
          case GL_INT_VEC2:
          case GL_FLOAT_MAT2:
          case GL_FLOAT_MAT2x3:
          case GL_FLOAT_MAT2x4:
            return 2;
          case GL_INT_VEC3:
          case GL_FLOAT_VEC3:
          case GL_BOOL_VEC3:
          case GL_FLOAT_MAT3:
          case GL_FLOAT_MAT3x2:
          case GL_FLOAT_MAT3x4:
            return 3;
          case GL_BOOL_VEC4:
          case GL_FLOAT_VEC4:
          case GL_INT_VEC4:
          case GL_FLOAT_MAT4:
          case GL_FLOAT_MAT4x2:
          case GL_FLOAT_MAT4x3:
            return 4;
          default:
            UNREACHABLE();
        }
    
        return 0;
    }
    
    bool IsMatrixType(GLenum type)
    {
        return VariableRowCount(type) > 1;
    }
    
    int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
    {
        ASSERT(allocationSize <= bitsSize);
    
        unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
    
        for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
        {
            if ((*bits & mask) == 0)
            {
                *bits |= mask;
                return i;
            }
    
            mask <<= 1;
        }
    
        return -1;
    }
    
    GLsizei ComputeRowPitch(GLsizei width, GLint internalformat, GLint alignment)
    {
        ASSERT(alignment > 0 && isPow2(alignment));
    
        GLsizei rawPitch = ComputePixelSize(internalformat) * width;
        return (rawPitch + alignment - 1) & ~(alignment - 1);
    }
    
    GLsizei ComputeDepthPitch(GLsizei width, GLsizei height, GLint internalformat, GLint alignment)
    {
        return ComputeRowPitch(width, internalformat, alignment) * height;
    }
    
    GLsizei ComputeCompressedRowPitch(GLsizei width, GLenum internalformat)
    {
        return ComputeCompressedSize(width, 1, internalformat);
    }
    
    GLsizei ComputeCompressedDepthPitch(GLsizei width, GLsizei height, GLenum internalformat)
    {
        return ComputeCompressedSize(width, height, internalformat);
    }
    
    GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat)
    {
        switch (internalformat)
        {
          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
            return 8 * ((width + 3) / 4) * ((height + 3) / 4);
          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
            return 16 * ((width + 3) / 4) * ((height + 3) / 4);
          default:
            return 0;
        }
    }
    
    bool IsCompressed(GLenum format)
    {
        if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
           format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
           format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE ||
           format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    bool IsDepthTexture(GLenum format)
    {
        if (format == GL_DEPTH_COMPONENT ||
            format == GL_DEPTH_STENCIL_OES ||
            format == GL_DEPTH_COMPONENT16 ||
            format == GL_DEPTH_COMPONENT32_OES ||
            format == GL_DEPTH24_STENCIL8_OES)
        {
            return true;
        }
    
        return false;
    }
    
    bool IsStencilTexture(GLenum format)
    {
        if (format == GL_DEPTH_STENCIL_OES ||
            format == GL_DEPTH24_STENCIL8_OES)
        {
            return true;
        }
    
        return false;
    }
    
    void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
    {
        int upsampleCount = 0;
    
        if (isCompressed)
        {
            // Don't expand the size of full textures that are at least 4x4
            // already.
            if (isImage || *requestWidth < 4 || *requestHeight < 4)
            {
                while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0)
                {
                    *requestWidth <<= 1;
                    *requestHeight <<= 1;
                    upsampleCount++;
                }
            }
        }
        *levelOffset = upsampleCount;
    }
    
    // Returns the size, in bytes, of a single texel in an Image
    int ComputePixelSize(GLint internalformat)
    {
        switch (internalformat)
        {
          case GL_ALPHA8_EXT:                       return sizeof(unsigned char);
          case GL_LUMINANCE8_EXT:                   return sizeof(unsigned char);
          case GL_ALPHA32F_EXT:                     return sizeof(float);
          case GL_LUMINANCE32F_EXT:                 return sizeof(float);
          case GL_ALPHA16F_EXT:                     return sizeof(unsigned short);
          case GL_LUMINANCE16F_EXT:                 return sizeof(unsigned short);
          case GL_LUMINANCE8_ALPHA8_EXT:            return sizeof(unsigned char) * 2;
          case GL_LUMINANCE_ALPHA32F_EXT:           return sizeof(float) * 2;
          case GL_LUMINANCE_ALPHA16F_EXT:           return sizeof(unsigned short) * 2;
          case GL_RGB8_OES:                         return sizeof(unsigned char) * 3;
          case GL_RGB565:                           return sizeof(unsigned short);
          case GL_RGB32F_EXT:                       return sizeof(float) * 3;
          case GL_RGB16F_EXT:                       return sizeof(unsigned short) * 3;
          case GL_RGBA8_OES:                        return sizeof(unsigned char) * 4;
          case GL_RGBA4:                            return sizeof(unsigned short);
          case GL_RGB5_A1:                          return sizeof(unsigned short);
          case GL_RGBA32F_EXT:                      return sizeof(float) * 4;
          case GL_RGBA16F_EXT:                      return sizeof(unsigned short) * 4;
          case GL_BGRA8_EXT:                        return sizeof(unsigned char) * 4;
          case GL_SRGB8_ALPHA8:                     return sizeof(unsigned char) * 4;
          case GL_RGB10_A2:                         return sizeof(unsigned char) * 4;
          case GL_RG8:                              return sizeof(unsigned char) * 2;
          case GL_R8:                               return sizeof(unsigned char);
          case GL_BGRA4_ANGLEX:                     return sizeof(unsigned short);
          case GL_BGR5_A1_ANGLEX:                   return sizeof(unsigned short);
          default:
            UNIMPLEMENTED();   // TODO: Remaining ES3 formats
            UNREACHABLE();
        }
    
        return 0;
    }
    
    bool IsCubemapTextureTarget(GLenum target)
    {
        return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
    }
    
    bool IsInternalTextureTarget(GLenum target)
    {
        return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);
    }
    
    GLint ConvertSizedInternalFormat(GLenum format, GLenum type)
    {
        switch (format)
        {
          case GL_ALPHA:
            switch (type)
            {
              case GL_UNSIGNED_BYTE:    return GL_ALPHA8_EXT;
              case GL_FLOAT:            return GL_ALPHA32F_EXT;
              case GL_HALF_FLOAT_OES:   return GL_ALPHA16F_EXT;
              default:                  UNIMPLEMENTED();
            }
            break;
          case GL_LUMINANCE:
            switch (type)
            {
              case GL_UNSIGNED_BYTE:    return GL_LUMINANCE8_EXT;
              case GL_FLOAT:            return GL_LUMINANCE32F_EXT;
              case GL_HALF_FLOAT_OES:   return GL_LUMINANCE16F_EXT;
              default:                  UNIMPLEMENTED();
            }
            break;
          case GL_LUMINANCE_ALPHA:
            switch (type)
            {
              case GL_UNSIGNED_BYTE:    return GL_LUMINANCE8_ALPHA8_EXT;
              case GL_FLOAT:            return GL_LUMINANCE_ALPHA32F_EXT;
              case GL_HALF_FLOAT_OES:   return GL_LUMINANCE_ALPHA16F_EXT;
              default:                  UNIMPLEMENTED();
            }
            break;
          case GL_RGB:
            switch (type)
            {
              case GL_UNSIGNED_BYTE:            return GL_RGB8_OES;
              case GL_UNSIGNED_SHORT_5_6_5:     return GL_RGB565;
              case GL_FLOAT:                    return GL_RGB32F_EXT;
              case GL_HALF_FLOAT_OES:           return GL_RGB16F_EXT;
              default:                          UNIMPLEMENTED();
            }
            break;
          case GL_RGBA:
            switch (type)
            {
              case GL_UNSIGNED_BYTE:            return GL_RGBA8_OES;
              case GL_UNSIGNED_SHORT_4_4_4_4:   return GL_RGBA4;
              case GL_UNSIGNED_SHORT_5_5_5_1:   return GL_RGB5_A1;
              case GL_FLOAT:                    return GL_RGBA32F_EXT;
              case GL_HALF_FLOAT_OES:           return GL_RGBA16F_EXT;
                break;
              default:                          UNIMPLEMENTED();
            }
            break;
          case GL_BGRA_EXT:
            switch (type)
            {
              case GL_UNSIGNED_BYTE:                    return GL_BGRA8_EXT;
              case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:   return GL_BGRA4_ANGLEX;
              case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:   return GL_BGR5_A1_ANGLEX;
              default:                                  UNIMPLEMENTED();
            }
            break;
          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
            return format;
          case GL_DEPTH_COMPONENT:
            switch (type)
            {
              case GL_UNSIGNED_SHORT:           return GL_DEPTH_COMPONENT16;
              case GL_UNSIGNED_INT:             return GL_DEPTH_COMPONENT32_OES;
              default:                          UNIMPLEMENTED();
            }
            break;
          case GL_DEPTH_STENCIL_OES:
            switch (type)
            {
              case GL_UNSIGNED_INT_24_8_OES:    return GL_DEPTH24_STENCIL8_OES;
              default:                          UNIMPLEMENTED();
            }
            break;
          default:
            UNIMPLEMENTED();
        }
    
        return GL_NONE;
    }
    
    GLenum ExtractFormat(GLenum internalformat)
    {
        switch (internalformat)
        {
          case GL_RGB565:                          return GL_RGB;
          case GL_RGBA4:                           return GL_RGBA;
          case GL_RGB5_A1:                         return GL_RGBA;
          case GL_RGB8_OES:                        return GL_RGB;
          case GL_RGBA8_OES:                       return GL_RGBA;
          case GL_LUMINANCE8_ALPHA8_EXT:           return GL_LUMINANCE_ALPHA;
          case GL_LUMINANCE8_EXT:                  return GL_LUMINANCE;
          case GL_ALPHA8_EXT:                      return GL_ALPHA;
          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:    return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:   return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
          case GL_RGBA32F_EXT:                     return GL_RGBA;
          case GL_RGB32F_EXT:                      return GL_RGB;
          case GL_ALPHA32F_EXT:                    return GL_ALPHA;
          case GL_LUMINANCE32F_EXT:                return GL_LUMINANCE;
          case GL_LUMINANCE_ALPHA32F_EXT:          return GL_LUMINANCE_ALPHA;
          case GL_RGBA16F_EXT:                     return GL_RGBA;
          case GL_RGB16F_EXT:                      return GL_RGB;
          case GL_ALPHA16F_EXT:                    return GL_ALPHA;
          case GL_LUMINANCE16F_EXT:                return GL_LUMINANCE;
          case GL_LUMINANCE_ALPHA16F_EXT:          return GL_LUMINANCE_ALPHA;
          case GL_BGRA8_EXT:                       return GL_BGRA_EXT;
          case GL_DEPTH_COMPONENT16:               return GL_DEPTH_COMPONENT;
          case GL_DEPTH_COMPONENT32_OES:           return GL_DEPTH_COMPONENT;
          case GL_DEPTH24_STENCIL8_OES:            return GL_DEPTH_STENCIL_OES;
          default:                                 return GL_NONE;   // Unsupported
        }
    }
    
    GLenum ExtractType(GLenum internalformat)
    {
        switch (internalformat)
        {
          case GL_RGB565:                          return GL_UNSIGNED_SHORT_5_6_5;
          case GL_RGBA4:                           return GL_UNSIGNED_SHORT_4_4_4_4;
          case GL_RGB5_A1:                         return GL_UNSIGNED_SHORT_5_5_5_1;
          case GL_RGB8_OES:                        return GL_UNSIGNED_BYTE;
          case GL_RGBA8_OES:                       return GL_UNSIGNED_BYTE;
          case GL_LUMINANCE8_ALPHA8_EXT:           return GL_UNSIGNED_BYTE;
          case GL_LUMINANCE8_EXT:                  return GL_UNSIGNED_BYTE;
          case GL_ALPHA8_EXT:                      return GL_UNSIGNED_BYTE;
          case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:    return GL_UNSIGNED_BYTE;
          case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:   return GL_UNSIGNED_BYTE;
          case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE;
          case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE;
          case GL_RGBA32F_EXT:                     return GL_FLOAT;
          case GL_RGB32F_EXT:                      return GL_FLOAT;
          case GL_ALPHA32F_EXT:                    return GL_FLOAT;
          case GL_LUMINANCE32F_EXT:                return GL_FLOAT;
          case GL_LUMINANCE_ALPHA32F_EXT:          return GL_FLOAT;
          case GL_RGBA16F_EXT:                     return GL_HALF_FLOAT_OES;
          case GL_RGB16F_EXT:                      return GL_HALF_FLOAT_OES;
          case GL_ALPHA16F_EXT:                    return GL_HALF_FLOAT_OES;
          case GL_LUMINANCE16F_EXT:                return GL_HALF_FLOAT_OES;
          case GL_LUMINANCE_ALPHA16F_EXT:          return GL_HALF_FLOAT_OES;
          case GL_BGRA8_EXT:                       return GL_UNSIGNED_BYTE;
          case GL_DEPTH_COMPONENT16:               return GL_UNSIGNED_SHORT;
          case GL_DEPTH_COMPONENT32_OES:           return GL_UNSIGNED_INT;
          case GL_DEPTH24_STENCIL8_OES:            return GL_UNSIGNED_INT_24_8_OES;
          default:                                 return GL_NONE;   // Unsupported
        }
    }
    
    bool IsColorRenderable(GLenum internalformat)
    {
        switch (internalformat)
        {
          case GL_RGBA4:
          case GL_RGB5_A1:
          case GL_RGB565:
          case GL_RGB8_OES:
          case GL_RGBA8_OES:
          case GL_BGRA8_EXT:
          case GL_SRGB8_ALPHA8:
          case GL_RGB10_A2:
          case GL_RG8:
          case GL_R8:
            return true;
          case GL_DEPTH_COMPONENT16:
          case GL_STENCIL_INDEX8:
          case GL_DEPTH24_STENCIL8_OES:
            return false;
          default:
            UNIMPLEMENTED();   // TODO: Remaining ES3 formats
            UNREACHABLE();
        }
    
        return false;
    }
    
    bool IsDepthRenderable(GLenum internalformat)
    {
        switch (internalformat)
        {
          case GL_DEPTH_COMPONENT16:
          case GL_DEPTH24_STENCIL8_OES:
            return true;
          case GL_STENCIL_INDEX8:
          case GL_RGBA4:
          case GL_RGB5_A1:
          case GL_RGB565:
          case GL_RGB8_OES:
          case GL_RGBA8_OES:
            return false;
          default:
            UNIMPLEMENTED();
        }
    
        return false;
    }
    
    bool IsStencilRenderable(GLenum internalformat)
    {
        switch (internalformat)
        {
          case GL_STENCIL_INDEX8:
          case GL_DEPTH24_STENCIL8_OES:
            return true;
          case GL_RGBA4:
          case GL_RGB5_A1:
          case GL_RGB565:
          case GL_RGB8_OES:
          case GL_RGBA8_OES:
          case GL_DEPTH_COMPONENT16:
            return false;
          default:
            UNIMPLEMENTED();
        }
    
        return false;
    }
    
    bool IsFloat32Format(GLint internalformat)
    {
        switch (internalformat)
        {
          case GL_RGBA32F_EXT:
          case GL_RGB32F_EXT:
          case GL_ALPHA32F_EXT:
          case GL_LUMINANCE32F_EXT:
          case GL_LUMINANCE_ALPHA32F_EXT:
            return true;
          default:
            return false;
        }
    }
    
    bool IsFloat16Format(GLint internalformat)
    {
        switch (internalformat)
        {
          case GL_RGBA16F_EXT:
          case GL_RGB16F_EXT:
          case GL_ALPHA16F_EXT:
          case GL_LUMINANCE16F_EXT:
          case GL_LUMINANCE_ALPHA16F_EXT:
            return true;
          default:
            return false;
        }
    }
    
    unsigned int GetAlphaSize(GLenum colorFormat)
    {
        switch (colorFormat)
        {
          case GL_RGBA16F_EXT:
            return 16;
          case GL_RGBA32F_EXT:
            return 32;
          case GL_RGBA4:
            return 4;
          case GL_RGBA8_OES:
          case GL_BGRA8_EXT:
            return 8;
          case GL_RGB5_A1:
            return 1;
          case GL_RGB8_OES:
          case GL_RGB565:
          case GL_RGB32F_EXT:
          case GL_RGB16F_EXT:
            return 0;
          default:
            return 0;
        }
    }
    
    unsigned int GetRedSize(GLenum colorFormat)
    {
        switch (colorFormat)
        {
          case GL_RGBA16F_EXT:
          case GL_RGB16F_EXT:
            return 16;
          case GL_RGBA32F_EXT:
          case GL_RGB32F_EXT:
            return 32;
          case GL_RGBA4:
            return 4;
          case GL_RGBA8_OES:
          case GL_BGRA8_EXT:
          case GL_RGB8_OES:
            return 8;
          case GL_RGB5_A1:
          case GL_RGB565:
            return 5;
          default:
            return 0;
        }
    }
    
    unsigned int GetGreenSize(GLenum colorFormat)
    {
        switch (colorFormat)
        {
          case GL_RGBA16F_EXT:
          case GL_RGB16F_EXT:
            return 16;
          case GL_RGBA32F_EXT:
          case GL_RGB32F_EXT:
            return 32;
          case GL_RGBA4:
            return 4;
          case GL_RGBA8_OES:
          case GL_BGRA8_EXT:
          case GL_RGB8_OES:
            return 8;
          case GL_RGB5_A1:
            return 5;
          case GL_RGB565:
            return 6;
          default:
            return 0;
        }
    }
    
    unsigned int GetBlueSize(GLenum colorFormat)
    {
        switch (colorFormat)
        {
          case GL_RGBA16F_EXT:
          case GL_RGB16F_EXT:
            return 16;
          case GL_RGBA32F_EXT:
          case GL_RGB32F_EXT:
            return 32;
          case GL_RGBA4:
            return 4;
          case GL_RGBA8_OES:
          case GL_BGRA8_EXT:
          case GL_RGB8_OES:
            return 8;
          case GL_RGB5_A1:
          case GL_RGB565:
            return 5;
          default:
            return 0;
        }
    }
    
    unsigned int GetDepthSize(GLenum depthFormat)
    {
        switch (depthFormat)
        {
          case GL_DEPTH_COMPONENT16:        return 16;
          case GL_DEPTH_COMPONENT32_OES:    return 32;
          case GL_DEPTH24_STENCIL8_OES:     return 24;
          default:                          return 0;
        }
    }
    
    unsigned int GetStencilSize(GLenum stencilFormat)
    {
        switch (stencilFormat)
        {
          case GL_DEPTH24_STENCIL8_OES:     return 8;
          default:                          return 0;
        }
    }
    
    bool IsTriangleMode(GLenum drawMode)
    {
        switch (drawMode)
        {
          case GL_TRIANGLES:
          case GL_TRIANGLE_FAN:
          case GL_TRIANGLE_STRIP:
            return true;
          case GL_POINTS:
          case GL_LINES:
          case GL_LINE_LOOP:
          case GL_LINE_STRIP:
            return false;
          default: UNREACHABLE();
        }
    
        return false;
    }
    
    struct FormatInfo
    {
        GLenum mFormat;
        GLenum mType;
        GLint mInternalformat;
    
        FormatInfo(GLenum format, GLenum type, GLint internalformat)
            : mFormat(format), mType(type), mInternalformat(internalformat) { }
    
        bool operator<(const FormatInfo& other) const
        {
            return memcmp(this, &other, sizeof(FormatInfo)) < 0;
        }
    };
    
    typedef std::set<FormatInfo> formatInfoSet;
    static formatInfoSet buildValidES3FormatCombinationSet()
    {
        formatInfoSet set;
    
        // From ES 3.0.1 spec, table 3.2
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_BYTE,                   GL_RGBA8             ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_BYTE,                   GL_RGB5_A1           ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_BYTE,                   GL_RGBA4             ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_BYTE,                   GL_SRGB8_ALPHA8      ));
        set.insert(FormatInfo(GL_RGBA,            GL_BYTE,                            GL_RGBA8_SNORM       ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4,          GL_RGBA4             ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV,     GL_RGB10_A2          ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV,     GL_RGB5_A1           ));
        set.insert(FormatInfo(GL_RGBA,            GL_HALF_FLOAT,                      GL_RGBA16F           ));
        set.insert(FormatInfo(GL_RGBA,            GL_FLOAT,                           GL_RGBA32F           ));
        set.insert(FormatInfo(GL_RGBA,            GL_FLOAT,                           GL_RGBA16F           ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_UNSIGNED_BYTE,                   GL_RGBA8UI           ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_BYTE,                            GL_RGBA8I            ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_UNSIGNED_SHORT,                  GL_RGBA16UI          ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_SHORT,                           GL_RGBA16I           ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_UNSIGNED_INT,                    GL_RGBA32UI          ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_INT,                             GL_RGBA32I           ));
        set.insert(FormatInfo(GL_RGBA_INTEGER,    GL_UNSIGNED_INT_2_10_10_10_REV,     GL_RGB10_A2UI        ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_BYTE,                   GL_RGB8              ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_BYTE,                   GL_RGB565            ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_BYTE,                   GL_SRGB8             ));
        set.insert(FormatInfo(GL_RGB,             GL_BYTE,                            GL_RGB8_SNORM        ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_SHORT_5_6_5,            GL_RGB565            ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_INT_10F_11F_11F_REV,    GL_R11F_G11F_B10F    ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_INT_5_9_9_9_REV,        GL_RGB9_E5           ));
        set.insert(FormatInfo(GL_RGB,             GL_HALF_FLOAT,                      GL_RGB16F            ));
        set.insert(FormatInfo(GL_RGB,             GL_HALF_FLOAT,                      GL_R11F_G11F_B10F    ));
        set.insert(FormatInfo(GL_RGB,             GL_HALF_FLOAT,                      GL_RGB9_E5           ));
        set.insert(FormatInfo(GL_RGB,             GL_FLOAT,                           GL_RGB32F            ));
        set.insert(FormatInfo(GL_RGB,             GL_FLOAT,                           GL_RGB16F            ));
        set.insert(FormatInfo(GL_RGB,             GL_FLOAT,                           GL_R11F_G11F_B10F    ));
        set.insert(FormatInfo(GL_RGB,             GL_FLOAT,                           GL_RGB9_E5           ));
        set.insert(FormatInfo(GL_RGB_INTEGER,     GL_UNSIGNED_BYTE,                   GL_RGB8UI            ));
        set.insert(FormatInfo(GL_RGB_INTEGER,     GL_BYTE,                            GL_RGB8I             ));
        set.insert(FormatInfo(GL_RGB_INTEGER,     GL_UNSIGNED_SHORT,                  GL_RGB16UI           ));
        set.insert(FormatInfo(GL_RGB_INTEGER,     GL_SHORT,                           GL_RGB16I            ));
        set.insert(FormatInfo(GL_RGB_INTEGER,     GL_UNSIGNED_INT,                    GL_RGB32UI           ));
        set.insert(FormatInfo(GL_RGB_INTEGER,     GL_INT,                             GL_RGB32I            ));
        set.insert(FormatInfo(GL_RG,              GL_UNSIGNED_BYTE,                   GL_RG8               ));
        set.insert(FormatInfo(GL_RG,              GL_BYTE,                            GL_RG8_SNORM         ));
        set.insert(FormatInfo(GL_RG,              GL_HALF_FLOAT,                      GL_RG16F             ));
        set.insert(FormatInfo(GL_RG,              GL_FLOAT,                           GL_RG32F             ));
        set.insert(FormatInfo(GL_RG,              GL_FLOAT,                           GL_RG16F             ));
        set.insert(FormatInfo(GL_RG_INTEGER,      GL_UNSIGNED_BYTE,                   GL_RG8UI             ));
        set.insert(FormatInfo(GL_RG_INTEGER,      GL_BYTE,                            GL_RG8I              ));
        set.insert(FormatInfo(GL_RG_INTEGER,      GL_UNSIGNED_SHORT,                  GL_RG16UI            ));
        set.insert(FormatInfo(GL_RG_INTEGER,      GL_SHORT,                           GL_RG16I             ));
        set.insert(FormatInfo(GL_RG_INTEGER,      GL_UNSIGNED_INT,                    GL_RG32UI            ));
        set.insert(FormatInfo(GL_RG_INTEGER,      GL_INT,                             GL_RG32I             ));
        set.insert(FormatInfo(GL_RED,             GL_UNSIGNED_BYTE,                   GL_R8                ));
        set.insert(FormatInfo(GL_RED,             GL_BYTE,                            GL_R8_SNORM          ));
        set.insert(FormatInfo(GL_RED,             GL_HALF_FLOAT,                      GL_R16F              ));
        set.insert(FormatInfo(GL_RED,             GL_FLOAT,                           GL_R32F              ));
        set.insert(FormatInfo(GL_RED,             GL_FLOAT,                           GL_R16F              ));
        set.insert(FormatInfo(GL_RED_INTEGER,     GL_UNSIGNED_BYTE,                   GL_R8UI              ));
        set.insert(FormatInfo(GL_RED_INTEGER,     GL_BYTE,                            GL_R8I               ));
        set.insert(FormatInfo(GL_RED_INTEGER,     GL_UNSIGNED_SHORT,                  GL_R16UI             ));
        set.insert(FormatInfo(GL_RED_INTEGER,     GL_SHORT,                           GL_R16I              ));
        set.insert(FormatInfo(GL_RED_INTEGER,     GL_UNSIGNED_INT,                    GL_R32UI             ));
        set.insert(FormatInfo(GL_RED_INTEGER,     GL_INT,                             GL_R32I              ));
        set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                  GL_DEPTH_COMPONENT16 ));
        set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                    GL_DEPTH_COMPONENT24 ));
        set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                    GL_DEPTH_COMPONENT16 ));
        set.insert(FormatInfo(GL_DEPTH_COMPONENT, GL_FLOAT,                           GL_DEPTH_COMPONENT32F));
        set.insert(FormatInfo(GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,               GL_DEPTH24_STENCIL8  ));
        set.insert(FormatInfo(GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV,  GL_DEPTH32F_STENCIL8 ));
    
        // From ES 3.0.1 spec, table 3.3
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_BYTE,                   GL_RGBA              ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4,          GL_RGBA              ));
        set.insert(FormatInfo(GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1,          GL_RGBA              ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_BYTE,                   GL_RGB               ));
        set.insert(FormatInfo(GL_RGB,             GL_UNSIGNED_SHORT_5_6_5,            GL_RGB               ));
        set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,                   GL_LUMINANCE_ALPHA   ));
        set.insert(FormatInfo(GL_LUMINANCE,       GL_UNSIGNED_BYTE,                   GL_LUMINANCE         ));
        set.insert(FormatInfo(GL_ALPHA,           GL_UNSIGNED_BYTE,                   GL_ALPHA             ));
    
        // From GL_OES_texture_float
        set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_FLOAT,                           GL_LUMINANCE_ALPHA   ));
        set.insert(FormatInfo(GL_LUMINANCE,       GL_FLOAT,                           GL_LUMINANCE         ));
        set.insert(FormatInfo(GL_ALPHA,           GL_FLOAT,                           GL_ALPHA             ));
    
        // From GL_OES_texture_half_float
        set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_HALF_FLOAT,                      GL_LUMINANCE_ALPHA   ));
        set.insert(FormatInfo(GL_LUMINANCE,       GL_HALF_FLOAT,                      GL_LUMINANCE         ));
        set.insert(FormatInfo(GL_ALPHA,           GL_HALF_FLOAT,                      GL_ALPHA             ));
    
        return set;
    }
    
    typedef std::set<GLint> internalFormatSet;
    static internalFormatSet buildValidES3InternalFormatSet(const formatInfoSet& formatCombos)
    {
        internalFormatSet internalFormats;
        for (formatInfoSet::const_iterator i = formatCombos.begin(); i != formatCombos.end(); i++)
        {
            internalFormats.insert(i->mInternalformat);
        }
        return internalFormats;
    }
    
    typedef std::set<GLenum> formatSet;
    static formatSet buildValidES3FormatSet(const formatInfoSet& formatCombos)
    {
        formatSet formats;
        for (formatInfoSet::const_iterator i = formatCombos.begin(); i != formatCombos.end(); i++)
        {
            formats.insert(i->mFormat);
        }
        return formats;
    }
    
    typedef std::set<GLenum> typeSet;
    static typeSet buildValidES3TypeSet(const formatInfoSet& formatCombos)
    {
        typeSet types;
        for (formatInfoSet::const_iterator i = formatCombos.begin(); i != formatCombos.end(); i++)
        {
            types.insert(i->mType);
        }
        return types;
    }
    
    bool IsValidES3FormatCombination(GLint internalformat, GLenum format, GLenum type, GLenum* err)
    {
        static const formatInfoSet combinations = buildValidES3FormatCombinationSet();
        static const internalFormatSet internalFormats = buildValidES3InternalFormatSet(combinations);
        static const formatSet formats = buildValidES3FormatSet(combinations);
        static const typeSet types = buildValidES3TypeSet(combinations);
    
        // Invalid internal format, format or type results in an INVALID_ENUM
        if (internalFormats.find(internalformat) == internalFormats.end() ||
            formats.find(format) == formats.end() ||
            types.find(type) == types.end())
        {
            *err = GL_INVALID_ENUM;
            return false;
        }
    
        // Invalid internal format + format + type combination results in an INVALID_OPERATION
        if (combinations.find(FormatInfo(format, type, internalformat)) == combinations.end())
        {
            *err = GL_INVALID_OPERATION;
            return false;
        }
    
        return true;
    }
    
    typedef std::set<GLenum> compressedFormatSet;
    static compressedFormatSet buildValidES3CompressedFormats()
    {
        compressedFormatSet formats;
    
        // From ES 3.0.1 spec, table 3.16
        formats.insert(GL_COMPRESSED_R11_EAC                       );
        formats.insert(GL_COMPRESSED_R11_EAC                       );
        formats.insert(GL_COMPRESSED_SIGNED_R11_EAC                );
        formats.insert(GL_COMPRESSED_RG11_EAC                      );
        formats.insert(GL_COMPRESSED_SIGNED_RG11_EAC               );
        formats.insert(GL_COMPRESSED_RGB8_ETC2                     );
        formats.insert(GL_COMPRESSED_SRGB8_ETC2                    );
        formats.insert(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 );
        formats.insert(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
        formats.insert(GL_COMPRESSED_RGBA8_ETC2_EAC                );
        formats.insert(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC         );
    
        // From GL_EXT_texture_compression_dxt1
        formats.insert(GL_COMPRESSED_RGB_S3TC_DXT1_EXT             );
        formats.insert(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT            );
    
        // From GL_ANGLE_texture_compression_dxt3
        formats.insert(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE          );
    
        // From GL_ANGLE_texture_compression_dxt5
        formats.insert(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE          );
    
        return formats;
    }
    
    bool IsValidES3CompressedFormat(GLenum format)
    {
        static const compressedFormatSet validCompressedFormats = buildValidES3CompressedFormats();
        return validCompressedFormats.find(format) != validCompressedFormats.end();
    }
    
    struct CopyConversion
    {
        GLenum mTextureFormat;
        GLenum mFramebufferFormat;
    
        CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
            : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
    
        bool operator<(const CopyConversion& other) const
        {
            return memcmp(this, &other, sizeof(CopyConversion)) < 0;
        }
    };
    
    typedef std::set<CopyConversion> copyConversionSet;
    static copyConversionSet buildValidES3CopyTexImageCombinations()
    {
        copyConversionSet set;
    
        // From ES 3.0.1 spec, table 3.15
        set.insert(CopyConversion(GL_ALPHA,           GL_RGBA));
        set.insert(CopyConversion(GL_LUMINANCE,       GL_RED));
        set.insert(CopyConversion(GL_LUMINANCE,       GL_RG));
        set.insert(CopyConversion(GL_LUMINANCE,       GL_RGB));
        set.insert(CopyConversion(GL_LUMINANCE,       GL_RGBA));
        set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
        set.insert(CopyConversion(GL_RED,             GL_RED));
        set.insert(CopyConversion(GL_RED,             GL_RG));
        set.insert(CopyConversion(GL_RED,             GL_RGB));
        set.insert(CopyConversion(GL_RED,             GL_RGBA));
        set.insert(CopyConversion(GL_RG,              GL_RG));
        set.insert(CopyConversion(GL_RG,              GL_RGB));
        set.insert(CopyConversion(GL_RG,              GL_RGBA));
        set.insert(CopyConversion(GL_RGB,             GL_RGB));
        set.insert(CopyConversion(GL_RGB,             GL_RGBA));
        set.insert(CopyConversion(GL_RGBA,            GL_RGBA));
    
        return set;
    }
    
    bool IsValidES3CopyTexImageCombination(GLenum textureFormat, GLenum frameBufferFormat)
    {
        static const copyConversionSet conversions = buildValidES3CopyTexImageCombinations();
        return conversions.find(CopyConversion(textureFormat, frameBufferFormat)) != conversions.end();
    }
    
    }
    
    std::string getTempPath()
    {
        char path[MAX_PATH];
        DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
        if (pathLen == 0)
        {
            UNREACHABLE();
            return std::string();
        }
    
        UINT unique = GetTempFileNameA(path, "sh", 0, path);
        if (unique == 0)
        {
            UNREACHABLE();
            return std::string();
        }
        
        return path;
    }
    
    void writeFile(const char* path, const void* content, size_t size)
    {
        FILE* file = fopen(path, "w");
        if (!file)
        {
            UNREACHABLE();
            return;
        }
    
        fwrite(content, sizeof(char), size, file);
        fclose(file);
    }