GLES1: Renderer (minimal)
This is the renderer code for GLES1 that delivers basic vertex
attributes, matrices, and allows texturing for unit 0 only (more units
mean implementing the multitexturing pipeline).
+ Sample
+ Update test expectations for GLES1 conformance tests
BUG=angleproject:2554
BUG=angleproject:2306
Change-Id: I398edc764f982fbfc4c5e0f9d6bfef1e91aec47c
Reviewed-on: https://chromium-review.googlesource.com/1057356
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Lingfeng Yang <lfy@google.com>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index cbf4ef2..f8d213b 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -117,7 +117,10 @@
const auto &vertexAttribs = vao->getVertexAttributes();
const auto &vertexBindings = vao->getVertexBindings();
- const AttributesMask &activeAttribs = (program->getActiveAttribLocationsMask() &
+ bool isGLES1 = context->getClientVersion() < Version(2, 0);
+
+ const AttributesMask &activeAttribs = ((isGLES1 ? context->getVertexArraysAttributeMask()
+ : program->getActiveAttribLocationsMask()) &
vao->getEnabledAttributesMask() & ~clientAttribs);
for (size_t attributeIndex : activeAttribs)
@@ -126,7 +129,7 @@
ASSERT(attrib.enabled);
const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
- ASSERT(program->isAttribLocationActive(attributeIndex));
+ ASSERT(isGLES1 || program->isAttribLocationActive(attributeIndex));
GLint maxVertexElement = maxVertex;
GLuint divisor = binding.getDivisor();
@@ -2675,140 +2678,150 @@
return false;
}
- gl::Program *program = state.getProgram();
- if (!program)
+ // If we are running GLES1, there is no current program.
+ if (context->getClientVersion() >= Version(2, 0))
{
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
- return false;
- }
- // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
- // vertex shader stage or fragment shader stage is a undefined behaviour.
- // But ANGLE should clearly generate an INVALID_OPERATION error instead of
- // produce undefined result.
- if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
- !program->hasLinkedShaderStage(ShaderType::Fragment))
- {
- context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
- "vertex shader stage or fragment shader stage.");
- return false;
- }
-
- if (!program->validateSamplers(nullptr, context->getCaps()))
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- if (extensions.multiview)
- {
- const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
- const int framebufferNumViews = framebuffer->getNumViews();
- if (framebufferNumViews != programNumViews)
+ gl::Program *program = state.getProgram();
+ if (!program)
{
- context->handleError(InvalidOperation() << "The number of views in the active program "
- "and draw framebuffer does not match.");
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
return false;
}
- const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
- if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
- framebufferNumViews > 1)
+ // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
+ // vertex shader stage or fragment shader stage is a undefined behaviour.
+ // But ANGLE should clearly generate an INVALID_OPERATION error instead of
+ // produce undefined result.
+ if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
+ !program->hasLinkedShaderStage(ShaderType::Fragment))
{
context->handleError(InvalidOperation()
- << "There is an active transform feedback object "
- "when the number of views in the active draw "
- "framebuffer is greater than 1.");
+ << "It is a undefined behaviour to render without "
+ "vertex shader stage or fragment shader stage.");
return false;
}
- if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
- state.isQueryActive(QueryType::TimeElapsed))
+ if (!program->validateSamplers(nullptr, context->getCaps()))
{
- context->handleError(InvalidOperation() << "There is an active query for target "
- "GL_TIME_ELAPSED_EXT when the number of "
- "views in the active draw framebuffer is "
- "greater than 1.");
- return false;
- }
- }
-
- // Do geometry shader specific validations
- if (program->hasLinkedShaderStage(ShaderType::Geometry))
- {
- if (!IsCompatibleDrawModeWithGeometryShader(mode,
- program->getGeometryShaderInputPrimitiveType()))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(),
- IncompatibleDrawModeAgainstGeometryShader);
- return false;
- }
- }
-
- // Uniform buffer validation
- for (unsigned int uniformBlockIndex = 0;
- uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
- {
- const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
- GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
- const OffsetBindingPointer<Buffer> &uniformBuffer =
- state.getIndexedUniformBuffer(blockBinding);
-
- if (uniformBuffer.get() == nullptr)
- {
- // undefined behaviour
- context->handleError(
- InvalidOperation()
- << "It is undefined behaviour to have a used but unbound uniform buffer.");
+ context->handleError(InvalidOperation());
return false;
}
- size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
- if (uniformBufferSize < uniformBlock.dataSize)
+ if (extensions.multiview)
{
- // undefined behaviour
- context->handleError(
- InvalidOperation()
- << "It is undefined behaviour to use a uniform buffer that is too small.");
- return false;
+ const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
+ const int framebufferNumViews = framebuffer->getNumViews();
+ if (framebufferNumViews != programNumViews)
+ {
+ context->handleError(InvalidOperation()
+ << "The number of views in the active program "
+ "and draw framebuffer does not match.");
+ return false;
+ }
+
+ const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
+ if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
+ framebufferNumViews > 1)
+ {
+ context->handleError(InvalidOperation()
+ << "There is an active transform feedback object "
+ "when the number of views in the active draw "
+ "framebuffer is greater than 1.");
+ return false;
+ }
+
+ if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
+ state.isQueryActive(QueryType::TimeElapsed))
+ {
+ context->handleError(InvalidOperation()
+ << "There is an active query for target "
+ "GL_TIME_ELAPSED_EXT when the number of "
+ "views in the active draw framebuffer is "
+ "greater than 1.");
+ return false;
+ }
}
- if (extensions.webglCompatibility &&
- uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
+ // Do geometry shader specific validations
+ if (program->hasLinkedShaderStage(ShaderType::Geometry))
{
- ANGLE_VALIDATION_ERR(context, InvalidOperation(),
- UniformBufferBoundForTransformFeedback);
- return false;
- }
- }
-
- // Do some additonal WebGL-specific validation
- if (extensions.webglCompatibility)
- {
- const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
- if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
- transformFeedbackObject->buffersBoundForOtherUse())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
- return false;
- }
- // Detect rendering feedback loops for WebGL.
- if (framebuffer->formsRenderingFeedbackLoopWith(state))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
- return false;
+ if (!IsCompatibleDrawModeWithGeometryShader(
+ mode, program->getGeometryShaderInputPrimitiveType()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(),
+ IncompatibleDrawModeAgainstGeometryShader);
+ return false;
+ }
}
- // Detect that the vertex shader input types match the attribute types
- if (!ValidateVertexShaderAttributeTypeMatch(context))
+ // Uniform buffer validation
+ for (unsigned int uniformBlockIndex = 0;
+ uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
{
- return false;
+ const gl::InterfaceBlock &uniformBlock =
+ program->getUniformBlockByIndex(uniformBlockIndex);
+ GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
+ const OffsetBindingPointer<Buffer> &uniformBuffer =
+ state.getIndexedUniformBuffer(blockBinding);
+
+ if (uniformBuffer.get() == nullptr)
+ {
+ // undefined behaviour
+ context->handleError(
+ InvalidOperation()
+ << "It is undefined behaviour to have a used but unbound uniform buffer.");
+ return false;
+ }
+
+ size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
+ if (uniformBufferSize < uniformBlock.dataSize)
+ {
+ // undefined behaviour
+ context->handleError(
+ InvalidOperation()
+ << "It is undefined behaviour to use a uniform buffer that is too small.");
+ return false;
+ }
+
+ if (extensions.webglCompatibility &&
+ uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(),
+ UniformBufferBoundForTransformFeedback);
+ return false;
+ }
}
- // Detect that the color buffer types match the fragment shader output types
- if (!ValidateFragmentShaderColorBufferTypeMatch(context))
+ // Do some additonal WebGL-specific validation
+ if (extensions.webglCompatibility)
{
- return false;
+ const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
+ if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
+ transformFeedbackObject->buffersBoundForOtherUse())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(),
+ TransformFeedbackBufferDoubleBound);
+ return false;
+ }
+ // Detect rendering feedback loops for WebGL.
+ if (framebuffer->formsRenderingFeedbackLoopWith(state))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
+ return false;
+ }
+
+ // Detect that the vertex shader input types match the attribute types
+ if (!ValidateVertexShaderAttributeTypeMatch(context))
+ {
+ return false;
+ }
+
+ // Detect that the color buffer types match the fragment shader output types
+ if (!ValidateFragmentShaderColorBufferTypeMatch(context))
+ {
+ return false;
+ }
}
}