summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/validationES.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/validationES.h')
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES.h956
1 files changed, 956 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/validationES.h b/gfx/angle/checkout/src/libANGLE/validationES.h
new file mode 100644
index 0000000000..b6aeb2683e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES.h
@@ -0,0 +1,956 @@
+//
+// Copyright (c) 2013 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.
+//
+
+// validationES.h: Validation functions for generic OpenGL ES entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES_H_
+#define LIBANGLE_VALIDATION_ES_H_
+
+#include "common/PackedEnums.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/VertexArray.h"
+
+#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+
+namespace egl
+{
+class Display;
+class Image;
+} // namespace egl
+
+namespace gl
+{
+class Context;
+struct Format;
+class Framebuffer;
+struct LinkedUniform;
+class Program;
+class Shader;
+
+void SetRobustLengthParam(GLsizei *length, GLsizei value);
+bool IsETC2EACFormat(const GLenum format);
+bool ValidTextureTarget(const Context *context, TextureType type);
+bool ValidTexture2DTarget(const Context *context, TextureType type);
+bool ValidTexture3DTarget(const Context *context, TextureType target);
+bool ValidTextureExternalTarget(const Context *context, TextureType target);
+bool ValidTextureExternalTarget(const Context *context, TextureTarget target);
+bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target);
+bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target);
+bool ValidTexLevelDestinationTarget(const Context *context, TextureType type);
+bool ValidFramebufferTarget(const Context *context, GLenum target);
+bool ValidMipLevel(const Context *context, TextureType type, GLint level);
+bool ValidImageSizeParameters(Context *context,
+ TextureType target,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ bool isSubImage);
+bool ValidCompressedImageSize(const Context *context,
+ GLenum internalFormat,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidCompressedSubImageSize(const Context *context,
+ GLenum internalFormat,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ size_t textureWidth,
+ size_t textureHeight,
+ size_t textureDepth);
+bool ValidImageDataSize(Context *context,
+ TextureType texType,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ GLsizei imageSize);
+
+bool ValidQueryType(const Context *context, QueryType queryType);
+
+bool ValidateWebGLVertexAttribPointer(Context *context,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr,
+ bool pureInteger);
+
+// Returns valid program if id is a valid program name
+// Errors INVALID_OPERATION if valid shader is given and returns NULL
+// Errors INVALID_VALUE otherwise and returns NULL
+Program *GetValidProgram(Context *context, GLuint id);
+
+// Returns valid shader if id is a valid shader name
+// Errors INVALID_OPERATION if valid program is given and returns NULL
+// Errors INVALID_VALUE otherwise and returns NULL
+Shader *GetValidShader(Context *context, GLuint id);
+
+bool ValidateAttachmentTarget(Context *context, GLenum attachment);
+bool ValidateRenderbufferStorageParametersBase(Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateFramebufferRenderbufferParameters(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+bool ValidateBlitFramebufferParameters(Context *context,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+bool ValidateReadPixelsBase(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels);
+bool ValidateReadPixelsRobustANGLE(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels);
+bool ValidateReadnPixelsEXT(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels);
+bool ValidateReadnPixelsRobustANGLE(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data);
+
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids);
+bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids);
+bool ValidateIsQueryEXT(gl::Context *context, GLuint id);
+bool ValidateBeginQueryBase(Context *context, QueryType target, GLuint id);
+bool ValidateBeginQueryEXT(Context *context, QueryType target, GLuint id);
+bool ValidateEndQueryBase(Context *context, QueryType target);
+bool ValidateEndQueryEXT(Context *context, QueryType target);
+bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target);
+bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams);
+bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params);
+bool ValidateGetQueryivRobustANGLE(Context *context,
+ QueryType target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams);
+bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params);
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params);
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params);
+
+bool ValidateUniformCommonBase(Context *context,
+ gl::Program *program,
+ GLint location,
+ GLsizei count,
+ const LinkedUniform **uniformOut);
+bool ValidateUniform1ivValue(Context *context,
+ GLenum uniformType,
+ GLsizei count,
+ const GLint *value);
+
+ANGLE_INLINE bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
+{
+ // Check that the value type is compatible with uniform type.
+ // Do the cheaper test first, for a little extra speed.
+ if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType)
+ {
+ context->validationError(GL_INVALID_OPERATION, err::kUniformSizeMismatch);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType);
+bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count);
+bool ValidateUniformMatrix(Context *context,
+ GLenum matrixType,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose);
+bool ValidateGetBooleanvRobustANGLE(Context *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *params);
+bool ValidateGetFloatvRobustANGLE(Context *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateStateQuery(Context *context,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams);
+bool ValidateGetIntegervRobustANGLE(Context *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+bool ValidateGetInteger64vRobustANGLE(Context *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+bool ValidateRobustStateQuery(Context *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams);
+
+bool ValidateCopyTexImageParametersBase(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ Format *textureFormatOut);
+
+void RecordDrawModeError(Context *context, PrimitiveMode mode);
+const char *ValidateDrawElementsStates(Context *context);
+
+ANGLE_INLINE bool ValidateDrawBase(Context *context, PrimitiveMode mode)
+{
+ if (!context->getStateCache().isValidDrawMode(mode))
+ {
+ RecordDrawModeError(context, mode);
+ return false;
+ }
+
+ intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
+ if (drawStatesError)
+ {
+ const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
+
+ // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
+ // Incomplete.
+ GLenum errorCode =
+ (errorMessage == err::kDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
+ : GL_INVALID_OPERATION);
+ context->validationError(errorCode, errorMessage);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstancedBase(Context *context,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstancedANGLE(Context *context,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstancedEXT(Context *context,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+
+bool ValidateDrawElementsInstancedBase(Context *context,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount);
+bool ValidateDrawElementsInstancedANGLE(Context *context,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount);
+bool ValidateDrawElementsInstancedEXT(Context *context,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount);
+
+bool ValidateDrawInstancedANGLE(Context *context);
+bool ValidateDrawInstancedEXT(Context *context);
+
+bool ValidateFramebufferTextureBase(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level);
+
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location);
+bool ValidateGetnUniformfvEXT(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLfloat *params);
+bool ValidateGetnUniformfvRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetnUniformivEXT(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLint *params);
+bool ValidateGetnUniformivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetnUniformuivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetUniformivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+
+bool ValidateDiscardFramebufferBase(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ bool defaultFramebuffer);
+
+bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker);
+bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker);
+
+bool ValidateEGLImageTargetTexture2DOES(Context *context,
+ gl::TextureType type,
+ GLeglImageOES image);
+bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
+ GLenum target,
+ GLeglImageOES image);
+
+bool ValidateBindVertexArrayBase(Context *context, GLuint array);
+
+bool ValidateProgramBinaryBase(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+bool ValidateGetProgramBinaryBase(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+
+bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs);
+
+bool ValidateGetBufferPointervBase(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei *length,
+ void **params);
+bool ValidateUnmapBufferBase(Context *context, BufferBinding target);
+bool ValidateMapBufferRangeBase(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateGenOrDelete(Context *context, GLint n);
+
+bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize);
+bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams);
+
+bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams);
+
+bool ValidateGetBufferParameterBase(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ bool pointerVersion,
+ GLsizei *numParams);
+
+bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams);
+
+bool ValidateGetRenderbufferParameterivBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length);
+
+bool ValidateGetTexParameterBase(Context *context,
+ TextureType target,
+ GLenum pname,
+ GLsizei *length);
+
+template <typename ParamType>
+bool ValidateTexParameterBase(Context *context,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const ParamType *params);
+
+bool ValidateGetVertexAttribBase(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei *length,
+ bool pointer,
+ bool pureIntegerEntryPoint);
+
+ANGLE_INLINE bool ValidateVertexFormat(Context *context,
+ GLuint index,
+ GLint size,
+ VertexAttribTypeCase validation)
+{
+ const Caps &caps = context->getCaps();
+ if (index >= caps.maxVertexAttributes)
+ {
+ context->validationError(GL_INVALID_VALUE, err::kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ switch (validation)
+ {
+ case VertexAttribTypeCase::Invalid:
+ context->validationError(GL_INVALID_ENUM, err::kInvalidType);
+ return false;
+ case VertexAttribTypeCase::Valid:
+ if (size < 1 || size > 4)
+ {
+ context->validationError(GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
+ return false;
+ }
+ break;
+ case VertexAttribTypeCase::ValidSize4Only:
+ if (size != 4)
+ {
+ context->validationError(GL_INVALID_OPERATION,
+ err::kInvalidVertexAttribSize2101010);
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
+// Note: These byte, short, and int types are all converted to float for the shader.
+ANGLE_INLINE bool ValidateFloatVertexFormat(Context *context,
+ GLuint index,
+ GLint size,
+ VertexAttribType type)
+{
+ return ValidateVertexFormat(context, index, size,
+ context->getStateCache().getVertexAttribTypeValidation(type));
+}
+
+ANGLE_INLINE bool ValidateIntegerVertexFormat(Context *context,
+ GLuint index,
+ GLint size,
+ VertexAttribType type)
+{
+ return ValidateVertexFormat(
+ context, index, size, context->getStateCache().getIntegerVertexAttribTypeValidation(type));
+}
+
+bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
+ GLint drawbuffer,
+ const GLenum *validComponentTypes,
+ size_t validComponentTypeCount);
+
+bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize);
+
+bool ValidateVertexAttribIndex(Context *context, GLuint index);
+
+bool ValidateGetActiveUniformBlockivBase(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateGetSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei *length);
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const ParamType *params);
+
+bool ValidateGetInternalFormativBase(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
+bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer);
+
+bool ValidateMultitextureUnit(Context *context, GLenum texture);
+
+bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
+ PrimitiveMode transformFeedbackPrimitiveMode,
+ PrimitiveMode renderPrimitiveMode);
+
+// Common validation for 2D and 3D variants of TexStorage*Multisample.
+bool ValidateTexStorageMultisample(Context *context,
+ TextureType target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateTexStorage2DMultisampleBase(Context *context,
+ TextureType target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateGetTexLevelParameterBase(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateMapBufferBase(Context *context, BufferBinding target);
+bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length);
+bool ValidateES3TexImage2DParameters(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels);
+bool ValidateES3CopyTexImage2DParameters(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+bool ValidateES3TexStorage2DParameters(Context *context,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidateES3TexStorage3DParameters(Context *context,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateGetMultisamplefvBase(Context *context, GLenum pname, GLuint index, GLfloat *val);
+bool ValidateSampleMaskiBase(Context *context, GLuint maskNumber, GLbitfield mask);
+
+// Utility macro for handling implementation methods inside Validation.
+#define ANGLE_HANDLE_VALIDATION_ERR(X) \
+ (void)(X); \
+ return false
+#define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR)
+
+// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
+// implementation format info for incomplete framebuffers. It seems like these queries are
+// incongruent with the other errors.
+// Inlined for speed.
+template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
+ANGLE_INLINE bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer)
+{
+ if (!framebuffer->isComplete(context))
+ {
+ context->validationError(ErrorCode, err::kFramebufferIncomplete);
+ return false;
+ }
+
+ return true;
+}
+
+const char *ValidateDrawStates(Context *context);
+
+void RecordDrawAttribsError(Context *context);
+
+ANGLE_INLINE bool ValidateDrawAttribs(Context *context, int64_t maxVertex)
+{
+ if (maxVertex > context->getStateCache().getNonInstancedVertexElementLimit())
+ {
+ RecordDrawAttribsError(context);
+ return false;
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawArraysAttribs(Context *context, GLint first, GLsizei count)
+{
+ if (!context->isBufferAccessValidationEnabled())
+ {
+ return true;
+ }
+
+ // Check the computation of maxVertex doesn't overflow.
+ // - first < 0 has been checked as an error condition.
+ // - if count <= 0, skip validating no-op draw calls.
+ // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
+ ASSERT(first >= 0);
+ ASSERT(count > 0);
+ int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
+ if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
+ {
+ context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
+ return false;
+ }
+
+ return ValidateDrawAttribs(context, maxVertex);
+}
+
+ANGLE_INLINE bool ValidateDrawInstancedAttribs(Context *context, GLint primcount)
+{
+ if (!context->isBufferAccessValidationEnabled())
+ {
+ return true;
+ }
+
+ if ((primcount - 1) > context->getStateCache().getInstancedVertexElementLimit())
+ {
+ RecordDrawAttribsError(context);
+ return false;
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawArraysCommon(Context *context,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (first < 0)
+ {
+ context->validationError(GL_INVALID_VALUE, err::kNegativeStart);
+ return false;
+ }
+
+ if (count <= 0)
+ {
+ if (count < 0)
+ {
+ context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
+ return false;
+ }
+
+ // Early exit.
+ return ValidateDrawBase(context, mode);
+ }
+
+ if (!ValidateDrawBase(context, mode))
+ {
+ return false;
+ }
+
+ if (context->getStateCache().isTransformFeedbackActiveUnpaused())
+ {
+ const State &state = context->getState();
+ TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
+ {
+ context->validationError(GL_INVALID_OPERATION, err::kTransformFeedbackBufferTooSmall);
+ return false;
+ }
+ }
+
+ return ValidateDrawArraysAttribs(context, first, count);
+}
+
+ANGLE_INLINE bool ValidateDrawElementsBase(Context *context,
+ PrimitiveMode mode,
+ DrawElementsType type)
+{
+ if (!context->getStateCache().isValidDrawElementsType(type))
+ {
+ if (type == DrawElementsType::UnsignedInt)
+ {
+ context->validationError(GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
+ return false;
+ }
+
+ ASSERT(type == DrawElementsType::InvalidEnum);
+ context->validationError(GL_INVALID_ENUM, err::kEnumNotSupported);
+ return false;
+ }
+
+ intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
+ if (drawElementsError)
+ {
+ // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
+ const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
+ context->validationError(GL_INVALID_OPERATION, errorMessage);
+ return false;
+ }
+
+ // Note that we are missing overflow checks for active transform feedback buffers.
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawElementsCommon(Context *context,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount)
+{
+ if (!ValidateDrawElementsBase(context, mode, type))
+ {
+ return false;
+ }
+
+ ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
+
+ if (context->getExtensions().webglCompatibility)
+ {
+ GLuint typeBytes = GetDrawElementsTypeSize(type);
+
+ if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
+ {
+ // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+ // The offset arguments to drawElements and [...], must be a multiple of the size of the
+ // data type passed to the call, or an INVALID_OPERATION error is generated.
+ context->validationError(GL_INVALID_OPERATION, err::kOffsetMustBeMultipleOfType);
+ return false;
+ }
+
+ // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+ // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
+ // error is generated.
+ if (reinterpret_cast<intptr_t>(indices) < 0)
+ {
+ context->validationError(GL_INVALID_VALUE, err::kNegativeOffset);
+ return false;
+ }
+ }
+
+ if (count <= 0)
+ {
+ if (count < 0)
+ {
+ context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
+ return false;
+ }
+
+ // Early exit.
+ return ValidateDrawBase(context, mode);
+ }
+
+ if (!ValidateDrawBase(context, mode))
+ {
+ return false;
+ }
+
+ const State &state = context->getState();
+ const VertexArray *vao = state.getVertexArray();
+ Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ if (!elementArrayBuffer)
+ {
+ if (!indices)
+ {
+ // This is an application error that would normally result in a crash, but we catch
+ // it and return an error
+ context->validationError(GL_INVALID_OPERATION, err::kElementArrayNoBufferOrPointer);
+ return false;
+ }
+ }
+ else
+ {
+ // The max possible type size is 8 and count is on 32 bits so doing the multiplication
+ // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
+ static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
+ constexpr uint64_t kMaxTypeSize = 8;
+ constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
+ constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
+ static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
+
+ uint64_t elementCount = static_cast<uint64_t>(count);
+ ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
+
+ // Doing the multiplication here is overflow-safe
+ uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
+
+ // The offset can be any value, check for overflows
+ uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
+ uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
+ if (elementDataSizeWithOffset < elementDataSizeNoOffset)
+ {
+ context->validationError(GL_INVALID_OPERATION, err::kIntegerOverflow);
+ return false;
+ }
+
+ if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
+ {
+ context->validationError(GL_INVALID_OPERATION, err::kInsufficientBufferSize);
+ return false;
+ }
+ }
+
+ if (context->isBufferAccessValidationEnabled() && primcount > 0)
+ {
+ // Use the parameter buffer to retrieve and cache the index range.
+ IndexRange indexRange{IndexRange::Undefined()};
+ ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
+
+ // If we use an index greater than our maximum supported index range, return an error.
+ // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
+ // always return an error if possible here.
+ if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
+ {
+ context->validationError(GL_INVALID_OPERATION, err::kExceedsMaxElement);
+ return false;
+ }
+
+ if (!ValidateDrawAttribs(context, static_cast<GLint>(indexRange.end)))
+ {
+ return false;
+ }
+
+ // No op if there are no real indices in the index data (all are primitive restart).
+ return (indexRange.vertexIndexCount > 0);
+ }
+
+ return true;
+}
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES_H_