Refactored TransformFeedback for multi-platform ANGLE and added tests.

Added angle_implementation_unit_tests target designed for testing the
cross-platform code in libGLESv2, and libGLESv2_static target as a
dependency. The goal is to incorporate these tests into Chromium's
angle_unittests target on all platforms; however, more work is needed
to make libGLESv2's common code compile on non-Windows platforms, so
this is an intermediate step.

BUG=angle:719

Change-Id: Ifc44a779352294e857d6e913d9b997a60674c443
Reviewed-on: https://chromium-review.googlesource.com/214105
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Kenneth Russell <kbr@chromium.org>
diff --git a/src/libGLESv2.gypi b/src/libGLESv2.gypi
index 4f8938d..f54ced3 100644
--- a/src/libGLESv2.gypi
+++ b/src/libGLESv2.gypi
@@ -114,6 +114,7 @@
             'libGLESv2/renderer/ShaderExecutable.h',
             'libGLESv2/renderer/SwapChain.h',
             'libGLESv2/renderer/TextureImpl.h',
+            'libGLESv2/renderer/TransformFeedbackImpl.h',
             'libGLESv2/renderer/VertexArrayImpl.h',
             'libGLESv2/renderer/copyimage.cpp',
             'libGLESv2/renderer/copyimage.h',
@@ -158,6 +159,8 @@
             'libGLESv2/renderer/d3d/TextureD3D.h',
             'libGLESv2/renderer/d3d/TextureStorage.cpp',
             'libGLESv2/renderer/d3d/TextureStorage.h',
+            'libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp',
+            'libGLESv2/renderer/d3d/TransformFeedbackD3D.h',
             'libGLESv2/renderer/d3d/VertexBuffer.cpp',
             'libGLESv2/renderer/d3d/VertexBuffer.h',
             'libGLESv2/renderer/d3d/VertexDataManager.cpp',
@@ -399,6 +402,33 @@
                         },
                     },
                 },
+                {
+                    # This target supports angle_implementation_unittests.
+                    # It only executes cross-platform code and therefore
+                    # doesn't need any Direct3D DLLs.
+                    'target_name': 'libGLESv2_static',
+                    'type': 'static_library',
+                    'dependencies': [ 'translator', 'commit_id' ],
+                    'includes': [ '../build/common_defines.gypi', ],
+                    'include_dirs':
+                    [
+                        '.',
+                        '../include',
+                        'libGLESv2',
+                    ],
+                    'sources':
+                    [
+                        '<@(angle_libglesv2_sources)',
+                    ],
+                    'defines':
+                    [
+                        'GL_APICALL=',
+                        'GL_GLEXT_PROTOTYPES=',
+                        'EGLAPI=',
+                        # Workaround for D3D-specific code in Renderer.h
+                        'ANGLE_COMPILE_OPTIMIZATION_LEVEL=0',
+                    ],
+                },
             ],
         },
         ],
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index fc1ca08..671bb1c 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -101,7 +101,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
-    mTransformFeedbackZero.set(new TransformFeedback(0));
+    mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0));
     bindTransformFeedback(0);
 
     mHasBeenCurrent = false;
@@ -262,7 +262,7 @@
 GLuint Context::createTransformFeedback()
 {
     GLuint handle = mTransformFeedbackAllocator.allocate();
-    TransformFeedback *transformFeedback = new TransformFeedback(handle);
+    TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle);
     transformFeedback->addRef();
     mTransformFeedbackMap[handle] = transformFeedback;
     return handle;
diff --git a/src/libGLESv2/TransformFeedback.cpp b/src/libGLESv2/TransformFeedback.cpp
index 79ce084..bfa7072 100644
--- a/src/libGLESv2/TransformFeedback.cpp
+++ b/src/libGLESv2/TransformFeedback.cpp
@@ -5,20 +5,24 @@
 //
 
 #include "libGLESv2/TransformFeedback.h"
+#include "libGLESv2/renderer/TransformFeedbackImpl.h"
 
 namespace gl
 {
 
-TransformFeedback::TransformFeedback(GLuint id)
+TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id)
     : RefCountObject(id),
+      mTransformFeedback(impl),
       mStarted(GL_FALSE),
       mPrimitiveMode(GL_NONE),
       mPaused(GL_FALSE)
 {
+    ASSERT(impl != NULL);
 }
 
 TransformFeedback::~TransformFeedback()
 {
+    SafeDelete(mTransformFeedback);
 }
 
 void TransformFeedback::start(GLenum primitiveMode)
@@ -26,6 +30,7 @@
     mStarted = GL_TRUE;
     mPrimitiveMode = primitiveMode;
     mPaused = GL_FALSE;
+    mTransformFeedback->begin(primitiveMode);
 }
 
 void TransformFeedback::stop()
@@ -33,6 +38,7 @@
     mStarted = GL_FALSE;
     mPrimitiveMode = GL_NONE;
     mPaused = GL_FALSE;
+    mTransformFeedback->end();
 }
 
 GLboolean TransformFeedback::isStarted() const
@@ -48,11 +54,13 @@
 void TransformFeedback::pause()
 {
     mPaused = GL_TRUE;
+    mTransformFeedback->pause();
 }
 
 void TransformFeedback::resume()
 {
     mPaused = GL_FALSE;
+    mTransformFeedback->resume();
 }
 
 GLboolean TransformFeedback::isPaused() const
