summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/validationES2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/validationES2.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES2.cpp922
1 files changed, 898 insertions, 24 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
index 9eece1b54a..2e5b955e99 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES2.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
@@ -21,6 +21,42 @@
namespace gl
{
+namespace
+{
+
+bool IsPartialBlit(gl::Context *context,
+ const FramebufferAttachment *readBuffer,
+ const FramebufferAttachment *writeBuffer,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1)
+{
+ const Extents &writeSize = writeBuffer->getSize();
+ const Extents &readSize = readBuffer->getSize();
+
+ if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
+ dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
+ {
+ return true;
+ }
+
+ if (context->getState().isScissorTestEnabled())
+ {
+ const Rectangle &scissor = context->getState().getScissor();
+ return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
+ scissor.height < writeSize.height;
+ }
+
+ return false;
+}
+
+} // anonymous namespace
+
bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type, const GLvoid *pixels)
@@ -31,7 +67,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
- if (!ValidImageSize(context, target, level, width, height, 1))
+ if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
@@ -110,7 +146,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
}
else
{
- if (texture->isImmutable())
+ if (texture->getImmutableFormat())
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -124,23 +160,10 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
- GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
- const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
-
- if (isCompressed != actualFormatInfo.compressed)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
if (isCompressed)
{
- if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
+ GLenum actualInternalFormat =
+ isSubImage ? texture->getInternalFormat(target, level) : internalformat;
switch (actualInternalFormat)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
@@ -165,8 +188,29 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
break;
+ case GL_ETC1_RGB8_OES:
+ if (!context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (!context->getExtensions().lossyETCDecode)
+ {
+ context->recordError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
+ return false;
+ }
+ break;
default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->recordError(Error(
+ GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
+ return false;
+ }
+ if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
@@ -350,6 +394,33 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
break;
+ case GL_ETC1_RGB8_OES:
+ if (context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (context->getExtensions().lossyETCDecode)
+ {
+ context->recordError(
+ Error(GL_INVALID_OPERATION,
+ "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
+ return false;
+ }
+ else
+ {
+ context->recordError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+ return false;
+ }
+ break;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL_OES:
if (!context->getExtensions().depthTextures)
@@ -395,21 +466,34 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
return true;
}
-
-
-bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
- GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height,
+bool ValidateES2CopyTexImageParameters(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
GLint border)
{
GLenum textureInternalFormat = GL_NONE;
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+ return false;
+ }
+
if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
{
return false;
}
- gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
GLenum textureFormat = internalFormatInfo.format;
@@ -502,6 +586,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ case GL_ETC1_RGB8_OES:
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
context->recordError(Error(GL_INVALID_OPERATION));
return false;
case GL_DEPTH_COMPONENT:
@@ -642,6 +728,32 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
return false;
}
break;
+ case GL_ETC1_RGB8_OES:
+ if (context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (context->getExtensions().lossyETCDecode)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION,
+ "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
+ return false;
+ }
+ else
+ {
+ context->recordError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+ return false;
+ }
+ break;
case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT32_OES:
@@ -759,6 +871,21 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le
return false;
}
break;
+ case GL_ETC1_RGB8_OES:
+ if (!context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ if (!context->getExtensions().lossyETCDecode)
+ {
+ context->recordError(
+ Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
+ return false;
+ }
+ break;
case GL_RGBA32F_EXT:
case GL_RGB32F_EXT:
case GL_ALPHA32F_EXT:
@@ -824,7 +951,7 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le
return false;
}
- if (texture->isImmutable())
+ if (texture->getImmutableFormat())
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -879,4 +1006,751 @@ bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
return true;
}
+bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ if (!context->getExtensions().discardFramebuffer)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ bool defaultFramebuffer = false;
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
+ return false;
+ }
+
+ return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
+}
+
+bool ValidateBindVertexArrayOES(Context *context, GLuint array)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, array);
+}
+
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateDeleteVertexArraysBase(context, n);
+}
+
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateGenVertexArraysBase(context, n);
+}
+
+bool ValidateIsVertexArrayOES(Context *context)
+{
+ if (!context->getExtensions().vertexArrayObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramBinaryOES(Context *context,
+ GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
+{
+ if (!context->getExtensions().getProgramBinary)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinaryOES(Context *context,
+ GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ if (!context->getExtensions().getProgramBinary)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
+}
+
+static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
+{
+ switch (source)
+ {
+ case GL_DEBUG_SOURCE_API:
+ case GL_DEBUG_SOURCE_SHADER_COMPILER:
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ case GL_DEBUG_SOURCE_OTHER:
+ // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
+ return !mustBeThirdPartyOrApplication;
+
+ case GL_DEBUG_SOURCE_THIRD_PARTY:
+ case GL_DEBUG_SOURCE_APPLICATION:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidDebugType(GLenum type)
+{
+ switch (type)
+ {
+ case GL_DEBUG_TYPE_ERROR:
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ case GL_DEBUG_TYPE_PORTABILITY:
+ case GL_DEBUG_TYPE_OTHER:
+ case GL_DEBUG_TYPE_MARKER:
+ case GL_DEBUG_TYPE_PUSH_GROUP:
+ case GL_DEBUG_TYPE_POP_GROUP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidDebugSeverity(GLenum severity)
+{
+ switch (severity)
+ {
+ case GL_DEBUG_SEVERITY_HIGH:
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ case GL_DEBUG_SEVERITY_LOW:
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateDebugMessageControlKHR(Context *context,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ return false;
+ }
+
+ if (!ValidDebugType(type) && type != GL_DONT_CARE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+ return false;
+ }
+
+ if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+ return false;
+ }
+
+ if (count > 0)
+ {
+ if (source == GL_DONT_CARE || type == GL_DONT_CARE)
+ {
+ context->recordError(Error(
+ GL_INVALID_OPERATION,
+ "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
+ return false;
+ }
+
+ if (severity != GL_DONT_CARE)
+ {
+ context->recordError(
+ Error(GL_INVALID_OPERATION,
+ "If count is greater than zero, severity must be GL_DONT_CARE."));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageInsertKHR(Context *context,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!context->getState().getDebug().isOutputEnabled())
+ {
+ // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
+ // not generate an error.
+ return false;
+ }
+
+ if (!ValidDebugSeverity(severity))
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+ return false;
+ }
+
+ if (!ValidDebugType(type))
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+ return false;
+ }
+
+ if (!ValidDebugSource(source, true))
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ return false;
+ }
+
+ size_t messageLength = (length < 0) ? strlen(buf) : length;
+ if (messageLength > context->getExtensions().maxDebugMessageLength)
+ {
+ context->recordError(
+ Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageCallbackKHR(Context *context,
+ GLDEBUGPROCKHR callback,
+ const void *userParam)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetDebugMessageLogKHR(Context *context,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (bufSize < 0 && messageLog != nullptr)
+ {
+ context->recordError(
+ Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePushDebugGroupKHR(Context *context,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidDebugSource(source, true))
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ return false;
+ }
+
+ size_t messageLength = (length < 0) ? strlen(message) : length;
+ if (messageLength > context->getExtensions().maxDebugMessageLength)
+ {
+ context->recordError(
+ Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+ return false;
+ }
+
+ size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
+ if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
+ {
+ context->recordError(
+ Error(GL_STACK_OVERFLOW,
+ "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePopDebugGroupKHR(Context *context)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
+ if (currentStackSize <= 1)
+ {
+ context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
+{
+ switch (identifier)
+ {
+ case GL_BUFFER:
+ if (context->getBuffer(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
+ return false;
+ }
+ return true;
+
+ case GL_SHADER:
+ if (context->getShader(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
+ return false;
+ }
+ return true;
+
+ case GL_PROGRAM:
+ if (context->getProgram(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
+ return false;
+ }
+ return true;
+
+ case GL_VERTEX_ARRAY:
+ if (context->getVertexArray(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
+ return false;
+ }
+ return true;
+
+ case GL_QUERY:
+ if (context->getQuery(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
+ return false;
+ }
+ return true;
+
+ case GL_TRANSFORM_FEEDBACK:
+ if (context->getTransformFeedback(name) == nullptr)
+ {
+ context->recordError(
+ Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
+ return false;
+ }
+ return true;
+
+ case GL_SAMPLER:
+ if (context->getSampler(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
+ return false;
+ }
+ return true;
+
+ case GL_TEXTURE:
+ if (context->getTexture(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
+ return false;
+ }
+ return true;
+
+ case GL_RENDERBUFFER:
+ if (context->getRenderbuffer(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
+ return false;
+ }
+ return true;
+
+ case GL_FRAMEBUFFER:
+ if (context->getFramebuffer(name) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
+ return false;
+ }
+ return true;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateObjectLabelKHR(Context *context,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateObjectIdentifierAndName(context, identifier, name))
+ {
+ return false;
+ }
+
+ size_t labelLength = (length < 0) ? strlen(label) : length;
+ if (labelLength > context->getExtensions().maxLabelLength)
+ {
+ context->recordError(
+ Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetObjectLabelKHR(Context *context,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ return false;
+ }
+
+ if (!ValidateObjectIdentifierAndName(context, identifier, name))
+ {
+ return false;
+ }
+
+ // Can no-op if bufSize is zero.
+ return bufSize > 0;
+}
+
+static bool ValidateObjectPtrName(Context *context, const void *ptr)
+{
+ if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateObjectPtrLabelKHR(Context *context,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (!ValidateObjectPtrName(context, ptr))
+ {
+ return false;
+ }
+
+ size_t labelLength = (length < 0) ? strlen(label) : length;
+ if (labelLength > context->getExtensions().maxLabelLength)
+ {
+ context->recordError(
+ Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetObjectPtrLabelKHR(Context *context,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ return false;
+ }
+
+ if (!ValidateObjectPtrName(context, ptr))
+ {
+ return false;
+ }
+
+ // Can no-op if bufSize is zero.
+ return bufSize > 0;
+}
+
+bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
+{
+ if (!context->getExtensions().debug)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ return false;
+ }
+
+ // TODO: represent this in Context::getQueryParameterInfo.
+ switch (pname)
+ {
+ case GL_DEBUG_CALLBACK_FUNCTION:
+ case GL_DEBUG_CALLBACK_USER_PARAM:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlitFramebufferANGLE(Context *context,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ if (!context->getExtensions().framebufferBlit)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
+ return false;
+ }
+
+ if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+ {
+ // TODO(jmadill): Determine if this should be available on other implementations.
+ context->recordError(Error(
+ GL_INVALID_OPERATION,
+ "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
+ return false;
+ }
+
+ if (filter == GL_LINEAR)
+ {
+ context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
+ return false;
+ }
+
+ const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
+ const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
+
+ if (readColorAttachment && drawColorAttachment)
+ {
+ if (!(readColorAttachment->type() == GL_TEXTURE &&
+ readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
+ readColorAttachment->type() != GL_RENDERBUFFER &&
+ readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ for (size_t drawbufferIdx = 0;
+ drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
+ {
+ const FramebufferAttachment *attachment =
+ drawFramebuffer->getDrawBuffer(drawbufferIdx);
+ if (attachment)
+ {
+ if (!(attachment->type() == GL_TEXTURE &&
+ attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
+ attachment->type() != GL_RENDERBUFFER &&
+ attachment->type() != GL_FRAMEBUFFER_DEFAULT)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // Return an error if the destination formats do not match
+ if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ int readSamples = readFramebuffer->getSamples(context->getData());
+
+ if (readSamples != 0 &&
+ IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
+ srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+
+ GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+ GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+ for (size_t i = 0; i < 2; i++)
+ {
+ if (mask & masks[i])
+ {
+ const FramebufferAttachment *readBuffer =
+ readFramebuffer->getAttachment(attachments[i]);
+ const FramebufferAttachment *drawBuffer =
+ drawFramebuffer->getAttachment(attachments[i]);
+
+ if (readBuffer && drawBuffer)
+ {
+ if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1))
+ {
+ // only whole-buffer copies are permitted
+ ERR(
+ "Only whole-buffer depth and stencil blits are supported by this "
+ "implementation.");
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+ }
+ }
+ }
+
+ return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+ dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClear(ValidationContext *context, GLbitfield mask)
+{
+ const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return false;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
+{
+ if (!context->getExtensions().drawBuffers)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
+ return false;
+ }
+
+ return ValidateDrawBuffersBase(context, n, bufs);
}
+
+} // namespace gl