validationES2.cpp (227287B)
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 // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters 8 9 #include "libANGLE/validationES2_autogen.h" 10 11 #include <cstdint> 12 13 #include "common/mathutil.h" 14 #include "common/string_utils.h" 15 #include "common/utilities.h" 16 #include "libANGLE/Context.h" 17 #include "libANGLE/ErrorStrings.h" 18 #include "libANGLE/Fence.h" 19 #include "libANGLE/Framebuffer.h" 20 #include "libANGLE/FramebufferAttachment.h" 21 #include "libANGLE/MemoryObject.h" 22 #include "libANGLE/Renderbuffer.h" 23 #include "libANGLE/Shader.h" 24 #include "libANGLE/Texture.h" 25 #include "libANGLE/Uniform.h" 26 #include "libANGLE/VertexArray.h" 27 #include "libANGLE/formatutils.h" 28 #include "libANGLE/validationES.h" 29 #include "libANGLE/validationES2.h" 30 #include "libANGLE/validationES3_autogen.h" 31 32 namespace gl 33 { 34 using namespace err; 35 36 namespace 37 { 38 39 bool IsPartialBlit(const Context *context, 40 const FramebufferAttachment *readBuffer, 41 const FramebufferAttachment *writeBuffer, 42 GLint srcX0, 43 GLint srcY0, 44 GLint srcX1, 45 GLint srcY1, 46 GLint dstX0, 47 GLint dstY0, 48 GLint dstX1, 49 GLint dstY1) 50 { 51 const Extents &writeSize = writeBuffer->getSize(); 52 const Extents &readSize = readBuffer->getSize(); 53 54 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width || 55 dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height) 56 { 57 return true; 58 } 59 60 if (context->getState().isScissorTestEnabled()) 61 { 62 const Rectangle &scissor = context->getState().getScissor(); 63 return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width || 64 scissor.height < writeSize.height; 65 } 66 67 return false; 68 } 69 70 bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat) 71 { 72 // Table 1.1 from the CHROMIUM_copy_texture spec 73 switch (GetUnsizedFormat(internalFormat)) 74 { 75 case GL_RED: 76 case GL_ALPHA: 77 case GL_LUMINANCE: 78 case GL_LUMINANCE_ALPHA: 79 case GL_RGB: 80 case GL_RGBA: 81 case GL_RGB8: 82 case GL_RGBA8: 83 case GL_BGRA_EXT: 84 case GL_BGRA8_EXT: 85 return true; 86 87 default: 88 return false; 89 } 90 } 91 92 bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat) 93 { 94 return IsValidCopyTextureSourceInternalFormatEnum(internalFormat); 95 } 96 97 bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat) 98 { 99 // Table 1.0 from the CHROMIUM_copy_texture spec 100 switch (internalFormat) 101 { 102 case GL_ALPHA: 103 case GL_BGRA8_EXT: 104 case GL_BGRA_EXT: 105 case GL_LUMINANCE: 106 case GL_LUMINANCE_ALPHA: 107 case GL_R11F_G11F_B10F: 108 case GL_R16F: 109 case GL_R32F: 110 case GL_R8: 111 case GL_R8UI: 112 case GL_RG16F: 113 case GL_RG32F: 114 case GL_RG8: 115 case GL_RG8UI: 116 case GL_RGB: 117 case GL_RGB10_A2: 118 case GL_RGB16F: 119 case GL_RGB32F: 120 case GL_RGB565: 121 case GL_RGB5_A1: 122 case GL_RGB8: 123 case GL_RGB8UI: 124 case GL_RGB9_E5: 125 case GL_RGBA: 126 case GL_RGBA16F: 127 case GL_RGBA32F: 128 case GL_RGBA4: 129 case GL_RGBA8: 130 case GL_RGBA8UI: 131 case GL_RGBX8_ANGLE: 132 case GL_SRGB8: 133 case GL_SRGB8_ALPHA8: 134 case GL_SRGB_ALPHA_EXT: 135 case GL_SRGB_EXT: 136 return true; 137 138 default: 139 return false; 140 } 141 } 142 143 bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat) 144 { 145 return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat); 146 } 147 148 bool IsValidCopyTextureDestinationFormatType(const Context *context, 149 angle::EntryPoint entryPoint, 150 GLint internalFormat, 151 GLenum type) 152 { 153 if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat)) 154 { 155 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 156 internalFormat); 157 return false; 158 } 159 160 if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat)) 161 { 162 context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedTypeAndFormat); 163 return false; 164 } 165 166 const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type); 167 if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) 168 { 169 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 170 internalFormat); 171 return false; 172 } 173 174 return true; 175 } 176 177 bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target) 178 { 179 switch (target) 180 { 181 case TextureTarget::_2D: 182 case TextureTarget::CubeMapNegativeX: 183 case TextureTarget::CubeMapNegativeY: 184 case TextureTarget::CubeMapNegativeZ: 185 case TextureTarget::CubeMapPositiveX: 186 case TextureTarget::CubeMapPositiveY: 187 case TextureTarget::CubeMapPositiveZ: 188 return true; 189 190 case TextureTarget::Rectangle: 191 return context->getExtensions().textureRectangleANGLE; 192 193 default: 194 return false; 195 } 196 } 197 198 bool IsValidCopyTextureDestinationTarget(const Context *context, 199 TextureType textureType, 200 TextureTarget target) 201 { 202 return TextureTargetToType(target) == textureType; 203 } 204 205 bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type) 206 { 207 switch (type) 208 { 209 case TextureType::_2D: 210 return true; 211 case TextureType::Rectangle: 212 return context->getExtensions().textureRectangleANGLE; 213 case TextureType::External: 214 return context->getExtensions().EGLImageExternalOES; 215 case TextureType::VideoImage: 216 return context->getExtensions().videoTextureWEBGL; 217 default: 218 return false; 219 } 220 } 221 222 bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLint level) 223 { 224 if (!ValidMipLevel(context, type, level)) 225 { 226 return false; 227 } 228 229 if (level > 0 && context->getClientVersion() < ES_3_0) 230 { 231 return false; 232 } 233 234 return true; 235 } 236 237 bool IsValidCopyTextureDestinationLevel(const Context *context, 238 angle::EntryPoint entryPoint, 239 TextureType type, 240 GLint level, 241 GLsizei width, 242 GLsizei height, 243 bool isSubImage) 244 { 245 if (!ValidMipLevel(context, type, level)) 246 { 247 return false; 248 } 249 250 if (!ValidImageSizeParameters(context, entryPoint, type, level, width, height, 1, isSubImage)) 251 { 252 return false; 253 } 254 255 const Caps &caps = context->getCaps(); 256 switch (type) 257 { 258 case TextureType::_2D: 259 return width <= (caps.max2DTextureSize >> level) && 260 height <= (caps.max2DTextureSize >> level); 261 case TextureType::Rectangle: 262 ASSERT(level == 0); 263 return width <= (caps.max2DTextureSize >> level) && 264 height <= (caps.max2DTextureSize >> level); 265 266 case TextureType::CubeMap: 267 return width <= (caps.maxCubeMapTextureSize >> level) && 268 height <= (caps.maxCubeMapTextureSize >> level); 269 default: 270 return true; 271 } 272 } 273 274 bool IsValidStencilFunc(GLenum func) 275 { 276 switch (func) 277 { 278 case GL_NEVER: 279 case GL_ALWAYS: 280 case GL_LESS: 281 case GL_LEQUAL: 282 case GL_EQUAL: 283 case GL_GEQUAL: 284 case GL_GREATER: 285 case GL_NOTEQUAL: 286 return true; 287 288 default: 289 return false; 290 } 291 } 292 293 bool IsValidStencilFace(GLenum face) 294 { 295 switch (face) 296 { 297 case GL_FRONT: 298 case GL_BACK: 299 case GL_FRONT_AND_BACK: 300 return true; 301 302 default: 303 return false; 304 } 305 } 306 307 bool IsValidStencilOp(GLenum op) 308 { 309 switch (op) 310 { 311 case GL_ZERO: 312 case GL_KEEP: 313 case GL_REPLACE: 314 case GL_INCR: 315 case GL_DECR: 316 case GL_INVERT: 317 case GL_INCR_WRAP: 318 case GL_DECR_WRAP: 319 return true; 320 321 default: 322 return false; 323 } 324 } 325 326 static inline bool Valid1to4ComponentFloatColorBufferFormat(const Context *context, GLenum format) 327 { 328 return (context->getExtensions().textureFloatOES && 329 (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F || 330 format == GL_R32F)) || 331 (context->getExtensions().textureHalfFloatOES && 332 (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F || 333 format == GL_R16F)); 334 } 335 336 static inline bool Valid2to4ComponentFloatColorBufferFormat(const Context *context, GLenum format) 337 { 338 return (context->getExtensions().textureFloatOES && 339 (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F)) || 340 (context->getExtensions().textureHalfFloatOES && 341 (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F)); 342 } 343 344 static inline bool Valid3to4ComponentFloatColorBufferFormat(const Context *context, GLenum format) 345 { 346 return (context->getExtensions().textureFloatOES && 347 (format == GL_RGBA32F || format == GL_RGB32F)) || 348 (context->getExtensions().textureHalfFloatOES && 349 (format == GL_RGBA16F || format == GL_RGB16F)); 350 } 351 352 static inline bool Valid4ComponentFloatColorBufferFormat(const Context *context, GLenum format) 353 { 354 return (context->getExtensions().textureFloatOES && format == GL_RGBA32F) || 355 (context->getExtensions().textureHalfFloatOES && format == GL_RGBA16F); 356 } 357 358 bool ValidateES2CopyTexImageParameters(const Context *context, 359 angle::EntryPoint entryPoint, 360 TextureTarget target, 361 GLint level, 362 GLenum internalformat, 363 bool isSubImage, 364 GLint xoffset, 365 GLint yoffset, 366 GLint x, 367 GLint y, 368 GLsizei width, 369 GLsizei height, 370 GLint border) 371 { 372 if (!ValidTexture2DDestinationTarget(context, target)) 373 { 374 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 375 return false; 376 } 377 378 TextureType texType = TextureTargetToType(target); 379 if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1, 380 isSubImage)) 381 { 382 // Error is already handled. 383 return false; 384 } 385 386 Format textureFormat = Format::Invalid(); 387 if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat, 388 isSubImage, xoffset, yoffset, 0, x, y, width, height, 389 border, &textureFormat)) 390 { 391 return false; 392 } 393 394 ASSERT(textureFormat.valid() || !isSubImage); 395 396 const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); 397 GLenum colorbufferFormat = 398 framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat; 399 const auto &formatInfo = *textureFormat.info; 400 401 // ValidateCopyTexImageParametersBase rejects compressed formats with GL_INVALID_OPERATION. 402 ASSERT(!formatInfo.compressed); 403 ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).compressed); 404 405 // ValidateCopyTexImageParametersBase rejects depth formats with GL_INVALID_OPERATION. 406 ASSERT(!formatInfo.depthBits); 407 ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).depthBits); 408 409 // [OpenGL ES 2.0.24] table 3.9 410 if (isSubImage) 411 { 412 switch (formatInfo.format) 413 { 414 case GL_ALPHA: 415 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 && 416 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && 417 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && 418 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 419 { 420 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 421 return false; 422 } 423 break; 424 case GL_LUMINANCE: 425 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT && 426 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && 427 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 428 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT && 429 colorbufferFormat != GL_BGR5_A1_ANGLEX && 430 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 431 !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 432 { 433 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 434 return false; 435 } 436 break; 437 case GL_RED_EXT: 438 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT && 439 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && 440 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 441 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F && 442 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F && 443 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT && 444 colorbufferFormat != GL_BGR5_A1_ANGLEX && 445 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 446 !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 447 { 448 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 449 return false; 450 } 451 break; 452 case GL_RG_EXT: 453 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 && 454 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && 455 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES && 456 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F && 457 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT && 458 colorbufferFormat != GL_BGR5_A1_ANGLEX && 459 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 460 !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 461 { 462 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 463 return false; 464 } 465 break; 466 case GL_RGB: 467 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && 468 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 469 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F && 470 colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT && 471 colorbufferFormat != GL_BGR5_A1_ANGLEX && 472 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 473 !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 474 { 475 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 476 return false; 477 } 478 break; 479 case GL_LUMINANCE_ALPHA: 480 case GL_RGBA: 481 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 482 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F && 483 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX && 484 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 485 { 486 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 487 return false; 488 } 489 break; 490 default: 491 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 492 return false; 493 } 494 495 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES) 496 { 497 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 498 return false; 499 } 500 } 501 else 502 { 503 switch (internalformat) 504 { 505 case GL_ALPHA: 506 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 && 507 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && 508 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && 509 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 510 { 511 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 512 return false; 513 } 514 break; 515 case GL_LUMINANCE: 516 case GL_RED_EXT: 517 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT && 518 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && 519 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 520 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && 521 colorbufferFormat != GL_BGR5_A1_ANGLEX && 522 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 523 !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 524 { 525 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 526 return false; 527 } 528 break; 529 case GL_RG_EXT: 530 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 && 531 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && 532 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT && 533 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX && 534 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 535 !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 536 { 537 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 538 return false; 539 } 540 break; 541 case GL_RGB: 542 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES && 543 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 544 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && 545 colorbufferFormat != GL_BGR5_A1_ANGLEX && 546 colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE && 547 !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 548 { 549 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 550 return false; 551 } 552 break; 553 case GL_LUMINANCE_ALPHA: 554 case GL_RGBA: 555 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && 556 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES && 557 colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_RGBA16F && 558 !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat)) 559 { 560 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 561 return false; 562 } 563 break; 564 default: 565 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 566 internalformat); 567 return false; 568 } 569 } 570 571 // If width or height is zero, it is a no-op. Return false without setting an error. 572 return (width > 0 && height > 0); 573 } 574 575 bool ValidCap(const Context *context, GLenum cap, bool queryOnly) 576 { 577 switch (cap) 578 { 579 // EXT_multisample_compatibility 580 case GL_MULTISAMPLE_EXT: 581 case GL_SAMPLE_ALPHA_TO_ONE_EXT: 582 return context->getExtensions().multisampleCompatibilityEXT; 583 584 case GL_CULL_FACE: 585 case GL_POLYGON_OFFSET_FILL: 586 case GL_SAMPLE_ALPHA_TO_COVERAGE: 587 case GL_SAMPLE_COVERAGE: 588 case GL_SCISSOR_TEST: 589 case GL_STENCIL_TEST: 590 case GL_DEPTH_TEST: 591 case GL_BLEND: 592 case GL_DITHER: 593 return true; 594 595 case GL_PRIMITIVE_RESTART_FIXED_INDEX: 596 case GL_RASTERIZER_DISCARD: 597 return (context->getClientMajorVersion() >= 3); 598 599 case GL_DEBUG_OUTPUT_SYNCHRONOUS: 600 case GL_DEBUG_OUTPUT: 601 return context->getExtensions().debugKHR; 602 603 case GL_BIND_GENERATES_RESOURCE_CHROMIUM: 604 return queryOnly && context->getExtensions().bindGeneratesResourceCHROMIUM; 605 606 case GL_CLIENT_ARRAYS_ANGLE: 607 return queryOnly && context->getExtensions().clientArraysANGLE; 608 609 case GL_FRAMEBUFFER_SRGB_EXT: 610 return context->getExtensions().sRGBWriteControlEXT; 611 612 case GL_SAMPLE_MASK: 613 return context->getClientVersion() >= Version(3, 1); 614 615 case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE: 616 return queryOnly && context->getExtensions().robustResourceInitializationANGLE; 617 618 case GL_TEXTURE_RECTANGLE_ANGLE: 619 return context->isWebGL(); 620 621 // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance 622 case GL_CLIP_DISTANCE0_EXT: 623 case GL_CLIP_DISTANCE1_EXT: 624 case GL_CLIP_DISTANCE2_EXT: 625 case GL_CLIP_DISTANCE3_EXT: 626 case GL_CLIP_DISTANCE4_EXT: 627 case GL_CLIP_DISTANCE5_EXT: 628 case GL_CLIP_DISTANCE6_EXT: 629 case GL_CLIP_DISTANCE7_EXT: 630 if (context->getExtensions().clipDistanceAPPLE || 631 context->getExtensions().clipCullDistanceEXT) 632 { 633 return true; 634 } 635 break; 636 case GL_SAMPLE_SHADING: 637 return context->getExtensions().sampleShadingOES; 638 case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM: 639 return context->getExtensions().shadingRateQCOM; 640 641 // COLOR_LOGIC_OP is in GLES1, but exposed through an ANGLE extension. 642 case GL_COLOR_LOGIC_OP: 643 return context->getClientVersion() < Version(2, 0) || 644 context->getExtensions().logicOpANGLE; 645 646 default: 647 break; 648 } 649 650 // GLES1 emulation: GLES1-specific caps after this point 651 if (context->getClientVersion().major != 1) 652 { 653 return false; 654 } 655 656 switch (cap) 657 { 658 case GL_ALPHA_TEST: 659 case GL_VERTEX_ARRAY: 660 case GL_NORMAL_ARRAY: 661 case GL_COLOR_ARRAY: 662 case GL_TEXTURE_COORD_ARRAY: 663 case GL_TEXTURE_2D: 664 case GL_LIGHTING: 665 case GL_LIGHT0: 666 case GL_LIGHT1: 667 case GL_LIGHT2: 668 case GL_LIGHT3: 669 case GL_LIGHT4: 670 case GL_LIGHT5: 671 case GL_LIGHT6: 672 case GL_LIGHT7: 673 case GL_NORMALIZE: 674 case GL_RESCALE_NORMAL: 675 case GL_COLOR_MATERIAL: 676 case GL_CLIP_PLANE0: 677 case GL_CLIP_PLANE1: 678 case GL_CLIP_PLANE2: 679 case GL_CLIP_PLANE3: 680 case GL_CLIP_PLANE4: 681 case GL_CLIP_PLANE5: 682 case GL_FOG: 683 case GL_POINT_SMOOTH: 684 case GL_LINE_SMOOTH: 685 return context->getClientVersion() < Version(2, 0); 686 case GL_POINT_SIZE_ARRAY_OES: 687 return context->getClientVersion() < Version(2, 0) && 688 context->getExtensions().pointSizeArrayOES; 689 case GL_TEXTURE_CUBE_MAP: 690 return context->getClientVersion() < Version(2, 0) && 691 context->getExtensions().textureCubeMapOES; 692 case GL_POINT_SPRITE_OES: 693 return context->getClientVersion() < Version(2, 0) && 694 context->getExtensions().pointSpriteOES; 695 default: 696 return false; 697 } 698 } 699 700 // Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section 701 // 3.1. 702 bool IsValidESSLCharacter(unsigned char c) 703 { 704 // Printing characters are valid except " $ ` @ \ ' DEL. 705 if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && 706 c != '\'') 707 { 708 return true; 709 } 710 711 // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid. 712 if (c >= 9 && c <= 13) 713 { 714 return true; 715 } 716 717 return false; 718 } 719 720 bool IsValidESSLString(const char *str, size_t len) 721 { 722 for (size_t i = 0; i < len; i++) 723 { 724 if (!IsValidESSLCharacter(str[i])) 725 { 726 return false; 727 } 728 } 729 730 return true; 731 } 732 733 bool ValidateWebGLNamePrefix(const Context *context, 734 angle::EntryPoint entryPoint, 735 const GLchar *name) 736 { 737 ASSERT(context->isWebGL()); 738 739 // WebGL 1.0 [Section 6.16] GLSL Constructs 740 // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL. 741 if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0) 742 { 743 context->validationError(entryPoint, GL_INVALID_OPERATION, 744 kWebglBindAttribLocationReservedPrefix); 745 return false; 746 } 747 748 return true; 749 } 750 751 bool ValidateWebGLNameLength(const Context *context, angle::EntryPoint entryPoint, size_t length) 752 { 753 ASSERT(context->isWebGL()); 754 755 if (context->isWebGL1() && length > 256) 756 { 757 // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths 758 // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute 759 // locations. 760 context->validationError(entryPoint, GL_INVALID_VALUE, kWebglNameLengthLimitExceeded); 761 762 return false; 763 } 764 else if (length > 1024) 765 { 766 // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of 767 // uniform and attribute locations. 768 context->validationError(entryPoint, GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded); 769 return false; 770 } 771 772 return true; 773 } 774 775 bool ValidBlendFunc(const Context *context, GLenum val) 776 { 777 const Extensions &ext = context->getExtensions(); 778 779 // these are always valid for src and dst. 780 switch (val) 781 { 782 case GL_ZERO: 783 case GL_ONE: 784 case GL_SRC_COLOR: 785 case GL_ONE_MINUS_SRC_COLOR: 786 case GL_DST_COLOR: 787 case GL_ONE_MINUS_DST_COLOR: 788 case GL_SRC_ALPHA: 789 case GL_ONE_MINUS_SRC_ALPHA: 790 case GL_DST_ALPHA: 791 case GL_ONE_MINUS_DST_ALPHA: 792 case GL_CONSTANT_COLOR: 793 case GL_ONE_MINUS_CONSTANT_COLOR: 794 case GL_CONSTANT_ALPHA: 795 case GL_ONE_MINUS_CONSTANT_ALPHA: 796 return true; 797 798 // EXT_blend_func_extended. 799 case GL_SRC1_COLOR_EXT: 800 case GL_SRC1_ALPHA_EXT: 801 case GL_ONE_MINUS_SRC1_COLOR_EXT: 802 case GL_ONE_MINUS_SRC1_ALPHA_EXT: 803 case GL_SRC_ALPHA_SATURATE_EXT: 804 return ext.blendFuncExtendedEXT; 805 806 default: 807 return false; 808 } 809 } 810 811 bool ValidSrcBlendFunc(const Context *context, GLenum val) 812 { 813 if (ValidBlendFunc(context, val)) 814 return true; 815 816 if (val == GL_SRC_ALPHA_SATURATE) 817 return true; 818 819 return false; 820 } 821 822 bool ValidDstBlendFunc(const Context *context, GLenum val) 823 { 824 if (ValidBlendFunc(context, val)) 825 return true; 826 827 if (val == GL_SRC_ALPHA_SATURATE) 828 { 829 if (context->getClientMajorVersion() >= 3) 830 return true; 831 } 832 833 return false; 834 } 835 836 bool ValidateES2TexImageParameters(const Context *context, 837 angle::EntryPoint entryPoint, 838 TextureTarget target, 839 GLint level, 840 GLenum internalformat, 841 bool isCompressed, 842 bool isSubImage, 843 GLint xoffset, 844 GLint yoffset, 845 GLsizei width, 846 GLsizei height, 847 GLint border, 848 GLenum format, 849 GLenum type, 850 GLsizei imageSize, 851 const void *pixels) 852 { 853 if (!ValidTexture2DDestinationTarget(context, target)) 854 { 855 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 856 return false; 857 } 858 859 return ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat, 860 isCompressed, isSubImage, xoffset, yoffset, width, 861 height, border, format, type, imageSize, pixels); 862 } 863 864 } // anonymous namespace 865 866 bool ValidateES2TexImageParametersBase(const Context *context, 867 angle::EntryPoint entryPoint, 868 TextureTarget target, 869 GLint level, 870 GLenum internalformat, 871 bool isCompressed, 872 bool isSubImage, 873 GLint xoffset, 874 GLint yoffset, 875 GLsizei width, 876 GLsizei height, 877 GLint border, 878 GLenum format, 879 GLenum type, 880 GLsizei imageSize, 881 const void *pixels) 882 { 883 884 TextureType texType = TextureTargetToType(target); 885 if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1, 886 isSubImage)) 887 { 888 // Error already handled. 889 return false; 890 } 891 892 if (!ValidMipLevel(context, texType, level)) 893 { 894 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 895 return false; 896 } 897 898 if ((xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width) || 899 (yoffset < 0 || std::numeric_limits<GLsizei>::max() - yoffset < height)) 900 { 901 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 902 return false; 903 } 904 905 const Caps &caps = context->getCaps(); 906 907 switch (texType) 908 { 909 case TextureType::_2D: 910 case TextureType::External: 911 case TextureType::VideoImage: 912 if (width > (caps.max2DTextureSize >> level) || 913 height > (caps.max2DTextureSize >> level)) 914 { 915 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 916 return false; 917 } 918 break; 919 920 case TextureType::Rectangle: 921 ASSERT(level == 0); 922 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize) 923 { 924 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 925 return false; 926 } 927 if (isCompressed) 928 { 929 context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed); 930 return false; 931 } 932 break; 933 934 case TextureType::CubeMap: 935 if (!isSubImage && width != height) 936 { 937 context->validationError(entryPoint, GL_INVALID_VALUE, 938 kCubemapFacesEqualDimensions); 939 return false; 940 } 941 942 if (width > (caps.maxCubeMapTextureSize >> level) || 943 height > (caps.maxCubeMapTextureSize >> level)) 944 { 945 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 946 return false; 947 } 948 break; 949 950 default: 951 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 952 return false; 953 } 954 955 Texture *texture = context->getTextureByType(texType); 956 if (!texture) 957 { 958 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound); 959 return false; 960 } 961 962 // Verify zero border 963 if (border != 0) 964 { 965 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder); 966 return false; 967 } 968 969 bool nonEqualFormatsAllowed = false; 970 971 if (isCompressed) 972 { 973 GLenum actualInternalFormat = 974 isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat 975 : internalformat; 976 977 const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(actualInternalFormat); 978 979 if (!internalFormatInfo.compressed && !internalFormatInfo.paletted) 980 { 981 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kInvalidInternalFormat, 982 internalformat); 983 return false; 984 } 985 986 if (!internalFormatInfo.textureSupport(context->getClientVersion(), 987 context->getExtensions())) 988 { 989 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kInvalidInternalFormat, 990 internalformat); 991 return false; 992 } 993 994 if (isSubImage) 995 { 996 // From OpenGL ES Version 1.1.12, section 3.7.4 Compressed Paletted 997 // Textures: 998 // 999 // Subimages may not be specified for compressed paletted textures. 1000 // Calling CompressedTexSubImage2D with any of the PALETTE* 1001 // arguments in table 3.11 will generate an INVALID OPERATION error. 1002 if (internalFormatInfo.paletted) 1003 { 1004 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 1005 internalformat); 1006 return false; 1007 } 1008 1009 // From the OES_compressed_ETC1_RGB8_texture spec: 1010 // 1011 // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or 1012 // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format 1013 // ETC1_RGB8_OES. 1014 // 1015 // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported. 1016 if (IsETC1Format(actualInternalFormat) && 1017 !context->getExtensions().compressedETC1RGB8SubTextureEXT) 1018 { 1019 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 1020 internalformat); 1021 return false; 1022 } 1023 1024 if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, 0, 1025 width, height, 1, texture->getWidth(target, level), 1026 texture->getHeight(target, level), 1027 texture->getDepth(target, level))) 1028 { 1029 context->validationError(entryPoint, GL_INVALID_OPERATION, 1030 kInvalidCompressedImageSize); 1031 return false; 1032 } 1033 1034 if (format != actualInternalFormat) 1035 { 1036 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 1037 return false; 1038 } 1039 } 1040 else 1041 { 1042 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height, 1)) 1043 { 1044 context->validationError(entryPoint, GL_INVALID_OPERATION, 1045 kInvalidCompressedImageSize); 1046 return false; 1047 } 1048 } 1049 } 1050 else 1051 { 1052 // validate <type> by itself (used as secondary key below) 1053 switch (type) 1054 { 1055 case GL_UNSIGNED_BYTE: 1056 case GL_UNSIGNED_SHORT_5_6_5: 1057 case GL_UNSIGNED_SHORT_4_4_4_4: 1058 case GL_UNSIGNED_SHORT_5_5_5_1: 1059 case GL_UNSIGNED_SHORT: 1060 case GL_UNSIGNED_INT: 1061 case GL_UNSIGNED_INT_24_8_OES: 1062 case GL_HALF_FLOAT_OES: 1063 case GL_FLOAT: 1064 break; 1065 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: 1066 if (!context->getExtensions().textureType2101010REVEXT) 1067 { 1068 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type); 1069 return false; 1070 } 1071 break; 1072 default: 1073 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType); 1074 return false; 1075 } 1076 1077 // validate <format> + <type> combinations 1078 // - invalid <format> -> sets INVALID_ENUM 1079 // - invalid <format>+<type> combination -> sets INVALID_OPERATION 1080 switch (format) 1081 { 1082 case GL_ALPHA: 1083 case GL_LUMINANCE: 1084 case GL_LUMINANCE_ALPHA: 1085 switch (type) 1086 { 1087 case GL_UNSIGNED_BYTE: 1088 case GL_FLOAT: 1089 case GL_HALF_FLOAT_OES: 1090 break; 1091 default: 1092 context->validationError(entryPoint, GL_INVALID_OPERATION, 1093 kMismatchedTypeAndFormat); 1094 return false; 1095 } 1096 break; 1097 case GL_RED: 1098 case GL_RG: 1099 if (!context->getExtensions().textureRgEXT) 1100 { 1101 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1102 format); 1103 return false; 1104 } 1105 switch (type) 1106 { 1107 case GL_UNSIGNED_BYTE: 1108 break; 1109 case GL_FLOAT: 1110 if (!context->getExtensions().textureFloatOES) 1111 { 1112 context->validationErrorF(entryPoint, GL_INVALID_ENUM, 1113 kEnumNotSupported, type); 1114 return false; 1115 } 1116 break; 1117 case GL_HALF_FLOAT_OES: 1118 if (!context->getExtensions().textureFloatOES && 1119 !context->getExtensions().textureHalfFloatOES) 1120 { 1121 context->validationErrorF(entryPoint, GL_INVALID_ENUM, 1122 kEnumNotSupported, type); 1123 return false; 1124 } 1125 break; 1126 case GL_SHORT: 1127 case GL_UNSIGNED_SHORT: 1128 if (!context->getExtensions().textureNorm16EXT) 1129 { 1130 context->validationErrorF(entryPoint, GL_INVALID_ENUM, 1131 kEnumNotSupported, type); 1132 return false; 1133 } 1134 break; 1135 default: 1136 context->validationError(entryPoint, GL_INVALID_OPERATION, 1137 kMismatchedTypeAndFormat); 1138 return false; 1139 } 1140 break; 1141 case GL_RGB: 1142 switch (type) 1143 { 1144 case GL_UNSIGNED_BYTE: 1145 case GL_UNSIGNED_SHORT_5_6_5: 1146 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: 1147 case GL_FLOAT: 1148 case GL_HALF_FLOAT_OES: 1149 break; 1150 case GL_SHORT: 1151 case GL_UNSIGNED_SHORT: 1152 if (!context->getExtensions().textureNorm16EXT) 1153 { 1154 context->validationError(entryPoint, GL_INVALID_OPERATION, 1155 kMismatchedTypeAndFormat); 1156 return false; 1157 } 1158 break; 1159 default: 1160 context->validationError(entryPoint, GL_INVALID_OPERATION, 1161 kMismatchedTypeAndFormat); 1162 return false; 1163 } 1164 break; 1165 case GL_RGBA: 1166 switch (type) 1167 { 1168 case GL_UNSIGNED_BYTE: 1169 case GL_UNSIGNED_SHORT_4_4_4_4: 1170 case GL_UNSIGNED_SHORT_5_5_5_1: 1171 case GL_FLOAT: 1172 case GL_HALF_FLOAT_OES: 1173 case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: 1174 break; 1175 case GL_SHORT: 1176 case GL_UNSIGNED_SHORT: 1177 if (!context->getExtensions().textureNorm16EXT) 1178 { 1179 context->validationError(entryPoint, GL_INVALID_OPERATION, 1180 kMismatchedTypeAndFormat); 1181 return false; 1182 } 1183 break; 1184 default: 1185 context->validationError(entryPoint, GL_INVALID_OPERATION, 1186 kMismatchedTypeAndFormat); 1187 return false; 1188 } 1189 break; 1190 case GL_BGRA_EXT: 1191 if (!context->getExtensions().textureFormatBGRA8888EXT) 1192 { 1193 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1194 format); 1195 return false; 1196 } 1197 switch (type) 1198 { 1199 case GL_UNSIGNED_BYTE: 1200 break; 1201 default: 1202 context->validationError(entryPoint, GL_INVALID_OPERATION, 1203 kMismatchedTypeAndFormat); 1204 return false; 1205 } 1206 break; 1207 case GL_SRGB_EXT: 1208 case GL_SRGB_ALPHA_EXT: 1209 if (!context->getExtensions().sRGBEXT) 1210 { 1211 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1212 format); 1213 return false; 1214 } 1215 switch (type) 1216 { 1217 case GL_UNSIGNED_BYTE: 1218 break; 1219 default: 1220 context->validationError(entryPoint, GL_INVALID_OPERATION, 1221 kMismatchedTypeAndFormat); 1222 return false; 1223 } 1224 break; 1225 case GL_DEPTH_COMPONENT: 1226 switch (type) 1227 { 1228 case GL_UNSIGNED_SHORT: 1229 case GL_UNSIGNED_INT: 1230 break; 1231 case GL_FLOAT: 1232 if (!context->getExtensions().depthBufferFloat2NV) 1233 { 1234 context->validationError(entryPoint, GL_INVALID_OPERATION, 1235 kMismatchedTypeAndFormat); 1236 return false; 1237 } 1238 break; 1239 default: 1240 context->validationError(entryPoint, GL_INVALID_OPERATION, 1241 kMismatchedTypeAndFormat); 1242 return false; 1243 } 1244 break; 1245 case GL_DEPTH_STENCIL_OES: 1246 switch (type) 1247 { 1248 case GL_UNSIGNED_INT_24_8_OES: 1249 break; 1250 default: 1251 context->validationError(entryPoint, GL_INVALID_OPERATION, 1252 kMismatchedTypeAndFormat); 1253 return false; 1254 } 1255 break; 1256 case GL_STENCIL_INDEX: 1257 switch (type) 1258 { 1259 case GL_UNSIGNED_BYTE: 1260 break; 1261 default: 1262 context->validationError(entryPoint, GL_INVALID_OPERATION, 1263 kMismatchedTypeAndFormat); 1264 return false; 1265 } 1266 break; 1267 default: 1268 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, format); 1269 return false; 1270 } 1271 1272 switch (format) 1273 { 1274 case GL_DEPTH_COMPONENT: 1275 case GL_DEPTH_STENCIL_OES: 1276 if (!context->getExtensions().depthTextureANGLE && 1277 !((context->getExtensions().packedDepthStencilOES || 1278 context->getExtensions().depthTextureCubeMapOES) && 1279 context->getExtensions().depthTextureOES)) 1280 { 1281 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1282 format); 1283 return false; 1284 } 1285 1286 switch (target) 1287 { 1288 case TextureTarget::_2D: 1289 break; 1290 case TextureTarget::CubeMapNegativeX: 1291 case TextureTarget::CubeMapNegativeY: 1292 case TextureTarget::CubeMapNegativeZ: 1293 case TextureTarget::CubeMapPositiveX: 1294 case TextureTarget::CubeMapPositiveY: 1295 case TextureTarget::CubeMapPositiveZ: 1296 if (!context->getExtensions().depthTextureCubeMapOES) 1297 { 1298 context->validationError(entryPoint, GL_INVALID_OPERATION, 1299 kMismatchedTargetAndFormat); 1300 return false; 1301 } 1302 break; 1303 default: 1304 context->validationError(entryPoint, GL_INVALID_OPERATION, 1305 kMismatchedTargetAndFormat); 1306 return false; 1307 } 1308 1309 // OES_depth_texture supports loading depth data and multiple levels, 1310 // but ANGLE_depth_texture does not 1311 if (!context->getExtensions().depthTextureOES) 1312 { 1313 if (pixels != nullptr) 1314 { 1315 context->validationError(entryPoint, GL_INVALID_OPERATION, 1316 kPixelDataNotNull); 1317 return false; 1318 } 1319 if (level != 0) 1320 { 1321 context->validationError(entryPoint, GL_INVALID_OPERATION, kLevelNotZero); 1322 return false; 1323 } 1324 } 1325 break; 1326 case GL_STENCIL_INDEX: 1327 if (!context->getExtensions().textureStencil8OES) 1328 { 1329 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); 1330 return false; 1331 } 1332 1333 switch (target) 1334 { 1335 case TextureTarget::_2D: 1336 case TextureTarget::_2DArray: 1337 case TextureTarget::CubeMapNegativeX: 1338 case TextureTarget::CubeMapNegativeY: 1339 case TextureTarget::CubeMapNegativeZ: 1340 case TextureTarget::CubeMapPositiveX: 1341 case TextureTarget::CubeMapPositiveY: 1342 case TextureTarget::CubeMapPositiveZ: 1343 break; 1344 default: 1345 context->validationError(entryPoint, GL_INVALID_OPERATION, 1346 kMismatchedTargetAndFormat); 1347 return false; 1348 } 1349 1350 if (internalformat != GL_STENCIL_INDEX8) 1351 { 1352 context->validationError(entryPoint, GL_INVALID_OPERATION, 1353 kMismatchedTargetAndFormat); 1354 return false; 1355 } 1356 break; 1357 default: 1358 break; 1359 } 1360 1361 if (!isSubImage) 1362 { 1363 switch (internalformat) 1364 { 1365 // Core ES 2.0 formats 1366 case GL_ALPHA: 1367 case GL_LUMINANCE: 1368 case GL_LUMINANCE_ALPHA: 1369 case GL_RGB: 1370 case GL_RGBA: 1371 break; 1372 1373 case GL_RGBA32F: 1374 if (!context->getExtensions().colorBufferFloatRgbaCHROMIUM) 1375 { 1376 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1377 return false; 1378 } 1379 1380 nonEqualFormatsAllowed = true; 1381 1382 if (type != GL_FLOAT) 1383 { 1384 context->validationError(entryPoint, GL_INVALID_OPERATION, 1385 kMismatchedTypeAndFormat); 1386 return false; 1387 } 1388 if (format != GL_RGBA) 1389 { 1390 context->validationError(entryPoint, GL_INVALID_OPERATION, 1391 kMismatchedTypeAndFormat); 1392 return false; 1393 } 1394 break; 1395 1396 case GL_RGB32F: 1397 if (!context->getExtensions().colorBufferFloatRgbCHROMIUM) 1398 { 1399 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1400 return false; 1401 } 1402 1403 nonEqualFormatsAllowed = true; 1404 1405 if (type != GL_FLOAT) 1406 { 1407 context->validationError(entryPoint, GL_INVALID_OPERATION, 1408 kMismatchedTypeAndFormat); 1409 return false; 1410 } 1411 if (format != GL_RGB) 1412 { 1413 context->validationError(entryPoint, GL_INVALID_OPERATION, 1414 kMismatchedTypeAndFormat); 1415 return false; 1416 } 1417 break; 1418 1419 case GL_BGRA_EXT: 1420 if (!context->getExtensions().textureFormatBGRA8888EXT) 1421 { 1422 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1423 return false; 1424 } 1425 break; 1426 1427 case GL_DEPTH_COMPONENT: 1428 if (!(context->getExtensions().depthTextureAny())) 1429 { 1430 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1431 return false; 1432 } 1433 break; 1434 1435 case GL_DEPTH_STENCIL: 1436 if (!(context->getExtensions().depthTextureANGLE || 1437 context->getExtensions().packedDepthStencilOES || 1438 context->getExtensions().depthTextureCubeMapOES)) 1439 { 1440 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1441 return false; 1442 } 1443 break; 1444 1445 case GL_STENCIL_INDEX8: 1446 if (!context->getExtensions().textureStencil8OES) 1447 { 1448 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1449 return false; 1450 } 1451 break; 1452 1453 case GL_RED: 1454 case GL_RG: 1455 if (!context->getExtensions().textureRgEXT) 1456 { 1457 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1458 return false; 1459 } 1460 break; 1461 1462 case GL_SRGB_EXT: 1463 case GL_SRGB_ALPHA_EXT: 1464 if (!context->getExtensions().sRGBEXT) 1465 { 1466 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1467 internalformat); 1468 return false; 1469 } 1470 break; 1471 1472 case GL_RGB10_A2_EXT: 1473 if (!context->getExtensions().textureType2101010REVEXT) 1474 { 1475 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1476 internalformat); 1477 return false; 1478 } 1479 1480 if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA) 1481 { 1482 context->validationError(entryPoint, GL_INVALID_OPERATION, 1483 kMismatchedTypeAndFormat); 1484 return false; 1485 } 1486 1487 nonEqualFormatsAllowed = true; 1488 1489 break; 1490 1491 case GL_RGB5_A1: 1492 if (context->getExtensions().textureType2101010REVEXT && 1493 type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA) 1494 { 1495 nonEqualFormatsAllowed = true; 1496 } 1497 1498 break; 1499 1500 case GL_RGBX8_ANGLE: 1501 if (context->getExtensions().rgbxInternalFormatANGLE && 1502 type == GL_UNSIGNED_BYTE && format == GL_RGB) 1503 { 1504 nonEqualFormatsAllowed = true; 1505 } 1506 1507 break; 1508 1509 case GL_R16_EXT: 1510 case GL_RG16_EXT: 1511 case GL_RGB16_EXT: 1512 case GL_RGBA16_EXT: 1513 case GL_R16_SNORM_EXT: 1514 case GL_RG16_SNORM_EXT: 1515 case GL_RGB16_SNORM_EXT: 1516 case GL_RGBA16_SNORM_EXT: 1517 if (!context->getExtensions().textureNorm16EXT) 1518 { 1519 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1520 internalformat); 1521 return false; 1522 } 1523 break; 1524 default: 1525 // Compressed formats are not valid internal formats for glTexImage*D 1526 context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat, 1527 internalformat); 1528 return false; 1529 } 1530 } 1531 1532 if (type == GL_FLOAT) 1533 { 1534 if (!context->getExtensions().textureFloatOES) 1535 { 1536 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type); 1537 return false; 1538 } 1539 } 1540 else if (type == GL_HALF_FLOAT_OES) 1541 { 1542 if (!context->getExtensions().textureHalfFloatOES) 1543 { 1544 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type); 1545 return false; 1546 } 1547 } 1548 } 1549 1550 if (isSubImage) 1551 { 1552 const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info; 1553 if (textureInternalFormat.internalFormat == GL_NONE) 1554 { 1555 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureLevel); 1556 return false; 1557 } 1558 1559 if (format != textureInternalFormat.format) 1560 { 1561 context->validationError(entryPoint, GL_INVALID_OPERATION, err::kTextureFormatMismatch); 1562 return false; 1563 } 1564 1565 if (context->isWebGL()) 1566 { 1567 if (GetInternalFormatInfo(format, type).sizedInternalFormat != 1568 textureInternalFormat.sizedInternalFormat) 1569 { 1570 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureTypeMismatch); 1571 return false; 1572 } 1573 } 1574 1575 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) || 1576 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level)) 1577 { 1578 context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow); 1579 return false; 1580 } 1581 1582 if (width > 0 && height > 0 && pixels == nullptr && 1583 context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr) 1584 { 1585 context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull); 1586 return false; 1587 } 1588 } 1589 else 1590 { 1591 if (texture->getImmutableFormat()) 1592 { 1593 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable); 1594 return false; 1595 } 1596 } 1597 1598 // From GL_CHROMIUM_color_buffer_float_rgb[a]: 1599 // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for 1600 // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the 1601 // internalformat parameter and format parameter of TexImage2D must match is lifted for this 1602 // case. 1603 if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed) 1604 { 1605 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination); 1606 return false; 1607 } 1608 1609 GLenum sizeCheckFormat = isSubImage ? format : internalformat; 1610 return ValidImageDataSize(context, entryPoint, texType, width, height, 1, sizeCheckFormat, type, 1611 pixels, imageSize); 1612 } 1613 1614 bool ValidateES2TexStorageParametersBase(const Context *context, 1615 angle::EntryPoint entryPoint, 1616 TextureType target, 1617 GLsizei levels, 1618 GLenum internalformat, 1619 GLsizei width, 1620 GLsizei height) 1621 { 1622 if (target != TextureType::_2D && target != TextureType::CubeMap && 1623 target != TextureType::Rectangle) 1624 { 1625 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 1626 return false; 1627 } 1628 1629 if (width < 1 || height < 1 || levels < 1) 1630 { 1631 context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall); 1632 return false; 1633 } 1634 1635 if (target == TextureType::CubeMap && width != height) 1636 { 1637 context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapFacesEqualDimensions); 1638 return false; 1639 } 1640 1641 if (levels != 1 && levels != log2(std::max(width, height)) + 1) 1642 { 1643 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels); 1644 return false; 1645 } 1646 1647 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat); 1648 if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE) 1649 { 1650 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1651 return false; 1652 } 1653 1654 const Caps &caps = context->getCaps(); 1655 1656 switch (target) 1657 { 1658 case TextureType::_2D: 1659 if (width > caps.max2DTextureSize || height > caps.max2DTextureSize) 1660 { 1661 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 1662 return false; 1663 } 1664 break; 1665 case TextureType::Rectangle: 1666 if (levels != 1) 1667 { 1668 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 1669 return false; 1670 } 1671 1672 if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize) 1673 { 1674 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 1675 return false; 1676 } 1677 if (formatInfo.compressed) 1678 { 1679 context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed); 1680 return false; 1681 } 1682 break; 1683 case TextureType::CubeMap: 1684 if (width > caps.maxCubeMapTextureSize || height > caps.maxCubeMapTextureSize) 1685 { 1686 context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize); 1687 return false; 1688 } 1689 break; 1690 case TextureType::InvalidEnum: 1691 context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid); 1692 return false; 1693 default: 1694 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, 1695 ToGLenum(target)); 1696 return false; 1697 } 1698 1699 if (levels != 1 && !context->getExtensions().textureNpotOES) 1700 { 1701 if (!isPow2(width) || !isPow2(height)) 1702 { 1703 context->validationError(entryPoint, GL_INVALID_OPERATION, kDimensionsMustBePow2); 1704 return false; 1705 } 1706 } 1707 1708 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) 1709 { 1710 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); 1711 return false; 1712 } 1713 1714 // Even with OES_texture_npot, some compressed formats may impose extra restrictions. 1715 if (formatInfo.compressed) 1716 { 1717 if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, 1)) 1718 { 1719 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCompressedImageSize); 1720 return false; 1721 } 1722 } 1723 1724 switch (internalformat) 1725 { 1726 case GL_DEPTH_COMPONENT16: 1727 case GL_DEPTH_COMPONENT32_OES: 1728 switch (target) 1729 { 1730 case TextureType::_2D: 1731 break; 1732 case TextureType::CubeMap: 1733 if (!context->getExtensions().depthTextureCubeMapOES) 1734 { 1735 context->validationError(entryPoint, GL_INVALID_OPERATION, 1736 kInvalidTextureTarget); 1737 return false; 1738 } 1739 break; 1740 default: 1741 context->validationError(entryPoint, GL_INVALID_OPERATION, 1742 kInvalidTextureTarget); 1743 return false; 1744 } 1745 1746 // ANGLE_depth_texture only supports 1-level textures 1747 if (!context->getExtensions().depthTextureOES) 1748 { 1749 if (levels != 1) 1750 { 1751 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels); 1752 return false; 1753 } 1754 } 1755 break; 1756 case GL_DEPTH24_STENCIL8_OES: 1757 switch (target) 1758 { 1759 case TextureType::_2D: 1760 break; 1761 case TextureType::CubeMap: 1762 if (!context->getExtensions().depthTextureCubeMapOES) 1763 { 1764 context->validationError(entryPoint, GL_INVALID_OPERATION, 1765 kInvalidTextureTarget); 1766 return false; 1767 } 1768 break; 1769 default: 1770 context->validationError(entryPoint, GL_INVALID_OPERATION, 1771 kInvalidTextureTarget); 1772 return false; 1773 } 1774 1775 if (!context->getExtensions().packedDepthStencilOES && 1776 !context->getExtensions().depthTextureCubeMapOES) 1777 { 1778 // ANGLE_depth_texture only supports 1-level textures 1779 if (levels != 1) 1780 { 1781 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels); 1782 return false; 1783 } 1784 } 1785 break; 1786 1787 default: 1788 break; 1789 } 1790 1791 Texture *texture = context->getTextureByType(target); 1792 if (!texture || texture->id().value == 0) 1793 { 1794 context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture); 1795 return false; 1796 } 1797 1798 if (texture->getImmutableFormat()) 1799 { 1800 context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable); 1801 return false; 1802 } 1803 1804 return true; 1805 } 1806 1807 bool ValidateDiscardFramebufferEXT(const Context *context, 1808 angle::EntryPoint entryPoint, 1809 GLenum target, 1810 GLsizei numAttachments, 1811 const GLenum *attachments) 1812 { 1813 if (!context->getExtensions().discardFramebufferEXT) 1814 { 1815 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1816 return false; 1817 } 1818 1819 bool defaultFramebuffer = false; 1820 1821 switch (target) 1822 { 1823 case GL_FRAMEBUFFER: 1824 defaultFramebuffer = 1825 (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault()); 1826 break; 1827 default: 1828 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 1829 return false; 1830 } 1831 1832 return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments, 1833 defaultFramebuffer); 1834 } 1835 1836 bool ValidateBindVertexArrayOES(const Context *context, 1837 angle::EntryPoint entryPoint, 1838 VertexArrayID array) 1839 { 1840 if (!context->getExtensions().vertexArrayObjectOES) 1841 { 1842 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1843 return false; 1844 } 1845 1846 return ValidateBindVertexArrayBase(context, entryPoint, array); 1847 } 1848 1849 bool ValidateDeleteVertexArraysOES(const Context *context, 1850 angle::EntryPoint entryPoint, 1851 GLsizei n, 1852 const VertexArrayID *arrays) 1853 { 1854 if (!context->getExtensions().vertexArrayObjectOES) 1855 { 1856 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1857 return false; 1858 } 1859 1860 return ValidateGenOrDelete(context, entryPoint, n); 1861 } 1862 1863 bool ValidateGenVertexArraysOES(const Context *context, 1864 angle::EntryPoint entryPoint, 1865 GLsizei n, 1866 const VertexArrayID *arrays) 1867 { 1868 if (!context->getExtensions().vertexArrayObjectOES) 1869 { 1870 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1871 return false; 1872 } 1873 1874 return ValidateGenOrDelete(context, entryPoint, n); 1875 } 1876 1877 bool ValidateIsVertexArrayOES(const Context *context, 1878 angle::EntryPoint entryPoint, 1879 VertexArrayID array) 1880 { 1881 if (!context->getExtensions().vertexArrayObjectOES) 1882 { 1883 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1884 return false; 1885 } 1886 1887 return true; 1888 } 1889 1890 bool ValidateProgramBinaryOES(const Context *context, 1891 angle::EntryPoint entryPoint, 1892 ShaderProgramID program, 1893 GLenum binaryFormat, 1894 const void *binary, 1895 GLint length) 1896 { 1897 if (!context->getExtensions().getProgramBinaryOES) 1898 { 1899 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1900 return false; 1901 } 1902 1903 return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length); 1904 } 1905 1906 bool ValidateGetProgramBinaryOES(const Context *context, 1907 angle::EntryPoint entryPoint, 1908 ShaderProgramID program, 1909 GLsizei bufSize, 1910 const GLsizei *length, 1911 const GLenum *binaryFormat, 1912 const void *binary) 1913 { 1914 if (!context->getExtensions().getProgramBinaryOES) 1915 { 1916 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1917 return false; 1918 } 1919 1920 return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat, 1921 binary); 1922 } 1923 1924 static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication) 1925 { 1926 switch (source) 1927 { 1928 case GL_DEBUG_SOURCE_API: 1929 case GL_DEBUG_SOURCE_SHADER_COMPILER: 1930 case GL_DEBUG_SOURCE_WINDOW_SYSTEM: 1931 case GL_DEBUG_SOURCE_OTHER: 1932 // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted 1933 return !mustBeThirdPartyOrApplication; 1934 1935 case GL_DEBUG_SOURCE_THIRD_PARTY: 1936 case GL_DEBUG_SOURCE_APPLICATION: 1937 return true; 1938 1939 default: 1940 return false; 1941 } 1942 } 1943 1944 static bool ValidDebugType(GLenum type) 1945 { 1946 switch (type) 1947 { 1948 case GL_DEBUG_TYPE_ERROR: 1949 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: 1950 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: 1951 case GL_DEBUG_TYPE_PERFORMANCE: 1952 case GL_DEBUG_TYPE_PORTABILITY: 1953 case GL_DEBUG_TYPE_OTHER: 1954 case GL_DEBUG_TYPE_MARKER: 1955 case GL_DEBUG_TYPE_PUSH_GROUP: 1956 case GL_DEBUG_TYPE_POP_GROUP: 1957 return true; 1958 1959 default: 1960 return false; 1961 } 1962 } 1963 1964 static bool ValidDebugSeverity(GLenum severity) 1965 { 1966 switch (severity) 1967 { 1968 case GL_DEBUG_SEVERITY_HIGH: 1969 case GL_DEBUG_SEVERITY_MEDIUM: 1970 case GL_DEBUG_SEVERITY_LOW: 1971 case GL_DEBUG_SEVERITY_NOTIFICATION: 1972 return true; 1973 1974 default: 1975 return false; 1976 } 1977 } 1978 1979 bool ValidateDebugMessageControlKHR(const Context *context, 1980 angle::EntryPoint entryPoint, 1981 GLenum source, 1982 GLenum type, 1983 GLenum severity, 1984 GLsizei count, 1985 const GLuint *ids, 1986 GLboolean enabled) 1987 { 1988 if (!context->getExtensions().debugKHR) 1989 { 1990 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 1991 return false; 1992 } 1993 1994 if (!ValidDebugSource(source, false) && source != GL_DONT_CARE) 1995 { 1996 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource); 1997 return false; 1998 } 1999 2000 if (!ValidDebugType(type) && type != GL_DONT_CARE) 2001 { 2002 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugType); 2003 return false; 2004 } 2005 2006 if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE) 2007 { 2008 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSeverity); 2009 return false; 2010 } 2011 2012 if (count > 0) 2013 { 2014 if (source == GL_DONT_CARE || type == GL_DONT_CARE) 2015 { 2016 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDebugSourceType); 2017 return false; 2018 } 2019 2020 if (severity != GL_DONT_CARE) 2021 { 2022 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDebugSeverity); 2023 return false; 2024 } 2025 } 2026 2027 return true; 2028 } 2029 2030 bool ValidateDebugMessageInsertKHR(const Context *context, 2031 angle::EntryPoint entryPoint, 2032 GLenum source, 2033 GLenum type, 2034 GLuint id, 2035 GLenum severity, 2036 GLsizei length, 2037 const GLchar *buf) 2038 { 2039 if (!context->getExtensions().debugKHR) 2040 { 2041 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2042 return false; 2043 } 2044 2045 if (!context->getState().getDebug().isOutputEnabled()) 2046 { 2047 // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do 2048 // not generate an error. 2049 return false; 2050 } 2051 2052 if (!ValidDebugSeverity(severity)) 2053 { 2054 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource); 2055 return false; 2056 } 2057 2058 if (!ValidDebugType(type)) 2059 { 2060 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugType); 2061 return false; 2062 } 2063 2064 if (!ValidDebugSource(source, true)) 2065 { 2066 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource); 2067 return false; 2068 } 2069 2070 size_t messageLength = (length < 0) ? strlen(buf) : length; 2071 if (messageLength > context->getCaps().maxDebugMessageLength) 2072 { 2073 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDebugMessageLength); 2074 return false; 2075 } 2076 2077 return true; 2078 } 2079 2080 bool ValidateDebugMessageCallbackKHR(const Context *context, 2081 angle::EntryPoint entryPoint, 2082 GLDEBUGPROCKHR callback, 2083 const void *userParam) 2084 { 2085 if (!context->getExtensions().debugKHR) 2086 { 2087 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2088 return false; 2089 } 2090 2091 return true; 2092 } 2093 2094 bool ValidateGetDebugMessageLogKHR(const Context *context, 2095 angle::EntryPoint entryPoint, 2096 GLuint count, 2097 GLsizei bufSize, 2098 const GLenum *sources, 2099 const GLenum *types, 2100 const GLuint *ids, 2101 const GLenum *severities, 2102 const GLsizei *lengths, 2103 const GLchar *messageLog) 2104 { 2105 if (!context->getExtensions().debugKHR) 2106 { 2107 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2108 return false; 2109 } 2110 2111 if (bufSize < 0 && messageLog != nullptr) 2112 { 2113 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 2114 return false; 2115 } 2116 2117 return true; 2118 } 2119 2120 bool ValidatePushDebugGroupKHR(const Context *context, 2121 angle::EntryPoint entryPoint, 2122 GLenum source, 2123 GLuint id, 2124 GLsizei length, 2125 const GLchar *message) 2126 { 2127 if (!context->getExtensions().debugKHR) 2128 { 2129 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2130 return false; 2131 } 2132 2133 if (!ValidDebugSource(source, true)) 2134 { 2135 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource); 2136 return false; 2137 } 2138 2139 size_t messageLength = (length < 0) ? strlen(message) : length; 2140 if (messageLength > context->getCaps().maxDebugMessageLength) 2141 { 2142 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDebugMessageLength); 2143 return false; 2144 } 2145 2146 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth(); 2147 if (currentStackSize >= context->getCaps().maxDebugGroupStackDepth) 2148 { 2149 context->validationError(entryPoint, GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth); 2150 return false; 2151 } 2152 2153 return true; 2154 } 2155 2156 bool ValidatePopDebugGroupKHR(const Context *context, angle::EntryPoint entryPoint) 2157 { 2158 if (!context->getExtensions().debugKHR) 2159 { 2160 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2161 return false; 2162 } 2163 2164 size_t currentStackSize = context->getState().getDebug().getGroupStackDepth(); 2165 if (currentStackSize <= 1) 2166 { 2167 context->validationError(entryPoint, GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup); 2168 return false; 2169 } 2170 2171 return true; 2172 } 2173 2174 static bool ValidateObjectIdentifierAndName(const Context *context, 2175 angle::EntryPoint entryPoint, 2176 GLenum identifier, 2177 GLuint name) 2178 { 2179 switch (identifier) 2180 { 2181 case GL_BUFFER: 2182 if (context->getBuffer({name}) == nullptr) 2183 { 2184 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBufferName); 2185 return false; 2186 } 2187 return true; 2188 2189 case GL_SHADER: 2190 if (context->getShader({name}) == nullptr) 2191 { 2192 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidShaderName); 2193 return false; 2194 } 2195 return true; 2196 2197 case GL_PROGRAM: 2198 if (context->getProgramNoResolveLink({name}) == nullptr) 2199 { 2200 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName); 2201 return false; 2202 } 2203 return true; 2204 2205 case GL_VERTEX_ARRAY: 2206 if (context->getVertexArray({name}) == nullptr) 2207 { 2208 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidVertexArrayName); 2209 return false; 2210 } 2211 return true; 2212 2213 case GL_QUERY: 2214 if (context->getQuery({name}) == nullptr) 2215 { 2216 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidQueryName); 2217 return false; 2218 } 2219 return true; 2220 2221 case GL_TRANSFORM_FEEDBACK: 2222 if (context->getTransformFeedback({name}) == nullptr) 2223 { 2224 context->validationError(entryPoint, GL_INVALID_VALUE, 2225 kInvalidTransformFeedbackName); 2226 return false; 2227 } 2228 return true; 2229 2230 case GL_SAMPLER: 2231 if (context->getSampler({name}) == nullptr) 2232 { 2233 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSamplerName); 2234 return false; 2235 } 2236 return true; 2237 2238 case GL_TEXTURE: 2239 if (context->getTexture({name}) == nullptr) 2240 { 2241 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName); 2242 return false; 2243 } 2244 return true; 2245 2246 case GL_RENDERBUFFER: 2247 if (!context->isRenderbuffer({name})) 2248 { 2249 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferName); 2250 return false; 2251 } 2252 return true; 2253 2254 case GL_FRAMEBUFFER: 2255 if (context->getFramebuffer({name}) == nullptr) 2256 { 2257 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferName); 2258 return false; 2259 } 2260 return true; 2261 2262 case GL_PROGRAM_PIPELINE: 2263 if (context->getProgramPipeline({name}) == nullptr) 2264 { 2265 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramPipelineName); 2266 return false; 2267 } 2268 return true; 2269 2270 default: 2271 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidIndentifier); 2272 return false; 2273 } 2274 } 2275 2276 static bool ValidateLabelLength(const Context *context, 2277 angle::EntryPoint entryPoint, 2278 GLsizei length, 2279 const GLchar *label) 2280 { 2281 size_t labelLength = 0; 2282 2283 if (length < 0) 2284 { 2285 if (label != nullptr) 2286 { 2287 labelLength = strlen(label); 2288 } 2289 } 2290 else 2291 { 2292 labelLength = static_cast<size_t>(length); 2293 } 2294 2295 if (labelLength > context->getCaps().maxLabelLength) 2296 { 2297 context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxLabelLength); 2298 return false; 2299 } 2300 2301 return true; 2302 } 2303 2304 bool ValidateObjectLabelKHR(const Context *context, 2305 angle::EntryPoint entryPoint, 2306 GLenum identifier, 2307 GLuint name, 2308 GLsizei length, 2309 const GLchar *label) 2310 { 2311 if (!context->getExtensions().debugKHR) 2312 { 2313 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2314 return false; 2315 } 2316 2317 if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name)) 2318 { 2319 return false; 2320 } 2321 2322 if (!ValidateLabelLength(context, entryPoint, length, label)) 2323 { 2324 return false; 2325 } 2326 2327 return true; 2328 } 2329 2330 bool ValidateGetObjectLabelKHR(const Context *context, 2331 angle::EntryPoint entryPoint, 2332 GLenum identifier, 2333 GLuint name, 2334 GLsizei bufSize, 2335 const GLsizei *length, 2336 const GLchar *label) 2337 { 2338 if (!context->getExtensions().debugKHR) 2339 { 2340 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2341 return false; 2342 } 2343 2344 if (bufSize < 0) 2345 { 2346 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 2347 return false; 2348 } 2349 2350 if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name)) 2351 { 2352 return false; 2353 } 2354 2355 return true; 2356 } 2357 2358 static bool ValidateObjectPtrName(const Context *context, 2359 angle::EntryPoint entryPoint, 2360 const void *ptr) 2361 { 2362 if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr) 2363 { 2364 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSyncPointer); 2365 return false; 2366 } 2367 2368 return true; 2369 } 2370 2371 bool ValidateObjectPtrLabelKHR(const Context *context, 2372 angle::EntryPoint entryPoint, 2373 const void *ptr, 2374 GLsizei length, 2375 const GLchar *label) 2376 { 2377 if (!context->getExtensions().debugKHR) 2378 { 2379 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2380 return false; 2381 } 2382 2383 if (!ValidateObjectPtrName(context, entryPoint, ptr)) 2384 { 2385 return false; 2386 } 2387 2388 if (!ValidateLabelLength(context, entryPoint, length, label)) 2389 { 2390 return false; 2391 } 2392 2393 return true; 2394 } 2395 2396 bool ValidateGetObjectPtrLabelKHR(const Context *context, 2397 angle::EntryPoint entryPoint, 2398 const void *ptr, 2399 GLsizei bufSize, 2400 const GLsizei *length, 2401 const GLchar *label) 2402 { 2403 if (!context->getExtensions().debugKHR) 2404 { 2405 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2406 return false; 2407 } 2408 2409 if (bufSize < 0) 2410 { 2411 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 2412 return false; 2413 } 2414 2415 if (!ValidateObjectPtrName(context, entryPoint, ptr)) 2416 { 2417 return false; 2418 } 2419 2420 return true; 2421 } 2422 2423 bool ValidateGetPointervKHR(const Context *context, 2424 angle::EntryPoint entryPoint, 2425 GLenum pname, 2426 void *const *params) 2427 { 2428 if (!context->getExtensions().debugKHR) 2429 { 2430 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2431 return false; 2432 } 2433 2434 // TODO: represent this in Context::getQueryParameterInfo. 2435 switch (pname) 2436 { 2437 case GL_DEBUG_CALLBACK_FUNCTION: 2438 case GL_DEBUG_CALLBACK_USER_PARAM: 2439 break; 2440 2441 default: 2442 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 2443 return false; 2444 } 2445 2446 return true; 2447 } 2448 2449 bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context, 2450 angle::EntryPoint entryPoint, 2451 GLenum pname, 2452 GLsizei bufSize, 2453 const GLsizei *length, 2454 void *const *params) 2455 { 2456 UNIMPLEMENTED(); 2457 return false; 2458 } 2459 2460 bool ValidateBlitFramebufferANGLE(const Context *context, 2461 angle::EntryPoint entryPoint, 2462 GLint srcX0, 2463 GLint srcY0, 2464 GLint srcX1, 2465 GLint srcY1, 2466 GLint dstX0, 2467 GLint dstY0, 2468 GLint dstX1, 2469 GLint dstY1, 2470 GLbitfield mask, 2471 GLenum filter) 2472 { 2473 if (!context->getExtensions().framebufferBlitANGLE) 2474 { 2475 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionNotAvailable); 2476 return false; 2477 } 2478 2479 if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) 2480 { 2481 // TODO(jmadill): Determine if this should be available on other implementations. 2482 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip); 2483 return false; 2484 } 2485 2486 if (filter == GL_LINEAR) 2487 { 2488 context->validationError(entryPoint, GL_INVALID_ENUM, kBlitExtensionLinear); 2489 return false; 2490 } 2491 2492 Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); 2493 Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); 2494 2495 if (mask & GL_COLOR_BUFFER_BIT) 2496 { 2497 const FramebufferAttachment *readColorAttachment = 2498 readFramebuffer->getReadColorAttachment(); 2499 const FramebufferAttachment *drawColorAttachment = 2500 drawFramebuffer->getFirstColorAttachment(); 2501 2502 if (readColorAttachment && drawColorAttachment) 2503 { 2504 if (!(readColorAttachment->type() == GL_TEXTURE && 2505 (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D || 2506 readColorAttachment->getTextureImageIndex().getType() == 2507 TextureType::Rectangle)) && 2508 readColorAttachment->type() != GL_RENDERBUFFER && 2509 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT) 2510 { 2511 context->validationError(entryPoint, GL_INVALID_OPERATION, 2512 kBlitExtensionFromInvalidAttachmentType); 2513 return false; 2514 } 2515 2516 for (size_t drawbufferIdx = 0; 2517 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx) 2518 { 2519 const FramebufferAttachment *attachment = 2520 drawFramebuffer->getDrawBuffer(drawbufferIdx); 2521 if (attachment) 2522 { 2523 if (!(attachment->type() == GL_TEXTURE && 2524 (attachment->getTextureImageIndex().getType() == TextureType::_2D || 2525 attachment->getTextureImageIndex().getType() == 2526 TextureType::Rectangle)) && 2527 attachment->type() != GL_RENDERBUFFER && 2528 attachment->type() != GL_FRAMEBUFFER_DEFAULT) 2529 { 2530 context->validationError(entryPoint, GL_INVALID_OPERATION, 2531 kBlitExtensionToInvalidAttachmentType); 2532 return false; 2533 } 2534 2535 // Return an error if the destination formats do not match 2536 if (!Format::EquivalentForBlit(attachment->getFormat(), 2537 readColorAttachment->getFormat())) 2538 { 2539 context->validationErrorF( 2540 entryPoint, GL_INVALID_OPERATION, kBlitExtensionFormatMismatch, 2541 readColorAttachment->getFormat().info->sizedInternalFormat, 2542 attachment->getFormat().info->sizedInternalFormat); 2543 return false; 2544 } 2545 } 2546 } 2547 2548 GLint samples = readFramebuffer->getSamples(context); 2549 if (samples != 0 && 2550 IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0, 2551 srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) 2552 { 2553 context->validationError(entryPoint, GL_INVALID_OPERATION, 2554 kBlitExtensionMultisampledWholeBufferBlit); 2555 return false; 2556 } 2557 } 2558 } 2559 2560 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT}; 2561 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; 2562 for (size_t i = 0; i < 2; i++) 2563 { 2564 if (mask & masks[i]) 2565 { 2566 const FramebufferAttachment *readBuffer = 2567 readFramebuffer->getAttachment(context, attachments[i]); 2568 const FramebufferAttachment *drawBuffer = 2569 drawFramebuffer->getAttachment(context, attachments[i]); 2570 2571 if (readBuffer && drawBuffer) 2572 { 2573 if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1, 2574 dstX0, dstY0, dstX1, dstY1)) 2575 { 2576 // only whole-buffer copies are permitted 2577 context->validationError(entryPoint, GL_INVALID_OPERATION, 2578 kBlitExtensionDepthStencilWholeBufferBlit); 2579 return false; 2580 } 2581 2582 if (readBuffer->getResourceSamples() != 0 || drawBuffer->getResourceSamples() != 0) 2583 { 2584 context->validationError(entryPoint, GL_INVALID_OPERATION, 2585 kBlitExtensionMultisampledDepthOrStencil); 2586 return false; 2587 } 2588 } 2589 } 2590 } 2591 2592 return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0, 2593 dstY0, dstX1, dstY1, mask, filter); 2594 } 2595 2596 bool ValidateBlitFramebufferNV(const Context *context, 2597 angle::EntryPoint entryPoint, 2598 GLint srcX0, 2599 GLint srcY0, 2600 GLint srcX1, 2601 GLint srcY1, 2602 GLint dstX0, 2603 GLint dstY0, 2604 GLint dstX1, 2605 GLint dstY1, 2606 GLbitfield mask, 2607 GLenum filter) 2608 { 2609 if (!context->getExtensions().framebufferBlitANGLE) 2610 { 2611 context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionNotAvailable); 2612 return false; 2613 } 2614 2615 return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0, 2616 dstY0, dstX1, dstY1, mask, filter); 2617 } 2618 2619 bool ValidateClear(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask) 2620 { 2621 Framebuffer *fbo = context->getState().getDrawFramebuffer(); 2622 const Extensions &extensions = context->getExtensions(); 2623 2624 if (!ValidateFramebufferComplete(context, entryPoint, fbo)) 2625 { 2626 return false; 2627 } 2628 2629 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) 2630 { 2631 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidClearMask); 2632 return false; 2633 } 2634 2635 if (extensions.webglCompatibilityANGLE && (mask & GL_COLOR_BUFFER_BIT) != 0) 2636 { 2637 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED, 2638 GL_SIGNED_NORMALIZED}; 2639 2640 for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount(); 2641 drawBufferIdx++) 2642 { 2643 if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawBufferIdx, 2644 validComponentTypes, 2645 ArraySize(validComponentTypes))) 2646 { 2647 return false; 2648 } 2649 } 2650 } 2651 2652 if ((extensions.multiviewOVR || extensions.multiview2OVR) && extensions.disjointTimerQueryEXT) 2653 { 2654 const State &state = context->getState(); 2655 Framebuffer *framebuffer = state.getDrawFramebuffer(); 2656 if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed)) 2657 { 2658 context->validationError(entryPoint, GL_INVALID_OPERATION, kMultiviewTimerQuery); 2659 return false; 2660 } 2661 } 2662 2663 return true; 2664 } 2665 2666 bool ValidateDrawBuffersEXT(const Context *context, 2667 angle::EntryPoint entryPoint, 2668 GLsizei n, 2669 const GLenum *bufs) 2670 { 2671 if (!context->getExtensions().drawBuffersEXT) 2672 { 2673 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 2674 return false; 2675 } 2676 2677 return ValidateDrawBuffersBase(context, entryPoint, n, bufs); 2678 } 2679 2680 bool ValidateTexImage2D(const Context *context, 2681 angle::EntryPoint entryPoint, 2682 TextureTarget target, 2683 GLint level, 2684 GLint internalformat, 2685 GLsizei width, 2686 GLsizei height, 2687 GLint border, 2688 GLenum format, 2689 GLenum type, 2690 const void *pixels) 2691 { 2692 if (context->getClientMajorVersion() < 3) 2693 { 2694 return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, 2695 false, false, 0, 0, width, height, border, format, 2696 type, -1, pixels); 2697 } 2698 2699 ASSERT(context->getClientMajorVersion() >= 3); 2700 return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat, 2701 false, false, 0, 0, 0, width, height, 1, border, format, 2702 type, -1, pixels); 2703 } 2704 2705 bool ValidateTexImage2DRobustANGLE(const Context *context, 2706 angle::EntryPoint entryPoint, 2707 TextureTarget target, 2708 GLint level, 2709 GLint internalformat, 2710 GLsizei width, 2711 GLsizei height, 2712 GLint border, 2713 GLenum format, 2714 GLenum type, 2715 GLsizei bufSize, 2716 const void *pixels) 2717 { 2718 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2719 { 2720 return false; 2721 } 2722 2723 if (context->getClientMajorVersion() < 3) 2724 { 2725 return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, 2726 false, false, 0, 0, width, height, border, format, 2727 type, bufSize, pixels); 2728 } 2729 2730 ASSERT(context->getClientMajorVersion() >= 3); 2731 return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat, 2732 false, false, 0, 0, 0, width, height, 1, border, format, 2733 type, bufSize, pixels); 2734 } 2735 2736 bool ValidateTexSubImage2D(const Context *context, 2737 angle::EntryPoint entryPoint, 2738 TextureTarget target, 2739 GLint level, 2740 GLint xoffset, 2741 GLint yoffset, 2742 GLsizei width, 2743 GLsizei height, 2744 GLenum format, 2745 GLenum type, 2746 const void *pixels) 2747 { 2748 2749 if (context->getClientMajorVersion() < 3) 2750 { 2751 return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false, 2752 true, xoffset, yoffset, width, height, 0, format, type, 2753 -1, pixels); 2754 } 2755 2756 ASSERT(context->getClientMajorVersion() >= 3); 2757 return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true, 2758 xoffset, yoffset, 0, width, height, 1, 0, format, type, 2759 -1, pixels); 2760 } 2761 2762 bool ValidateTexSubImage2DRobustANGLE(const Context *context, 2763 angle::EntryPoint entryPoint, 2764 TextureTarget target, 2765 GLint level, 2766 GLint xoffset, 2767 GLint yoffset, 2768 GLsizei width, 2769 GLsizei height, 2770 GLenum format, 2771 GLenum type, 2772 GLsizei bufSize, 2773 const void *pixels) 2774 { 2775 if (!ValidateRobustEntryPoint(context, entryPoint, bufSize)) 2776 { 2777 return false; 2778 } 2779 2780 if (context->getClientMajorVersion() < 3) 2781 { 2782 return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false, 2783 true, xoffset, yoffset, width, height, 0, format, type, 2784 bufSize, pixels); 2785 } 2786 2787 ASSERT(context->getClientMajorVersion() >= 3); 2788 return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true, 2789 xoffset, yoffset, 0, width, height, 1, 0, format, type, 2790 bufSize, pixels); 2791 } 2792 2793 bool ValidateTexSubImage3DOES(const Context *context, 2794 angle::EntryPoint entryPoint, 2795 TextureTarget target, 2796 GLint level, 2797 GLint xoffset, 2798 GLint yoffset, 2799 GLint zoffset, 2800 GLsizei width, 2801 GLsizei height, 2802 GLsizei depth, 2803 GLenum format, 2804 GLenum type, 2805 const void *pixels) 2806 { 2807 return ValidateTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset, 2808 width, height, depth, format, type, pixels); 2809 } 2810 2811 bool ValidateCompressedTexImage2D(const Context *context, 2812 angle::EntryPoint entryPoint, 2813 TextureTarget target, 2814 GLint level, 2815 GLenum internalformat, 2816 GLsizei width, 2817 GLsizei height, 2818 GLint border, 2819 GLsizei imageSize, 2820 const void *data) 2821 { 2822 if (context->getClientMajorVersion() < 3) 2823 { 2824 if (!ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, true, 2825 false, 0, 0, width, height, border, GL_NONE, GL_NONE, -1, 2826 data)) 2827 { 2828 return false; 2829 } 2830 } 2831 else 2832 { 2833 ASSERT(context->getClientMajorVersion() >= 3); 2834 if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat, 2835 true, false, 0, 0, 0, width, height, 1, border, 2836 GL_NONE, GL_NONE, -1, data)) 2837 { 2838 return false; 2839 } 2840 } 2841 2842 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat); 2843 2844 GLuint expectedImageSize = 0; 2845 if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &expectedImageSize)) 2846 { 2847 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 2848 return false; 2849 } 2850 2851 if (imageSize < 0 || static_cast<GLuint>(imageSize) != expectedImageSize) 2852 { 2853 context->validationError(entryPoint, GL_INVALID_VALUE, 2854 kCompressedTextureDimensionsMustMatchData); 2855 return false; 2856 } 2857 2858 if (target == TextureTarget::Rectangle) 2859 { 2860 context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed); 2861 return false; 2862 } 2863 2864 return true; 2865 } 2866 2867 bool ValidateCompressedTexImage2DRobustANGLE(const Context *context, 2868 angle::EntryPoint entryPoint, 2869 TextureTarget target, 2870 GLint level, 2871 GLenum internalformat, 2872 GLsizei width, 2873 GLsizei height, 2874 GLint border, 2875 GLsizei imageSize, 2876 GLsizei dataSize, 2877 const void *data) 2878 { 2879 if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize)) 2880 { 2881 return false; 2882 } 2883 2884 return ValidateCompressedTexImage2D(context, entryPoint, target, level, internalformat, width, 2885 height, border, imageSize, data); 2886 } 2887 2888 bool ValidateCompressedTexImage3DOES(const Context *context, 2889 angle::EntryPoint entryPoint, 2890 TextureTarget target, 2891 GLint level, 2892 GLenum internalformat, 2893 GLsizei width, 2894 GLsizei height, 2895 GLsizei depth, 2896 GLint border, 2897 GLsizei imageSize, 2898 const void *data) 2899 { 2900 return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width, 2901 height, depth, border, imageSize, data); 2902 } 2903 2904 bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context, 2905 angle::EntryPoint entryPoint, 2906 TextureTarget target, 2907 GLint level, 2908 GLint xoffset, 2909 GLint yoffset, 2910 GLsizei width, 2911 GLsizei height, 2912 GLenum format, 2913 GLsizei imageSize, 2914 GLsizei dataSize, 2915 const void *data) 2916 { 2917 if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize)) 2918 { 2919 return false; 2920 } 2921 2922 return ValidateCompressedTexSubImage2D(context, entryPoint, target, level, xoffset, yoffset, 2923 width, height, format, imageSize, data); 2924 } 2925 2926 bool ValidateCompressedTexSubImage2D(const Context *context, 2927 angle::EntryPoint entryPoint, 2928 TextureTarget target, 2929 GLint level, 2930 GLint xoffset, 2931 GLint yoffset, 2932 GLsizei width, 2933 GLsizei height, 2934 GLenum format, 2935 GLsizei imageSize, 2936 const void *data) 2937 { 2938 if (context->getClientMajorVersion() < 3) 2939 { 2940 if (!ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, true, true, 2941 xoffset, yoffset, width, height, 0, format, GL_NONE, -1, 2942 data)) 2943 { 2944 return false; 2945 } 2946 } 2947 else 2948 { 2949 ASSERT(context->getClientMajorVersion() >= 3); 2950 if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, true, 2951 true, xoffset, yoffset, 0, width, height, 1, 0, format, 2952 GL_NONE, -1, data)) 2953 { 2954 return false; 2955 } 2956 } 2957 2958 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format); 2959 GLuint blockSize = 0; 2960 if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize)) 2961 { 2962 context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow); 2963 return false; 2964 } 2965 2966 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize) 2967 { 2968 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize); 2969 return false; 2970 } 2971 2972 return true; 2973 } 2974 2975 bool ValidateCompressedTexSubImage3DOES(const Context *context, 2976 angle::EntryPoint entryPoint, 2977 TextureTarget target, 2978 GLint level, 2979 GLint xoffset, 2980 GLint yoffset, 2981 GLint zoffset, 2982 GLsizei width, 2983 GLsizei height, 2984 GLsizei depth, 2985 GLenum format, 2986 GLsizei imageSize, 2987 const void *data) 2988 { 2989 return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, 2990 zoffset, width, height, depth, format, imageSize, data); 2991 } 2992 2993 bool ValidateGetBufferPointervOES(const Context *context, 2994 angle::EntryPoint entryPoint, 2995 BufferBinding target, 2996 GLenum pname, 2997 void *const *params) 2998 { 2999 if (!context->getExtensions().mapbufferOES) 3000 { 3001 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3002 return false; 3003 } 3004 3005 return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params); 3006 } 3007 3008 bool ValidateMapBufferOES(const Context *context, 3009 angle::EntryPoint entryPoint, 3010 BufferBinding target, 3011 GLenum access) 3012 { 3013 if (!context->getExtensions().mapbufferOES) 3014 { 3015 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3016 return false; 3017 } 3018 3019 if (!context->isValidBufferBinding(target)) 3020 { 3021 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 3022 return false; 3023 } 3024 3025 Buffer *buffer = context->getState().getTargetBuffer(target); 3026 3027 if (buffer == nullptr) 3028 { 3029 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable); 3030 return false; 3031 } 3032 3033 if (access != GL_WRITE_ONLY_OES) 3034 { 3035 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAccessBits); 3036 return false; 3037 } 3038 3039 // Though there is no explicit mention of an interaction between GL_EXT_buffer_storage 3040 // and GL_OES_mapbuffer extension, allow it as long as the access type of glmapbufferOES 3041 // is compatible with the buffer's usage flags specified during glBufferStorageEXT 3042 if (buffer->isImmutable() && (buffer->getStorageExtUsageFlags() & GL_MAP_WRITE_BIT) == 0) 3043 { 3044 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable); 3045 return false; 3046 } 3047 3048 if (buffer->isMapped()) 3049 { 3050 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferAlreadyMapped); 3051 return false; 3052 } 3053 3054 return ValidateMapBufferBase(context, entryPoint, target); 3055 } 3056 3057 bool ValidateUnmapBufferOES(const Context *context, 3058 angle::EntryPoint entryPoint, 3059 BufferBinding target) 3060 { 3061 if (!context->getExtensions().mapbufferOES) 3062 { 3063 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3064 return false; 3065 } 3066 3067 return ValidateUnmapBufferBase(context, entryPoint, target); 3068 } 3069 3070 bool ValidateMapBufferRangeEXT(const Context *context, 3071 angle::EntryPoint entryPoint, 3072 BufferBinding target, 3073 GLintptr offset, 3074 GLsizeiptr length, 3075 GLbitfield access) 3076 { 3077 if (!context->getExtensions().mapBufferRangeEXT) 3078 { 3079 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3080 return false; 3081 } 3082 3083 return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access); 3084 } 3085 3086 bool ValidateMapBufferBase(const Context *context, 3087 angle::EntryPoint entryPoint, 3088 BufferBinding target) 3089 { 3090 Buffer *buffer = context->getState().getTargetBuffer(target); 3091 ASSERT(buffer != nullptr); 3092 3093 // Check if this buffer is currently being used as a transform feedback output buffer 3094 if (context->getState().isTransformFeedbackActive()) 3095 { 3096 TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); 3097 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++) 3098 { 3099 const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i); 3100 if (transformFeedbackBuffer.get() == buffer) 3101 { 3102 context->validationError(entryPoint, GL_INVALID_OPERATION, 3103 kBufferBoundForTransformFeedback); 3104 return false; 3105 } 3106 } 3107 } 3108 3109 if (buffer->hasWebGLXFBBindingConflict(context->isWebGL())) 3110 { 3111 context->validationError(entryPoint, GL_INVALID_OPERATION, 3112 kBufferBoundForTransformFeedback); 3113 return false; 3114 } 3115 3116 return true; 3117 } 3118 3119 bool ValidateFlushMappedBufferRangeEXT(const Context *context, 3120 angle::EntryPoint entryPoint, 3121 BufferBinding target, 3122 GLintptr offset, 3123 GLsizeiptr length) 3124 { 3125 if (!context->getExtensions().mapBufferRangeEXT) 3126 { 3127 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3128 return false; 3129 } 3130 3131 return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length); 3132 } 3133 3134 bool ValidateBindUniformLocationCHROMIUM(const Context *context, 3135 angle::EntryPoint entryPoint, 3136 ShaderProgramID program, 3137 UniformLocation location, 3138 const GLchar *name) 3139 { 3140 if (!context->getExtensions().bindUniformLocationCHROMIUM) 3141 { 3142 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3143 return false; 3144 } 3145 3146 Program *programObject = GetValidProgram(context, entryPoint, program); 3147 if (!programObject) 3148 { 3149 return false; 3150 } 3151 3152 if (location.value < 0) 3153 { 3154 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLocation); 3155 return false; 3156 } 3157 3158 const Caps &caps = context->getCaps(); 3159 if (static_cast<long>(location.value) >= 3160 (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4) 3161 { 3162 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBindUniformLocation); 3163 return false; 3164 } 3165 3166 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for 3167 // shader-related entry points 3168 if (context->isWebGL() && !IsValidESSLString(name, strlen(name))) 3169 { 3170 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters); 3171 return false; 3172 } 3173 3174 if (strncmp(name, "gl_", 3) == 0) 3175 { 3176 context->validationError(entryPoint, GL_INVALID_VALUE, kNameBeginsWithGL); 3177 return false; 3178 } 3179 3180 return true; 3181 } 3182 3183 bool ValidateCoverageModulationCHROMIUM(const Context *context, 3184 angle::EntryPoint entryPoint, 3185 GLenum components) 3186 { 3187 if (!context->getExtensions().framebufferMixedSamplesCHROMIUM) 3188 { 3189 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3190 return false; 3191 } 3192 switch (components) 3193 { 3194 case GL_RGB: 3195 case GL_RGBA: 3196 case GL_ALPHA: 3197 case GL_NONE: 3198 break; 3199 default: 3200 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCoverageComponents); 3201 return false; 3202 } 3203 3204 return true; 3205 } 3206 3207 bool ValidateCopyTextureCHROMIUM(const Context *context, 3208 angle::EntryPoint entryPoint, 3209 TextureID sourceId, 3210 GLint sourceLevel, 3211 TextureTarget destTarget, 3212 TextureID destId, 3213 GLint destLevel, 3214 GLint internalFormat, 3215 GLenum destType, 3216 GLboolean unpackFlipY, 3217 GLboolean unpackPremultiplyAlpha, 3218 GLboolean unpackUnmultiplyAlpha) 3219 { 3220 if (!context->getExtensions().copyTextureCHROMIUM) 3221 { 3222 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3223 return false; 3224 } 3225 3226 const Texture *source = context->getTexture(sourceId); 3227 if (source == nullptr) 3228 { 3229 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture); 3230 return false; 3231 } 3232 3233 if (!IsValidCopyTextureSourceTarget(context, source->getType())) 3234 { 3235 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 3236 internalFormat); 3237 return false; 3238 } 3239 3240 TextureType sourceType = source->getType(); 3241 ASSERT(sourceType != TextureType::CubeMap); 3242 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType); 3243 3244 if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel)) 3245 { 3246 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel); 3247 return false; 3248 } 3249 3250 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel)); 3251 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel)); 3252 if (sourceWidth == 0 || sourceHeight == 0) 3253 { 3254 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 3255 internalFormat); 3256 return false; 3257 } 3258 3259 const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info; 3260 if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat)) 3261 { 3262 context->validationError(entryPoint, GL_INVALID_OPERATION, 3263 kInvalidSourceTextureInternalFormat); 3264 return false; 3265 } 3266 3267 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget)) 3268 { 3269 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 3270 return false; 3271 } 3272 3273 const Texture *dest = context->getTexture(destId); 3274 if (dest == nullptr) 3275 { 3276 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture); 3277 return false; 3278 } 3279 3280 const InternalFormat &destInternalFormatInfo = GetInternalFormatInfo(internalFormat, destType); 3281 if (sourceType == TextureType::External && destInternalFormatInfo.isInt() && 3282 !context->getExtensions().EGLImageExternalEssl3OES) 3283 { 3284 context->validationError(entryPoint, GL_INVALID_OPERATION, 3285 kANGLECopyTextureMissingRequiredExtension); 3286 return false; 3287 } 3288 3289 if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget)) 3290 { 3291 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType); 3292 return false; 3293 } 3294 3295 if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel, 3296 sourceWidth, sourceHeight, false)) 3297 { 3298 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 3299 return false; 3300 } 3301 3302 if (!IsValidCopyTextureDestinationFormatType(context, entryPoint, internalFormat, destType)) 3303 { 3304 return false; 3305 } 3306 3307 if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight) 3308 { 3309 context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapFacesEqualDimensions); 3310 return false; 3311 } 3312 3313 if (dest->getImmutableFormat()) 3314 { 3315 context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable); 3316 return false; 3317 } 3318 3319 return true; 3320 } 3321 3322 bool ValidateCopySubTextureCHROMIUM(const Context *context, 3323 angle::EntryPoint entryPoint, 3324 TextureID sourceId, 3325 GLint sourceLevel, 3326 TextureTarget destTarget, 3327 TextureID destId, 3328 GLint destLevel, 3329 GLint xoffset, 3330 GLint yoffset, 3331 GLint x, 3332 GLint y, 3333 GLsizei width, 3334 GLsizei height, 3335 GLboolean unpackFlipY, 3336 GLboolean unpackPremultiplyAlpha, 3337 GLboolean unpackUnmultiplyAlpha) 3338 { 3339 if (!context->getExtensions().copyTextureCHROMIUM) 3340 { 3341 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3342 return false; 3343 } 3344 3345 const Texture *source = context->getTexture(sourceId); 3346 if (source == nullptr) 3347 { 3348 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture); 3349 return false; 3350 } 3351 3352 if (!IsValidCopyTextureSourceTarget(context, source->getType())) 3353 { 3354 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureType); 3355 return false; 3356 } 3357 3358 TextureType sourceType = source->getType(); 3359 ASSERT(sourceType != TextureType::CubeMap); 3360 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType); 3361 3362 if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel)) 3363 { 3364 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 3365 return false; 3366 } 3367 3368 if (source->getWidth(sourceTarget, sourceLevel) == 0 || 3369 source->getHeight(sourceTarget, sourceLevel) == 0) 3370 { 3371 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel); 3372 return false; 3373 } 3374 3375 if (x < 0 || y < 0) 3376 { 3377 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 3378 return false; 3379 } 3380 3381 if (width < 0 || height < 0) 3382 { 3383 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 3384 return false; 3385 } 3386 3387 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) || 3388 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel)) 3389 { 3390 context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall); 3391 return false; 3392 } 3393 3394 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel); 3395 if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat)) 3396 { 3397 context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat, 3398 sourceFormat.info->internalFormat); 3399 return false; 3400 } 3401 3402 if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget)) 3403 { 3404 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 3405 return false; 3406 } 3407 3408 const Texture *dest = context->getTexture(destId); 3409 if (dest == nullptr) 3410 { 3411 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture); 3412 return false; 3413 } 3414 3415 if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget)) 3416 { 3417 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType); 3418 return false; 3419 } 3420 3421 if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel, width, 3422 height, true)) 3423 { 3424 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 3425 return false; 3426 } 3427 3428 if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0) 3429 { 3430 context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationLevelNotDefined); 3431 return false; 3432 } 3433 3434 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info; 3435 if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat)) 3436 { 3437 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination); 3438 return false; 3439 } 3440 3441 if (sourceType == TextureType::External && destFormat.isInt() && 3442 !context->getExtensions().EGLImageExternalEssl3OES) 3443 { 3444 context->validationError(entryPoint, GL_INVALID_OPERATION, 3445 kANGLECopyTextureMissingRequiredExtension); 3446 return false; 3447 } 3448 3449 if (xoffset < 0 || yoffset < 0) 3450 { 3451 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 3452 return false; 3453 } 3454 3455 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) || 3456 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel)) 3457 { 3458 context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow); 3459 return false; 3460 } 3461 3462 return true; 3463 } 3464 3465 bool ValidateCompressedCopyTextureCHROMIUM(const Context *context, 3466 angle::EntryPoint entryPoint, 3467 TextureID sourceId, 3468 TextureID destId) 3469 { 3470 if (!context->getExtensions().copyCompressedTextureCHROMIUM) 3471 { 3472 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3473 return false; 3474 } 3475 3476 const Texture *source = context->getTexture(sourceId); 3477 if (source == nullptr) 3478 { 3479 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture); 3480 return false; 3481 } 3482 3483 if (source->getType() != TextureType::_2D) 3484 { 3485 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureType); 3486 return false; 3487 } 3488 3489 if (source->getWidth(TextureTarget::_2D, 0) == 0 || 3490 source->getHeight(TextureTarget::_2D, 0) == 0) 3491 { 3492 context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureLevelZeroDefined); 3493 return false; 3494 } 3495 3496 const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0); 3497 if (!sourceFormat.info->compressed) 3498 { 3499 context->validationError(entryPoint, GL_INVALID_OPERATION, kSourceTextureMustBeCompressed); 3500 return false; 3501 } 3502 3503 const Texture *dest = context->getTexture(destId); 3504 if (dest == nullptr) 3505 { 3506 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture); 3507 return false; 3508 } 3509 3510 if (dest->getType() != TextureType::_2D) 3511 { 3512 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType); 3513 return false; 3514 } 3515 3516 if (dest->getImmutableFormat()) 3517 { 3518 context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable); 3519 return false; 3520 } 3521 3522 return true; 3523 } 3524 3525 bool ValidateCreateShader(const Context *context, angle::EntryPoint entryPoint, ShaderType type) 3526 { 3527 switch (type) 3528 { 3529 case ShaderType::Vertex: 3530 case ShaderType::Fragment: 3531 break; 3532 3533 case ShaderType::Compute: 3534 if (context->getClientVersion() < ES_3_1) 3535 { 3536 context->validationError(entryPoint, GL_INVALID_ENUM, kES31Required); 3537 return false; 3538 } 3539 break; 3540 3541 case ShaderType::Geometry: 3542 if (!context->getExtensions().geometryShaderAny() && 3543 context->getClientVersion() < ES_3_2) 3544 { 3545 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType); 3546 return false; 3547 } 3548 break; 3549 3550 case ShaderType::TessControl: 3551 if (!context->getExtensions().tessellationShaderEXT && 3552 context->getClientVersion() < ES_3_2) 3553 { 3554 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType); 3555 return false; 3556 } 3557 break; 3558 3559 case ShaderType::TessEvaluation: 3560 if (!context->getExtensions().tessellationShaderEXT && 3561 context->getClientVersion() < ES_3_2) 3562 { 3563 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType); 3564 return false; 3565 } 3566 break; 3567 3568 default: 3569 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType); 3570 return false; 3571 } 3572 3573 return true; 3574 } 3575 3576 bool ValidateBufferData(const Context *context, 3577 angle::EntryPoint entryPoint, 3578 BufferBinding target, 3579 GLsizeiptr size, 3580 const void *data, 3581 BufferUsage usage) 3582 { 3583 if (size < 0) 3584 { 3585 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 3586 return false; 3587 } 3588 3589 switch (usage) 3590 { 3591 case BufferUsage::StreamDraw: 3592 case BufferUsage::StaticDraw: 3593 case BufferUsage::DynamicDraw: 3594 break; 3595 3596 case BufferUsage::StreamRead: 3597 case BufferUsage::StaticRead: 3598 case BufferUsage::DynamicRead: 3599 case BufferUsage::StreamCopy: 3600 case BufferUsage::StaticCopy: 3601 case BufferUsage::DynamicCopy: 3602 if (context->getClientMajorVersion() < 3) 3603 { 3604 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferUsage); 3605 return false; 3606 } 3607 break; 3608 3609 default: 3610 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferUsage); 3611 return false; 3612 } 3613 3614 if (!context->isValidBufferBinding(target)) 3615 { 3616 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 3617 return false; 3618 } 3619 3620 Buffer *buffer = context->getState().getTargetBuffer(target); 3621 3622 if (!buffer) 3623 { 3624 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound); 3625 return false; 3626 } 3627 3628 if (buffer->hasWebGLXFBBindingConflict(context->isWebGL())) 3629 { 3630 context->validationError(entryPoint, GL_INVALID_OPERATION, 3631 kBufferBoundForTransformFeedback); 3632 return false; 3633 } 3634 3635 if (buffer->isImmutable()) 3636 { 3637 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferImmutable); 3638 return false; 3639 } 3640 3641 return true; 3642 } 3643 3644 bool ValidateBufferSubData(const Context *context, 3645 angle::EntryPoint entryPoint, 3646 BufferBinding target, 3647 GLintptr offset, 3648 GLsizeiptr size, 3649 const void *data) 3650 { 3651 if (size < 0) 3652 { 3653 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 3654 return false; 3655 } 3656 3657 if (offset < 0) 3658 { 3659 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset); 3660 return false; 3661 } 3662 3663 if (!context->isValidBufferBinding(target)) 3664 { 3665 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes); 3666 return false; 3667 } 3668 3669 Buffer *buffer = context->getState().getTargetBuffer(target); 3670 3671 if (!buffer) 3672 { 3673 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound); 3674 return false; 3675 } 3676 3677 // EXT_buffer_storage allows persistently mapped buffers to be updated via glBufferSubData 3678 bool isPersistent = (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0; 3679 3680 // Verify that buffer is not currently mapped unless persistent 3681 if (buffer->isMapped() && !isPersistent) 3682 { 3683 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped); 3684 return false; 3685 } 3686 3687 if (buffer->hasWebGLXFBBindingConflict(context->isWebGL())) 3688 { 3689 context->validationError(entryPoint, GL_INVALID_OPERATION, 3690 kBufferBoundForTransformFeedback); 3691 return false; 3692 } 3693 3694 if (buffer->isImmutable() && 3695 (buffer->getStorageExtUsageFlags() & GL_DYNAMIC_STORAGE_BIT_EXT) == 0) 3696 { 3697 context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotUpdatable); 3698 return false; 3699 } 3700 3701 // Check for possible overflow of size + offset 3702 angle::CheckedNumeric<decltype(size + offset)> checkedSize(size); 3703 checkedSize += offset; 3704 if (!checkedSize.IsValid()) 3705 { 3706 context->validationError(entryPoint, GL_INVALID_VALUE, kParamOverflow); 3707 return false; 3708 } 3709 3710 if (size + offset > buffer->getSize()) 3711 { 3712 context->validationError(entryPoint, GL_INVALID_VALUE, kInsufficientBufferSize); 3713 return false; 3714 } 3715 3716 return true; 3717 } 3718 3719 bool ValidateRequestExtensionANGLE(const Context *context, 3720 angle::EntryPoint entryPoint, 3721 const GLchar *name) 3722 { 3723 if (!context->getExtensions().requestExtensionANGLE) 3724 { 3725 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3726 return false; 3727 } 3728 3729 if (!context->isExtensionRequestable(name)) 3730 { 3731 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotRequestable); 3732 return false; 3733 } 3734 3735 return true; 3736 } 3737 3738 bool ValidateDisableExtensionANGLE(const Context *context, 3739 angle::EntryPoint entryPoint, 3740 const GLchar *name) 3741 { 3742 if (!context->getExtensions().requestExtensionANGLE) 3743 { 3744 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 3745 return false; 3746 } 3747 3748 if (!context->isExtensionDisablable(name)) 3749 { 3750 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotDisablable); 3751 return false; 3752 } 3753 3754 return true; 3755 } 3756 3757 bool ValidateActiveTexture(const Context *context, angle::EntryPoint entryPoint, GLenum texture) 3758 { 3759 if (context->getClientMajorVersion() < 2) 3760 { 3761 return ValidateMultitextureUnit(context, entryPoint, texture); 3762 } 3763 3764 if (texture < GL_TEXTURE0 || 3765 texture > 3766 GL_TEXTURE0 + static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits) - 1) 3767 { 3768 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCombinedImageUnit); 3769 return false; 3770 } 3771 3772 return true; 3773 } 3774 3775 bool ValidateAttachShader(const Context *context, 3776 angle::EntryPoint entryPoint, 3777 ShaderProgramID program, 3778 ShaderProgramID shader) 3779 { 3780 Program *programObject = GetValidProgram(context, entryPoint, program); 3781 if (!programObject) 3782 { 3783 return false; 3784 } 3785 3786 Shader *shaderObject = GetValidShader(context, entryPoint, shader); 3787 if (!shaderObject) 3788 { 3789 return false; 3790 } 3791 3792 if (programObject->getAttachedShader(shaderObject->getType())) 3793 { 3794 context->validationError(entryPoint, GL_INVALID_OPERATION, kShaderAttachmentHasShader); 3795 return false; 3796 } 3797 3798 return true; 3799 } 3800 3801 bool ValidateBindAttribLocation(const Context *context, 3802 angle::EntryPoint entryPoint, 3803 ShaderProgramID program, 3804 GLuint index, 3805 const GLchar *name) 3806 { 3807 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 3808 { 3809 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); 3810 return false; 3811 } 3812 3813 if (strncmp(name, "gl_", 3) == 0) 3814 { 3815 context->validationError(entryPoint, GL_INVALID_OPERATION, kNameBeginsWithGL); 3816 return false; 3817 } 3818 3819 if (context->isWebGL()) 3820 { 3821 const size_t length = strlen(name); 3822 3823 if (!IsValidESSLString(name, length)) 3824 { 3825 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters 3826 // for shader-related entry points 3827 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters); 3828 return false; 3829 } 3830 3831 if (!ValidateWebGLNameLength(context, entryPoint, length) || 3832 !ValidateWebGLNamePrefix(context, entryPoint, name)) 3833 { 3834 return false; 3835 } 3836 } 3837 3838 return GetValidProgram(context, entryPoint, program) != nullptr; 3839 } 3840 3841 bool ValidateBindFramebuffer(const Context *context, 3842 angle::EntryPoint entryPoint, 3843 GLenum target, 3844 FramebufferID framebuffer) 3845 { 3846 return ValidateBindFramebufferBase(context, entryPoint, target, framebuffer); 3847 } 3848 3849 bool ValidateBindRenderbuffer(const Context *context, 3850 angle::EntryPoint entryPoint, 3851 GLenum target, 3852 RenderbufferID renderbuffer) 3853 { 3854 return ValidateBindRenderbufferBase(context, entryPoint, target, renderbuffer); 3855 } 3856 3857 static bool ValidBlendEquationMode(const Context *context, GLenum mode) 3858 { 3859 switch (mode) 3860 { 3861 case GL_FUNC_ADD: 3862 case GL_FUNC_SUBTRACT: 3863 case GL_FUNC_REVERSE_SUBTRACT: 3864 return true; 3865 3866 case GL_MIN: 3867 case GL_MAX: 3868 return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinmaxEXT; 3869 3870 default: 3871 return false; 3872 } 3873 } 3874 3875 static bool ValidAdvancedBlendEquationMode(const Context *context, GLenum mode) 3876 { 3877 switch (mode) 3878 { 3879 case GL_MULTIPLY_KHR: 3880 case GL_SCREEN_KHR: 3881 case GL_OVERLAY_KHR: 3882 case GL_DARKEN_KHR: 3883 case GL_LIGHTEN_KHR: 3884 case GL_COLORDODGE_KHR: 3885 case GL_COLORBURN_KHR: 3886 case GL_HARDLIGHT_KHR: 3887 case GL_SOFTLIGHT_KHR: 3888 case GL_DIFFERENCE_KHR: 3889 case GL_EXCLUSION_KHR: 3890 case GL_HSL_HUE_KHR: 3891 case GL_HSL_SATURATION_KHR: 3892 case GL_HSL_COLOR_KHR: 3893 case GL_HSL_LUMINOSITY_KHR: 3894 return context->getClientVersion() >= ES_3_2 || 3895 context->getExtensions().blendEquationAdvancedKHR; 3896 3897 default: 3898 return false; 3899 } 3900 } 3901 3902 bool ValidateBlendColor(const Context *context, 3903 angle::EntryPoint entryPoint, 3904 GLfloat red, 3905 GLfloat green, 3906 GLfloat blue, 3907 GLfloat alpha) 3908 { 3909 return true; 3910 } 3911 3912 bool ValidateBlendEquation(const Context *context, angle::EntryPoint entryPoint, GLenum mode) 3913 { 3914 if (!ValidBlendEquationMode(context, mode) && !ValidAdvancedBlendEquationMode(context, mode)) 3915 { 3916 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation); 3917 return false; 3918 } 3919 3920 return true; 3921 } 3922 3923 bool ValidateBlendEquationSeparate(const Context *context, 3924 angle::EntryPoint entryPoint, 3925 GLenum modeRGB, 3926 GLenum modeAlpha) 3927 { 3928 if (!ValidBlendEquationMode(context, modeRGB)) 3929 { 3930 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation); 3931 return false; 3932 } 3933 3934 if (!ValidBlendEquationMode(context, modeAlpha)) 3935 { 3936 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation); 3937 return false; 3938 } 3939 3940 return true; 3941 } 3942 3943 bool ValidateBlendFunc(const Context *context, 3944 angle::EntryPoint entryPoint, 3945 GLenum sfactor, 3946 GLenum dfactor) 3947 { 3948 return ValidateBlendFuncSeparate(context, entryPoint, sfactor, dfactor, sfactor, dfactor); 3949 } 3950 3951 bool ValidateBlendFuncSeparate(const Context *context, 3952 angle::EntryPoint entryPoint, 3953 GLenum srcRGB, 3954 GLenum dstRGB, 3955 GLenum srcAlpha, 3956 GLenum dstAlpha) 3957 { 3958 if (!ValidSrcBlendFunc(context, srcRGB)) 3959 { 3960 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction); 3961 return false; 3962 } 3963 3964 if (!ValidDstBlendFunc(context, dstRGB)) 3965 { 3966 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction); 3967 return false; 3968 } 3969 3970 if (!ValidSrcBlendFunc(context, srcAlpha)) 3971 { 3972 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction); 3973 return false; 3974 } 3975 3976 if (!ValidDstBlendFunc(context, dstAlpha)) 3977 { 3978 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction); 3979 return false; 3980 } 3981 3982 if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc || 3983 context->isWebGL()) 3984 { 3985 bool constantColorUsed = 3986 (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || 3987 dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); 3988 3989 bool constantAlphaUsed = 3990 (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || 3991 dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); 3992 3993 if (constantColorUsed && constantAlphaUsed) 3994 { 3995 if (context->isWebGL()) 3996 { 3997 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidConstantColor); 3998 return false; 3999 } 4000 4001 WARN() << kConstantColorAlphaLimitation; 4002 context->validationError(entryPoint, GL_INVALID_OPERATION, 4003 kConstantColorAlphaLimitation); 4004 return false; 4005 } 4006 } 4007 4008 return true; 4009 } 4010 4011 bool ValidateGetString(const Context *context, angle::EntryPoint entryPoint, GLenum name) 4012 { 4013 switch (name) 4014 { 4015 case GL_VENDOR: 4016 case GL_RENDERER: 4017 case GL_VERSION: 4018 case GL_SHADING_LANGUAGE_VERSION: 4019 case GL_EXTENSIONS: 4020 break; 4021 4022 case GL_REQUESTABLE_EXTENSIONS_ANGLE: 4023 if (!context->getExtensions().requestExtensionANGLE) 4024 { 4025 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName); 4026 return false; 4027 } 4028 break; 4029 4030 case GL_SERIALIZED_CONTEXT_STRING_ANGLE: 4031 if (!context->getExtensions().getSerializedContextStringANGLE) 4032 { 4033 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName); 4034 return false; 4035 } 4036 break; 4037 4038 default: 4039 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName); 4040 return false; 4041 } 4042 4043 return true; 4044 } 4045 4046 bool ValidateLineWidth(const Context *context, angle::EntryPoint entryPoint, GLfloat width) 4047 { 4048 if (width <= 0.0f || isNaN(width)) 4049 { 4050 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidWidth); 4051 return false; 4052 } 4053 4054 return true; 4055 } 4056 4057 bool ValidateDepthRangef(const Context *context, 4058 angle::EntryPoint entryPoint, 4059 GLfloat zNear, 4060 GLfloat zFar) 4061 { 4062 if (context->isWebGL() && zNear > zFar) 4063 { 4064 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDepthRange); 4065 return false; 4066 } 4067 4068 return true; 4069 } 4070 4071 bool ValidateRenderbufferStorage(const Context *context, 4072 angle::EntryPoint entryPoint, 4073 GLenum target, 4074 GLenum internalformat, 4075 GLsizei width, 4076 GLsizei height) 4077 { 4078 return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, 0, internalformat, 4079 width, height); 4080 } 4081 4082 bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context, 4083 angle::EntryPoint entryPoint, 4084 GLenum target, 4085 GLsizei samples, 4086 GLenum internalformat, 4087 GLsizei width, 4088 GLsizei height) 4089 { 4090 if (!context->getExtensions().framebufferMultisampleANGLE) 4091 { 4092 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 4093 return false; 4094 } 4095 4096 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal 4097 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is 4098 // generated. 4099 if (samples > context->getCaps().maxSamples) 4100 { 4101 context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange); 4102 return false; 4103 } 4104 4105 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create 4106 // the specified storage. This is different than ES 3.0 in which a sample number higher 4107 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. 4108 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. 4109 if (context->getClientMajorVersion() >= 3) 4110 { 4111 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); 4112 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) 4113 { 4114 context->validationError(entryPoint, GL_OUT_OF_MEMORY, kSamplesOutOfRange); 4115 return false; 4116 } 4117 } 4118 4119 return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples, 4120 internalformat, width, height); 4121 } 4122 4123 bool ValidateCheckFramebufferStatus(const Context *context, 4124 angle::EntryPoint entryPoint, 4125 GLenum target) 4126 { 4127 if (!ValidFramebufferTarget(context, target)) 4128 { 4129 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget); 4130 return false; 4131 } 4132 4133 return true; 4134 } 4135 4136 bool ValidateClearColor(const Context *context, 4137 angle::EntryPoint entryPoint, 4138 GLfloat red, 4139 GLfloat green, 4140 GLfloat blue, 4141 GLfloat alpha) 4142 { 4143 return true; 4144 } 4145 4146 bool ValidateClearDepthf(const Context *context, angle::EntryPoint entryPoint, GLfloat depth) 4147 { 4148 return true; 4149 } 4150 4151 bool ValidateClearStencil(const Context *context, angle::EntryPoint entryPoint, GLint s) 4152 { 4153 return true; 4154 } 4155 4156 bool ValidateColorMask(const Context *context, 4157 angle::EntryPoint entryPoint, 4158 GLboolean red, 4159 GLboolean green, 4160 GLboolean blue, 4161 GLboolean alpha) 4162 { 4163 return true; 4164 } 4165 4166 bool ValidateCompileShader(const Context *context, 4167 angle::EntryPoint entryPoint, 4168 ShaderProgramID shader) 4169 { 4170 return true; 4171 } 4172 4173 bool ValidateCreateProgram(const Context *context, angle::EntryPoint entryPoint) 4174 { 4175 return true; 4176 } 4177 4178 bool ValidateCullFace(const Context *context, angle::EntryPoint entryPoint, CullFaceMode mode) 4179 { 4180 switch (mode) 4181 { 4182 case CullFaceMode::Front: 4183 case CullFaceMode::Back: 4184 case CullFaceMode::FrontAndBack: 4185 break; 4186 4187 default: 4188 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCullMode); 4189 return false; 4190 } 4191 4192 return true; 4193 } 4194 4195 bool ValidateDeleteProgram(const Context *context, 4196 angle::EntryPoint entryPoint, 4197 ShaderProgramID program) 4198 { 4199 if (program.value == 0) 4200 { 4201 return false; 4202 } 4203 4204 if (!context->getProgramResolveLink(program)) 4205 { 4206 if (context->getShader(program)) 4207 { 4208 context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName); 4209 return false; 4210 } 4211 else 4212 { 4213 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName); 4214 return false; 4215 } 4216 } 4217 4218 return true; 4219 } 4220 4221 bool ValidateDeleteShader(const Context *context, 4222 angle::EntryPoint entryPoint, 4223 ShaderProgramID shader) 4224 { 4225 if (shader.value == 0) 4226 { 4227 return false; 4228 } 4229 4230 if (!context->getShader(shader)) 4231 { 4232 if (context->getProgramResolveLink(shader)) 4233 { 4234 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName); 4235 return false; 4236 } 4237 else 4238 { 4239 context->validationError(entryPoint, GL_INVALID_VALUE, kExpectedShaderName); 4240 return false; 4241 } 4242 } 4243 4244 return true; 4245 } 4246 4247 bool ValidateDepthFunc(const Context *context, angle::EntryPoint entryPoint, GLenum func) 4248 { 4249 switch (func) 4250 { 4251 case GL_NEVER: 4252 case GL_ALWAYS: 4253 case GL_LESS: 4254 case GL_LEQUAL: 4255 case GL_EQUAL: 4256 case GL_GREATER: 4257 case GL_GEQUAL: 4258 case GL_NOTEQUAL: 4259 break; 4260 4261 default: 4262 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, func); 4263 return false; 4264 } 4265 4266 return true; 4267 } 4268 4269 bool ValidateDepthMask(const Context *context, angle::EntryPoint entryPoint, GLboolean flag) 4270 { 4271 return true; 4272 } 4273 4274 bool ValidateDetachShader(const Context *context, 4275 angle::EntryPoint entryPoint, 4276 ShaderProgramID program, 4277 ShaderProgramID shader) 4278 { 4279 Program *programObject = GetValidProgram(context, entryPoint, program); 4280 if (!programObject) 4281 { 4282 return false; 4283 } 4284 4285 Shader *shaderObject = GetValidShader(context, entryPoint, shader); 4286 if (!shaderObject) 4287 { 4288 return false; 4289 } 4290 4291 const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType()); 4292 if (attachedShader != shaderObject) 4293 { 4294 context->validationError(entryPoint, GL_INVALID_OPERATION, kShaderToDetachMustBeAttached); 4295 return false; 4296 } 4297 4298 return true; 4299 } 4300 4301 bool ValidateDisableVertexAttribArray(const Context *context, 4302 angle::EntryPoint entryPoint, 4303 GLuint index) 4304 { 4305 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 4306 { 4307 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); 4308 return false; 4309 } 4310 4311 return true; 4312 } 4313 4314 bool ValidateEnableVertexAttribArray(const Context *context, 4315 angle::EntryPoint entryPoint, 4316 GLuint index) 4317 { 4318 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 4319 { 4320 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); 4321 return false; 4322 } 4323 4324 return true; 4325 } 4326 4327 bool ValidateFinish(const Context *context, angle::EntryPoint entryPoint) 4328 { 4329 return true; 4330 } 4331 4332 bool ValidateFlush(const Context *context, angle::EntryPoint entryPoint) 4333 { 4334 return true; 4335 } 4336 4337 bool ValidateFrontFace(const Context *context, angle::EntryPoint entryPoint, GLenum mode) 4338 { 4339 switch (mode) 4340 { 4341 case GL_CW: 4342 case GL_CCW: 4343 break; 4344 default: 4345 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode); 4346 return false; 4347 } 4348 4349 return true; 4350 } 4351 4352 bool ValidateGetActiveAttrib(const Context *context, 4353 angle::EntryPoint entryPoint, 4354 ShaderProgramID program, 4355 GLuint index, 4356 GLsizei bufsize, 4357 const GLsizei *length, 4358 const GLint *size, 4359 const GLenum *type, 4360 const GLchar *name) 4361 { 4362 if (bufsize < 0) 4363 { 4364 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 4365 return false; 4366 } 4367 4368 Program *programObject = GetValidProgram(context, entryPoint, program); 4369 4370 if (!programObject) 4371 { 4372 return false; 4373 } 4374 4375 if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount())) 4376 { 4377 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform); 4378 return false; 4379 } 4380 4381 return true; 4382 } 4383 4384 bool ValidateGetActiveUniform(const Context *context, 4385 angle::EntryPoint entryPoint, 4386 ShaderProgramID program, 4387 GLuint index, 4388 GLsizei bufsize, 4389 const GLsizei *length, 4390 const GLint *size, 4391 const GLenum *type, 4392 const GLchar *name) 4393 { 4394 if (bufsize < 0) 4395 { 4396 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 4397 return false; 4398 } 4399 4400 Program *programObject = GetValidProgram(context, entryPoint, program); 4401 4402 if (!programObject) 4403 { 4404 return false; 4405 } 4406 4407 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount())) 4408 { 4409 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform); 4410 return false; 4411 } 4412 4413 return true; 4414 } 4415 4416 bool ValidateGetAttachedShaders(const Context *context, 4417 angle::EntryPoint entryPoint, 4418 ShaderProgramID program, 4419 GLsizei maxcount, 4420 const GLsizei *count, 4421 const ShaderProgramID *shaders) 4422 { 4423 if (maxcount < 0) 4424 { 4425 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeMaxCount); 4426 return false; 4427 } 4428 4429 Program *programObject = GetValidProgram(context, entryPoint, program); 4430 4431 if (!programObject) 4432 { 4433 return false; 4434 } 4435 4436 return true; 4437 } 4438 4439 bool ValidateGetAttribLocation(const Context *context, 4440 angle::EntryPoint entryPoint, 4441 ShaderProgramID program, 4442 const GLchar *name) 4443 { 4444 if (strncmp(name, "gl_", 3) == 0) 4445 { 4446 return false; 4447 } 4448 4449 if (context->isWebGL()) 4450 { 4451 const size_t length = strlen(name); 4452 4453 if (!IsValidESSLString(name, length)) 4454 { 4455 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters 4456 // for shader-related entry points 4457 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters); 4458 return false; 4459 } 4460 4461 if (!ValidateWebGLNameLength(context, entryPoint, length) || 4462 strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0) 4463 { 4464 return false; 4465 } 4466 } 4467 4468 Program *programObject = GetValidProgram(context, entryPoint, program); 4469 4470 if (!programObject) 4471 { 4472 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotBound); 4473 return false; 4474 } 4475 4476 if (!programObject->isLinked()) 4477 { 4478 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 4479 return false; 4480 } 4481 4482 return true; 4483 } 4484 4485 bool ValidateGetBooleanv(const Context *context, 4486 angle::EntryPoint entryPoint, 4487 GLenum pname, 4488 const GLboolean *params) 4489 { 4490 GLenum nativeType; 4491 unsigned int numParams = 0; 4492 return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); 4493 } 4494 4495 bool ValidateGetError(const Context *context, angle::EntryPoint entryPoint) 4496 { 4497 return true; 4498 } 4499 4500 bool ValidateGetFloatv(const Context *context, 4501 angle::EntryPoint entryPoint, 4502 GLenum pname, 4503 const GLfloat *params) 4504 { 4505 GLenum nativeType; 4506 unsigned int numParams = 0; 4507 return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); 4508 } 4509 4510 bool ValidateGetIntegerv(const Context *context, 4511 angle::EntryPoint entryPoint, 4512 GLenum pname, 4513 const GLint *params) 4514 { 4515 GLenum nativeType; 4516 unsigned int numParams = 0; 4517 return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams); 4518 } 4519 4520 bool ValidateGetProgramInfoLog(const Context *context, 4521 angle::EntryPoint entryPoint, 4522 ShaderProgramID program, 4523 GLsizei bufsize, 4524 const GLsizei *length, 4525 const GLchar *infolog) 4526 { 4527 if (bufsize < 0) 4528 { 4529 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 4530 return false; 4531 } 4532 4533 Program *programObject = GetValidProgram(context, entryPoint, program); 4534 if (!programObject) 4535 { 4536 return false; 4537 } 4538 4539 return true; 4540 } 4541 4542 bool ValidateGetShaderInfoLog(const Context *context, 4543 angle::EntryPoint entryPoint, 4544 ShaderProgramID shader, 4545 GLsizei bufsize, 4546 const GLsizei *length, 4547 const GLchar *infolog) 4548 { 4549 if (bufsize < 0) 4550 { 4551 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 4552 return false; 4553 } 4554 4555 Shader *shaderObject = GetValidShader(context, entryPoint, shader); 4556 if (!shaderObject) 4557 { 4558 return false; 4559 } 4560 4561 return true; 4562 } 4563 4564 bool ValidateGetShaderPrecisionFormat(const Context *context, 4565 angle::EntryPoint entryPoint, 4566 GLenum shadertype, 4567 GLenum precisiontype, 4568 const GLint *range, 4569 const GLint *precision) 4570 { 4571 switch (shadertype) 4572 { 4573 case GL_VERTEX_SHADER: 4574 case GL_FRAGMENT_SHADER: 4575 break; 4576 case GL_COMPUTE_SHADER: 4577 context->validationError(entryPoint, GL_INVALID_OPERATION, 4578 kUnimplementedComputeShaderPrecision); 4579 return false; 4580 default: 4581 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType); 4582 return false; 4583 } 4584 4585 switch (precisiontype) 4586 { 4587 case GL_LOW_FLOAT: 4588 case GL_MEDIUM_FLOAT: 4589 case GL_HIGH_FLOAT: 4590 case GL_LOW_INT: 4591 case GL_MEDIUM_INT: 4592 case GL_HIGH_INT: 4593 break; 4594 4595 default: 4596 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPrecision); 4597 return false; 4598 } 4599 4600 return true; 4601 } 4602 4603 bool ValidateGetShaderSource(const Context *context, 4604 angle::EntryPoint entryPoint, 4605 ShaderProgramID shader, 4606 GLsizei bufsize, 4607 const GLsizei *length, 4608 const GLchar *source) 4609 { 4610 if (bufsize < 0) 4611 { 4612 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 4613 return false; 4614 } 4615 4616 Shader *shaderObject = GetValidShader(context, entryPoint, shader); 4617 if (!shaderObject) 4618 { 4619 return false; 4620 } 4621 4622 return true; 4623 } 4624 4625 bool ValidateGetUniformLocation(const Context *context, 4626 angle::EntryPoint entryPoint, 4627 ShaderProgramID program, 4628 const GLchar *name) 4629 { 4630 if (strstr(name, "gl_") == name) 4631 { 4632 return false; 4633 } 4634 4635 // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for 4636 // shader-related entry points 4637 if (context->isWebGL() && !IsValidESSLString(name, strlen(name))) 4638 { 4639 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters); 4640 return false; 4641 } 4642 4643 Program *programObject = GetValidProgram(context, entryPoint, program); 4644 4645 if (!programObject) 4646 { 4647 return false; 4648 } 4649 4650 if (!programObject->isLinked()) 4651 { 4652 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 4653 return false; 4654 } 4655 4656 return true; 4657 } 4658 4659 bool ValidateHint(const Context *context, angle::EntryPoint entryPoint, GLenum target, GLenum mode) 4660 { 4661 switch (mode) 4662 { 4663 case GL_FASTEST: 4664 case GL_NICEST: 4665 case GL_DONT_CARE: 4666 break; 4667 4668 default: 4669 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode); 4670 return false; 4671 } 4672 4673 switch (target) 4674 { 4675 case GL_GENERATE_MIPMAP_HINT: 4676 break; 4677 4678 case GL_TEXTURE_FILTERING_HINT_CHROMIUM: 4679 if (!context->getExtensions().textureFilteringHintCHROMIUM) 4680 { 4681 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); 4682 return false; 4683 } 4684 break; 4685 4686 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT: 4687 if (context->getClientVersion() < ES_3_0 && 4688 !context->getExtensions().standardDerivativesOES) 4689 { 4690 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); 4691 return false; 4692 } 4693 break; 4694 4695 case GL_PERSPECTIVE_CORRECTION_HINT: 4696 case GL_POINT_SMOOTH_HINT: 4697 case GL_LINE_SMOOTH_HINT: 4698 case GL_FOG_HINT: 4699 if (context->getClientMajorVersion() >= 2) 4700 { 4701 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); 4702 return false; 4703 } 4704 break; 4705 4706 default: 4707 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target); 4708 return false; 4709 } 4710 4711 return true; 4712 } 4713 4714 bool ValidateIsBuffer(const Context *context, angle::EntryPoint entryPoint, BufferID buffer) 4715 { 4716 return true; 4717 } 4718 4719 bool ValidateIsFramebuffer(const Context *context, 4720 angle::EntryPoint entryPoint, 4721 FramebufferID framebuffer) 4722 { 4723 return true; 4724 } 4725 4726 bool ValidateIsProgram(const Context *context, 4727 angle::EntryPoint entryPoint, 4728 ShaderProgramID program) 4729 { 4730 return true; 4731 } 4732 4733 bool ValidateIsRenderbuffer(const Context *context, 4734 angle::EntryPoint entryPoint, 4735 RenderbufferID renderbuffer) 4736 { 4737 return true; 4738 } 4739 4740 bool ValidateIsShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID shader) 4741 { 4742 return true; 4743 } 4744 4745 bool ValidateIsTexture(const Context *context, angle::EntryPoint entryPoint, TextureID texture) 4746 { 4747 return true; 4748 } 4749 4750 bool ValidatePixelStorei(const Context *context, 4751 angle::EntryPoint entryPoint, 4752 GLenum pname, 4753 GLint param) 4754 { 4755 if (context->getClientMajorVersion() < 3) 4756 { 4757 switch (pname) 4758 { 4759 case GL_UNPACK_IMAGE_HEIGHT: 4760 case GL_UNPACK_SKIP_IMAGES: 4761 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 4762 return false; 4763 4764 case GL_UNPACK_ROW_LENGTH: 4765 case GL_UNPACK_SKIP_ROWS: 4766 case GL_UNPACK_SKIP_PIXELS: 4767 if (!context->getExtensions().unpackSubimageEXT) 4768 { 4769 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 4770 return false; 4771 } 4772 break; 4773 4774 case GL_PACK_ROW_LENGTH: 4775 case GL_PACK_SKIP_ROWS: 4776 case GL_PACK_SKIP_PIXELS: 4777 if (!context->getExtensions().packSubimageNV) 4778 { 4779 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 4780 return false; 4781 } 4782 break; 4783 } 4784 } 4785 4786 if (param < 0) 4787 { 4788 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeParam); 4789 return false; 4790 } 4791 4792 switch (pname) 4793 { 4794 case GL_UNPACK_ALIGNMENT: 4795 if (param != 1 && param != 2 && param != 4 && param != 8) 4796 { 4797 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidUnpackAlignment); 4798 return false; 4799 } 4800 break; 4801 4802 case GL_PACK_ALIGNMENT: 4803 if (param != 1 && param != 2 && param != 4 && param != 8) 4804 { 4805 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidUnpackAlignment); 4806 return false; 4807 } 4808 break; 4809 4810 case GL_PACK_REVERSE_ROW_ORDER_ANGLE: 4811 if (!context->getExtensions().packReverseRowOrderANGLE) 4812 { 4813 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 4814 } 4815 break; 4816 4817 case GL_UNPACK_ROW_LENGTH: 4818 case GL_UNPACK_IMAGE_HEIGHT: 4819 case GL_UNPACK_SKIP_IMAGES: 4820 case GL_UNPACK_SKIP_ROWS: 4821 case GL_UNPACK_SKIP_PIXELS: 4822 case GL_PACK_ROW_LENGTH: 4823 case GL_PACK_SKIP_ROWS: 4824 case GL_PACK_SKIP_PIXELS: 4825 break; 4826 4827 default: 4828 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname); 4829 return false; 4830 } 4831 4832 return true; 4833 } 4834 4835 bool ValidatePolygonOffset(const Context *context, 4836 angle::EntryPoint entryPoint, 4837 GLfloat factor, 4838 GLfloat units) 4839 { 4840 return true; 4841 } 4842 4843 bool ValidateReleaseShaderCompiler(const Context *context, angle::EntryPoint entryPoint) 4844 { 4845 return true; 4846 } 4847 4848 bool ValidateSampleCoverage(const Context *context, 4849 angle::EntryPoint entryPoint, 4850 GLfloat value, 4851 GLboolean invert) 4852 { 4853 return true; 4854 } 4855 4856 bool ValidateScissor(const Context *context, 4857 angle::EntryPoint entryPoint, 4858 GLint x, 4859 GLint y, 4860 GLsizei width, 4861 GLsizei height) 4862 { 4863 if (width < 0 || height < 0) 4864 { 4865 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize); 4866 return false; 4867 } 4868 4869 return true; 4870 } 4871 4872 bool ValidateShaderBinary(const Context *context, 4873 angle::EntryPoint entryPoint, 4874 GLsizei n, 4875 const ShaderProgramID *shaders, 4876 GLenum binaryformat, 4877 const void *binary, 4878 GLsizei length) 4879 { 4880 const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats; 4881 if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == 4882 shaderBinaryFormats.end()) 4883 { 4884 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderBinaryFormat); 4885 return false; 4886 } 4887 4888 return true; 4889 } 4890 4891 bool ValidateShaderSource(const Context *context, 4892 angle::EntryPoint entryPoint, 4893 ShaderProgramID shader, 4894 GLsizei count, 4895 const GLchar *const *string, 4896 const GLint *length) 4897 { 4898 if (count < 0) 4899 { 4900 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); 4901 return false; 4902 } 4903 4904 Shader *shaderObject = GetValidShader(context, entryPoint, shader); 4905 if (!shaderObject) 4906 { 4907 return false; 4908 } 4909 4910 return true; 4911 } 4912 4913 bool ValidateStencilFunc(const Context *context, 4914 angle::EntryPoint entryPoint, 4915 GLenum func, 4916 GLint ref, 4917 GLuint mask) 4918 { 4919 if (!IsValidStencilFunc(func)) 4920 { 4921 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4922 return false; 4923 } 4924 4925 return true; 4926 } 4927 4928 bool ValidateStencilFuncSeparate(const Context *context, 4929 angle::EntryPoint entryPoint, 4930 GLenum face, 4931 GLenum func, 4932 GLint ref, 4933 GLuint mask) 4934 { 4935 if (!IsValidStencilFace(face)) 4936 { 4937 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4938 return false; 4939 } 4940 4941 if (!IsValidStencilFunc(func)) 4942 { 4943 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4944 return false; 4945 } 4946 4947 return true; 4948 } 4949 4950 bool ValidateStencilMask(const Context *context, angle::EntryPoint entryPoint, GLuint mask) 4951 { 4952 return true; 4953 } 4954 4955 bool ValidateStencilMaskSeparate(const Context *context, 4956 angle::EntryPoint entryPoint, 4957 GLenum face, 4958 GLuint mask) 4959 { 4960 if (!IsValidStencilFace(face)) 4961 { 4962 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4963 return false; 4964 } 4965 4966 return true; 4967 } 4968 4969 bool ValidateStencilOp(const Context *context, 4970 angle::EntryPoint entryPoint, 4971 GLenum fail, 4972 GLenum zfail, 4973 GLenum zpass) 4974 { 4975 if (!IsValidStencilOp(fail)) 4976 { 4977 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4978 return false; 4979 } 4980 4981 if (!IsValidStencilOp(zfail)) 4982 { 4983 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4984 return false; 4985 } 4986 4987 if (!IsValidStencilOp(zpass)) 4988 { 4989 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 4990 return false; 4991 } 4992 4993 return true; 4994 } 4995 4996 bool ValidateStencilOpSeparate(const Context *context, 4997 angle::EntryPoint entryPoint, 4998 GLenum face, 4999 GLenum fail, 5000 GLenum zfail, 5001 GLenum zpass) 5002 { 5003 if (!IsValidStencilFace(face)) 5004 { 5005 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil); 5006 return false; 5007 } 5008 5009 return ValidateStencilOp(context, entryPoint, fail, zfail, zpass); 5010 } 5011 5012 bool ValidateUniform1f(const Context *context, 5013 angle::EntryPoint entryPoint, 5014 UniformLocation location, 5015 GLfloat x) 5016 { 5017 return ValidateUniform(context, entryPoint, GL_FLOAT, location, 1); 5018 } 5019 5020 bool ValidateUniform1fv(const Context *context, 5021 angle::EntryPoint entryPoint, 5022 UniformLocation location, 5023 GLsizei count, 5024 const GLfloat *v) 5025 { 5026 return ValidateUniform(context, entryPoint, GL_FLOAT, location, count); 5027 } 5028 5029 bool ValidateUniform1i(const Context *context, 5030 angle::EntryPoint entryPoint, 5031 UniformLocation location, 5032 GLint x) 5033 { 5034 return ValidateUniform1iv(context, entryPoint, location, 1, &x); 5035 } 5036 5037 bool ValidateUniform2fv(const Context *context, 5038 angle::EntryPoint entryPoint, 5039 UniformLocation location, 5040 GLsizei count, 5041 const GLfloat *v) 5042 { 5043 return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, count); 5044 } 5045 5046 bool ValidateUniform2i(const Context *context, 5047 angle::EntryPoint entryPoint, 5048 UniformLocation location, 5049 GLint x, 5050 GLint y) 5051 { 5052 return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, 1); 5053 } 5054 5055 bool ValidateUniform2iv(const Context *context, 5056 angle::EntryPoint entryPoint, 5057 UniformLocation location, 5058 GLsizei count, 5059 const GLint *v) 5060 { 5061 return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, count); 5062 } 5063 5064 bool ValidateUniform3f(const Context *context, 5065 angle::EntryPoint entryPoint, 5066 UniformLocation location, 5067 GLfloat x, 5068 GLfloat y, 5069 GLfloat z) 5070 { 5071 return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, 1); 5072 } 5073 5074 bool ValidateUniform3fv(const Context *context, 5075 angle::EntryPoint entryPoint, 5076 UniformLocation location, 5077 GLsizei count, 5078 const GLfloat *v) 5079 { 5080 return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, count); 5081 } 5082 5083 bool ValidateUniform3i(const Context *context, 5084 angle::EntryPoint entryPoint, 5085 UniformLocation location, 5086 GLint x, 5087 GLint y, 5088 GLint z) 5089 { 5090 return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, 1); 5091 } 5092 5093 bool ValidateUniform3iv(const Context *context, 5094 angle::EntryPoint entryPoint, 5095 UniformLocation location, 5096 GLsizei count, 5097 const GLint *v) 5098 { 5099 return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, count); 5100 } 5101 5102 bool ValidateUniform4f(const Context *context, 5103 angle::EntryPoint entryPoint, 5104 UniformLocation location, 5105 GLfloat x, 5106 GLfloat y, 5107 GLfloat z, 5108 GLfloat w) 5109 { 5110 return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, 1); 5111 } 5112 5113 bool ValidateUniform4fv(const Context *context, 5114 angle::EntryPoint entryPoint, 5115 UniformLocation location, 5116 GLsizei count, 5117 const GLfloat *v) 5118 { 5119 return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, count); 5120 } 5121 5122 bool ValidateUniform4i(const Context *context, 5123 angle::EntryPoint entryPoint, 5124 UniformLocation location, 5125 GLint x, 5126 GLint y, 5127 GLint z, 5128 GLint w) 5129 { 5130 return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, 1); 5131 } 5132 5133 bool ValidateUniform4iv(const Context *context, 5134 angle::EntryPoint entryPoint, 5135 UniformLocation location, 5136 GLsizei count, 5137 const GLint *v) 5138 { 5139 return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, count); 5140 } 5141 5142 bool ValidateUniformMatrix2fv(const Context *context, 5143 angle::EntryPoint entryPoint, 5144 UniformLocation location, 5145 GLsizei count, 5146 GLboolean transpose, 5147 const GLfloat *value) 5148 { 5149 return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT2, location, count, transpose); 5150 } 5151 5152 bool ValidateUniformMatrix3fv(const Context *context, 5153 angle::EntryPoint entryPoint, 5154 UniformLocation location, 5155 GLsizei count, 5156 GLboolean transpose, 5157 const GLfloat *value) 5158 { 5159 return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT3, location, count, transpose); 5160 } 5161 5162 bool ValidateUniformMatrix4fv(const Context *context, 5163 angle::EntryPoint entryPoint, 5164 UniformLocation location, 5165 GLsizei count, 5166 GLboolean transpose, 5167 const GLfloat *value) 5168 { 5169 return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT4, location, count, transpose); 5170 } 5171 5172 bool ValidateValidateProgram(const Context *context, 5173 angle::EntryPoint entryPoint, 5174 ShaderProgramID program) 5175 { 5176 Program *programObject = GetValidProgram(context, entryPoint, program); 5177 5178 if (!programObject) 5179 { 5180 return false; 5181 } 5182 5183 return true; 5184 } 5185 5186 bool ValidateVertexAttrib1f(const Context *context, 5187 angle::EntryPoint entryPoint, 5188 GLuint index, 5189 GLfloat x) 5190 { 5191 return ValidateVertexAttribIndex(context, entryPoint, index); 5192 } 5193 5194 bool ValidateVertexAttrib1fv(const Context *context, 5195 angle::EntryPoint entryPoint, 5196 GLuint index, 5197 const GLfloat *values) 5198 { 5199 return ValidateVertexAttribIndex(context, entryPoint, index); 5200 } 5201 5202 bool ValidateVertexAttrib2f(const Context *context, 5203 angle::EntryPoint entryPoint, 5204 GLuint index, 5205 GLfloat x, 5206 GLfloat y) 5207 { 5208 return ValidateVertexAttribIndex(context, entryPoint, index); 5209 } 5210 5211 bool ValidateVertexAttrib2fv(const Context *context, 5212 angle::EntryPoint entryPoint, 5213 GLuint index, 5214 const GLfloat *values) 5215 { 5216 return ValidateVertexAttribIndex(context, entryPoint, index); 5217 } 5218 5219 bool ValidateVertexAttrib3f(const Context *context, 5220 angle::EntryPoint entryPoint, 5221 GLuint index, 5222 GLfloat x, 5223 GLfloat y, 5224 GLfloat z) 5225 { 5226 return ValidateVertexAttribIndex(context, entryPoint, index); 5227 } 5228 5229 bool ValidateVertexAttrib3fv(const Context *context, 5230 angle::EntryPoint entryPoint, 5231 GLuint index, 5232 const GLfloat *values) 5233 { 5234 return ValidateVertexAttribIndex(context, entryPoint, index); 5235 } 5236 5237 bool ValidateVertexAttrib4f(const Context *context, 5238 angle::EntryPoint entryPoint, 5239 GLuint index, 5240 GLfloat x, 5241 GLfloat y, 5242 GLfloat z, 5243 GLfloat w) 5244 { 5245 return ValidateVertexAttribIndex(context, entryPoint, index); 5246 } 5247 5248 bool ValidateVertexAttrib4fv(const Context *context, 5249 angle::EntryPoint entryPoint, 5250 GLuint index, 5251 const GLfloat *values) 5252 { 5253 return ValidateVertexAttribIndex(context, entryPoint, index); 5254 } 5255 5256 bool ValidateViewport(const Context *context, 5257 angle::EntryPoint entryPoint, 5258 GLint x, 5259 GLint y, 5260 GLsizei width, 5261 GLsizei height) 5262 { 5263 if (width < 0 || height < 0) 5264 { 5265 context->validationError(entryPoint, GL_INVALID_VALUE, kViewportNegativeSize); 5266 return false; 5267 } 5268 5269 return true; 5270 } 5271 5272 bool ValidateGetFramebufferAttachmentParameteriv(const Context *context, 5273 angle::EntryPoint entryPoint, 5274 GLenum target, 5275 GLenum attachment, 5276 GLenum pname, 5277 const GLint *params) 5278 { 5279 return ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment, 5280 pname, nullptr); 5281 } 5282 5283 bool ValidateGetProgramiv(const Context *context, 5284 angle::EntryPoint entryPoint, 5285 ShaderProgramID program, 5286 GLenum pname, 5287 const GLint *params) 5288 { 5289 return ValidateGetProgramivBase(context, entryPoint, program, pname, nullptr); 5290 } 5291 5292 bool ValidateCopyTexImage2D(const Context *context, 5293 angle::EntryPoint entryPoint, 5294 TextureTarget target, 5295 GLint level, 5296 GLenum internalformat, 5297 GLint x, 5298 GLint y, 5299 GLsizei width, 5300 GLsizei height, 5301 GLint border) 5302 { 5303 if (context->getClientMajorVersion() < 3) 5304 { 5305 return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, internalformat, 5306 false, 0, 0, x, y, width, height, border); 5307 } 5308 5309 ASSERT(context->getClientMajorVersion() == 3); 5310 return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, internalformat, 5311 false, 0, 0, 0, x, y, width, height, border); 5312 } 5313 5314 bool ValidateCopyTexSubImage2D(const Context *context, 5315 angle::EntryPoint entryPoint, 5316 TextureTarget target, 5317 GLint level, 5318 GLint xoffset, 5319 GLint yoffset, 5320 GLint x, 5321 GLint y, 5322 GLsizei width, 5323 GLsizei height) 5324 { 5325 if (context->getClientMajorVersion() < 3) 5326 { 5327 return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, GL_NONE, true, 5328 xoffset, yoffset, x, y, width, height, 0); 5329 } 5330 5331 return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, GL_NONE, true, 5332 xoffset, yoffset, 0, x, y, width, height, 0); 5333 } 5334 5335 bool ValidateCopyTexSubImage3DOES(const Context *context, 5336 angle::EntryPoint entryPoint, 5337 TextureTarget target, 5338 GLint level, 5339 GLint xoffset, 5340 GLint yoffset, 5341 GLint zoffset, 5342 GLint x, 5343 GLint y, 5344 GLsizei width, 5345 GLsizei height) 5346 { 5347 return ValidateCopyTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset, 5348 x, y, width, height); 5349 } 5350 5351 bool ValidateDeleteBuffers(const Context *context, 5352 angle::EntryPoint entryPoint, 5353 GLint n, 5354 const BufferID *buffers) 5355 { 5356 return ValidateGenOrDelete(context, entryPoint, n); 5357 } 5358 5359 bool ValidateDeleteFramebuffers(const Context *context, 5360 angle::EntryPoint entryPoint, 5361 GLint n, 5362 const FramebufferID *framebuffers) 5363 { 5364 return ValidateGenOrDelete(context, entryPoint, n); 5365 } 5366 5367 bool ValidateDeleteRenderbuffers(const Context *context, 5368 angle::EntryPoint entryPoint, 5369 GLint n, 5370 const RenderbufferID *renderbuffers) 5371 { 5372 return ValidateGenOrDelete(context, entryPoint, n); 5373 } 5374 5375 bool ValidateDeleteTextures(const Context *context, 5376 angle::EntryPoint entryPoint, 5377 GLint n, 5378 const TextureID *textures) 5379 { 5380 return ValidateGenOrDelete(context, entryPoint, n); 5381 } 5382 5383 bool ValidateDisable(const Context *context, angle::EntryPoint entryPoint, GLenum cap) 5384 { 5385 if (!ValidCap(context, cap, false)) 5386 { 5387 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap); 5388 return false; 5389 } 5390 5391 return true; 5392 } 5393 5394 bool ValidateEnable(const Context *context, angle::EntryPoint entryPoint, GLenum cap) 5395 { 5396 if (!ValidCap(context, cap, false)) 5397 { 5398 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap); 5399 return false; 5400 } 5401 5402 if (context->getLimitations().noSampleAlphaToCoverageSupport && 5403 cap == GL_SAMPLE_ALPHA_TO_COVERAGE) 5404 { 5405 context->validationError(entryPoint, GL_INVALID_OPERATION, 5406 kNoSampleAlphaToCoveragesLimitation); 5407 5408 // We also output an error message to the debugger window if tracing is active, so that 5409 // developers can see the error message. 5410 ERR() << kNoSampleAlphaToCoveragesLimitation; 5411 return false; 5412 } 5413 5414 return true; 5415 } 5416 5417 bool ValidateFramebufferRenderbuffer(const Context *context, 5418 angle::EntryPoint entryPoint, 5419 GLenum target, 5420 GLenum attachment, 5421 GLenum renderbuffertarget, 5422 RenderbufferID renderbuffer) 5423 { 5424 return ValidateFramebufferRenderbufferBase(context, entryPoint, target, attachment, 5425 renderbuffertarget, renderbuffer); 5426 } 5427 5428 bool ValidateFramebufferTexture2D(const Context *context, 5429 angle::EntryPoint entryPoint, 5430 GLenum target, 5431 GLenum attachment, 5432 TextureTarget textarget, 5433 TextureID texture, 5434 GLint level) 5435 { 5436 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap 5437 // extension 5438 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES && 5439 level != 0) 5440 { 5441 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel); 5442 return false; 5443 } 5444 5445 if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level)) 5446 { 5447 return false; 5448 } 5449 5450 if (texture.value != 0) 5451 { 5452 Texture *tex = context->getTexture(texture); 5453 ASSERT(tex); 5454 5455 const Caps &caps = context->getCaps(); 5456 5457 switch (textarget) 5458 { 5459 case TextureTarget::_2D: 5460 { 5461 if (level > log2(caps.max2DTextureSize)) 5462 { 5463 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 5464 return false; 5465 } 5466 if (tex->getType() != TextureType::_2D) 5467 { 5468 context->validationError(entryPoint, GL_INVALID_OPERATION, 5469 kInvalidTextureTarget); 5470 return false; 5471 } 5472 } 5473 break; 5474 5475 case TextureTarget::Rectangle: 5476 { 5477 if (level != 0) 5478 { 5479 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 5480 return false; 5481 } 5482 if (tex->getType() != TextureType::Rectangle) 5483 { 5484 context->validationError(entryPoint, GL_INVALID_OPERATION, 5485 kTextureTargetMismatch); 5486 return false; 5487 } 5488 } 5489 break; 5490 5491 case TextureTarget::CubeMapNegativeX: 5492 case TextureTarget::CubeMapNegativeY: 5493 case TextureTarget::CubeMapNegativeZ: 5494 case TextureTarget::CubeMapPositiveX: 5495 case TextureTarget::CubeMapPositiveY: 5496 case TextureTarget::CubeMapPositiveZ: 5497 { 5498 if (level > log2(caps.maxCubeMapTextureSize)) 5499 { 5500 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 5501 return false; 5502 } 5503 if (tex->getType() != TextureType::CubeMap) 5504 { 5505 context->validationError(entryPoint, GL_INVALID_OPERATION, 5506 kTextureTargetMismatch); 5507 return false; 5508 } 5509 } 5510 break; 5511 5512 case TextureTarget::_2DMultisample: 5513 { 5514 if (context->getClientVersion() < ES_3_1 && 5515 !context->getExtensions().textureMultisampleANGLE) 5516 { 5517 context->validationError(entryPoint, GL_INVALID_OPERATION, 5518 kMultisampleTextureExtensionOrES31Required); 5519 return false; 5520 } 5521 5522 if (level != 0) 5523 { 5524 context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero); 5525 return false; 5526 } 5527 if (tex->getType() != TextureType::_2DMultisample) 5528 { 5529 context->validationError(entryPoint, GL_INVALID_OPERATION, 5530 kTextureTargetMismatch); 5531 return false; 5532 } 5533 } 5534 break; 5535 5536 case TextureTarget::External: 5537 { 5538 if (!context->getExtensions().YUVTargetEXT) 5539 { 5540 context->validationError(entryPoint, GL_INVALID_OPERATION, 5541 kYUVTargetExtensionRequired); 5542 return false; 5543 } 5544 5545 if (attachment != GL_COLOR_ATTACHMENT0) 5546 { 5547 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment); 5548 return false; 5549 } 5550 5551 if (tex->getType() != TextureType::External) 5552 { 5553 context->validationError(entryPoint, GL_INVALID_OPERATION, 5554 kTextureTargetMismatch); 5555 return false; 5556 } 5557 } 5558 break; 5559 5560 default: 5561 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 5562 return false; 5563 } 5564 } 5565 5566 return true; 5567 } 5568 5569 bool ValidateFramebufferTexture3DOES(const Context *context, 5570 angle::EntryPoint entryPoint, 5571 GLenum target, 5572 GLenum attachment, 5573 TextureTarget textargetPacked, 5574 TextureID texture, 5575 GLint level, 5576 GLint zoffset) 5577 { 5578 // We don't call into a base ValidateFramebufferTexture3D here because 5579 // it doesn't exist for OpenGL ES. This function is replaced by 5580 // FramebufferTextureLayer in ES 3.x, which has broader support. 5581 if (!context->getExtensions().texture3DOES) 5582 { 5583 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 5584 return false; 5585 } 5586 5587 // Attachments are required to be bound to level 0 without ES3 or the 5588 // GL_OES_fbo_render_mipmap extension 5589 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES && 5590 level != 0) 5591 { 5592 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel); 5593 return false; 5594 } 5595 5596 if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level)) 5597 { 5598 return false; 5599 } 5600 5601 if (texture.value != 0) 5602 { 5603 Texture *tex = context->getTexture(texture); 5604 ASSERT(tex); 5605 5606 const Caps &caps = context->getCaps(); 5607 5608 switch (textargetPacked) 5609 { 5610 case TextureTarget::_3D: 5611 { 5612 if (level > log2(caps.max3DTextureSize)) 5613 { 5614 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel); 5615 return false; 5616 } 5617 if (zoffset >= caps.max3DTextureSize) 5618 { 5619 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidZOffset); 5620 return false; 5621 } 5622 if (tex->getType() != TextureType::_3D) 5623 { 5624 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureType); 5625 return false; 5626 } 5627 } 5628 break; 5629 5630 default: 5631 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget); 5632 return false; 5633 } 5634 } 5635 5636 return true; 5637 } 5638 5639 bool ValidateGenBuffers(const Context *context, 5640 angle::EntryPoint entryPoint, 5641 GLint n, 5642 const BufferID *buffers) 5643 { 5644 return ValidateGenOrDelete(context, entryPoint, n); 5645 } 5646 5647 bool ValidateGenFramebuffers(const Context *context, 5648 angle::EntryPoint entryPoint, 5649 GLint n, 5650 const FramebufferID *framebuffers) 5651 { 5652 return ValidateGenOrDelete(context, entryPoint, n); 5653 } 5654 5655 bool ValidateGenRenderbuffers(const Context *context, 5656 angle::EntryPoint entryPoint, 5657 GLint n, 5658 const RenderbufferID *renderbuffers) 5659 { 5660 return ValidateGenOrDelete(context, entryPoint, n); 5661 } 5662 5663 bool ValidateGenTextures(const Context *context, 5664 angle::EntryPoint entryPoint, 5665 GLint n, 5666 const TextureID *textures) 5667 { 5668 return ValidateGenOrDelete(context, entryPoint, n); 5669 } 5670 5671 bool ValidateGenerateMipmap(const Context *context, 5672 angle::EntryPoint entryPoint, 5673 TextureType target) 5674 { 5675 return ValidateGenerateMipmapBase(context, entryPoint, target); 5676 } 5677 5678 bool ValidateGetBufferParameteriv(const Context *context, 5679 angle::EntryPoint entryPoint, 5680 BufferBinding target, 5681 GLenum pname, 5682 const GLint *params) 5683 { 5684 return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr); 5685 } 5686 5687 bool ValidateGetRenderbufferParameteriv(const Context *context, 5688 angle::EntryPoint entryPoint, 5689 GLenum target, 5690 GLenum pname, 5691 const GLint *params) 5692 { 5693 return ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, nullptr); 5694 } 5695 5696 bool ValidateGetShaderiv(const Context *context, 5697 angle::EntryPoint entryPoint, 5698 ShaderProgramID shader, 5699 GLenum pname, 5700 const GLint *params) 5701 { 5702 return ValidateGetShaderivBase(context, entryPoint, shader, pname, nullptr); 5703 } 5704 5705 bool ValidateGetTexParameterfv(const Context *context, 5706 angle::EntryPoint entryPoint, 5707 TextureType target, 5708 GLenum pname, 5709 const GLfloat *params) 5710 { 5711 return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); 5712 } 5713 5714 bool ValidateGetTexParameteriv(const Context *context, 5715 angle::EntryPoint entryPoint, 5716 TextureType target, 5717 GLenum pname, 5718 const GLint *params) 5719 { 5720 return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); 5721 } 5722 5723 bool ValidateGetTexParameterIivOES(const Context *context, 5724 angle::EntryPoint entryPoint, 5725 TextureType target, 5726 GLenum pname, 5727 const GLint *params) 5728 { 5729 if (context->getClientMajorVersion() < 3) 5730 { 5731 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 5732 return false; 5733 } 5734 return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); 5735 } 5736 5737 bool ValidateGetTexParameterIuivOES(const Context *context, 5738 angle::EntryPoint entryPoint, 5739 TextureType target, 5740 GLenum pname, 5741 const GLuint *params) 5742 { 5743 if (context->getClientMajorVersion() < 3) 5744 { 5745 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 5746 return false; 5747 } 5748 return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr); 5749 } 5750 5751 bool ValidateGetUniformfv(const Context *context, 5752 angle::EntryPoint entryPoint, 5753 ShaderProgramID program, 5754 UniformLocation location, 5755 const GLfloat *params) 5756 { 5757 return ValidateGetUniformBase(context, entryPoint, program, location); 5758 } 5759 5760 bool ValidateGetUniformiv(const Context *context, 5761 angle::EntryPoint entryPoint, 5762 ShaderProgramID program, 5763 UniformLocation location, 5764 const GLint *params) 5765 { 5766 return ValidateGetUniformBase(context, entryPoint, program, location); 5767 } 5768 5769 bool ValidateGetVertexAttribfv(const Context *context, 5770 angle::EntryPoint entryPoint, 5771 GLuint index, 5772 GLenum pname, 5773 const GLfloat *params) 5774 { 5775 return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false); 5776 } 5777 5778 bool ValidateGetVertexAttribiv(const Context *context, 5779 angle::EntryPoint entryPoint, 5780 GLuint index, 5781 GLenum pname, 5782 const GLint *params) 5783 { 5784 return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false); 5785 } 5786 5787 bool ValidateGetVertexAttribPointerv(const Context *context, 5788 angle::EntryPoint entryPoint, 5789 GLuint index, 5790 GLenum pname, 5791 void *const *pointer) 5792 { 5793 return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, true, false); 5794 } 5795 5796 bool ValidateIsEnabled(const Context *context, angle::EntryPoint entryPoint, GLenum cap) 5797 { 5798 if (!ValidCap(context, cap, true)) 5799 { 5800 context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap); 5801 return false; 5802 } 5803 5804 return true; 5805 } 5806 5807 bool ValidateLinkProgram(const Context *context, 5808 angle::EntryPoint entryPoint, 5809 ShaderProgramID program) 5810 { 5811 if (context->hasActiveTransformFeedback(program)) 5812 { 5813 // ES 3.0.4 section 2.15 page 91 5814 context->validationError(entryPoint, GL_INVALID_OPERATION, 5815 kTransformFeedbackActiveDuringLink); 5816 return false; 5817 } 5818 5819 Program *programObject = GetValidProgram(context, entryPoint, program); 5820 if (!programObject) 5821 { 5822 return false; 5823 } 5824 5825 return true; 5826 } 5827 5828 bool ValidateReadPixels(const Context *context, 5829 angle::EntryPoint entryPoint, 5830 GLint x, 5831 GLint y, 5832 GLsizei width, 5833 GLsizei height, 5834 GLenum format, 5835 GLenum type, 5836 const void *pixels) 5837 { 5838 return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, -1, 5839 nullptr, nullptr, nullptr, pixels); 5840 } 5841 5842 bool ValidateTexParameterf(const Context *context, 5843 angle::EntryPoint entryPoint, 5844 TextureType target, 5845 GLenum pname, 5846 GLfloat param) 5847 { 5848 return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, ¶m); 5849 } 5850 5851 bool ValidateTexParameterfv(const Context *context, 5852 angle::EntryPoint entryPoint, 5853 TextureType target, 5854 GLenum pname, 5855 const GLfloat *params) 5856 { 5857 return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params); 5858 } 5859 5860 bool ValidateTexParameteri(const Context *context, 5861 angle::EntryPoint entryPoint, 5862 TextureType target, 5863 GLenum pname, 5864 GLint param) 5865 { 5866 return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, ¶m); 5867 } 5868 5869 bool ValidateTexParameteriv(const Context *context, 5870 angle::EntryPoint entryPoint, 5871 TextureType target, 5872 GLenum pname, 5873 const GLint *params) 5874 { 5875 return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params); 5876 } 5877 5878 bool ValidateTexParameterIivOES(const Context *context, 5879 angle::EntryPoint entryPoint, 5880 TextureType target, 5881 GLenum pname, 5882 const GLint *params) 5883 { 5884 if (context->getClientMajorVersion() < 3) 5885 { 5886 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 5887 return false; 5888 } 5889 return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params); 5890 } 5891 5892 bool ValidateTexParameterIuivOES(const Context *context, 5893 angle::EntryPoint entryPoint, 5894 TextureType target, 5895 GLenum pname, 5896 const GLuint *params) 5897 { 5898 if (context->getClientMajorVersion() < 3) 5899 { 5900 context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required); 5901 return false; 5902 } 5903 return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params); 5904 } 5905 5906 bool ValidateUseProgram(const Context *context, 5907 angle::EntryPoint entryPoint, 5908 ShaderProgramID program) 5909 { 5910 if (program.value != 0) 5911 { 5912 Program *programObject = context->getProgramResolveLink(program); 5913 if (!programObject) 5914 { 5915 // ES 3.1.0 section 7.3 page 72 5916 if (context->getShader(program)) 5917 { 5918 context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName); 5919 return false; 5920 } 5921 else 5922 { 5923 context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName); 5924 return false; 5925 } 5926 } 5927 if (!programObject->isLinked()) 5928 { 5929 context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked); 5930 return false; 5931 } 5932 } 5933 if (context->getState().isTransformFeedbackActiveUnpaused()) 5934 { 5935 // ES 3.0.4 section 2.15 page 91 5936 context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackUseProgram); 5937 return false; 5938 } 5939 5940 return true; 5941 } 5942 5943 bool ValidateDeleteFencesNV(const Context *context, 5944 angle::EntryPoint entryPoint, 5945 GLsizei n, 5946 const FenceNVID *fences) 5947 { 5948 if (!context->getExtensions().fenceNV) 5949 { 5950 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 5951 return false; 5952 } 5953 5954 if (n < 0) 5955 { 5956 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); 5957 return false; 5958 } 5959 5960 return true; 5961 } 5962 5963 bool ValidateFinishFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence) 5964 { 5965 if (!context->getExtensions().fenceNV) 5966 { 5967 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 5968 return false; 5969 } 5970 5971 FenceNV *fenceObject = context->getFenceNV(fence); 5972 5973 if (fenceObject == nullptr) 5974 { 5975 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence); 5976 return false; 5977 } 5978 5979 if (!fenceObject->isSet()) 5980 { 5981 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState); 5982 return false; 5983 } 5984 5985 return true; 5986 } 5987 5988 bool ValidateGenFencesNV(const Context *context, 5989 angle::EntryPoint entryPoint, 5990 GLsizei n, 5991 const FenceNVID *fences) 5992 { 5993 if (!context->getExtensions().fenceNV) 5994 { 5995 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 5996 return false; 5997 } 5998 5999 if (n < 0) 6000 { 6001 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount); 6002 return false; 6003 } 6004 6005 return true; 6006 } 6007 6008 bool ValidateGetFenceivNV(const Context *context, 6009 angle::EntryPoint entryPoint, 6010 FenceNVID fence, 6011 GLenum pname, 6012 const GLint *params) 6013 { 6014 if (!context->getExtensions().fenceNV) 6015 { 6016 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 6017 return false; 6018 } 6019 6020 FenceNV *fenceObject = context->getFenceNV(fence); 6021 6022 if (fenceObject == nullptr) 6023 { 6024 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence); 6025 return false; 6026 } 6027 6028 if (!fenceObject->isSet()) 6029 { 6030 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState); 6031 return false; 6032 } 6033 6034 switch (pname) 6035 { 6036 case GL_FENCE_STATUS_NV: 6037 case GL_FENCE_CONDITION_NV: 6038 break; 6039 6040 default: 6041 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname); 6042 return false; 6043 } 6044 6045 return true; 6046 } 6047 6048 bool ValidateGetGraphicsResetStatusEXT(const Context *context, angle::EntryPoint entryPoint) 6049 { 6050 if (!context->getExtensions().robustnessEXT) 6051 { 6052 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6053 return false; 6054 } 6055 6056 return true; 6057 } 6058 6059 bool ValidateGetTranslatedShaderSourceANGLE(const Context *context, 6060 angle::EntryPoint entryPoint, 6061 ShaderProgramID shader, 6062 GLsizei bufsize, 6063 const GLsizei *length, 6064 const GLchar *source) 6065 { 6066 if (!context->getExtensions().translatedShaderSourceANGLE) 6067 { 6068 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6069 return false; 6070 } 6071 6072 if (bufsize < 0) 6073 { 6074 context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize); 6075 return false; 6076 } 6077 6078 Shader *shaderObject = context->getShader(shader); 6079 6080 if (!shaderObject) 6081 { 6082 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName); 6083 return false; 6084 } 6085 6086 return true; 6087 } 6088 6089 bool ValidateIsFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence) 6090 { 6091 if (!context->getExtensions().fenceNV) 6092 { 6093 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 6094 return false; 6095 } 6096 6097 return true; 6098 } 6099 6100 bool ValidateSetFenceNV(const Context *context, 6101 angle::EntryPoint entryPoint, 6102 FenceNVID fence, 6103 GLenum condition) 6104 { 6105 if (!context->getExtensions().fenceNV) 6106 { 6107 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 6108 return false; 6109 } 6110 6111 if (condition != GL_ALL_COMPLETED_NV) 6112 { 6113 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFenceCondition); 6114 return false; 6115 } 6116 6117 FenceNV *fenceObject = context->getFenceNV(fence); 6118 6119 if (fenceObject == nullptr) 6120 { 6121 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence); 6122 return false; 6123 } 6124 6125 return true; 6126 } 6127 6128 bool ValidateTestFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence) 6129 { 6130 if (!context->getExtensions().fenceNV) 6131 { 6132 context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported); 6133 return false; 6134 } 6135 6136 FenceNV *fenceObject = context->getFenceNV(fence); 6137 6138 if (fenceObject == nullptr) 6139 { 6140 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence); 6141 return false; 6142 } 6143 6144 if (fenceObject->isSet() != GL_TRUE) 6145 { 6146 context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState); 6147 return false; 6148 } 6149 6150 return true; 6151 } 6152 6153 bool ValidateTexStorage2DEXT(const Context *context, 6154 angle::EntryPoint entryPoint, 6155 TextureType type, 6156 GLsizei levels, 6157 GLenum internalformat, 6158 GLsizei width, 6159 GLsizei height) 6160 { 6161 if (!context->getExtensions().textureStorageEXT) 6162 { 6163 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6164 return false; 6165 } 6166 6167 if (context->getClientMajorVersion() < 3) 6168 { 6169 return ValidateES2TexStorageParametersBase(context, entryPoint, type, levels, 6170 internalformat, width, height); 6171 } 6172 6173 ASSERT(context->getClientMajorVersion() >= 3); 6174 return ValidateES3TexStorage2DParameters(context, entryPoint, type, levels, internalformat, 6175 width, height, 1); 6176 } 6177 6178 bool ValidateVertexAttribDivisorANGLE(const Context *context, 6179 angle::EntryPoint entryPoint, 6180 GLuint index, 6181 GLuint divisor) 6182 { 6183 if (!context->getExtensions().instancedArraysANGLE) 6184 { 6185 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6186 return false; 6187 } 6188 6189 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 6190 { 6191 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); 6192 return false; 6193 } 6194 6195 if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT) 6196 { 6197 if (index == 0 && divisor != 0) 6198 { 6199 context->validationError(entryPoint, GL_INVALID_OPERATION, 6200 kAttributeZeroRequiresDivisorLimitation); 6201 6202 // We also output an error message to the debugger window if tracing is active, so 6203 // that developers can see the error message. 6204 ERR() << kAttributeZeroRequiresDivisorLimitation; 6205 return false; 6206 } 6207 } 6208 6209 return true; 6210 } 6211 6212 bool ValidateVertexAttribDivisorEXT(const Context *context, 6213 angle::EntryPoint entryPoint, 6214 GLuint index, 6215 GLuint divisor) 6216 { 6217 if (!context->getExtensions().instancedArraysEXT) 6218 { 6219 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6220 return false; 6221 } 6222 6223 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 6224 { 6225 context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute); 6226 return false; 6227 } 6228 6229 return true; 6230 } 6231 6232 bool ValidateTexImage3DOES(const Context *context, 6233 angle::EntryPoint entryPoint, 6234 TextureTarget target, 6235 GLint level, 6236 GLenum internalformat, 6237 GLsizei width, 6238 GLsizei height, 6239 GLsizei depth, 6240 GLint border, 6241 GLenum format, 6242 GLenum type, 6243 const void *pixels) 6244 { 6245 return ValidateTexImage3D(context, entryPoint, target, level, internalformat, width, height, 6246 depth, border, format, type, pixels); 6247 } 6248 6249 bool ValidatePopGroupMarkerEXT(const Context *context, angle::EntryPoint entryPoint) 6250 { 6251 if (!context->getExtensions().debugMarkerEXT) 6252 { 6253 // The debug marker calls should not set error state 6254 // However, it seems reasonable to set an error state if the extension is not enabled 6255 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6256 return false; 6257 } 6258 6259 return true; 6260 } 6261 6262 bool ValidateTexStorage1DEXT(const Context *context, 6263 angle::EntryPoint entryPoint, 6264 GLenum target, 6265 GLsizei levels, 6266 GLenum internalformat, 6267 GLsizei width) 6268 { 6269 UNIMPLEMENTED(); 6270 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6271 return false; 6272 } 6273 6274 bool ValidateTexStorage3DEXT(const Context *context, 6275 angle::EntryPoint entryPoint, 6276 TextureType target, 6277 GLsizei levels, 6278 GLenum internalformat, 6279 GLsizei width, 6280 GLsizei height, 6281 GLsizei depth) 6282 { 6283 if (!context->getExtensions().textureStorageEXT) 6284 { 6285 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6286 return false; 6287 } 6288 6289 if (context->getClientMajorVersion() < 3) 6290 { 6291 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6292 return false; 6293 } 6294 6295 return ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat, 6296 width, height, depth); 6297 } 6298 6299 bool ValidateMaxShaderCompilerThreadsKHR(const Context *context, 6300 angle::EntryPoint entryPoint, 6301 GLuint count) 6302 { 6303 if (!context->getExtensions().parallelShaderCompileKHR) 6304 { 6305 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6306 return false; 6307 } 6308 return true; 6309 } 6310 6311 bool ValidateMultiDrawArraysANGLE(const Context *context, 6312 angle::EntryPoint entryPoint, 6313 PrimitiveMode mode, 6314 const GLint *firsts, 6315 const GLsizei *counts, 6316 GLsizei drawcount) 6317 { 6318 if (!context->getExtensions().multiDrawANGLE) 6319 { 6320 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6321 return false; 6322 } 6323 for (GLsizei drawID = 0; drawID < drawcount; ++drawID) 6324 { 6325 if (!ValidateDrawArrays(context, entryPoint, mode, firsts[drawID], counts[drawID])) 6326 { 6327 return false; 6328 } 6329 } 6330 return true; 6331 } 6332 6333 bool ValidateMultiDrawElementsANGLE(const Context *context, 6334 angle::EntryPoint entryPoint, 6335 PrimitiveMode mode, 6336 const GLsizei *counts, 6337 DrawElementsType type, 6338 const GLvoid *const *indices, 6339 GLsizei drawcount) 6340 { 6341 if (!context->getExtensions().multiDrawANGLE) 6342 { 6343 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6344 return false; 6345 } 6346 for (GLsizei drawID = 0; drawID < drawcount; ++drawID) 6347 { 6348 if (!ValidateDrawElements(context, entryPoint, mode, counts[drawID], type, indices[drawID])) 6349 { 6350 return false; 6351 } 6352 } 6353 return true; 6354 } 6355 6356 bool ValidateProvokingVertexANGLE(const Context *context, 6357 angle::EntryPoint entryPoint, 6358 ProvokingVertexConvention modePacked) 6359 { 6360 if (!context->getExtensions().provokingVertexANGLE) 6361 { 6362 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6363 return false; 6364 } 6365 6366 switch (modePacked) 6367 { 6368 case ProvokingVertexConvention::FirstVertexConvention: 6369 case ProvokingVertexConvention::LastVertexConvention: 6370 break; 6371 default: 6372 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProvokingVertex); 6373 return false; 6374 } 6375 6376 return true; 6377 } 6378 6379 bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context, 6380 angle::EntryPoint entryPoint, 6381 GLenum target, 6382 GLenum attachment, 6383 TextureTarget textarget, 6384 TextureID texture, 6385 GLint level, 6386 GLsizei samples) 6387 { 6388 if (!context->getExtensions().multisampledRenderToTextureEXT) 6389 { 6390 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6391 return false; 6392 } 6393 6394 if (samples < 0) 6395 { 6396 return false; 6397 } 6398 6399 // EXT_multisampled_render_to_texture states that the value of samples 6400 // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples) 6401 // otherwise GL_INVALID_VALUE is generated. 6402 if (samples > context->getCaps().maxSamples) 6403 { 6404 context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange); 6405 return false; 6406 } 6407 6408 if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level)) 6409 { 6410 return false; 6411 } 6412 6413 // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than 6414 // the maximum sample number supported by this format is passed. 6415 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. 6416 if (texture.value != 0 && context->getClientMajorVersion() >= 3) 6417 { 6418 Texture *tex = context->getTexture(texture); 6419 GLenum sizedInternalFormat = tex->getFormat(textarget, level).info->sizedInternalFormat; 6420 const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); 6421 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) 6422 { 6423 context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange); 6424 return false; 6425 } 6426 } 6427 6428 // Unless EXT_multisampled_render_to_texture2 is enabled, only color attachment 0 can be used. 6429 if (!context->getExtensions().multisampledRenderToTexture2EXT && 6430 attachment != GL_COLOR_ATTACHMENT0) 6431 { 6432 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment); 6433 return false; 6434 } 6435 6436 if (!ValidTexture2DDestinationTarget(context, textarget)) 6437 { 6438 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 6439 return false; 6440 } 6441 6442 return true; 6443 } 6444 6445 bool ValidateRenderbufferStorageMultisampleEXT(const Context *context, 6446 angle::EntryPoint entryPoint, 6447 GLenum target, 6448 GLsizei samples, 6449 GLenum internalformat, 6450 GLsizei width, 6451 GLsizei height) 6452 { 6453 if (!context->getExtensions().multisampledRenderToTextureEXT) 6454 { 6455 context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled); 6456 return false; 6457 } 6458 if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples, 6459 internalformat, width, height)) 6460 { 6461 return false; 6462 } 6463 6464 // EXT_multisampled_render_to_texture states that the value of samples 6465 // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples) 6466 // otherwise GL_INVALID_VALUE is generated. 6467 if (samples > context->getCaps().maxSamples) 6468 { 6469 context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange); 6470 return false; 6471 } 6472 6473 // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create 6474 // the specified storage. This is different than ES 3.0 in which a sample number higher 6475 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. 6476 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. 6477 if (context->getClientMajorVersion() >= 3) 6478 { 6479 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); 6480 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) 6481 { 6482 context->validationError(entryPoint, GL_OUT_OF_MEMORY, kSamplesOutOfRange); 6483 return false; 6484 } 6485 } 6486 6487 return true; 6488 } 6489 6490 void RecordBindTextureTypeError(const Context *context, 6491 angle::EntryPoint entryPoint, 6492 TextureType target) 6493 { 6494 ASSERT(!context->getStateCache().isValidBindTextureType(target)); 6495 6496 switch (target) 6497 { 6498 case TextureType::Rectangle: 6499 ASSERT(!context->getExtensions().textureRectangleANGLE); 6500 context->validationError(entryPoint, GL_INVALID_ENUM, kTextureRectangleNotSupported); 6501 break; 6502 6503 case TextureType::_3D: 6504 case TextureType::_2DArray: 6505 ASSERT(context->getClientMajorVersion() < 3); 6506 context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required); 6507 break; 6508 6509 case TextureType::_2DMultisample: 6510 ASSERT(context->getClientVersion() < Version(3, 1) && 6511 !context->getExtensions().textureMultisampleANGLE); 6512 context->validationError(entryPoint, GL_INVALID_ENUM, 6513 kMultisampleTextureExtensionOrES31Required); 6514 break; 6515 6516 case TextureType::_2DMultisampleArray: 6517 ASSERT(!context->getExtensions().textureStorageMultisample2dArrayOES); 6518 context->validationError(entryPoint, GL_INVALID_ENUM, 6519 kMultisampleArrayExtensionRequired); 6520 break; 6521 6522 case TextureType::External: 6523 ASSERT(!context->getExtensions().EGLImageExternalOES && 6524 !context->getExtensions().EGLStreamConsumerExternalNV); 6525 context->validationError(entryPoint, GL_INVALID_ENUM, kExternalTextureNotSupported); 6526 break; 6527 6528 case TextureType::VideoImage: 6529 ASSERT(!context->getExtensions().videoTextureWEBGL); 6530 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 6531 break; 6532 6533 case TextureType::Buffer: 6534 ASSERT(!context->getExtensions().textureBufferOES && 6535 !context->getExtensions().textureBufferEXT); 6536 context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled); 6537 break; 6538 6539 default: 6540 context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); 6541 } 6542 } 6543 6544 } // namespace gl