diff --git a/src/libGLESv2/TransformFeedback.h b/src/libGLESv2/TransformFeedback.h
index d6f4522..885a4fe 100644
--- a/src/libGLESv2/TransformFeedback.h
+++ b/src/libGLESv2/TransformFeedback.h
@@ -12,13 +12,18 @@
 
 #include "angle_gl.h"
 
+namespace rx
+{
+class TransformFeedbackImpl;
+}
+
 namespace gl
 {
 
 class TransformFeedback : public RefCountObject
 {
   public:
-    explicit TransformFeedback(GLuint id);
+    TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id);
     virtual ~TransformFeedback();
 
     void start(GLenum primitiveMode);
@@ -34,6 +39,8 @@
   private:
     DISALLOW_COPY_AND_ASSIGN(TransformFeedback);
 
+    rx::TransformFeedbackImpl* mTransformFeedback;
+
     GLboolean mStarted;
     GLenum mPrimitiveMode;
     GLboolean mPaused;
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index 760663e..e4c0476 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -60,6 +60,7 @@
 class TextureStorage;
 class UniformStorage;
 class TextureImpl;
+class TransformFeedbackImpl;
 
 struct ConfigDesc
 {
@@ -229,6 +230,9 @@
     virtual QueryImpl *createQuery(GLenum type) = 0;
     virtual FenceImpl *createFence() = 0;
 
+    // Transform Feedback creation
+    virtual TransformFeedbackImpl* createTransformFeedback() = 0;
+
     // Current GLES client version
     void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; }
     int getCurrentClientVersion() const { return mCurrentClientVersion; }
diff --git a/src/libGLESv2/renderer/TransformFeedbackImpl.h b/src/libGLESv2/renderer/TransformFeedbackImpl.h
new file mode 100644
index 0000000..8425604
--- /dev/null
+++ b/src/libGLESv2/renderer/TransformFeedbackImpl.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#define LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/TransformFeedback.h"
+
+namespace rx
+{
+
+class TransformFeedbackImpl
+{
+  public:
+    virtual ~TransformFeedbackImpl() { }
+
+    virtual void begin(GLenum primitiveMode) = 0;
+    virtual void end() = 0;
+    virtual void pause() = 0;
+    virtual void resume() = 0;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
diff --git a/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp
new file mode 100644
index 0000000..706658b
--- /dev/null
+++ b/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp
@@ -0,0 +1,39 @@
+#include "precompiled.h"
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
+
+#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
+
+namespace rx
+{
+
+TransformFeedbackD3D::TransformFeedbackD3D()
+{
+}
+
+TransformFeedbackD3D::~TransformFeedbackD3D()
+{
+}
+
+void TransformFeedbackD3D::begin(GLenum primitiveMode)
+{
+}
+
+void TransformFeedbackD3D::end()
+{
+}
+
+void TransformFeedbackD3D::pause()
+{
+}
+
+void TransformFeedbackD3D::resume()
+{
+}
+
+}
diff --git a/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h b/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h
new file mode 100644
index 0000000..7c367ab
--- /dev/null
+++ b/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+#define LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+
+#include "libGLESv2/renderer/TransformFeedbackImpl.h"
+#include "libGLESv2/angletypes.h"
+
+namespace rx
+{
+
+class TransformFeedbackD3D : public TransformFeedbackImpl
+{
+  public:
+    TransformFeedbackD3D();
+    virtual ~TransformFeedbackD3D();
+
+    virtual void begin(GLenum primitiveMode);
+    virtual void end();
+    virtual void pause();
+    virtual void resume();
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
index a173acd..0c94728 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -14,6 +14,7 @@
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Framebuffer.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
@@ -2488,6 +2489,11 @@
     return new Fence11(this);
 }
 
+TransformFeedbackImpl* Renderer11::createTransformFeedback()
+{
+    return new TransformFeedbackD3D();
+}
+
 bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
 {
     ASSERT(getRendererExtensions().pixelBufferObject);
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
index e75e602..3288f2b 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
@@ -178,6 +178,9 @@
     virtual QueryImpl *createQuery(GLenum type);
     virtual FenceImpl *createFence();
 
+    // Transform Feedback creation
+    virtual TransformFeedbackImpl* createTransformFeedback();
+
     // D3D11-renderer specific methods
     ID3D11Device *getDevice() { return mDevice; }
     ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index 1d36cae..0abe089 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -18,6 +18,7 @@
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/renderer/d3d/IndexDataManager.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
+#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
 #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
@@ -600,6 +601,11 @@
     return new Fence9(this);
 }
 
+TransformFeedbackImpl* Renderer9::createTransformFeedback()
+{
+    return new TransformFeedbackD3D();
+}
+
 bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
 {
     // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
index 1413196..2fee522 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
@@ -180,6 +180,9 @@
     virtual QueryImpl *createQuery(GLenum type);
     virtual FenceImpl *createFence();
 
+    // Transform Feedback creation
+    virtual TransformFeedbackImpl* createTransformFeedback();
+
     // Buffer-to-texture and Texture-to-buffer copies
     virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
     virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,