Commit f0dcb8b5 by Jamie Madill Committed by Commit Bot

Refactor transform feedback EPs.

BUG=angleproject:747 Change-Id: I4891966cd7b3d478980202e795742e15dd1dcb01 Reviewed-on: https://chromium-review.googlesource.com/637125Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent d7576737
......@@ -374,7 +374,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
// 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 @@ GLuint Context::createSampler()
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 @@ void Context::deleteSampler(GLuint sampler)
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 @@ void Context::useProgram(GLuint program)
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 @@ void Context::detachTransformFeedback(GLuint transformFeedback)
// 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 @@ bool Context::isVertexArray(GLuint array)
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
......@@ -85,7 +85,6 @@ class Context final : public ValidationContext
GLuint createTexture();
GLuint createRenderbuffer();
GLuint createSampler();
GLuint createTransformFeedback();
GLsync createFenceSync();
GLuint createPaths(GLsizei range);
......@@ -95,7 +94,6 @@ class Context final : public ValidationContext
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 @@ class Context final : public ValidationContext
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 @@ class Context final : public ValidationContext
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,
......
......@@ -147,6 +147,7 @@ ERRMSG(StencilReferenceMaskOrMismatch,
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.");
......
......@@ -2914,4 +2914,200 @@ bool ValidateUniformMatrix4x3fv(Context *context,
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
......@@ -491,6 +491,25 @@ bool ValidateUniformMatrix4x3fv(Context *context,
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_
......@@ -735,6 +735,7 @@ void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data)
{
return;
}
context->getIntegeri_v(target, index, data);
}
}
......@@ -762,22 +763,12 @@ void GL_APIENTRY EndTransformFeedback(void)
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 @@ BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLs
{
return;
}
context->bindBufferRange(target, index, buffer, offset, size);
}
}
......@@ -812,6 +804,7 @@ void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
{
return;
}
context->bindBufferBase(target, index, buffer);
}
}
......@@ -829,42 +822,13 @@ void GL_APIENTRY TransformFeedbackVaryings(GLuint program,
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 @@ void GL_APIENTRY GetTransformFeedbackVarying(GLuint program,
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)
{
return;
}
if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
if (!context->skipValidation() &&
!ValidateGetTransformFeedbackVarying(context, program, index, bufSize, length, size,
type, name))
{
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 @@ void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
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 @@ void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
return;
}
for (int i = 0; i < n; i++)
{
context->deleteTransformFeedback(ids[i]);
}
context->deleteTransformFeedbacks(n, ids);
}
}
......@@ -2216,10 +2127,7 @@ void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint *ids)
return;
}
for (int i = 0; i < n; i++)
{
ids[i] = context->createTransformFeedback();
}
context->genTransformFeedbacks(n, ids);
}
}
......@@ -2230,21 +2138,12 @@ GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientMajorVersion() < 3)
{
context->handleError(InvalidOperation());
return GL_FALSE;
}
if (id == 0)
if (!context->skipValidation() && !ValidateIsTransformFeedback(context, id))
{
// 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 @@ void GL_APIENTRY PauseTransformFeedback(void)
Context *context = GetValidGlobalContext();
if (context)
{
if (context->getClientMajorVersion() < 3)
{
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())
if (!context->skipValidation() && !ValidatePauseTransformFeedback(context))
{
context->handleError(InvalidOperation());
return;
}
transformFeedback->pause();
context->pauseTransformFeedback();
}
}
......@@ -2284,23 +2172,12 @@ void GL_APIENTRY ResumeTransformFeedback(void)
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();
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment