Refactor remaining GLES 2.0 entry points.
This will pave the way for several features, like auto-generation.
BUG=angleproject:747
Change-Id: Ic390ac412f4e6b61346629093f185a4c07ea0284
Reviewed-on: https://chromium-review.googlesource.com/474118
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 94671a9..fb23cac 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -284,6 +284,58 @@
return false;
}
+bool IsValidStencilFunc(GLenum func)
+{
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidStencilFace(GLenum face)
+{
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidStencilOp(GLenum op)
+{
+ switch (op)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
} // anonymous namespace
bool ValidateES2TexImageParameters(Context *context,
@@ -741,292 +793,6 @@
return true;
}
-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)
-{
- if (!ValidTexture2DDestinationTarget(context, target))
- {
- context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
- return false;
- }
-
- if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
- {
- context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
- return false;
- }
-
- Format textureFormat = Format::Invalid();
- if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
- xoffset, yoffset, 0, x, y, width, height, border,
- &textureFormat))
- {
- return false;
- }
-
- const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
- GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
- const auto &formatInfo = *textureFormat.info;
-
- // [OpenGL ES 2.0.24] table 3.9
- if (isSubImage)
- {
- switch (formatInfo.format)
- {
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RED_EXT:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
- colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RG_EXT:
- if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- 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:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- default:
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
- else
- {
- switch (internalformat)
- {
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RED_EXT:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RG_EXT:
- if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->getExtensions().textureCompressionDXT1)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->handleError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->getExtensions().textureCompressionDXT3)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->handleError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->getExtensions().textureCompressionDXT5)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->handleError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (context->getExtensions().compressedETC1RGB8Texture)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->handleError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- if (context->getExtensions().lossyETCDecode)
- {
- context->handleError(Error(GL_INVALID_OPERATION,
- "ETC lossy decode formats can't be copied to."));
- return false;
- }
- else
- {
- context->handleError(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:
- case GL_DEPTH_STENCIL_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (context->getExtensions().depthTextures)
- {
- context->handleError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->handleError(Error(GL_INVALID_ENUM));
- return false;
- }
- default:
- context->handleError(Error(GL_INVALID_ENUM));
- return false;
- }
- }
-
- // If width or height is zero, it is a no-op. Return false without setting an error.
- return (width > 0 && height > 0);
-}
-
bool ValidateES2TexStorageParameters(Context *context,
GLenum target,
GLsizei levels,
@@ -3752,6 +3518,15 @@
}
}
+bool ValidateBlendColor(ValidationContext *context,
+ GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha)
+{
+ return true;
+}
+
bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
{
if (!ValidBlendEquationMode(mode))
@@ -4075,4 +3850,985 @@
width, height);
}
+bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
+{
+ if (!ValidFramebufferTarget(target))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid Framebuffer target"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateClearColor(ValidationContext *context,
+ GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha)
+{
+ return true;
+}
+
+bool ValidateClearDepthf(ValidationContext *context, GLclampf depth)
+{
+ return true;
+}
+
+bool ValidateClearStencil(ValidationContext *context, GLint s)
+{
+ return true;
+}
+
+bool ValidateColorMask(ValidationContext *context,
+ GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha)
+{
+ return true;
+}
+
+bool ValidateCompileShader(ValidationContext *context, GLuint shader)
+{
+ return true;
+}
+
+bool ValidateCreateProgram(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateCullFace(ValidationContext *context, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid cull face parameter"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
+{
+ if (program == 0)
+ {
+ return false;
+ }
+
+ if (!context->getProgram(program))
+ {
+ if (context->getShader(program))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Shader handle passed to DeleteProgram"));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid program handle"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
+{
+ if (shader == 0)
+ {
+ return false;
+ }
+
+ if (!context->getShader(shader))
+ {
+ if (context->getProgram(shader))
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "Program handle passed to DeleteShader"));
+ return false;
+ }
+ else
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Invalid shader handle"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDepthFunc(ValidationContext *context, GLenum func)
+{
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_NOTEQUAL:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid depth function"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
+{
+ return true;
+}
+
+bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ const Shader *attachedShader = nullptr;
+
+ switch (shaderObject->getType())
+ {
+ case GL_VERTEX_SHADER:
+ {
+ attachedShader = programObject->getAttachedVertexShader();
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ attachedShader = programObject->getAttachedFragmentShader();
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ attachedShader = programObject->getAttachedComputeShader();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ if (attachedShader != shaderObject)
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "Cannot detach non-attached shader."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Attrib array index out of range"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFinish(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateFlush(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateFrontFace(ValidationContext *context, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_CW:
+ case GL_CCW:
+ break;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid mode for FrontFace"));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveAttrib(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ if (bufsize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "index exeeds program active attribute count."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniform(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ if (bufsize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "index exceeds program active uniform count."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetAttachedShaders(ValidationContext *context,
+ GLuint program,
+ GLsizei maxcount,
+ GLsizei *count,
+ GLuint *shaders)
+{
+ if (maxcount < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "max count must be non-negative."));
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
+{
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "program not linked."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetError(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetProgramInfoLog(ValidationContext *context,
+ GLuint program,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
+{
+ if (bufsize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderInfoLog(ValidationContext *context,
+ GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
+{
+ if (bufsize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
+ GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision)
+{
+ switch (shadertype)
+ {
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ break;
+ case GL_COMPUTE_SHADER:
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "compute shader precision not yet implemented."));
+ return false;
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "invalid shader type."));
+ return false;
+ }
+
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ case GL_MEDIUM_FLOAT:
+ case GL_HIGH_FLOAT:
+ case GL_LOW_INT:
+ case GL_MEDIUM_INT:
+ case GL_HIGH_INT:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "invalid precision type."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderSource(ValidationContext *context,
+ GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source)
+{
+ if (bufsize < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "bufsize must be non-negative."));
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
+{
+ if (strstr(name, "gl_") == name)
+ {
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->handleError(Error(GL_INVALID_OPERATION, "program is not linked."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FASTEST:
+ case GL_NICEST:
+ case GL_DONT_CARE:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "invalid hint mode."));
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ if (!context->getExtensions().standardDerivatives)
+ {
+ context->handleError(
+ Error(GL_INVALID_OPERATION, "hint requires OES_standard_derivatives."));
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM, "invalid hint target."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
+{
+ return true;
+}
+
+bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
+{
+ return true;
+}
+
+bool ValidateIsProgram(ValidationContext *context, GLuint program)
+{
+ return true;
+}
+
+bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
+{
+ return true;
+}
+
+bool ValidateIsShader(ValidationContext *context, GLuint shader)
+{
+ return true;
+}
+
+bool ValidateIsTexture(ValidationContext *context, GLuint texture)
+{
+ return true;
+}
+
+bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ switch (pname)
+ {
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ if (!context->getExtensions().unpackSubimage)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if (!context->getExtensions().packSubimage)
+ {
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (param < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->handleError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ break;
+
+ default:
+ context->handleError(Error(GL_INVALID_ENUM));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
+{
+ return true;
+}
+
+bool ValidateReleaseShaderCompiler(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert)
+{
+ return true;
+}
+
+bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Scissor width and height must be non-negative."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateShaderBinary(ValidationContext *context,
+ GLsizei n,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const GLvoid *binary,
+ GLsizei length)
+{
+ const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
+ if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
+ shaderBinaryFormats.end())
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid shader binary format."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateShaderSource(ValidationContext *context,
+ GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
+{
+ if (count < 0)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Count must be non-negative."));
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
+{
+ if (!IsValidStencilFunc(func))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFuncSeparate(ValidationContext *context,
+ GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask)
+{
+ if (!IsValidStencilFace(face))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
+ return false;
+ }
+
+ if (!IsValidStencilFunc(func))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil function."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilMask(ValidationContext *context, GLuint mask)
+{
+ return true;
+}
+
+bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
+{
+ if (!IsValidStencilFace(face))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (!IsValidStencilOp(fail))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil fail op."));
+ return false;
+ }
+
+ if (!IsValidStencilOp(zfail))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z fail op."));
+ return false;
+ }
+
+ if (!IsValidStencilOp(zpass))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil z pass op."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilOpSeparate(ValidationContext *context,
+ GLenum face,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass)
+{
+ if (!IsValidStencilFace(face))
+ {
+ context->handleError(Error(GL_INVALID_ENUM, "Invalid stencil face."));
+ return false;
+ }
+
+ return ValidateStencilOp(context, fail, zfail, zpass);
+}
+
+bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
+{
+ return ValidateUniform(context, GL_FLOAT, location, 1);
+}
+
+bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT, location, count);
+}
+
+bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
+}
+
+bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
+}
+
+bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
+{
+ return ValidateUniform(context, GL_INT_VEC2, location, 1);
+}
+
+bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+ return ValidateUniform(context, GL_INT_VEC2, location, count);
+}
+
+bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
+}
+
+bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
+}
+
+bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
+{
+ return ValidateUniform(context, GL_INT_VEC3, location, 1);
+}
+
+bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+ return ValidateUniform(context, GL_INT_VEC3, location, count);
+}
+
+bool ValidateUniform4f(ValidationContext *context,
+ GLint location,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
+}
+
+bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
+}
+
+bool ValidateUniform4i(ValidationContext *context,
+ GLint location,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w)
+{
+ return ValidateUniform(context, GL_INT_VEC4, location, 1);
+}
+
+bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+ return ValidateUniform(context, GL_INT_VEC4, location, count);
+}
+
+bool ValidateUniformMatrix2fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
+}
+
+bool ValidateUniformMatrix3fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
+}
+
+bool ValidateUniformMatrix4fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
+}
+
+bool ValidateValidateProgram(ValidationContext *context, GLuint program)
+{
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->handleError(Error(GL_INVALID_VALUE, "Vertex attrib index out of range."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib3f(ValidationContext *context,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib4f(ValidationContext *context,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ context->handleError(
+ Error(GL_INVALID_VALUE, "Viewport width and height must be non-negative."));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
+{
+ return ValidateDrawArraysCommon(context, mode, first, count, 1);
+}
+
} // namespace gl