Refactor transform feedback EPs.
BUG=angleproject:747
Change-Id: I4891966cd7b3d478980202e795742e15dd1dcb01
Reviewed-on: https://chromium-review.googlesource.com/637125
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 9b112a4..6d9fddc 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -374,7 +374,7 @@
// In the initial state, a default transform feedback object is bound and treated as
// a transform feedback object with a name of zero. That object is bound any time
// BindTransformFeedback is called with id of zero
- bindTransformFeedback(0);
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
}
// Initialize dirty bit masks
@@ -629,13 +629,6 @@
return mState.mSamplers->createSampler();
}
-GLuint Context::createTransformFeedback()
-{
- GLuint transformFeedback = mTransformFeedbackHandleAllocator.allocate();
- mTransformFeedbackMap.assign(transformFeedback, nullptr);
- return transformFeedback;
-}
-
// Returns an unused framebuffer name
GLuint Context::createFramebuffer()
{
@@ -799,26 +792,6 @@
mState.mSamplers->deleteObject(this, sampler);
}
-void Context::deleteTransformFeedback(GLuint transformFeedback)
-{
- if (transformFeedback == 0)
- {
- return;
- }
-
- TransformFeedback *transformFeedbackObject = nullptr;
- if (mTransformFeedbackMap.erase(transformFeedback, &transformFeedbackObject))
- {
- if (transformFeedbackObject != nullptr)
- {
- detachTransformFeedback(transformFeedback);
- transformFeedbackObject->release(this);
- }
-
- mTransformFeedbackHandleAllocator.release(transformFeedback);
- }
-}
-
void Context::deleteFramebuffer(GLuint framebuffer)
{
if (mState.mFramebuffers->getFramebuffer(framebuffer))
@@ -1131,8 +1104,9 @@
mGLState.setProgram(this, getProgram(program));
}
-void Context::bindTransformFeedback(GLuint transformFeedbackHandle)
+void Context::bindTransformFeedback(GLenum target, GLuint transformFeedbackHandle)
{
+ ASSERT(target == GL_TRANSFORM_FEEDBACK);
TransformFeedback *transformFeedback =
checkTransformFeedbackAllocation(transformFeedbackHandle);
mGLState.setTransformFeedbackBinding(this, transformFeedback);
@@ -2383,7 +2357,7 @@
// VAOs and FBOs and set the current bound transform feedback back to 0.
if (mGLState.removeTransformFeedbackBinding(this, transformFeedback))
{
- bindTransformFeedback(0);
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
}
}
@@ -5032,4 +5006,92 @@
return (vao != nullptr ? GL_TRUE : GL_FALSE);
}
+void Context::endTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ transformFeedback->end(this);
+}
+
+void Context::transformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
+}
+
+void Context::getTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
+}
+
+void Context::deleteTransformFeedbacks(GLsizei n, const GLuint *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ GLuint transformFeedback = ids[i];
+ if (transformFeedback == 0)
+ {
+ continue;
+ }
+
+ TransformFeedback *transformFeedbackObject = nullptr;
+ if (mTransformFeedbackMap.erase(transformFeedback, &transformFeedbackObject))
+ {
+ if (transformFeedbackObject != nullptr)
+ {
+ detachTransformFeedback(transformFeedback);
+ transformFeedbackObject->release(this);
+ }
+
+ mTransformFeedbackHandleAllocator.release(transformFeedback);
+ }
+ }
+}
+
+void Context::genTransformFeedbacks(GLsizei n, GLuint *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ GLuint transformFeedback = mTransformFeedbackHandleAllocator.allocate();
+ mTransformFeedbackMap.assign(transformFeedback, nullptr);
+ ids[i] = transformFeedback;
+ }
+}
+
+bool Context::isTransformFeedback(GLuint id)
+{
+ if (id == 0)
+ {
+ // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
+ // returns FALSE
+ return GL_FALSE;
+ }
+
+ const TransformFeedback *transformFeedback = getTransformFeedback(id);
+ return ((transformFeedback != nullptr) ? GL_TRUE : GL_FALSE);
+}
+
+void Context::pauseTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ transformFeedback->pause();
+}
+
+void Context::resumeTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ transformFeedback->resume();
+}
+
} // namespace gl
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 2dd7736..6250bed 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -85,7 +85,6 @@
GLuint createTexture();
GLuint createRenderbuffer();
GLuint createSampler();
- GLuint createTransformFeedback();
GLsync createFenceSync();
GLuint createPaths(GLsizei range);
@@ -95,7 +94,6 @@
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
void deleteSampler(GLuint sampler);
- void deleteTransformFeedback(GLuint transformFeedback);
void deleteFenceSync(GLsync fenceSync);
void deletePaths(GLuint first, GLsizei range);
@@ -163,7 +161,7 @@
void bindPixelPackBuffer(GLuint bufferHandle);
void bindPixelUnpackBuffer(GLuint bufferHandle);
void useProgram(GLuint program);
- void bindTransformFeedback(GLuint transformFeedbackHandle);
+ void bindTransformFeedback(GLenum target, GLuint transformFeedbackHandle);
void bindDrawIndirectBuffer(GLuint bufferHandle);
void beginQuery(GLenum target, GLuint query);
@@ -814,6 +812,25 @@
void genVertexArrays(GLsizei n, GLuint *arrays);
bool isVertexArray(GLuint array);
+ void endTransformFeedback();
+ void transformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+ void getTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name);
+
+ void deleteTransformFeedbacks(GLsizei n, const GLuint *ids);
+ void genTransformFeedbacks(GLsizei n, GLuint *ids);
+ bool isTransformFeedback(GLuint id);
+ void pauseTransformFeedback();
+ void resumeTransformFeedback();
+
void getProgramBinary(GLuint program,
GLsizei bufSize,
GLsizei *length,
diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h
index b9a662c..d2c37c5 100644
--- a/src/libANGLE/ErrorStrings.h
+++ b/src/libANGLE/ErrorStrings.h
@@ -147,6 +147,7 @@
ERRMSG(StrideMustBeMultipleOfType, "Stride must be a multiple of the passed in datatype.");
ERRMSG(TextureNotBound, "A texture must be bound.");
ERRMSG(TextureNotPow2, "The texture is a non-power-of-two texture.");
+ERRMSG(TransformFeedbackDoesNotExist, "Transform feedback object that does not exist.");
ERRMSG(TypeMismatch,
"Passed in texture target and format must match the one originally used to define the "
"texture.");
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 4463108..f07d29f 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -2914,4 +2914,200 @@
return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
}
+bool ValidateEndTransformFeedback(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ if (!transformFeedback->isActive())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTransformFeedbackVaryings(Context *context,
+ GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (count < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
+ return false;
+ }
+
+ switch (bufferMode)
+ {
+ case GL_INTERLEAVED_ATTRIBS:
+ break;
+ case GL_SEPARATE_ATTRIBS:
+ {
+ const Caps &caps = context->getCaps();
+ if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+ }
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTransformFeedbackVarying(Context *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK:
+ {
+ // Cannot bind a transform feedback object if the current one is started and not
+ // paused (3.0.2 pg 85 section 2.14.1)
+ TransformFeedback *curTransformFeedback =
+ context->getGLState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
+ // 2.14.1)
+ if (!context->isTransformFeedbackGenerated(id))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsTransformFeedback(Context *context, GLuint id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePauseTransformFeedback(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
+ if (!transformFeedback->isActive() || transformFeedback->isPaused())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateResumeTransformFeedback(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
+ if (!transformFeedback->isActive() || !transformFeedback->isPaused())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ return true;
+}
+
} // namespace gl
diff --git a/src/libANGLE/validationES3.h b/src/libANGLE/validationES3.h
index 4a9b34c..7f62f8c 100644
--- a/src/libANGLE/validationES3.h
+++ b/src/libANGLE/validationES3.h
@@ -491,6 +491,25 @@
GLboolean transpose,
const GLfloat *value);
+bool ValidateEndTransformFeedback(Context *context);
+bool ValidateTransformFeedbackVaryings(Context *context,
+ GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+bool ValidateGetTransformFeedbackVarying(Context *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name);
+bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id);
+bool ValidateIsTransformFeedback(Context *context, GLuint id);
+bool ValidatePauseTransformFeedback(Context *context);
+bool ValidateResumeTransformFeedback(Context *context);
+
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES3_H_
diff --git a/src/libGLESv2/entry_points_gles_3_0.cpp b/src/libGLESv2/entry_points_gles_3_0.cpp
index e194cca..e89796c 100644
--- a/src/libGLESv2/entry_points_gles_3_0.cpp
+++ b/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -735,6 +735,7 @@
{
return;
}
+
context->getIntegeri_v(target, index, data);
}
}
@@ -762,22 +763,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
+ if (!context->skipValidation() && !ValidateEndTransformFeedback(context))
{
- context->handleError(InvalidOperation());
return;
}
- TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != nullptr);
-
- if (!transformFeedback->isActive())
- {
- context->handleError(InvalidOperation());
- return;
- }
-
- transformFeedback->end(context);
+ context->endTransformFeedback();
}
}
@@ -797,6 +788,7 @@
{
return;
}
+
context->bindBufferRange(target, index, buffer, offset, size);
}
}
@@ -812,6 +804,7 @@
{
return;
}
+
context->bindBufferBase(target, index, buffer);
}
}
@@ -829,42 +822,13 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
- {
- context->handleError(InvalidOperation());
- return;
- }
-
- if (count < 0)
- {
- context->handleError(InvalidValue());
- return;
- }
-
- const Caps &caps = context->getCaps();
- switch (bufferMode)
- {
- case GL_INTERLEAVED_ATTRIBS:
- break;
- case GL_SEPARATE_ATTRIBS:
- if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
- {
- context->handleError(InvalidValue());
- return;
- }
- break;
- default:
- context->handleError(InvalidEnum());
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
+ if (!context->skipValidation() &&
+ !ValidateTransformFeedbackVaryings(context, program, count, varyings, bufferMode))
{
return;
}
- programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
+ context->transformFeedbackVaryings(program, count, varyings, bufferMode);
}
}
@@ -884,31 +848,14 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
- {
- context->handleError(InvalidOperation());
- return;
- }
-
- if (bufSize < 0)
- {
- context->handleError(InvalidValue());
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
+ if (!context->skipValidation() &&
+ !ValidateGetTransformFeedbackVarying(context, program, index, bufSize, length, size,
+ type, name))
{
return;
}
- if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
- {
- context->handleError(InvalidValue());
- return;
- }
-
- programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
+ context->getTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
}
}
@@ -2143,45 +2090,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
+ if (!context->skipValidation() && !ValidateBindTransformFeedback(context, target, id))
{
- context->handleError(InvalidOperation());
return;
}
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK:
- {
- // Cannot bind a transform feedback object if the current one is started and not
- // paused (3.0.2 pg 85 section 2.14.1)
- TransformFeedback *curTransformFeedback =
- context->getGLState().getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isActive() &&
- !curTransformFeedback->isPaused())
- {
- context->handleError(InvalidOperation());
- return;
- }
-
- // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
- // 2.14.1)
- if (!context->isTransformFeedbackGenerated(id))
- {
- context->handleError(
- InvalidOperation()
- << "Cannot bind a transform feedback object that does not exist.");
- return;
- }
-
- context->bindTransformFeedback(id);
- }
- break;
-
- default:
- context->handleError(InvalidEnum());
- return;
- }
+ context->bindTransformFeedback(target, id);
}
}
@@ -2197,10 +2111,7 @@
return;
}
- for (int i = 0; i < n; i++)
- {
- context->deleteTransformFeedback(ids[i]);
- }
+ context->deleteTransformFeedbacks(n, ids);
}
}
@@ -2216,10 +2127,7 @@
return;
}
- for (int i = 0; i < n; i++)
- {
- ids[i] = context->createTransformFeedback();
- }
+ context->genTransformFeedbacks(n, ids);
}
}
@@ -2230,21 +2138,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
+ if (!context->skipValidation() && !ValidateIsTransformFeedback(context, id))
{
- context->handleError(InvalidOperation());
return GL_FALSE;
}
- if (id == 0)
- {
- // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
- // returns FALSE
- return GL_FALSE;
- }
-
- const TransformFeedback *transformFeedback = context->getTransformFeedback(id);
- return ((transformFeedback != nullptr) ? GL_TRUE : GL_FALSE);
+ return context->isTransformFeedback(id);
}
return GL_FALSE;
@@ -2257,23 +2156,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
+ if (!context->skipValidation() && !ValidatePauseTransformFeedback(context))
{
- context->handleError(InvalidOperation());
return;
}
- TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != nullptr);
-
- // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
- if (!transformFeedback->isActive() || transformFeedback->isPaused())
- {
- context->handleError(InvalidOperation());
- return;
- }
-
- transformFeedback->pause();
+ context->pauseTransformFeedback();
}
}
@@ -2284,23 +2172,12 @@
Context *context = GetValidGlobalContext();
if (context)
{
- if (context->getClientMajorVersion() < 3)
+ if (!context->skipValidation() && !ValidateResumeTransformFeedback(context))
{
- context->handleError(InvalidOperation());
return;
}
- TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != nullptr);
-
- // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
- if (!transformFeedback->isActive() || !transformFeedback->isPaused())
- {
- context->handleError(InvalidOperation());
- return;
- }
-
- transformFeedback->resume();
+ context->resumeTransformFeedback();
}
}