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