Transform Feedback and Sampler API Implemented
Implemented API functions related to creating,
binding, deleting or accessing the parameters
of Transform Feedback and Sampler objects.
Change-Id: I267605733758332439addd71c24f5f438d22ba46
Reviewed-on: https://swiftshader-review.googlesource.com/2814
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 120035c..2ef8661 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -1343,6 +1343,11 @@
return mState.elementArrayBuffer;
}
+TransformFeedback *Context::getTransformFeedback()
+{
+ return getTransformFeedback(mState.transformFeedback);
+}
+
Program *Context::getCurrentProgram()
{
return mResourceManager->getProgram(mState.currentProgram);
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 08b9149..0a4b2b6 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -15,6 +15,7 @@
#include "Framebuffer.h"
#include "Program.h"
#include "Query.h"
+#include "Sampler.h"
#include "Texture.h"
#include "common/debug.h"
@@ -1320,15 +1321,15 @@
error(GL_INVALID_VALUE);
}
- if((access & ~(GL_MAP_READ_BIT |
- GL_MAP_WRITE_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT |
- GL_MAP_INVALIDATE_BUFFER_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
- {
- error(GL_INVALID_VALUE);
- }
+ if((access & ~(GL_MAP_READ_BIT |
+ GL_MAP_WRITE_BIT |
+ GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_INVALIDATE_BUFFER_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT)) != 0)
+ {
+ error(GL_INVALID_VALUE);
+ }
UNIMPLEMENTED();
return nullptr;
@@ -1356,7 +1357,17 @@
{
TRACE("(GLuint array = %d)", array);
- UNIMPLEMENTED();
+ if(array == 0)
+ {
+ return;
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context && !context->bindVertexArray(array))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
}
void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
@@ -1368,7 +1379,15 @@
return error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ for(int i = 0; i < n; i++)
+ {
+ context->deleteVertexArray(arrays[i]);
+ }
+ }
}
void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)
@@ -1380,14 +1399,38 @@
return error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ for(int i = 0; i < n; i++)
+ {
+ arrays[i] = context->createVertexArray();
+ }
+ }
}
GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
{
TRACE("(GLuint array = %d)", array);
- UNIMPLEMENTED();
+ if(array == 0)
+ {
+ return GL_FALSE;
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::VertexArray *arrayObject = context->getVertexArray(array);
+
+ if(arrayObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
return GL_FALSE;
}
@@ -1464,12 +1507,50 @@
return error(GL_INVALID_ENUM);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
+
+ if(transformFeedbackObject)
+ {
+ if(transformFeedbackObject->isActive())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ transformFeedbackObject->begin(primitiveMode);
+ }
+ else
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
}
void GL_APIENTRY glEndTransformFeedback(void)
{
- UNIMPLEMENTED();
+ TRACE("()");
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
+
+ if(transformFeedbackObject)
+ {
+ if(!transformFeedbackObject->isActive())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ transformFeedbackObject->end();
+ }
+ else
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
}
void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
@@ -1477,16 +1558,47 @@
TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d, GLintptr offset = %d, GLsizeiptr size = %d)",
target, index, buffer, offset, size);
- switch(target)
+ if(buffer != 0 && size <= 0)
{
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- case GL_UNIFORM_BUFFER:
- break;
- default:
- return error(GL_INVALID_ENUM);
+ return error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ switch(target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if(index >= es2::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ if(size & 0x3 || offset & 0x3) // size and offset must be multiples of 4
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
+ transformFeedback->setBuffer(index, context->getBuffer(buffer), offset, size);
+ }
+ break;
+ case GL_UNIFORM_BUFFER:
+ if(index >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ if(offset % es2::IMPLEMENTATION_UNIFORM_BUFFER_OFFSET_ALIGNMENT != 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ UNIMPLEMENTED();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
@@ -1494,16 +1606,34 @@
TRACE("(GLenum target = 0x%X, GLuint index = %d, GLuint buffer = %d)",
target, index, buffer);
- switch(target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- case GL_UNIFORM_BUFFER:
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
+ es2::Context *context = es2::getContext();
- UNIMPLEMENTED();
+ if(context)
+ {
+ switch(target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if(index >= es2::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ else
+ {
+ es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
+ transformFeedback->setBuffer(index, context->getBuffer(buffer));
+ }
+ break;
+ case GL_UNIFORM_BUFFER:
+ if(index >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ UNIMPLEMENTED();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)
@@ -1511,6 +1641,31 @@
TRACE("(GLuint program = %d, GLsizei count = %d, const GLchar *const*varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
program, count, varyings, bufferMode);
+ switch(bufferMode)
+ {
+ case GL_SEPARATE_ATTRIBS:
+ if(count > es2::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ case GL_INTERLEAVED_ATTRIBS:
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Program *programObject = context->getProgram(program);
+
+ if(!programObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+ }
+
UNIMPLEMENTED();
}
@@ -2259,6 +2414,17 @@
return error(GL_INVALID_VALUE);
}
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
+ if(transformFeedback && transformFeedback->isActive() && (mode != transformFeedback->primitiveMode()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+
UNIMPLEMENTED();
}
@@ -2296,6 +2462,17 @@
return error(GL_INVALID_VALUE);
}
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback* transformFeedback = context->getTransformFeedback();
+ if(transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+
UNIMPLEMENTED();
}
@@ -2400,7 +2577,15 @@
return error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ for(int i = 0; i < count; i++)
+ {
+ samplers[i] = context->createSampler();
+ }
+ }
}
void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)
@@ -2412,14 +2597,38 @@
return error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ for(int i = 0; i < count; i++)
+ {
+ context->deleteSampler(samplers[i]);
+ }
+ }
}
GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
{
TRACE("(GLuint sampler = %d)", sampler);
- UNIMPLEMENTED();
+ if(sampler == 0)
+ {
+ return GL_FALSE;
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Sampler *samplerObject = context->getSampler(sampler);
+
+ if(samplerObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
return GL_FALSE;
}
@@ -2427,7 +2636,27 @@
{
TRACE("(GLuint unit = %d, GLuint sampler = %d)", unit, sampler);
- UNIMPLEMENTED();
+ if(unit >= es2::MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ if(sampler != 0)
+ {
+ es2::Sampler *samplerObject = context->getSampler(sampler);
+
+ if(!samplerObject)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
+
+ context->bindSampler(unit, sampler);
+ }
}
void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
@@ -2443,7 +2672,119 @@
TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLint *param = 0x%0.8p)",
sampler, pname, param);
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;
+
+ if(!samplerObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch(pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ switch(*param)
+ {
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ case GL_REPEAT:
+ samplerObject->mWrapModeS = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_WRAP_T:
+ switch(*param)
+ {
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ case GL_REPEAT:
+ samplerObject->mWrapModeT = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_WRAP_R:
+ switch(*param)
+ {
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ case GL_REPEAT:
+ samplerObject->mWrapModeR = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ switch(*param)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ samplerObject->mMinFilter = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ switch(*param)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ samplerObject->mMagFilter = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ samplerObject->mMinLod = (GLfloat)*param;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ samplerObject->mMaxLod = (GLfloat)*param;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ switch(*param)
+ {
+ case GL_COMPARE_REF_TO_TEXTURE:
+ case GL_NONE:
+ samplerObject->mCompareMode = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ switch(*param)
+ {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ samplerObject->mCompareFunc = *param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
@@ -2459,7 +2800,119 @@
TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, const GLfloat *param = 0x%0.8p)",
sampler, pname, param);
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;
+
+ if(!samplerObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch(pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ switch((GLenum)*param)
+ {
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ case GL_REPEAT:
+ samplerObject->mWrapModeS = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_WRAP_T:
+ switch((GLenum)*param)
+ {
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ case GL_REPEAT:
+ samplerObject->mWrapModeT = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_WRAP_R:
+ switch((GLenum)*param)
+ {
+ case GL_CLAMP_TO_EDGE:
+ case GL_MIRRORED_REPEAT:
+ case GL_REPEAT:
+ samplerObject->mWrapModeR = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ switch((GLenum)*param)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ samplerObject->mMinFilter = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ switch((GLenum)*param)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ samplerObject->mMagFilter = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ samplerObject->mMinLod = *param;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ samplerObject->mMaxLod = *param;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ switch((GLenum)*param)
+ {
+ case GL_COMPARE_REF_TO_TEXTURE:
+ case GL_NONE:
+ samplerObject->mCompareMode = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ switch((GLenum)*param)
+ {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ samplerObject->mCompareFunc = (GLenum)*param;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
@@ -2467,7 +2920,50 @@
TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",
sampler, pname, params);
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;
+
+ if(!samplerObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch(pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ *params = samplerObject->mWrapModeS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = samplerObject->mWrapModeT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = samplerObject->mWrapModeR;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = samplerObject->mMinFilter;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = samplerObject->mMagFilter;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLint)samplerObject->mMinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLint)samplerObject->mMaxLod;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = samplerObject->mCompareMode;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = samplerObject->mCompareFunc;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
@@ -2475,7 +2971,50 @@
TRACE("(GLuint sampler = %d, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)",
sampler, pname, params);
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Sampler *samplerObject = (sampler != 0) ? context->getSampler(sampler) : nullptr;
+
+ if(!samplerObject)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ switch(pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLfloat)samplerObject->mWrapModeS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLfloat)samplerObject->mWrapModeT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = (GLfloat)samplerObject->mWrapModeR;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLfloat)samplerObject->mMinFilter;
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLfloat)samplerObject->mMagFilter;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = samplerObject->mMinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = samplerObject->mMaxLod;
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = (GLfloat)samplerObject->mCompareMode;
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = (GLfloat)samplerObject->mCompareFunc;
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
@@ -2488,39 +3027,136 @@
{
TRACE("(GLenum target = 0x%X, GLuint id = %d)", target, id);
- UNIMPLEMENTED();
+ if(target != GL_TRANSFORM_FEEDBACK)
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
+
+ if(transformFeedbackObject && transformFeedbackObject->isActive() && !transformFeedbackObject->isPaused())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if(!context->bindTransformFeedback(id))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ }
}
void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
{
TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
- UNIMPLEMENTED();
+ if(n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ for(int i = 0; i < n; i++)
+ {
+ if (ids[i] != 0)
+ {
+ context->deleteTransformFeedback(ids[i]);
+ }
+ }
+ }
}
void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)
{
TRACE("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
- UNIMPLEMENTED();
+ if(n < 0)
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ for(int i = 0; i < n; i++)
+ {
+ ids[i] = context->createTransformFeedback();
+ }
+ }
}
GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
{
TRACE("(GLuint id = %d)", id);
- UNIMPLEMENTED();
+ if(id == 0)
+ {
+ return GL_FALSE;
+ }
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback(id);
+
+ if(transformFeedbackObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
return GL_FALSE;
}
void GL_APIENTRY glPauseTransformFeedback(void)
{
- UNIMPLEMENTED();
+ TRACE("()");
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
+
+ if(transformFeedbackObject)
+ {
+ if(!transformFeedbackObject->isActive() || transformFeedbackObject->isPaused())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ transformFeedbackObject->setPaused(true);
+ }
+ }
}
void GL_APIENTRY glResumeTransformFeedback(void)
{
- UNIMPLEMENTED();
+ TRACE("()");
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::TransformFeedback *transformFeedbackObject = context->getTransformFeedback();
+
+ if(transformFeedbackObject)
+ {
+ if(!transformFeedbackObject->isActive() || !transformFeedbackObject->isPaused())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+ transformFeedbackObject->setPaused(false);
+ }
+ }
}
void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)