Add functionality to create and destroy TransformFeedback objects.

BUG=angle:491

Change-Id: I3ee3c2aec1878ad656a8f522943a29fea6f7e215
Reviewed-on: https://chromium-review.googlesource.com/185033
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 8322d7e..8c1cd3c 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -28,6 +28,7 @@
 #include "libGLESv2/VertexArray.h"
 #include "libGLESv2/Sampler.h"
 #include "libGLESv2/validationES.h"
+#include "libGLESv2/TransformFeedback.h"
 
 #include "libEGL/Surface.h"
 
@@ -192,6 +193,13 @@
     bindPixelPackBuffer(0);
     bindPixelUnpackBuffer(0);
 
+    // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
+    // 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
+    mTransformFeedbackZero.set(new TransformFeedback(0));
+    bindTransformFeedback(0);
+
     mState.currentProgram = 0;
     mCurrentProgramBinary.set(NULL);
 
@@ -252,6 +260,12 @@
         deleteVertexArray(mVertexArrayMap.begin()->first);
     }
 
+    mTransformFeedbackZero.set(NULL);
+    while (!mTransformFeedbackMap.empty())
+    {
+        deleteTransformFeedback(mTransformFeedbackMap.begin()->first);
+    }
+
     for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
     {
         for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
@@ -274,6 +288,8 @@
     mState.arrayBuffer.set(NULL);
     mState.renderbuffer.set(NULL);
 
+    mState.transformFeedback.set(NULL);
+
     mTexture2DZero.set(NULL);
     mTextureCubeMapZero.set(NULL);
     mTexture3DZero.set(NULL);
@@ -881,6 +897,15 @@
     return mResourceManager->createSampler();
 }
 
+GLuint Context::createTransformFeedback()
+{
+    GLuint handle = mTransformFeedbackAllocator.allocate();
+    TransformFeedback *transformFeedback = new TransformFeedback(handle);
+    transformFeedback->addRef();
+    mTransformFeedbackMap[handle] = transformFeedback;
+    return handle;
+}
+
 // Returns an unused framebuffer name
 GLuint Context::createFramebuffer()
 {
@@ -983,6 +1008,18 @@
     mResourceManager->deleteSampler(sampler);
 }
 
+void Context::deleteTransformFeedback(GLuint transformFeedback)
+{
+    TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(transformFeedback);
+    if (iter != mTransformFeedbackMap.end())
+    {
+        detachTransformFeedback(transformFeedback);
+        mTransformFeedbackAllocator.release(transformFeedback);
+        iter->second->release();
+        mTransformFeedbackMap.erase(iter);
+    }
+}
+
 void Context::deleteFramebuffer(GLuint framebuffer)
 {
     FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
@@ -1072,6 +1109,19 @@
     return mResourceManager->getSampler(handle);
 }
 
+TransformFeedback *Context::getTransformFeedback(GLuint handle) const
+{
+    if (handle == 0)
+    {
+        return mTransformFeedbackZero.get();
+    }
+    else
+    {
+        TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle);
+        return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL;
+    }
+}
+
 Framebuffer *Context::getReadFramebuffer()
 {
     return getFramebuffer(mState.readFramebuffer);
@@ -1089,6 +1139,11 @@
     return vao;
 }
 
+TransformFeedback *Context::getCurrentTransformFeedback() const
+{
+    return mState.transformFeedback.get();
+}
+
 bool Context::isSampler(GLuint samplerName) const
 {
     return mResourceManager->isSampler(samplerName);
@@ -1292,6 +1347,12 @@
 
 }
 
+void Context::bindTransformFeedback(GLuint transformFeedback)
+{
+    TransformFeedback *transformFeedbackObject = getTransformFeedback(transformFeedback);
+    mState.transformFeedback.set(transformFeedbackObject);
+}
+
 void Context::beginQuery(GLenum target, GLuint query)
 {
     // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>  
@@ -3413,6 +3474,14 @@
     }
 }
 
+void Context::detachTransformFeedback(GLuint transformFeedback)
+{
+    if (mState.transformFeedback.id() == transformFeedback)
+    {
+        bindTransformFeedback(0);
+    }
+}
+
 void Context::detachSampler(GLuint sampler)
 {
     // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: