validationES.h (59611B)
1 // 2 // Copyright 2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // validationES.h: Validation functions for generic OpenGL ES entry point parameters 8 9 #ifndef LIBANGLE_VALIDATION_ES_H_ 10 #define LIBANGLE_VALIDATION_ES_H_ 11 12 #include "common/PackedEnums.h" 13 #include "common/mathutil.h" 14 #include "common/utilities.h" 15 #include "libANGLE/Context.h" 16 #include "libANGLE/ErrorStrings.h" 17 #include "libANGLE/Framebuffer.h" 18 #include "libANGLE/VertexArray.h" 19 20 #include <GLES2/gl2.h> 21 #include <GLES3/gl3.h> 22 #include <GLES3/gl31.h> 23 24 namespace egl 25 { 26 class Display; 27 class Image; 28 } // namespace egl 29 30 namespace gl 31 { 32 class Context; 33 struct Format; 34 class Framebuffer; 35 struct LinkedUniform; 36 class Program; 37 class Shader; 38 39 void SetRobustLengthParam(const GLsizei *length, GLsizei value); 40 bool ValidTextureTarget(const Context *context, TextureType type); 41 bool ValidTexture2DTarget(const Context *context, TextureType type); 42 bool ValidTexture3DTarget(const Context *context, TextureType target); 43 bool ValidTextureExternalTarget(const Context *context, TextureType target); 44 bool ValidTextureExternalTarget(const Context *context, TextureTarget target); 45 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target); 46 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target); 47 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type); 48 bool ValidFramebufferTarget(const Context *context, GLenum target); 49 bool ValidMipLevel(const Context *context, TextureType type, GLint level); 50 bool ValidImageSizeParameters(const Context *context, 51 angle::EntryPoint entryPoint, 52 TextureType target, 53 GLint level, 54 GLsizei width, 55 GLsizei height, 56 GLsizei depth, 57 bool isSubImage); 58 bool ValidCompressedImageSize(const Context *context, 59 GLenum internalFormat, 60 GLint level, 61 GLsizei width, 62 GLsizei height, 63 GLsizei depth); 64 bool ValidCompressedSubImageSize(const Context *context, 65 GLenum internalFormat, 66 GLint xoffset, 67 GLint yoffset, 68 GLint zoffset, 69 GLsizei width, 70 GLsizei height, 71 GLsizei depth, 72 size_t textureWidth, 73 size_t textureHeight, 74 size_t textureDepth); 75 bool ValidImageDataSize(const Context *context, 76 angle::EntryPoint entryPoint, 77 TextureType texType, 78 GLsizei width, 79 GLsizei height, 80 GLsizei depth, 81 GLenum format, 82 GLenum type, 83 const void *pixels, 84 GLsizei imageSize); 85 86 bool ValidQueryType(const Context *context, QueryType queryType); 87 88 bool ValidateWebGLVertexAttribPointer(const Context *context, 89 angle::EntryPoint entryPoint, 90 VertexAttribType type, 91 GLboolean normalized, 92 GLsizei stride, 93 const void *ptr, 94 bool pureInteger); 95 96 // Returns valid program if id is a valid program name 97 // Errors INVALID_OPERATION if valid shader is given and returns NULL 98 // Errors INVALID_VALUE otherwise and returns NULL 99 Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id); 100 101 // Returns valid shader if id is a valid shader name 102 // Errors INVALID_OPERATION if valid program is given and returns NULL 103 // Errors INVALID_VALUE otherwise and returns NULL 104 Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id); 105 106 bool ValidateAttachmentTarget(const Context *context, 107 angle::EntryPoint entryPoint, 108 GLenum attachment); 109 110 bool ValidateBlitFramebufferParameters(const Context *context, 111 angle::EntryPoint entryPoint, 112 GLint srcX0, 113 GLint srcY0, 114 GLint srcX1, 115 GLint srcY1, 116 GLint dstX0, 117 GLint dstY0, 118 GLint dstX1, 119 GLint dstY1, 120 GLbitfield mask, 121 GLenum filter); 122 123 bool ValidateBindFramebufferBase(const Context *context, 124 angle::EntryPoint entryPoint, 125 GLenum target, 126 FramebufferID framebuffer); 127 bool ValidateBindRenderbufferBase(const Context *context, 128 angle::EntryPoint entryPoint, 129 GLenum target, 130 RenderbufferID renderbuffer); 131 bool ValidateFramebufferParameteriBase(const Context *context, 132 angle::EntryPoint entryPoint, 133 GLenum target, 134 GLenum pname, 135 GLint param); 136 bool ValidateFramebufferRenderbufferBase(const Context *context, 137 angle::EntryPoint entryPoint, 138 GLenum target, 139 GLenum attachment, 140 GLenum renderbuffertarget, 141 RenderbufferID renderbuffer); 142 bool ValidateFramebufferTextureBase(const Context *context, 143 angle::EntryPoint entryPoint, 144 GLenum target, 145 GLenum attachment, 146 TextureID texture, 147 GLint level); 148 bool ValidateGenerateMipmapBase(const Context *context, 149 angle::EntryPoint entryPoint, 150 TextureType target); 151 152 bool ValidateRenderbufferStorageParametersBase(const Context *context, 153 angle::EntryPoint entryPoint, 154 GLenum target, 155 GLsizei samples, 156 GLenum internalformat, 157 GLsizei width, 158 GLsizei height); 159 160 bool ValidatePixelPack(const Context *context, 161 angle::EntryPoint entryPoint, 162 GLenum format, 163 GLenum type, 164 GLint x, 165 GLint y, 166 GLsizei width, 167 GLsizei height, 168 GLsizei bufSize, 169 GLsizei *length, 170 const void *pixels); 171 172 bool ValidateReadPixelsBase(const Context *context, 173 angle::EntryPoint entryPoint, 174 GLint x, 175 GLint y, 176 GLsizei width, 177 GLsizei height, 178 GLenum format, 179 GLenum type, 180 GLsizei bufSize, 181 GLsizei *length, 182 GLsizei *columns, 183 GLsizei *rows, 184 const void *pixels); 185 bool ValidateReadPixelsRobustANGLE(const Context *context, 186 angle::EntryPoint entryPoint, 187 GLint x, 188 GLint y, 189 GLsizei width, 190 GLsizei height, 191 GLenum format, 192 GLenum type, 193 GLsizei bufSize, 194 const GLsizei *length, 195 const GLsizei *columns, 196 const GLsizei *rows, 197 const void *pixels); 198 bool ValidateReadnPixelsEXT(const Context *context, 199 angle::EntryPoint entryPoint, 200 GLint x, 201 GLint y, 202 GLsizei width, 203 GLsizei height, 204 GLenum format, 205 GLenum type, 206 GLsizei bufSize, 207 const void *pixels); 208 bool ValidateReadnPixelsRobustANGLE(const Context *context, 209 angle::EntryPoint entryPoint, 210 GLint x, 211 GLint y, 212 GLsizei width, 213 GLsizei height, 214 GLenum format, 215 GLenum type, 216 GLsizei bufSize, 217 const GLsizei *length, 218 const GLsizei *columns, 219 const GLsizei *rows, 220 const void *data); 221 222 bool ValidateGenQueriesEXT(const Context *context, 223 angle::EntryPoint entryPoint, 224 GLsizei n, 225 const QueryID *ids); 226 bool ValidateDeleteQueriesEXT(const Context *context, 227 angle::EntryPoint entryPoint, 228 GLsizei n, 229 const QueryID *ids); 230 bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id); 231 bool ValidateBeginQueryBase(const Context *context, 232 angle::EntryPoint entryPoint, 233 QueryType target, 234 QueryID id); 235 bool ValidateBeginQueryEXT(const Context *context, 236 angle::EntryPoint entryPoint, 237 QueryType target, 238 QueryID id); 239 bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target); 240 bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target); 241 bool ValidateQueryCounterEXT(const Context *context, 242 angle::EntryPoint entryPoint, 243 QueryID id, 244 QueryType target); 245 bool ValidateGetQueryivBase(const Context *context, 246 angle::EntryPoint entryPoint, 247 QueryType target, 248 GLenum pname, 249 GLsizei *numParams); 250 bool ValidateGetQueryivEXT(const Context *context, 251 angle::EntryPoint entryPoint, 252 QueryType target, 253 GLenum pname, 254 const GLint *params); 255 bool ValidateGetQueryivRobustANGLE(const Context *context, 256 angle::EntryPoint entryPoint, 257 QueryType target, 258 GLenum pname, 259 GLsizei bufSize, 260 const GLsizei *length, 261 const GLint *params); 262 bool ValidateGetQueryObjectValueBase(const Context *context, 263 angle::EntryPoint entryPoint, 264 QueryID id, 265 GLenum pname, 266 GLsizei *numParams); 267 bool ValidateGetQueryObjectivEXT(const Context *context, 268 angle::EntryPoint entryPoint, 269 QueryID id, 270 GLenum pname, 271 const GLint *params); 272 bool ValidateGetQueryObjectivRobustANGLE(const Context *context, 273 angle::EntryPoint entryPoint, 274 QueryID id, 275 GLenum pname, 276 GLsizei bufSize, 277 const GLsizei *length, 278 const GLint *params); 279 bool ValidateGetQueryObjectuivEXT(const Context *context, 280 angle::EntryPoint entryPoint, 281 QueryID id, 282 GLenum pname, 283 const GLuint *params); 284 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context, 285 angle::EntryPoint entryPoint, 286 QueryID id, 287 GLenum pname, 288 GLsizei bufSize, 289 const GLsizei *length, 290 const GLuint *params); 291 bool ValidateGetQueryObjecti64vEXT(const Context *context, 292 angle::EntryPoint entryPoint, 293 QueryID id, 294 GLenum pname, 295 GLint64 *params); 296 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context, 297 angle::EntryPoint entryPoint, 298 QueryID id, 299 GLenum pname, 300 GLsizei bufSize, 301 const GLsizei *length, 302 GLint64 *params); 303 bool ValidateGetQueryObjectui64vEXT(const Context *context, 304 angle::EntryPoint entryPoint, 305 QueryID id, 306 GLenum pname, 307 GLuint64 *params); 308 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context, 309 angle::EntryPoint entryPoint, 310 QueryID id, 311 GLenum pname, 312 GLsizei bufSize, 313 const GLsizei *length, 314 GLuint64 *params); 315 316 bool ValidateUniformCommonBase(const Context *context, 317 angle::EntryPoint entryPoint, 318 const Program *program, 319 UniformLocation location, 320 GLsizei count, 321 const LinkedUniform **uniformOut); 322 bool ValidateUniform1ivValue(const Context *context, 323 angle::EntryPoint entryPoint, 324 GLenum uniformType, 325 GLsizei count, 326 const GLint *value); 327 328 ANGLE_INLINE bool ValidateUniformValue(const Context *context, 329 angle::EntryPoint entryPoint, 330 GLenum valueType, 331 GLenum uniformType) 332 { 333 // Check that the value type is compatible with uniform type. 334 // Do the cheaper test first, for a little extra speed. 335 if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType) 336 { 337 context->validationError(entryPoint, GL_INVALID_OPERATION, err::kUniformSizeMismatch); 338 return false; 339 } 340 return true; 341 } 342 343 bool ValidateUniformMatrixValue(const Context *context, 344 angle::EntryPoint entryPoint, 345 GLenum valueType, 346 GLenum uniformType); 347 bool ValidateUniform(const Context *context, 348 angle::EntryPoint entryPoint, 349 GLenum uniformType, 350 UniformLocation location, 351 GLsizei count); 352 bool ValidateUniformMatrix(const Context *context, 353 angle::EntryPoint entryPoint, 354 GLenum matrixType, 355 UniformLocation location, 356 GLsizei count, 357 GLboolean transpose); 358 bool ValidateGetBooleanvRobustANGLE(const Context *context, 359 angle::EntryPoint entryPoint, 360 GLenum pname, 361 GLsizei bufSize, 362 const GLsizei *length, 363 const GLboolean *params); 364 bool ValidateGetFloatvRobustANGLE(const Context *context, 365 angle::EntryPoint entryPoint, 366 GLenum pname, 367 GLsizei bufSize, 368 const GLsizei *length, 369 const GLfloat *params); 370 bool ValidateStateQuery(const Context *context, 371 angle::EntryPoint entryPoint, 372 GLenum pname, 373 GLenum *nativeType, 374 unsigned int *numParams); 375 bool ValidateGetIntegervRobustANGLE(const Context *context, 376 angle::EntryPoint entryPoint, 377 GLenum pname, 378 GLsizei bufSize, 379 const GLsizei *length, 380 const GLint *data); 381 bool ValidateGetInteger64vRobustANGLE(const Context *context, 382 angle::EntryPoint entryPoint, 383 GLenum pname, 384 GLsizei bufSize, 385 const GLsizei *length, 386 GLint64 *data); 387 bool ValidateRobustStateQuery(const Context *context, 388 angle::EntryPoint entryPoint, 389 GLenum pname, 390 GLsizei bufSize, 391 GLenum *nativeType, 392 unsigned int *numParams); 393 394 bool ValidateCopyImageSubDataBase(const Context *context, 395 angle::EntryPoint entryPoint, 396 GLuint srcName, 397 GLenum srcTarget, 398 GLint srcLevel, 399 GLint srcX, 400 GLint srcY, 401 GLint srcZ, 402 GLuint dstName, 403 GLenum dstTarget, 404 GLint dstLevel, 405 GLint dstX, 406 GLint dstY, 407 GLint dstZ, 408 GLsizei srcWidth, 409 GLsizei srcHeight, 410 GLsizei srcDepth); 411 412 bool ValidateCopyTexImageParametersBase(const Context *context, 413 angle::EntryPoint entryPoint, 414 TextureTarget target, 415 GLint level, 416 GLenum internalformat, 417 bool isSubImage, 418 GLint xoffset, 419 GLint yoffset, 420 GLint zoffset, 421 GLint x, 422 GLint y, 423 GLsizei width, 424 GLsizei height, 425 GLint border, 426 Format *textureFormatOut); 427 428 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode); 429 const char *ValidateDrawElementsStates(const Context *context); 430 431 ANGLE_INLINE bool ValidateDrawBase(const Context *context, 432 angle::EntryPoint entryPoint, 433 PrimitiveMode mode) 434 { 435 intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context); 436 if (drawStatesError) 437 { 438 const char *errorMessage = reinterpret_cast<const char *>(drawStatesError); 439 440 // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer 441 // Incomplete. 442 bool isFramebufferIncomplete = strcmp(errorMessage, err::kDrawFramebufferIncomplete) == 0; 443 GLenum errorCode = 444 isFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION : GL_INVALID_OPERATION; 445 context->validationError(entryPoint, errorCode, errorMessage); 446 return false; 447 } 448 449 if (!context->getStateCache().isValidDrawMode(mode)) 450 { 451 RecordDrawModeError(context, entryPoint, mode); 452 return false; 453 } 454 455 return true; 456 } 457 458 bool ValidateDrawArraysInstancedBase(const Context *context, 459 angle::EntryPoint entryPoint, 460 PrimitiveMode mode, 461 GLint first, 462 GLsizei count, 463 GLsizei primcount); 464 bool ValidateDrawArraysInstancedANGLE(const Context *context, 465 angle::EntryPoint entryPoint, 466 PrimitiveMode mode, 467 GLint first, 468 GLsizei count, 469 GLsizei primcount); 470 bool ValidateDrawArraysInstancedEXT(const Context *context, 471 angle::EntryPoint entryPoint, 472 PrimitiveMode mode, 473 GLint first, 474 GLsizei count, 475 GLsizei primcount); 476 477 bool ValidateDrawElementsInstancedBase(const Context *context, 478 angle::EntryPoint entryPoint, 479 PrimitiveMode mode, 480 GLsizei count, 481 DrawElementsType type, 482 const void *indices, 483 GLsizei primcount); 484 bool ValidateDrawElementsInstancedANGLE(const Context *context, 485 angle::EntryPoint entryPoint, 486 PrimitiveMode mode, 487 GLsizei count, 488 DrawElementsType type, 489 const void *indices, 490 GLsizei primcount); 491 bool ValidateDrawElementsInstancedEXT(const Context *context, 492 angle::EntryPoint entryPoint, 493 PrimitiveMode mode, 494 GLsizei count, 495 DrawElementsType type, 496 const void *indices, 497 GLsizei primcount); 498 499 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint); 500 501 bool ValidateGetUniformBase(const Context *context, 502 angle::EntryPoint entryPoint, 503 ShaderProgramID program, 504 UniformLocation location); 505 bool ValidateSizedGetUniform(const Context *context, 506 angle::EntryPoint entryPoint, 507 ShaderProgramID program, 508 UniformLocation location, 509 GLsizei bufSize, 510 GLsizei *length); 511 bool ValidateGetnUniformfvEXT(const Context *context, 512 angle::EntryPoint entryPoint, 513 ShaderProgramID program, 514 UniformLocation location, 515 GLsizei bufSize, 516 const GLfloat *params); 517 bool ValidateGetnUniformfvRobustANGLE(const Context *context, 518 angle::EntryPoint entryPoint, 519 ShaderProgramID program, 520 UniformLocation location, 521 GLsizei bufSize, 522 const GLsizei *length, 523 const GLfloat *params); 524 bool ValidateGetnUniformivEXT(const Context *context, 525 angle::EntryPoint entryPoint, 526 ShaderProgramID program, 527 UniformLocation location, 528 GLsizei bufSize, 529 const GLint *params); 530 bool ValidateGetnUniformivRobustANGLE(const Context *context, 531 angle::EntryPoint entryPoint, 532 ShaderProgramID program, 533 UniformLocation location, 534 GLsizei bufSize, 535 const GLsizei *length, 536 const GLint *params); 537 bool ValidateGetnUniformuivRobustANGLE(const Context *context, 538 angle::EntryPoint entryPoint, 539 ShaderProgramID program, 540 UniformLocation location, 541 GLsizei bufSize, 542 const GLsizei *length, 543 const GLuint *params); 544 bool ValidateGetUniformfvRobustANGLE(const Context *context, 545 angle::EntryPoint entryPoint, 546 ShaderProgramID program, 547 UniformLocation location, 548 GLsizei bufSize, 549 const GLsizei *length, 550 const GLfloat *params); 551 bool ValidateGetUniformivRobustANGLE(const Context *context, 552 angle::EntryPoint entryPoint, 553 ShaderProgramID program, 554 UniformLocation location, 555 GLsizei bufSize, 556 const GLsizei *length, 557 const GLint *params); 558 bool ValidateGetUniformuivRobustANGLE(const Context *context, 559 angle::EntryPoint entryPoint, 560 ShaderProgramID program, 561 UniformLocation location, 562 GLsizei bufSize, 563 const GLsizei *length, 564 const GLuint *params); 565 566 bool ValidateDiscardFramebufferBase(const Context *context, 567 angle::EntryPoint entryPoint, 568 GLenum target, 569 GLsizei numAttachments, 570 const GLenum *attachments, 571 bool defaultFramebuffer); 572 573 bool ValidateInsertEventMarkerEXT(const Context *context, 574 angle::EntryPoint entryPoint, 575 GLsizei length, 576 const char *marker); 577 bool ValidatePushGroupMarkerEXT(const Context *context, 578 angle::EntryPoint entryPoint, 579 GLsizei length, 580 const char *marker); 581 bool ValidateEGLImageObject(const Context *context, 582 angle::EntryPoint entryPoint, 583 TextureType type, 584 GLeglImageOES image); 585 bool ValidateEGLImageTargetTexture2DOES(const Context *context, 586 angle::EntryPoint entryPoint, 587 TextureType type, 588 GLeglImageOES image); 589 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context, 590 angle::EntryPoint entryPoint, 591 GLenum target, 592 GLeglImageOES image); 593 594 bool ValidateProgramBinaryBase(const Context *context, 595 angle::EntryPoint entryPoint, 596 ShaderProgramID program, 597 GLenum binaryFormat, 598 const void *binary, 599 GLint length); 600 bool ValidateGetProgramBinaryBase(const Context *context, 601 angle::EntryPoint entryPoint, 602 ShaderProgramID program, 603 GLsizei bufSize, 604 const GLsizei *length, 605 const GLenum *binaryFormat, 606 const void *binary); 607 608 bool ValidateDrawBuffersBase(const Context *context, 609 angle::EntryPoint entryPoint, 610 GLsizei n, 611 const GLenum *bufs); 612 613 bool ValidateGetBufferPointervBase(const Context *context, 614 angle::EntryPoint entryPoint, 615 BufferBinding target, 616 GLenum pname, 617 GLsizei *length, 618 void *const *params); 619 bool ValidateUnmapBufferBase(const Context *context, 620 angle::EntryPoint entryPoint, 621 BufferBinding target); 622 bool ValidateMapBufferRangeBase(const Context *context, 623 angle::EntryPoint entryPoint, 624 BufferBinding target, 625 GLintptr offset, 626 GLsizeiptr length, 627 GLbitfield access); 628 bool ValidateFlushMappedBufferRangeBase(const Context *context, 629 angle::EntryPoint entryPoint, 630 BufferBinding target, 631 GLintptr offset, 632 GLsizeiptr length); 633 634 bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n); 635 636 bool ValidateRobustEntryPoint(const Context *context, 637 angle::EntryPoint entryPoint, 638 GLsizei bufSize); 639 bool ValidateRobustBufferSize(const Context *context, 640 angle::EntryPoint entryPoint, 641 GLsizei bufSize, 642 GLsizei numParams); 643 644 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context, 645 angle::EntryPoint entryPoint, 646 GLenum target, 647 GLenum attachment, 648 GLenum pname, 649 GLsizei *numParams); 650 651 bool ValidateGetFramebufferParameterivBase(const Context *context, 652 angle::EntryPoint entryPoint, 653 GLenum target, 654 GLenum pname, 655 const GLint *params); 656 657 bool ValidateGetBufferParameterBase(const Context *context, 658 angle::EntryPoint entryPoint, 659 BufferBinding target, 660 GLenum pname, 661 bool pointerVersion, 662 GLsizei *numParams); 663 664 bool ValidateGetProgramivBase(const Context *context, 665 angle::EntryPoint entryPoint, 666 ShaderProgramID program, 667 GLenum pname, 668 GLsizei *numParams); 669 670 bool ValidateGetRenderbufferParameterivBase(const Context *context, 671 angle::EntryPoint entryPoint, 672 GLenum target, 673 GLenum pname, 674 GLsizei *length); 675 676 bool ValidateGetShaderivBase(const Context *context, 677 angle::EntryPoint entryPoint, 678 ShaderProgramID shader, 679 GLenum pname, 680 GLsizei *length); 681 682 bool ValidateGetTexParameterBase(const Context *context, 683 angle::EntryPoint entryPoint, 684 TextureType target, 685 GLenum pname, 686 GLsizei *length); 687 688 template <typename ParamType> 689 bool ValidateTexParameterBase(const Context *context, 690 angle::EntryPoint entryPoint, 691 TextureType target, 692 GLenum pname, 693 GLsizei bufSize, 694 bool vectorParams, 695 const ParamType *params); 696 697 bool ValidateGetVertexAttribBase(const Context *context, 698 angle::EntryPoint entryPoint, 699 GLuint index, 700 GLenum pname, 701 GLsizei *length, 702 bool pointer, 703 bool pureIntegerEntryPoint); 704 705 ANGLE_INLINE bool ValidateVertexFormat(const Context *context, 706 angle::EntryPoint entryPoint, 707 GLuint index, 708 GLint size, 709 VertexAttribTypeCase validation) 710 { 711 const Caps &caps = context->getCaps(); 712 if (index >= static_cast<GLuint>(caps.maxVertexAttributes)) 713 { 714 context->validationError(entryPoint, GL_INVALID_VALUE, 715 err::kIndexExceedsMaxVertexAttribute); 716 return false; 717 } 718 719 switch (validation) 720 { 721 case VertexAttribTypeCase::Invalid: 722 context->validationError(entryPoint, GL_INVALID_ENUM, err::kInvalidType); 723 return false; 724 case VertexAttribTypeCase::Valid: 725 if (size < 1 || size > 4) 726 { 727 context->validationError(entryPoint, GL_INVALID_VALUE, err::kInvalidVertexAttrSize); 728 return false; 729 } 730 break; 731 case VertexAttribTypeCase::ValidSize4Only: 732 if (size != 4) 733 { 734 context->validationError(entryPoint, GL_INVALID_OPERATION, 735 err::kInvalidVertexAttribSize2101010); 736 return false; 737 } 738 break; 739 case VertexAttribTypeCase::ValidSize3or4: 740 if (size != 3 && size != 4) 741 { 742 context->validationError(entryPoint, GL_INVALID_OPERATION, 743 err::kInvalidVertexAttribSize1010102); 744 return false; 745 } 746 break; 747 } 748 749 return true; 750 } 751 752 // Note: These byte, short, and int types are all converted to float for the shader. 753 ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context, 754 angle::EntryPoint entryPoint, 755 GLuint index, 756 GLint size, 757 VertexAttribType type) 758 { 759 return ValidateVertexFormat(context, entryPoint, index, size, 760 context->getStateCache().getVertexAttribTypeValidation(type)); 761 } 762 763 ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context, 764 angle::EntryPoint entryPoint, 765 GLuint index, 766 GLint size, 767 VertexAttribType type) 768 { 769 return ValidateVertexFormat( 770 context, entryPoint, index, size, 771 context->getStateCache().getIntegerVertexAttribTypeValidation(type)); 772 } 773 774 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context, 775 angle::EntryPoint entryPoint, 776 GLint drawbuffer, 777 const GLenum *validComponentTypes, 778 size_t validComponentTypeCount); 779 780 bool ValidateRobustCompressedTexImageBase(const Context *context, 781 angle::EntryPoint entryPoint, 782 GLsizei imageSize, 783 GLsizei dataSize); 784 785 bool ValidateVertexAttribIndex(const Context *context, angle::EntryPoint entryPoint, GLuint index); 786 787 bool ValidateGetActiveUniformBlockivBase(const Context *context, 788 angle::EntryPoint entryPoint, 789 ShaderProgramID program, 790 UniformBlockIndex uniformBlockIndex, 791 GLenum pname, 792 GLsizei *length); 793 794 bool ValidateGetSamplerParameterBase(const Context *context, 795 angle::EntryPoint entryPoint, 796 SamplerID sampler, 797 GLenum pname, 798 GLsizei *length); 799 800 template <typename ParamType> 801 bool ValidateSamplerParameterBase(const Context *context, 802 angle::EntryPoint entryPoint, 803 SamplerID sampler, 804 GLenum pname, 805 GLsizei bufSize, 806 bool vectorParams, 807 const ParamType *params); 808 809 bool ValidateGetInternalFormativBase(const Context *context, 810 angle::EntryPoint entryPoint, 811 GLenum target, 812 GLenum internalformat, 813 GLenum pname, 814 GLsizei bufSize, 815 GLsizei *numParams); 816 817 bool ValidateFramebufferNotMultisampled(const Context *context, 818 angle::EntryPoint entryPoint, 819 const Framebuffer *framebuffer, 820 bool checkReadBufferResourceSamples); 821 822 bool ValidateMultitextureUnit(const Context *context, angle::EntryPoint entryPoint, GLenum texture); 823 824 bool ValidateTransformFeedbackPrimitiveMode(const Context *context, 825 angle::EntryPoint entryPoint, 826 PrimitiveMode transformFeedbackPrimitiveMode, 827 PrimitiveMode renderPrimitiveMode); 828 829 // Common validation for 2D and 3D variants of TexStorage*Multisample. 830 bool ValidateTexStorageMultisample(const Context *context, 831 angle::EntryPoint entryPoint, 832 TextureType target, 833 GLsizei samples, 834 GLint internalFormat, 835 GLsizei width, 836 GLsizei height); 837 838 bool ValidateTexStorage2DMultisampleBase(const Context *context, 839 angle::EntryPoint entryPoint, 840 TextureType target, 841 GLsizei samples, 842 GLint internalFormat, 843 GLsizei width, 844 GLsizei height); 845 846 bool ValidateGetTexLevelParameterBase(const Context *context, 847 angle::EntryPoint entryPoint, 848 TextureTarget target, 849 GLint level, 850 GLenum pname, 851 GLsizei *length); 852 853 bool ValidateMapBufferBase(const Context *context, 854 angle::EntryPoint entryPoint, 855 BufferBinding target); 856 bool ValidateIndexedStateQuery(const Context *context, 857 angle::EntryPoint entryPoint, 858 GLenum pname, 859 GLuint index, 860 GLsizei *length); 861 bool ValidateES3TexImage2DParameters(const Context *context, 862 angle::EntryPoint entryPoint, 863 TextureTarget target, 864 GLint level, 865 GLenum internalformat, 866 bool isCompressed, 867 bool isSubImage, 868 GLint xoffset, 869 GLint yoffset, 870 GLint zoffset, 871 GLsizei width, 872 GLsizei height, 873 GLsizei depth, 874 GLint border, 875 GLenum format, 876 GLenum type, 877 GLsizei imageSize, 878 const void *pixels); 879 bool ValidateES3CopyTexImage2DParameters(const Context *context, 880 angle::EntryPoint entryPoint, 881 TextureTarget target, 882 GLint level, 883 GLenum internalformat, 884 bool isSubImage, 885 GLint xoffset, 886 GLint yoffset, 887 GLint zoffset, 888 GLint x, 889 GLint y, 890 GLsizei width, 891 GLsizei height, 892 GLint border); 893 bool ValidateES3TexStorageParametersBase(const Context *context, 894 angle::EntryPoint entryPoint, 895 TextureType target, 896 GLsizei levels, 897 GLenum internalformat, 898 GLsizei width, 899 GLsizei height, 900 GLsizei depth); 901 bool ValidateES3TexStorage2DParameters(const Context *context, 902 angle::EntryPoint entryPoint, 903 TextureType target, 904 GLsizei levels, 905 GLenum internalformat, 906 GLsizei width, 907 GLsizei height, 908 GLsizei depth); 909 bool ValidateES3TexStorage3DParameters(const Context *context, 910 angle::EntryPoint entryPoint, 911 TextureType target, 912 GLsizei levels, 913 GLenum internalformat, 914 GLsizei width, 915 GLsizei height, 916 GLsizei depth); 917 918 bool ValidateGetMultisamplefvBase(const Context *context, 919 angle::EntryPoint entryPoint, 920 GLenum pname, 921 GLuint index, 922 const GLfloat *val); 923 bool ValidateSampleMaskiBase(const Context *context, 924 angle::EntryPoint entryPoint, 925 GLuint maskNumber, 926 GLbitfield mask); 927 928 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context, 929 const ProgramExecutable *programExecutable); 930 931 // We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying 932 // implementation format info for incomplete framebuffers. It seems like these queries are 933 // incongruent with the other errors. 934 // Inlined for speed. 935 template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION> 936 ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context, 937 angle::EntryPoint entryPoint, 938 const Framebuffer *framebuffer) 939 { 940 const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context); 941 if (!framebufferStatus.isComplete()) 942 { 943 ASSERT(framebufferStatus.reason != nullptr); 944 context->validationError(entryPoint, ErrorCode, framebufferStatus.reason); 945 return false; 946 } 947 948 return true; 949 } 950 951 const char *ValidateProgramPipelineDrawStates(const State &state, 952 const Extensions &extensions, 953 ProgramPipeline *programPipeline); 954 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline); 955 const char *ValidateDrawStates(const Context *context); 956 const char *ValidateProgramPipeline(const Context *context); 957 958 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint); 959 960 ANGLE_INLINE bool ValidateDrawAttribs(const Context *context, 961 angle::EntryPoint entryPoint, 962 int64_t maxVertex) 963 { 964 if (maxVertex > context->getStateCache().getNonInstancedVertexElementLimit()) 965 { 966 RecordDrawAttribsError(context, entryPoint); 967 return false; 968 } 969 970 return true; 971 } 972 973 ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context, 974 angle::EntryPoint entryPoint, 975 GLint first, 976 GLsizei count) 977 { 978 if (!context->isBufferAccessValidationEnabled()) 979 { 980 return true; 981 } 982 983 // Check the computation of maxVertex doesn't overflow. 984 // - first < 0 has been checked as an error condition. 985 // - if count <= 0, skip validating no-op draw calls. 986 // From this we know maxVertex will be positive, and only need to check if it overflows GLint. 987 ASSERT(first >= 0); 988 ASSERT(count > 0); 989 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1; 990 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max())) 991 { 992 context->validationError(entryPoint, GL_INVALID_OPERATION, err::kIntegerOverflow); 993 return false; 994 } 995 996 return ValidateDrawAttribs(context, entryPoint, maxVertex); 997 } 998 999 ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context, 1000 angle::EntryPoint entryPoint, 1001 GLint primcount) 1002 { 1003 if (!context->isBufferAccessValidationEnabled()) 1004 { 1005 return true; 1006 } 1007 1008 if ((primcount - 1) > context->getStateCache().getInstancedVertexElementLimit()) 1009 { 1010 RecordDrawAttribsError(context, entryPoint); 1011 return false; 1012 } 1013 1014 return true; 1015 } 1016 1017 ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context, 1018 angle::EntryPoint entryPoint, 1019 PrimitiveMode mode, 1020 GLint first, 1021 GLsizei count, 1022 GLsizei primcount) 1023 { 1024 if (first < 0) 1025 { 1026 context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeStart); 1027 return false; 1028 } 1029 1030 if (count <= 0) 1031 { 1032 if (count < 0) 1033 { 1034 context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeCount); 1035 return false; 1036 } 1037 1038 // Early exit. 1039 return ValidateDrawBase(context, entryPoint, mode); 1040 } 1041 1042 if (primcount <= 0) 1043 { 1044 if (primcount < 0) 1045 { 1046 context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeCount); 1047 return false; 1048 } 1049 // Early exit. 1050 return ValidateDrawBase(context, entryPoint, mode); 1051 } 1052 1053 if (!ValidateDrawBase(context, entryPoint, mode)) 1054 { 1055 return false; 1056 } 1057 1058 if (context->getStateCache().isTransformFeedbackActiveUnpaused() && 1059 !context->supportsGeometryOrTesselation()) 1060 { 1061 const State &state = context->getState(); 1062 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); 1063 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount)) 1064 { 1065 context->validationError(entryPoint, GL_INVALID_OPERATION, 1066 err::kTransformFeedbackBufferTooSmall); 1067 return false; 1068 } 1069 } 1070 1071 return ValidateDrawArraysAttribs(context, entryPoint, first, count); 1072 } 1073 1074 ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context, 1075 angle::EntryPoint entryPoint, 1076 PrimitiveMode mode, 1077 DrawElementsType type) 1078 { 1079 if (!context->getStateCache().isValidDrawElementsType(type)) 1080 { 1081 if (type == DrawElementsType::UnsignedInt) 1082 { 1083 context->validationError(entryPoint, GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte); 1084 return false; 1085 } 1086 1087 ASSERT(type == DrawElementsType::InvalidEnum); 1088 context->validationErrorF(entryPoint, GL_INVALID_ENUM, err::kEnumInvalid); 1089 return false; 1090 } 1091 1092 intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context); 1093 if (drawElementsError) 1094 { 1095 // All errors from ValidateDrawElementsStates return INVALID_OPERATION. 1096 const char *errorMessage = reinterpret_cast<const char *>(drawElementsError); 1097 context->validationError(entryPoint, GL_INVALID_OPERATION, errorMessage); 1098 return false; 1099 } 1100 1101 // Note that we are missing overflow checks for active transform feedback buffers. 1102 return true; 1103 } 1104 1105 ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context, 1106 angle::EntryPoint entryPoint, 1107 PrimitiveMode mode, 1108 GLsizei count, 1109 DrawElementsType type, 1110 const void *indices, 1111 GLsizei primcount) 1112 { 1113 if (!ValidateDrawElementsBase(context, entryPoint, mode, type)) 1114 { 1115 return false; 1116 } 1117 1118 ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0); 1119 1120 if (context->isWebGL()) 1121 { 1122 GLuint typeBytes = GetDrawElementsTypeSize(type); 1123 1124 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0) 1125 { 1126 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements 1127 // The offset arguments to drawElements and [...], must be a multiple of the size of the 1128 // data type passed to the call, or an INVALID_OPERATION error is generated. 1129 context->validationError(entryPoint, GL_INVALID_OPERATION, 1130 err::kOffsetMustBeMultipleOfType); 1131 return false; 1132 } 1133 1134 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements 1135 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE 1136 // error is generated. 1137 if (reinterpret_cast<intptr_t>(indices) < 0) 1138 { 1139 context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeOffset); 1140 return false; 1141 } 1142 } 1143 1144 if (count <= 0) 1145 { 1146 if (count < 0) 1147 { 1148 context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeCount); 1149 return false; 1150 } 1151 1152 // Early exit. 1153 return ValidateDrawBase(context, entryPoint, mode); 1154 } 1155 1156 if (!ValidateDrawBase(context, entryPoint, mode)) 1157 { 1158 return false; 1159 } 1160 1161 const State &state = context->getState(); 1162 const VertexArray *vao = state.getVertexArray(); 1163 Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); 1164 1165 if (!elementArrayBuffer) 1166 { 1167 if (!indices) 1168 { 1169 // This is an application error that would normally result in a crash, but we catch 1170 // it and return an error 1171 context->validationError(entryPoint, GL_INVALID_OPERATION, 1172 err::kElementArrayNoBufferOrPointer); 1173 return false; 1174 } 1175 } 1176 else 1177 { 1178 // The max possible type size is 8 and count is on 32 bits so doing the multiplication 1179 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0. 1180 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type"); 1181 constexpr uint64_t kMaxTypeSize = 8; 1182 constexpr uint64_t kIntMax = std::numeric_limits<int>::max(); 1183 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max(); 1184 static_assert(kIntMax < kUint64Max / kMaxTypeSize, ""); 1185 1186 uint64_t elementCount = static_cast<uint64_t>(count); 1187 ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize); 1188 1189 // Doing the multiplication here is overflow-safe 1190 uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type); 1191 1192 // The offset can be any value, check for overflows 1193 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices)); 1194 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset; 1195 if (elementDataSizeWithOffset < elementDataSizeNoOffset) 1196 { 1197 context->validationError(entryPoint, GL_INVALID_OPERATION, err::kIntegerOverflow); 1198 return false; 1199 } 1200 1201 // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064 1202 if ((elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize())) && 1203 (primcount > 0)) 1204 { 1205 context->validationError(entryPoint, GL_INVALID_OPERATION, 1206 err::kInsufficientBufferSize); 1207 return false; 1208 } 1209 } 1210 1211 if (context->isBufferAccessValidationEnabled() && primcount > 0) 1212 { 1213 // Use the parameter buffer to retrieve and cache the index range. 1214 IndexRange indexRange{IndexRange::Undefined()}; 1215 ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange)); 1216 1217 // If we use an index greater than our maximum supported index range, return an error. 1218 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should 1219 // always return an error if possible here. 1220 if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex) 1221 { 1222 context->validationError(entryPoint, GL_INVALID_OPERATION, err::kExceedsMaxElement); 1223 return false; 1224 } 1225 1226 if (!ValidateDrawAttribs(context, entryPoint, static_cast<GLint>(indexRange.end))) 1227 { 1228 return false; 1229 } 1230 1231 // No op if there are no real indices in the index data (all are primitive restart). 1232 return (indexRange.vertexIndexCount > 0); 1233 } 1234 1235 return true; 1236 } 1237 1238 ANGLE_INLINE bool ValidateBindVertexArrayBase(const Context *context, 1239 angle::EntryPoint entryPoint, 1240 VertexArrayID array) 1241 { 1242 if (!context->isVertexArrayGenerated(array)) 1243 { 1244 // The default VAO should always exist 1245 ASSERT(array.value != 0); 1246 context->validationError(entryPoint, GL_INVALID_OPERATION, err::kInvalidVertexArray); 1247 return false; 1248 } 1249 1250 return true; 1251 } 1252 1253 ANGLE_INLINE bool ValidateVertexAttribIndex(const Context *context, 1254 angle::EntryPoint entryPoint, 1255 GLuint index) 1256 { 1257 if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes)) 1258 { 1259 context->validationError(entryPoint, GL_INVALID_VALUE, 1260 err::kIndexExceedsMaxVertexAttribute); 1261 return false; 1262 } 1263 1264 return true; 1265 } 1266 1267 bool ValidateLogicOpCommon(const Context *context, 1268 angle::EntryPoint entryPoint, 1269 LogicalOperation opcodePacked); 1270 } // namespace gl 1271 1272 #endif // LIBANGLE_VALIDATION_ES_H_