validationES.cpp (303237B)
1 // 2 // Copyright 2013 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 // validationES.h: Validation functions for generic OpenGL ES entry point parameters 8 9 #include "libANGLE/validationES.h" 10 11 #include "libANGLE/Context.h" 12 #include "libANGLE/Display.h" 13 #include "libANGLE/ErrorStrings.h" 14 #include "libANGLE/Framebuffer.h" 15 #include "libANGLE/FramebufferAttachment.h" 16 #include "libANGLE/Image.h" 17 #include "libANGLE/Program.h" 18 #include "libANGLE/Query.h" 19 #include "libANGLE/Texture.h" 20 #include "libANGLE/TransformFeedback.h" 21 #include "libANGLE/angletypes.h" 22 #include "libANGLE/formatutils.h" 23 #include "libANGLE/queryconversions.h" 24 #include "libANGLE/queryutils.h" 25 #include "libANGLE/validationES2.h" 26 #include "libANGLE/validationES3.h" 27 28 #include "common/mathutil.h" 29 #include "common/utilities.h" 30 31 using namespace angle; 32 33 namespace gl 34 { 35 using namespace err; 36 37 namespace 38 { 39 bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat) 40 { 41 // List of compressed format that require that the texture size is smaller than or a multiple of 42 // the compressed block size. 43 switch (internalFormat) 44 { 45 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 46 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 47 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: 48 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: 49 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 52 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 53 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: 54 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE: 55 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE: 56 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE: 57 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE: 58 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE: 59 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE: 60 case GL_COMPRESSED_RED_RGTC1_EXT: 61 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: 62 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: 63 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 64 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT: 65 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 66 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 67 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 68 return true; 69 70 default: 71 return false; 72 } 73 } 74 bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat) 75 { 76 // Compressed sub textures have additional formats that requires exact size. 77 // ES 3.1, Section 8.7, Page 171 78 return CompressedTextureFormatRequiresExactSize(internalFormat) || 79 IsETC2EACFormat(internalFormat) || IsASTC2DFormat(internalFormat); 80 } 81 82 bool DifferenceCanOverflow(GLint a, GLint b) 83 { 84 CheckedNumeric<GLint> checkedA(a); 85 checkedA -= b; 86 // Use negation to make sure that the difference can't overflow regardless of the order. 87 checkedA = -checkedA; 88 return !checkedA.IsValid(); 89 } 90 91 bool ValidReadPixelsTypeEnum(const Context *context, GLenum type) 92 { 93 switch (type) 94 { 95 // Types referenced in Table 3.4 of the ES 2.0.25 spec 96 case GL_UNSIGNED_BYTE: 97 case GL_UNSIGNED_SHORT_4_4_4_4: 98 case GL_UNSIGNED_SHORT_5_5_5_1: 99 case GL_UNSIGNED_SHORT_5_6_5: 100 return context->getClientVersion() >= ES_2_0; 101 102 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil) 103 case GL_BYTE: 104 case GL_INT: 105 case GL_SHORT: 106 case GL_UNSIGNED_INT: 107 case GL_UNSIGNED_INT_10F_11F_11F_REV: 108 case GL_UNSIGNED_INT_2_10_10_10_REV: 109 case GL_UNSIGNED_INT_5_9_9_9_REV: 110 case GL_UNSIGNED_SHORT: 111 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: 112 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: 113 return context->getClientVersion() >= ES_3_0; 114 115 case GL_FLOAT: 116 return context->getClientVersion() >= ES_3_0 || 117 context->getExtensions().textureFloatOES || 118 context->getExtensions().colorBufferHalfFloatEXT; 119 120 case GL_HALF_FLOAT: 121 return context->getClientVersion() >= ES_3_0 || 122 context->getExtensions().textureHalfFloatOES; 123 124 case GL_HALF_FLOAT_OES: 125 return context->getExtensions().colorBufferHalfFloatEXT; 126 127 default: 128 return false; 129 } 130 } 131 132 bool ValidReadPixelsFormatEnum(const Context *context, GLenum format) 133 { 134 switch (format) 135 { 136 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance) 137 case GL_RGBA: 138 case GL_RGB: 139 case GL_ALPHA: 140 return context->getClientVersion() >= ES_2_0; 141 142 // Formats referenced in Table 3.2 of the ES 3.0.5 spec 143 case GL_RG: 144 case GL_RED: 145 case GL_RGBA_INTEGER: 146 case GL_RGB_INTEGER: 147 case GL_RG_INTEGER: 148 case GL_RED_INTEGER: 149 return context->getClientVersion() >= ES_3_0; 150 151 case GL_SRGB_ALPHA_EXT: 152 case GL_SRGB_EXT: 153 return context->getExtensions().sRGBEXT; 154 155 case GL_BGRA_EXT: 156 return context->getExtensions().readFormatBgraEXT; 157 158 case GL_RGBX8_ANGLE: 159 return context->getExtensions().rgbxInternalFormatANGLE; 160 161 default: 162 return false; 163 } 164 } 165 166 bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context, 167 const gl::InternalFormat *info, 168 GLenum type) 169 { 170 bool supportsReadDepthNV = context->getExtensions().readDepthNV && (info->depthBits > 0); 171 switch (type) 172 { 173 case GL_UNSIGNED_SHORT: 174 case GL_UNSIGNED_INT: 175 case GL_UNSIGNED_INT_24_8: 176 return supportsReadDepthNV; 177 default: 178 return false; 179 } 180 } 181 182 bool ValidReadPixelsFloatDepthType(const Context *context, 183 const gl::InternalFormat *info, 184 GLenum type) 185 { 186 return context->getExtensions().readDepthNV && (type == GL_FLOAT) && 187 context->getExtensions().depthBufferFloat2NV; 188 } 189 190 bool ValidReadPixelsFormatType(const Context *context, 191 const gl::InternalFormat *info, 192 GLenum format, 193 GLenum type) 194 { 195 switch (info->componentType) 196 { 197 case GL_UNSIGNED_NORMALIZED: 198 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use 199 // ReadPixels with BGRA even if the extension is not present 200 switch (format) 201 { 202 case GL_RGBA: 203 return ((type == GL_UNSIGNED_BYTE) && info->pixelBytes >= 1) || 204 (context->getExtensions().textureNorm16EXT && 205 (type == GL_UNSIGNED_SHORT) && info->pixelBytes >= 2); 206 case GL_BGRA_EXT: 207 return context->getExtensions().readFormatBgraEXT && (type == GL_UNSIGNED_BYTE); 208 case GL_STENCIL_INDEX_OES: 209 return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE); 210 case GL_DEPTH_COMPONENT: 211 return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type); 212 case GL_DEPTH_STENCIL_OES: 213 return context->getExtensions().readDepthStencilNV && 214 (type == GL_UNSIGNED_INT_24_8_OES) && info->stencilBits > 0; 215 case GL_RGBX8_ANGLE: 216 return context->getExtensions().rgbxInternalFormatANGLE && 217 (type == GL_UNSIGNED_BYTE); 218 default: 219 return false; 220 } 221 case GL_SIGNED_NORMALIZED: 222 return (format == GL_RGBA && type == GL_BYTE && info->pixelBytes >= 1) || 223 (context->getExtensions().textureNorm16EXT && format == GL_RGBA && 224 type == GL_UNSIGNED_SHORT && info->pixelBytes >= 2); 225 226 case GL_INT: 227 return (format == GL_RGBA_INTEGER && type == GL_INT); 228 229 case GL_UNSIGNED_INT: 230 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT); 231 232 case GL_FLOAT: 233 switch (format) 234 { 235 case GL_RGBA: 236 return (type == GL_FLOAT); 237 case GL_DEPTH_COMPONENT: 238 return ValidReadPixelsFloatDepthType(context, info, type); 239 case GL_DEPTH_STENCIL_OES: 240 return context->getExtensions().readDepthStencilNV && 241 type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && info->stencilBits > 0; 242 default: 243 return false; 244 } 245 default: 246 UNREACHABLE(); 247 return false; 248 } 249 } 250 251 template <typename ParamType> 252 bool ValidateTextureWrapModeValue(const Context *context, 253 angle::EntryPoint entryPoint, 254 const ParamType *params, 255 bool restrictedWrapModes) 256 { 257 switch (ConvertToGLenum(params[0])) 258 { 259 case GL_CLAMP_TO_EDGE: 260 break; 261 262 case GL_CLAMP_TO_BORDER: 263 if (!context->getExtensions().textureBorderClampAny() && 264 context->getClientVersion() < ES_3_2) 265 { 266 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 267 return false; 268 } 269 break; 270 271 case GL_REPEAT: 272 case GL_MIRRORED_REPEAT: 273 if (restrictedWrapModes) 274 { 275 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error. 276 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidWrapModeTexture); 277 return false; 278 } 279 break; 280 281 default: 282 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureWrap); 283 return false; 284 } 285 286 return true; 287 } 288 289 template <typename ParamType> 290 bool ValidateTextureMinFilterValue(const Context *context, 291 angle::EntryPoint entryPoint, 292 const ParamType *params, 293 bool restrictedMinFilter) 294 { 295 switch (ConvertToGLenum(params[0])) 296 { 297 case GL_NEAREST: 298 case GL_LINEAR: 299 break; 300 301 case GL_NEAREST_MIPMAP_NEAREST: 302 case GL_LINEAR_MIPMAP_NEAREST: 303 case GL_NEAREST_MIPMAP_LINEAR: 304 case GL_LINEAR_MIPMAP_LINEAR: 305 if (restrictedMinFilter) 306 { 307 // OES_EGL_image_external specifies this error. 308 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFilterTexture); 309 return false; 310 } 311 break; 312 313 default: 314 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureFilterParam); 315 return false; 316 } 317 318 return true; 319 } 320 321 template <typename ParamType> 322 bool ValidateTextureMagFilterValue(const Context *context, 323 angle::EntryPoint entryPoint, 324 const ParamType *params) 325 { 326 switch (ConvertToGLenum(params[0])) 327 { 328 case GL_NEAREST: 329 case GL_LINEAR: 330 break; 331 332 default: 333 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureFilterParam); 334 return false; 335 } 336 337 return true; 338 } 339 340 template <typename ParamType> 341 bool ValidateTextureCompareModeValue(const Context *context, 342 angle::EntryPoint entryPoint, 343 const ParamType *params) 344 { 345 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17 346 switch (ConvertToGLenum(params[0])) 347 { 348 case GL_NONE: 349 case GL_COMPARE_REF_TO_TEXTURE: 350 break; 351 352 default: 353 context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter); 354 return false; 355 } 356 357 return true; 358 } 359 360 template <typename ParamType> 361 bool ValidateTextureCompareFuncValue(const Context *context, 362 angle::EntryPoint entryPoint, 363 const ParamType *params) 364 { 365 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17 366 switch (ConvertToGLenum(params[0])) 367 { 368 case GL_LEQUAL: 369 case GL_GEQUAL: 370 case GL_LESS: 371 case GL_GREATER: 372 case GL_EQUAL: 373 case GL_NOTEQUAL: 374 case GL_ALWAYS: 375 case GL_NEVER: 376 break; 377 378 default: 379 context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter); 380 return false; 381 } 382 383 return true; 384 } 385 386 template <typename ParamType> 387 bool ValidateTextureSRGBDecodeValue(const Context *context, 388 angle::EntryPoint entryPoint, 389 const ParamType *params) 390 { 391 if (!context->getExtensions().textureSRGBDecodeEXT) 392 { 393 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 394 return false; 395 } 396 397 switch (ConvertToGLenum(params[0])) 398 { 399 case GL_DECODE_EXT: 400 case GL_SKIP_DECODE_EXT: 401 break; 402 403 default: 404 context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter); 405 return false; 406 } 407 408 return true; 409 } 410 411 template <typename ParamType> 412 bool ValidateTextureSRGBOverrideValue(const Context *context, 413 angle::EntryPoint entryPoint, 414 const ParamType *params) 415 { 416 if (!context->getExtensions().textureFormatSRGBOverrideEXT) 417 { 418 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 419 return false; 420 } 421 422 switch (ConvertToGLenum(params[0])) 423 { 424 case GL_SRGB: 425 case GL_NONE: 426 break; 427 428 default: 429 context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter); 430 return false; 431 } 432 433 return true; 434 } 435 436 bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context, 437 angle::EntryPoint entryPoint) 438 { 439 if (!context->getExtensions().textureFilterAnisotropicEXT) 440 { 441 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 442 return false; 443 } 444 445 return true; 446 } 447 448 bool ValidateTextureMaxAnisotropyValue(const Context *context, 449 angle::EntryPoint entryPoint, 450 GLfloat paramValue) 451 { 452 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint)) 453 { 454 return false; 455 } 456 457 GLfloat largest = context->getCaps().maxTextureAnisotropy; 458 459 if (paramValue < 1 || paramValue > largest) 460 { 461 context->validationError(entryPoint, GL_INVALID_VALUE, kOutsideOfBounds); 462 return false; 463 } 464 465 return true; 466 } 467 468 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context) 469 { 470 const auto &glState = context->getState(); 471 const Program *program = context->getActiveLinkedProgram(); 472 const Framebuffer *framebuffer = glState.getDrawFramebuffer(); 473 474 auto drawBufferMask = 475 framebuffer->getDrawBufferMask() & glState.getBlendStateExt().compareColorMask(0); 476 auto fragmentOutputMask = program->getExecutable().getActiveOutputVariablesMask(); 477 478 return drawBufferMask == (drawBufferMask & fragmentOutputMask); 479 } 480 481 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context) 482 { 483 const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context); 484 const Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); 485 486 return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().to_ulong(), 487 framebuffer->getDrawBufferTypeMask().to_ulong(), 488 executable->getActiveOutputVariablesMask().to_ulong(), 489 framebuffer->getDrawBufferMask().to_ulong()); 490 } 491 492 bool ValidateVertexShaderAttributeTypeMatch(const Context *context) 493 { 494 const auto &glState = context->getState(); 495 const Program *program = context->getActiveLinkedProgram(); 496 const VertexArray *vao = context->getState().getVertexArray(); 497 498 if (!program) 499 { 500 return false; 501 } 502 503 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong(); 504 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong(); 505 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong(); 506 507 vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex; 508 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits); 509 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits); 510 511 const ProgramExecutable &executable = program->getExecutable(); 512 return ValidateComponentTypeMasks(executable.getAttributesTypeMask().to_ulong(), 513 vaoAttribTypeBits, executable.getAttributesMask().to_ulong(), 514 0xFFFF); 515 } 516 517 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode, 518 PrimitiveMode geometryShaderInputPrimitiveType) 519 { 520 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives 521 switch (drawMode) 522 { 523 case PrimitiveMode::Points: 524 return geometryShaderInputPrimitiveType == PrimitiveMode::Points; 525 case PrimitiveMode::Lines: 526 case PrimitiveMode::LineStrip: 527 case PrimitiveMode::LineLoop: 528 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines; 529 case PrimitiveMode::LinesAdjacency: 530 case PrimitiveMode::LineStripAdjacency: 531 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency; 532 case PrimitiveMode::Triangles: 533 case PrimitiveMode::TriangleFan: 534 case PrimitiveMode::TriangleStrip: 535 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles; 536 case PrimitiveMode::TrianglesAdjacency: 537 case PrimitiveMode::TriangleStripAdjacency: 538 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency; 539 default: 540 UNREACHABLE(); 541 return false; 542 } 543 } 544 545 // GLES1 texture parameters are a small subset of the others 546 bool IsValidGLES1TextureParameter(GLenum pname) 547 { 548 switch (pname) 549 { 550 case GL_TEXTURE_MAG_FILTER: 551 case GL_TEXTURE_MIN_FILTER: 552 case GL_TEXTURE_WRAP_S: 553 case GL_TEXTURE_WRAP_T: 554 case GL_TEXTURE_WRAP_R: 555 case GL_GENERATE_MIPMAP: 556 case GL_TEXTURE_CROP_RECT_OES: 557 return true; 558 default: 559 return false; 560 } 561 } 562 563 unsigned int GetSamplerParameterCount(GLenum pname) 564 { 565 return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1; 566 } 567 568 const char *ValidateProgramDrawAdvancedBlendState(const Context *context, Program *program) 569 { 570 const State &state = context->getState(); 571 const BlendEquationBitSet &supportedBlendEquations = 572 program->getExecutable().getAdvancedBlendEquations(); 573 const DrawBufferMask &enabledDrawBufferMask = state.getBlendStateExt().getEnabledMask(); 574 575 for (size_t blendEnabledBufferIndex : enabledDrawBufferMask) 576 { 577 const gl::BlendEquationType &enabledBlendEquation = gl::FromGLenum<gl::BlendEquationType>( 578 state.getBlendStateExt().getEquationColorIndexed(blendEnabledBufferIndex)); 579 580 if (enabledBlendEquation < gl::BlendEquationType::Multiply || 581 enabledBlendEquation > gl::BlendEquationType::HslLuminosity) 582 { 583 continue; 584 } 585 586 if (!supportedBlendEquations.test(enabledBlendEquation)) 587 { 588 return gl::err::kBlendEquationNotEnabled; 589 } 590 } 591 592 return nullptr; 593 } 594 595 ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context, 596 const Extensions &extensions, 597 Program *program) 598 { 599 const State &state = context->getState(); 600 if (extensions.multiviewOVR || extensions.multiview2OVR) 601 { 602 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1; 603 Framebuffer *framebuffer = state.getDrawFramebuffer(); 604 const int framebufferNumViews = framebuffer->getNumViews(); 605 606 if (framebufferNumViews != programNumViews) 607 { 608 return gl::err::kMultiviewMismatch; 609 } 610 611 if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1) 612 { 613 return gl::err::kMultiviewTransformFeedback; 614 } 615 616 if (extensions.disjointTimerQueryEXT && framebufferNumViews > 1 && 617 state.isQueryActive(QueryType::TimeElapsed)) 618 { 619 return gl::err::kMultiviewTimerQuery; 620 } 621 } 622 623 // Uniform buffer validation 624 for (unsigned int uniformBlockIndex = 0; 625 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) 626 { 627 const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); 628 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex); 629 const OffsetBindingPointer<Buffer> &uniformBuffer = 630 state.getIndexedUniformBuffer(blockBinding); 631 632 if (uniformBuffer.get() == nullptr && context->isWebGL()) 633 { 634 // undefined behaviour 635 return gl::err::kUniformBufferUnbound; 636 } 637 638 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer); 639 if (uniformBufferSize < uniformBlock.dataSize && 640 (context->isWebGL() || context->isBufferAccessValidationEnabled())) 641 { 642 // undefined behaviour 643 return gl::err::kUniformBufferTooSmall; 644 } 645 646 if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) 647 { 648 return gl::err::kUniformBufferBoundForTransformFeedback; 649 } 650 } 651 652 // Enabled blend equation validation 653 const char *errorString = nullptr; 654 655 if (extensions.blendEquationAdvancedKHR) 656 { 657 errorString = ValidateProgramDrawAdvancedBlendState(context, program); 658 } 659 660 return errorString; 661 } 662 } // anonymous namespace 663 664 void SetRobustLengthParam(const GLsizei *length, GLsizei value) 665 { 666 if (length) 667 { 668 // Currently we modify robust length parameters in the validation layer. We should be only 669 // doing this in the Context instead. 670 // TODO(http://anglebug.com/4406): Remove when possible. 671 *const_cast<GLsizei *>(length) = value; 672 } 673 } 674 675 bool ValidTextureTarget(const Context *context, TextureType type) 676 { 677 switch (type) 678 { 679 case TextureType::_2D: 680 case TextureType::CubeMap: 681 return true; 682 683 case TextureType::Rectangle: 684 return context->getExtensions().textureRectangleANGLE; 685 686 case TextureType::_3D: 687 return ((context->getClientMajorVersion() >= 3) || 688 context->getExtensions().texture3DOES); 689 690 case TextureType::_2DArray: 691 return (context->getClientMajorVersion() >= 3); 692 693 case TextureType::_2DMultisample: 694 return (context->getClientVersion() >= Version(3, 1) || 695 context->getExtensions().textureMultisampleANGLE); 696 case TextureType::_2DMultisampleArray: 697 return context->getExtensions().textureStorageMultisample2dArrayOES; 698 699 case TextureType::CubeMapArray: 700 return (context->getClientVersion() >= Version(3, 2) || 701 context->getExtensions().textureCubeMapArrayAny()); 702 703 case TextureType::VideoImage: 704 return context->getExtensions().videoTextureWEBGL; 705 706 case TextureType::Buffer: 707 return (context->getClientVersion() >= Version(3, 2) || 708 context->getExtensions().textureBufferAny()); 709 710 default: 711 return false; 712 } 713 } 714 715 bool ValidTexture2DTarget(const Context *context, TextureType type) 716 { 717 switch (type) 718 { 719 case TextureType::_2D: 720 case TextureType::CubeMap: 721 return true; 722 723 case TextureType::Rectangle: 724 return context->getExtensions().textureRectangleANGLE; 725 726 default: 727 return false; 728 } 729 } 730 731 bool ValidTexture3DTarget(const Context *context, TextureType target) 732 { 733 switch (target) 734 { 735 case TextureType::_3D: 736 case TextureType::_2DArray: 737 return (context->getClientMajorVersion() >= 3); 738 739 case TextureType::CubeMapArray: 740 return (context->getClientVersion() >= Version(3, 2) || 741 context->getExtensions().textureCubeMapArrayAny()); 742 743 default: 744 return false; 745 } 746 } 747 748 // Most texture GL calls are not compatible with external textures, so we have a separate validation 749 // function for use in the GL calls that do 750 bool ValidTextureExternalTarget(const Context *context, TextureType target) 751 { 752 return (target == TextureType::External) && 753 (context->getExtensions().EGLImageExternalOES || 754 context->getExtensions().EGLStreamConsumerExternalNV); 755 } 756 757 bool ValidTextureExternalTarget(const Context *context, TextureTarget target) 758 { 759 return (target == TextureTarget::External) && 760 ValidTextureExternalTarget(context, TextureType::External); 761 } 762 763 // This function differs from ValidTextureTarget in that the target must be 764 // usable as the destination of a 2D operation-- so a cube face is valid, but 765 // GL_TEXTURE_CUBE_MAP is not. 766 // Note: duplicate of IsInternalTextureTarget 767 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target) 768 { 769 switch (target) 770 { 771 case TextureTarget::_2D: 772 case TextureTarget::CubeMapNegativeX: 773 case TextureTarget::CubeMapNegativeY: 774 case TextureTarget::CubeMapNegativeZ: 775 case TextureTarget::CubeMapPositiveX: 776 case TextureTarget::CubeMapPositiveY: 777 case TextureTarget::CubeMapPositiveZ: 778 return true; 779 case TextureTarget::Rectangle: 780 return context->getExtensions().textureRectangleANGLE; 781 case TextureTarget::VideoImage: 782 return context->getExtensions().videoTextureWEBGL; 783 default: 784 return false; 785 } 786 } 787 788 bool ValidateTransformFeedbackPrimitiveMode(const Context *context, 789 angle::EntryPoint entryPoint, 790 PrimitiveMode transformFeedbackPrimitiveMode, 791 PrimitiveMode renderPrimitiveMode) 792 { 793 ASSERT(context); 794 795 if ((!context->getExtensions().geometryShaderAny() || 796 !context->getExtensions().tessellationShaderEXT) && 797 context->getClientVersion() < ES_3_2) 798 { 799 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode 800 // that does not match the current transform feedback object's draw mode (if transform 801 // feedback is active), (3.0.2, section 2.14, pg 86) 802 return transformFeedbackPrimitiveMode == renderPrimitiveMode; 803 } 804 805 const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context); 806 ASSERT(executable); 807 if (executable->hasLinkedShaderStage(ShaderType::Geometry)) 808 { 809 // If geometry shader is active, transform feedback mode must match what is output from this 810 // stage. 811 renderPrimitiveMode = executable->getGeometryShaderOutputPrimitiveType(); 812 } 813 else if (executable->hasLinkedShaderStage(ShaderType::TessEvaluation)) 814 { 815 // Similarly with tessellation shaders, but only if no geometry shader is present. With 816 // tessellation shaders, only triangles are possibly output. 817 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles && 818 executable->getTessGenMode() == GL_TRIANGLES; 819 } 820 821 // [GL_EXT_geometry_shader] Table 12.1gs 822 switch (renderPrimitiveMode) 823 { 824 case PrimitiveMode::Points: 825 return transformFeedbackPrimitiveMode == PrimitiveMode::Points; 826 case PrimitiveMode::Lines: 827 case PrimitiveMode::LineStrip: 828 case PrimitiveMode::LineLoop: 829 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines; 830 case PrimitiveMode::Triangles: 831 case PrimitiveMode::TriangleFan: 832 case PrimitiveMode::TriangleStrip: 833 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles; 834 case PrimitiveMode::Patches: 835 return transformFeedbackPrimitiveMode == PrimitiveMode::Patches; 836 default: 837 UNREACHABLE(); 838 return false; 839 } 840 } 841 842 bool ValidateDrawElementsInstancedBase(const Context *context, 843 angle::EntryPoint entryPoint, 844 PrimitiveMode mode, 845 GLsizei count, 846 DrawElementsType type, 847 const void *indices, 848 GLsizei primcount) 849 { 850 if (primcount <= 0) 851 { 852 if (primcount < 0) 853 { 854 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativePrimcount); 855 return false; 856 } 857 858 // Early exit. 859 return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 860 primcount); 861 } 862 863 if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, primcount)) 864 { 865 return false; 866 } 867 868 if (count == 0) 869 { 870 // Early exit. 871 return true; 872 } 873 874 return ValidateDrawInstancedAttribs(context, entryPoint, primcount); 875 } 876 877 bool ValidateDrawArraysInstancedBase(const Context *context, 878 angle::EntryPoint entryPoint, 879 PrimitiveMode mode, 880 GLint first, 881 GLsizei count, 882 GLsizei primcount) 883 { 884 if (primcount <= 0) 885 { 886 if (primcount < 0) 887 { 888 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativePrimcount); 889 return false; 890 } 891 892 // Early exit. 893 return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount); 894 } 895 896 if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount)) 897 { 898 return false; 899 } 900 901 if (count == 0) 902 { 903 // Early exit. 904 return true; 905 } 906 907 return ValidateDrawInstancedAttribs(context, entryPoint, primcount); 908 } 909 910 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint) 911 { 912 // Verify there is at least one active attribute with a divisor of zero 913 const State &state = context->getState(); 914 const ProgramExecutable *executable = state.getLinkedProgramExecutable(context); 915 916 if (!executable) 917 { 918 // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't 919 // an error. 920 context->getState().getDebug().insertMessage( 921 GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH, 922 std::string("Attempting to draw without a program"), gl::LOG_WARN, entryPoint); 923 return true; 924 } 925 926 const auto &attribs = state.getVertexArray()->getVertexAttributes(); 927 const auto &bindings = state.getVertexArray()->getVertexBindings(); 928 for (size_t attributeIndex = 0; attributeIndex < attribs.size(); attributeIndex++) 929 { 930 const VertexAttribute &attrib = attribs[attributeIndex]; 931 const VertexBinding &binding = bindings[attrib.bindingIndex]; 932 if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0) 933 { 934 return true; 935 } 936 } 937 938 context->validationError(entryPoint, GL_INVALID_OPERATION, kNoZeroDivisor); 939 return false; 940 } 941 942 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target) 943 { 944 switch (target) 945 { 946 case TextureTarget::_3D: 947 case TextureTarget::_2DArray: 948 return true; 949 case TextureTarget::CubeMapArray: 950 return (context->getClientVersion() >= Version(3, 2) || 951 context->getExtensions().textureCubeMapArrayAny()); 952 default: 953 return false; 954 } 955 } 956 957 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type) 958 { 959 switch (type) 960 { 961 case TextureType::_2D: 962 case TextureType::_2DArray: 963 case TextureType::_2DMultisample: 964 case TextureType::CubeMap: 965 case TextureType::_3D: 966 return true; 967 case TextureType::CubeMapArray: 968 return (context->getClientVersion() >= Version(3, 2) || 969 context->getExtensions().textureCubeMapArrayAny()); 970 case TextureType::Rectangle: 971 return context->getExtensions().textureRectangleANGLE; 972 case TextureType::_2DMultisampleArray: 973 return context->getExtensions().textureStorageMultisample2dArrayOES; 974 case TextureType::Buffer: 975 return (context->getClientVersion() >= Version(3, 2) || 976 context->getExtensions().textureBufferAny()); 977 default: 978 return false; 979 } 980 } 981 982 bool ValidFramebufferTarget(const Context *context, GLenum target) 983 { 984 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && 985 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER, 986 "ANGLE framebuffer enums must equal the ES3 framebuffer enums."); 987 988 switch (target) 989 { 990 case GL_FRAMEBUFFER: 991 return true; 992 993 case GL_READ_FRAMEBUFFER: 994 case GL_DRAW_FRAMEBUFFER: 995 return (context->getExtensions().framebufferBlitAny() || 996 context->getClientMajorVersion() >= 3); 997 998 default: 999 return false; 1000 } 1001 } 1002 1003 bool ValidMipLevel(const Context *context, TextureType type, GLint level) 1004 { 1005 const auto &caps = context->getCaps(); 1006 int maxDimension = 0; 1007 switch (type) 1008 { 1009 case TextureType::_2D: 1010 case TextureType::_2DArray: 1011 case TextureType::_2DMultisample: 1012 case TextureType::_2DMultisampleArray: 1013 // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable 1014 // level-of-detail" for multisample textures should be. Could maybe make it zero. 1015 maxDimension = caps.max2DTextureSize; 1016 break; 1017 1018 case TextureType::CubeMap: 1019 case TextureType::CubeMapArray: 1020 maxDimension = caps.maxCubeMapTextureSize; 1021 break; 1022 1023 case TextureType::External: 1024 case TextureType::Rectangle: 1025 case TextureType::VideoImage: 1026 case TextureType::Buffer: 1027 return level == 0; 1028 1029 case TextureType::_3D: 1030 maxDimension = caps.max3DTextureSize; 1031 break; 1032 1033 default: 1034 UNREACHABLE(); 1035 } 1036 1037 return level <= log2(maxDimension) && level >= 0; 1038 } 1039 1040 bool ValidImageSizeParameters(const Context *context, 1041 angle::EntryPoint entryPoint, 1042 TextureType target, 1043 GLint level, 1044 GLsizei width, 1045 GLsizei height, 1046 GLsizei depth, 1047 bool isSubImage) 1048 { 1049 if (width < 0 || height < 0 || depth < 0) 1050 { 1051 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 1052 return false; 1053 } 1054 // TexSubImage parameters can be NPOT without textureNPOT extension, 1055 // as long as the destination texture is POT. 1056 bool hasNPOTSupport = 1057 context->getExtensions().textureNpotOES || context->getClientVersion() >= Version(3, 0); 1058 if (!isSubImage && !hasNPOTSupport && 1059 (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth)))) 1060 { 1061 context->validationError(entryPoint, GL_INVALID_VALUE, kTextureNotPow2); 1062 return false; 1063 } 1064 1065 if (!ValidMipLevel(context, target, level)) 1066 { 1067 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 1068 return false; 1069 } 1070 1071 return true; 1072 } 1073 1074 bool ValidCompressedBaseLevel(GLsizei size, GLuint blockSize, GLint level) 1075 { 1076 // Already checked in ValidMipLevel. 1077 ASSERT(level < 32); 1078 // This function is used only for 4x4 BC formats. 1079 ASSERT(blockSize == 4); 1080 // Use the constant value to avoid division. 1081 return ((size << level) % 4) == 0; 1082 } 1083 1084 bool ValidCompressedImageSize(const Context *context, 1085 GLenum internalFormat, 1086 GLint level, 1087 GLsizei width, 1088 GLsizei height, 1089 GLsizei depth) 1090 { 1091 if (width < 0 || height < 0) 1092 { 1093 return false; 1094 } 1095 1096 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat); 1097 1098 if (!formatInfo.compressed && !formatInfo.paletted) 1099 { 1100 return false; 1101 } 1102 1103 // A texture format can not be both block-compressed and paletted 1104 ASSERT(!(formatInfo.compressed && formatInfo.paletted)); 1105 1106 if (formatInfo.compressed) 1107 { 1108 // Only PVRTC1 requires dimensions to be powers of two 1109 if (IsPVRTC1Format(internalFormat)) 1110 { 1111 if (!isPow2(width) || !isPow2(height)) 1112 { 1113 return false; 1114 } 1115 1116 if (context->getLimitations().squarePvrtc1) 1117 { 1118 if (width != height) 1119 { 1120 return false; 1121 } 1122 } 1123 } 1124 1125 if (CompressedTextureFormatRequiresExactSize(internalFormat)) 1126 { 1127 // In WebGL compatibility mode and D3D, enforce that the base level implied 1128 // by the compressed texture's mip level would conform to the block 1129 // size. 1130 if (context->isWebGL() || 1131 context->getLimitations().compressedBaseMipLevelMultipleOfFour) 1132 { 1133 // This check is performed only for BC formats. 1134 ASSERT(formatInfo.compressedBlockDepth == 1); 1135 if (!ValidCompressedBaseLevel(width, formatInfo.compressedBlockWidth, level) || 1136 !ValidCompressedBaseLevel(height, formatInfo.compressedBlockHeight, level)) 1137 { 1138 return false; 1139 } 1140 } 1141 // non-WebGL and non-D3D check is not necessary for the following formats 1142 // From EXT_texture_compression_s3tc specification: 1143 // If the width or height is not a multiple of four, there will be 4x4 blocks at the 1144 // edge of the image that contain "extra" texels that are not part of the image. From 1145 // EXT_texture_compression_bptc & EXT_texture_compression_rgtc specification: If an 1146 // RGTC/BPTC image has a width or height that is not a multiple of four, the data 1147 // corresponding to texels outside the image are irrelevant and undefined. 1148 } 1149 } 1150 1151 if (formatInfo.paletted) 1152 { 1153 // TODO(http://anglebug.com/7688): multi-level paletted images 1154 if (level != 0) 1155 { 1156 return false; 1157 } 1158 1159 if (!isPow2(width) || !isPow2(height)) 1160 { 1161 return false; 1162 } 1163 } 1164 1165 return true; 1166 } 1167 1168 bool ValidCompressedSubImageSize(const Context *context, 1169 GLenum internalFormat, 1170 GLint xoffset, 1171 GLint yoffset, 1172 GLint zoffset, 1173 GLsizei width, 1174 GLsizei height, 1175 GLsizei depth, 1176 size_t textureWidth, 1177 size_t textureHeight, 1178 size_t textureDepth) 1179 { 1180 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat); 1181 if (!formatInfo.compressed) 1182 { 1183 return false; 1184 } 1185 1186 if (xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0 || depth < 0) 1187 { 1188 return false; 1189 } 1190 1191 // ANGLE does not support compressed 3D blocks (provided exclusively by ASTC 3D formats), so 1192 // there is no need to check the depth here. Only width and height determine whether a 2D array 1193 // element or a 2D slice of a sliced 3D texture fill the entire level. 1194 bool fillsEntireMip = xoffset == 0 && yoffset == 0 && 1195 static_cast<size_t>(width) == textureWidth && 1196 static_cast<size_t>(height) == textureHeight; 1197 1198 if (CompressedFormatRequiresWholeImage(internalFormat)) 1199 { 1200 return fillsEntireMip; 1201 } 1202 1203 if (CompressedSubTextureFormatRequiresExactSize(internalFormat)) 1204 { 1205 if (xoffset % formatInfo.compressedBlockWidth != 0 || 1206 yoffset % formatInfo.compressedBlockHeight != 0 || 1207 zoffset % formatInfo.compressedBlockDepth != 0) 1208 { 1209 return false; 1210 } 1211 1212 // Allowed to either have data that is a multiple of block size or is smaller than the block 1213 // size but fills the entire mip 1214 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 && 1215 (height % formatInfo.compressedBlockHeight) == 0 && 1216 (depth % formatInfo.compressedBlockDepth) == 0; 1217 if (!sizeMultipleOfBlockSize && !fillsEntireMip) 1218 { 1219 return false; 1220 } 1221 } 1222 1223 return true; 1224 } 1225 1226 bool ValidImageDataSize(const Context *context, 1227 angle::EntryPoint entryPoint, 1228 TextureType texType, 1229 GLsizei width, 1230 GLsizei height, 1231 GLsizei depth, 1232 GLenum format, 1233 GLenum type, 1234 const void *pixels, 1235 GLsizei imageSize) 1236 { 1237 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack); 1238 if (pixelUnpackBuffer == nullptr && imageSize < 0) 1239 { 1240 // Checks are not required 1241 return true; 1242 } 1243 1244 // ...the data would be unpacked from the buffer object such that the memory reads required 1245 // would exceed the data store size. 1246 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type); 1247 ASSERT(formatInfo.internalFormat != GL_NONE); 1248 const Extents size(width, height, depth); 1249 const auto &unpack = context->getState().getUnpackState(); 1250 1251 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray; 1252 GLuint endByte = 0; 1253 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte)) 1254 { 1255 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 1256 return false; 1257 } 1258 1259 if (pixelUnpackBuffer) 1260 { 1261 CheckedNumeric<size_t> checkedEndByte(endByte); 1262 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels)); 1263 checkedEndByte += checkedOffset; 1264 1265 if (!checkedEndByte.IsValid() || 1266 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize()))) 1267 { 1268 // Overflow past the end of the buffer 1269 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 1270 return false; 1271 } 1272 if (pixelUnpackBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) 1273 { 1274 context->validationError(entryPoint, GL_INVALID_OPERATION, 1275 kPixelUnpackBufferBoundForTransformFeedback); 1276 return false; 1277 } 1278 } 1279 else 1280 { 1281 ASSERT(imageSize >= 0); 1282 if (pixels == nullptr && imageSize != 0) 1283 { 1284 context->validationError(entryPoint, GL_INVALID_OPERATION, kImageSizeMustBeZero); 1285 return false; 1286 } 1287 1288 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize)) 1289 { 1290 context->validationError(entryPoint, GL_INVALID_OPERATION, kImageSizeTooSmall); 1291 return false; 1292 } 1293 } 1294 1295 return true; 1296 } 1297 1298 bool ValidQueryType(const Context *context, QueryType queryType) 1299 { 1300 switch (queryType) 1301 { 1302 case QueryType::AnySamples: 1303 case QueryType::AnySamplesConservative: 1304 return context->getClientMajorVersion() >= 3 || 1305 context->getExtensions().occlusionQueryBooleanEXT; 1306 case QueryType::TransformFeedbackPrimitivesWritten: 1307 return (context->getClientMajorVersion() >= 3); 1308 case QueryType::TimeElapsed: 1309 return context->getExtensions().disjointTimerQueryEXT; 1310 case QueryType::CommandsCompleted: 1311 return context->getExtensions().syncQueryCHROMIUM; 1312 case QueryType::PrimitivesGenerated: 1313 return context->getClientVersion() >= ES_3_2 || 1314 context->getExtensions().geometryShaderAny(); 1315 default: 1316 return false; 1317 } 1318 } 1319 1320 bool ValidateWebGLVertexAttribPointer(const Context *context, 1321 angle::EntryPoint entryPoint, 1322 VertexAttribType type, 1323 GLboolean normalized, 1324 GLsizei stride, 1325 const void *ptr, 1326 bool pureInteger) 1327 { 1328 ASSERT(context->isWebGL()); 1329 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride 1330 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to 1331 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride 1332 // parameter exceeds 255. 1333 constexpr GLsizei kMaxWebGLStride = 255; 1334 if (stride > kMaxWebGLStride) 1335 { 1336 context->validationError(entryPoint, GL_INVALID_VALUE, kStrideExceedsWebGLLimit); 1337 return false; 1338 } 1339 1340 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements 1341 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to 1342 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call, 1343 // or an INVALID_OPERATION error is generated. 1344 angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger); 1345 size_t typeSize = GetVertexFormatSize(internalType); 1346 1347 ASSERT(isPow2(typeSize) && typeSize > 0); 1348 size_t sizeMask = (typeSize - 1); 1349 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0) 1350 { 1351 context->validationError(entryPoint, GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType); 1352 return false; 1353 } 1354 1355 if ((stride & sizeMask) != 0) 1356 { 1357 context->validationError(entryPoint, GL_INVALID_OPERATION, kStrideMustBeMultipleOfType); 1358 return false; 1359 } 1360 1361 return true; 1362 } 1363 1364 Program *GetValidProgramNoResolve(const Context *context, 1365 angle::EntryPoint entryPoint, 1366 ShaderProgramID id) 1367 { 1368 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will 1369 // generate the error INVALID_VALUE if the provided name is not the name of either a shader 1370 // or program object and INVALID_OPERATION if the provided name identifies an object 1371 // that is not the expected type." 1372 1373 Program *validProgram = context->getProgramNoResolveLink(id); 1374 1375 if (!validProgram) 1376 { 1377 if (context->getShader(id)) 1378 { 1379 context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName); 1380 } 1381 else 1382 { 1383 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName); 1384 } 1385 } 1386 1387 return validProgram; 1388 } 1389 1390 Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id) 1391 { 1392 Program *program = GetValidProgramNoResolve(context, entryPoint, id); 1393 if (program) 1394 { 1395 program->resolveLink(context); 1396 } 1397 return program; 1398 } 1399 1400 Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id) 1401 { 1402 // See ValidProgram for spec details. 1403 1404 Shader *validShader = context->getShader(id); 1405 1406 if (!validShader) 1407 { 1408 if (context->getProgramNoResolveLink(id)) 1409 { 1410 context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedShaderName); 1411 } 1412 else 1413 { 1414 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidShaderName); 1415 } 1416 } 1417 1418 return validShader; 1419 } 1420 1421 bool ValidateAttachmentTarget(const Context *context, 1422 angle::EntryPoint entryPoint, 1423 GLenum attachment) 1424 { 1425 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) 1426 { 1427 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffersEXT) 1428 { 1429 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 1430 return false; 1431 } 1432 1433 // Color attachment 0 is validated below because it is always valid 1434 const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); 1435 if (colorAttachment >= context->getCaps().maxColorAttachments) 1436 { 1437 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment); 1438 return false; 1439 } 1440 } 1441 else 1442 { 1443 switch (attachment) 1444 { 1445 case GL_COLOR_ATTACHMENT0: 1446 case GL_DEPTH_ATTACHMENT: 1447 case GL_STENCIL_ATTACHMENT: 1448 break; 1449 1450 case GL_DEPTH_STENCIL_ATTACHMENT: 1451 if (!context->isWebGL() && context->getClientMajorVersion() < 3) 1452 { 1453 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 1454 return false; 1455 } 1456 break; 1457 1458 default: 1459 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 1460 return false; 1461 } 1462 } 1463 1464 return true; 1465 } 1466 1467 bool ValidateRenderbufferStorageParametersBase(const Context *context, 1468 angle::EntryPoint entryPoint, 1469 GLenum target, 1470 GLsizei samples, 1471 GLenum internalformat, 1472 GLsizei width, 1473 GLsizei height) 1474 { 1475 switch (target) 1476 { 1477 case GL_RENDERBUFFER: 1478 break; 1479 default: 1480 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget); 1481 return false; 1482 } 1483 1484 if (width < 0 || height < 0 || samples < 0) 1485 { 1486 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight); 1487 return false; 1488 } 1489 1490 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format. 1491 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat); 1492 1493 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat); 1494 if (!formatCaps.renderbuffer) 1495 { 1496 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat); 1497 return false; 1498 } 1499 1500 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be 1501 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains 1502 // only sized internal formats. 1503 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat); 1504 if (formatInfo.internalFormat == GL_NONE) 1505 { 1506 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat); 1507 return false; 1508 } 1509 1510 if (std::max(width, height) > context->getCaps().maxRenderbufferSize) 1511 { 1512 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxRenderbufferSize); 1513 return false; 1514 } 1515 1516 RenderbufferID id = context->getState().getRenderbufferId(); 1517 if (id.value == 0) 1518 { 1519 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidRenderbufferTarget); 1520 return false; 1521 } 1522 1523 return true; 1524 } 1525 1526 bool ValidateBlitFramebufferParameters(const Context *context, 1527 angle::EntryPoint entryPoint, 1528 GLint srcX0, 1529 GLint srcY0, 1530 GLint srcX1, 1531 GLint srcY1, 1532 GLint dstX0, 1533 GLint dstY0, 1534 GLint dstX1, 1535 GLint dstY1, 1536 GLbitfield mask, 1537 GLenum filter) 1538 { 1539 switch (filter) 1540 { 1541 case GL_NEAREST: 1542 break; 1543 case GL_LINEAR: 1544 break; 1545 default: 1546 context->validationError(entryPoint, GL_INVALID_ENUM, kBlitInvalidFilter); 1547 return false; 1548 } 1549 1550 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) 1551 { 1552 context->validationError(entryPoint, GL_INVALID_VALUE, kBlitInvalidMask); 1553 return false; 1554 } 1555 1556 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the 1557 // color buffer, leaving only nearest being unfiltered from above 1558 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST) 1559 { 1560 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor); 1561 return false; 1562 } 1563 1564 const auto &glState = context->getState(); 1565 Framebuffer *readFramebuffer = glState.getReadFramebuffer(); 1566 Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); 1567 1568 if (!readFramebuffer || !drawFramebuffer) 1569 { 1570 context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, 1571 kBlitFramebufferMissing); 1572 return false; 1573 } 1574 1575 if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer)) 1576 { 1577 return false; 1578 } 1579 1580 if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer)) 1581 { 1582 return false; 1583 } 1584 1585 // EXT_YUV_target disallows blitting to or from a YUV framebuffer 1586 if ((mask & GL_COLOR_BUFFER_BIT) != 0 && 1587 (readFramebuffer->hasYUVAttachment() || drawFramebuffer->hasYUVAttachment())) 1588 { 1589 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitYUVFramebuffer); 1590 return false; 1591 } 1592 1593 // The draw and read framebuffers can only match if: 1594 // - They are the default framebuffer AND 1595 // - The read/draw surfaces are different 1596 if ((readFramebuffer->id() == drawFramebuffer->id()) && 1597 ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) || 1598 (context->getCurrentDrawSurface() == context->getCurrentReadSurface()))) 1599 { 1600 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitFeedbackLoop); 1601 return false; 1602 } 1603 1604 // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist, 1605 // consider it MS. checkReadBufferResourceSamples = false 1606 if (!ValidateFramebufferNotMultisampled(context, entryPoint, drawFramebuffer, false)) 1607 { 1608 return false; 1609 } 1610 1611 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we 1612 // always run it in order to avoid triggering driver bugs. 1613 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) || 1614 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1)) 1615 { 1616 context->validationError(entryPoint, GL_INVALID_VALUE, kBlitDimensionsOutOfRange); 1617 return false; 1618 } 1619 1620 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; 1621 1622 if (mask & GL_COLOR_BUFFER_BIT) 1623 { 1624 const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment(); 1625 const Extensions &extensions = context->getExtensions(); 1626 1627 if (readColorBuffer) 1628 { 1629 const Format &readFormat = readColorBuffer->getFormat(); 1630 1631 for (size_t drawbufferIdx = 0; 1632 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx) 1633 { 1634 const FramebufferAttachment *attachment = 1635 drawFramebuffer->getDrawBuffer(drawbufferIdx); 1636 if (attachment) 1637 { 1638 const Format &drawFormat = attachment->getFormat(); 1639 1640 // The GL ES 3.0.2 spec (pg 193) states that: 1641 // 1) If the read buffer is fixed point format, the draw buffer must be as well 1642 // 2) If the read buffer is an unsigned integer format, the draw buffer must be 1643 // as well 1644 // 3) If the read buffer is a signed integer format, the draw buffer must be as 1645 // well 1646 // Changes with EXT_color_buffer_float: 1647 // Case 1) is changed to fixed point OR floating point 1648 GLenum readComponentType = readFormat.info->componentType; 1649 GLenum drawComponentType = drawFormat.info->componentType; 1650 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED || 1651 readComponentType == GL_SIGNED_NORMALIZED); 1652 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED || 1653 drawComponentType == GL_SIGNED_NORMALIZED); 1654 1655 if (extensions.colorBufferFloatEXT) 1656 { 1657 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT); 1658 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT); 1659 1660 if (readFixedOrFloat != drawFixedOrFloat) 1661 { 1662 context->validationError(entryPoint, GL_INVALID_OPERATION, 1663 kBlitTypeMismatchFixedOrFloat); 1664 return false; 1665 } 1666 } 1667 else if (readFixedPoint != drawFixedPoint) 1668 { 1669 context->validationError(entryPoint, GL_INVALID_OPERATION, 1670 kBlitTypeMismatchFixedPoint); 1671 return false; 1672 } 1673 1674 if (readComponentType == GL_UNSIGNED_INT && 1675 drawComponentType != GL_UNSIGNED_INT) 1676 { 1677 context->validationError(entryPoint, GL_INVALID_OPERATION, 1678 kBlitTypeMismatchUnsignedInteger); 1679 return false; 1680 } 1681 1682 if (readComponentType == GL_INT && drawComponentType != GL_INT) 1683 { 1684 context->validationError(entryPoint, GL_INVALID_OPERATION, 1685 kBlitTypeMismatchSignedInteger); 1686 return false; 1687 } 1688 1689 if (readColorBuffer->getResourceSamples() > 0 && 1690 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds)) 1691 { 1692 context->validationError(entryPoint, GL_INVALID_OPERATION, 1693 kBlitMultisampledFormatOrBoundsMismatch); 1694 return false; 1695 } 1696 1697 if (context->isWebGL() && *readColorBuffer == *attachment) 1698 { 1699 context->validationError(entryPoint, GL_INVALID_OPERATION, 1700 kBlitSameImageColor); 1701 return false; 1702 } 1703 } 1704 } 1705 1706 if (readFormat.info->isInt() && filter == GL_LINEAR) 1707 { 1708 context->validationError(entryPoint, GL_INVALID_OPERATION, 1709 kBlitIntegerWithLinearFilter); 1710 return false; 1711 } 1712 } 1713 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment 1714 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing 1715 // attachment and WebGL defines it to be an error. We do the check unconditionally as the 1716 // situation is an application error that would lead to a crash in ANGLE. 1717 else if (drawFramebuffer->hasEnabledDrawBuffer()) 1718 { 1719 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitMissingColor); 1720 return false; 1721 } 1722 } 1723 1724 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT}; 1725 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; 1726 for (size_t i = 0; i < 2; i++) 1727 { 1728 if (mask & masks[i]) 1729 { 1730 const FramebufferAttachment *readBuffer = 1731 readFramebuffer->getAttachment(context, attachments[i]); 1732 const FramebufferAttachment *drawBuffer = 1733 drawFramebuffer->getAttachment(context, attachments[i]); 1734 1735 if (readBuffer && drawBuffer) 1736 { 1737 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat())) 1738 { 1739 context->validationError(entryPoint, GL_INVALID_OPERATION, 1740 kBlitDepthOrStencilFormatMismatch); 1741 return false; 1742 } 1743 1744 if (readBuffer->getResourceSamples() > 0 && !sameBounds) 1745 { 1746 context->validationError(entryPoint, GL_INVALID_OPERATION, 1747 kBlitMultisampledBoundsMismatch); 1748 return false; 1749 } 1750 1751 if (context->isWebGL() && *readBuffer == *drawBuffer) 1752 { 1753 context->validationError(entryPoint, GL_INVALID_OPERATION, 1754 kBlitSameImageDepthOrStencil); 1755 return false; 1756 } 1757 } 1758 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment 1759 else if (drawBuffer) 1760 { 1761 context->validationError(entryPoint, GL_INVALID_OPERATION, 1762 kBlitMissingDepthOrStencil); 1763 return false; 1764 } 1765 } 1766 } 1767 1768 // OVR_multiview2: 1769 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the 1770 // current draw framebuffer isMultiview() or the number of 1771 // views in the current read framebuffer is more than one. 1772 if (readFramebuffer->readDisallowedByMultiview()) 1773 { 1774 context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview); 1775 return false; 1776 } 1777 if (drawFramebuffer->isMultiview()) 1778 { 1779 context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview); 1780 return false; 1781 } 1782 1783 return true; 1784 } 1785 1786 bool ValidateBindFramebufferBase(const Context *context, 1787 angle::EntryPoint entryPoint, 1788 GLenum target, 1789 FramebufferID framebuffer) 1790 { 1791 if (!ValidFramebufferTarget(context, target)) 1792 { 1793 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 1794 return false; 1795 } 1796 1797 if (!context->getState().isBindGeneratesResourceEnabled() && 1798 !context->isFramebufferGenerated(framebuffer)) 1799 { 1800 context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated); 1801 return false; 1802 } 1803 1804 return true; 1805 } 1806 1807 bool ValidateBindRenderbufferBase(const Context *context, 1808 angle::EntryPoint entryPoint, 1809 GLenum target, 1810 RenderbufferID renderbuffer) 1811 { 1812 if (target != GL_RENDERBUFFER) 1813 { 1814 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget); 1815 return false; 1816 } 1817 1818 if (!context->getState().isBindGeneratesResourceEnabled() && 1819 !context->isRenderbufferGenerated(renderbuffer)) 1820 { 1821 context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated); 1822 return false; 1823 } 1824 1825 return true; 1826 } 1827 1828 bool ValidateFramebufferParameteriBase(const Context *context, 1829 angle::EntryPoint entryPoint, 1830 GLenum target, 1831 GLenum pname, 1832 GLint param) 1833 { 1834 if (!ValidFramebufferTarget(context, target)) 1835 { 1836 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 1837 return false; 1838 } 1839 1840 switch (pname) 1841 { 1842 case GL_FRAMEBUFFER_DEFAULT_WIDTH: 1843 { 1844 GLint maxWidth = context->getCaps().maxFramebufferWidth; 1845 if (param < 0 || param > maxWidth) 1846 { 1847 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferWidth); 1848 return false; 1849 } 1850 break; 1851 } 1852 case GL_FRAMEBUFFER_DEFAULT_HEIGHT: 1853 { 1854 GLint maxHeight = context->getCaps().maxFramebufferHeight; 1855 if (param < 0 || param > maxHeight) 1856 { 1857 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferHeight); 1858 return false; 1859 } 1860 break; 1861 } 1862 case GL_FRAMEBUFFER_DEFAULT_SAMPLES: 1863 { 1864 GLint maxSamples = context->getCaps().maxFramebufferSamples; 1865 if (param < 0 || param > maxSamples) 1866 { 1867 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferSamples); 1868 return false; 1869 } 1870 break; 1871 } 1872 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: 1873 { 1874 break; 1875 } 1876 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT: 1877 { 1878 if (!context->getExtensions().geometryShaderAny() && 1879 context->getClientVersion() < ES_3_2) 1880 { 1881 context->validationError(entryPoint, GL_INVALID_ENUM, 1882 kGeometryShaderExtensionNotEnabled); 1883 return false; 1884 } 1885 GLint maxLayers = context->getCaps().maxFramebufferLayers; 1886 if (param < 0 || param > maxLayers) 1887 { 1888 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferLayer); 1889 return false; 1890 } 1891 break; 1892 } 1893 case GL_FRAMEBUFFER_FLIP_Y_MESA: 1894 { 1895 if (!context->getExtensions().framebufferFlipYMESA) 1896 { 1897 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 1898 return false; 1899 } 1900 break; 1901 } 1902 default: 1903 { 1904 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 1905 return false; 1906 } 1907 } 1908 1909 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 1910 ASSERT(framebuffer); 1911 if (framebuffer->isDefault()) 1912 { 1913 context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebuffer); 1914 return false; 1915 } 1916 return true; 1917 } 1918 1919 bool ValidateFramebufferRenderbufferBase(const Context *context, 1920 angle::EntryPoint entryPoint, 1921 GLenum target, 1922 GLenum attachment, 1923 GLenum renderbuffertarget, 1924 RenderbufferID renderbuffer) 1925 { 1926 if (!ValidFramebufferTarget(context, target)) 1927 { 1928 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 1929 return false; 1930 } 1931 1932 if (renderbuffertarget != GL_RENDERBUFFER) 1933 { 1934 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget); 1935 return false; 1936 } 1937 1938 Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 1939 1940 ASSERT(framebuffer); 1941 if (framebuffer->isDefault()) 1942 { 1943 context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget); 1944 return false; 1945 } 1946 1947 if (!ValidateAttachmentTarget(context, entryPoint, attachment)) 1948 { 1949 return false; 1950 } 1951 1952 // [OpenGL ES 2.0.25] Section 4.4.3 page 112 1953 // [OpenGL ES 3.0.2] Section 4.4.2 page 201 1954 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of 1955 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. 1956 if (renderbuffer.value != 0) 1957 { 1958 if (!context->getRenderbuffer(renderbuffer)) 1959 { 1960 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidRenderbufferTarget); 1961 return false; 1962 } 1963 } 1964 1965 return true; 1966 } 1967 1968 bool ValidateFramebufferTextureBase(const Context *context, 1969 angle::EntryPoint entryPoint, 1970 GLenum target, 1971 GLenum attachment, 1972 TextureID texture, 1973 GLint level) 1974 { 1975 if (!ValidFramebufferTarget(context, target)) 1976 { 1977 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 1978 return false; 1979 } 1980 1981 if (!ValidateAttachmentTarget(context, entryPoint, attachment)) 1982 { 1983 return false; 1984 } 1985 1986 if (texture.value != 0) 1987 { 1988 Texture *tex = context->getTexture(texture); 1989 1990 if (tex == nullptr) 1991 { 1992 context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture); 1993 return false; 1994 } 1995 1996 if (level < 0) 1997 { 1998 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 1999 return false; 2000 } 2001 2002 // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer" 2003 // An INVALID_VALUE error is generated if texture is not zero and level is 2004 // not a supported texture level for textarget 2005 2006 // Common criteria for not supported texture levels(other criteria are handled case by case 2007 // in non base functions): If texture refers to an immutable-format texture, level must be 2008 // greater than or equal to zero and smaller than the value of TEXTURE_IMMUTABLE_LEVELS for 2009 // texture. 2010 if (tex->getImmutableFormat() && context->getClientVersion() >= ES_3_1) 2011 { 2012 if (level >= static_cast<GLint>(tex->getImmutableLevels())) 2013 { 2014 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 2015 return false; 2016 } 2017 } 2018 2019 // GLES spec 3.2, Section 9.2.8 "Attaching Texture Images to a Framebuffer" 2020 // An INVALID_OPERATION error is generated if <texture> is the name of a buffer texture. 2021 if ((context->getClientVersion() >= ES_3_2 || 2022 context->getExtensions().textureBufferAny()) && 2023 tex->getType() == TextureType::Buffer) 2024 { 2025 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget); 2026 return false; 2027 } 2028 2029 if (tex->getState().hasProtectedContent() != context->getState().hasProtectedContent()) 2030 { 2031 context->validationError( 2032 entryPoint, GL_INVALID_OPERATION, 2033 "Mismatch between Texture and Context Protected Content state"); 2034 return false; 2035 } 2036 } 2037 2038 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 2039 ASSERT(framebuffer); 2040 2041 if (framebuffer->isDefault()) 2042 { 2043 context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget); 2044 return false; 2045 } 2046 2047 return true; 2048 } 2049 2050 bool ValidateGenerateMipmapBase(const Context *context, 2051 angle::EntryPoint entryPoint, 2052 TextureType target) 2053 { 2054 if (!ValidTextureTarget(context, target)) 2055 { 2056 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 2057 return false; 2058 } 2059 2060 Texture *texture = context->getTextureByType(target); 2061 2062 if (texture == nullptr) 2063 { 2064 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotBound); 2065 return false; 2066 } 2067 2068 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel(); 2069 2070 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so 2071 // that out-of-range base level has a non-color-renderable / non-texture-filterable format. 2072 if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS) 2073 { 2074 context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelOutOfRange); 2075 return false; 2076 } 2077 2078 TextureTarget baseTarget = (target == TextureType::CubeMap) 2079 ? TextureTarget::CubeMapPositiveX 2080 : NonCubeTextureTypeToTarget(target); 2081 const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info); 2082 if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 || 2083 format.stencilBits > 0) 2084 { 2085 context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed); 2086 return false; 2087 } 2088 2089 // GenerateMipmap accepts formats that are unsized or both color renderable and filterable. 2090 bool formatUnsized = !format.sized; 2091 bool formatColorRenderableAndFilterable = 2092 format.filterSupport(context->getClientVersion(), context->getExtensions()) && 2093 format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions()); 2094 if (!formatUnsized && !formatColorRenderableAndFilterable) 2095 { 2096 context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed); 2097 return false; 2098 } 2099 2100 // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap 2101 // generation 2102 if (format.colorEncoding == GL_SRGB && format.format == GL_RGB) 2103 { 2104 context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed); 2105 return false; 2106 } 2107 2108 // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and 2109 // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT. 2110 if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB) 2111 { 2112 context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed); 2113 return false; 2114 } 2115 2116 // Non-power of 2 ES2 check 2117 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNpotOES && 2118 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) || 2119 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0))))) 2120 { 2121 ASSERT(target == TextureType::_2D || target == TextureType::Rectangle || 2122 target == TextureType::CubeMap); 2123 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotPow2); 2124 return false; 2125 } 2126 2127 // Cube completeness check 2128 if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete()) 2129 { 2130 context->validationError(entryPoint, GL_INVALID_OPERATION, kCubemapIncomplete); 2131 return false; 2132 } 2133 2134 if (context->isWebGL() && (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 || 2135 texture->getHeight(baseTarget, effectiveBaseLevel) == 0)) 2136 { 2137 context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapZeroSize); 2138 return false; 2139 } 2140 2141 return true; 2142 } 2143 2144 bool ValidateReadPixelsRobustANGLE(const Context *context, 2145 angle::EntryPoint entryPoint, 2146 GLint x, 2147 GLint y, 2148 GLsizei width, 2149 GLsizei height, 2150 GLenum format, 2151 GLenum type, 2152 GLsizei bufSize, 2153 const GLsizei *length, 2154 const GLsizei *columns, 2155 const GLsizei *rows, 2156 const void *pixels) 2157 { 2158 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2159 { 2160 return false; 2161 } 2162 2163 GLsizei writeLength = 0; 2164 GLsizei writeColumns = 0; 2165 GLsizei writeRows = 0; 2166 2167 if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize, 2168 &writeLength, &writeColumns, &writeRows, pixels)) 2169 { 2170 return false; 2171 } 2172 2173 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 2174 { 2175 return false; 2176 } 2177 2178 SetRobustLengthParam(length, writeLength); 2179 SetRobustLengthParam(columns, writeColumns); 2180 SetRobustLengthParam(rows, writeRows); 2181 2182 return true; 2183 } 2184 2185 bool ValidateReadnPixelsEXT(const Context *context, 2186 angle::EntryPoint entryPoint, 2187 GLint x, 2188 GLint y, 2189 GLsizei width, 2190 GLsizei height, 2191 GLenum format, 2192 GLenum type, 2193 GLsizei bufSize, 2194 const void *pixels) 2195 { 2196 if (bufSize < 0) 2197 { 2198 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 2199 return false; 2200 } 2201 2202 return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize, 2203 nullptr, nullptr, nullptr, pixels); 2204 } 2205 2206 bool ValidateReadnPixelsRobustANGLE(const Context *context, 2207 angle::EntryPoint entryPoint, 2208 GLint x, 2209 GLint y, 2210 GLsizei width, 2211 GLsizei height, 2212 GLenum format, 2213 GLenum type, 2214 GLsizei bufSize, 2215 const GLsizei *length, 2216 const GLsizei *columns, 2217 const GLsizei *rows, 2218 const void *data) 2219 { 2220 GLsizei writeLength = 0; 2221 GLsizei writeColumns = 0; 2222 GLsizei writeRows = 0; 2223 2224 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2225 { 2226 return false; 2227 } 2228 2229 if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize, 2230 &writeLength, &writeColumns, &writeRows, data)) 2231 { 2232 return false; 2233 } 2234 2235 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 2236 { 2237 return false; 2238 } 2239 2240 SetRobustLengthParam(length, writeLength); 2241 SetRobustLengthParam(columns, writeColumns); 2242 SetRobustLengthParam(rows, writeRows); 2243 2244 return true; 2245 } 2246 2247 bool ValidateGenQueriesEXT(const Context *context, 2248 angle::EntryPoint entryPoint, 2249 GLsizei n, 2250 const QueryID *ids) 2251 { 2252 if (!context->getExtensions().occlusionQueryBooleanEXT && 2253 !context->getExtensions().disjointTimerQueryEXT) 2254 { 2255 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled); 2256 return false; 2257 } 2258 2259 return ValidateGenOrDelete(context, entryPoint, n); 2260 } 2261 2262 bool ValidateDeleteQueriesEXT(const Context *context, 2263 angle::EntryPoint entryPoint, 2264 GLsizei n, 2265 const QueryID *ids) 2266 { 2267 if (!context->getExtensions().occlusionQueryBooleanEXT && 2268 !context->getExtensions().disjointTimerQueryEXT) 2269 { 2270 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled); 2271 return false; 2272 } 2273 2274 return ValidateGenOrDelete(context, entryPoint, n); 2275 } 2276 2277 bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id) 2278 { 2279 if (!context->getExtensions().occlusionQueryBooleanEXT && 2280 !context->getExtensions().disjointTimerQueryEXT) 2281 { 2282 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled); 2283 return false; 2284 } 2285 2286 return true; 2287 } 2288 2289 bool ValidateBeginQueryBase(const Context *context, 2290 angle::EntryPoint entryPoint, 2291 QueryType target, 2292 QueryID id) 2293 { 2294 if (!ValidQueryType(context, target)) 2295 { 2296 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType); 2297 return false; 2298 } 2299 2300 if (id.value == 0) 2301 { 2302 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId); 2303 return false; 2304 } 2305 2306 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id> 2307 // of zero, if the active query object name for <target> is non-zero (for the 2308 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if 2309 // the active query for either target is non-zero), if <id> is the name of an 2310 // existing query object whose type does not match <target>, or if <id> is the 2311 // active query object name for any query type, the error INVALID_OPERATION is 2312 // generated. 2313 2314 // Ensure no other queries are active 2315 // NOTE: If other queries than occlusion are supported, we will need to check 2316 // separately that: 2317 // a) The query ID passed is not the current active query for any target/type 2318 // b) There are no active queries for the requested target (and in the case 2319 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, 2320 // no query may be active for either if glBeginQuery targets either. 2321 2322 if (context->getState().isQueryActive(target)) 2323 { 2324 context->validationError(entryPoint, GL_INVALID_OPERATION, kOtherQueryActive); 2325 return false; 2326 } 2327 2328 // check that name was obtained with glGenQueries 2329 if (!context->isQueryGenerated(id)) 2330 { 2331 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId); 2332 return false; 2333 } 2334 2335 // Check for type mismatch. If query is not yet started we're good to go. 2336 Query *queryObject = context->getQuery(id); 2337 if (queryObject && queryObject->getType() != target) 2338 { 2339 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryTargetMismatch); 2340 return false; 2341 } 2342 2343 return true; 2344 } 2345 2346 bool ValidateBeginQueryEXT(const Context *context, 2347 angle::EntryPoint entryPoint, 2348 QueryType target, 2349 QueryID id) 2350 { 2351 if (!context->getExtensions().occlusionQueryBooleanEXT && 2352 !context->getExtensions().disjointTimerQueryEXT && 2353 !context->getExtensions().syncQueryCHROMIUM) 2354 { 2355 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled); 2356 return false; 2357 } 2358 2359 return ValidateBeginQueryBase(context, entryPoint, target, id); 2360 } 2361 2362 bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target) 2363 { 2364 if (!ValidQueryType(context, target)) 2365 { 2366 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType); 2367 return false; 2368 } 2369 2370 const Query *queryObject = context->getState().getActiveQuery(target); 2371 2372 if (queryObject == nullptr) 2373 { 2374 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryInactive); 2375 return false; 2376 } 2377 2378 return true; 2379 } 2380 2381 bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target) 2382 { 2383 if (!context->getExtensions().occlusionQueryBooleanEXT && 2384 !context->getExtensions().disjointTimerQueryEXT && 2385 !context->getExtensions().syncQueryCHROMIUM) 2386 { 2387 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled); 2388 return false; 2389 } 2390 2391 return ValidateEndQueryBase(context, entryPoint, target); 2392 } 2393 2394 bool ValidateQueryCounterEXT(const Context *context, 2395 angle::EntryPoint entryPoint, 2396 QueryID id, 2397 QueryType target) 2398 { 2399 if (!context->getExtensions().disjointTimerQueryEXT) 2400 { 2401 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2402 return false; 2403 } 2404 2405 if (target != QueryType::Timestamp) 2406 { 2407 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryTarget); 2408 return false; 2409 } 2410 2411 if (!context->isQueryGenerated(id)) 2412 { 2413 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId); 2414 return false; 2415 } 2416 2417 // If query object is not started, that's fine. 2418 Query *queryObject = context->getQuery(id); 2419 if (queryObject && context->getState().isQueryActive(queryObject)) 2420 { 2421 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryActive); 2422 return false; 2423 } 2424 2425 return true; 2426 } 2427 2428 bool ValidateGetQueryivBase(const Context *context, 2429 angle::EntryPoint entryPoint, 2430 QueryType target, 2431 GLenum pname, 2432 GLsizei *numParams) 2433 { 2434 if (numParams) 2435 { 2436 *numParams = 0; 2437 } 2438 2439 if (!ValidQueryType(context, target) && target != QueryType::Timestamp) 2440 { 2441 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType); 2442 return false; 2443 } 2444 2445 switch (pname) 2446 { 2447 case GL_CURRENT_QUERY_EXT: 2448 if (target == QueryType::Timestamp) 2449 { 2450 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryTarget); 2451 return false; 2452 } 2453 break; 2454 case GL_QUERY_COUNTER_BITS_EXT: 2455 if (!context->getExtensions().disjointTimerQueryEXT || 2456 (target != QueryType::Timestamp && target != QueryType::TimeElapsed)) 2457 { 2458 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 2459 return false; 2460 } 2461 break; 2462 default: 2463 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 2464 return false; 2465 } 2466 2467 if (numParams) 2468 { 2469 // All queries return only one value 2470 *numParams = 1; 2471 } 2472 2473 return true; 2474 } 2475 2476 bool ValidateGetQueryivEXT(const Context *context, 2477 angle::EntryPoint entryPoint, 2478 QueryType target, 2479 GLenum pname, 2480 const GLint *params) 2481 { 2482 if (!context->getExtensions().occlusionQueryBooleanEXT && 2483 !context->getExtensions().disjointTimerQueryEXT && 2484 !context->getExtensions().syncQueryCHROMIUM) 2485 { 2486 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2487 return false; 2488 } 2489 2490 return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr); 2491 } 2492 2493 bool ValidateGetQueryivRobustANGLE(const Context *context, 2494 angle::EntryPoint entryPoint, 2495 QueryType target, 2496 GLenum pname, 2497 GLsizei bufSize, 2498 const GLsizei *length, 2499 const GLint *params) 2500 { 2501 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2502 { 2503 return false; 2504 } 2505 2506 GLsizei numParams = 0; 2507 2508 if (!ValidateGetQueryivBase(context, entryPoint, target, pname, &numParams)) 2509 { 2510 return false; 2511 } 2512 2513 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 2514 { 2515 return false; 2516 } 2517 2518 SetRobustLengthParam(length, numParams); 2519 2520 return true; 2521 } 2522 2523 bool ValidateGetQueryObjectValueBase(const Context *context, 2524 angle::EntryPoint entryPoint, 2525 QueryID id, 2526 GLenum pname, 2527 GLsizei *numParams) 2528 { 2529 if (numParams) 2530 { 2531 *numParams = 1; 2532 } 2533 2534 if (context->isContextLost()) 2535 { 2536 context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost); 2537 2538 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) 2539 { 2540 // Generate an error but still return true, the context still needs to return a 2541 // value in this case. 2542 return true; 2543 } 2544 else 2545 { 2546 return false; 2547 } 2548 } 2549 2550 Query *queryObject = context->getQuery(id); 2551 2552 if (!queryObject) 2553 { 2554 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId); 2555 return false; 2556 } 2557 2558 if (context->getState().isQueryActive(queryObject)) 2559 { 2560 context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryActive); 2561 return false; 2562 } 2563 2564 switch (pname) 2565 { 2566 case GL_QUERY_RESULT_EXT: 2567 case GL_QUERY_RESULT_AVAILABLE_EXT: 2568 break; 2569 2570 default: 2571 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 2572 return false; 2573 } 2574 2575 return true; 2576 } 2577 2578 bool ValidateGetQueryObjectivEXT(const Context *context, 2579 angle::EntryPoint entryPoint, 2580 QueryID id, 2581 GLenum pname, 2582 const GLint *params) 2583 { 2584 if (!context->getExtensions().disjointTimerQueryEXT) 2585 { 2586 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2587 return false; 2588 } 2589 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); 2590 } 2591 2592 bool ValidateGetQueryObjectivRobustANGLE(const Context *context, 2593 angle::EntryPoint entryPoint, 2594 QueryID id, 2595 GLenum pname, 2596 GLsizei bufSize, 2597 const GLsizei *length, 2598 const GLint *params) 2599 { 2600 if (!context->getExtensions().disjointTimerQueryEXT) 2601 { 2602 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2603 return false; 2604 } 2605 2606 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2607 { 2608 return false; 2609 } 2610 2611 GLsizei numParams = 0; 2612 2613 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams)) 2614 { 2615 return false; 2616 } 2617 2618 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 2619 { 2620 return false; 2621 } 2622 2623 SetRobustLengthParam(length, numParams); 2624 2625 return true; 2626 } 2627 2628 bool ValidateGetQueryObjectuivEXT(const Context *context, 2629 angle::EntryPoint entryPoint, 2630 QueryID id, 2631 GLenum pname, 2632 const GLuint *params) 2633 { 2634 if (!context->getExtensions().disjointTimerQueryEXT && 2635 !context->getExtensions().occlusionQueryBooleanEXT && 2636 !context->getExtensions().syncQueryCHROMIUM) 2637 { 2638 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2639 return false; 2640 } 2641 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); 2642 } 2643 2644 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context, 2645 angle::EntryPoint entryPoint, 2646 QueryID id, 2647 GLenum pname, 2648 GLsizei bufSize, 2649 const GLsizei *length, 2650 const GLuint *params) 2651 { 2652 if (!context->getExtensions().disjointTimerQueryEXT && 2653 !context->getExtensions().occlusionQueryBooleanEXT && 2654 !context->getExtensions().syncQueryCHROMIUM) 2655 { 2656 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2657 return false; 2658 } 2659 2660 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2661 { 2662 return false; 2663 } 2664 2665 GLsizei numParams = 0; 2666 2667 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams)) 2668 { 2669 return false; 2670 } 2671 2672 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 2673 { 2674 return false; 2675 } 2676 2677 SetRobustLengthParam(length, numParams); 2678 2679 return true; 2680 } 2681 2682 bool ValidateGetQueryObjecti64vEXT(const Context *context, 2683 angle::EntryPoint entryPoint, 2684 QueryID id, 2685 GLenum pname, 2686 GLint64 *params) 2687 { 2688 if (!context->getExtensions().disjointTimerQueryEXT) 2689 { 2690 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2691 return false; 2692 } 2693 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); 2694 } 2695 2696 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context, 2697 angle::EntryPoint entryPoint, 2698 QueryID id, 2699 GLenum pname, 2700 GLsizei bufSize, 2701 const GLsizei *length, 2702 GLint64 *params) 2703 { 2704 if (!context->getExtensions().disjointTimerQueryEXT) 2705 { 2706 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2707 return false; 2708 } 2709 2710 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2711 { 2712 return false; 2713 } 2714 2715 GLsizei numParams = 0; 2716 2717 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams)) 2718 { 2719 return false; 2720 } 2721 2722 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 2723 { 2724 return false; 2725 } 2726 2727 SetRobustLengthParam(length, numParams); 2728 2729 return true; 2730 } 2731 2732 bool ValidateGetQueryObjectui64vEXT(const Context *context, 2733 angle::EntryPoint entryPoint, 2734 QueryID id, 2735 GLenum pname, 2736 GLuint64 *params) 2737 { 2738 if (!context->getExtensions().disjointTimerQueryEXT) 2739 { 2740 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2741 return false; 2742 } 2743 return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr); 2744 } 2745 2746 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context, 2747 angle::EntryPoint entryPoint, 2748 QueryID id, 2749 GLenum pname, 2750 GLsizei bufSize, 2751 const GLsizei *length, 2752 GLuint64 *params) 2753 { 2754 if (!context->getExtensions().disjointTimerQueryEXT) 2755 { 2756 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2757 return false; 2758 } 2759 2760 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2761 { 2762 return false; 2763 } 2764 2765 GLsizei numParams = 0; 2766 2767 if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams)) 2768 { 2769 return false; 2770 } 2771 2772 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 2773 { 2774 return false; 2775 } 2776 2777 SetRobustLengthParam(length, numParams); 2778 2779 return true; 2780 } 2781 2782 bool ValidateUniformCommonBase(const Context *context, 2783 angle::EntryPoint entryPoint, 2784 const Program *program, 2785 UniformLocation location, 2786 GLsizei count, 2787 const LinkedUniform **uniformOut) 2788 { 2789 // TODO(Jiajia): Add image uniform check in future. 2790 if (count < 0) 2791 { 2792 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); 2793 return false; 2794 } 2795 2796 if (!program) 2797 { 2798 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidProgramName); 2799 return false; 2800 } 2801 2802 if (!program->isLinked()) 2803 { 2804 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 2805 return false; 2806 } 2807 2808 if (location.value == -1) 2809 { 2810 // Silently ignore the uniform command 2811 return false; 2812 } 2813 2814 const auto &uniformLocations = program->getUniformLocations(); 2815 size_t castedLocation = static_cast<size_t>(location.value); 2816 if (castedLocation >= uniformLocations.size()) 2817 { 2818 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation); 2819 return false; 2820 } 2821 2822 const auto &uniformLocation = uniformLocations[castedLocation]; 2823 if (uniformLocation.ignored) 2824 { 2825 // Silently ignore the uniform command 2826 return false; 2827 } 2828 2829 if (!uniformLocation.used()) 2830 { 2831 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation); 2832 return false; 2833 } 2834 2835 const auto &uniform = program->getUniformByIndex(uniformLocation.index); 2836 2837 // attempting to write an array to a non-array uniform is an INVALID_OPERATION 2838 if (count > 1 && !uniform.isArray()) 2839 { 2840 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformCount); 2841 return false; 2842 } 2843 2844 *uniformOut = &uniform; 2845 return true; 2846 } 2847 2848 bool ValidateUniform1ivValue(const Context *context, 2849 angle::EntryPoint entryPoint, 2850 GLenum uniformType, 2851 GLsizei count, 2852 const GLint *value) 2853 { 2854 // Value type is GL_INT, because we only get here from glUniform1i{v}. 2855 // It is compatible with INT or BOOL. 2856 // Do these cheap tests first, for a little extra speed. 2857 if (GL_INT == uniformType || GL_BOOL == uniformType) 2858 { 2859 return true; 2860 } 2861 2862 if (IsSamplerType(uniformType)) 2863 { 2864 // Check that the values are in range. 2865 const GLint max = context->getCaps().maxCombinedTextureImageUnits; 2866 for (GLsizei i = 0; i < count; ++i) 2867 { 2868 if (value[i] < 0 || value[i] >= max) 2869 { 2870 context->validationError(entryPoint, GL_INVALID_VALUE, 2871 kSamplerUniformValueOutOfRange); 2872 return false; 2873 } 2874 } 2875 return true; 2876 } 2877 2878 context->validationError(entryPoint, GL_INVALID_OPERATION, kUniformTypeMismatch); 2879 return false; 2880 } 2881 2882 bool ValidateUniformMatrixValue(const Context *context, 2883 angle::EntryPoint entryPoint, 2884 GLenum valueType, 2885 GLenum uniformType) 2886 { 2887 // Check that the value type is compatible with uniform type. 2888 if (valueType == uniformType) 2889 { 2890 return true; 2891 } 2892 2893 context->validationError(entryPoint, GL_INVALID_OPERATION, kUniformTypeMismatch); 2894 return false; 2895 } 2896 2897 bool ValidateUniform(const Context *context, 2898 angle::EntryPoint entryPoint, 2899 GLenum valueType, 2900 UniformLocation location, 2901 GLsizei count) 2902 { 2903 const LinkedUniform *uniform = nullptr; 2904 Program *programObject = context->getActiveLinkedProgram(); 2905 return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, 2906 &uniform) && 2907 ValidateUniformValue(context, entryPoint, valueType, uniform->type); 2908 } 2909 2910 bool ValidateUniform1iv(const Context *context, 2911 angle::EntryPoint entryPoint, 2912 UniformLocation location, 2913 GLsizei count, 2914 const GLint *value) 2915 { 2916 const LinkedUniform *uniform = nullptr; 2917 Program *programObject = context->getActiveLinkedProgram(); 2918 return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, 2919 &uniform) && 2920 ValidateUniform1ivValue(context, entryPoint, uniform->type, count, value); 2921 } 2922 2923 bool ValidateUniformMatrix(const Context *context, 2924 angle::EntryPoint entryPoint, 2925 GLenum valueType, 2926 UniformLocation location, 2927 GLsizei count, 2928 GLboolean transpose) 2929 { 2930 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3) 2931 { 2932 context->validationError(entryPoint, GL_INVALID_VALUE, kES3Required); 2933 return false; 2934 } 2935 2936 const LinkedUniform *uniform = nullptr; 2937 Program *programObject = context->getActiveLinkedProgram(); 2938 return ValidateUniformCommonBase(context, entryPoint, programObject, location, count, 2939 &uniform) && 2940 ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->type); 2941 } 2942 2943 bool ValidateStateQuery(const Context *context, 2944 angle::EntryPoint entryPoint, 2945 GLenum pname, 2946 GLenum *nativeType, 2947 unsigned int *numParams) 2948 { 2949 if (!context->getQueryParameterInfo(pname, nativeType, numParams)) 2950 { 2951 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 2952 return false; 2953 } 2954 2955 const Caps &caps = context->getCaps(); 2956 2957 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) 2958 { 2959 int colorAttachment = (pname - GL_DRAW_BUFFER0); 2960 2961 if (colorAttachment >= caps.maxDrawBuffers) 2962 { 2963 context->validationError(entryPoint, GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer); 2964 return false; 2965 } 2966 } 2967 2968 switch (pname) 2969 { 2970 case GL_TEXTURE_BINDING_2D: 2971 case GL_TEXTURE_BINDING_CUBE_MAP: 2972 case GL_TEXTURE_BINDING_3D: 2973 case GL_TEXTURE_BINDING_2D_ARRAY: 2974 case GL_TEXTURE_BINDING_2D_MULTISAMPLE: 2975 break; 2976 case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY: 2977 if (!context->getExtensions().textureStorageMultisample2dArrayOES) 2978 { 2979 context->validationError(entryPoint, GL_INVALID_ENUM, 2980 kMultisampleArrayExtensionRequired); 2981 return false; 2982 } 2983 break; 2984 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE: 2985 if (!context->getExtensions().textureRectangleANGLE) 2986 { 2987 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 2988 return false; 2989 } 2990 break; 2991 case GL_TEXTURE_BINDING_EXTERNAL_OES: 2992 if (!context->getExtensions().EGLStreamConsumerExternalNV && 2993 !context->getExtensions().EGLImageExternalOES) 2994 { 2995 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 2996 return false; 2997 } 2998 break; 2999 case GL_TEXTURE_BUFFER_BINDING: 3000 case GL_TEXTURE_BINDING_BUFFER: 3001 case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT: 3002 case GL_MAX_TEXTURE_BUFFER_SIZE: 3003 if (context->getClientVersion() < Version(3, 2) && 3004 !context->getExtensions().textureBufferAny()) 3005 { 3006 context->validationError(entryPoint, GL_INVALID_ENUM, 3007 kTextureBufferExtensionNotAvailable); 3008 return false; 3009 } 3010 break; 3011 3012 case GL_IMPLEMENTATION_COLOR_READ_TYPE: 3013 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: 3014 { 3015 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); 3016 ASSERT(readFramebuffer); 3017 3018 if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, entryPoint, 3019 readFramebuffer)) 3020 { 3021 return false; 3022 } 3023 3024 if (readFramebuffer->getReadBufferState() == GL_NONE) 3025 { 3026 context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone); 3027 return false; 3028 } 3029 3030 const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment(); 3031 if (!attachment) 3032 { 3033 context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNotAttached); 3034 return false; 3035 } 3036 } 3037 break; 3038 3039 case GL_PRIMITIVE_BOUNDING_BOX: 3040 if (!context->getExtensions().primitiveBoundingBoxAny()) 3041 { 3042 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 3043 return false; 3044 } 3045 break; 3046 3047 case GL_SHADING_RATE_QCOM: 3048 if (!context->getExtensions().shadingRateQCOM) 3049 { 3050 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 3051 return false; 3052 } 3053 break; 3054 3055 default: 3056 break; 3057 } 3058 3059 // pname is valid, but there are no parameters to return 3060 if (*numParams == 0) 3061 { 3062 return false; 3063 } 3064 3065 return true; 3066 } 3067 3068 bool ValidateGetBooleanvRobustANGLE(const Context *context, 3069 angle::EntryPoint entryPoint, 3070 GLenum pname, 3071 GLsizei bufSize, 3072 const GLsizei *length, 3073 const GLboolean *params) 3074 { 3075 GLenum nativeType; 3076 unsigned int numParams = 0; 3077 3078 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams)) 3079 { 3080 return false; 3081 } 3082 3083 SetRobustLengthParam(length, numParams); 3084 3085 return true; 3086 } 3087 3088 bool ValidateGetFloatvRobustANGLE(const Context *context, 3089 angle::EntryPoint entryPoint, 3090 GLenum pname, 3091 GLsizei bufSize, 3092 const GLsizei *length, 3093 const GLfloat *params) 3094 { 3095 GLenum nativeType; 3096 unsigned int numParams = 0; 3097 3098 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams)) 3099 { 3100 return false; 3101 } 3102 3103 SetRobustLengthParam(length, numParams); 3104 3105 return true; 3106 } 3107 3108 bool ValidateGetIntegervRobustANGLE(const Context *context, 3109 angle::EntryPoint entryPoint, 3110 GLenum pname, 3111 GLsizei bufSize, 3112 const GLsizei *length, 3113 const GLint *data) 3114 { 3115 GLenum nativeType; 3116 unsigned int numParams = 0; 3117 3118 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams)) 3119 { 3120 return false; 3121 } 3122 3123 SetRobustLengthParam(length, numParams); 3124 3125 return true; 3126 } 3127 3128 bool ValidateGetInteger64vRobustANGLE(const Context *context, 3129 angle::EntryPoint entryPoint, 3130 GLenum pname, 3131 GLsizei bufSize, 3132 const GLsizei *length, 3133 GLint64 *data) 3134 { 3135 GLenum nativeType; 3136 unsigned int numParams = 0; 3137 3138 if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams)) 3139 { 3140 return false; 3141 } 3142 3143 if (nativeType == GL_INT_64_ANGLEX) 3144 { 3145 CastStateValues(context, nativeType, pname, numParams, data); 3146 return false; 3147 } 3148 3149 SetRobustLengthParam(length, numParams); 3150 return true; 3151 } 3152 3153 bool ValidateRobustStateQuery(const Context *context, 3154 angle::EntryPoint entryPoint, 3155 GLenum pname, 3156 GLsizei bufSize, 3157 GLenum *nativeType, 3158 unsigned int *numParams) 3159 { 3160 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 3161 { 3162 return false; 3163 } 3164 3165 if (!ValidateStateQuery(context, entryPoint, pname, nativeType, numParams)) 3166 { 3167 return false; 3168 } 3169 3170 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, *numParams)) 3171 { 3172 return false; 3173 } 3174 3175 return true; 3176 } 3177 3178 bool ValidateCopyImageSubDataTarget(const Context *context, 3179 angle::EntryPoint entryPoint, 3180 GLuint name, 3181 GLenum target) 3182 { 3183 // From EXT_copy_image: INVALID_ENUM is generated if either <srcTarget> or <dstTarget> is not 3184 // RENDERBUFFER or a valid non - proxy texture target, is TEXTURE_BUFFER, or is one of the 3185 // cubemap face selectors described in table 3.17, or if the target does not match the type of 3186 // the object. INVALID_VALUE is generated if either <srcName> or <dstName> does not correspond 3187 // to a valid renderbuffer or texture object according to the corresponding target parameter. 3188 switch (target) 3189 { 3190 case GL_RENDERBUFFER: 3191 { 3192 RenderbufferID renderbuffer = PackParam<RenderbufferID>(name); 3193 if (!context->isRenderbuffer(renderbuffer)) 3194 { 3195 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferName); 3196 return false; 3197 } 3198 break; 3199 } 3200 case GL_TEXTURE_2D: 3201 case GL_TEXTURE_3D: 3202 case GL_TEXTURE_2D_ARRAY: 3203 case GL_TEXTURE_CUBE_MAP: 3204 case GL_TEXTURE_CUBE_MAP_ARRAY_EXT: 3205 { 3206 TextureID texture = PackParam<TextureID>(name); 3207 if (!context->isTexture(texture)) 3208 { 3209 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName); 3210 return false; 3211 } 3212 3213 Texture *textureObject = context->getTexture(texture); 3214 if (textureObject && textureObject->getType() != PackParam<TextureType>(target)) 3215 { 3216 context->validationError(entryPoint, GL_INVALID_ENUM, err::kTextureTypeMismatch); 3217 return false; 3218 } 3219 break; 3220 } 3221 default: 3222 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget); 3223 return false; 3224 } 3225 3226 return true; 3227 } 3228 3229 bool ValidateCopyImageSubDataLevel(const Context *context, 3230 angle::EntryPoint entryPoint, 3231 GLenum target, 3232 GLint level) 3233 { 3234 switch (target) 3235 { 3236 case GL_RENDERBUFFER: 3237 { 3238 if (level != 0) 3239 { 3240 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 3241 return false; 3242 } 3243 break; 3244 } 3245 case GL_TEXTURE_2D: 3246 case GL_TEXTURE_3D: 3247 case GL_TEXTURE_2D_ARRAY: 3248 case GL_TEXTURE_CUBE_MAP: 3249 case GL_TEXTURE_CUBE_MAP_ARRAY_EXT: 3250 { 3251 if (!ValidMipLevel(context, PackParam<TextureType>(target), level)) 3252 { 3253 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 3254 return false; 3255 } 3256 break; 3257 } 3258 default: 3259 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget); 3260 return false; 3261 } 3262 3263 return true; 3264 } 3265 3266 bool ValidateCopyImageSubDataTargetRegion(const Context *context, 3267 angle::EntryPoint entryPoint, 3268 GLuint name, 3269 GLenum target, 3270 GLint level, 3271 GLint offsetX, 3272 GLint offsetY, 3273 GLint offsetZ, 3274 GLsizei width, 3275 GLsizei height, 3276 GLsizei *samples) 3277 { 3278 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries 3279 // of the corresponding image object. 3280 if (offsetX < 0 || offsetY < 0 || offsetZ < 0) 3281 { 3282 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 3283 return false; 3284 } 3285 3286 if (target == GL_RENDERBUFFER) 3287 { 3288 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the 3289 // boundaries of the corresponding image object 3290 Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name)); 3291 if ((buffer->getWidth() - offsetX < width) || (buffer->getHeight() - offsetY < height)) 3292 { 3293 context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall); 3294 return false; 3295 } 3296 } 3297 else 3298 { 3299 Texture *texture = context->getTexture(PackParam<TextureID>(name)); 3300 3301 // INVALID_OPERATION is generated if either object is a texture and the texture is not 3302 // complete 3303 // This will handle the texture completeness check. Note that this ignores format-based 3304 // compleness rules. 3305 if (!texture->isSamplerCompleteForCopyImage(context, nullptr)) 3306 { 3307 context->validationError(entryPoint, GL_INVALID_OPERATION, kNotTextureComplete); 3308 return false; 3309 } 3310 3311 GLenum textureTargetToUse = target; 3312 if (target == GL_TEXTURE_CUBE_MAP) 3313 { 3314 // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight 3315 textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X; 3316 } 3317 3318 const GLsizei textureWidth = static_cast<GLsizei>( 3319 texture->getWidth(PackParam<TextureTarget>(textureTargetToUse), level)); 3320 const GLsizei textureHeight = static_cast<GLsizei>( 3321 texture->getHeight(PackParam<TextureTarget>(textureTargetToUse), level)); 3322 3323 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the 3324 // boundaries of the corresponding image object 3325 if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height)) 3326 { 3327 context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall); 3328 return false; 3329 } 3330 3331 *samples = texture->getSamples(PackParam<TextureTarget>(textureTargetToUse), level); 3332 *samples = (*samples == 0) ? 1 : *samples; 3333 } 3334 3335 return true; 3336 } 3337 3338 bool ValidateCompressedRegion(const Context *context, 3339 angle::EntryPoint entryPoint, 3340 const InternalFormat &formatInfo, 3341 GLsizei width, 3342 GLsizei height) 3343 { 3344 ASSERT(formatInfo.compressed); 3345 3346 // INVALID_VALUE is generated if the image format is compressed and the dimensions of the 3347 // subregion fail to meet the alignment constraints of the format. 3348 if ((width % formatInfo.compressedBlockWidth != 0) || 3349 (height % formatInfo.compressedBlockHeight != 0)) 3350 { 3351 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedRegionSize); 3352 return false; 3353 } 3354 3355 return true; 3356 } 3357 3358 const InternalFormat &GetTargetFormatInfo(const Context *context, 3359 angle::EntryPoint entryPoint, 3360 GLuint name, 3361 GLenum target, 3362 GLint level) 3363 { 3364 static const InternalFormat defaultInternalFormat; 3365 3366 switch (target) 3367 { 3368 case GL_RENDERBUFFER: 3369 { 3370 Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name)); 3371 return *buffer->getFormat().info; 3372 } 3373 case GL_TEXTURE_2D: 3374 case GL_TEXTURE_3D: 3375 case GL_TEXTURE_2D_ARRAY: 3376 case GL_TEXTURE_CUBE_MAP: 3377 case GL_TEXTURE_CUBE_MAP_ARRAY_EXT: 3378 { 3379 Texture *texture = context->getTexture(PackParam<TextureID>(name)); 3380 GLenum textureTargetToUse = target; 3381 3382 if (target == GL_TEXTURE_CUBE_MAP) 3383 { 3384 // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the 3385 // textureWidth/textureHeight 3386 textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X; 3387 } 3388 return *texture->getFormat(PackParam<TextureTarget>(textureTargetToUse), level).info; 3389 } 3390 default: 3391 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget); 3392 return defaultInternalFormat; 3393 } 3394 } 3395 3396 bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compressedFormat) 3397 { 3398 // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the 3399 // EXT_copy_image spec. 3400 switch (compressedFormat) 3401 { 3402 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 3403 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 3404 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 3405 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 3406 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: 3407 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 3408 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT: 3409 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 3410 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 3411 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 3412 case GL_COMPRESSED_RGBA8_ETC2_EAC: 3413 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 3414 case GL_COMPRESSED_RG11_EAC: 3415 case GL_COMPRESSED_SIGNED_RG11_EAC: 3416 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: 3417 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: 3418 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: 3419 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: 3420 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: 3421 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: 3422 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: 3423 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: 3424 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: 3425 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: 3426 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: 3427 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: 3428 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: 3429 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: 3430 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: 3431 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: 3432 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: 3433 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: 3434 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: 3435 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: 3436 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: 3437 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: 3438 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: 3439 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: 3440 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: 3441 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: 3442 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: 3443 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: 3444 case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES: 3445 case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES: 3446 case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES: 3447 case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES: 3448 case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES: 3449 case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES: 3450 case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES: 3451 case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES: 3452 case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES: 3453 case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES: 3454 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES: 3455 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES: 3456 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES: 3457 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES: 3458 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES: 3459 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES: 3460 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES: 3461 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES: 3462 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES: 3463 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES: 3464 { 3465 switch (uncompressedFormat) 3466 { 3467 case GL_RGBA32UI: 3468 case GL_RGBA32I: 3469 case GL_RGBA32F: 3470 return true; 3471 default: 3472 return false; 3473 } 3474 } 3475 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 3476 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 3477 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 3478 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 3479 case GL_COMPRESSED_RED_RGTC1_EXT: 3480 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: 3481 case GL_COMPRESSED_RGB8_ETC2: 3482 case GL_COMPRESSED_SRGB8_ETC2: 3483 case GL_COMPRESSED_R11_EAC: 3484 case GL_COMPRESSED_SIGNED_R11_EAC: 3485 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 3486 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 3487 { 3488 switch (uncompressedFormat) 3489 { 3490 case GL_RGBA16UI: 3491 case GL_RGBA16I: 3492 case GL_RGBA16F: 3493 case GL_RG32UI: 3494 case GL_RG32I: 3495 case GL_RG32F: 3496 return true; 3497 default: 3498 return false; 3499 } 3500 } 3501 default: 3502 break; 3503 } 3504 3505 return false; 3506 } 3507 3508 bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo, 3509 const InternalFormat &dstFormatInfo) 3510 { 3511 // Validates compressed format compatibility from Table 4.X.2 of the EXT_copy_image spec. 3512 3513 ASSERT(srcFormatInfo.internalFormat != dstFormatInfo.internalFormat); 3514 3515 const GLenum srcFormat = srcFormatInfo.internalFormat; 3516 const GLenum dstFormat = dstFormatInfo.internalFormat; 3517 3518 switch (srcFormat) 3519 { 3520 case GL_COMPRESSED_RED_RGTC1_EXT: 3521 return (dstFormat == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT); 3522 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: 3523 return (dstFormat == GL_COMPRESSED_RED_RGTC1_EXT); 3524 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: 3525 return (dstFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT); 3526 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 3527 return (dstFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT); 3528 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 3529 return (dstFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT); 3530 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 3531 return (dstFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT); 3532 case GL_COMPRESSED_R11_EAC: 3533 return (dstFormat == GL_COMPRESSED_SIGNED_R11_EAC); 3534 case GL_COMPRESSED_SIGNED_R11_EAC: 3535 return (dstFormat == GL_COMPRESSED_R11_EAC); 3536 case GL_COMPRESSED_RG11_EAC: 3537 return (dstFormat == GL_COMPRESSED_SIGNED_RG11_EAC); 3538 case GL_COMPRESSED_SIGNED_RG11_EAC: 3539 return (dstFormat == GL_COMPRESSED_RG11_EAC); 3540 default: 3541 break; 3542 } 3543 3544 // Since they can't be the same format and are both compressed formats, one must be linear and 3545 // the other nonlinear. 3546 if (srcFormatInfo.colorEncoding == dstFormatInfo.colorEncoding) 3547 { 3548 return false; 3549 } 3550 3551 const GLenum linearFormat = (srcFormatInfo.colorEncoding == GL_LINEAR) ? srcFormat : dstFormat; 3552 const GLenum nonLinearFormat = 3553 (srcFormatInfo.colorEncoding != GL_LINEAR) ? srcFormat : dstFormat; 3554 3555 switch (linearFormat) 3556 { 3557 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT: 3558 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT); 3559 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 3560 return (nonLinearFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT); 3561 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 3562 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT); 3563 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 3564 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT); 3565 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 3566 return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT); 3567 case GL_COMPRESSED_RGB8_ETC2: 3568 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ETC2); 3569 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 3570 return (nonLinearFormat == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2); 3571 case GL_COMPRESSED_RGBA8_ETC2_EAC: 3572 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC); 3573 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: 3574 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR); 3575 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: 3576 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR); 3577 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: 3578 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR); 3579 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: 3580 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR); 3581 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: 3582 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR); 3583 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: 3584 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR); 3585 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: 3586 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR); 3587 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: 3588 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR); 3589 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: 3590 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR); 3591 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: 3592 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR); 3593 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: 3594 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR); 3595 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: 3596 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR); 3597 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: 3598 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR); 3599 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: 3600 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR); 3601 case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES: 3602 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES); 3603 case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES: 3604 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES); 3605 case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES: 3606 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES); 3607 case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES: 3608 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES); 3609 case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES: 3610 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES); 3611 case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES: 3612 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES); 3613 case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES: 3614 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES); 3615 case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES: 3616 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES); 3617 case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES: 3618 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES); 3619 case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES: 3620 return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES); 3621 default: 3622 break; 3623 } 3624 3625 return false; 3626 } 3627 3628 bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo, 3629 const InternalFormat &dstFormatInfo) 3630 { 3631 // Matching source and destination formats are compatible. 3632 if (srcFormatInfo.internalFormat == dstFormatInfo.internalFormat) 3633 { 3634 return true; 3635 } 3636 3637 if (srcFormatInfo.compressed != dstFormatInfo.compressed) 3638 { 3639 GLenum uncompressedFormat = (!srcFormatInfo.compressed) ? srcFormatInfo.internalFormat 3640 : dstFormatInfo.internalFormat; 3641 GLenum compressedFormat = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat 3642 : dstFormatInfo.internalFormat; 3643 3644 return ValidateCopyMixedFormatCompatible(uncompressedFormat, compressedFormat); 3645 } 3646 3647 if (!srcFormatInfo.compressed) 3648 { 3649 // Source and destination are uncompressed formats. 3650 return (srcFormatInfo.pixelBytes == dstFormatInfo.pixelBytes); 3651 } 3652 3653 return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo); 3654 } 3655 3656 bool ValidateCopyImageSubDataBase(const Context *context, 3657 angle::EntryPoint entryPoint, 3658 GLuint srcName, 3659 GLenum srcTarget, 3660 GLint srcLevel, 3661 GLint srcX, 3662 GLint srcY, 3663 GLint srcZ, 3664 GLuint dstName, 3665 GLenum dstTarget, 3666 GLint dstLevel, 3667 GLint dstX, 3668 GLint dstY, 3669 GLint dstZ, 3670 GLsizei srcWidth, 3671 GLsizei srcHeight, 3672 GLsizei srcDepth) 3673 { 3674 // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries 3675 // of the corresponding image object 3676 if ((srcWidth < 0) || (srcHeight < 0) || (srcDepth < 0)) 3677 { 3678 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 3679 return false; 3680 } 3681 3682 if (!ValidateCopyImageSubDataTarget(context, entryPoint, srcName, srcTarget)) 3683 { 3684 return false; 3685 } 3686 if (!ValidateCopyImageSubDataTarget(context, entryPoint, dstName, dstTarget)) 3687 { 3688 return false; 3689 } 3690 3691 if (!ValidateCopyImageSubDataLevel(context, entryPoint, srcTarget, srcLevel)) 3692 { 3693 return false; 3694 } 3695 if (!ValidateCopyImageSubDataLevel(context, entryPoint, dstTarget, dstLevel)) 3696 { 3697 return false; 3698 } 3699 3700 const InternalFormat &srcFormatInfo = 3701 GetTargetFormatInfo(context, entryPoint, srcName, srcTarget, srcLevel); 3702 const InternalFormat &dstFormatInfo = 3703 GetTargetFormatInfo(context, entryPoint, dstName, dstTarget, dstLevel); 3704 GLsizei dstWidth = srcWidth; 3705 GLsizei dstHeight = srcHeight; 3706 GLsizei srcSamples = 1; 3707 GLsizei dstSamples = 1; 3708 3709 if (srcFormatInfo.internalFormat == GL_NONE || dstFormatInfo.internalFormat == GL_NONE) 3710 { 3711 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureLevel); 3712 return false; 3713 } 3714 3715 if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel, 3716 srcX, srcY, srcZ, srcWidth, srcHeight, &srcSamples)) 3717 { 3718 return false; 3719 } 3720 3721 // When copying from a compressed image to an uncompressed image the image texel dimensions 3722 // written to the uncompressed image will be source extent divided by the compressed texel block 3723 // dimensions. 3724 if ((srcFormatInfo.compressed) && (!dstFormatInfo.compressed)) 3725 { 3726 ASSERT(srcFormatInfo.compressedBlockWidth != 0); 3727 ASSERT(srcFormatInfo.compressedBlockHeight != 0); 3728 3729 dstWidth /= srcFormatInfo.compressedBlockWidth; 3730 dstHeight /= srcFormatInfo.compressedBlockHeight; 3731 } 3732 // When copying from an uncompressed image to a compressed image the image texel dimensions 3733 // written to the compressed image will be the source extent multiplied by the compressed texel 3734 // block dimensions. 3735 else if ((!srcFormatInfo.compressed) && (dstFormatInfo.compressed)) 3736 { 3737 dstWidth *= dstFormatInfo.compressedBlockWidth; 3738 dstHeight *= dstFormatInfo.compressedBlockHeight; 3739 } 3740 3741 if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel, 3742 dstX, dstY, dstZ, dstWidth, dstHeight, &dstSamples)) 3743 { 3744 return false; 3745 } 3746 3747 bool fillsEntireMip = false; 3748 gl::Texture *dstTexture = context->getTexture({dstName}); 3749 gl::TextureTarget dstTargetPacked = gl::PackParam<gl::TextureTarget>(dstTarget); 3750 // TODO(http://anglebug.com/5643): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER) are 3751 // unsupported when used with compressed formats due to gl::PackParam() returning 3752 // TextureTarget::InvalidEnum. 3753 if (dstTargetPacked != gl::TextureTarget::InvalidEnum) 3754 { 3755 const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel); 3756 fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width && 3757 srcHeight == dstExtents.height && srcDepth == dstExtents.depth; 3758 } 3759 3760 if (srcFormatInfo.compressed && !fillsEntireMip && 3761 !ValidateCompressedRegion(context, entryPoint, srcFormatInfo, srcWidth, srcHeight)) 3762 { 3763 return false; 3764 } 3765 3766 if (dstFormatInfo.compressed && !fillsEntireMip && 3767 !ValidateCompressedRegion(context, entryPoint, dstFormatInfo, dstWidth, dstHeight)) 3768 { 3769 return false; 3770 } 3771 3772 // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats 3773 // are not compatible, if one image is compressed and the other is uncompressed and the block 3774 // size of compressed image is not equal to the texel size of the compressed image. 3775 if (!ValidateCopyFormatCompatible(srcFormatInfo, dstFormatInfo)) 3776 { 3777 context->validationError(entryPoint, GL_INVALID_OPERATION, kIncompatibleTextures); 3778 return false; 3779 } 3780 3781 // INVALID_OPERATION is generated if the source and destination number of samples do not match 3782 if (srcSamples != dstSamples) 3783 { 3784 context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange); 3785 return false; 3786 } 3787 3788 return true; 3789 } 3790 3791 bool ValidateCopyTexImageParametersBase(const Context *context, 3792 angle::EntryPoint entryPoint, 3793 TextureTarget target, 3794 GLint level, 3795 GLenum internalformat, 3796 bool isSubImage, 3797 GLint xoffset, 3798 GLint yoffset, 3799 GLint zoffset, 3800 GLint x, 3801 GLint y, 3802 GLsizei width, 3803 GLsizei height, 3804 GLint border, 3805 Format *textureFormatOut) 3806 { 3807 TextureType texType = TextureTargetToType(target); 3808 3809 if (xoffset < 0 || yoffset < 0 || zoffset < 0) 3810 { 3811 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 3812 return false; 3813 } 3814 3815 if (width < 0 || height < 0) 3816 { 3817 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 3818 return false; 3819 } 3820 3821 if (std::numeric_limits<GLsizei>::max() - xoffset < width || 3822 std::numeric_limits<GLsizei>::max() - yoffset < height) 3823 { 3824 context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow); 3825 return false; 3826 } 3827 3828 if (std::numeric_limits<GLint>::max() - width < x || 3829 std::numeric_limits<GLint>::max() - height < y) 3830 { 3831 context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow); 3832 return false; 3833 } 3834 3835 if (border != 0) 3836 { 3837 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder); 3838 return false; 3839 } 3840 3841 if (!ValidMipLevel(context, texType, level)) 3842 { 3843 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 3844 return false; 3845 } 3846 3847 const State &state = context->getState(); 3848 Framebuffer *readFramebuffer = state.getReadFramebuffer(); 3849 if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer)) 3850 { 3851 return false; 3852 } 3853 3854 // checkReadBufferResourceSamples = true. Treat renderToTexture textures as single sample since 3855 // they will be resolved before copying. 3856 if (!readFramebuffer->isDefault() && 3857 !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true)) 3858 { 3859 return false; 3860 } 3861 3862 if (readFramebuffer->getReadBufferState() == GL_NONE) 3863 { 3864 context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone); 3865 return false; 3866 } 3867 3868 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment 3869 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing 3870 // attachment and WebGL defines it to be an error. We do the check unconditionally as the 3871 // situation is an application error that would lead to a crash in ANGLE. 3872 const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment(); 3873 if (source == nullptr) 3874 { 3875 context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingReadAttachment); 3876 return false; 3877 } 3878 3879 if (source->isYUV()) 3880 { 3881 context->validationError(entryPoint, GL_INVALID_OPERATION, kCopyFromYUVFramebuffer); 3882 return false; 3883 } 3884 3885 // ANGLE_multiview spec, Revision 1: 3886 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an 3887 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer 3888 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read 3889 // framebuffer is more than one. 3890 if (readFramebuffer->readDisallowedByMultiview()) 3891 { 3892 context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, 3893 kMultiviewReadFramebuffer); 3894 return false; 3895 } 3896 3897 const Caps &caps = context->getCaps(); 3898 3899 GLint maxDimension = 0; 3900 switch (texType) 3901 { 3902 case TextureType::_2D: 3903 maxDimension = caps.max2DTextureSize; 3904 break; 3905 3906 case TextureType::CubeMap: 3907 case TextureType::CubeMapArray: 3908 maxDimension = caps.maxCubeMapTextureSize; 3909 break; 3910 3911 case TextureType::Rectangle: 3912 maxDimension = caps.maxRectangleTextureSize; 3913 break; 3914 3915 case TextureType::_2DArray: 3916 maxDimension = caps.max2DTextureSize; 3917 break; 3918 3919 case TextureType::_3D: 3920 maxDimension = caps.max3DTextureSize; 3921 break; 3922 3923 default: 3924 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 3925 return false; 3926 } 3927 3928 Texture *texture = state.getTargetTexture(texType); 3929 if (!texture) 3930 { 3931 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotBound); 3932 return false; 3933 } 3934 3935 if (texture->getImmutableFormat() && !isSubImage) 3936 { 3937 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable); 3938 return false; 3939 } 3940 3941 const InternalFormat &formatInfo = 3942 isSubImage ? *texture->getFormat(target, level).info 3943 : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE); 3944 3945 if (formatInfo.depthBits > 0 || formatInfo.compressed) 3946 { 3947 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 3948 return false; 3949 } 3950 3951 if (isSubImage) 3952 { 3953 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) || 3954 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) || 3955 static_cast<size_t>(zoffset) >= texture->getDepth(target, level)) 3956 { 3957 context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow); 3958 return false; 3959 } 3960 } 3961 else 3962 { 3963 if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) && 3964 width != height) 3965 { 3966 context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapIncomplete); 3967 return false; 3968 } 3969 3970 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) 3971 { 3972 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 3973 internalformat); 3974 return false; 3975 } 3976 3977 int maxLevelDimension = (maxDimension >> level); 3978 if (static_cast<int>(width) > maxLevelDimension || 3979 static_cast<int>(height) > maxLevelDimension) 3980 { 3981 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 3982 return false; 3983 } 3984 } 3985 3986 // Do not leak the previous texture format for non-subImage case. 3987 if (textureFormatOut && isSubImage) 3988 { 3989 *textureFormatOut = texture->getFormat(target, level); 3990 } 3991 3992 // Detect texture copying feedback loops for WebGL. 3993 if (context->isWebGL()) 3994 { 3995 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset)) 3996 { 3997 context->validationError(entryPoint, GL_INVALID_OPERATION, kFeedbackLoop); 3998 return false; 3999 } 4000 } 4001 4002 return true; 4003 } 4004 4005 const char *ValidateProgramPipelineDrawStates(const Context *context, 4006 const Extensions &extensions, 4007 ProgramPipeline *programPipeline) 4008 { 4009 for (const ShaderType shaderType : gl::AllShaderTypes()) 4010 { 4011 Program *program = programPipeline->getShaderProgram(shaderType); 4012 if (program) 4013 { 4014 const char *errorMsg = ValidateProgramDrawStates(context, extensions, program); 4015 if (errorMsg) 4016 { 4017 return errorMsg; 4018 } 4019 } 4020 } 4021 4022 return nullptr; 4023 } 4024 4025 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline) 4026 { 4027 // An INVALID_OPERATION error is generated by any command that transfers vertices to the 4028 // GL or launches compute work if the current set of active 4029 // program objects cannot be executed, for reasons including: 4030 // - There is no current program object specified by UseProgram, there is a current program 4031 // pipeline object, and that object is empty (no executable code is installed for any stage). 4032 // - A program object is active for at least one, but not all of the shader 4033 // stages that were present when the program was linked. 4034 if (!programPipeline->getExecutable().getLinkedShaderStages().any()) 4035 { 4036 return gl::err::kNoExecutableCodeInstalled; 4037 } 4038 for (const ShaderType shaderType : gl::AllShaderTypes()) 4039 { 4040 Program *shaderProgram = programPipeline->getShaderProgram(shaderType); 4041 if (shaderProgram) 4042 { 4043 ProgramExecutable &executable = shaderProgram->getExecutable(); 4044 for (const ShaderType programShaderType : executable.getLinkedShaderStages()) 4045 { 4046 if (shaderProgram != programPipeline->getShaderProgram(programShaderType)) 4047 { 4048 return gl::err::kNotAllStagesOfSeparableProgramUsed; 4049 } 4050 } 4051 } 4052 } 4053 4054 // [EXT_geometry_shader] Section 11.1.gs Geometry Shaders 4055 // A non-separable program object or program pipeline object that includes 4056 // a geometry shader must also include a vertex shader. 4057 // An INVALID_OPERATION error is generated by any command that transfers 4058 // vertices to the GL if the current program state has a geometry shader 4059 // but no vertex shader. 4060 if (!programPipeline->getShaderProgram(ShaderType::Vertex) && 4061 programPipeline->getShaderProgram(ShaderType::Geometry)) 4062 { 4063 return gl::err::kNoActiveGraphicsShaderStage; 4064 } 4065 4066 return nullptr; 4067 } 4068 4069 // Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer 4070 // completeness check. 4071 const char *ValidateDrawStates(const Context *context) 4072 { 4073 const Extensions &extensions = context->getExtensions(); 4074 const State &state = context->getState(); 4075 4076 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange, 4077 // and UnmapBuffer entry points are removed from the WebGL 2.0 API. 4078 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14 4079 VertexArray *vertexArray = state.getVertexArray(); 4080 ASSERT(vertexArray); 4081 4082 if (!extensions.webglCompatibilityANGLE && vertexArray->hasInvalidMappedArrayBuffer()) 4083 { 4084 return kBufferMapped; 4085 } 4086 4087 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See 4088 // Section 6.10 of the WebGL 1.0 spec. 4089 Framebuffer *framebuffer = state.getDrawFramebuffer(); 4090 ASSERT(framebuffer); 4091 4092 if (context->getLimitations().noSeparateStencilRefsAndMasks || 4093 extensions.webglCompatibilityANGLE) 4094 { 4095 ASSERT(framebuffer); 4096 const FramebufferAttachment *dsAttachment = 4097 framebuffer->getStencilOrDepthStencilAttachment(); 4098 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0; 4099 ASSERT(stencilBits <= 8); 4100 4101 const DepthStencilState &depthStencilState = state.getDepthStencilState(); 4102 if (depthStencilState.stencilTest && stencilBits > 0) 4103 { 4104 GLuint maxStencilValue = (1 << stencilBits) - 1; 4105 4106 bool differentRefs = 4107 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) != 4108 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue)); 4109 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) != 4110 (depthStencilState.stencilBackWritemask & maxStencilValue); 4111 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) != 4112 (depthStencilState.stencilBackMask & maxStencilValue); 4113 4114 if (differentRefs || differentWritemasks || differentMasks) 4115 { 4116 if (!extensions.webglCompatibilityANGLE) 4117 { 4118 WARN() << "This ANGLE implementation does not support separate front/back " 4119 "stencil writemasks, reference values, or stencil mask values."; 4120 } 4121 return kStencilReferenceMaskOrMismatch; 4122 } 4123 } 4124 } 4125 4126 if (!extensions.floatBlendEXT) 4127 { 4128 const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask = 4129 state.getBlendEnabledDrawBufferMask() & 4130 framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask(); 4131 if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any()) 4132 { 4133 return kUnsupportedFloatBlending; 4134 } 4135 } 4136 4137 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc || 4138 extensions.webglCompatibilityANGLE) 4139 { 4140 if (state.hasSimultaneousConstantColorAndAlphaBlendFunc()) 4141 { 4142 if (extensions.webglCompatibilityANGLE) 4143 { 4144 return kInvalidConstantColor; 4145 } 4146 4147 WARN() << kConstantColorAlphaLimitation; 4148 return kConstantColorAlphaLimitation; 4149 } 4150 } 4151 4152 if (!framebuffer->isComplete(context)) 4153 { 4154 // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION. 4155 return kDrawFramebufferIncomplete; 4156 } 4157 4158 bool framebufferIsYUV = framebuffer->hasYUVAttachment(); 4159 if (framebufferIsYUV) 4160 { 4161 const BlendState &blendState = state.getBlendState(); 4162 if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue) 4163 { 4164 // When rendering into a YUV framebuffer, the color mask must have r g and b set to 4165 // true. 4166 return kInvalidColorMaskForYUV; 4167 } 4168 4169 if (blendState.blend) 4170 { 4171 // When rendering into a YUV framebuffer, blending must be disabled. 4172 return kInvalidBlendStateForYUV; 4173 } 4174 } 4175 else 4176 { 4177 if (framebuffer->hasExternalTextureAttachment()) 4178 { 4179 // It is an error to render into an external texture that is not YUV. 4180 return kExternalTextureAttachmentNotYUV; 4181 } 4182 } 4183 4184 // Advanced blend equation can only be enabled for a single render target. 4185 const BlendStateExt &blendStateExt = state.getBlendStateExt(); 4186 if (blendStateExt.getUsesAdvancedBlendEquationMask().any()) 4187 { 4188 const size_t drawBufferCount = framebuffer->getDrawbufferStateCount(); 4189 uint32_t advancedBlendRenderTargetCount = 0; 4190 4191 for (size_t drawBufferIndex : blendStateExt.getUsesAdvancedBlendEquationMask()) 4192 { 4193 if (drawBufferIndex < drawBufferCount && 4194 framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE && 4195 blendStateExt.getEnabledMask().test(drawBufferIndex) && 4196 blendStateExt.getUsesAdvancedBlendEquationMask().test(drawBufferIndex)) 4197 { 4198 ++advancedBlendRenderTargetCount; 4199 } 4200 } 4201 4202 if (advancedBlendRenderTargetCount > 1) 4203 { 4204 return kAdvancedBlendEquationWithMRT; 4205 } 4206 } 4207 4208 if (context->getStateCache().hasAnyEnabledClientAttrib()) 4209 { 4210 if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled()) 4211 { 4212 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking 4213 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no 4214 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls 4215 // to drawArrays or drawElements will generate an INVALID_OPERATION error. 4216 return kVertexArrayNoBuffer; 4217 } 4218 4219 if (state.getVertexArray()->hasEnabledNullPointerClientArray()) 4220 { 4221 // This is an application error that would normally result in a crash, but we catch it 4222 // and return an error 4223 return kVertexArrayNoBufferPointer; 4224 } 4225 } 4226 4227 // If we are running GLES1, there is no current program. 4228 if (context->getClientVersion() >= Version(2, 0)) 4229 { 4230 Program *program = state.getLinkedProgram(context); 4231 ProgramPipeline *programPipeline = state.getLinkedProgramPipeline(context); 4232 const ProgramExecutable *executable = state.getProgramExecutable(); 4233 4234 bool programIsYUVOutput = false; 4235 4236 if (program) 4237 { 4238 const char *errorMsg = ValidateProgramDrawStates(context, extensions, program); 4239 if (errorMsg) 4240 { 4241 return errorMsg; 4242 } 4243 4244 programIsYUVOutput = executable->isYUVOutput(); 4245 } 4246 else if (programPipeline) 4247 { 4248 const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline); 4249 if (errorMsg) 4250 { 4251 return errorMsg; 4252 } 4253 4254 errorMsg = ValidateProgramPipelineDrawStates(context, extensions, programPipeline); 4255 if (errorMsg) 4256 { 4257 return errorMsg; 4258 } 4259 4260 if (!programPipeline->isLinked()) 4261 { 4262 return kProgramPipelineLinkFailed; 4263 } 4264 4265 programIsYUVOutput = executable->isYUVOutput(); 4266 } 4267 4268 if (executable) 4269 { 4270 if (!executable->validateSamplers(nullptr, context->getCaps())) 4271 { 4272 return kTextureTypeConflict; 4273 } 4274 4275 if (executable->hasLinkedTessellationShader()) 4276 { 4277 if (!executable->hasLinkedShaderStage(ShaderType::Vertex)) 4278 { 4279 return kTessellationShaderRequiresVertexShader; 4280 } 4281 4282 if (!executable->hasLinkedShaderStage(ShaderType::TessControl) || 4283 !executable->hasLinkedShaderStage(ShaderType::TessEvaluation)) 4284 { 4285 return kTessellationShaderRequiresBothControlAndEvaluation; 4286 } 4287 } 4288 4289 if (state.isTransformFeedbackActive()) 4290 { 4291 if (!ValidateProgramExecutableXFBBuffersPresent(context, executable)) 4292 { 4293 return kTransformFeedbackBufferMissing; 4294 } 4295 } 4296 } 4297 4298 if (programIsYUVOutput != framebufferIsYUV) 4299 { 4300 // Both the program and framebuffer must match in YUV output state. 4301 return kYUVOutputMissmatch; 4302 } 4303 4304 if (!state.validateSamplerFormats()) 4305 { 4306 return kSamplerFormatMismatch; 4307 } 4308 4309 // Do some additional WebGL-specific validation 4310 if (extensions.webglCompatibilityANGLE) 4311 { 4312 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback(); 4313 if (state.isTransformFeedbackActive() && 4314 transformFeedbackObject->buffersBoundForOtherUseInWebGL()) 4315 { 4316 return kTransformFeedbackBufferDoubleBound; 4317 } 4318 4319 // Detect rendering feedback loops for WebGL. 4320 if (framebuffer->formsRenderingFeedbackLoopWith(context)) 4321 { 4322 return kFeedbackLoop; 4323 } 4324 4325 // Detect that the vertex shader input types match the attribute types 4326 if (!ValidateVertexShaderAttributeTypeMatch(context)) 4327 { 4328 return kVertexShaderTypeMismatch; 4329 } 4330 4331 if (!context->getState().getRasterizerState().rasterizerDiscard && 4332 !context->getState().allActiveDrawBufferChannelsMasked()) 4333 { 4334 // Detect that if there's active color buffer without fragment shader output 4335 if (!ValidateFragmentShaderColorBufferMaskMatch(context)) 4336 { 4337 return kDrawBufferMaskMismatch; 4338 } 4339 4340 // Detect that the color buffer types match the fragment shader output types 4341 if (!ValidateFragmentShaderColorBufferTypeMatch(context)) 4342 { 4343 return kDrawBufferTypeMismatch; 4344 } 4345 } 4346 4347 const VertexArray *vao = context->getState().getVertexArray(); 4348 if (vao->hasTransformFeedbackBindingConflict(context)) 4349 { 4350 return kVertexBufferBoundForTransformFeedback; 4351 } 4352 4353 // Validate that we are rendering with a linked program. 4354 if (!program->isLinked()) 4355 { 4356 return kProgramNotLinked; 4357 } 4358 } 4359 } 4360 4361 return nullptr; 4362 } 4363 4364 const char *ValidateProgramPipeline(const Context *context) 4365 { 4366 const State &state = context->getState(); 4367 // If we are running GLES1, there is no current program. 4368 if (context->getClientVersion() >= Version(2, 0)) 4369 { 4370 ProgramPipeline *programPipeline = state.getProgramPipeline(); 4371 if (programPipeline) 4372 { 4373 const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline); 4374 if (errorMsg) 4375 { 4376 return errorMsg; 4377 } 4378 } 4379 } 4380 return nullptr; 4381 } 4382 4383 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode) 4384 { 4385 const State &state = context->getState(); 4386 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); 4387 if (state.isTransformFeedbackActiveUnpaused()) 4388 { 4389 if (!ValidateTransformFeedbackPrimitiveMode(context, entryPoint, 4390 curTransformFeedback->getPrimitiveMode(), mode)) 4391 { 4392 context->validationError(entryPoint, GL_INVALID_OPERATION, 4393 kInvalidDrawModeTransformFeedback); 4394 return; 4395 } 4396 } 4397 4398 const Extensions &extensions = context->getExtensions(); 4399 4400 switch (mode) 4401 { 4402 case PrimitiveMode::Points: 4403 case PrimitiveMode::Lines: 4404 case PrimitiveMode::LineLoop: 4405 case PrimitiveMode::LineStrip: 4406 case PrimitiveMode::Triangles: 4407 case PrimitiveMode::TriangleStrip: 4408 case PrimitiveMode::TriangleFan: 4409 break; 4410 4411 case PrimitiveMode::LinesAdjacency: 4412 case PrimitiveMode::LineStripAdjacency: 4413 case PrimitiveMode::TrianglesAdjacency: 4414 case PrimitiveMode::TriangleStripAdjacency: 4415 if (!extensions.geometryShaderAny() && context->getClientVersion() < ES_3_2) 4416 { 4417 context->validationError(entryPoint, GL_INVALID_ENUM, 4418 kGeometryShaderExtensionNotEnabled); 4419 return; 4420 } 4421 break; 4422 4423 case PrimitiveMode::Patches: 4424 if (!extensions.tessellationShaderEXT && context->getClientVersion() < ES_3_2) 4425 { 4426 context->validationError(entryPoint, GL_INVALID_ENUM, 4427 kTessellationShaderExtensionNotEnabled); 4428 return; 4429 } 4430 break; 4431 4432 default: 4433 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDrawMode); 4434 return; 4435 } 4436 4437 // If we are running GLES1, there is no current program. 4438 if (context->getClientVersion() >= Version(2, 0)) 4439 { 4440 const ProgramExecutable *executable = state.getProgramExecutable(); 4441 ASSERT(executable); 4442 4443 // Do geometry shader specific validations 4444 if (executable->hasLinkedShaderStage(ShaderType::Geometry)) 4445 { 4446 if (!IsCompatibleDrawModeWithGeometryShader( 4447 mode, executable->getGeometryShaderInputPrimitiveType())) 4448 { 4449 context->validationError(entryPoint, GL_INVALID_OPERATION, 4450 kIncompatibleDrawModeAgainstGeometryShader); 4451 return; 4452 } 4453 } 4454 4455 if (executable->hasLinkedTessellationShader() && mode != PrimitiveMode::Patches) 4456 { 4457 context->validationError(entryPoint, GL_INVALID_OPERATION, 4458 kIncompatibleDrawModeWithTessellationShader); 4459 return; 4460 } 4461 4462 if (!executable->hasLinkedTessellationShader() && mode == PrimitiveMode::Patches) 4463 { 4464 context->validationError(entryPoint, GL_INVALID_OPERATION, 4465 kIncompatibleDrawModeWithoutTessellationShader); 4466 return; 4467 } 4468 } 4469 4470 // An error should be recorded. 4471 UNREACHABLE(); 4472 } 4473 4474 bool ValidateDrawArraysInstancedANGLE(const Context *context, 4475 angle::EntryPoint entryPoint, 4476 PrimitiveMode mode, 4477 GLint first, 4478 GLsizei count, 4479 GLsizei primcount) 4480 { 4481 if (!context->getExtensions().instancedArraysANGLE) 4482 { 4483 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4484 return false; 4485 } 4486 4487 if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount)) 4488 { 4489 return false; 4490 } 4491 4492 return ValidateDrawInstancedANGLE(context, entryPoint); 4493 } 4494 4495 bool ValidateDrawArraysInstancedEXT(const Context *context, 4496 angle::EntryPoint entryPoint, 4497 PrimitiveMode mode, 4498 GLint first, 4499 GLsizei count, 4500 GLsizei primcount) 4501 { 4502 if (!context->getExtensions().instancedArraysEXT) 4503 { 4504 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4505 return false; 4506 } 4507 4508 if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount)) 4509 { 4510 return false; 4511 } 4512 4513 return true; 4514 } 4515 4516 const char *ValidateDrawElementsStates(const Context *context) 4517 { 4518 const State &state = context->getState(); 4519 4520 if (context->getStateCache().isTransformFeedbackActiveUnpaused()) 4521 { 4522 // EXT_geometry_shader allows transform feedback to work with all draw commands. 4523 // [EXT_geometry_shader] Section 12.1, "Transform Feedback" 4524 if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2) 4525 { 4526 // It is an invalid operation to call DrawElements, DrawRangeElements or 4527 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg 4528 // 86) 4529 return kUnsupportedDrawModeForTransformFeedback; 4530 } 4531 } 4532 4533 const VertexArray *vao = state.getVertexArray(); 4534 Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); 4535 4536 if (elementArrayBuffer) 4537 { 4538 if (elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) 4539 { 4540 return kElementArrayBufferBoundForTransformFeedback; 4541 } 4542 if (elementArrayBuffer->isMapped() && 4543 (!elementArrayBuffer->isImmutable() || 4544 (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0)) 4545 { 4546 return kBufferMapped; 4547 } 4548 } 4549 else 4550 { 4551 // [WebGL 1.0] Section 6.2 No Client Side Arrays 4552 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to 4553 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated. 4554 if (!context->getState().areClientArraysEnabled() || context->isWebGL()) 4555 { 4556 return kMustHaveElementArrayBinding; 4557 } 4558 } 4559 4560 return nullptr; 4561 } 4562 4563 bool ValidateDrawElementsInstancedANGLE(const Context *context, 4564 angle::EntryPoint entryPoint, 4565 PrimitiveMode mode, 4566 GLsizei count, 4567 DrawElementsType type, 4568 const void *indices, 4569 GLsizei primcount) 4570 { 4571 if (!context->getExtensions().instancedArraysANGLE) 4572 { 4573 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4574 return false; 4575 } 4576 4577 if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, 4578 primcount)) 4579 { 4580 return false; 4581 } 4582 4583 return ValidateDrawInstancedANGLE(context, entryPoint); 4584 } 4585 4586 bool ValidateDrawElementsInstancedEXT(const Context *context, 4587 angle::EntryPoint entryPoint, 4588 PrimitiveMode mode, 4589 GLsizei count, 4590 DrawElementsType type, 4591 const void *indices, 4592 GLsizei primcount) 4593 { 4594 if (!context->getExtensions().instancedArraysEXT) 4595 { 4596 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4597 return false; 4598 } 4599 4600 if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices, 4601 primcount)) 4602 { 4603 return false; 4604 } 4605 4606 return true; 4607 } 4608 4609 bool ValidateGetUniformBase(const Context *context, 4610 angle::EntryPoint entryPoint, 4611 ShaderProgramID program, 4612 UniformLocation location) 4613 { 4614 if (program.value == 0) 4615 { 4616 context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist); 4617 return false; 4618 } 4619 4620 Program *programObject = GetValidProgram(context, entryPoint, program); 4621 if (!programObject) 4622 { 4623 return false; 4624 } 4625 4626 if (!programObject || !programObject->isLinked()) 4627 { 4628 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 4629 return false; 4630 } 4631 4632 if (!programObject->isValidUniformLocation(location)) 4633 { 4634 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation); 4635 return false; 4636 } 4637 4638 return true; 4639 } 4640 4641 bool ValidateSizedGetUniform(const Context *context, 4642 angle::EntryPoint entryPoint, 4643 ShaderProgramID program, 4644 UniformLocation location, 4645 GLsizei bufSize, 4646 GLsizei *length) 4647 { 4648 if (length) 4649 { 4650 *length = 0; 4651 } 4652 4653 if (!ValidateGetUniformBase(context, entryPoint, program, location)) 4654 { 4655 return false; 4656 } 4657 4658 if (bufSize < 0) 4659 { 4660 context->validationError(entryPoint, GL_INVALID_OPERATION, kNegativeBufferSize); 4661 return false; 4662 } 4663 4664 Program *programObject = context->getProgramResolveLink(program); 4665 ASSERT(programObject); 4666 4667 // sized queries -- ensure the provided buffer is large enough 4668 const LinkedUniform &uniform = programObject->getUniformByLocation(location); 4669 size_t requiredBytes = VariableExternalSize(uniform.type); 4670 if (static_cast<size_t>(bufSize) < requiredBytes) 4671 { 4672 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize); 4673 return false; 4674 } 4675 4676 if (length) 4677 { 4678 *length = VariableComponentCount(uniform.type); 4679 } 4680 return true; 4681 } 4682 4683 bool ValidateGetnUniformfvEXT(const Context *context, 4684 angle::EntryPoint entryPoint, 4685 ShaderProgramID program, 4686 UniformLocation location, 4687 GLsizei bufSize, 4688 const GLfloat *params) 4689 { 4690 return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr); 4691 } 4692 4693 bool ValidateGetnUniformfvRobustANGLE(const Context *context, 4694 angle::EntryPoint entryPoint, 4695 ShaderProgramID program, 4696 UniformLocation location, 4697 GLsizei bufSize, 4698 const GLsizei *length, 4699 const GLfloat *params) 4700 { 4701 UNIMPLEMENTED(); 4702 return false; 4703 } 4704 4705 bool ValidateGetnUniformivEXT(const Context *context, 4706 angle::EntryPoint entryPoint, 4707 ShaderProgramID program, 4708 UniformLocation location, 4709 GLsizei bufSize, 4710 const GLint *params) 4711 { 4712 return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr); 4713 } 4714 4715 bool ValidateGetnUniformivRobustANGLE(const Context *context, 4716 angle::EntryPoint entryPoint, 4717 ShaderProgramID program, 4718 UniformLocation location, 4719 GLsizei bufSize, 4720 const GLsizei *length, 4721 const GLint *params) 4722 { 4723 UNIMPLEMENTED(); 4724 return false; 4725 } 4726 4727 bool ValidateGetnUniformuivRobustANGLE(const Context *context, 4728 angle::EntryPoint entryPoint, 4729 ShaderProgramID program, 4730 UniformLocation location, 4731 GLsizei bufSize, 4732 const GLsizei *length, 4733 const GLuint *params) 4734 { 4735 UNIMPLEMENTED(); 4736 return false; 4737 } 4738 4739 bool ValidateGetUniformfvRobustANGLE(const Context *context, 4740 angle::EntryPoint entryPoint, 4741 ShaderProgramID program, 4742 UniformLocation location, 4743 GLsizei bufSize, 4744 const GLsizei *length, 4745 const GLfloat *params) 4746 { 4747 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 4748 { 4749 return false; 4750 } 4751 4752 GLsizei writeLength = 0; 4753 4754 // bufSize is validated in ValidateSizedGetUniform 4755 if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength)) 4756 { 4757 return false; 4758 } 4759 4760 SetRobustLengthParam(length, writeLength); 4761 4762 return true; 4763 } 4764 4765 bool ValidateGetUniformivRobustANGLE(const Context *context, 4766 angle::EntryPoint entryPoint, 4767 ShaderProgramID program, 4768 UniformLocation location, 4769 GLsizei bufSize, 4770 const GLsizei *length, 4771 const GLint *params) 4772 { 4773 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 4774 { 4775 return false; 4776 } 4777 4778 GLsizei writeLength = 0; 4779 4780 // bufSize is validated in ValidateSizedGetUniform 4781 if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength)) 4782 { 4783 return false; 4784 } 4785 4786 SetRobustLengthParam(length, writeLength); 4787 4788 return true; 4789 } 4790 4791 bool ValidateGetUniformuivRobustANGLE(const Context *context, 4792 angle::EntryPoint entryPoint, 4793 ShaderProgramID program, 4794 UniformLocation location, 4795 GLsizei bufSize, 4796 const GLsizei *length, 4797 const GLuint *params) 4798 { 4799 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 4800 { 4801 return false; 4802 } 4803 4804 if (context->getClientMajorVersion() < 3) 4805 { 4806 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 4807 return false; 4808 } 4809 4810 GLsizei writeLength = 0; 4811 4812 // bufSize is validated in ValidateSizedGetUniform 4813 if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength)) 4814 { 4815 return false; 4816 } 4817 4818 SetRobustLengthParam(length, writeLength); 4819 4820 return true; 4821 } 4822 4823 bool ValidateDiscardFramebufferBase(const Context *context, 4824 angle::EntryPoint entryPoint, 4825 GLenum target, 4826 GLsizei numAttachments, 4827 const GLenum *attachments, 4828 bool defaultFramebuffer) 4829 { 4830 if (numAttachments < 0) 4831 { 4832 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeAttachments); 4833 return false; 4834 } 4835 4836 for (GLsizei i = 0; i < numAttachments; ++i) 4837 { 4838 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31) 4839 { 4840 if (defaultFramebuffer) 4841 { 4842 context->validationError(entryPoint, GL_INVALID_ENUM, 4843 kDefaultFramebufferInvalidAttachment); 4844 return false; 4845 } 4846 4847 if (attachments[i] >= 4848 GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments)) 4849 { 4850 context->validationError(entryPoint, GL_INVALID_OPERATION, 4851 kExceedsMaxColorAttachments); 4852 return false; 4853 } 4854 } 4855 else 4856 { 4857 switch (attachments[i]) 4858 { 4859 case GL_DEPTH_ATTACHMENT: 4860 case GL_STENCIL_ATTACHMENT: 4861 case GL_DEPTH_STENCIL_ATTACHMENT: 4862 if (defaultFramebuffer) 4863 { 4864 context->validationError(entryPoint, GL_INVALID_ENUM, 4865 kDefaultFramebufferInvalidAttachment); 4866 return false; 4867 } 4868 break; 4869 case GL_COLOR: 4870 case GL_DEPTH: 4871 case GL_STENCIL: 4872 if (!defaultFramebuffer) 4873 { 4874 context->validationError(entryPoint, GL_INVALID_ENUM, 4875 kDefaultFramebufferAttachmentOnUserFBO); 4876 return false; 4877 } 4878 break; 4879 default: 4880 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 4881 return false; 4882 } 4883 } 4884 } 4885 4886 return true; 4887 } 4888 4889 bool ValidateInsertEventMarkerEXT(const Context *context, 4890 angle::EntryPoint entryPoint, 4891 GLsizei length, 4892 const char *marker) 4893 { 4894 if (!context->getExtensions().debugMarkerEXT) 4895 { 4896 // The debug marker calls should not set error state 4897 // However, it seems reasonable to set an error state if the extension is not enabled 4898 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4899 return false; 4900 } 4901 4902 // Note that debug marker calls must not set error state 4903 if (length < 0) 4904 { 4905 return false; 4906 } 4907 4908 if (marker == nullptr) 4909 { 4910 return false; 4911 } 4912 4913 return true; 4914 } 4915 4916 bool ValidatePushGroupMarkerEXT(const Context *context, 4917 angle::EntryPoint entryPoint, 4918 GLsizei length, 4919 const char *marker) 4920 { 4921 if (!context->getExtensions().debugMarkerEXT) 4922 { 4923 // The debug marker calls should not set error state 4924 // However, it seems reasonable to set an error state if the extension is not enabled 4925 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4926 return false; 4927 } 4928 4929 // Note that debug marker calls must not set error state 4930 if (length < 0) 4931 { 4932 return false; 4933 } 4934 4935 if (length > 0 && marker == nullptr) 4936 { 4937 return false; 4938 } 4939 4940 return true; 4941 } 4942 4943 bool ValidateEGLImageObject(const Context *context, 4944 angle::EntryPoint entryPoint, 4945 TextureType type, 4946 GLeglImageOES image) 4947 { 4948 egl::Image *imageObject = static_cast<egl::Image *>(image); 4949 4950 ASSERT(context->getDisplay()); 4951 if (!context->getDisplay()->isValidImage(imageObject)) 4952 { 4953 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEGLImage); 4954 return false; 4955 } 4956 4957 if (imageObject->getSamples() > 0) 4958 { 4959 context->validationError(entryPoint, GL_INVALID_OPERATION, 4960 kEGLImageCannotCreate2DMultisampled); 4961 return false; 4962 } 4963 4964 if (!imageObject->isTexturable(context)) 4965 { 4966 context->validationError(entryPoint, GL_INVALID_OPERATION, 4967 kEGLImageTextureFormatNotSupported); 4968 return false; 4969 } 4970 4971 // Validate source egl image and target texture are compatible 4972 size_t depth = static_cast<size_t>(imageObject->getExtents().depth); 4973 if (imageObject->isYUV() && type != TextureType::External) 4974 { 4975 context->validationError(entryPoint, GL_INVALID_OPERATION, 4976 "Image is YUV, target must be TEXTURE_EXTERNAL_OES"); 4977 return false; 4978 } 4979 4980 if (depth > 1 && type != TextureType::_2DArray && type != TextureType::CubeMap && 4981 type != TextureType::CubeMapArray && type != TextureType::_3D) 4982 { 4983 context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch); 4984 return false; 4985 } 4986 4987 if (imageObject->isCubeMap() && type != TextureType::CubeMapArray && 4988 (type != TextureType::CubeMap || depth > gl::kCubeFaceCount)) 4989 { 4990 context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch); 4991 return false; 4992 } 4993 4994 if (imageObject->getLevelCount() > 1 && type == TextureType::External) 4995 { 4996 context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch); 4997 return false; 4998 } 4999 5000 // 3d EGLImages are currently not supported 5001 if (type == TextureType::_3D) 5002 { 5003 context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch); 5004 return false; 5005 } 5006 5007 if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent()) 5008 { 5009 context->validationError(entryPoint, GL_INVALID_OPERATION, 5010 "Mismatch between Image and Context Protected Content state"); 5011 return false; 5012 } 5013 5014 return true; 5015 } 5016 5017 bool ValidateEGLImageTargetTexture2DOES(const Context *context, 5018 angle::EntryPoint entryPoint, 5019 TextureType type, 5020 GLeglImageOES image) 5021 { 5022 if (!context->getExtensions().EGLImageOES && !context->getExtensions().EGLImageExternalOES) 5023 { 5024 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 5025 return false; 5026 } 5027 5028 switch (type) 5029 { 5030 case TextureType::_2D: 5031 if (!context->getExtensions().EGLImageOES) 5032 { 5033 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 5034 ToGLenum(type)); 5035 } 5036 break; 5037 5038 case TextureType::_2DArray: 5039 if (!context->getExtensions().EGLImageArrayEXT) 5040 { 5041 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 5042 ToGLenum(type)); 5043 } 5044 break; 5045 5046 case TextureType::External: 5047 if (!context->getExtensions().EGLImageExternalOES) 5048 { 5049 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 5050 ToGLenum(type)); 5051 } 5052 break; 5053 5054 default: 5055 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 5056 return false; 5057 } 5058 5059 return ValidateEGLImageObject(context, entryPoint, type, image); 5060 } 5061 5062 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context, 5063 angle::EntryPoint entryPoint, 5064 GLenum target, 5065 GLeglImageOES image) 5066 { 5067 if (!context->getExtensions().EGLImageOES) 5068 { 5069 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 5070 return false; 5071 } 5072 5073 switch (target) 5074 { 5075 case GL_RENDERBUFFER: 5076 break; 5077 5078 default: 5079 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget); 5080 return false; 5081 } 5082 5083 egl::Image *imageObject = static_cast<egl::Image *>(image); 5084 5085 ASSERT(context->getDisplay()); 5086 if (!context->getDisplay()->isValidImage(imageObject)) 5087 { 5088 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEGLImage); 5089 return false; 5090 } 5091 5092 if (!imageObject->isRenderable(context)) 5093 { 5094 context->validationError(entryPoint, GL_INVALID_OPERATION, 5095 kEGLImageRenderbufferFormatNotSupported); 5096 return false; 5097 } 5098 5099 if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent()) 5100 { 5101 context->validationError(entryPoint, GL_INVALID_OPERATION, 5102 "Mismatch between Image and Context Protected Content state"); 5103 return false; 5104 } 5105 5106 return true; 5107 } 5108 5109 bool ValidateProgramBinaryBase(const Context *context, 5110 angle::EntryPoint entryPoint, 5111 ShaderProgramID program, 5112 GLenum binaryFormat, 5113 const void *binary, 5114 GLint length) 5115 { 5116 Program *programObject = GetValidProgram(context, entryPoint, program); 5117 if (programObject == nullptr) 5118 { 5119 return false; 5120 } 5121 5122 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats; 5123 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == 5124 programBinaryFormats.end()) 5125 { 5126 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramBinaryFormat); 5127 return false; 5128 } 5129 5130 if (context->hasActiveTransformFeedback(program)) 5131 { 5132 // ES 3.0.4 section 2.15 page 91 5133 context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackProgramBinary); 5134 return false; 5135 } 5136 5137 return true; 5138 } 5139 5140 bool ValidateGetProgramBinaryBase(const Context *context, 5141 angle::EntryPoint entryPoint, 5142 ShaderProgramID program, 5143 GLsizei bufSize, 5144 const GLsizei *length, 5145 const GLenum *binaryFormat, 5146 const void *binary) 5147 { 5148 Program *programObject = GetValidProgram(context, entryPoint, program); 5149 if (programObject == nullptr) 5150 { 5151 return false; 5152 } 5153 5154 if (!programObject->isLinked()) 5155 { 5156 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 5157 return false; 5158 } 5159 5160 if (context->getCaps().programBinaryFormats.empty()) 5161 { 5162 context->validationError(entryPoint, GL_INVALID_OPERATION, kNoProgramBinaryFormats); 5163 return false; 5164 } 5165 5166 return true; 5167 } 5168 5169 bool ValidateDrawBuffersBase(const Context *context, 5170 angle::EntryPoint entryPoint, 5171 GLsizei n, 5172 const GLenum *bufs) 5173 { 5174 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS 5175 if (n < 0) 5176 { 5177 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); 5178 return false; 5179 } 5180 if (n > context->getCaps().maxDrawBuffers) 5181 { 5182 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer); 5183 return false; 5184 } 5185 5186 ASSERT(context->getState().getDrawFramebuffer()); 5187 FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id(); 5188 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments; 5189 5190 // This should come first before the check for the default frame buffer 5191 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM 5192 // rather than INVALID_OPERATION 5193 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) 5194 { 5195 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; 5196 5197 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK && 5198 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 || 5199 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31)) 5200 { 5201 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi 5202 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this 5203 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects. 5204 // 3.1 is still a bit ambiguous about the error, but future specs are 5205 // expected to clarify that GL_INVALID_ENUM is the correct error. 5206 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDrawBuffer); 5207 return false; 5208 } 5209 else if (bufs[colorAttachment] >= maxColorAttachment) 5210 { 5211 context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsMaxColorAttachments); 5212 return false; 5213 } 5214 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment && 5215 frameBufferId.value != 0) 5216 { 5217 // INVALID_OPERATION-GL is bound to buffer and ith argument 5218 // is not COLOR_ATTACHMENTi or NONE 5219 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDrawBufferValue); 5220 return false; 5221 } 5222 } 5223 5224 // INVALID_OPERATION is generated if GL is bound to the default framebuffer 5225 // and n is not 1 or bufs is bound to value other than BACK and NONE 5226 if (frameBufferId.value == 0) 5227 { 5228 if (n != 1) 5229 { 5230 context->validationError(entryPoint, GL_INVALID_OPERATION, 5231 kInvalidDrawBufferCountForDefault); 5232 return false; 5233 } 5234 5235 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) 5236 { 5237 context->validationError(entryPoint, GL_INVALID_OPERATION, 5238 kDefaultFramebufferInvalidDrawBuffer); 5239 return false; 5240 } 5241 } 5242 5243 return true; 5244 } 5245 5246 bool ValidateGetBufferPointervBase(const Context *context, 5247 angle::EntryPoint entryPoint, 5248 BufferBinding target, 5249 GLenum pname, 5250 GLsizei *length, 5251 void *const *params) 5252 { 5253 if (length) 5254 { 5255 *length = 0; 5256 } 5257 5258 if (!context->isValidBufferBinding(target)) 5259 { 5260 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 5261 return false; 5262 } 5263 5264 switch (pname) 5265 { 5266 case GL_BUFFER_MAP_POINTER: 5267 break; 5268 5269 default: 5270 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 5271 return false; 5272 } 5273 5274 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a 5275 // target bound to zero generate an INVALID_OPERATION error." 5276 // GLES 3.1 section 6.6 explicitly specifies this error. 5277 if (context->getState().getTargetBuffer(target) == nullptr) 5278 { 5279 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferPointerNotAvailable); 5280 return false; 5281 } 5282 5283 if (length) 5284 { 5285 *length = 1; 5286 } 5287 5288 return true; 5289 } 5290 5291 bool ValidateUnmapBufferBase(const Context *context, 5292 angle::EntryPoint entryPoint, 5293 BufferBinding target) 5294 { 5295 if (!context->isValidBufferBinding(target)) 5296 { 5297 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 5298 return false; 5299 } 5300 5301 Buffer *buffer = context->getState().getTargetBuffer(target); 5302 5303 if (buffer == nullptr || !buffer->isMapped()) 5304 { 5305 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMapped); 5306 return false; 5307 } 5308 5309 return true; 5310 } 5311 5312 bool ValidateMapBufferRangeBase(const Context *context, 5313 angle::EntryPoint entryPoint, 5314 BufferBinding target, 5315 GLintptr offset, 5316 GLsizeiptr length, 5317 GLbitfield access) 5318 { 5319 if (!context->isValidBufferBinding(target)) 5320 { 5321 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 5322 return false; 5323 } 5324 5325 if (offset < 0) 5326 { 5327 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 5328 return false; 5329 } 5330 5331 if (length < 0) 5332 { 5333 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength); 5334 return false; 5335 } 5336 5337 Buffer *buffer = context->getState().getTargetBuffer(target); 5338 5339 if (!buffer) 5340 { 5341 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable); 5342 return false; 5343 } 5344 5345 // Check for buffer overflow 5346 CheckedNumeric<size_t> checkedOffset(offset); 5347 auto checkedSize = checkedOffset + length; 5348 5349 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize())) 5350 { 5351 context->validationError(entryPoint, GL_INVALID_VALUE, kMapOutOfRange); 5352 return false; 5353 } 5354 5355 // Check for invalid bits in the mask 5356 constexpr GLbitfield kAllAccessBits = 5357 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | 5358 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT; 5359 5360 if (buffer->isImmutable()) 5361 { 5362 // GL_EXT_buffer_storage's additions to glMapBufferRange 5363 constexpr GLbitfield kBufferStorageAccessBits = 5364 kAllAccessBits | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT; 5365 5366 if ((access & ~kBufferStorageAccessBits) != 0) 5367 { 5368 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidAccessBits); 5369 return false; 5370 } 5371 5372 // It is invalid if any of bufferStorageMatchedAccessBits bits are included in access, 5373 // but the same bits are not included in the buffer's storage flags 5374 constexpr GLbitfield kBufferStorageMatchedAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | 5375 GL_MAP_PERSISTENT_BIT_EXT | 5376 GL_MAP_COHERENT_BIT_EXT; 5377 GLbitfield accessFlags = access & kBufferStorageMatchedAccessBits; 5378 if ((accessFlags & buffer->getStorageExtUsageFlags()) != accessFlags) 5379 { 5380 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBits); 5381 return false; 5382 } 5383 } 5384 else if ((access & ~kAllAccessBits) != 0) 5385 { 5386 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidAccessBits); 5387 return false; 5388 } 5389 5390 if (length == 0) 5391 { 5392 context->validationError(entryPoint, GL_INVALID_OPERATION, kLengthZero); 5393 return false; 5394 } 5395 5396 if (buffer->isMapped()) 5397 { 5398 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferAlreadyMapped); 5399 return false; 5400 } 5401 5402 // Check for invalid bit combinations 5403 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) 5404 { 5405 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite); 5406 return false; 5407 } 5408 5409 GLbitfield writeOnlyBits = 5410 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT; 5411 5412 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) 5413 { 5414 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsRead); 5415 return false; 5416 } 5417 5418 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) 5419 { 5420 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsFlush); 5421 return false; 5422 } 5423 5424 return ValidateMapBufferBase(context, entryPoint, target); 5425 } 5426 5427 bool ValidateFlushMappedBufferRangeBase(const Context *context, 5428 angle::EntryPoint entryPoint, 5429 BufferBinding target, 5430 GLintptr offset, 5431 GLsizeiptr length) 5432 { 5433 if (offset < 0) 5434 { 5435 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 5436 return false; 5437 } 5438 5439 if (length < 0) 5440 { 5441 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength); 5442 return false; 5443 } 5444 5445 if (!context->isValidBufferBinding(target)) 5446 { 5447 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 5448 return false; 5449 } 5450 5451 Buffer *buffer = context->getState().getTargetBuffer(target); 5452 5453 if (buffer == nullptr) 5454 { 5455 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFlushZero); 5456 return false; 5457 } 5458 5459 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) 5460 { 5461 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFlushTarget); 5462 return false; 5463 } 5464 5465 // Check for buffer overflow 5466 CheckedNumeric<size_t> checkedOffset(offset); 5467 auto checkedSize = checkedOffset + length; 5468 5469 if (!checkedSize.IsValid() || 5470 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength())) 5471 { 5472 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlushOutOfRange); 5473 return false; 5474 } 5475 5476 return true; 5477 } 5478 5479 bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n) 5480 { 5481 if (n < 0) 5482 { 5483 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); 5484 return false; 5485 } 5486 return true; 5487 } 5488 5489 bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize) 5490 { 5491 if (!context->getExtensions().robustClientMemoryANGLE) 5492 { 5493 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 5494 return false; 5495 } 5496 5497 if (bufSize < 0) 5498 { 5499 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 5500 return false; 5501 } 5502 5503 return true; 5504 } 5505 5506 bool ValidateRobustBufferSize(const Context *context, 5507 angle::EntryPoint entryPoint, 5508 GLsizei bufSize, 5509 GLsizei numParams) 5510 { 5511 if (bufSize < numParams) 5512 { 5513 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientParams); 5514 return false; 5515 } 5516 5517 return true; 5518 } 5519 5520 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, 5521 angle::EntryPoint entryPoint, 5522 GLenum target, 5523 GLenum attachment, 5524 GLenum pname, 5525 GLsizei *numParams) 5526 { 5527 if (!ValidFramebufferTarget(context, target)) 5528 { 5529 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 5530 return false; 5531 } 5532 5533 int clientVersion = context->getClientMajorVersion(); 5534 5535 switch (pname) 5536 { 5537 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 5538 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 5539 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 5540 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 5541 break; 5542 5543 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR: 5544 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR: 5545 if (clientVersion < 3 || 5546 !(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR)) 5547 { 5548 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 5549 return false; 5550 } 5551 break; 5552 5553 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT: 5554 if (!context->getExtensions().multisampledRenderToTextureEXT) 5555 { 5556 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 5557 return false; 5558 } 5559 break; 5560 5561 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: 5562 if (clientVersion < 3 && !context->getExtensions().sRGBEXT) 5563 { 5564 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 5565 return false; 5566 } 5567 break; 5568 5569 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: 5570 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: 5571 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: 5572 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: 5573 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: 5574 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: 5575 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 5576 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: 5577 if (clientVersion < 3) 5578 { 5579 context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required); 5580 return false; 5581 } 5582 break; 5583 5584 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT: 5585 if (!context->getExtensions().geometryShaderAny() && 5586 context->getClientVersion() < ES_3_2) 5587 { 5588 context->validationError(entryPoint, GL_INVALID_ENUM, 5589 kGeometryShaderExtensionNotEnabled); 5590 return false; 5591 } 5592 break; 5593 5594 default: 5595 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 5596 return false; 5597 } 5598 5599 // Determine if the attachment is a valid enum 5600 switch (attachment) 5601 { 5602 case GL_BACK: 5603 case GL_DEPTH: 5604 case GL_STENCIL: 5605 if (clientVersion < 3) 5606 { 5607 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 5608 return false; 5609 } 5610 break; 5611 5612 case GL_DEPTH_STENCIL_ATTACHMENT: 5613 if (clientVersion < 3 && !context->isWebGL1()) 5614 { 5615 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 5616 return false; 5617 } 5618 break; 5619 5620 case GL_COLOR_ATTACHMENT0: 5621 case GL_DEPTH_ATTACHMENT: 5622 case GL_STENCIL_ATTACHMENT: 5623 break; 5624 5625 default: 5626 if ((clientVersion < 3 && !context->getExtensions().drawBuffersEXT) || 5627 attachment < GL_COLOR_ATTACHMENT0_EXT || 5628 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= 5629 static_cast<GLuint>(context->getCaps().maxColorAttachments)) 5630 { 5631 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 5632 return false; 5633 } 5634 break; 5635 } 5636 5637 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 5638 ASSERT(framebuffer); 5639 5640 if (framebuffer->isDefault()) 5641 { 5642 if (clientVersion < 3) 5643 { 5644 context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget); 5645 return false; 5646 } 5647 5648 switch (attachment) 5649 { 5650 case GL_BACK: 5651 case GL_DEPTH: 5652 case GL_STENCIL: 5653 break; 5654 5655 default: 5656 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment); 5657 return false; 5658 } 5659 } 5660 else 5661 { 5662 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) 5663 { 5664 // Valid attachment query 5665 } 5666 else 5667 { 5668 switch (attachment) 5669 { 5670 case GL_DEPTH_ATTACHMENT: 5671 case GL_STENCIL_ATTACHMENT: 5672 break; 5673 5674 case GL_DEPTH_STENCIL_ATTACHMENT: 5675 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1()) 5676 { 5677 context->validationError(entryPoint, GL_INVALID_OPERATION, 5678 kInvalidAttachment); 5679 return false; 5680 } 5681 break; 5682 5683 default: 5684 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment); 5685 return false; 5686 } 5687 } 5688 } 5689 5690 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment); 5691 if (attachmentObject) 5692 { 5693 ASSERT(attachmentObject->type() == GL_RENDERBUFFER || 5694 attachmentObject->type() == GL_TEXTURE || 5695 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT); 5696 5697 switch (pname) 5698 { 5699 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 5700 if (attachmentObject->type() != GL_RENDERBUFFER && 5701 attachmentObject->type() != GL_TEXTURE) 5702 { 5703 context->validationError(entryPoint, GL_INVALID_ENUM, 5704 kFramebufferIncompleteAttachment); 5705 return false; 5706 } 5707 break; 5708 5709 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 5710 if (attachmentObject->type() != GL_TEXTURE) 5711 { 5712 context->validationError(entryPoint, GL_INVALID_ENUM, 5713 kFramebufferIncompleteAttachment); 5714 return false; 5715 } 5716 break; 5717 5718 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 5719 if (attachmentObject->type() != GL_TEXTURE) 5720 { 5721 context->validationError(entryPoint, GL_INVALID_ENUM, 5722 kFramebufferIncompleteAttachment); 5723 return false; 5724 } 5725 break; 5726 5727 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 5728 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) 5729 { 5730 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment); 5731 return false; 5732 } 5733 break; 5734 5735 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: 5736 if (attachmentObject->type() != GL_TEXTURE) 5737 { 5738 context->validationError(entryPoint, GL_INVALID_ENUM, 5739 kFramebufferIncompleteAttachment); 5740 return false; 5741 } 5742 break; 5743 5744 default: 5745 break; 5746 } 5747 } 5748 else 5749 { 5750 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 5751 // is NONE, then querying any other pname will generate INVALID_ENUM. 5752 5753 // ES 3.0.2 spec pg 235 states that if the attachment type is none, 5754 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an 5755 // INVALID_OPERATION for all other pnames 5756 5757 switch (pname) 5758 { 5759 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 5760 break; 5761 5762 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 5763 if (clientVersion < 3) 5764 { 5765 context->validationError(entryPoint, GL_INVALID_ENUM, 5766 kInvalidFramebufferAttachmentParameter); 5767 return false; 5768 } 5769 break; 5770 5771 default: 5772 if (clientVersion < 3) 5773 { 5774 context->validationError(entryPoint, GL_INVALID_ENUM, 5775 kInvalidFramebufferAttachmentParameter); 5776 return false; 5777 } 5778 else 5779 { 5780 context->validationError(entryPoint, GL_INVALID_OPERATION, 5781 kInvalidFramebufferAttachmentParameter); 5782 return false; 5783 } 5784 } 5785 } 5786 5787 if (numParams) 5788 { 5789 *numParams = 1; 5790 } 5791 5792 return true; 5793 } 5794 5795 bool ValidateGetFramebufferParameterivBase(const Context *context, 5796 angle::EntryPoint entryPoint, 5797 GLenum target, 5798 GLenum pname, 5799 const GLint *params) 5800 { 5801 if (!ValidFramebufferTarget(context, target)) 5802 { 5803 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 5804 return false; 5805 } 5806 5807 switch (pname) 5808 { 5809 case GL_FRAMEBUFFER_DEFAULT_WIDTH: 5810 case GL_FRAMEBUFFER_DEFAULT_HEIGHT: 5811 case GL_FRAMEBUFFER_DEFAULT_SAMPLES: 5812 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: 5813 break; 5814 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT: 5815 if (!context->getExtensions().geometryShaderAny() && 5816 context->getClientVersion() < ES_3_2) 5817 { 5818 context->validationError(entryPoint, GL_INVALID_ENUM, 5819 kGeometryShaderExtensionNotEnabled); 5820 return false; 5821 } 5822 break; 5823 case GL_FRAMEBUFFER_FLIP_Y_MESA: 5824 if (!context->getExtensions().framebufferFlipYMESA) 5825 { 5826 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 5827 return false; 5828 } 5829 break; 5830 default: 5831 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 5832 return false; 5833 } 5834 5835 const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 5836 ASSERT(framebuffer); 5837 5838 if (framebuffer->isDefault()) 5839 { 5840 context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebuffer); 5841 return false; 5842 } 5843 return true; 5844 } 5845 5846 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context, 5847 angle::EntryPoint entryPoint, 5848 GLenum target, 5849 GLenum attachment, 5850 GLenum pname, 5851 GLsizei bufSize, 5852 const GLsizei *length, 5853 const GLint *params) 5854 { 5855 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 5856 { 5857 return false; 5858 } 5859 5860 GLsizei numParams = 0; 5861 if (!ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment, 5862 pname, &numParams)) 5863 { 5864 return false; 5865 } 5866 5867 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 5868 { 5869 return false; 5870 } 5871 5872 SetRobustLengthParam(length, numParams); 5873 5874 return true; 5875 } 5876 5877 bool ValidateGetBufferParameterivRobustANGLE(const Context *context, 5878 angle::EntryPoint entryPoint, 5879 BufferBinding target, 5880 GLenum pname, 5881 GLsizei bufSize, 5882 const GLsizei *length, 5883 const GLint *params) 5884 { 5885 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 5886 { 5887 return false; 5888 } 5889 5890 GLsizei numParams = 0; 5891 5892 if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams)) 5893 { 5894 return false; 5895 } 5896 5897 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 5898 { 5899 return false; 5900 } 5901 5902 SetRobustLengthParam(length, numParams); 5903 return true; 5904 } 5905 5906 bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context, 5907 angle::EntryPoint entryPoint, 5908 BufferBinding target, 5909 GLenum pname, 5910 GLsizei bufSize, 5911 const GLsizei *length, 5912 const GLint64 *params) 5913 { 5914 GLsizei numParams = 0; 5915 5916 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 5917 { 5918 return false; 5919 } 5920 5921 if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams)) 5922 { 5923 return false; 5924 } 5925 5926 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 5927 { 5928 return false; 5929 } 5930 5931 SetRobustLengthParam(length, numParams); 5932 5933 return true; 5934 } 5935 5936 bool ValidateGetProgramivBase(const Context *context, 5937 angle::EntryPoint entryPoint, 5938 ShaderProgramID program, 5939 GLenum pname, 5940 GLsizei *numParams) 5941 { 5942 // Currently, all GetProgramiv queries return 1 parameter 5943 if (numParams) 5944 { 5945 *numParams = 1; 5946 } 5947 5948 if (context->isContextLost()) 5949 { 5950 context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost); 5951 5952 if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR) 5953 { 5954 // Generate an error but still return true, the context still needs to return a 5955 // value in this case. 5956 return true; 5957 } 5958 else 5959 { 5960 return false; 5961 } 5962 } 5963 5964 // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now. 5965 Program *programObject = (pname == GL_COMPLETION_STATUS_KHR) 5966 ? GetValidProgramNoResolve(context, entryPoint, program) 5967 : GetValidProgram(context, entryPoint, program); 5968 if (!programObject) 5969 { 5970 return false; 5971 } 5972 5973 switch (pname) 5974 { 5975 case GL_DELETE_STATUS: 5976 case GL_LINK_STATUS: 5977 case GL_VALIDATE_STATUS: 5978 case GL_INFO_LOG_LENGTH: 5979 case GL_ATTACHED_SHADERS: 5980 case GL_ACTIVE_ATTRIBUTES: 5981 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 5982 case GL_ACTIVE_UNIFORMS: 5983 case GL_ACTIVE_UNIFORM_MAX_LENGTH: 5984 break; 5985 5986 case GL_PROGRAM_BINARY_LENGTH: 5987 if (context->getClientMajorVersion() < 3 && 5988 !context->getExtensions().getProgramBinaryOES) 5989 { 5990 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 5991 return false; 5992 } 5993 break; 5994 5995 case GL_ACTIVE_UNIFORM_BLOCKS: 5996 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: 5997 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: 5998 case GL_TRANSFORM_FEEDBACK_VARYINGS: 5999 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: 6000 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: 6001 if (context->getClientMajorVersion() < 3) 6002 { 6003 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES30); 6004 return false; 6005 } 6006 break; 6007 6008 case GL_PROGRAM_SEPARABLE: 6009 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS: 6010 if (context->getClientVersion() < Version(3, 1)) 6011 { 6012 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31); 6013 return false; 6014 } 6015 break; 6016 6017 case GL_COMPUTE_WORK_GROUP_SIZE: 6018 if (context->getClientVersion() < Version(3, 1)) 6019 { 6020 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31); 6021 return false; 6022 } 6023 6024 // [OpenGL ES 3.1] Chapter 7.12 Page 122 6025 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a 6026 // program which has not been linked successfully, or which does not contain objects to 6027 // form a compute shader. 6028 if (!programObject->isLinked()) 6029 { 6030 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 6031 return false; 6032 } 6033 if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute)) 6034 { 6035 context->validationError(entryPoint, GL_INVALID_OPERATION, 6036 kNoActiveComputeShaderStage); 6037 return false; 6038 } 6039 break; 6040 6041 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT: 6042 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT: 6043 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT: 6044 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT: 6045 if (!context->getExtensions().geometryShaderAny() && 6046 context->getClientVersion() < ES_3_2) 6047 { 6048 context->validationError(entryPoint, GL_INVALID_ENUM, 6049 kGeometryShaderExtensionNotEnabled); 6050 return false; 6051 } 6052 6053 // [EXT_geometry_shader] Chapter 7.12 6054 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT, 6055 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or 6056 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked 6057 // successfully, or which does not contain objects to form a geometry shader. 6058 if (!programObject->isLinked()) 6059 { 6060 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 6061 return false; 6062 } 6063 if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry)) 6064 { 6065 context->validationError(entryPoint, GL_INVALID_OPERATION, 6066 kNoActiveGeometryShaderStage); 6067 return false; 6068 } 6069 break; 6070 6071 case GL_COMPLETION_STATUS_KHR: 6072 if (!context->getExtensions().parallelShaderCompileKHR) 6073 { 6074 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6075 return false; 6076 } 6077 break; 6078 case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT: 6079 case GL_TESS_GEN_MODE_EXT: 6080 case GL_TESS_GEN_SPACING_EXT: 6081 case GL_TESS_GEN_VERTEX_ORDER_EXT: 6082 case GL_TESS_GEN_POINT_MODE_EXT: 6083 if (!context->getExtensions().tessellationShaderEXT && 6084 context->getClientVersion() < ES_3_2) 6085 { 6086 context->validationError(entryPoint, GL_INVALID_ENUM, 6087 kTessellationShaderExtensionNotEnabled); 6088 return false; 6089 } 6090 if (!programObject->isLinked()) 6091 { 6092 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 6093 return false; 6094 } 6095 break; 6096 default: 6097 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6098 return false; 6099 } 6100 6101 return true; 6102 } 6103 6104 bool ValidateGetProgramivRobustANGLE(const Context *context, 6105 angle::EntryPoint entryPoint, 6106 ShaderProgramID program, 6107 GLenum pname, 6108 GLsizei bufSize, 6109 const GLsizei *length, 6110 const GLint *params) 6111 { 6112 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6113 { 6114 return false; 6115 } 6116 6117 GLsizei numParams = 0; 6118 6119 if (!ValidateGetProgramivBase(context, entryPoint, program, pname, &numParams)) 6120 { 6121 return false; 6122 } 6123 6124 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6125 { 6126 return false; 6127 } 6128 6129 SetRobustLengthParam(length, numParams); 6130 6131 return true; 6132 } 6133 6134 bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context, 6135 angle::EntryPoint entryPoint, 6136 GLenum target, 6137 GLenum pname, 6138 GLsizei bufSize, 6139 const GLsizei *length, 6140 const GLint *params) 6141 { 6142 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6143 { 6144 return false; 6145 } 6146 6147 GLsizei numParams = 0; 6148 6149 if (!ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, &numParams)) 6150 { 6151 return false; 6152 } 6153 6154 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6155 { 6156 return false; 6157 } 6158 6159 SetRobustLengthParam(length, numParams); 6160 6161 return true; 6162 } 6163 6164 bool ValidateGetShaderivRobustANGLE(const Context *context, 6165 angle::EntryPoint entryPoint, 6166 ShaderProgramID shader, 6167 GLenum pname, 6168 GLsizei bufSize, 6169 const GLsizei *length, 6170 const GLint *params) 6171 { 6172 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6173 { 6174 return false; 6175 } 6176 6177 GLsizei numParams = 0; 6178 6179 if (!ValidateGetShaderivBase(context, entryPoint, shader, pname, &numParams)) 6180 { 6181 return false; 6182 } 6183 6184 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6185 { 6186 return false; 6187 } 6188 6189 SetRobustLengthParam(length, numParams); 6190 6191 return true; 6192 } 6193 6194 bool ValidateGetTexParameterfvRobustANGLE(const Context *context, 6195 angle::EntryPoint entryPoint, 6196 TextureType target, 6197 GLenum pname, 6198 GLsizei bufSize, 6199 const GLsizei *length, 6200 const GLfloat *params) 6201 { 6202 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6203 { 6204 return false; 6205 } 6206 6207 GLsizei numParams = 0; 6208 6209 if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams)) 6210 { 6211 return false; 6212 } 6213 6214 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6215 { 6216 return false; 6217 } 6218 6219 SetRobustLengthParam(length, numParams); 6220 6221 return true; 6222 } 6223 6224 bool ValidateGetTexParameterivRobustANGLE(const Context *context, 6225 angle::EntryPoint entryPoint, 6226 TextureType target, 6227 GLenum pname, 6228 GLsizei bufSize, 6229 const GLsizei *length, 6230 const GLint *params) 6231 { 6232 6233 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6234 { 6235 return false; 6236 } 6237 GLsizei numParams = 0; 6238 if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams)) 6239 { 6240 return false; 6241 } 6242 6243 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6244 { 6245 return false; 6246 } 6247 6248 SetRobustLengthParam(length, numParams); 6249 return true; 6250 } 6251 6252 bool ValidateGetTexParameterIivRobustANGLE(const Context *context, 6253 angle::EntryPoint entryPoint, 6254 TextureType target, 6255 GLenum pname, 6256 GLsizei bufSize, 6257 const GLsizei *length, 6258 const GLint *params) 6259 { 6260 UNIMPLEMENTED(); 6261 return false; 6262 } 6263 6264 bool ValidateGetTexParameterIuivRobustANGLE(const Context *context, 6265 angle::EntryPoint entryPoint, 6266 TextureType target, 6267 GLenum pname, 6268 GLsizei bufSize, 6269 const GLsizei *length, 6270 const GLuint *params) 6271 { 6272 UNIMPLEMENTED(); 6273 return false; 6274 } 6275 6276 bool ValidateTexParameterfvRobustANGLE(const Context *context, 6277 angle::EntryPoint entryPoint, 6278 TextureType target, 6279 GLenum pname, 6280 GLsizei bufSize, 6281 const GLfloat *params) 6282 { 6283 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6284 { 6285 return false; 6286 } 6287 6288 return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params); 6289 } 6290 6291 bool ValidateTexParameterivRobustANGLE(const Context *context, 6292 angle::EntryPoint entryPoint, 6293 TextureType target, 6294 GLenum pname, 6295 GLsizei bufSize, 6296 const GLint *params) 6297 { 6298 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6299 { 6300 return false; 6301 } 6302 6303 return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params); 6304 } 6305 6306 bool ValidateTexParameterIivRobustANGLE(const Context *context, 6307 angle::EntryPoint entryPoint, 6308 TextureType target, 6309 GLenum pname, 6310 GLsizei bufSize, 6311 const GLint *params) 6312 { 6313 UNIMPLEMENTED(); 6314 return false; 6315 } 6316 6317 bool ValidateTexParameterIuivRobustANGLE(const Context *context, 6318 angle::EntryPoint entryPoint, 6319 TextureType target, 6320 GLenum pname, 6321 GLsizei bufSize, 6322 const GLuint *params) 6323 { 6324 UNIMPLEMENTED(); 6325 return false; 6326 } 6327 6328 bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context, 6329 angle::EntryPoint entryPoint, 6330 SamplerID sampler, 6331 GLenum pname, 6332 GLsizei bufSize, 6333 const GLsizei *length, 6334 const GLfloat *params) 6335 { 6336 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6337 { 6338 return false; 6339 } 6340 6341 GLsizei numParams = 0; 6342 6343 if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams)) 6344 { 6345 return false; 6346 } 6347 6348 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6349 { 6350 return false; 6351 } 6352 6353 SetRobustLengthParam(length, numParams); 6354 return true; 6355 } 6356 6357 bool ValidateGetSamplerParameterivRobustANGLE(const Context *context, 6358 angle::EntryPoint entryPoint, 6359 SamplerID sampler, 6360 GLenum pname, 6361 GLsizei bufSize, 6362 const GLsizei *length, 6363 const GLint *params) 6364 { 6365 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6366 { 6367 return false; 6368 } 6369 6370 GLsizei numParams = 0; 6371 6372 if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams)) 6373 { 6374 return false; 6375 } 6376 6377 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6378 { 6379 return false; 6380 } 6381 6382 SetRobustLengthParam(length, numParams); 6383 return true; 6384 } 6385 6386 bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context, 6387 angle::EntryPoint entryPoint, 6388 SamplerID sampler, 6389 GLenum pname, 6390 GLsizei bufSize, 6391 const GLsizei *length, 6392 const GLint *params) 6393 { 6394 UNIMPLEMENTED(); 6395 return false; 6396 } 6397 6398 bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context, 6399 angle::EntryPoint entryPoint, 6400 SamplerID sampler, 6401 GLenum pname, 6402 GLsizei bufSize, 6403 const GLsizei *length, 6404 const GLuint *params) 6405 { 6406 UNIMPLEMENTED(); 6407 return false; 6408 } 6409 6410 bool ValidateSamplerParameterfvRobustANGLE(const Context *context, 6411 angle::EntryPoint entryPoint, 6412 SamplerID sampler, 6413 GLenum pname, 6414 GLsizei bufSize, 6415 const GLfloat *params) 6416 { 6417 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6418 { 6419 return false; 6420 } 6421 6422 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params); 6423 } 6424 6425 bool ValidateSamplerParameterivRobustANGLE(const Context *context, 6426 angle::EntryPoint entryPoint, 6427 SamplerID sampler, 6428 GLenum pname, 6429 GLsizei bufSize, 6430 const GLint *params) 6431 { 6432 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6433 { 6434 return false; 6435 } 6436 6437 return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params); 6438 } 6439 6440 bool ValidateSamplerParameterIivRobustANGLE(const Context *context, 6441 angle::EntryPoint entryPoint, 6442 SamplerID sampler, 6443 GLenum pname, 6444 GLsizei bufSize, 6445 const GLint *param) 6446 { 6447 UNIMPLEMENTED(); 6448 return false; 6449 } 6450 6451 bool ValidateSamplerParameterIuivRobustANGLE(const Context *context, 6452 angle::EntryPoint entryPoint, 6453 SamplerID sampler, 6454 GLenum pname, 6455 GLsizei bufSize, 6456 const GLuint *param) 6457 { 6458 UNIMPLEMENTED(); 6459 return false; 6460 } 6461 6462 bool ValidateGetVertexAttribfvRobustANGLE(const Context *context, 6463 angle::EntryPoint entryPoint, 6464 GLuint index, 6465 GLenum pname, 6466 GLsizei bufSize, 6467 const GLsizei *length, 6468 const GLfloat *params) 6469 { 6470 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6471 { 6472 return false; 6473 } 6474 6475 GLsizei writeLength = 0; 6476 6477 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false)) 6478 { 6479 return false; 6480 } 6481 6482 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 6483 { 6484 return false; 6485 } 6486 6487 SetRobustLengthParam(length, writeLength); 6488 return true; 6489 } 6490 6491 bool ValidateGetVertexAttribivRobustANGLE(const Context *context, 6492 angle::EntryPoint entryPoint, 6493 GLuint index, 6494 GLenum pname, 6495 GLsizei bufSize, 6496 const GLsizei *length, 6497 const GLint *params) 6498 { 6499 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6500 { 6501 return false; 6502 } 6503 6504 GLsizei writeLength = 0; 6505 6506 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false)) 6507 { 6508 return false; 6509 } 6510 6511 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 6512 { 6513 return false; 6514 } 6515 6516 SetRobustLengthParam(length, writeLength); 6517 6518 return true; 6519 } 6520 6521 bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context, 6522 angle::EntryPoint entryPoint, 6523 GLuint index, 6524 GLenum pname, 6525 GLsizei bufSize, 6526 const GLsizei *length, 6527 void *const *pointer) 6528 { 6529 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6530 { 6531 return false; 6532 } 6533 6534 GLsizei writeLength = 0; 6535 6536 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true, false)) 6537 { 6538 return false; 6539 } 6540 6541 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 6542 { 6543 return false; 6544 } 6545 6546 SetRobustLengthParam(length, writeLength); 6547 6548 return true; 6549 } 6550 6551 bool ValidateGetVertexAttribIivRobustANGLE(const Context *context, 6552 angle::EntryPoint entryPoint, 6553 GLuint index, 6554 GLenum pname, 6555 GLsizei bufSize, 6556 const GLsizei *length, 6557 const GLint *params) 6558 { 6559 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6560 { 6561 return false; 6562 } 6563 6564 GLsizei writeLength = 0; 6565 6566 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true)) 6567 { 6568 return false; 6569 } 6570 6571 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 6572 { 6573 return false; 6574 } 6575 6576 SetRobustLengthParam(length, writeLength); 6577 6578 return true; 6579 } 6580 6581 bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context, 6582 angle::EntryPoint entryPoint, 6583 GLuint index, 6584 GLenum pname, 6585 GLsizei bufSize, 6586 const GLsizei *length, 6587 const GLuint *params) 6588 { 6589 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6590 { 6591 return false; 6592 } 6593 6594 GLsizei writeLength = 0; 6595 6596 if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true)) 6597 { 6598 return false; 6599 } 6600 6601 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 6602 { 6603 return false; 6604 } 6605 6606 SetRobustLengthParam(length, writeLength); 6607 6608 return true; 6609 } 6610 6611 bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context, 6612 angle::EntryPoint entryPoint, 6613 ShaderProgramID program, 6614 UniformBlockIndex uniformBlockIndex, 6615 GLenum pname, 6616 GLsizei bufSize, 6617 const GLsizei *length, 6618 const GLint *params) 6619 { 6620 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6621 { 6622 return false; 6623 } 6624 6625 GLsizei writeLength = 0; 6626 6627 if (!ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex, pname, 6628 &writeLength)) 6629 { 6630 return false; 6631 } 6632 6633 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength)) 6634 { 6635 return false; 6636 } 6637 6638 SetRobustLengthParam(length, writeLength); 6639 6640 return true; 6641 } 6642 6643 bool ValidateGetInternalformativRobustANGLE(const Context *context, 6644 angle::EntryPoint entryPoint, 6645 GLenum target, 6646 GLenum internalformat, 6647 GLenum pname, 6648 GLsizei bufSize, 6649 const GLsizei *length, 6650 const GLint *params) 6651 { 6652 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 6653 { 6654 return false; 6655 } 6656 6657 GLsizei numParams = 0; 6658 6659 if (!ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname, 6660 bufSize, &numParams)) 6661 { 6662 return false; 6663 } 6664 6665 if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams)) 6666 { 6667 return false; 6668 } 6669 6670 SetRobustLengthParam(length, numParams); 6671 6672 return true; 6673 } 6674 6675 // Perform validation from WebGL 2 section 5.10 "Invalid Clears": 6676 // In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the 6677 // specified clear value and the type of a buffer that is being cleared generates an 6678 // INVALID_OPERATION error instead of producing undefined results 6679 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context, 6680 angle::EntryPoint entryPoint, 6681 GLint drawbuffer, 6682 const GLenum *validComponentTypes, 6683 size_t validComponentTypeCount) 6684 { 6685 const FramebufferAttachment *attachment = 6686 context->getState().getDrawFramebuffer()->getDrawBuffer(drawbuffer); 6687 if (attachment) 6688 { 6689 GLenum componentType = attachment->getFormat().info->componentType; 6690 const GLenum *end = validComponentTypes + validComponentTypeCount; 6691 if (std::find(validComponentTypes, end, componentType) == end) 6692 { 6693 context->validationError(entryPoint, GL_INVALID_OPERATION, kNoDefinedClearConversion); 6694 return false; 6695 } 6696 } 6697 6698 return true; 6699 } 6700 6701 bool ValidateRobustCompressedTexImageBase(const Context *context, 6702 angle::EntryPoint entryPoint, 6703 GLsizei imageSize, 6704 GLsizei dataSize) 6705 { 6706 if (!ValidateRobustEntryPoint(context, entryPoint, dataSize)) 6707 { 6708 return false; 6709 } 6710 6711 Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack); 6712 if (pixelUnpackBuffer == nullptr) 6713 { 6714 if (dataSize < imageSize) 6715 { 6716 context->validationError(entryPoint, GL_INVALID_OPERATION, kCompressedDataSizeTooSmall); 6717 } 6718 } 6719 return true; 6720 } 6721 6722 bool ValidateGetBufferParameterBase(const Context *context, 6723 angle::EntryPoint entryPoint, 6724 BufferBinding target, 6725 GLenum pname, 6726 bool pointerVersion, 6727 GLsizei *numParams) 6728 { 6729 if (numParams) 6730 { 6731 *numParams = 0; 6732 } 6733 6734 if (!context->isValidBufferBinding(target)) 6735 { 6736 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 6737 return false; 6738 } 6739 6740 const Buffer *buffer = context->getState().getTargetBuffer(target); 6741 if (!buffer) 6742 { 6743 // A null buffer means that "0" is bound to the requested buffer target 6744 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound); 6745 return false; 6746 } 6747 6748 const Extensions &extensions = context->getExtensions(); 6749 6750 switch (pname) 6751 { 6752 case GL_BUFFER_USAGE: 6753 case GL_BUFFER_SIZE: 6754 break; 6755 6756 case GL_BUFFER_ACCESS_OES: 6757 if (!extensions.mapbufferOES) 6758 { 6759 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6760 return false; 6761 } 6762 break; 6763 6764 case GL_BUFFER_MAPPED: 6765 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal."); 6766 if (context->getClientMajorVersion() < 3 && !extensions.mapbufferOES && 6767 !extensions.mapBufferRangeEXT) 6768 { 6769 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6770 return false; 6771 } 6772 break; 6773 6774 case GL_BUFFER_MAP_POINTER: 6775 if (!pointerVersion) 6776 { 6777 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMapPointerQuery); 6778 return false; 6779 } 6780 break; 6781 6782 case GL_BUFFER_ACCESS_FLAGS: 6783 case GL_BUFFER_MAP_OFFSET: 6784 case GL_BUFFER_MAP_LENGTH: 6785 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRangeEXT) 6786 { 6787 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6788 return false; 6789 } 6790 break; 6791 6792 case GL_MEMORY_SIZE_ANGLE: 6793 if (!context->getExtensions().memorySizeANGLE) 6794 { 6795 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 6796 return false; 6797 } 6798 break; 6799 6800 case GL_RESOURCE_INITIALIZED_ANGLE: 6801 if (!context->getExtensions().robustResourceInitializationANGLE) 6802 { 6803 context->validationError(entryPoint, GL_INVALID_ENUM, 6804 kRobustResourceInitializationExtensionRequired); 6805 return false; 6806 } 6807 break; 6808 6809 default: 6810 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6811 return false; 6812 } 6813 6814 // All buffer parameter queries return one value. 6815 if (numParams) 6816 { 6817 *numParams = 1; 6818 } 6819 6820 return true; 6821 } 6822 6823 bool ValidateGetRenderbufferParameterivBase(const Context *context, 6824 angle::EntryPoint entryPoint, 6825 GLenum target, 6826 GLenum pname, 6827 GLsizei *length) 6828 { 6829 if (length) 6830 { 6831 *length = 0; 6832 } 6833 6834 if (target != GL_RENDERBUFFER) 6835 { 6836 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget); 6837 return false; 6838 } 6839 6840 Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); 6841 if (renderbuffer == nullptr) 6842 { 6843 context->validationError(entryPoint, GL_INVALID_OPERATION, kRenderbufferNotBound); 6844 return false; 6845 } 6846 6847 switch (pname) 6848 { 6849 case GL_RENDERBUFFER_WIDTH: 6850 case GL_RENDERBUFFER_HEIGHT: 6851 case GL_RENDERBUFFER_INTERNAL_FORMAT: 6852 case GL_RENDERBUFFER_RED_SIZE: 6853 case GL_RENDERBUFFER_GREEN_SIZE: 6854 case GL_RENDERBUFFER_BLUE_SIZE: 6855 case GL_RENDERBUFFER_ALPHA_SIZE: 6856 case GL_RENDERBUFFER_DEPTH_SIZE: 6857 case GL_RENDERBUFFER_STENCIL_SIZE: 6858 break; 6859 6860 case GL_RENDERBUFFER_SAMPLES_ANGLE: 6861 if (context->getClientMajorVersion() < 3 && 6862 !context->getExtensions().framebufferMultisampleANGLE) 6863 { 6864 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 6865 return false; 6866 } 6867 break; 6868 6869 case GL_MEMORY_SIZE_ANGLE: 6870 if (!context->getExtensions().memorySizeANGLE) 6871 { 6872 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 6873 return false; 6874 } 6875 break; 6876 6877 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: 6878 case GL_IMPLEMENTATION_COLOR_READ_TYPE: 6879 if (!context->getExtensions().getImageANGLE) 6880 { 6881 context->validationError(entryPoint, GL_INVALID_ENUM, kGetImageExtensionNotEnabled); 6882 return false; 6883 } 6884 break; 6885 6886 case GL_RESOURCE_INITIALIZED_ANGLE: 6887 if (!context->getExtensions().robustResourceInitializationANGLE) 6888 { 6889 context->validationError(entryPoint, GL_INVALID_ENUM, 6890 kRobustResourceInitializationExtensionRequired); 6891 return false; 6892 } 6893 break; 6894 6895 default: 6896 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6897 return false; 6898 } 6899 6900 if (length) 6901 { 6902 *length = 1; 6903 } 6904 return true; 6905 } 6906 6907 bool ValidateGetShaderivBase(const Context *context, 6908 angle::EntryPoint entryPoint, 6909 ShaderProgramID shader, 6910 GLenum pname, 6911 GLsizei *length) 6912 { 6913 if (length) 6914 { 6915 *length = 0; 6916 } 6917 6918 if (context->isContextLost()) 6919 { 6920 context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost); 6921 6922 if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR) 6923 { 6924 // Generate an error but still return true, the context still needs to return a 6925 // value in this case. 6926 return true; 6927 } 6928 else 6929 { 6930 return false; 6931 } 6932 } 6933 6934 if (GetValidShader(context, entryPoint, shader) == nullptr) 6935 { 6936 return false; 6937 } 6938 6939 switch (pname) 6940 { 6941 case GL_SHADER_TYPE: 6942 case GL_DELETE_STATUS: 6943 case GL_COMPILE_STATUS: 6944 case GL_INFO_LOG_LENGTH: 6945 case GL_SHADER_SOURCE_LENGTH: 6946 break; 6947 6948 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: 6949 if (!context->getExtensions().translatedShaderSourceANGLE) 6950 { 6951 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 6952 return false; 6953 } 6954 break; 6955 6956 case GL_COMPLETION_STATUS_KHR: 6957 if (!context->getExtensions().parallelShaderCompileKHR) 6958 { 6959 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6960 return false; 6961 } 6962 break; 6963 6964 default: 6965 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 6966 return false; 6967 } 6968 6969 if (length) 6970 { 6971 *length = 1; 6972 } 6973 return true; 6974 } 6975 6976 bool ValidateGetTexParameterBase(const Context *context, 6977 angle::EntryPoint entryPoint, 6978 TextureType target, 6979 GLenum pname, 6980 GLsizei *length) 6981 { 6982 if (length) 6983 { 6984 *length = 0; 6985 } 6986 6987 if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) || 6988 target == TextureType::Buffer) 6989 { 6990 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 6991 return false; 6992 } 6993 6994 if (context->getTextureByType(target) == nullptr) 6995 { 6996 // Should only be possible for external textures 6997 context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound); 6998 return false; 6999 } 7000 7001 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname)) 7002 { 7003 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7004 return false; 7005 } 7006 7007 switch (pname) 7008 { 7009 case GL_TEXTURE_MAG_FILTER: 7010 case GL_TEXTURE_MIN_FILTER: 7011 case GL_TEXTURE_WRAP_S: 7012 case GL_TEXTURE_WRAP_T: 7013 break; 7014 7015 case GL_TEXTURE_USAGE_ANGLE: 7016 if (!context->getExtensions().textureUsageANGLE) 7017 { 7018 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7019 return false; 7020 } 7021 break; 7022 7023 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 7024 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint)) 7025 { 7026 return false; 7027 } 7028 break; 7029 7030 case GL_TEXTURE_IMMUTABLE_FORMAT: 7031 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorageEXT) 7032 { 7033 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7034 return false; 7035 } 7036 break; 7037 7038 case GL_TEXTURE_WRAP_R: 7039 case GL_TEXTURE_IMMUTABLE_LEVELS: 7040 case GL_TEXTURE_SWIZZLE_R: 7041 case GL_TEXTURE_SWIZZLE_G: 7042 case GL_TEXTURE_SWIZZLE_B: 7043 case GL_TEXTURE_SWIZZLE_A: 7044 case GL_TEXTURE_BASE_LEVEL: 7045 case GL_TEXTURE_MAX_LEVEL: 7046 case GL_TEXTURE_MIN_LOD: 7047 case GL_TEXTURE_MAX_LOD: 7048 if (context->getClientMajorVersion() < 3) 7049 { 7050 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES30); 7051 return false; 7052 } 7053 break; 7054 7055 case GL_TEXTURE_COMPARE_MODE: 7056 case GL_TEXTURE_COMPARE_FUNC: 7057 if (context->getClientMajorVersion() < 3 && !context->getExtensions().shadowSamplersEXT) 7058 { 7059 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7060 return false; 7061 } 7062 break; 7063 7064 case GL_TEXTURE_SRGB_DECODE_EXT: 7065 if (!context->getExtensions().textureSRGBDecodeEXT) 7066 { 7067 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7068 return false; 7069 } 7070 break; 7071 7072 case GL_DEPTH_STENCIL_TEXTURE_MODE: 7073 case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE: 7074 if (context->getClientVersion() < ES_3_1) 7075 { 7076 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31); 7077 return false; 7078 } 7079 break; 7080 7081 case GL_GENERATE_MIPMAP: 7082 case GL_TEXTURE_CROP_RECT_OES: 7083 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture 7084 // after GL_OES_draw_texture functionality implemented 7085 if (context->getClientMajorVersion() > 1) 7086 { 7087 context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only); 7088 return false; 7089 } 7090 break; 7091 7092 case GL_MEMORY_SIZE_ANGLE: 7093 if (!context->getExtensions().memorySizeANGLE) 7094 { 7095 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7096 return false; 7097 } 7098 break; 7099 7100 case GL_TEXTURE_BORDER_COLOR: 7101 if (!context->getExtensions().textureBorderClampOES && 7102 context->getClientVersion() < ES_3_2) 7103 { 7104 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 7105 return false; 7106 } 7107 break; 7108 7109 case GL_TEXTURE_NATIVE_ID_ANGLE: 7110 if (!context->getExtensions().textureExternalUpdateANGLE) 7111 { 7112 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 7113 return false; 7114 } 7115 break; 7116 7117 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: 7118 case GL_IMPLEMENTATION_COLOR_READ_TYPE: 7119 if (!context->getExtensions().getImageANGLE) 7120 { 7121 context->validationError(entryPoint, GL_INVALID_ENUM, kGetImageExtensionNotEnabled); 7122 return false; 7123 } 7124 break; 7125 7126 case GL_RESOURCE_INITIALIZED_ANGLE: 7127 if (!context->getExtensions().robustResourceInitializationANGLE) 7128 { 7129 context->validationError(entryPoint, GL_INVALID_ENUM, 7130 kRobustResourceInitializationExtensionRequired); 7131 return false; 7132 } 7133 break; 7134 7135 case GL_TEXTURE_PROTECTED_EXT: 7136 if (!context->getExtensions().protectedTexturesEXT) 7137 { 7138 context->validationError(entryPoint, GL_INVALID_ENUM, 7139 kProtectedTexturesExtensionRequired); 7140 return false; 7141 } 7142 break; 7143 7144 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: 7145 break; 7146 7147 default: 7148 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7149 return false; 7150 } 7151 7152 if (length) 7153 { 7154 *length = GetTexParameterCount(pname); 7155 } 7156 return true; 7157 } 7158 7159 bool ValidateGetVertexAttribBase(const Context *context, 7160 angle::EntryPoint entryPoint, 7161 GLuint index, 7162 GLenum pname, 7163 GLsizei *length, 7164 bool pointer, 7165 bool pureIntegerEntryPoint) 7166 { 7167 if (length) 7168 { 7169 *length = 0; 7170 } 7171 7172 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3) 7173 { 7174 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 7175 return false; 7176 } 7177 7178 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 7179 { 7180 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); 7181 return false; 7182 } 7183 7184 if (pointer) 7185 { 7186 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) 7187 { 7188 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7189 return false; 7190 } 7191 } 7192 else 7193 { 7194 switch (pname) 7195 { 7196 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: 7197 case GL_VERTEX_ATTRIB_ARRAY_SIZE: 7198 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: 7199 case GL_VERTEX_ATTRIB_ARRAY_TYPE: 7200 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: 7201 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 7202 case GL_CURRENT_VERTEX_ATTRIB: 7203 break; 7204 7205 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: 7206 static_assert( 7207 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE, 7208 "ANGLE extension enums not equal to GL enums."); 7209 if (context->getClientMajorVersion() < 3 && 7210 !context->getExtensions().instancedArraysAny()) 7211 { 7212 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 7213 pname); 7214 return false; 7215 } 7216 break; 7217 7218 case GL_VERTEX_ATTRIB_ARRAY_INTEGER: 7219 if (context->getClientMajorVersion() < 3) 7220 { 7221 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 7222 pname); 7223 return false; 7224 } 7225 break; 7226 7227 case GL_VERTEX_ATTRIB_BINDING: 7228 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: 7229 if (context->getClientVersion() < ES_3_1) 7230 { 7231 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31); 7232 return false; 7233 } 7234 break; 7235 7236 default: 7237 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7238 return false; 7239 } 7240 } 7241 7242 if (length) 7243 { 7244 if (pname == GL_CURRENT_VERTEX_ATTRIB) 7245 { 7246 *length = 4; 7247 } 7248 else 7249 { 7250 *length = 1; 7251 } 7252 } 7253 7254 return true; 7255 } 7256 7257 bool ValidatePixelPack(const Context *context, 7258 angle::EntryPoint entryPoint, 7259 GLenum format, 7260 GLenum type, 7261 GLint x, 7262 GLint y, 7263 GLsizei width, 7264 GLsizei height, 7265 GLsizei bufSize, 7266 GLsizei *length, 7267 const void *pixels) 7268 { 7269 // Check for pixel pack buffer related API errors 7270 Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack); 7271 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped()) 7272 { 7273 // ...the buffer object's data store is currently mapped. 7274 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped); 7275 return false; 7276 } 7277 if (pixelPackBuffer != nullptr && 7278 pixelPackBuffer->hasWebGLXFBBindingConflict(context->isWebGL())) 7279 { 7280 context->validationError(entryPoint, GL_INVALID_OPERATION, 7281 kPixelPackBufferBoundForTransformFeedback); 7282 return false; 7283 } 7284 7285 // .. the data would be packed to the buffer object such that the memory writes required 7286 // would exceed the data store size. 7287 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type); 7288 const Extents size(width, height, 1); 7289 const auto &pack = context->getState().getPackState(); 7290 7291 GLuint endByte = 0; 7292 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte)) 7293 { 7294 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 7295 return false; 7296 } 7297 7298 if (bufSize >= 0) 7299 { 7300 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte) 7301 { 7302 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize); 7303 return false; 7304 } 7305 } 7306 7307 if (pixelPackBuffer != nullptr) 7308 { 7309 CheckedNumeric<size_t> checkedEndByte(endByte); 7310 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels)); 7311 checkedEndByte += checkedOffset; 7312 7313 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize())) 7314 { 7315 // Overflow past the end of the buffer 7316 context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow); 7317 return false; 7318 } 7319 } 7320 7321 if (pixelPackBuffer == nullptr && length != nullptr) 7322 { 7323 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max())) 7324 { 7325 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 7326 return false; 7327 } 7328 7329 *length = static_cast<GLsizei>(endByte); 7330 } 7331 7332 if (context->isWebGL()) 7333 { 7334 // WebGL 2.0 disallows the scenario: 7335 // GL_PACK_SKIP_PIXELS + width > DataStoreWidth 7336 // where: 7337 // DataStoreWidth = (GL_PACK_ROW_LENGTH ? GL_PACK_ROW_LENGTH : width) 7338 // Since these two pack parameters can only be set to non-zero values 7339 // on WebGL 2.0 contexts, verify them for all WebGL contexts. 7340 GLint dataStoreWidth = pack.rowLength ? pack.rowLength : width; 7341 if (pack.skipPixels + width > dataStoreWidth) 7342 { 7343 context->validationError(entryPoint, GL_INVALID_OPERATION, 7344 kInvalidPackParametersForWebGL); 7345 return false; 7346 } 7347 } 7348 7349 return true; 7350 } 7351 7352 bool ValidateReadPixelsBase(const Context *context, 7353 angle::EntryPoint entryPoint, 7354 GLint x, 7355 GLint y, 7356 GLsizei width, 7357 GLsizei height, 7358 GLenum format, 7359 GLenum type, 7360 GLsizei bufSize, 7361 GLsizei *length, 7362 GLsizei *columns, 7363 GLsizei *rows, 7364 const void *pixels) 7365 { 7366 if (length != nullptr) 7367 { 7368 *length = 0; 7369 } 7370 if (rows != nullptr) 7371 { 7372 *rows = 0; 7373 } 7374 if (columns != nullptr) 7375 { 7376 *columns = 0; 7377 } 7378 7379 if (width < 0 || height < 0) 7380 { 7381 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 7382 return false; 7383 } 7384 7385 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); 7386 ASSERT(readFramebuffer); 7387 7388 if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer)) 7389 { 7390 return false; 7391 } 7392 7393 // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be 7394 // resolved before reading. 7395 if (!readFramebuffer->isDefault() && 7396 !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true)) 7397 { 7398 return false; 7399 } 7400 7401 if (readFramebuffer->getReadBufferState() == GL_NONE) 7402 { 7403 context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone); 7404 return false; 7405 } 7406 7407 const FramebufferAttachment *readBuffer = nullptr; 7408 switch (format) 7409 { 7410 case GL_DEPTH_COMPONENT: 7411 readBuffer = readFramebuffer->getDepthAttachment(); 7412 break; 7413 case GL_STENCIL_INDEX_OES: 7414 case GL_DEPTH_STENCIL_OES: 7415 readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment(); 7416 break; 7417 default: 7418 readBuffer = readFramebuffer->getReadColorAttachment(); 7419 break; 7420 } 7421 7422 // OVR_multiview2, Revision 1: 7423 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if 7424 // the number of views in the current read framebuffer is more than one. 7425 if (readFramebuffer->readDisallowedByMultiview()) 7426 { 7427 context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, 7428 kMultiviewReadFramebuffer); 7429 return false; 7430 } 7431 7432 if (context->isWebGL()) 7433 { 7434 // The ES 2.0 spec states that the format must be "among those defined in table 3.4, 7435 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format 7436 // and type before validating the combination of format and type. However, the 7437 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and 7438 // verifies that GL_INVALID_OPERATION is generated. 7439 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in 7440 // dEQP/WebGL. 7441 if (!ValidReadPixelsFormatEnum(context, format)) 7442 { 7443 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 7444 return false; 7445 } 7446 7447 if (!ValidReadPixelsTypeEnum(context, type)) 7448 { 7449 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType); 7450 return false; 7451 } 7452 } 7453 7454 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment 7455 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing 7456 // attachment and WebGL defines it to be an error. We do the check unconditionally as the 7457 // situation is an application error that would lead to a crash in ANGLE. 7458 if (readBuffer == nullptr) 7459 { 7460 context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingReadAttachment); 7461 return false; 7462 } 7463 7464 GLenum currentFormat = GL_NONE; 7465 GLenum currentType = GL_NONE; 7466 7467 switch (format) 7468 { 7469 case GL_DEPTH_COMPONENT: 7470 case GL_STENCIL_INDEX_OES: 7471 case GL_DEPTH_STENCIL_OES: 7472 // Only rely on ValidReadPixelsFormatType for depth/stencil formats 7473 break; 7474 default: 7475 currentFormat = readFramebuffer->getImplementationColorReadFormat(context); 7476 currentType = readFramebuffer->getImplementationColorReadType(context); 7477 break; 7478 } 7479 7480 bool validFormatTypeCombination = 7481 ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type); 7482 7483 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination) 7484 { 7485 context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedTypeAndFormat); 7486 return false; 7487 } 7488 7489 if (!ValidatePixelPack(context, entryPoint, format, type, x, y, width, height, bufSize, length, 7490 pixels)) 7491 { 7492 return false; 7493 } 7494 7495 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) { 7496 angle::CheckedNumeric<int> clippedExtent(length); 7497 if (start < 0) 7498 { 7499 // "subtract" the area that is less than 0 7500 clippedExtent += start; 7501 } 7502 7503 angle::CheckedNumeric<int> readExtent = start; 7504 readExtent += length; 7505 if (!readExtent.IsValid()) 7506 { 7507 return false; 7508 } 7509 7510 if (readExtent.ValueOrDie() > bufferSize) 7511 { 7512 // Subtract the region to the right of the read buffer 7513 clippedExtent -= (readExtent - bufferSize); 7514 } 7515 7516 if (!clippedExtent.IsValid()) 7517 { 7518 return false; 7519 } 7520 7521 *outExtent = std::max<int>(clippedExtent.ValueOrDie(), 0); 7522 return true; 7523 }; 7524 7525 GLsizei writtenColumns = 0; 7526 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns)) 7527 { 7528 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 7529 return false; 7530 } 7531 7532 GLsizei writtenRows = 0; 7533 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows)) 7534 { 7535 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 7536 return false; 7537 } 7538 7539 if (columns != nullptr) 7540 { 7541 *columns = writtenColumns; 7542 } 7543 7544 if (rows != nullptr) 7545 { 7546 *rows = writtenRows; 7547 } 7548 7549 return true; 7550 } 7551 7552 template <typename ParamType> 7553 bool ValidateTexParameterBase(const Context *context, 7554 angle::EntryPoint entryPoint, 7555 TextureType target, 7556 GLenum pname, 7557 GLsizei bufSize, 7558 bool vectorParams, 7559 const ParamType *params) 7560 { 7561 if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) || 7562 target == TextureType::Buffer) 7563 { 7564 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 7565 return false; 7566 } 7567 7568 if (context->getTextureByType(target) == nullptr) 7569 { 7570 // Should only be possible for external textures 7571 context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound); 7572 return false; 7573 } 7574 7575 const GLsizei minBufSize = GetTexParameterCount(pname); 7576 if (bufSize >= 0 && bufSize < minBufSize) 7577 { 7578 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize); 7579 return false; 7580 } 7581 7582 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname)) 7583 { 7584 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7585 return false; 7586 } 7587 7588 switch (pname) 7589 { 7590 case GL_TEXTURE_WRAP_R: 7591 case GL_TEXTURE_SWIZZLE_R: 7592 case GL_TEXTURE_SWIZZLE_G: 7593 case GL_TEXTURE_SWIZZLE_B: 7594 case GL_TEXTURE_SWIZZLE_A: 7595 case GL_TEXTURE_BASE_LEVEL: 7596 case GL_TEXTURE_MAX_LEVEL: 7597 case GL_TEXTURE_COMPARE_MODE: 7598 case GL_TEXTURE_COMPARE_FUNC: 7599 case GL_TEXTURE_MIN_LOD: 7600 case GL_TEXTURE_MAX_LOD: 7601 if (context->getClientMajorVersion() < 3 && 7602 !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES)) 7603 { 7604 context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required); 7605 return false; 7606 } 7607 if (target == TextureType::External && 7608 !context->getExtensions().EGLImageExternalEssl3OES) 7609 { 7610 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7611 return false; 7612 } 7613 if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL) 7614 { 7615 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7616 } 7617 break; 7618 7619 case GL_GENERATE_MIPMAP: 7620 case GL_TEXTURE_CROP_RECT_OES: 7621 if (context->getClientMajorVersion() > 1) 7622 { 7623 context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only); 7624 return false; 7625 } 7626 break; 7627 7628 default: 7629 break; 7630 } 7631 7632 if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray) 7633 { 7634 switch (pname) 7635 { 7636 case GL_TEXTURE_MIN_FILTER: 7637 case GL_TEXTURE_MAG_FILTER: 7638 case GL_TEXTURE_WRAP_S: 7639 case GL_TEXTURE_WRAP_T: 7640 case GL_TEXTURE_WRAP_R: 7641 case GL_TEXTURE_MIN_LOD: 7642 case GL_TEXTURE_MAX_LOD: 7643 case GL_TEXTURE_COMPARE_MODE: 7644 case GL_TEXTURE_COMPARE_FUNC: 7645 case GL_TEXTURE_BORDER_COLOR: 7646 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 7647 return false; 7648 } 7649 } 7650 7651 switch (pname) 7652 { 7653 case GL_TEXTURE_WRAP_S: 7654 case GL_TEXTURE_WRAP_T: 7655 case GL_TEXTURE_WRAP_R: 7656 { 7657 bool restrictedWrapModes = ((target == TextureType::External && 7658 !context->getExtensions().EGLImageExternalWrapModesEXT) || 7659 target == TextureType::Rectangle); 7660 if (!ValidateTextureWrapModeValue(context, entryPoint, params, restrictedWrapModes)) 7661 { 7662 return false; 7663 } 7664 } 7665 break; 7666 7667 case GL_TEXTURE_MIN_FILTER: 7668 { 7669 bool restrictedMinFilter = 7670 target == TextureType::External || target == TextureType::Rectangle; 7671 if (!ValidateTextureMinFilterValue(context, entryPoint, params, restrictedMinFilter)) 7672 { 7673 return false; 7674 } 7675 } 7676 break; 7677 7678 case GL_TEXTURE_MAG_FILTER: 7679 if (!ValidateTextureMagFilterValue(context, entryPoint, params)) 7680 { 7681 return false; 7682 } 7683 break; 7684 7685 case GL_TEXTURE_USAGE_ANGLE: 7686 if (!context->getExtensions().textureUsageANGLE) 7687 { 7688 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7689 return false; 7690 } 7691 7692 switch (ConvertToGLenum(params[0])) 7693 { 7694 case GL_NONE: 7695 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: 7696 break; 7697 7698 default: 7699 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 7700 pname); 7701 return false; 7702 } 7703 break; 7704 7705 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 7706 { 7707 GLfloat paramValue = static_cast<GLfloat>(params[0]); 7708 if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue)) 7709 { 7710 return false; 7711 } 7712 ASSERT(static_cast<ParamType>(paramValue) == params[0]); 7713 } 7714 break; 7715 7716 case GL_TEXTURE_MIN_LOD: 7717 case GL_TEXTURE_MAX_LOD: 7718 // any value is permissible 7719 break; 7720 7721 case GL_TEXTURE_COMPARE_MODE: 7722 if (!ValidateTextureCompareModeValue(context, entryPoint, params)) 7723 { 7724 return false; 7725 } 7726 break; 7727 7728 case GL_TEXTURE_COMPARE_FUNC: 7729 if (!ValidateTextureCompareFuncValue(context, entryPoint, params)) 7730 { 7731 return false; 7732 } 7733 break; 7734 7735 case GL_TEXTURE_SWIZZLE_R: 7736 case GL_TEXTURE_SWIZZLE_G: 7737 case GL_TEXTURE_SWIZZLE_B: 7738 case GL_TEXTURE_SWIZZLE_A: 7739 switch (ConvertToGLenum(params[0])) 7740 { 7741 case GL_RED: 7742 case GL_GREEN: 7743 case GL_BLUE: 7744 case GL_ALPHA: 7745 case GL_ZERO: 7746 case GL_ONE: 7747 break; 7748 7749 default: 7750 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 7751 pname); 7752 return false; 7753 } 7754 break; 7755 7756 case GL_TEXTURE_BASE_LEVEL: 7757 if (ConvertToGLint(params[0]) < 0) 7758 { 7759 context->validationError(entryPoint, GL_INVALID_VALUE, kBaseLevelNegative); 7760 return false; 7761 } 7762 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0) 7763 { 7764 context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero); 7765 return false; 7766 } 7767 if ((target == TextureType::_2DMultisample || 7768 target == TextureType::_2DMultisampleArray) && 7769 static_cast<GLuint>(params[0]) != 0) 7770 { 7771 context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero); 7772 return false; 7773 } 7774 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0) 7775 { 7776 context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero); 7777 return false; 7778 } 7779 break; 7780 7781 case GL_TEXTURE_MAX_LEVEL: 7782 if (ConvertToGLint(params[0]) < 0) 7783 { 7784 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 7785 return false; 7786 } 7787 break; 7788 7789 case GL_DEPTH_STENCIL_TEXTURE_MODE: 7790 if (context->getClientVersion() < Version(3, 1)) 7791 { 7792 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31); 7793 return false; 7794 } 7795 switch (ConvertToGLenum(params[0])) 7796 { 7797 case GL_DEPTH_COMPONENT: 7798 case GL_STENCIL_INDEX: 7799 break; 7800 7801 default: 7802 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 7803 pname); 7804 return false; 7805 } 7806 break; 7807 7808 case GL_TEXTURE_SRGB_DECODE_EXT: 7809 if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params)) 7810 { 7811 return false; 7812 } 7813 break; 7814 7815 case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT: 7816 if (!ValidateTextureSRGBOverrideValue(context, entryPoint, params)) 7817 { 7818 return false; 7819 } 7820 break; 7821 7822 case GL_GENERATE_MIPMAP: 7823 if (context->getClientMajorVersion() > 1) 7824 { 7825 context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only); 7826 return false; 7827 } 7828 break; 7829 7830 case GL_TEXTURE_CROP_RECT_OES: 7831 if (context->getClientMajorVersion() > 1) 7832 { 7833 context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only); 7834 return false; 7835 } 7836 if (!vectorParams) 7837 { 7838 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize); 7839 return false; 7840 } 7841 break; 7842 7843 case GL_TEXTURE_BORDER_COLOR: 7844 if (!context->getExtensions().textureBorderClampOES && 7845 context->getClientVersion() < ES_3_2) 7846 { 7847 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 7848 return false; 7849 } 7850 if (!vectorParams) 7851 { 7852 context->validationError(entryPoint, GL_INVALID_ENUM, kInsufficientBufferSize); 7853 return false; 7854 } 7855 break; 7856 7857 case GL_RESOURCE_INITIALIZED_ANGLE: 7858 if (!context->getExtensions().robustResourceInitializationANGLE) 7859 { 7860 context->validationError(entryPoint, GL_INVALID_ENUM, 7861 kRobustResourceInitializationExtensionRequired); 7862 return false; 7863 } 7864 break; 7865 7866 case GL_TEXTURE_PROTECTED_EXT: 7867 if (!context->getExtensions().protectedTexturesEXT) 7868 { 7869 context->validationError(entryPoint, GL_INVALID_ENUM, 7870 kProtectedTexturesExtensionRequired); 7871 return false; 7872 } 7873 if (ConvertToBool(params[0]) != context->getState().hasProtectedContent()) 7874 { 7875 context->validationError(entryPoint, GL_INVALID_OPERATION, 7876 "Protected Texture must match Protected Context"); 7877 return false; 7878 } 7879 break; 7880 7881 default: 7882 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7883 return false; 7884 } 7885 7886 return true; 7887 } 7888 7889 template bool ValidateTexParameterBase(const Context *, 7890 angle::EntryPoint, 7891 TextureType, 7892 GLenum, 7893 GLsizei, 7894 bool, 7895 const GLfloat *); 7896 template bool ValidateTexParameterBase(const Context *, 7897 angle::EntryPoint, 7898 TextureType, 7899 GLenum, 7900 GLsizei, 7901 bool, 7902 const GLint *); 7903 template bool ValidateTexParameterBase(const Context *, 7904 angle::EntryPoint, 7905 TextureType, 7906 GLenum, 7907 GLsizei, 7908 bool, 7909 const GLuint *); 7910 7911 bool ValidateGetActiveUniformBlockivBase(const Context *context, 7912 angle::EntryPoint entryPoint, 7913 ShaderProgramID program, 7914 UniformBlockIndex uniformBlockIndex, 7915 GLenum pname, 7916 GLsizei *length) 7917 { 7918 if (length) 7919 { 7920 *length = 0; 7921 } 7922 7923 if (context->getClientMajorVersion() < 3) 7924 { 7925 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 7926 return false; 7927 } 7928 7929 Program *programObject = GetValidProgram(context, entryPoint, program); 7930 if (!programObject) 7931 { 7932 return false; 7933 } 7934 7935 if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount()) 7936 { 7937 context->validationError(entryPoint, GL_INVALID_VALUE, 7938 kIndexExceedsActiveUniformBlockCount); 7939 return false; 7940 } 7941 7942 switch (pname) 7943 { 7944 case GL_UNIFORM_BLOCK_BINDING: 7945 case GL_UNIFORM_BLOCK_DATA_SIZE: 7946 case GL_UNIFORM_BLOCK_NAME_LENGTH: 7947 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: 7948 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: 7949 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: 7950 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: 7951 break; 7952 7953 default: 7954 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 7955 return false; 7956 } 7957 7958 if (length) 7959 { 7960 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES) 7961 { 7962 const InterfaceBlock &uniformBlock = 7963 programObject->getUniformBlockByIndex(uniformBlockIndex.value); 7964 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size()); 7965 } 7966 else 7967 { 7968 *length = 1; 7969 } 7970 } 7971 7972 return true; 7973 } 7974 7975 template <typename ParamType> 7976 bool ValidateSamplerParameterBase(const Context *context, 7977 angle::EntryPoint entryPoint, 7978 SamplerID sampler, 7979 GLenum pname, 7980 GLsizei bufSize, 7981 bool vectorParams, 7982 const ParamType *params) 7983 { 7984 if (context->getClientMajorVersion() < 3) 7985 { 7986 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 7987 return false; 7988 } 7989 7990 if (!context->isSampler(sampler)) 7991 { 7992 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler); 7993 return false; 7994 } 7995 7996 const GLsizei minBufSize = GetSamplerParameterCount(pname); 7997 if (bufSize >= 0 && bufSize < minBufSize) 7998 { 7999 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize); 8000 return false; 8001 } 8002 8003 switch (pname) 8004 { 8005 case GL_TEXTURE_WRAP_S: 8006 case GL_TEXTURE_WRAP_T: 8007 case GL_TEXTURE_WRAP_R: 8008 if (!ValidateTextureWrapModeValue(context, entryPoint, params, false)) 8009 { 8010 return false; 8011 } 8012 break; 8013 8014 case GL_TEXTURE_MIN_FILTER: 8015 if (!ValidateTextureMinFilterValue(context, entryPoint, params, false)) 8016 { 8017 return false; 8018 } 8019 break; 8020 8021 case GL_TEXTURE_MAG_FILTER: 8022 if (!ValidateTextureMagFilterValue(context, entryPoint, params)) 8023 { 8024 return false; 8025 } 8026 break; 8027 8028 case GL_TEXTURE_MIN_LOD: 8029 case GL_TEXTURE_MAX_LOD: 8030 // any value is permissible 8031 break; 8032 8033 case GL_TEXTURE_COMPARE_MODE: 8034 if (!ValidateTextureCompareModeValue(context, entryPoint, params)) 8035 { 8036 return false; 8037 } 8038 break; 8039 8040 case GL_TEXTURE_COMPARE_FUNC: 8041 if (!ValidateTextureCompareFuncValue(context, entryPoint, params)) 8042 { 8043 return false; 8044 } 8045 break; 8046 8047 case GL_TEXTURE_SRGB_DECODE_EXT: 8048 if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params)) 8049 { 8050 return false; 8051 } 8052 break; 8053 8054 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 8055 { 8056 GLfloat paramValue = static_cast<GLfloat>(params[0]); 8057 if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue)) 8058 { 8059 return false; 8060 } 8061 } 8062 break; 8063 8064 case GL_TEXTURE_BORDER_COLOR: 8065 if (!context->getExtensions().textureBorderClampOES && 8066 context->getClientVersion() < ES_3_2) 8067 { 8068 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 8069 return false; 8070 } 8071 if (!vectorParams) 8072 { 8073 context->validationError(entryPoint, GL_INVALID_ENUM, kInsufficientBufferSize); 8074 return false; 8075 } 8076 break; 8077 8078 default: 8079 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 8080 return false; 8081 } 8082 8083 return true; 8084 } 8085 8086 template bool ValidateSamplerParameterBase(const Context *, 8087 angle::EntryPoint, 8088 SamplerID, 8089 GLenum, 8090 GLsizei, 8091 bool, 8092 const GLfloat *); 8093 template bool ValidateSamplerParameterBase(const Context *, 8094 angle::EntryPoint, 8095 SamplerID, 8096 GLenum, 8097 GLsizei, 8098 bool, 8099 const GLint *); 8100 template bool ValidateSamplerParameterBase(const Context *, 8101 angle::EntryPoint, 8102 SamplerID, 8103 GLenum, 8104 GLsizei, 8105 bool, 8106 const GLuint *); 8107 8108 bool ValidateGetSamplerParameterBase(const Context *context, 8109 angle::EntryPoint entryPoint, 8110 SamplerID sampler, 8111 GLenum pname, 8112 GLsizei *length) 8113 { 8114 if (length) 8115 { 8116 *length = 0; 8117 } 8118 8119 if (context->getClientMajorVersion() < 3) 8120 { 8121 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 8122 return false; 8123 } 8124 8125 if (!context->isSampler(sampler)) 8126 { 8127 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler); 8128 return false; 8129 } 8130 8131 switch (pname) 8132 { 8133 case GL_TEXTURE_WRAP_S: 8134 case GL_TEXTURE_WRAP_T: 8135 case GL_TEXTURE_WRAP_R: 8136 case GL_TEXTURE_MIN_FILTER: 8137 case GL_TEXTURE_MAG_FILTER: 8138 case GL_TEXTURE_MIN_LOD: 8139 case GL_TEXTURE_MAX_LOD: 8140 case GL_TEXTURE_COMPARE_MODE: 8141 case GL_TEXTURE_COMPARE_FUNC: 8142 break; 8143 8144 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 8145 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint)) 8146 { 8147 return false; 8148 } 8149 break; 8150 8151 case GL_TEXTURE_SRGB_DECODE_EXT: 8152 if (!context->getExtensions().textureSRGBDecodeEXT) 8153 { 8154 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 8155 return false; 8156 } 8157 break; 8158 8159 case GL_TEXTURE_BORDER_COLOR: 8160 if (!context->getExtensions().textureBorderClampOES && 8161 context->getClientVersion() < ES_3_2) 8162 { 8163 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 8164 return false; 8165 } 8166 break; 8167 8168 default: 8169 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 8170 return false; 8171 } 8172 8173 if (length) 8174 { 8175 *length = GetSamplerParameterCount(pname); 8176 } 8177 return true; 8178 } 8179 8180 bool ValidateGetInternalFormativBase(const Context *context, 8181 angle::EntryPoint entryPoint, 8182 GLenum target, 8183 GLenum internalformat, 8184 GLenum pname, 8185 GLsizei bufSize, 8186 GLsizei *numParams) 8187 { 8188 if (numParams) 8189 { 8190 *numParams = 0; 8191 } 8192 8193 if (context->getClientMajorVersion() < 3) 8194 { 8195 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 8196 return false; 8197 } 8198 8199 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); 8200 if (!formatCaps.renderbuffer) 8201 { 8202 context->validationError(entryPoint, GL_INVALID_ENUM, kFormatNotRenderable); 8203 return false; 8204 } 8205 8206 switch (target) 8207 { 8208 case GL_RENDERBUFFER: 8209 break; 8210 8211 case GL_TEXTURE_2D_MULTISAMPLE: 8212 if (context->getClientVersion() < ES_3_1 && 8213 !context->getExtensions().textureMultisampleANGLE) 8214 { 8215 context->validationError(entryPoint, GL_INVALID_ENUM, 8216 kMultisampleTextureExtensionOrES31Required); 8217 return false; 8218 } 8219 break; 8220 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES: 8221 if (!context->getExtensions().textureStorageMultisample2dArrayOES) 8222 { 8223 context->validationError(entryPoint, GL_INVALID_ENUM, 8224 kMultisampleArrayExtensionRequired); 8225 return false; 8226 } 8227 break; 8228 default: 8229 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget); 8230 return false; 8231 } 8232 8233 if (bufSize < 0) 8234 { 8235 context->validationError(entryPoint, GL_INVALID_VALUE, kInsufficientBufferSize); 8236 return false; 8237 } 8238 8239 GLsizei maxWriteParams = 0; 8240 switch (pname) 8241 { 8242 case GL_NUM_SAMPLE_COUNTS: 8243 maxWriteParams = 1; 8244 break; 8245 8246 case GL_SAMPLES: 8247 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size()); 8248 break; 8249 8250 default: 8251 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 8252 return false; 8253 } 8254 8255 if (numParams) 8256 { 8257 // glGetInternalFormativ will not overflow bufSize 8258 *numParams = std::min(bufSize, maxWriteParams); 8259 } 8260 8261 return true; 8262 } 8263 8264 bool ValidateFramebufferNotMultisampled(const Context *context, 8265 angle::EntryPoint entryPoint, 8266 const Framebuffer *framebuffer, 8267 bool checkReadBufferResourceSamples) 8268 { 8269 int samples = checkReadBufferResourceSamples 8270 ? framebuffer->getReadBufferResourceSamples(context) 8271 : framebuffer->getSamples(context); 8272 if (samples != 0) 8273 { 8274 context->validationError(entryPoint, GL_INVALID_OPERATION, 8275 kInvalidMultisampledFramebufferOperation); 8276 return false; 8277 } 8278 return true; 8279 } 8280 8281 bool ValidateMultitextureUnit(const Context *context, angle::EntryPoint entryPoint, GLenum texture) 8282 { 8283 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits) 8284 { 8285 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMultitextureUnit); 8286 return false; 8287 } 8288 return true; 8289 } 8290 8291 bool ValidateTexStorageMultisample(const Context *context, 8292 angle::EntryPoint entryPoint, 8293 TextureType target, 8294 GLsizei samples, 8295 GLint internalFormat, 8296 GLsizei width, 8297 GLsizei height) 8298 { 8299 const Caps &caps = context->getCaps(); 8300 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize) 8301 { 8302 context->validationError(entryPoint, GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange); 8303 return false; 8304 } 8305 8306 if (samples == 0) 8307 { 8308 context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesZero); 8309 return false; 8310 } 8311 8312 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); 8313 if (!formatCaps.textureAttachment) 8314 { 8315 context->validationError(entryPoint, GL_INVALID_ENUM, kRenderableInternalFormat); 8316 return false; 8317 } 8318 8319 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat 8320 // is one of the unsized base internalformats listed in table 8.11. 8321 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat); 8322 if (formatInfo.internalFormat == GL_NONE) 8323 { 8324 context->validationError(entryPoint, GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported); 8325 return false; 8326 } 8327 8328 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) 8329 { 8330 context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange); 8331 return false; 8332 } 8333 8334 Texture *texture = context->getTextureByType(target); 8335 if (!texture || texture->id().value == 0) 8336 { 8337 context->validationError(entryPoint, GL_INVALID_OPERATION, kZeroBoundToTarget); 8338 return false; 8339 } 8340 8341 if (texture->getImmutableFormat()) 8342 { 8343 context->validationError(entryPoint, GL_INVALID_OPERATION, kImmutableTextureBound); 8344 return false; 8345 } 8346 return true; 8347 } 8348 8349 bool ValidateTexStorage2DMultisampleBase(const Context *context, 8350 angle::EntryPoint entryPoint, 8351 TextureType target, 8352 GLsizei samples, 8353 GLint internalFormat, 8354 GLsizei width, 8355 GLsizei height) 8356 { 8357 if (target != TextureType::_2DMultisample) 8358 { 8359 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget); 8360 return false; 8361 } 8362 8363 if (width < 1 || height < 1) 8364 { 8365 context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall); 8366 return false; 8367 } 8368 8369 return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalFormat, 8370 width, height); 8371 } 8372 8373 bool ValidateGetTexLevelParameterBase(const Context *context, 8374 angle::EntryPoint entryPoint, 8375 TextureTarget target, 8376 GLint level, 8377 GLenum pname, 8378 GLsizei *length) 8379 { 8380 8381 if (length) 8382 { 8383 *length = 0; 8384 } 8385 8386 TextureType type = TextureTargetToType(target); 8387 8388 if (!ValidTexLevelDestinationTarget(context, type)) 8389 { 8390 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 8391 return false; 8392 } 8393 8394 if (context->getTextureByType(type) == nullptr) 8395 { 8396 context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound); 8397 return false; 8398 } 8399 8400 if (!ValidMipLevel(context, type, level)) 8401 { 8402 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 8403 return false; 8404 } 8405 8406 switch (pname) 8407 { 8408 case GL_TEXTURE_RED_TYPE: 8409 case GL_TEXTURE_GREEN_TYPE: 8410 case GL_TEXTURE_BLUE_TYPE: 8411 case GL_TEXTURE_ALPHA_TYPE: 8412 case GL_TEXTURE_DEPTH_TYPE: 8413 case GL_TEXTURE_RED_SIZE: 8414 case GL_TEXTURE_GREEN_SIZE: 8415 case GL_TEXTURE_BLUE_SIZE: 8416 case GL_TEXTURE_ALPHA_SIZE: 8417 case GL_TEXTURE_DEPTH_SIZE: 8418 case GL_TEXTURE_STENCIL_SIZE: 8419 case GL_TEXTURE_SHARED_SIZE: 8420 case GL_TEXTURE_INTERNAL_FORMAT: 8421 case GL_TEXTURE_WIDTH: 8422 case GL_TEXTURE_HEIGHT: 8423 case GL_TEXTURE_DEPTH: 8424 case GL_TEXTURE_SAMPLES: 8425 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS: 8426 case GL_TEXTURE_COMPRESSED: 8427 break; 8428 8429 case GL_RESOURCE_INITIALIZED_ANGLE: 8430 if (!context->getExtensions().robustResourceInitializationANGLE) 8431 { 8432 context->validationError(entryPoint, GL_INVALID_ENUM, 8433 kRobustResourceInitializationExtensionRequired); 8434 return false; 8435 } 8436 break; 8437 8438 case GL_TEXTURE_BUFFER_DATA_STORE_BINDING: 8439 case GL_TEXTURE_BUFFER_OFFSET: 8440 case GL_TEXTURE_BUFFER_SIZE: 8441 if (context->getClientVersion() < Version(3, 2) && 8442 !context->getExtensions().textureBufferAny()) 8443 { 8444 context->validationError(entryPoint, GL_INVALID_ENUM, 8445 kTextureBufferExtensionNotAvailable); 8446 return false; 8447 } 8448 break; 8449 8450 default: 8451 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 8452 return false; 8453 } 8454 8455 if (length) 8456 { 8457 *length = 1; 8458 } 8459 return true; 8460 } 8461 8462 bool ValidateGetMultisamplefvBase(const Context *context, 8463 angle::EntryPoint entryPoint, 8464 GLenum pname, 8465 GLuint index, 8466 const GLfloat *val) 8467 { 8468 if (pname != GL_SAMPLE_POSITION) 8469 { 8470 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 8471 return false; 8472 } 8473 8474 Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); 8475 GLint samples = framebuffer->getSamples(context); 8476 8477 if (index >= static_cast<GLuint>(samples)) 8478 { 8479 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsSamples); 8480 return false; 8481 } 8482 8483 return true; 8484 } 8485 8486 bool ValidateSampleMaskiBase(const Context *context, 8487 angle::EntryPoint entryPoint, 8488 GLuint maskNumber, 8489 GLbitfield mask) 8490 { 8491 if (maskNumber >= static_cast<GLuint>(context->getCaps().maxSampleMaskWords)) 8492 { 8493 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber); 8494 return false; 8495 } 8496 8497 return true; 8498 } 8499 8500 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint) 8501 { 8502 // An overflow can happen when adding the offset. Check against a special constant. 8503 if (context->getStateCache().getNonInstancedVertexElementLimit() == 8504 VertexAttribute::kIntegerOverflow || 8505 context->getStateCache().getInstancedVertexElementLimit() == 8506 VertexAttribute::kIntegerOverflow) 8507 { 8508 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 8509 } 8510 else 8511 { 8512 // [OpenGL ES 3.0.2] section 2.9.4 page 40: 8513 // We can return INVALID_OPERATION if our buffer does not have enough backing data. 8514 context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientVertexBufferSize); 8515 } 8516 } 8517 8518 bool ValidateLoseContextCHROMIUM(const Context *context, 8519 angle::EntryPoint entryPoint, 8520 GraphicsResetStatus current, 8521 GraphicsResetStatus other) 8522 { 8523 if (!context->getExtensions().loseContextCHROMIUM) 8524 { 8525 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 8526 return false; 8527 } 8528 8529 switch (current) 8530 { 8531 case GraphicsResetStatus::GuiltyContextReset: 8532 case GraphicsResetStatus::InnocentContextReset: 8533 case GraphicsResetStatus::UnknownContextReset: 8534 break; 8535 8536 default: 8537 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidResetStatus); 8538 } 8539 8540 switch (other) 8541 { 8542 case GraphicsResetStatus::GuiltyContextReset: 8543 case GraphicsResetStatus::InnocentContextReset: 8544 case GraphicsResetStatus::UnknownContextReset: 8545 break; 8546 8547 default: 8548 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidResetStatus); 8549 } 8550 8551 return true; 8552 } 8553 8554 // GL_ANGLE_texture_storage_external 8555 bool ValidateTexImage2DExternalANGLE(const Context *context, 8556 angle::EntryPoint entryPoint, 8557 TextureTarget target, 8558 GLint level, 8559 GLint internalformat, 8560 GLsizei width, 8561 GLsizei height, 8562 GLint border, 8563 GLenum format, 8564 GLenum type) 8565 { 8566 if (!context->getExtensions().textureExternalUpdateANGLE) 8567 { 8568 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 8569 return false; 8570 } 8571 8572 if (!ValidTexture2DDestinationTarget(context, target) && 8573 !ValidTextureExternalTarget(context, target)) 8574 { 8575 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 8576 return false; 8577 } 8578 8579 if (context->getClientMajorVersion() <= 2) 8580 { 8581 if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat, 8582 false, false, 0, 0, width, height, border, format, 8583 type, -1, nullptr)) 8584 { 8585 return false; 8586 } 8587 } 8588 else 8589 { 8590 if (!ValidateES3TexImageParametersBase(context, entryPoint, target, level, internalformat, 8591 false, false, 0, 0, 0, width, height, 1, border, 8592 format, type, -1, nullptr)) 8593 { 8594 return false; 8595 } 8596 } 8597 8598 return true; 8599 } 8600 8601 bool ValidateInvalidateTextureANGLE(const Context *context, 8602 angle::EntryPoint entryPoint, 8603 TextureType target) 8604 { 8605 if (!context->getExtensions().textureExternalUpdateANGLE) 8606 { 8607 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 8608 return false; 8609 } 8610 8611 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) 8612 { 8613 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 8614 return false; 8615 } 8616 8617 return true; 8618 } 8619 8620 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context, 8621 const ProgramExecutable *programExecutable) 8622 { 8623 size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount(); 8624 const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); 8625 for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex) 8626 { 8627 const OffsetBindingPointer<Buffer> &buffer = 8628 transformFeedback->getIndexedBuffer(programXfbIndex); 8629 if (!buffer.get()) 8630 { 8631 return false; 8632 } 8633 } 8634 8635 return true; 8636 } 8637 8638 bool ValidateLogicOpCommon(const Context *context, 8639 angle::EntryPoint entryPoint, 8640 LogicalOperation opcodePacked) 8641 { 8642 switch (opcodePacked) 8643 { 8644 case LogicalOperation::And: 8645 case LogicalOperation::AndInverted: 8646 case LogicalOperation::AndReverse: 8647 case LogicalOperation::Clear: 8648 case LogicalOperation::Copy: 8649 case LogicalOperation::CopyInverted: 8650 case LogicalOperation::Equiv: 8651 case LogicalOperation::Invert: 8652 case LogicalOperation::Nand: 8653 case LogicalOperation::Noop: 8654 case LogicalOperation::Nor: 8655 case LogicalOperation::Or: 8656 case LogicalOperation::OrInverted: 8657 case LogicalOperation::OrReverse: 8658 case LogicalOperation::Set: 8659 case LogicalOperation::Xor: 8660 return true; 8661 default: 8662 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLogicOp); 8663 return false; 8664 } 8665 } 8666 } // namespace gl