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 // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
      8 
      9 #include "libGLESv2/validationES2.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 #include "common/utilities.h"
     21 
     22 namespace gl
     23 {
     24 
     25 static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height,
     26                                      GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
     27                                      gl::Texture2D *texture)
     28 {
     29     if (!texture)
     30     {
     31         context->recordError(Error(GL_INVALID_OPERATION));
     32         return false;
     33     }
     34 
     35     if (compressed != texture->isCompressed(level))
     36     {
     37         context->recordError(Error(GL_INVALID_OPERATION));
     38         return false;
     39     }
     40 
     41     if (format != GL_NONE)
     42     {
     43         if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
     44         {
     45             context->recordError(Error(GL_INVALID_OPERATION));
     46             return false;
     47         }
     48     }
     49 
     50     if (compressed)
     51     {
     52         if ((width % 4 != 0 && width != texture->getWidth(level)) ||
     53             (height % 4 != 0 && height != texture->getHeight(level)))
     54         {
     55             context->recordError(Error(GL_INVALID_OPERATION));
     56             return false;
     57         }
     58     }
     59 
     60     if (xoffset + width > texture->getWidth(level) ||
     61         yoffset + height > texture->getHeight(level))
     62     {
     63         context->recordError(Error(GL_INVALID_VALUE));
     64         return false;
     65     }
     66 
     67     return true;
     68 }
     69 
     70 static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height,
     71                                        GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
     72                                        gl::TextureCubeMap *texture)
     73 {
     74     if (!texture)
     75     {
     76         context->recordError(Error(GL_INVALID_OPERATION));
     77         return false;
     78     }
     79 
     80     if (compressed != texture->isCompressed(target, level))
     81     {
     82         context->recordError(Error(GL_INVALID_OPERATION));
     83         return false;
     84     }
     85 
     86     if (format != GL_NONE)
     87     {
     88         if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
     89         {
     90             context->recordError(Error(GL_INVALID_OPERATION));
     91             return false;
     92         }
     93     }
     94 
     95     if (compressed)
     96     {
     97         if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
     98             (height % 4 != 0 && height != texture->getHeight(target, 0)))
     99         {
    100             context->recordError(Error(GL_INVALID_OPERATION));
    101             return false;
    102         }
    103     }
    104 
    105     if (xoffset + width > texture->getWidth(target, level) ||
    106         yoffset + height > texture->getHeight(target, level))
    107     {
    108         context->recordError(Error(GL_INVALID_VALUE));
    109         return false;
    110     }
    111 
    112     return true;
    113 }
    114 
    115 bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
    116                                    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
    117                                    GLint border, GLenum format, GLenum type, const GLvoid *pixels)
    118 {
    119     if (!ValidTexture2DDestinationTarget(context, target))
    120     {
    121         context->recordError(Error(GL_INVALID_ENUM));
    122         return false;
    123     }
    124 
    125     if (!ValidImageSize(context, target, level, width, height, 1))
    126     {
    127         context->recordError(Error(GL_INVALID_VALUE));
    128         return false;
    129     }
    130 
    131     if (level < 0 || xoffset < 0 ||
    132         std::numeric_limits<GLsizei>::max() - xoffset < width ||
    133         std::numeric_limits<GLsizei>::max() - yoffset < height)
    134     {
    135         context->recordError(Error(GL_INVALID_VALUE));
    136         return false;
    137     }
    138 
    139     if (!isSubImage && !isCompressed && internalformat != format)
    140     {
    141         context->recordError(Error(GL_INVALID_OPERATION));
    142         return false;
    143     }
    144 
    145     const gl::Caps &caps = context->getCaps();
    146 
    147     gl::Texture *texture = NULL;
    148     bool textureCompressed = false;
    149     GLenum textureInternalFormat = GL_NONE;
    150     GLint textureLevelWidth = 0;
    151     GLint textureLevelHeight = 0;
    152     switch (target)
    153     {
    154       case GL_TEXTURE_2D:
    155         {
    156             if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
    157                 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
    158             {
    159                 context->recordError(Error(GL_INVALID_VALUE));
    160                 return false;
    161             }
    162 
    163             gl::Texture2D *tex2d = context->getTexture2D();
    164             if (tex2d)
    165             {
    166                 textureCompressed = tex2d->isCompressed(level);
    167                 textureInternalFormat = tex2d->getInternalFormat(level);
    168                 textureLevelWidth = tex2d->getWidth(level);
    169                 textureLevelHeight = tex2d->getHeight(level);
    170                 texture = tex2d;
    171             }
    172 
    173             if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
    174                                                         level, format, type, tex2d))
    175             {
    176                 return false;
    177             }
    178 
    179             texture = tex2d;
    180         }
    181         break;
    182 
    183       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    184       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    185       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    186       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    187       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    188       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
    189         {
    190             if (!isSubImage && width != height)
    191             {
    192                 context->recordError(Error(GL_INVALID_VALUE));
    193                 return false;
    194             }
    195 
    196             if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
    197                 static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
    198             {
    199                 context->recordError(Error(GL_INVALID_VALUE));
    200                 return false;
    201             }
    202 
    203             gl::TextureCubeMap *texCube = context->getTextureCubeMap();
    204             if (texCube)
    205             {
    206                 textureCompressed = texCube->isCompressed(target, level);
    207                 textureInternalFormat = texCube->getInternalFormat(target, level);
    208                 textureLevelWidth = texCube->getWidth(target, level);
    209                 textureLevelHeight = texCube->getHeight(target, level);
    210                 texture = texCube;
    211             }
    212 
    213             if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
    214                                                           target, level, format, type, texCube))
    215             {
    216                 return false;
    217             }
    218         }
    219         break;
    220 
    221       default:
    222         context->recordError(Error(GL_INVALID_ENUM));
    223         return false;
    224     }
    225 
    226     if (!texture)
    227     {
    228         context->recordError(Error(GL_INVALID_OPERATION));
    229         return false;
    230     }
    231 
    232     if (!isSubImage && texture->isImmutable())
    233     {
    234         context->recordError(Error(GL_INVALID_OPERATION));
    235         return false;
    236     }
    237 
    238     // Verify zero border
    239     if (border != 0)
    240     {
    241         context->recordError(Error(GL_INVALID_VALUE));
    242         return false;
    243     }
    244 
    245     GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
    246     if (isCompressed)
    247     {
    248         if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
    249         {
    250             context->recordError(Error(GL_INVALID_OPERATION));
    251             return false;
    252         }
    253 
    254         switch (actualInternalFormat)
    255         {
    256           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    257           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    258             if (!context->getExtensions().textureCompressionDXT1)
    259             {
    260                 context->recordError(Error(GL_INVALID_ENUM));
    261                 return false;
    262             }
    263             break;
    264           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
    265             if (!context->getExtensions().textureCompressionDXT1)
    266             {
    267                 context->recordError(Error(GL_INVALID_ENUM));
    268                 return false;
    269             }
    270             break;
    271           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
    272             if (!context->getExtensions().textureCompressionDXT5)
    273             {
    274                 context->recordError(Error(GL_INVALID_ENUM));
    275                 return false;
    276             }
    277             break;
    278           default:
    279             context->recordError(Error(GL_INVALID_ENUM));
    280             return false;
    281         }
    282     }
    283     else
    284     {
    285         // validate <type> by itself (used as secondary key below)
    286         switch (type)
    287         {
    288           case GL_UNSIGNED_BYTE:
    289           case GL_UNSIGNED_SHORT_5_6_5:
    290           case GL_UNSIGNED_SHORT_4_4_4_4:
    291           case GL_UNSIGNED_SHORT_5_5_5_1:
    292           case GL_UNSIGNED_SHORT:
    293           case GL_UNSIGNED_INT:
    294           case GL_UNSIGNED_INT_24_8_OES:
    295           case GL_HALF_FLOAT_OES:
    296           case GL_FLOAT:
    297             break;
    298           default:
    299             context->recordError(Error(GL_INVALID_ENUM));
    300             return false;
    301         }
    302 
    303         // validate <format> + <type> combinations
    304         // - invalid <format> -> sets INVALID_ENUM
    305         // - invalid <format>+<type> combination -> sets INVALID_OPERATION
    306         switch (format)
    307         {
    308           case GL_ALPHA:
    309           case GL_LUMINANCE:
    310           case GL_LUMINANCE_ALPHA:
    311             switch (type)
    312             {
    313               case GL_UNSIGNED_BYTE:
    314               case GL_FLOAT:
    315               case GL_HALF_FLOAT_OES:
    316                 break;
    317               default:
    318                   context->recordError(Error(GL_INVALID_OPERATION));
    319                   return false;
    320             }
    321             break;
    322           case GL_RED:
    323           case GL_RG:
    324               if (!context->getExtensions().textureRG)
    325               {
    326                   context->recordError(Error(GL_INVALID_ENUM));
    327                   return false;
    328               }
    329               switch (type)
    330               {
    331                 case GL_UNSIGNED_BYTE:
    332                 case GL_FLOAT:
    333                 case GL_HALF_FLOAT_OES:
    334                   break;
    335                 default:
    336                   context->recordError(Error(GL_INVALID_OPERATION));
    337                   return false;
    338               }
    339               break;
    340           case GL_RGB:
    341             switch (type)
    342             {
    343               case GL_UNSIGNED_BYTE:
    344               case GL_UNSIGNED_SHORT_5_6_5:
    345               case GL_FLOAT:
    346               case GL_HALF_FLOAT_OES:
    347                 break;
    348               default:
    349                 context->recordError(Error(GL_INVALID_OPERATION));
    350                 return false;
    351             }
    352             break;
    353           case GL_RGBA:
    354             switch (type)
    355             {
    356               case GL_UNSIGNED_BYTE:
    357               case GL_UNSIGNED_SHORT_4_4_4_4:
    358               case GL_UNSIGNED_SHORT_5_5_5_1:
    359               case GL_FLOAT:
    360               case GL_HALF_FLOAT_OES:
    361                 break;
    362               default:
    363                 context->recordError(Error(GL_INVALID_OPERATION));
    364                 return false;
    365             }
    366             break;
    367           case GL_BGRA_EXT:
    368             switch (type)
    369             {
    370               case GL_UNSIGNED_BYTE:
    371                 break;
    372               default:
    373                 context->recordError(Error(GL_INVALID_OPERATION));
    374                 return false;
    375             }
    376             break;
    377           case GL_SRGB_EXT:
    378           case GL_SRGB_ALPHA_EXT:
    379             if (!context->getExtensions().sRGB)
    380             {
    381                 context->recordError(Error(GL_INVALID_ENUM));
    382                 return false;
    383             }
    384             switch (type)
    385             {
    386               case GL_UNSIGNED_BYTE:
    387                 break;
    388               default:
    389                 context->recordError(Error(GL_INVALID_OPERATION));
    390                 return false;
    391             }
    392             break;
    393           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:  // error cases for compressed textures are handled below
    394           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    395           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
    396           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
    397             break;
    398           case GL_DEPTH_COMPONENT:
    399             switch (type)
    400             {
    401               case GL_UNSIGNED_SHORT:
    402               case GL_UNSIGNED_INT:
    403                 break;
    404               default:
    405                 context->recordError(Error(GL_INVALID_OPERATION));
    406                 return false;
    407             }
    408             break;
    409           case GL_DEPTH_STENCIL_OES:
    410             switch (type)
    411             {
    412               case GL_UNSIGNED_INT_24_8_OES:
    413                 break;
    414               default:
    415                 context->recordError(Error(GL_INVALID_OPERATION));
    416                 return false;
    417             }
    418             break;
    419           default:
    420             context->recordError(Error(GL_INVALID_ENUM));
    421             return false;
    422         }
    423 
    424         switch (format)
    425         {
    426           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    427           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    428             if (context->getExtensions().textureCompressionDXT1)
    429             {
    430                 context->recordError(Error(GL_INVALID_OPERATION));
    431                 return false;
    432             }
    433             else
    434             {
    435                 context->recordError(Error(GL_INVALID_ENUM));
    436                 return false;
    437             }
    438             break;
    439           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
    440             if (context->getExtensions().textureCompressionDXT3)
    441             {
    442                 context->recordError(Error(GL_INVALID_OPERATION));
    443                 return false;
    444             }
    445             else
    446             {
    447                 context->recordError(Error(GL_INVALID_ENUM));
    448                 return false;
    449             }
    450             break;
    451           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
    452             if (context->getExtensions().textureCompressionDXT5)
    453             {
    454                 context->recordError(Error(GL_INVALID_OPERATION));
    455                 return false;
    456             }
    457             else
    458             {
    459                 context->recordError(Error(GL_INVALID_ENUM));
    460                 return false;
    461             }
    462             break;
    463           case GL_DEPTH_COMPONENT:
    464           case GL_DEPTH_STENCIL_OES:
    465             if (!context->getExtensions().depthTextures)
    466             {
    467                 context->recordError(Error(GL_INVALID_VALUE));
    468                 return false;
    469             }
    470             if (target != GL_TEXTURE_2D)
    471             {
    472                 context->recordError(Error(GL_INVALID_OPERATION));
    473                 return false;
    474             }
    475             // OES_depth_texture supports loading depth data and multiple levels,
    476             // but ANGLE_depth_texture does not
    477             if (pixels != NULL || level != 0)
    478             {
    479                 context->recordError(Error(GL_INVALID_OPERATION));
    480                 return false;
    481             }
    482             break;
    483           default:
    484             break;
    485         }
    486 
    487         if (type == GL_FLOAT)
    488         {
    489             if (!context->getExtensions().textureFloat)
    490             {
    491                 context->recordError(Error(GL_INVALID_ENUM));
    492                 return false;
    493             }
    494         }
    495         else if (type == GL_HALF_FLOAT_OES)
    496         {
    497             if (!context->getExtensions().textureHalfFloat)
    498             {
    499                 context->recordError(Error(GL_INVALID_ENUM));
    500                 return false;
    501             }
    502         }
    503     }
    504 
    505     return true;
    506 }
    507 
    508 
    509 
    510 bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
    511                                        GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
    512                                        GLint border)
    513 {
    514     GLenum textureInternalFormat = GL_NONE;
    515 
    516     if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
    517                                             xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
    518     {
    519         return false;
    520     }
    521 
    522     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
    523     GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
    524     GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format;
    525 
    526     // [OpenGL ES 2.0.24] table 3.9
    527     if (isSubImage)
    528     {
    529         switch (textureFormat)
    530         {
    531           case GL_ALPHA:
    532             if (colorbufferFormat != GL_ALPHA8_EXT &&
    533                 colorbufferFormat != GL_RGBA4 &&
    534                 colorbufferFormat != GL_RGB5_A1 &&
    535                 colorbufferFormat != GL_RGBA8_OES)
    536             {
    537                 context->recordError(Error(GL_INVALID_OPERATION));
    538                 return false;
    539             }
    540             break;
    541           case GL_LUMINANCE:
    542               if (colorbufferFormat != GL_R8_EXT &&
    543                   colorbufferFormat != GL_RG8_EXT &&
    544                   colorbufferFormat != GL_RGB565 &&
    545                   colorbufferFormat != GL_RGB8_OES &&
    546                   colorbufferFormat != GL_RGBA4 &&
    547                   colorbufferFormat != GL_RGB5_A1 &&
    548                   colorbufferFormat != GL_RGBA8_OES)
    549               {
    550                   context->recordError(Error(GL_INVALID_OPERATION));
    551                   return false;
    552               }
    553               break;
    554           case GL_RED_EXT:
    555               if (colorbufferFormat != GL_R8_EXT &&
    556                   colorbufferFormat != GL_RG8_EXT &&
    557                   colorbufferFormat != GL_RGB565 &&
    558                   colorbufferFormat != GL_RGB8_OES &&
    559                   colorbufferFormat != GL_RGBA4 &&
    560                   colorbufferFormat != GL_RGB5_A1 &&
    561                   colorbufferFormat != GL_RGBA8_OES)
    562               {
    563                   context->recordError(Error(GL_INVALID_OPERATION));
    564                   return false;
    565               }
    566               break;
    567           case GL_RG_EXT:
    568               if (colorbufferFormat != GL_RG8_EXT &&
    569                   colorbufferFormat != GL_RGB565 &&
    570                   colorbufferFormat != GL_RGB8_OES &&
    571                   colorbufferFormat != GL_RGBA4 &&
    572                   colorbufferFormat != GL_RGB5_A1 &&
    573                   colorbufferFormat != GL_RGBA8_OES)
    574               {
    575                   context->recordError(Error(GL_INVALID_OPERATION));
    576                   return false;
    577               }
    578               break;
    579           case GL_RGB:
    580             if (colorbufferFormat != GL_RGB565 &&
    581                 colorbufferFormat != GL_RGB8_OES &&
    582                 colorbufferFormat != GL_RGBA4 &&
    583                 colorbufferFormat != GL_RGB5_A1 &&
    584                 colorbufferFormat != GL_RGBA8_OES)
    585             {
    586                 context->recordError(Error(GL_INVALID_OPERATION));
    587                 return false;
    588             }
    589             break;
    590           case GL_LUMINANCE_ALPHA:
    591           case GL_RGBA:
    592             if (colorbufferFormat != GL_RGBA4 &&
    593                 colorbufferFormat != GL_RGB5_A1 &&
    594                 colorbufferFormat != GL_RGBA8_OES)
    595             {
    596                 context->recordError(Error(GL_INVALID_OPERATION));
    597                 return false;
    598             }
    599             break;
    600           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    601           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    602           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
    603           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
    604             context->recordError(Error(GL_INVALID_OPERATION));
    605             return false;
    606           case GL_DEPTH_COMPONENT:
    607           case GL_DEPTH_STENCIL_OES:
    608             context->recordError(Error(GL_INVALID_OPERATION));
    609             return false;
    610           default:
    611             context->recordError(Error(GL_INVALID_OPERATION));
    612             return false;
    613         }
    614     }
    615     else
    616     {
    617         switch (internalformat)
    618         {
    619           case GL_ALPHA:
    620             if (colorbufferFormat != GL_ALPHA8_EXT &&
    621                 colorbufferFormat != GL_RGBA4 &&
    622                 colorbufferFormat != GL_RGB5_A1 &&
    623                 colorbufferFormat != GL_BGRA8_EXT &&
    624                 colorbufferFormat != GL_RGBA8_OES)
    625             {
    626                 context->recordError(Error(GL_INVALID_OPERATION));
    627                 return false;
    628             }
    629             break;
    630           case GL_LUMINANCE:
    631               if (colorbufferFormat != GL_R8_EXT &&
    632                   colorbufferFormat != GL_RG8_EXT &&
    633                   colorbufferFormat != GL_RGB565 &&
    634                   colorbufferFormat != GL_RGB8_OES &&
    635                   colorbufferFormat != GL_RGBA4 &&
    636                   colorbufferFormat != GL_RGB5_A1 &&
    637                   colorbufferFormat != GL_BGRA8_EXT &&
    638                   colorbufferFormat != GL_RGBA8_OES)
    639               {
    640                   context->recordError(Error(GL_INVALID_OPERATION));
    641                   return false;
    642               }
    643               break;
    644           case GL_RED_EXT:
    645               if (colorbufferFormat != GL_R8_EXT &&
    646                   colorbufferFormat != GL_RG8_EXT &&
    647                   colorbufferFormat != GL_RGB565 &&
    648                   colorbufferFormat != GL_RGB8_OES &&
    649                   colorbufferFormat != GL_RGBA4 &&
    650                   colorbufferFormat != GL_RGB5_A1 &&
    651                   colorbufferFormat != GL_BGRA8_EXT &&
    652                   colorbufferFormat != GL_RGBA8_OES)
    653               {
    654                   context->recordError(Error(GL_INVALID_OPERATION));
    655                   return false;
    656               }
    657               break;
    658           case GL_RG_EXT:
    659               if (colorbufferFormat != GL_RG8_EXT &&
    660                   colorbufferFormat != GL_RGB565 &&
    661                   colorbufferFormat != GL_RGB8_OES &&
    662                   colorbufferFormat != GL_RGBA4 &&
    663                   colorbufferFormat != GL_RGB5_A1 &&
    664                   colorbufferFormat != GL_BGRA8_EXT &&
    665                   colorbufferFormat != GL_RGBA8_OES)
    666               {
    667                   context->recordError(Error(GL_INVALID_OPERATION));
    668                   return false;
    669               }
    670               break;
    671           case GL_RGB:
    672             if (colorbufferFormat != GL_RGB565 &&
    673                 colorbufferFormat != GL_RGB8_OES &&
    674                 colorbufferFormat != GL_RGBA4 &&
    675                 colorbufferFormat != GL_RGB5_A1 &&
    676                 colorbufferFormat != GL_BGRA8_EXT &&
    677                 colorbufferFormat != GL_RGBA8_OES)
    678             {
    679                 context->recordError(Error(GL_INVALID_OPERATION));
    680                 return false;
    681             }
    682             break;
    683           case GL_LUMINANCE_ALPHA:
    684           case GL_RGBA:
    685             if (colorbufferFormat != GL_RGBA4 &&
    686                 colorbufferFormat != GL_RGB5_A1 &&
    687                 colorbufferFormat != GL_BGRA8_EXT &&
    688                 colorbufferFormat != GL_RGBA8_OES)
    689             {
    690                 context->recordError(Error(GL_INVALID_OPERATION));
    691                 return false;
    692             }
    693             break;
    694           case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    695           case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    696             if (context->getExtensions().textureCompressionDXT1)
    697             {
    698                 context->recordError(Error(GL_INVALID_OPERATION));
    699                 return false;
    700             }
    701             else
    702             {
    703                 context->recordError(Error(GL_INVALID_ENUM));
    704                 return false;
    705             }
    706             break;
    707           case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
    708             if (context->getExtensions().textureCompressionDXT3)
    709             {
    710                 context->recordError(Error(GL_INVALID_OPERATION));
    711                 return false;
    712             }
    713             else
    714             {
    715                 context->recordError(Error(GL_INVALID_ENUM));
    716                 return false;
    717             }
    718             break;
    719           case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
    720             if (context->getExtensions().textureCompressionDXT5)
    721             {
    722                 context->recordError(Error(GL_INVALID_OPERATION));
    723                 return false;
    724             }
    725             else
    726             {
    727                 context->recordError(Error(GL_INVALID_ENUM));
    728                 return false;
    729             }
    730             break;
    731           case GL_DEPTH_COMPONENT:
    732           case GL_DEPTH_COMPONENT16:
    733           case GL_DEPTH_COMPONENT32_OES:
    734           case GL_DEPTH_STENCIL_OES:
    735           case GL_DEPTH24_STENCIL8_OES:
    736             if (context->getExtensions().depthTextures)
    737             {
    738                 context->recordError(Error(GL_INVALID_OPERATION));
    739                 return false;
    740             }
    741             else
    742             {
    743                 context->recordError(Error(GL_INVALID_ENUM));
    744                 return false;
    745             }
    746           default:
    747             context->recordError(Error(GL_INVALID_ENUM));
    748             return false;
    749         }
    750     }
    751 
    752     // If width or height is zero, it is a no-op.  Return false without setting an error.
    753     return (width > 0 && height > 0);
    754 }
    755 
    756 bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
    757                                      GLsizei width, GLsizei height)
    758 {
    759     if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
    760     {
    761         context->recordError(Error(GL_INVALID_ENUM));
    762         return false;
    763     }
    764 
    765     if (width < 1 || height < 1 || levels < 1)
    766     {
    767         context->recordError(Error(GL_INVALID_VALUE));
    768         return false;
    769     }
    770 
    771     if (target == GL_TEXTURE_CUBE_MAP && width != height)
    772     {
    773         context->recordError(Error(GL_INVALID_VALUE));
    774         return false;
    775     }
    776 
    777     if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
    778     {
    779         context->recordError(Error(GL_INVALID_OPERATION));
    780         return false;
    781     }
    782 
    783     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
    784     if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
    785     {
    786         context->recordError(Error(GL_INVALID_ENUM));
    787         return false;
    788     }
    789 
    790     const gl::Caps &caps = context->getCaps();
    791 
    792     switch (target)
    793     {
    794       case GL_TEXTURE_2D:
    795         if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
    796             static_cast<GLuint>(height) > caps.max2DTextureSize)
    797         {
    798             context->recordError(Error(GL_INVALID_VALUE));
    799             return false;
    800         }
    801         break;
    802       case GL_TEXTURE_CUBE_MAP:
    803         if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
    804             static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
    805         {
    806             context->recordError(Error(GL_INVALID_VALUE));
    807             return false;
    808         }
    809         break;
    810       default:
    811         context->recordError(Error(GL_INVALID_ENUM));
    812         return false;
    813     }
    814 
    815     if (levels != 1 && !context->getExtensions().textureNPOT)
    816     {
    817         if (!gl::isPow2(width) || !gl::isPow2(height))
    818         {
    819             context->recordError(Error(GL_INVALID_OPERATION));
    820             return false;
    821         }
    822     }
    823 
    824     switch (internalformat)
    825     {
    826       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    827       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    828         if (!context->getExtensions().textureCompressionDXT1)
    829         {
    830             context->recordError(Error(GL_INVALID_ENUM));
    831             return false;
    832         }
    833         break;
    834       case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
    835         if (!context->getExtensions().textureCompressionDXT3)
    836         {
    837             context->recordError(Error(GL_INVALID_ENUM));
    838             return false;
    839         }
    840         break;
    841       case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
    842         if (!context->getExtensions().textureCompressionDXT5)
    843         {
    844             context->recordError(Error(GL_INVALID_ENUM));
    845             return false;
    846         }
    847         break;
    848       case GL_RGBA32F_EXT:
    849       case GL_RGB32F_EXT:
    850       case GL_ALPHA32F_EXT:
    851       case GL_LUMINANCE32F_EXT:
    852       case GL_LUMINANCE_ALPHA32F_EXT:
    853         if (!context->getExtensions().textureFloat)
    854         {
    855             context->recordError(Error(GL_INVALID_ENUM));
    856             return false;
    857         }
    858         break;
    859       case GL_RGBA16F_EXT:
    860       case GL_RGB16F_EXT:
    861       case GL_ALPHA16F_EXT:
    862       case GL_LUMINANCE16F_EXT:
    863       case GL_LUMINANCE_ALPHA16F_EXT:
    864         if (!context->getExtensions().textureHalfFloat)
    865         {
    866             context->recordError(Error(GL_INVALID_ENUM));
    867             return false;
    868         }
    869         break;
    870       case GL_R8_EXT:
    871       case GL_RG8_EXT:
    872       case GL_R16F_EXT:
    873       case GL_RG16F_EXT:
    874       case GL_R32F_EXT:
    875       case GL_RG32F_EXT:
    876         if (!context->getExtensions().textureRG)
    877         {
    878             context->recordError(Error(GL_INVALID_ENUM));
    879             return false;
    880         }
    881         break;
    882       case GL_DEPTH_COMPONENT16:
    883       case GL_DEPTH_COMPONENT32_OES:
    884       case GL_DEPTH24_STENCIL8_OES:
    885         if (!context->getExtensions().depthTextures)
    886         {
    887             context->recordError(Error(GL_INVALID_ENUM));
    888             return false;
    889         }
    890         if (target != GL_TEXTURE_2D)
    891         {
    892             context->recordError(Error(GL_INVALID_OPERATION));
    893             return false;
    894         }
    895         // ANGLE_depth_texture only supports 1-level textures
    896         if (levels != 1)
    897         {
    898             context->recordError(Error(GL_INVALID_OPERATION));
    899             return false;
    900         }
    901         break;
    902       default:
    903         break;
    904     }
    905 
    906     gl::Texture *texture = NULL;
    907     switch(target)
    908     {
    909       case GL_TEXTURE_2D:
    910         texture = context->getTexture2D();
    911         break;
    912       case GL_TEXTURE_CUBE_MAP:
    913         texture = context->getTextureCubeMap();
    914         break;
    915       default:
    916         UNREACHABLE();
    917     }
    918 
    919     if (!texture || texture->id() == 0)
    920     {
    921         context->recordError(Error(GL_INVALID_OPERATION));
    922         return false;
    923     }
    924 
    925     if (texture->isImmutable())
    926     {
    927         context->recordError(Error(GL_INVALID_OPERATION));
    928         return false;
    929     }
    930 
    931     return true;
    932 }
    933 
    934 // check for combinations of format and type that are valid for ReadPixels
    935 bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
    936 {
    937     switch (format)
    938     {
    939       case GL_RGBA:
    940         switch (type)
    941         {
    942           case GL_UNSIGNED_BYTE:
    943             break;
    944           default:
    945             return false;
    946         }
    947         break;
    948       case GL_BGRA_EXT:
    949         switch (type)
    950         {
    951           case GL_UNSIGNED_BYTE:
    952           case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
    953           case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
    954             break;
    955           default:
    956             return false;
    957         }
    958         break;
    959       case GL_RG_EXT:
    960       case GL_RED_EXT:
    961         if (!context->getExtensions().textureRG)
    962         {
    963             return false;
    964         }
    965         switch (type)
    966         {
    967           case GL_UNSIGNED_BYTE:
    968             break;
    969           default:
    970             return false;
    971         }
    972         break;
    973 
    974       default:
    975         return false;
    976     }
    977     return true;
    978 }
    979 
    980 }
    981