// // Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // validationESEXT.cpp: Validation functions for OpenGL ES extension entry points. #include "libANGLE/validationESEXT_autogen.h" #include "libANGLE/Context.h" #include "libANGLE/ErrorStrings.h" #include "libANGLE/validationES.h" #include "libANGLE/validationES32.h" namespace gl { using namespace err; namespace { template bool ValidateGetImageFormatAndType(const Context *context, ObjectT *obj, GLenum format, GLenum type) { GLenum implFormat = obj->getImplementationColorReadFormat(context); if (!ValidES3Format(format) && (format != implFormat || format == GL_NONE)) { context->validationError(GL_INVALID_ENUM, kInvalidFormat); return false; } GLenum implType = obj->getImplementationColorReadType(context); if (!ValidES3Type(type) && (type != implType || type == GL_NONE)) { context->validationError(GL_INVALID_ENUM, kInvalidType); return false; } // Format/type combinations are not yet validated. return true; } } // namespace bool ValidateGetTexImageANGLE(const Context *context, TextureTarget target, GLint level, GLenum format, GLenum type, const void *pixels) { if (!context->getExtensions().getImageANGLE) { context->validationError(GL_INVALID_OPERATION, kGetImageExtensionNotEnabled); return false; } if (!ValidTexture2DDestinationTarget(context, target) && !ValidTexture3DDestinationTarget(context, target)) { context->validationError(GL_INVALID_ENUM, kInvalidTextureTarget); return false; } if (level < 0) { context->validationError(GL_INVALID_VALUE, kNegativeLevel); return false; } TextureType textureType = TextureTargetToType(target); if (!ValidMipLevel(context, textureType, level)) { context->validationError(GL_INVALID_VALUE, kInvalidMipLevel); return false; } Texture *texture = context->getTextureByTarget(target); if (!ValidateGetImageFormatAndType(context, texture, format, type)) { return false; } GLsizei width = static_cast(texture->getWidth(target, level)); GLsizei height = static_cast(texture->getHeight(target, level)); if (!ValidatePixelPack(context, format, type, 0, 0, width, height, -1, nullptr, pixels)) { return false; } return true; } bool ValidateGetRenderbufferImageANGLE(const Context *context, GLenum target, GLenum format, GLenum type, const void *pixels) { if (!context->getExtensions().getImageANGLE) { context->validationError(GL_INVALID_OPERATION, kGetImageExtensionNotEnabled); return false; } if (target != GL_RENDERBUFFER) { context->validationError(GL_INVALID_ENUM, kInvalidRenderbufferTarget); return false; } Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); if (!ValidateGetImageFormatAndType(context, renderbuffer, format, type)) { return false; } GLsizei width = renderbuffer->getWidth(); GLsizei height = renderbuffer->getHeight(); if (!ValidatePixelPack(context, format, type, 0, 0, width, height, -1, nullptr, pixels)) { return false; } return true; } bool ValidateDrawElementsBaseVertexEXT(const Context *context, PrimitiveMode mode, GLsizei count, DrawElementsType type, const void *indices, GLint basevertex) { if (!context->getExtensions().drawElementsBaseVertexAny()) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateDrawElementsCommon(context, mode, count, type, indices, 1); } bool ValidateDrawElementsInstancedBaseVertexEXT(const Context *context, PrimitiveMode mode, GLsizei count, DrawElementsType type, const void *indices, GLsizei instancecount, GLint basevertex) { if (!context->getExtensions().drawElementsBaseVertexAny()) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, instancecount); } bool ValidateDrawRangeElementsBaseVertexEXT(const Context *context, PrimitiveMode mode, GLuint start, GLuint end, GLsizei count, DrawElementsType type, const void *indices, GLint basevertex) { if (!context->getExtensions().drawElementsBaseVertexAny()) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } if (end < start) { context->validationError(GL_INVALID_VALUE, kInvalidElementRange); return false; } if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0)) { return false; } // Skip range checks for no-op calls. if (count <= 0) { return true; } // Note that resolving the index range is a bit slow. We should probably optimize this. IndexRange indexRange; ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, indices, &indexRange)); if (indexRange.end > end || indexRange.start < start) { // GL spec says that behavior in this case is undefined - generating an error is fine. context->validationError(GL_INVALID_OPERATION, kExceedsElementRange); return false; } return true; } bool ValidateMultiDrawElementsBaseVertexEXT(const Context *context, PrimitiveMode mode, const GLsizei *count, DrawElementsType type, const void *const *indices, GLsizei drawcount, const GLint *basevertex) { return true; } bool ValidateDrawElementsBaseVertexOES(const Context *context, PrimitiveMode mode, GLsizei count, DrawElementsType type, const void *indices, GLint basevertex) { if (!context->getExtensions().drawElementsBaseVertexAny()) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateDrawElementsCommon(context, mode, count, type, indices, 1); } bool ValidateDrawElementsInstancedBaseVertexOES(const Context *context, PrimitiveMode mode, GLsizei count, DrawElementsType type, const void *indices, GLsizei instancecount, GLint basevertex) { if (!context->getExtensions().drawElementsBaseVertexAny()) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, instancecount); } bool ValidateDrawRangeElementsBaseVertexOES(const Context *context, PrimitiveMode mode, GLuint start, GLuint end, GLsizei count, DrawElementsType type, const void *indices, GLint basevertex) { if (!context->getExtensions().drawElementsBaseVertexAny()) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } if (end < start) { context->validationError(GL_INVALID_VALUE, kInvalidElementRange); return false; } if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0)) { return false; } // Skip range checks for no-op calls. if (count <= 0) { return true; } // Note that resolving the index range is a bit slow. We should probably optimize this. IndexRange indexRange; ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, indices, &indexRange)); if (indexRange.end > end || indexRange.start < start) { // GL spec says that behavior in this case is undefined - generating an error is fine. context->validationError(GL_INVALID_OPERATION, kExceedsElementRange); return false; } return true; } bool ValidateBlendEquationSeparateiEXT(const Context *context, GLuint buf, GLenum modeRGB, GLenum modeAlpha) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendEquationSeparatei(context, buf, modeRGB, modeAlpha); } bool ValidateBlendEquationiEXT(const Context *context, GLuint buf, GLenum mode) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendEquationi(context, buf, mode); } bool ValidateBlendFuncSeparateiEXT(const Context *context, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendFuncSeparatei(context, buf, srcRGB, dstRGB, srcAlpha, dstAlpha); } bool ValidateBlendFunciEXT(const Context *context, GLuint buf, GLenum src, GLenum dst) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendFunci(context, buf, src, dst); } bool ValidateColorMaskiEXT(const Context *context, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateColorMaski(context, index, r, g, b, a); } bool ValidateDisableiEXT(const Context *context, GLenum target, GLuint index) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateDisablei(context, target, index); } bool ValidateEnableiEXT(const Context *context, GLenum target, GLuint index) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateEnablei(context, target, index); } bool ValidateIsEnablediEXT(const Context *context, GLenum target, GLuint index) { if (!context->getExtensions().drawBuffersIndexedEXT) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateIsEnabledi(context, target, index); } bool ValidateBlendEquationSeparateiOES(const Context *context, GLuint buf, GLenum modeRGB, GLenum modeAlpha) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendEquationSeparatei(context, buf, modeRGB, modeAlpha); } bool ValidateBlendEquationiOES(const Context *context, GLuint buf, GLenum mode) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendEquationi(context, buf, mode); } bool ValidateBlendFuncSeparateiOES(const Context *context, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendFuncSeparatei(context, buf, srcRGB, dstRGB, srcAlpha, dstAlpha); } bool ValidateBlendFunciOES(const Context *context, GLuint buf, GLenum src, GLenum dst) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateBlendFunci(context, buf, src, dst); } bool ValidateColorMaskiOES(const Context *context, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateColorMaski(context, index, r, g, b, a); } bool ValidateDisableiOES(const Context *context, GLenum target, GLuint index) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateDisablei(context, target, index); } bool ValidateEnableiOES(const Context *context, GLenum target, GLuint index) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateEnablei(context, target, index); } bool ValidateIsEnablediOES(const Context *context, GLenum target, GLuint index) { if (!context->getExtensions().drawBuffersIndexedOES) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } return ValidateIsEnabledi(context, target, index); } bool ValidateGetInteger64vEXT(const Context *context, GLenum pname, const GLint64 *data) { if (!context->getExtensions().disjointTimerQuery) { context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled); return false; } GLenum nativeType = GL_NONE; unsigned int numParams = 0; if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { return false; } return true; } } // namespace gl