1 // 2 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // validationES.h: Validation functions for generic OpenGL ES entry point parameters 8 9 #include "libGLESv2/validationES.h" 10 #include "libGLESv2/validationES2.h" 11 #include "libGLESv2/validationES3.h" 12 #include "libGLESv2/Context.h" 13 #include "libGLESv2/Texture.h" 14 #include "libGLESv2/Framebuffer.h" 15 #include "libGLESv2/FramebufferAttachment.h" 16 #include "libGLESv2/formatutils.h" 17 #include "libGLESv2/main.h" 18 #include "libGLESv2/Query.h" 19 #include "libGLESv2/ProgramBinary.h" 20 #include "libGLESv2/TransformFeedback.h" 21 #include "libGLESv2/VertexArray.h" 22 #include "libGLESv2/renderer/BufferImpl.h" 23 24 #include "common/mathutil.h" 25 #include "common/utilities.h" 26 27 namespace gl 28 { 29 30 bool ValidCap(const Context *context, GLenum cap) 31 { 32 switch (cap) 33 { 34 case GL_CULL_FACE: 35 case GL_POLYGON_OFFSET_FILL: 36 case GL_SAMPLE_ALPHA_TO_COVERAGE: 37 case GL_SAMPLE_COVERAGE: 38 case GL_SCISSOR_TEST: 39 case GL_STENCIL_TEST: 40 case GL_DEPTH_TEST: 41 case GL_BLEND: 42 case GL_DITHER: 43 return true; 44 case GL_PRIMITIVE_RESTART_FIXED_INDEX: 45 case GL_RASTERIZER_DISCARD: 46 return (context->getClientVersion() >= 3); 47 default: 48 return false; 49 } 50 } 51 52 bool ValidTextureTarget(const Context *context, GLenum target) 53 { 54 switch (target) 55 { 56 case GL_TEXTURE_2D: 57 case GL_TEXTURE_CUBE_MAP: 58 return true; 59 60 case GL_TEXTURE_3D: 61 case GL_TEXTURE_2D_ARRAY: 62 return (context->getClientVersion() >= 3); 63 64 default: 65 return false; 66 } 67 } 68 69 // This function differs from ValidTextureTarget in that the target must be 70 // usable as the destination of a 2D operation-- so a cube face is valid, but 71 // GL_TEXTURE_CUBE_MAP is not. 72 // Note: duplicate of IsInternalTextureTarget 73 bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) 74 { 75 switch (target) 76 { 77 case GL_TEXTURE_2D: 78 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 79 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 80 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 81 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 82 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 83 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 84 return true; 85 case GL_TEXTURE_2D_ARRAY: 86 case GL_TEXTURE_3D: 87 return (context->getClientVersion() >= 3); 88 default: 89 return false; 90 } 91 } 92 93 bool ValidFramebufferTarget(GLenum target) 94 { 95 META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER); 96 97 switch (target) 98 { 99 case GL_FRAMEBUFFER: return true; 100 case GL_READ_FRAMEBUFFER: return true; 101 case GL_DRAW_FRAMEBUFFER: return true; 102 default: return false; 103 } 104 } 105 106 bool ValidBufferTarget(const Context *context, GLenum target) 107 { 108 switch (target) 109 { 110 case GL_ARRAY_BUFFER: 111 case GL_ELEMENT_ARRAY_BUFFER: 112 return true; 113 114 case GL_PIXEL_PACK_BUFFER: 115 case GL_PIXEL_UNPACK_BUFFER: 116 return context->getExtensions().pixelBufferObject; 117 118 case GL_COPY_READ_BUFFER: 119 case GL_COPY_WRITE_BUFFER: 120 case GL_TRANSFORM_FEEDBACK_BUFFER: 121 case GL_UNIFORM_BUFFER: 122 return (context->getClientVersion() >= 3); 123 124 default: 125 return false; 126 } 127 } 128 129 bool ValidBufferParameter(const Context *context, GLenum pname) 130 { 131 switch (pname) 132 { 133 case GL_BUFFER_USAGE: 134 case GL_BUFFER_SIZE: 135 return true; 136 137 // GL_BUFFER_MAP_POINTER is a special case, and may only be 138 // queried with GetBufferPointerv 139 case GL_BUFFER_ACCESS_FLAGS: 140 case GL_BUFFER_MAPPED: 141 case GL_BUFFER_MAP_OFFSET: 142 case GL_BUFFER_MAP_LENGTH: 143 return (context->getClientVersion() >= 3); 144 145 default: 146 return false; 147 } 148 } 149 150 bool ValidMipLevel(const Context *context, GLenum target, GLint level) 151 { 152 size_t maxDimension = 0; 153 switch (target) 154 { 155 case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break; 156 case GL_TEXTURE_CUBE_MAP: 157 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 158 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 159 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 160 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 161 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 162 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break; 163 case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break; 164 case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break; 165 default: UNREACHABLE(); 166 } 167 168 return level <= gl::log2(maxDimension); 169 } 170 171 bool ValidImageSize(const Context *context, GLenum target, GLint level, 172 GLsizei width, GLsizei height, GLsizei depth) 173 { 174 if (level < 0 || width < 0 || height < 0 || depth < 0) 175 { 176 return false; 177 } 178 179 if (!context->getExtensions().textureNPOT && 180 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))) 181 { 182 return false; 183 } 184 185 if (!ValidMipLevel(context, target, level)) 186 { 187 return false; 188 } 189 190 return true; 191 } 192 193 bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height) 194 { 195 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); 196 if (!formatInfo.compressed) 197 { 198 return false; 199 } 200 201 if (width < 0 || (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) || 202 height < 0 || (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0)) 203 { 204 return false; 205 } 206 207 return true; 208 } 209 210 bool ValidQueryType(const Context *context, GLenum queryType) 211 { 212 META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT); 213 META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); 214 215 switch (queryType) 216 { 217 case GL_ANY_SAMPLES_PASSED: 218 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: 219 return true; 220 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: 221 return (context->getClientVersion() >= 3); 222 default: 223 return false; 224 } 225 } 226 227 bool ValidProgram(Context *context, GLuint id) 228 { 229 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the 230 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and 231 // INVALID_OPERATION if the provided name identifies an object that is not the expected type." 232 233 if (context->getProgram(id) != NULL) 234 { 235 return true; 236 } 237 else if (context->getShader(id) != NULL) 238 { 239 // ID is the wrong type 240 context->recordError(Error(GL_INVALID_OPERATION)); 241 return false; 242 } 243 else 244 { 245 // No shader/program object has this ID 246 context->recordError(Error(GL_INVALID_VALUE)); 247 return false; 248 } 249 } 250 251 bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) 252 { 253 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) 254 { 255 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); 256 257 if (colorAttachment >= context->getCaps().maxColorAttachments) 258 { 259 context->recordError(Error(GL_INVALID_VALUE)); 260 return false; 261 } 262 } 263 else 264 { 265 switch (attachment) 266 { 267 case GL_DEPTH_ATTACHMENT: 268 case GL_STENCIL_ATTACHMENT: 269 break; 270 271 case GL_DEPTH_STENCIL_ATTACHMENT: 272 if (context->getClientVersion() < 3) 273 { 274 context->recordError(Error(GL_INVALID_ENUM)); 275 return false; 276 } 277 break; 278 279 default: 280 context->recordError(Error(GL_INVALID_ENUM)); 281 return false; 282 } 283 } 284 285 return true; 286 } 287 288 bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, 289 GLenum internalformat, GLsizei width, GLsizei height, 290 bool angleExtension) 291 { 292 switch (target) 293 { 294 case GL_RENDERBUFFER: 295 break; 296 default: 297 context->recordError(Error(GL_INVALID_ENUM)); 298 return false; 299 } 300 301 if (width < 0 || height < 0 || samples < 0) 302 { 303 context->recordError(Error(GL_INVALID_VALUE)); 304 return false; 305 } 306 307 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); 308 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) 309 { 310 context->recordError(Error(GL_INVALID_ENUM)); 311 return false; 312 } 313 314 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be 315 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains 316 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the 317 // internal format must be sized and not an integer format if samples is greater than zero. 318 if (formatInfo.pixelBytes == 0) 319 { 320 context->recordError(Error(GL_INVALID_ENUM)); 321 return false; 322 } 323 324 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) 325 { 326 context->recordError(Error(GL_INVALID_OPERATION)); 327 return false; 328 } 329 330 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); 331 if (!formatCaps.renderable) 332 { 333 context->recordError(Error(GL_INVALID_ENUM)); 334 return false; 335 } 336 337 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize) 338 { 339 context->recordError(Error(GL_INVALID_VALUE)); 340 return false; 341 } 342 343 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal 344 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2) 345 // states that samples must be less than or equal to the maximum samples for the specified 346 // internal format. 347 if (angleExtension) 348 { 349 ASSERT(context->getExtensions().framebufferMultisample); 350 if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples) 351 { 352 context->recordError(Error(GL_INVALID_VALUE)); 353 return false; 354 } 355 356 // Check if this specific format supports enough samples 357 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) 358 { 359 context->recordError(Error(GL_OUT_OF_MEMORY)); 360 return false; 361 } 362 } 363 else 364 { 365 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples()) 366 { 367 context->recordError(Error(GL_INVALID_VALUE)); 368 return false; 369 } 370 } 371 372 GLuint handle = context->getState().getRenderbufferId(); 373 if (handle == 0) 374 { 375 context->recordError(Error(GL_INVALID_OPERATION)); 376 return false; 377 } 378 379 return true; 380 } 381 382 bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, 383 GLenum renderbuffertarget, GLuint renderbuffer) 384 { 385 if (!ValidFramebufferTarget(target)) 386 { 387 context->recordError(Error(GL_INVALID_ENUM)); 388 return false; 389 } 390 391 gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 392 GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); 393 394 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) 395 { 396 context->recordError(Error(GL_INVALID_OPERATION)); 397 return false; 398 } 399 400 if (!ValidateAttachmentTarget(context, attachment)) 401 { 402 return false; 403 } 404 405 // [OpenGL ES 2.0.25] Section 4.4.3 page 112 406 // [OpenGL ES 3.0.2] Section 4.4.2 page 201 407 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of 408 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. 409 if (renderbuffer != 0) 410 { 411 if (!context->getRenderbuffer(renderbuffer)) 412 { 413 context->recordError(Error(GL_INVALID_OPERATION)); 414 return false; 415 } 416 } 417 418 return true; 419 } 420 421 static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer, 422 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 423 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) 424 { 425 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || 426 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() || 427 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight()) 428 { 429 return true; 430 } 431 else if (context->getState().isScissorTestEnabled()) 432 { 433 const Rectangle &scissor = context->getState().getScissor(); 434 435 return scissor.x > 0 || scissor.y > 0 || 436 scissor.width < writeBuffer->getWidth() || 437 scissor.height < writeBuffer->getHeight(); 438 } 439 else 440 { 441 return false; 442 } 443 } 444 445 bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 446 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, 447 GLenum filter, bool fromAngleExtension) 448 { 449 switch (filter) 450 { 451 case GL_NEAREST: 452 break; 453 case GL_LINEAR: 454 if (fromAngleExtension) 455 { 456 context->recordError(Error(GL_INVALID_ENUM)); 457 return false; 458 } 459 break; 460 default: 461 context->recordError(Error(GL_INVALID_ENUM)); 462 return false; 463 } 464 465 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) 466 { 467 context->recordError(Error(GL_INVALID_VALUE)); 468 return false; 469 } 470 471 if (mask == 0) 472 { 473 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no 474 // buffers are copied. 475 return false; 476 } 477 478 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) 479 { 480 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); 481 context->recordError(Error(GL_INVALID_OPERATION)); 482 return false; 483 } 484 485 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the 486 // color buffer, leaving only nearest being unfiltered from above 487 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST) 488 { 489 context->recordError(Error(GL_INVALID_OPERATION)); 490 return false; 491 } 492 493 if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) 494 { 495 if (fromAngleExtension) 496 { 497 ERR("Blits with the same source and destination framebuffer are not supported by this " 498 "implementation."); 499 } 500 context->recordError(Error(GL_INVALID_OPERATION)); 501 return false; 502 } 503 504 gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); 505 gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); 506 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || 507 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) 508 { 509 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); 510 return false; 511 } 512 513 if (drawFramebuffer->getSamples() != 0) 514 { 515 context->recordError(Error(GL_INVALID_OPERATION)); 516 return false; 517 } 518 519 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; 520 521 if (mask & GL_COLOR_BUFFER_BIT) 522 { 523 gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); 524 gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); 525 526 if (readColorBuffer && drawColorBuffer) 527 { 528 GLenum readInternalFormat = readColorBuffer->getActualFormat(); 529 const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat); 530 531 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) 532 { 533 if (drawFramebuffer->isEnabledColorAttachment(i)) 534 { 535 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat(); 536 const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat); 537 538 // The GL ES 3.0.2 spec (pg 193) states that: 539 // 1) If the read buffer is fixed point format, the draw buffer must be as well 540 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well 541 // 3) If the read buffer is a signed integer format, the draw buffer must be as well 542 if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) && 543 !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED)) 544 { 545 context->recordError(Error(GL_INVALID_OPERATION)); 546 return false; 547 } 548 549 if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT) 550 { 551 context->recordError(Error(GL_INVALID_OPERATION)); 552 return false; 553 } 554 555 if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT) 556 { 557 context->recordError(Error(GL_INVALID_OPERATION)); 558 return false; 559 } 560 561 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds)) 562 { 563 context->recordError(Error(GL_INVALID_OPERATION)); 564 return false; 565 } 566 } 567 } 568 569 if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) 570 { 571 context->recordError(Error(GL_INVALID_OPERATION)); 572 return false; 573 } 574 575 if (fromAngleExtension) 576 { 577 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); 578 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER) 579 { 580 context->recordError(Error(GL_INVALID_OPERATION)); 581 return false; 582 } 583 584 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 585 { 586 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) 587 { 588 FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); 589 ASSERT(attachment); 590 591 if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER) 592 { 593 context->recordError(Error(GL_INVALID_OPERATION)); 594 return false; 595 } 596 597 if (attachment->getActualFormat() != readColorBuffer->getActualFormat()) 598 { 599 context->recordError(Error(GL_INVALID_OPERATION)); 600 return false; 601 } 602 } 603 } 604 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, 605 srcX0, srcY0, srcX1, srcY1, 606 dstX0, dstY0, dstX1, dstY1)) 607 { 608 context->recordError(Error(GL_INVALID_OPERATION)); 609 return false; 610 } 611 } 612 } 613 } 614 615 if (mask & GL_DEPTH_BUFFER_BIT) 616 { 617 gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer(); 618 gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer(); 619 620 if (readDepthBuffer && drawDepthBuffer) 621 { 622 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat()) 623 { 624 context->recordError(Error(GL_INVALID_OPERATION)); 625 return false; 626 } 627 628 if (readDepthBuffer->getSamples() > 0 && !sameBounds) 629 { 630 context->recordError(Error(GL_INVALID_OPERATION)); 631 return false; 632 } 633 634 if (fromAngleExtension) 635 { 636 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer, 637 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) 638 { 639 ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); 640 context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted 641 return false; 642 } 643 644 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0) 645 { 646 context->recordError(Error(GL_INVALID_OPERATION)); 647 return false; 648 } 649 } 650 } 651 } 652 653 if (mask & GL_STENCIL_BUFFER_BIT) 654 { 655 gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer(); 656 gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); 657 658 if (readStencilBuffer && drawStencilBuffer) 659 { 660 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) 661 { 662 context->recordError(Error(GL_INVALID_OPERATION)); 663 return false; 664 } 665 666 if (readStencilBuffer->getSamples() > 0 && !sameBounds) 667 { 668 context->recordError(Error(GL_INVALID_OPERATION)); 669 return false; 670 } 671 672 if (fromAngleExtension) 673 { 674 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer, 675 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) 676 { 677 ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); 678 context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted 679 return false; 680 } 681 682 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0) 683 { 684 context->recordError(Error(GL_INVALID_OPERATION)); 685 return false; 686 } 687 } 688 } 689 } 690 691 return true; 692 } 693 694 bool ValidateGetVertexAttribParameters(Context *context, GLenum pname) 695 { 696 switch (pname) 697 { 698 case GL_VERTEX_ATTRIB_ARRAY_ENABLED: 699 case GL_VERTEX_ATTRIB_ARRAY_SIZE: 700 case GL_VERTEX_ATTRIB_ARRAY_STRIDE: 701 case GL_VERTEX_ATTRIB_ARRAY_TYPE: 702 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: 703 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 704 case GL_CURRENT_VERTEX_ATTRIB: 705 return true; 706 707 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: 708 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses 709 // the same constant. 710 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); 711 return true; 712 713 case GL_VERTEX_ATTRIB_ARRAY_INTEGER: 714 if (context->getClientVersion() < 3) 715 { 716 context->recordError(Error(GL_INVALID_ENUM)); 717 return false; 718 } 719 return true; 720 721 default: 722 context->recordError(Error(GL_INVALID_ENUM)); 723 return false; 724 } 725 } 726 727 bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) 728 { 729 switch (pname) 730 { 731 case GL_TEXTURE_WRAP_R: 732 case GL_TEXTURE_SWIZZLE_R: 733 case GL_TEXTURE_SWIZZLE_G: 734 case GL_TEXTURE_SWIZZLE_B: 735 case GL_TEXTURE_SWIZZLE_A: 736 case GL_TEXTURE_BASE_LEVEL: 737 case GL_TEXTURE_MAX_LEVEL: 738 case GL_TEXTURE_COMPARE_MODE: 739 case GL_TEXTURE_COMPARE_FUNC: 740 case GL_TEXTURE_MIN_LOD: 741 case GL_TEXTURE_MAX_LOD: 742 if (context->getClientVersion() < 3) 743 { 744 context->recordError(Error(GL_INVALID_ENUM)); 745 return false; 746 } 747 break; 748 749 default: break; 750 } 751 752 switch (pname) 753 { 754 case GL_TEXTURE_WRAP_S: 755 case GL_TEXTURE_WRAP_T: 756 case GL_TEXTURE_WRAP_R: 757 switch (param) 758 { 759 case GL_REPEAT: 760 case GL_CLAMP_TO_EDGE: 761 case GL_MIRRORED_REPEAT: 762 return true; 763 default: 764 context->recordError(Error(GL_INVALID_ENUM)); 765 return false; 766 } 767 768 case GL_TEXTURE_MIN_FILTER: 769 switch (param) 770 { 771 case GL_NEAREST: 772 case GL_LINEAR: 773 case GL_NEAREST_MIPMAP_NEAREST: 774 case GL_LINEAR_MIPMAP_NEAREST: 775 case GL_NEAREST_MIPMAP_LINEAR: 776 case GL_LINEAR_MIPMAP_LINEAR: 777 return true; 778 default: 779 context->recordError(Error(GL_INVALID_ENUM)); 780 return false; 781 } 782 break; 783 784 case GL_TEXTURE_MAG_FILTER: 785 switch (param) 786 { 787 case GL_NEAREST: 788 case GL_LINEAR: 789 return true; 790 default: 791 context->recordError(Error(GL_INVALID_ENUM)); 792 return false; 793 } 794 break; 795 796 case GL_TEXTURE_USAGE_ANGLE: 797 switch (param) 798 { 799 case GL_NONE: 800 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: 801 return true; 802 default: 803 context->recordError(Error(GL_INVALID_ENUM)); 804 return false; 805 } 806 break; 807 808 case GL_TEXTURE_MAX_ANISOTROPY_EXT: 809 if (!context->getExtensions().textureFilterAnisotropic) 810 { 811 context->recordError(Error(GL_INVALID_ENUM)); 812 return false; 813 } 814 815 // we assume the parameter passed to this validation method is truncated, not rounded 816 if (param < 1) 817 { 818 context->recordError(Error(GL_INVALID_VALUE)); 819 return false; 820 } 821 return true; 822 823 case GL_TEXTURE_MIN_LOD: 824 case GL_TEXTURE_MAX_LOD: 825 // any value is permissible 826 return true; 827 828 case GL_TEXTURE_COMPARE_MODE: 829 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17 830 switch (param) 831 { 832 case GL_NONE: 833 case GL_COMPARE_REF_TO_TEXTURE: 834 return true; 835 default: 836 context->recordError(Error(GL_INVALID_ENUM)); 837 return false; 838 } 839 break; 840 841 case GL_TEXTURE_COMPARE_FUNC: 842 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17 843 switch (param) 844 { 845 case GL_LEQUAL: 846 case GL_GEQUAL: 847 case GL_LESS: 848 case GL_GREATER: 849 case GL_EQUAL: 850 case GL_NOTEQUAL: 851 case GL_ALWAYS: 852 case GL_NEVER: 853 return true; 854 default: 855 context->recordError(Error(GL_INVALID_ENUM)); 856 return false; 857 } 858 break; 859 860 case GL_TEXTURE_SWIZZLE_R: 861 case GL_TEXTURE_SWIZZLE_G: 862 case GL_TEXTURE_SWIZZLE_B: 863 case GL_TEXTURE_SWIZZLE_A: 864 switch (param) 865 { 866 case GL_RED: 867 case GL_GREEN: 868 case GL_BLUE: 869 case GL_ALPHA: 870 case GL_ZERO: 871 case GL_ONE: 872 return true; 873 default: 874 context->recordError(Error(GL_INVALID_ENUM)); 875 return false; 876 } 877 break; 878 879 case GL_TEXTURE_BASE_LEVEL: 880 case GL_TEXTURE_MAX_LEVEL: 881 if (param < 0) 882 { 883 context->recordError(Error(GL_INVALID_VALUE)); 884 return false; 885 } 886 return true; 887 888 default: 889 context->recordError(Error(GL_INVALID_ENUM)); 890 return false; 891 } 892 } 893 894 bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname) 895 { 896 switch (pname) 897 { 898 case GL_TEXTURE_MIN_FILTER: 899 case GL_TEXTURE_MAG_FILTER: 900 case GL_TEXTURE_WRAP_S: 901 case GL_TEXTURE_WRAP_T: 902 case GL_TEXTURE_WRAP_R: 903 case GL_TEXTURE_MIN_LOD: 904 case GL_TEXTURE_MAX_LOD: 905 case GL_TEXTURE_COMPARE_MODE: 906 case GL_TEXTURE_COMPARE_FUNC: 907 return true; 908 909 default: 910 context->recordError(Error(GL_INVALID_ENUM)); 911 return false; 912 } 913 } 914 915 bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, 916 GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels) 917 { 918 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); 919 ASSERT(framebuffer); 920 921 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) 922 { 923 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); 924 return false; 925 } 926 927 if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) 928 { 929 context->recordError(Error(GL_INVALID_OPERATION)); 930 return false; 931 } 932 933 if (!framebuffer->getReadColorbuffer()) 934 { 935 context->recordError(Error(GL_INVALID_OPERATION)); 936 return false; 937 } 938 939 GLenum currentInternalFormat, currentFormat, currentType; 940 GLuint clientVersion = context->getClientVersion(); 941 942 context->getCurrentReadFormatType(¤tInternalFormat, ¤tFormat, ¤tType); 943 944 bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) : 945 ValidES3ReadFormatType(context, currentInternalFormat, format, type); 946 947 if (!(currentFormat == format && currentType == type) && !validReadFormat) 948 { 949 context->recordError(Error(GL_INVALID_OPERATION)); 950 return false; 951 } 952 953 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); 954 const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); 955 956 GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment()); 957 // sized query sanity check 958 if (bufSize) 959 { 960 int requiredSize = outputPitch * height; 961 if (requiredSize > *bufSize) 962 { 963 context->recordError(Error(GL_INVALID_OPERATION)); 964 return false; 965 } 966 } 967 968 return true; 969 } 970 971 bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) 972 { 973 if (!ValidQueryType(context, target)) 974 { 975 context->recordError(Error(GL_INVALID_ENUM)); 976 return false; 977 } 978 979 if (id == 0) 980 { 981 context->recordError(Error(GL_INVALID_OPERATION)); 982 return false; 983 } 984 985 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id> 986 // of zero, if the active query object name for <target> is non-zero (for the 987 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if 988 // the active query for either target is non-zero), if <id> is the name of an 989 // existing query object whose type does not match <target>, or if <id> is the 990 // active query object name for any query type, the error INVALID_OPERATION is 991 // generated. 992 993 // Ensure no other queries are active 994 // NOTE: If other queries than occlusion are supported, we will need to check 995 // separately that: 996 // a) The query ID passed is not the current active query for any target/type 997 // b) There are no active queries for the requested target (and in the case 998 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, 999 // no query may be active for either if glBeginQuery targets either. 1000 if (context->getState().isQueryActive()) 1001 { 1002 context->recordError(Error(GL_INVALID_OPERATION)); 1003 return false; 1004 } 1005 1006 Query *queryObject = context->getQuery(id, true, target); 1007 1008 // check that name was obtained with glGenQueries 1009 if (!queryObject) 1010 { 1011 context->recordError(Error(GL_INVALID_OPERATION)); 1012 return false; 1013 } 1014 1015 // check for type mismatch 1016 if (queryObject->getType() != target) 1017 { 1018 context->recordError(Error(GL_INVALID_OPERATION)); 1019 return false; 1020 } 1021 1022 return true; 1023 } 1024 1025 bool ValidateEndQuery(gl::Context *context, GLenum target) 1026 { 1027 if (!ValidQueryType(context, target)) 1028 { 1029 context->recordError(Error(GL_INVALID_ENUM)); 1030 return false; 1031 } 1032 1033 const Query *queryObject = context->getState().getActiveQuery(target); 1034 1035 if (queryObject == NULL) 1036 { 1037 context->recordError(Error(GL_INVALID_OPERATION)); 1038 return false; 1039 } 1040 1041 return true; 1042 } 1043 1044 static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType, 1045 GLint location, GLsizei count, LinkedUniform **uniformOut) 1046 { 1047 if (count < 0) 1048 { 1049 context->recordError(Error(GL_INVALID_VALUE)); 1050 return false; 1051 } 1052 1053 gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); 1054 if (!programBinary) 1055 { 1056 context->recordError(Error(GL_INVALID_OPERATION)); 1057 return false; 1058 } 1059 1060 if (location == -1) 1061 { 1062 // Silently ignore the uniform command 1063 return false; 1064 } 1065 1066 if (!programBinary->isValidUniformLocation(location)) 1067 { 1068 context->recordError(Error(GL_INVALID_OPERATION)); 1069 return false; 1070 } 1071 1072 LinkedUniform *uniform = programBinary->getUniformByLocation(location); 1073 1074 // attempting to write an array to a non-array uniform is an INVALID_OPERATION 1075 if (uniform->elementCount() == 1 && count > 1) 1076 { 1077 context->recordError(Error(GL_INVALID_OPERATION)); 1078 return false; 1079 } 1080 1081 *uniformOut = uniform; 1082 return true; 1083 } 1084 1085 bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count) 1086 { 1087 // Check for ES3 uniform entry points 1088 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) 1089 { 1090 context->recordError(Error(GL_INVALID_OPERATION)); 1091 return false; 1092 } 1093 1094 LinkedUniform *uniform = NULL; 1095 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform)) 1096 { 1097 return false; 1098 } 1099 1100 GLenum targetBoolType = VariableBoolVectorType(uniformType); 1101 bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT); 1102 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) 1103 { 1104 context->recordError(Error(GL_INVALID_OPERATION)); 1105 return false; 1106 } 1107 1108 return true; 1109 } 1110 1111 bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, 1112 GLboolean transpose) 1113 { 1114 // Check for ES3 uniform entry points 1115 int rows = VariableRowCount(matrixType); 1116 int cols = VariableColumnCount(matrixType); 1117 if (rows != cols && context->getClientVersion() < 3) 1118 { 1119 context->recordError(Error(GL_INVALID_OPERATION)); 1120 return false; 1121 } 1122 1123 if (transpose != GL_FALSE && context->getClientVersion() < 3) 1124 { 1125 context->recordError(Error(GL_INVALID_VALUE)); 1126 return false; 1127 } 1128 1129 LinkedUniform *uniform = NULL; 1130 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform)) 1131 { 1132 return false; 1133 } 1134 1135 if (uniform->type != matrixType) 1136 { 1137 context->recordError(Error(GL_INVALID_OPERATION)); 1138 return false; 1139 } 1140 1141 return true; 1142 } 1143 1144 bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams) 1145 { 1146 if (!context->getQueryParameterInfo(pname, nativeType, numParams)) 1147 { 1148 context->recordError(Error(GL_INVALID_ENUM)); 1149 return false; 1150 } 1151 1152 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) 1153 { 1154 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0); 1155 1156 if (colorAttachment >= context->getCaps().maxDrawBuffers) 1157 { 1158 context->recordError(Error(GL_INVALID_OPERATION)); 1159 return false; 1160 } 1161 } 1162 1163 switch (pname) 1164 { 1165 case GL_TEXTURE_BINDING_2D: 1166 case GL_TEXTURE_BINDING_CUBE_MAP: 1167 case GL_TEXTURE_BINDING_3D: 1168 case GL_TEXTURE_BINDING_2D_ARRAY: 1169 if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits) 1170 { 1171 context->recordError(Error(GL_INVALID_OPERATION)); 1172 return false; 1173 } 1174 break; 1175 1176 case GL_IMPLEMENTATION_COLOR_READ_TYPE: 1177 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: 1178 { 1179 Framebuffer *framebuffer = context->getState().getReadFramebuffer(); 1180 ASSERT(framebuffer); 1181 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) 1182 { 1183 context->recordError(Error(GL_INVALID_OPERATION)); 1184 return false; 1185 } 1186 1187 FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); 1188 if (!attachment) 1189 { 1190 context->recordError(Error(GL_INVALID_OPERATION)); 1191 return false; 1192 } 1193 } 1194 break; 1195 1196 default: 1197 break; 1198 } 1199 1200 // pname is valid, but there are no parameters to return 1201 if (numParams == 0) 1202 { 1203 return false; 1204 } 1205 1206 return true; 1207 } 1208 1209 bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, 1210 GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, 1211 GLint border, GLenum *textureFormatOut) 1212 { 1213 1214 if (!ValidTexture2DDestinationTarget(context, target)) 1215 { 1216 context->recordError(Error(GL_INVALID_ENUM)); 1217 return false; 1218 } 1219 1220 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) 1221 { 1222 context->recordError(Error(GL_INVALID_VALUE)); 1223 return false; 1224 } 1225 1226 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height) 1227 { 1228 context->recordError(Error(GL_INVALID_VALUE)); 1229 return false; 1230 } 1231 1232 if (border != 0) 1233 { 1234 context->recordError(Error(GL_INVALID_VALUE)); 1235 return false; 1236 } 1237 1238 if (!ValidMipLevel(context, target, level)) 1239 { 1240 context->recordError(Error(GL_INVALID_VALUE)); 1241 return false; 1242 } 1243 1244 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); 1245 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) 1246 { 1247 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); 1248 return false; 1249 } 1250 1251 if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) 1252 { 1253 context->recordError(Error(GL_INVALID_OPERATION)); 1254 return false; 1255 } 1256 1257 const gl::Caps &caps = context->getCaps(); 1258 1259 gl::Texture *texture = NULL; 1260 GLenum textureInternalFormat = GL_NONE; 1261 GLint textureLevelWidth = 0; 1262 GLint textureLevelHeight = 0; 1263 GLint textureLevelDepth = 0; 1264 GLuint maxDimension = 0; 1265 1266 switch (target) 1267 { 1268 case GL_TEXTURE_2D: 1269 { 1270 gl::Texture2D *texture2d = context->getTexture2D(); 1271 if (texture2d) 1272 { 1273 textureInternalFormat = texture2d->getInternalFormat(level); 1274 textureLevelWidth = texture2d->getWidth(level); 1275 textureLevelHeight = texture2d->getHeight(level); 1276 textureLevelDepth = 1; 1277 texture = texture2d; 1278 maxDimension = caps.max2DTextureSize; 1279 } 1280 } 1281 break; 1282 1283 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1284 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1285 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1286 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1287 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1288 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1289 { 1290 gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); 1291 if (textureCube) 1292 { 1293 textureInternalFormat = textureCube->getInternalFormat(target, level); 1294 textureLevelWidth = textureCube->getWidth(target, level); 1295 textureLevelHeight = textureCube->getHeight(target, level); 1296 textureLevelDepth = 1; 1297 texture = textureCube; 1298 maxDimension = caps.maxCubeMapTextureSize; 1299 } 1300 } 1301 break; 1302 1303 case GL_TEXTURE_2D_ARRAY: 1304 { 1305 gl::Texture2DArray *texture2dArray = context->getTexture2DArray(); 1306 if (texture2dArray) 1307 { 1308 textureInternalFormat = texture2dArray->getInternalFormat(level); 1309 textureLevelWidth = texture2dArray->getWidth(level); 1310 textureLevelHeight = texture2dArray->getHeight(level); 1311 textureLevelDepth = texture2dArray->getLayers(level); 1312 texture = texture2dArray; 1313 maxDimension = caps.max2DTextureSize; 1314 } 1315 } 1316 break; 1317 1318 case GL_TEXTURE_3D: 1319 { 1320 gl::Texture3D *texture3d = context->getTexture3D(); 1321 if (texture3d) 1322 { 1323 textureInternalFormat = texture3d->getInternalFormat(level); 1324 textureLevelWidth = texture3d->getWidth(level); 1325 textureLevelHeight = texture3d->getHeight(level); 1326 textureLevelDepth = texture3d->getDepth(level); 1327 texture = texture3d; 1328 maxDimension = caps.max3DTextureSize; 1329 } 1330 } 1331 break; 1332 1333 default: 1334 context->recordError(Error(GL_INVALID_ENUM)); 1335 return false; 1336 } 1337 1338 if (!texture) 1339 { 1340 context->recordError(Error(GL_INVALID_OPERATION)); 1341 return false; 1342 } 1343 1344 if (texture->isImmutable() && !isSubImage) 1345 { 1346 context->recordError(Error(GL_INVALID_OPERATION)); 1347 return false; 1348 } 1349 1350 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); 1351 1352 if (formatInfo.depthBits > 0) 1353 { 1354 context->recordError(Error(GL_INVALID_OPERATION)); 1355 return false; 1356 } 1357 1358 if (formatInfo.compressed) 1359 { 1360 if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) || 1361 ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight)) 1362 { 1363 context->recordError(Error(GL_INVALID_OPERATION)); 1364 return false; 1365 } 1366 } 1367 1368 if (isSubImage) 1369 { 1370 if (xoffset + width > textureLevelWidth || 1371 yoffset + height > textureLevelHeight || 1372 zoffset >= textureLevelDepth) 1373 { 1374 context->recordError(Error(GL_INVALID_VALUE)); 1375 return false; 1376 } 1377 } 1378 else 1379 { 1380 if (IsCubemapTextureTarget(target) && width != height) 1381 { 1382 context->recordError(Error(GL_INVALID_VALUE)); 1383 return false; 1384 } 1385 1386 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) 1387 { 1388 context->recordError(Error(GL_INVALID_ENUM)); 1389 return false; 1390 } 1391 1392 int maxLevelDimension = (maxDimension >> level); 1393 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension) 1394 { 1395 context->recordError(Error(GL_INVALID_VALUE)); 1396 return false; 1397 } 1398 } 1399 1400 *textureFormatOut = textureInternalFormat; 1401 return true; 1402 } 1403 1404 static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount) 1405 { 1406 switch (mode) 1407 { 1408 case GL_POINTS: 1409 case GL_LINES: 1410 case GL_LINE_LOOP: 1411 case GL_LINE_STRIP: 1412 case GL_TRIANGLES: 1413 case GL_TRIANGLE_STRIP: 1414 case GL_TRIANGLE_FAN: 1415 break; 1416 default: 1417 context->recordError(Error(GL_INVALID_ENUM)); 1418 return false; 1419 } 1420 1421 if (count < 0) 1422 { 1423 context->recordError(Error(GL_INVALID_VALUE)); 1424 return false; 1425 } 1426 1427 const State &state = context->getState(); 1428 1429 // Check for mapped buffers 1430 if (state.hasMappedBuffer(GL_ARRAY_BUFFER)) 1431 { 1432 context->recordError(Error(GL_INVALID_OPERATION)); 1433 return false; 1434 } 1435 1436 const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); 1437 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || 1438 state.getStencilRef() != state.getStencilBackRef() || 1439 depthStencilState.stencilMask != depthStencilState.stencilBackMask) 1440 { 1441 // Note: these separate values are not supported in WebGL, due to D3D's limitations. 1442 // See Section 6.10 of the WebGL 1.0 spec 1443 ERR("This ANGLE implementation does not support separate front/back stencil " 1444 "writemasks, reference values, or stencil mask values."); 1445 context->recordError(Error(GL_INVALID_OPERATION)); 1446 return false; 1447 } 1448 1449 const gl::Framebuffer *fbo = state.getDrawFramebuffer(); 1450 if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) 1451 { 1452 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); 1453 return false; 1454 } 1455 1456 if (state.getCurrentProgramId() == 0) 1457 { 1458 context->recordError(Error(GL_INVALID_OPERATION)); 1459 return false; 1460 } 1461 1462 gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); 1463 if (!programBinary->validateSamplers(NULL, context->getCaps())) 1464 { 1465 context->recordError(Error(GL_INVALID_OPERATION)); 1466 return false; 1467 } 1468 1469 // Buffer validations 1470 const VertexArray *vao = state.getVertexArray(); 1471 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) 1472 { 1473 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); 1474 bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1); 1475 if (attribActive && attrib.enabled) 1476 { 1477 gl::Buffer *buffer = attrib.buffer.get(); 1478 1479 if (buffer) 1480 { 1481 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib)); 1482 GLint64 maxVertexElement = 0; 1483 1484 if (attrib.divisor > 0) 1485 { 1486 maxVertexElement = static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor); 1487 } 1488 else 1489 { 1490 maxVertexElement = static_cast<GLint64>(maxVertex); 1491 } 1492 1493 GLint64 attribDataSize = maxVertexElement * attribStride; 1494 1495 // [OpenGL ES 3.0.2] section 2.9.4 page 40: 1496 // We can return INVALID_OPERATION if our vertex attribute does not have 1497 // enough backing data. 1498 if (attribDataSize > buffer->getSize()) 1499 { 1500 context->recordError(Error(GL_INVALID_OPERATION)); 1501 return false; 1502 } 1503 } 1504 else if (attrib.pointer == NULL) 1505 { 1506 // This is an application error that would normally result in a crash, 1507 // but we catch it and return an error 1508 context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer.")); 1509 return false; 1510 } 1511 } 1512 } 1513 1514 // No-op if zero count 1515 return (count > 0); 1516 } 1517 1518 bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) 1519 { 1520 if (first < 0) 1521 { 1522 context->recordError(Error(GL_INVALID_VALUE)); 1523 return false; 1524 } 1525 1526 const State &state = context->getState(); 1527 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); 1528 if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && 1529 curTransformFeedback->getDrawMode() != mode) 1530 { 1531 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode 1532 // that does not match the current transform feedback object's draw mode (if transform feedback 1533 // is active), (3.0.2, section 2.14, pg 86) 1534 context->recordError(Error(GL_INVALID_OPERATION)); 1535 return false; 1536 } 1537 1538 if (!ValidateDrawBase(context, mode, count, count, primcount)) 1539 { 1540 return false; 1541 } 1542 1543 return true; 1544 } 1545 1546 bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) 1547 { 1548 if (primcount < 0) 1549 { 1550 context->recordError(Error(GL_INVALID_VALUE)); 1551 return false; 1552 } 1553 1554 if (!ValidateDrawArrays(context, mode, first, count, primcount)) 1555 { 1556 return false; 1557 } 1558 1559 // No-op if zero primitive count 1560 return (primcount > 0); 1561 } 1562 1563 static bool ValidateDrawInstancedANGLE(Context *context) 1564 { 1565 // Verify there is at least one active attribute with a divisor of zero 1566 const gl::State& state = context->getState(); 1567 1568 gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); 1569 1570 const VertexArray *vao = state.getVertexArray(); 1571 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) 1572 { 1573 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); 1574 bool active = (programBinary->getSemanticIndex(attributeIndex) != -1); 1575 if (active && attrib.divisor == 0) 1576 { 1577 return true; 1578 } 1579 } 1580 1581 context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute" 1582 "has a divisor of zero.")); 1583 return false; 1584 } 1585 1586 bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) 1587 { 1588 if (!ValidateDrawInstancedANGLE(context)) 1589 { 1590 return false; 1591 } 1592 1593 return ValidateDrawArraysInstanced(context, mode, first, count, primcount); 1594 } 1595 1596 bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, 1597 const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut) 1598 { 1599 switch (type) 1600 { 1601 case GL_UNSIGNED_BYTE: 1602 case GL_UNSIGNED_SHORT: 1603 break; 1604 case GL_UNSIGNED_INT: 1605 if (!context->getExtensions().elementIndexUint) 1606 { 1607 context->recordError(Error(GL_INVALID_ENUM)); 1608 return false; 1609 } 1610 break; 1611 default: 1612 context->recordError(Error(GL_INVALID_ENUM)); 1613 return false; 1614 } 1615 1616 const State &state = context->getState(); 1617 1618 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); 1619 if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) 1620 { 1621 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced 1622 // while transform feedback is active, (3.0.2, section 2.14, pg 86) 1623 context->recordError(Error(GL_INVALID_OPERATION)); 1624 return false; 1625 } 1626 1627 // Check for mapped buffers 1628 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) 1629 { 1630 context->recordError(Error(GL_INVALID_OPERATION)); 1631 return false; 1632 } 1633 1634 const gl::VertexArray *vao = state.getVertexArray(); 1635 const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); 1636 if (!indices && !elementArrayBuffer) 1637 { 1638 context->recordError(Error(GL_INVALID_OPERATION)); 1639 return false; 1640 } 1641 1642 if (elementArrayBuffer) 1643 { 1644 const gl::Type &typeInfo = gl::GetTypeInfo(type); 1645 1646 GLint64 offset = reinterpret_cast<GLint64>(indices); 1647 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset; 1648 1649 // check for integer overflows 1650 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) || 1651 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max())) 1652 { 1653 context->recordError(Error(GL_OUT_OF_MEMORY)); 1654 return false; 1655 } 1656 1657 // Check for reading past the end of the bound buffer object 1658 if (byteCount > elementArrayBuffer->getSize()) 1659 { 1660 context->recordError(Error(GL_INVALID_OPERATION)); 1661 return false; 1662 } 1663 } 1664 else if (!indices) 1665 { 1666 // Catch this programming error here 1667 context->recordError(Error(GL_INVALID_OPERATION)); 1668 return false; 1669 } 1670 1671 // Use max index to validate if our vertex buffers are large enough for the pull. 1672 // TODO: offer fast path, with disabled index validation. 1673 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. 1674 if (elementArrayBuffer) 1675 { 1676 unsigned int offset = reinterpret_cast<unsigned int>(indices); 1677 if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) 1678 { 1679 const void *dataPointer = elementArrayBuffer->getImplementation()->getData(); 1680 const uint8_t *offsetPointer = static_cast<const uint8_t *>(dataPointer) + offset; 1681 *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); 1682 } 1683 } 1684 else 1685 { 1686 *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count); 1687 } 1688 1689 if (!ValidateDrawBase(context, mode, count, static_cast<GLsizei>(indexRangeOut->end), primcount)) 1690 { 1691 return false; 1692 } 1693 1694 return true; 1695 } 1696 1697 bool ValidateDrawElementsInstanced(Context *context, 1698 GLenum mode, GLsizei count, GLenum type, 1699 const GLvoid *indices, GLsizei primcount, 1700 rx::RangeUI *indexRangeOut) 1701 { 1702 if (primcount < 0) 1703 { 1704 context->recordError(Error(GL_INVALID_VALUE)); 1705 return false; 1706 } 1707 1708 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut)) 1709 { 1710 return false; 1711 } 1712 1713 // No-op zero primitive count 1714 return (primcount > 0); 1715 } 1716 1717 bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, 1718 const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut) 1719 { 1720 if (!ValidateDrawInstancedANGLE(context)) 1721 { 1722 return false; 1723 } 1724 1725 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut); 1726 } 1727 1728 bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, 1729 GLuint texture, GLint level) 1730 { 1731 if (!ValidFramebufferTarget(target)) 1732 { 1733 context->recordError(Error(GL_INVALID_ENUM)); 1734 return false; 1735 } 1736 1737 if (!ValidateAttachmentTarget(context, attachment)) 1738 { 1739 return false; 1740 } 1741 1742 if (texture != 0) 1743 { 1744 gl::Texture *tex = context->getTexture(texture); 1745 1746 if (tex == NULL) 1747 { 1748 context->recordError(Error(GL_INVALID_OPERATION)); 1749 return false; 1750 } 1751 1752 if (level < 0) 1753 { 1754 context->recordError(Error(GL_INVALID_VALUE)); 1755 return false; 1756 } 1757 } 1758 1759 const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); 1760 GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); 1761 1762 if (framebufferHandle == 0 || !framebuffer) 1763 { 1764 context->recordError(Error(GL_INVALID_OPERATION)); 1765 return false; 1766 } 1767 1768 return true; 1769 } 1770 1771 bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, 1772 GLenum textarget, GLuint texture, GLint level) 1773 { 1774 // Attachments are required to be bound to level 0 in ES2 1775 if (context->getClientVersion() < 3 && level != 0) 1776 { 1777 context->recordError(Error(GL_INVALID_VALUE)); 1778 return false; 1779 } 1780 1781 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) 1782 { 1783 return false; 1784 } 1785 1786 if (texture != 0) 1787 { 1788 gl::Texture *tex = context->getTexture(texture); 1789 ASSERT(tex); 1790 1791 const gl::Caps &caps = context->getCaps(); 1792 1793 switch (textarget) 1794 { 1795 case GL_TEXTURE_2D: 1796 { 1797 if (level > gl::log2(caps.max2DTextureSize)) 1798 { 1799 context->recordError(Error(GL_INVALID_VALUE)); 1800 return false; 1801 } 1802 if (tex->getTarget() != GL_TEXTURE_2D) 1803 { 1804 context->recordError(Error(GL_INVALID_OPERATION)); 1805 return false; 1806 } 1807 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex); 1808 if (tex2d->isCompressed(level)) 1809 { 1810 context->recordError(Error(GL_INVALID_OPERATION)); 1811 return false; 1812 } 1813 } 1814 break; 1815 1816 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1817 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1818 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1819 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1820 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1821 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1822 { 1823 if (level > gl::log2(caps.maxCubeMapTextureSize)) 1824 { 1825 context->recordError(Error(GL_INVALID_VALUE)); 1826 return false; 1827 } 1828 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) 1829 { 1830 context->recordError(Error(GL_INVALID_OPERATION)); 1831 return false; 1832 } 1833 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex); 1834 if (texcube->isCompressed(textarget, level)) 1835 { 1836 context->recordError(Error(GL_INVALID_OPERATION)); 1837 return false; 1838 } 1839 } 1840 break; 1841 1842 default: 1843 context->recordError(Error(GL_INVALID_ENUM)); 1844 return false; 1845 } 1846 } 1847 1848 return true; 1849 } 1850 1851 bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) 1852 { 1853 if (program == 0) 1854 { 1855 context->recordError(Error(GL_INVALID_VALUE)); 1856 return false; 1857 } 1858 1859 gl::Program *programObject = context->getProgram(program); 1860 1861 if (!programObject || !programObject->isLinked()) 1862 { 1863 context->recordError(Error(GL_INVALID_OPERATION)); 1864 return false; 1865 } 1866 1867 gl::ProgramBinary *programBinary = programObject->getProgramBinary(); 1868 if (!programBinary) 1869 { 1870 context->recordError(Error(GL_INVALID_OPERATION)); 1871 return false; 1872 } 1873 1874 if (!programBinary->isValidUniformLocation(location)) 1875 { 1876 context->recordError(Error(GL_INVALID_OPERATION)); 1877 return false; 1878 } 1879 1880 return true; 1881 } 1882 1883 bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params) 1884 { 1885 return ValidateGetUniformBase(context, program, location); 1886 } 1887 1888 bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params) 1889 { 1890 return ValidateGetUniformBase(context, program, location); 1891 } 1892 1893 static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize) 1894 { 1895 if (!ValidateGetUniformBase(context, program, location)) 1896 { 1897 return false; 1898 } 1899 1900 gl::Program *programObject = context->getProgram(program); 1901 ASSERT(programObject); 1902 gl::ProgramBinary *programBinary = programObject->getProgramBinary(); 1903 1904 // sized queries -- ensure the provided buffer is large enough 1905 LinkedUniform *uniform = programBinary->getUniformByLocation(location); 1906 size_t requiredBytes = VariableExternalSize(uniform->type); 1907 if (static_cast<size_t>(bufSize) < requiredBytes) 1908 { 1909 context->recordError(Error(GL_INVALID_OPERATION)); 1910 return false; 1911 } 1912 1913 return true; 1914 } 1915 1916 bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params) 1917 { 1918 return ValidateSizedGetUniform(context, program, location, bufSize); 1919 } 1920 1921 bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params) 1922 { 1923 return ValidateSizedGetUniform(context, program, location, bufSize); 1924 } 1925 1926 } 1927