Home | History | Annotate | Download | only in libGLESv2
      1 //
      2 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
      8 
      9 #include "libGLESv2/validationES3.h"
     10 #include "libGLESv2/validationES.h"
     11 #include "libGLESv2/Context.h"
     12 #include "libGLESv2/Texture.h"
     13 #include "libGLESv2/Framebuffer.h"
     14 #include "libGLESv2/Renderbuffer.h"
     15 #include "libGLESv2/formatutils.h"
     16 #include "libGLESv2/main.h"
     17 #include "libGLESv2/FramebufferAttachment.h"
     18 
     19 #include "common/mathutil.h"
     20 
     21 namespace gl
     22 {
     23 
     24 struct ES3FormatCombination
     25 {
     26     GLenum internalFormat;
     27     GLenum format;
     28     GLenum type;
     29 };
     30 
     31 bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
     32 {
     33     return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
     34 }
     35 
     36 typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
     37 
     38 static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
     39 {
     40     ES3FormatCombination info;
     41     info.internalFormat = internalFormat;
     42     info.format = format;
     43     info.type = type;
     44     set->insert(info);
     45 }
     46 
     47 ES3FormatCombinationSet BuildES3FormatSet()
     48 {
     49     ES3FormatCombinationSet set;
     50 
     51     // Format combinations from ES 3.0.1 spec, table 3.2
     52 
     53     //                        | Internal format      | Format            | Type                            |
     54     //                        |                      |                   |                                 |
     55     InsertES3FormatCombo(&set, GL_RGBA8,              GL_RGBA,            GL_UNSIGNED_BYTE                 );
     56     InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_BYTE                 );
     57     InsertES3FormatCombo(&set, GL_RGBA4,              GL_RGBA,            GL_UNSIGNED_BYTE                 );
     58     InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8,       GL_RGBA,            GL_UNSIGNED_BYTE                 );
     59     InsertES3FormatCombo(&set, GL_RGBA8_SNORM,        GL_RGBA,            GL_BYTE                          );
     60     InsertES3FormatCombo(&set, GL_RGBA4,              GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4        );
     61     InsertES3FormatCombo(&set, GL_RGB10_A2,           GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV   );
     62     InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_INT_2_10_10_10_REV   );
     63     InsertES3FormatCombo(&set, GL_RGB5_A1,            GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1        );
     64     InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_HALF_FLOAT                    );
     65     InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_HALF_FLOAT_OES                );
     66     InsertES3FormatCombo(&set, GL_RGBA32F,            GL_RGBA,            GL_FLOAT                         );
     67     InsertES3FormatCombo(&set, GL_RGBA16F,            GL_RGBA,            GL_FLOAT                         );
     68     InsertES3FormatCombo(&set, GL_RGBA8UI,            GL_RGBA_INTEGER,    GL_UNSIGNED_BYTE                 );
     69     InsertES3FormatCombo(&set, GL_RGBA8I,             GL_RGBA_INTEGER,    GL_BYTE                          );
     70     InsertES3FormatCombo(&set, GL_RGBA16UI,           GL_RGBA_INTEGER,    GL_UNSIGNED_SHORT                );
     71     InsertES3FormatCombo(&set, GL_RGBA16I,            GL_RGBA_INTEGER,    GL_SHORT                         );
     72     InsertES3FormatCombo(&set, GL_RGBA32UI,           GL_RGBA_INTEGER,    GL_UNSIGNED_INT                  );
     73     InsertES3FormatCombo(&set, GL_RGBA32I,            GL_RGBA_INTEGER,    GL_INT                           );
     74     InsertES3FormatCombo(&set, GL_RGB10_A2UI,         GL_RGBA_INTEGER,    GL_UNSIGNED_INT_2_10_10_10_REV   );
     75     InsertES3FormatCombo(&set, GL_RGB8,               GL_RGB,             GL_UNSIGNED_BYTE                 );
     76     InsertES3FormatCombo(&set, GL_RGB565,             GL_RGB,             GL_UNSIGNED_BYTE                 );
     77     InsertES3FormatCombo(&set, GL_SRGB8,              GL_RGB,             GL_UNSIGNED_BYTE                 );
     78     InsertES3FormatCombo(&set, GL_RGB8_SNORM,         GL_RGB,             GL_BYTE                          );
     79     InsertES3FormatCombo(&set, GL_RGB565,             GL_RGB,             GL_UNSIGNED_SHORT_5_6_5          );
     80     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_UNSIGNED_INT_10F_11F_11F_REV  );
     81     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_UNSIGNED_INT_5_9_9_9_REV      );
     82     InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_HALF_FLOAT                    );
     83     InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_HALF_FLOAT_OES                );
     84     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_HALF_FLOAT                    );
     85     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_HALF_FLOAT_OES                );
     86     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_HALF_FLOAT                    );
     87     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_HALF_FLOAT_OES                );
     88     InsertES3FormatCombo(&set, GL_RGB32F,             GL_RGB,             GL_FLOAT                         );
     89     InsertES3FormatCombo(&set, GL_RGB16F,             GL_RGB,             GL_FLOAT                         );
     90     InsertES3FormatCombo(&set, GL_R11F_G11F_B10F,     GL_RGB,             GL_FLOAT                         );
     91     InsertES3FormatCombo(&set, GL_RGB9_E5,            GL_RGB,             GL_FLOAT                         );
     92     InsertES3FormatCombo(&set, GL_RGB8UI,             GL_RGB_INTEGER,     GL_UNSIGNED_BYTE                 );
     93     InsertES3FormatCombo(&set, GL_RGB8I,              GL_RGB_INTEGER,     GL_BYTE                          );
     94     InsertES3FormatCombo(&set, GL_RGB16UI,            GL_RGB_INTEGER,     GL_UNSIGNED_SHORT                );
     95     InsertES3FormatCombo(&set, GL_RGB16I,             GL_RGB_INTEGER,     GL_SHORT                         );
     96     InsertES3FormatCombo(&set, GL_RGB32UI,            GL_RGB_INTEGER,     GL_UNSIGNED_INT                  );
     97     InsertES3FormatCombo(&set, GL_RGB32I,             GL_RGB_INTEGER,     GL_INT                           );
     98     InsertES3FormatCombo(&set, GL_RG8,                GL_RG,              GL_UNSIGNED_BYTE                 );
     99     InsertES3FormatCombo(&set, GL_RG8_SNORM,          GL_RG,              GL_BYTE                          );
    100     InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_HALF_FLOAT                    );
    101     InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_HALF_FLOAT_OES                );
    102     InsertES3FormatCombo(&set, GL_RG32F,              GL_RG,              GL_FLOAT                         );
    103     InsertES3FormatCombo(&set, GL_RG16F,              GL_RG,              GL_FLOAT                         );
    104     InsertES3FormatCombo(&set, GL_RG8UI,              GL_RG_INTEGER,      GL_UNSIGNED_BYTE                 );
    105     InsertES3FormatCombo(&set, GL_RG8I,               GL_RG_INTEGER,      GL_BYTE                          );
    106     InsertES3FormatCombo(&set, GL_RG16UI,             GL_RG_INTEGER,      GL_UNSIGNED_SHORT                );
    107     InsertES3FormatCombo(&set, GL_RG16I,              GL_RG_INTEGER,      GL_SHORT                         );
    108     InsertES3FormatCombo(&set, GL_RG32UI,             GL_RG_INTEGER,      GL_UNSIGNED_INT                  );
    109     InsertES3FormatCombo(&set, GL_RG32I,              GL_RG_INTEGER,      GL_INT                           );
    110     InsertES3FormatCombo(&set, GL_R8,                 GL_RED,             GL_UNSIGNED_BYTE                 );
    111     InsertES3FormatCombo(&set, GL_R8_SNORM,           GL_RED,             GL_BYTE                          );
    112     InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_HALF_FLOAT                    );
    113     InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_HALF_FLOAT_OES                );
    114     InsertES3FormatCombo(&set, GL_R32F,               GL_RED,             GL_FLOAT                         );
    115     InsertES3FormatCombo(&set, GL_R16F,               GL_RED,             GL_FLOAT                         );
    116     InsertES3FormatCombo(&set, GL_R8UI,               GL_RED_INTEGER,     GL_UNSIGNED_BYTE                 );
    117     InsertES3FormatCombo(&set, GL_R8I,                GL_RED_INTEGER,     GL_BYTE                          );
    118     InsertES3FormatCombo(&set, GL_R16UI,              GL_RED_INTEGER,     GL_UNSIGNED_SHORT                );
    119     InsertES3FormatCombo(&set, GL_R16I,               GL_RED_INTEGER,     GL_SHORT                         );
    120     InsertES3FormatCombo(&set, GL_R32UI,              GL_RED_INTEGER,     GL_UNSIGNED_INT                  );
    121     InsertES3FormatCombo(&set, GL_R32I,               GL_RED_INTEGER,     GL_INT                           );
    122 
    123     // Unsized formats
    124     InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_BYTE                 );
    125     InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_SHORT_4_4_4_4        );
    126     InsertES3FormatCombo(&set, GL_RGBA,               GL_RGBA,            GL_UNSIGNED_SHORT_5_5_5_1        );
    127     InsertES3FormatCombo(&set, GL_RGB,                GL_RGB,             GL_UNSIGNED_BYTE                 );
    128     InsertES3FormatCombo(&set, GL_RGB,                GL_RGB,             GL_UNSIGNED_SHORT_5_6_5          );
    129     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE                 );
    130     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_UNSIGNED_BYTE                 );
    131     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_UNSIGNED_BYTE                 );
    132     InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT,     GL_SRGB_ALPHA_EXT,  GL_UNSIGNED_BYTE                 );
    133     InsertES3FormatCombo(&set, GL_SRGB_EXT,           GL_SRGB_EXT,        GL_UNSIGNED_BYTE                 );
    134 
    135     // Depth stencil formats
    136     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16,  GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT                );
    137     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
    138     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
    139     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT                         );
    140     InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8,   GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8             );
    141     InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8,  GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
    142 
    143     // From GL_EXT_sRGB
    144     InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT,   GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE                  );
    145     InsertES3FormatCombo(&set, GL_SRGB8,              GL_SRGB_EXT,       GL_UNSIGNED_BYTE                  );
    146 
    147     // From GL_OES_texture_float
    148     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_FLOAT                         );
    149     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_FLOAT                         );
    150     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_FLOAT                         );
    151 
    152     // From GL_OES_texture_half_float
    153     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_HALF_FLOAT                    );
    154     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA,    GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES                );
    155     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_HALF_FLOAT                    );
    156     InsertES3FormatCombo(&set, GL_LUMINANCE,          GL_LUMINANCE,       GL_HALF_FLOAT_OES                );
    157     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_HALF_FLOAT                    );
    158     InsertES3FormatCombo(&set, GL_ALPHA,              GL_ALPHA,           GL_HALF_FLOAT_OES                );
    159 
    160     // From GL_EXT_texture_format_BGRA8888
    161     InsertES3FormatCombo(&set, GL_BGRA_EXT,           GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
    162 
    163     // From GL_EXT_texture_storage
    164     //                    | Internal format          | Format            | Type                            |
    165     //                    |                          |                   |                                 |
    166     InsertES3FormatCombo(&set, GL_ALPHA8_EXT,             GL_ALPHA,           GL_UNSIGNED_BYTE                 );
    167     InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT,         GL_LUMINANCE,       GL_UNSIGNED_BYTE                 );
    168     InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE                 );
    169     InsertES3FormatCombo(&set, GL_ALPHA32F_EXT,           GL_ALPHA,           GL_FLOAT                         );
    170     InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT,       GL_LUMINANCE,       GL_FLOAT                         );
    171     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT                         );
    172     InsertES3FormatCombo(&set, GL_ALPHA16F_EXT,           GL_ALPHA,           GL_HALF_FLOAT                    );
    173     InsertES3FormatCombo(&set, GL_ALPHA16F_EXT,           GL_ALPHA,           GL_HALF_FLOAT_OES                );
    174     InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT,       GL_LUMINANCE,       GL_HALF_FLOAT                    );
    175     InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT,       GL_LUMINANCE,       GL_HALF_FLOAT_OES                );
    176     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT                    );
    177     InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES                );
    178 
    179     // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
    180     InsertES3FormatCombo(&set, GL_BGRA8_EXT,              GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
    181     InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX,           GL_BGRA_EXT,        GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
    182     InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX,           GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
    183     InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX,         GL_BGRA_EXT,        GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
    184     InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX,         GL_BGRA_EXT,        GL_UNSIGNED_BYTE                 );
    185 
    186     // From GL_ANGLE_depth_texture
    187     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES         );
    188 
    189     // Compressed formats
    190     // From ES 3.0.1 spec, table 3.16
    191     //                    | Internal format                             | Format                                      | Type           |
    192     //                    |                                             |                                             |                |
    193     InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC,                        GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE);
    194     InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC,                        GL_COMPRESSED_R11_EAC,                        GL_UNSIGNED_BYTE);
    195     InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC,                 GL_COMPRESSED_SIGNED_R11_EAC,                 GL_UNSIGNED_BYTE);
    196     InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC,                       GL_COMPRESSED_RG11_EAC,                       GL_UNSIGNED_BYTE);
    197     InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC,                GL_COMPRESSED_SIGNED_RG11_EAC,                GL_UNSIGNED_BYTE);
    198     InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2,                      GL_COMPRESSED_RGB8_ETC2,                      GL_UNSIGNED_BYTE);
    199     InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2,                     GL_COMPRESSED_SRGB8_ETC2,                     GL_UNSIGNED_BYTE);
    200     InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,  GL_UNSIGNED_BYTE);
    201     InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE);
    202     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_COMPRESSED_RGBA8_ETC2_EAC,                 GL_UNSIGNED_BYTE);
    203     InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,          GL_UNSIGNED_BYTE);
    204 
    205 
    206     // From GL_EXT_texture_compression_dxt1
    207     InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_COMPRESSED_RGB_S3TC_DXT1_EXT,              GL_UNSIGNED_BYTE);
    208     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,             GL_UNSIGNED_BYTE);
    209 
    210     // From GL_ANGLE_texture_compression_dxt3
    211     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,           GL_UNSIGNED_BYTE);
    212 
    213     // From GL_ANGLE_texture_compression_dxt5
    214     InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,           GL_UNSIGNED_BYTE);
    215 
    216     return set;
    217 }
    218 
    219 static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
    220 {
    221     // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid
    222     // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d)
    223     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
    224     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
    225     {
    226         context->recordError(Error(GL_INVALID_ENUM));
    227         return false;
    228     }
    229 
    230     // The type and format are valid if any supported internal format has that type and format
    231     bool formatSupported = false;
    232     bool typeSupported = false;
    233 
    234     static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
    235     for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
    236     {
    237         if (i->format == format || i->type == type)
    238         {
    239             const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
    240             bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
    241             if (supported && i->type == type)
    242             {
    243                 typeSupported = true;
    244             }
    245             if (supported && i->format == format)
    246             {
    247                 formatSupported = true;
    248             }
    249 
    250             // Early-out if both type and format are supported now
    251             if (typeSupported && formatSupported)
    252             {
    253                 break;
    254             }
    255         }
    256     }
    257 
    258     if (!typeSupported || !formatSupported)
    259     {
    260         context->recordError(Error(GL_INVALID_ENUM));
    261         return false;
    262     }
    263 
    264     // Check if this is a valid format combination to load texture data
    265     ES3FormatCombination searchFormat;
    266     searchFormat.internalFormat = internalFormat;
    267     searchFormat.format = format;
    268     searchFormat.type = type;
    269 
    270     if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
    271     {
    272         context->recordError(Error(GL_INVALID_OPERATION));
    273         return false;
    274     }
    275 
    276     return true;
    277 }
    278 
    279 bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
    280                                    GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
    281                                    GLint border, GLenum format, GLenum type, const GLvoid *pixels)
    282 {
    283     if (!ValidTexture2DDestinationTarget(context, target))
    284     {
    285         context->recordError(Error(GL_INVALID_ENUM));
    286         return false;
    287     }
    288 
    289     // Validate image size
    290     if (!ValidImageSize(context, target, level, width, height, depth))
    291     {
    292         context->recordError(Error(GL_INVALID_VALUE));
    293         return false;
    294     }
    295 
    296     // Verify zero border
    297     if (border != 0)
    298     {
    299         context->recordError(Error(GL_INVALID_VALUE));
    300         return false;
    301     }
    302 
    303     if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
    304         std::numeric_limits<GLsizei>::max() - xoffset < width ||
    305         std::numeric_limits<GLsizei>::max() - yoffset < height ||
    306         std::numeric_limits<GLsizei>::max() - zoffset < depth)
    307     {
    308         context->recordError(Error(GL_INVALID_VALUE));
    309         return false;
    310     }
    311 
    312     const gl::Caps &caps = context->getCaps();
    313 
    314     gl::Texture *texture = NULL;
    315     bool textureCompressed = false;
    316     GLenum textureInternalFormat = GL_NONE;
    317     GLint textureLevelWidth = 0;
    318     GLint textureLevelHeight = 0;
    319     GLint textureLevelDepth = 0;
    320     switch (target)
    321     {
    322       case GL_TEXTURE_2D:
    323         {
    324             if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
    325                 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
    326             {
    327                 context->recordError(Error(GL_INVALID_VALUE));
    328                 return false;
    329             }
    330 
    331             gl::Texture2D *texture2d = context->getTexture2D();
    332             if (texture2d)
    333             {
    334                 textureCompressed = texture2d->isCompressed(level);
    335                 textureInternalFormat = texture2d->getInternalFormat(level);
    336                 textureLevelWidth = texture2d->getWidth(level);
    337                 textureLevelHeight = texture2d->getHeight(level);
    338                 textureLevelDepth = 1;
    339                 texture = texture2d;
    340             }
    341         }
    342         break;
    343 
    344       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    345       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    346       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    347       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    348       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    349       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    350         {
    351             if (!isSubImage && width != height)
    352             {
    353                 context->recordError(Error(GL_INVALID_VALUE));
    354                 return false;
    355             }
    356 
    357             if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
    358             {
    359                 context->recordError(Error(GL_INVALID_VALUE));
    360                 return false;
    361             }
    362 
    363             gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
    364             if (textureCube)
    365             {
    366                 textureCompressed = textureCube->isCompressed(target, level);
    367                 textureInternalFormat = textureCube->getInternalFormat(target, level);
    368                 textureLevelWidth = textureCube->getWidth(target, level);
    369                 textureLevelHeight = textureCube->getHeight(target, level);
    370                 textureLevelDepth = 1;
    371                 texture = textureCube;
    372             }
    373         }
    374         break;
    375 
    376       case GL_TEXTURE_3D:
    377         {
    378             if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
    379                 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
    380                 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
    381             {
    382                 context->recordError(Error(GL_INVALID_VALUE));
    383                 return false;
    384             }
    385 
    386             gl::Texture3D *texture3d = context->getTexture3D();
    387             if (texture3d)
    388             {
    389                 textureCompressed = texture3d->isCompressed(level);
    390                 textureInternalFormat = texture3d->getInternalFormat(level);
    391                 textureLevelWidth = texture3d->getWidth(level);
    392                 textureLevelHeight = texture3d->getHeight(level);
    393                 textureLevelDepth = texture3d->getDepth(level);
    394                 texture = texture3d;
    395             }
    396         }
    397         break;
    398 
    399         case GL_TEXTURE_2D_ARRAY:
    400           {
    401               if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
    402                   static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
    403                   static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
    404               {
    405                   context->recordError(Error(GL_INVALID_VALUE));
    406                   return false;
    407               }
    408 
    409               gl::Texture2DArray *texture2darray = context->getTexture2DArray();
    410               if (texture2darray)
    411               {
    412                   textureCompressed = texture2darray->isCompressed(level);
    413                   textureInternalFormat = texture2darray->getInternalFormat(level);
    414                   textureLevelWidth = texture2darray->getWidth(level);
    415                   textureLevelHeight = texture2darray->getHeight(level);
    416                   textureLevelDepth = texture2darray->getLayers(level);
    417                   texture = texture2darray;
    418               }
    419           }
    420           break;
    421 
    422       default:
    423         context->recordError(Error(GL_INVALID_ENUM));
    424         return false;
    425     }
    426 
    427     if (!texture)
    428     {
    429         context->recordError(Error(GL_INVALID_OPERATION));
    430         return false;
    431     }
    432 
    433     if (texture->isImmutable() && !isSubImage)
    434     {
    435         context->recordError(Error(GL_INVALID_OPERATION));
    436         return false;
    437     }
    438 
    439     // Validate texture formats
    440     GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
    441     const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
    442     if (isCompressed)
    443     {
    444         if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
    445         {
    446             context->recordError(Error(GL_INVALID_OPERATION));
    447             return false;
    448         }
    449 
    450         if (!actualFormatInfo.compressed)
    451         {
    452             context->recordError(Error(GL_INVALID_ENUM));
    453             return false;
    454         }
    455 
    456         if (target == GL_TEXTURE_3D)
    457         {
    458             context->recordError(Error(GL_INVALID_OPERATION));
    459             return false;
    460         }
    461     }
    462     else
    463     {
    464         if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
    465         {
    466             return false;
    467         }
    468 
    469         if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
    470         {
    471             context->recordError(Error(GL_INVALID_OPERATION));
    472             return false;
    473         }
    474     }
    475 
    476     // Validate sub image parameters
    477     if (isSubImage)
    478     {
    479         if (isCompressed != textureCompressed)
    480         {
    481             context->recordError(Error(GL_INVALID_OPERATION));
    482             return false;
    483         }
    484 
    485         if (isCompressed)
    486         {
    487             if ((width % 4 != 0 && width != textureLevelWidth) ||
    488                 (height % 4 != 0 && height != textureLevelHeight))
    489             {
    490                 context->recordError(Error(GL_INVALID_OPERATION));
    491                 return false;
    492             }
    493         }
    494 
    495         if (width == 0 || height == 0 || depth == 0)
    496         {
    497             return false;
    498         }
    499 
    500         if (xoffset < 0 || yoffset < 0 || zoffset < 0)
    501         {
    502             context->recordError(Error(GL_INVALID_VALUE));
    503             return false;
    504         }
    505 
    506         if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
    507             std::numeric_limits<GLsizei>::max() - yoffset < height ||
    508             std::numeric_limits<GLsizei>::max() - zoffset < depth)
    509         {
    510             context->recordError(Error(GL_INVALID_VALUE));
    511             return false;
    512         }
    513 
    514         if (xoffset + width > textureLevelWidth ||
    515             yoffset + height > textureLevelHeight ||
    516             zoffset + depth > textureLevelDepth)
    517         {
    518             context->recordError(Error(GL_INVALID_VALUE));
    519             return false;
    520         }
    521     }
    522 
    523     // Check for pixel unpack buffer related API errors
    524     gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
    525     if (pixelUnpackBuffer != NULL)
    526     {
    527         // ...the data would be unpacked from the buffer object such that the memory reads required
    528         // would exceed the data store size.
    529         size_t widthSize = static_cast<size_t>(width);
    530         size_t heightSize = static_cast<size_t>(height);
    531         size_t depthSize = static_cast<size_t>(depth);
    532         GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
    533 
    534         size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
    535 
    536         if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
    537             !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
    538             !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
    539         {
    540             // Overflow past the end of the buffer
    541             context->recordError(Error(GL_INVALID_OPERATION));
    542             return false;
    543         }
    544 
    545         size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes;
    546         size_t offset = reinterpret_cast<size_t>(pixels);
    547 
    548         if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
    549             ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
    550         {
    551             // Overflow past the end of the buffer
    552             context->recordError(Error(GL_INVALID_OPERATION));
    553             return false;
    554         }
    555 
    556         // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
    557         // indicated by type.
    558         size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
    559 
    560         if ((offset % dataBytesPerPixel) != 0)
    561         {
    562             context->recordError(Error(GL_INVALID_OPERATION));
    563             return false;
    564         }
    565 
    566         // ...the buffer object's data store is currently mapped.
    567         if (pixelUnpackBuffer->isMapped())
    568         {
    569             context->recordError(Error(GL_INVALID_OPERATION));
    570             return false;
    571         }
    572     }
    573 
    574     return true;
    575 }
    576 
    577 struct EffectiveInternalFormatInfo
    578 {
    579     GLenum mEffectiveFormat;
    580     GLenum mDestFormat;
    581     GLuint mMinRedBits;
    582     GLuint mMaxRedBits;
    583     GLuint mMinGreenBits;
    584     GLuint mMaxGreenBits;
    585     GLuint mMinBlueBits;
    586     GLuint mMaxBlueBits;
    587     GLuint mMinAlphaBits;
    588     GLuint mMaxAlphaBits;
    589 
    590     EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
    591                                 GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
    592                                 GLuint minAlphaBits, GLuint maxAlphaBits)
    593         : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
    594           mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
    595           mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
    596           mMaxAlphaBits(maxAlphaBits) {};
    597 };
    598 
    599 typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
    600 
    601 static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
    602 {
    603     EffectiveInternalFormatList list;
    604 
    605     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
    606     //                                                    linear source buffer component sizes.
    607     //                                                                            | Source channel min/max sizes |
    608     //                                         Effective Internal Format |  N/A   |  R   |  G   |  B   |  A      |
    609     list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8));
    610     list.push_back(EffectiveInternalFormatInfo(GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0));
    611     list.push_back(EffectiveInternalFormatInfo(GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0));
    612     list.push_back(EffectiveInternalFormatInfo(GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0));
    613     list.push_back(EffectiveInternalFormatInfo(GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0));
    614     list.push_back(EffectiveInternalFormatInfo(GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4));
    615     list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1));
    616     list.push_back(EffectiveInternalFormatInfo(GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8));
    617     list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
    618 
    619     return list;
    620 }
    621 
    622 static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
    623 {
    624     EffectiveInternalFormatList list;
    625 
    626     // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
    627     //                                                    linear source buffer component sizes.
    628     //                                                                                        |          Source channel min/max sizes            |
    629     //                                         Effective Internal Format |    Dest Format     |     R     |      G     |      B     |      A     |
    630     list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT,              GL_ALPHA,           0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1,        8));
    631     list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT,          GL_LUMINANCE,       1,        8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
    632     list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT,   GL_LUMINANCE_ALPHA, 1,        8, 0, UINT_MAX, 0, UINT_MAX, 1,        8));
    633     list.push_back(EffectiveInternalFormatInfo(GL_RGB565,                  GL_RGB,             1,        5, 1,        6, 1,        5, 0, UINT_MAX));
    634     list.push_back(EffectiveInternalFormatInfo(GL_RGB8,                    GL_RGB,             6,        8, 7,        8, 6,        8, 0, UINT_MAX));
    635     list.push_back(EffectiveInternalFormatInfo(GL_RGBA4,                   GL_RGBA,            1,        4, 1,        4, 1,        4, 1,        4));
    636     list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1,                 GL_RGBA,            5,        5, 5,        5, 5,        5, 1,        1));
    637     list.push_back(EffectiveInternalFormatInfo(GL_RGBA8,                   GL_RGBA,            5,        8, 5,        8, 5,        8, 5,        8));
    638 
    639     return list;
    640 }
    641 
    642 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
    643                                        GLenum *outEffectiveFormat)
    644 {
    645     const EffectiveInternalFormatList *list = NULL;
    646     GLenum targetFormat = GL_NONE;
    647 
    648     if (destFormat.pixelBytes > 0)
    649     {
    650         static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
    651         list = &sizedList;
    652     }
    653     else
    654     {
    655         static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
    656         list = &unsizedList;
    657         targetFormat = destFormat.format;
    658     }
    659 
    660     for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
    661     {
    662         const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
    663         if ((formatInfo.mDestFormat == targetFormat) &&
    664             (formatInfo.mMinRedBits   <= srcFormat.redBits   && formatInfo.mMaxRedBits   >= srcFormat.redBits)   &&
    665             (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
    666             (formatInfo.mMinBlueBits  <= srcFormat.blueBits  && formatInfo.mMaxBlueBits  >= srcFormat.blueBits)  &&
    667             (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
    668         {
    669             *outEffectiveFormat = formatInfo.mEffectiveFormat;
    670             return true;
    671         }
    672     }
    673 
    674     return false;
    675 }
    676 
    677 struct CopyConversion
    678 {
    679     GLenum mTextureFormat;
    680     GLenum mFramebufferFormat;
    681 
    682     CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
    683         : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
    684 
    685     bool operator<(const CopyConversion& other) const
    686     {
    687         return memcmp(this, &other, sizeof(CopyConversion)) < 0;
    688     }
    689 };
    690 
    691 typedef std::set<CopyConversion> CopyConversionSet;
    692 
    693 static CopyConversionSet BuildValidES3CopyTexImageCombinations()
    694 {
    695     CopyConversionSet set;
    696 
    697     // From ES 3.0.1 spec, table 3.15
    698     set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
    699     set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
    700     set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
    701     set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
    702     set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
    703     set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
    704     set.insert(CopyConversion(GL_RED, GL_RED));
    705     set.insert(CopyConversion(GL_RED, GL_RG));
    706     set.insert(CopyConversion(GL_RED, GL_RGB));
    707     set.insert(CopyConversion(GL_RED, GL_RGBA));
    708     set.insert(CopyConversion(GL_RG, GL_RG));
    709     set.insert(CopyConversion(GL_RG, GL_RGB));
    710     set.insert(CopyConversion(GL_RG, GL_RGBA));
    711     set.insert(CopyConversion(GL_RGB, GL_RGB));
    712     set.insert(CopyConversion(GL_RGB, GL_RGBA));
    713     set.insert(CopyConversion(GL_RGBA, GL_RGBA));
    714 
    715     // Necessary for ANGLE back-buffers
    716     set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
    717     set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
    718     set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
    719     set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
    720     set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
    721     set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
    722     set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
    723 
    724     set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
    725     set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
    726     set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
    727     set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
    728     set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
    729     set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
    730     set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
    731     set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
    732     set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
    733     set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
    734 
    735     return set;
    736 }
    737 
    738 static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
    739 {
    740     const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
    741     const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
    742 
    743     static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
    744     if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
    745     {
    746         // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
    747         // must both be signed, unsigned, or fixed point and both source and destinations
    748         // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
    749         // conversion between fixed and floating point.
    750 
    751         if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
    752         {
    753             return false;
    754         }
    755 
    756         if (((textureInternalFormatInfo.componentType == GL_INT)          != (framebufferInternalFormatInfo.componentType == GL_INT         )) ||
    757             ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
    758         {
    759             return false;
    760         }
    761 
    762         if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
    763              textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
    764              textureInternalFormatInfo.componentType == GL_FLOAT) &&
    765             !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
    766               framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
    767               framebufferInternalFormatInfo.componentType == GL_FLOAT))
    768         {
    769             return false;
    770         }
    771 
    772         // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
    773         // The effective internal format of the source buffer is determined with the following rules applied in order:
    774         //    * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
    775         //      effective internal format is the source buffer's sized internal format.
    776         //    * If the source buffer is a texture that was created with an unsized base internal format, then the
    777         //      effective internal format is the source image array's effective internal format, as specified by table
    778         //      3.12, which is determined from the <format> and <type> that were used when the source image array was
    779         //      specified by TexImage*.
    780         //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
    781         //      Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
    782         //      with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
    783         //      FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
    784         //      is SRGB.
    785         const InternalFormat *sourceEffectiveFormat = NULL;
    786         if (readBufferHandle != 0)
    787         {
    788             // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
    789             if (framebufferInternalFormatInfo.pixelBytes > 0)
    790             {
    791                 sourceEffectiveFormat = &framebufferInternalFormatInfo;
    792             }
    793             else
    794             {
    795                 // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
    796                 // texture. We can use the same table we use when creating textures to get its effective sized format.
    797                 const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
    798                 sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat);
    799             }
    800         }
    801         else
    802         {
    803             // The effective internal format must be derived from the source framebuffer's channel sizes.
    804             // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
    805             if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
    806             {
    807                 GLenum effectiveFormat;
    808                 if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
    809                 {
    810                     sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
    811                 }
    812                 else
    813                 {
    814                     return false;
    815                 }
    816             }
    817             else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
    818             {
    819                 // SRGB buffers can only be copied to sized format destinations according to table 3.18
    820                 if ((textureInternalFormatInfo.pixelBytes > 0) &&
    821                     (framebufferInternalFormatInfo.redBits   >= 1 && framebufferInternalFormatInfo.redBits   <= 8) &&
    822                     (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
    823                     (framebufferInternalFormatInfo.blueBits  >= 1 && framebufferInternalFormatInfo.blueBits  <= 8) &&
    824                     (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
    825                 {
    826                     sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
    827                 }
    828                 else
    829                 {
    830                     return false;
    831                 }
    832             }
    833             else
    834             {
    835                 UNREACHABLE();
    836                 return false;
    837             }
    838         }
    839 
    840         if (textureInternalFormatInfo.pixelBytes > 0)
    841         {
    842             // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
    843             // component sizes of the source and destination formats must exactly match
    844             if (textureInternalFormatInfo.redBits   != sourceEffectiveFormat->redBits   ||
    845                 textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
    846                 textureInternalFormatInfo.blueBits  != sourceEffectiveFormat->blueBits  ||
    847                 textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
    848             {
    849                 return false;
    850             }
    851         }
    852 
    853 
    854         return true; // A conversion function exists, and no rule in the specification has precluded conversion
    855                      // between these formats.
    856     }
    857 
    858     return false;
    859 }
    860 
    861 bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat,
    862                                        bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset,
    863                                        GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
    864 {
    865     GLenum textureInternalFormat;
    866     if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
    867                                             xoffset, yoffset, zoffset, x, y, width, height,
    868                                             border, &textureInternalFormat))
    869     {
    870         return false;
    871     }
    872 
    873     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
    874 
    875     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
    876     {
    877         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
    878         return false;
    879     }
    880 
    881     if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
    882     {
    883         context->recordError(Error(GL_INVALID_OPERATION));
    884         return false;
    885     }
    886 
    887     gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
    888     GLenum colorbufferInternalFormat = source->getInternalFormat();
    889 
    890     if (isSubImage)
    891     {
    892         if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
    893                                                context->getState().getReadFramebuffer()->id()))
    894         {
    895             context->recordError(Error(GL_INVALID_OPERATION));
    896             return false;
    897         }
    898     }
    899     else
    900     {
    901         if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
    902                                                 context->getState().getReadFramebuffer()->id()))
    903         {
    904             context->recordError(Error(GL_INVALID_OPERATION));
    905             return false;
    906         }
    907     }
    908 
    909     // If width or height is zero, it is a no-op.  Return false without setting an error.
    910     return (width > 0 && height > 0);
    911 }
    912 
    913 bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
    914                                      GLsizei width, GLsizei height, GLsizei depth)
    915 {
    916     if (width < 1 || height < 1 || depth < 1 || levels < 1)
    917     {
    918         context->recordError(Error(GL_INVALID_VALUE));
    919         return false;
    920     }
    921 
    922     if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1)
    923     {
    924         context->recordError(Error(GL_INVALID_OPERATION));
    925         return false;
    926     }
    927 
    928     const gl::Caps &caps = context->getCaps();
    929 
    930     gl::Texture *texture = NULL;
    931     switch (target)
    932     {
    933       case GL_TEXTURE_2D:
    934         {
    935             texture = context->getTexture2D();
    936 
    937             if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
    938                 static_cast<GLuint>(height) > caps.max2DTextureSize)
    939             {
    940                 context->recordError(Error(GL_INVALID_VALUE));
    941                 return false;
    942             }
    943         }
    944         break;
    945 
    946       case GL_TEXTURE_CUBE_MAP:
    947         {
    948             texture = context->getTextureCubeMap();
    949 
    950             if (width != height)
    951             {
    952                 context->recordError(Error(GL_INVALID_VALUE));
    953                 return false;
    954             }
    955 
    956             if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
    957             {
    958                 context->recordError(Error(GL_INVALID_VALUE));
    959                 return false;
    960             }
    961         }
    962         break;
    963 
    964       case GL_TEXTURE_3D:
    965         {
    966             texture = context->getTexture3D();
    967 
    968             if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
    969                 static_cast<GLuint>(height) > caps.max3DTextureSize ||
    970                 static_cast<GLuint>(depth) > caps.max3DTextureSize)
    971             {
    972                 context->recordError(Error(GL_INVALID_VALUE));
    973                 return false;
    974             }
    975         }
    976         break;
    977 
    978       case GL_TEXTURE_2D_ARRAY:
    979         {
    980             texture = context->getTexture2DArray();
    981 
    982             if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
    983                 static_cast<GLuint>(height) > caps.max2DTextureSize ||
    984                 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
    985             {
    986                 context->recordError(Error(GL_INVALID_VALUE));
    987                 return false;
    988             }
    989         }
    990         break;
    991 
    992       default:
    993         context->recordError(Error(GL_INVALID_ENUM));
    994         return false;
    995     }
    996 
    997     if (!texture || texture->id() == 0)
    998     {
    999         context->recordError(Error(GL_INVALID_OPERATION));
   1000         return false;
   1001     }
   1002 
   1003     if (texture->isImmutable())
   1004     {
   1005         context->recordError(Error(GL_INVALID_OPERATION));
   1006         return false;
   1007     }
   1008 
   1009     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
   1010     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
   1011     {
   1012         context->recordError(Error(GL_INVALID_ENUM));
   1013         return false;
   1014     }
   1015 
   1016     if (formatInfo.pixelBytes == 0)
   1017     {
   1018         context->recordError(Error(GL_INVALID_ENUM));
   1019         return false;
   1020     }
   1021 
   1022     return true;
   1023 }
   1024 
   1025 bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
   1026                                      GLuint texture, GLint level, GLint layer)
   1027 {
   1028     if (context->getClientVersion() < 3)
   1029     {
   1030         context->recordError(Error(GL_INVALID_OPERATION));
   1031         return false;
   1032     }
   1033 
   1034     if (layer < 0)
   1035     {
   1036         context->recordError(Error(GL_INVALID_VALUE));
   1037         return false;
   1038     }
   1039 
   1040     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
   1041     {
   1042         return false;
   1043     }
   1044 
   1045     const gl::Caps &caps = context->getCaps();
   1046     if (texture != 0)
   1047     {
   1048         gl::Texture *tex = context->getTexture(texture);
   1049         ASSERT(tex);
   1050 
   1051         switch (tex->getTarget())
   1052         {
   1053           case GL_TEXTURE_2D_ARRAY:
   1054             {
   1055                 if (level > gl::log2(caps.max2DTextureSize))
   1056                 {
   1057                     context->recordError(Error(GL_INVALID_VALUE));
   1058                     return false;
   1059                 }
   1060 
   1061                 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
   1062                 {
   1063                     context->recordError(Error(GL_INVALID_VALUE));
   1064                     return false;
   1065                 }
   1066 
   1067                 gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
   1068                 if (texArray->isCompressed(level))
   1069                 {
   1070                     context->recordError(Error(GL_INVALID_OPERATION));
   1071                     return false;
   1072                 }
   1073             }
   1074             break;
   1075 
   1076           case GL_TEXTURE_3D:
   1077             {
   1078                 if (level > gl::log2(caps.max3DTextureSize))
   1079                 {
   1080                     context->recordError(Error(GL_INVALID_VALUE));
   1081                     return false;
   1082                 }
   1083 
   1084                 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
   1085                 {
   1086                     context->recordError(Error(GL_INVALID_VALUE));
   1087                     return false;
   1088                 }
   1089 
   1090                 gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
   1091                 if (tex3d->isCompressed(level))
   1092                 {
   1093                     context->recordError(Error(GL_INVALID_OPERATION));
   1094                     return false;
   1095                 }
   1096             }
   1097             break;
   1098 
   1099           default:
   1100             context->recordError(Error(GL_INVALID_OPERATION));
   1101             return false;
   1102         }
   1103     }
   1104 
   1105     return true;
   1106 }
   1107 
   1108 bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
   1109 {
   1110     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
   1111 
   1112     switch (format)
   1113     {
   1114       case GL_RGBA:
   1115         switch (type)
   1116         {
   1117           case GL_UNSIGNED_BYTE:
   1118             break;
   1119           case GL_UNSIGNED_INT_2_10_10_10_REV:
   1120             if (internalFormat != GL_RGB10_A2)
   1121             {
   1122                 return false;
   1123             }
   1124             break;
   1125           case GL_FLOAT:
   1126             if (internalFormatInfo.componentType != GL_FLOAT)
   1127             {
   1128                 return false;
   1129             }
   1130             break;
   1131           default:
   1132             return false;
   1133         }
   1134         break;
   1135       case GL_RGBA_INTEGER:
   1136         switch (type)
   1137         {
   1138           case GL_INT:
   1139             if (internalFormatInfo.componentType != GL_INT)
   1140             {
   1141                 return false;
   1142             }
   1143             break;
   1144           case GL_UNSIGNED_INT:
   1145             if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
   1146             {
   1147                 return false;
   1148             }
   1149             break;
   1150           default:
   1151             return false;
   1152         }
   1153         break;
   1154       case GL_BGRA_EXT:
   1155         switch (type)
   1156         {
   1157           case GL_UNSIGNED_BYTE:
   1158           case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
   1159           case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
   1160             break;
   1161           default:
   1162             return false;
   1163         }
   1164         break;
   1165       case GL_RG_EXT:
   1166       case GL_RED_EXT:
   1167         if (!context->getExtensions().textureRG)
   1168         {
   1169             return false;
   1170         }
   1171         switch (type)
   1172         {
   1173         case GL_UNSIGNED_BYTE:
   1174             break;
   1175         default:
   1176             return false;
   1177         }
   1178         break;
   1179       default:
   1180         return false;
   1181     }
   1182     return true;
   1183 }
   1184 
   1185 bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
   1186                                              const GLenum* attachments)
   1187 {
   1188     bool defaultFramebuffer = false;
   1189 
   1190     switch (target)
   1191     {
   1192       case GL_DRAW_FRAMEBUFFER:
   1193       case GL_FRAMEBUFFER:
   1194         defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
   1195         break;
   1196       case GL_READ_FRAMEBUFFER:
   1197         defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
   1198         break;
   1199       default:
   1200           context->recordError(Error(GL_INVALID_ENUM));
   1201           return false;
   1202     }
   1203 
   1204     for (int i = 0; i < numAttachments; ++i)
   1205     {
   1206         if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
   1207         {
   1208             if (defaultFramebuffer)
   1209             {
   1210                 context->recordError(Error(GL_INVALID_ENUM));
   1211                 return false;
   1212             }
   1213 
   1214             if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
   1215             {
   1216                 context->recordError(Error(GL_INVALID_OPERATION));
   1217                 return false;
   1218             }
   1219         }
   1220         else
   1221         {
   1222             switch (attachments[i])
   1223             {
   1224               case GL_DEPTH_ATTACHMENT:
   1225               case GL_STENCIL_ATTACHMENT:
   1226               case GL_DEPTH_STENCIL_ATTACHMENT:
   1227                 if (defaultFramebuffer)
   1228                 {
   1229                     context->recordError(Error(GL_INVALID_ENUM));
   1230                     return false;
   1231                 }
   1232                 break;
   1233               case GL_COLOR:
   1234               case GL_DEPTH:
   1235               case GL_STENCIL:
   1236                 if (!defaultFramebuffer)
   1237                 {
   1238                     context->recordError(Error(GL_INVALID_ENUM));
   1239                     return false;
   1240                 }
   1241                 break;
   1242               default:
   1243                 context->recordError(Error(GL_INVALID_ENUM));
   1244                 return false;
   1245             }
   1246         }
   1247     }
   1248 
   1249     return true;
   1250 }
   1251 
   1252 bool ValidateClearBuffer(Context *context)
   1253 {
   1254     if (context->getClientVersion() < 3)
   1255     {
   1256         context->recordError(Error(GL_INVALID_OPERATION));
   1257         return false;
   1258     }
   1259 
   1260     const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
   1261     if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
   1262     {
   1263         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
   1264         return false;
   1265     }
   1266 
   1267     return true;
   1268 }
   1269 
   1270 bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
   1271 {
   1272     if (context->getClientVersion() < 3)
   1273     {
   1274         context->recordError(Error(GL_INVALID_OPERATION));
   1275         return false;
   1276     }
   1277 
   1278     return ValidateGetUniformBase(context, program, location);
   1279 }
   1280 
   1281 }
   1282