Pass ImplFactory to Texture constructor

This improves encapsulation inside the Texture class, and removes
duplication of createTexture calls. This is a necessary step towards
adding a shared "Data" structure to the Texture classes, following a
similar pattern as for example the Framebuffer class.

This patch also shares the same MockFactory class among different
unit tests.

BUG=angleproject:596
TEST=angle_unittests

Change-Id: Ie8d3a9aa4ec35565d7ecbabb8c40e7b1ba068721
Reviewed-on: https://chromium-review.googlesource.com/340200
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index dcb6b21..0b413f6 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -172,19 +172,19 @@
     // In order that access to these initial textures not be lost, they are treated as texture
     // objects all of whose names are 0.
 
-    Texture *zeroTexture2D = new Texture(mRenderer->createTexture(GL_TEXTURE_2D), 0, GL_TEXTURE_2D);
+    Texture *zeroTexture2D = new Texture(mRenderer, 0, GL_TEXTURE_2D);
     mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
 
-    Texture *zeroTextureCube = new Texture(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0, GL_TEXTURE_CUBE_MAP);
+    Texture *zeroTextureCube = new Texture(mRenderer, 0, GL_TEXTURE_CUBE_MAP);
     mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
 
     if (mClientVersion >= 3)
     {
         // TODO: These could also be enabled via extension
-        Texture *zeroTexture3D = new Texture(mRenderer->createTexture(GL_TEXTURE_3D), 0, GL_TEXTURE_3D);
+        Texture *zeroTexture3D = new Texture(mRenderer, 0, GL_TEXTURE_3D);
         mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
 
-        Texture *zeroTexture2DArray = new Texture(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0, GL_TEXTURE_2D_ARRAY);
+        Texture *zeroTexture2DArray = new Texture(mRenderer, 0, GL_TEXTURE_2D_ARRAY);
         mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
     }
 
diff --git a/src/libANGLE/Image_unittest.cpp b/src/libANGLE/Image_unittest.cpp
index 9c89be0..dcdd264 100644
--- a/src/libANGLE/Image_unittest.cpp
+++ b/src/libANGLE/Image_unittest.cpp
@@ -14,8 +14,10 @@
 #include "libANGLE/renderer/ImageImpl_mock.h"
 #include "libANGLE/renderer/TextureImpl_mock.h"
 #include "libANGLE/renderer/RenderbufferImpl_mock.h"
+#include "tests/angle_unittests_utils.h"
 
 using ::testing::_;
+using ::testing::NiceMock;
 using ::testing::Return;
 
 namespace angle
@@ -23,9 +25,11 @@
 // Verify ref counts are maintained between images and their siblings when objects are deleted
 TEST(ImageTest, RefCounting)
 {
+    NiceMock<rx::MockFactory> mockFactory;
     // Create a texture and an EGL image that uses the texture as its source
     rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
-    gl::Texture *texture = new gl::Texture(textureImpl, 1, GL_TEXTURE_2D);
+    EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
+    gl::Texture *texture = new gl::Texture(&mockFactory, 1, GL_TEXTURE_2D);
     texture->addRef();
 
     rx::MockImageImpl *imageImpl = new rx::MockImageImpl();
@@ -82,9 +86,11 @@
 // Verify that respecifiying textures releases references to the Image.
 TEST(ImageTest, RespecificationReleasesReferences)
 {
+    NiceMock<rx::MockFactory> mockFactory;
     // Create a texture and an EGL image that uses the texture as its source
     rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
-    gl::Texture *texture = new gl::Texture(textureImpl, 1, GL_TEXTURE_2D);
+    EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
+    gl::Texture *texture = new gl::Texture(&mockFactory, 1, GL_TEXTURE_2D);
     texture->addRef();
 
     gl::PixelUnpackState defaultUnpackState;
diff --git a/src/libANGLE/Program_unittest.cpp b/src/libANGLE/Program_unittest.cpp
index 78b9a80..6d99f00 100644
--- a/src/libANGLE/Program_unittest.cpp
+++ b/src/libANGLE/Program_unittest.cpp
@@ -8,7 +8,6 @@
 
 #include <gtest/gtest.h>
 
-#include "tests/angle_unittests_utils.h"
 #include "libANGLE/Program.h"
 
 using namespace gl;
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 3872d39..a0af9c6 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -403,7 +403,7 @@
         return textureMapIt->second;
     }
 
-    Texture *texture = new Texture(mFactory->createTexture(type), handle, type);
+    Texture *texture = new Texture(mFactory, handle, type);
     texture->addRef();
 
     if (handleAllocated)
diff --git a/src/libANGLE/ResourceManager_unittest.cpp b/src/libANGLE/ResourceManager_unittest.cpp
index d6ddeaf..86b987c 100644
--- a/src/libANGLE/ResourceManager_unittest.cpp
+++ b/src/libANGLE/ResourceManager_unittest.cpp
@@ -9,8 +9,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include "tests/angle_unittests_utils.h"
 #include "libANGLE/ResourceManager.h"
+#include "tests/angle_unittests_utils.h"
 
 using namespace rx;
 using namespace gl;
@@ -18,14 +18,6 @@
 namespace
 {
 
-class MockFactory : public NullFactory
-{
-  public:
-    MOCK_METHOD0(createBuffer, BufferImpl*());
-    MOCK_METHOD1(createTexture, TextureImpl*(GLenum));
-    MOCK_METHOD0(createRenderbuffer, RenderbufferImpl*());
-};
-
 class ResourceManagerTest : public testing::Test
 {
   protected:
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index 702ea59..920f52e 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -16,6 +16,8 @@
 #include "libANGLE/Image.h"
 #include "libANGLE/Surface.h"
 #include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/TextureImpl.h"
 
 namespace gl
 {
@@ -47,9 +49,9 @@
     return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level;
 }
 
-Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
+Texture::Texture(rx::ImplFactory *factory, GLuint id, GLenum target)
     : egl::ImageSibling(id),
-      mTexture(impl),
+      mTexture(factory->createTexture(target)),
       mLabel(),
       mTextureState(),
       mTarget(target),
@@ -863,4 +865,9 @@
 {
     return id();
 }
+
+rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
+{
+    return mTexture;
+}
 }
diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h
index f6cddf1..4f84777 100644
--- a/src/libANGLE/Texture.h
+++ b/src/libANGLE/Texture.h
@@ -21,13 +21,18 @@
 #include "libANGLE/FramebufferAttachment.h"
 #include "libANGLE/Image.h"
 #include "libANGLE/angletypes.h"
-#include "libANGLE/renderer/TextureImpl.h"
 
 namespace egl
 {
 class Surface;
 }
 
+namespace rx
+{
+class ImplFactory;
+class TextureImpl;
+}
+
 namespace gl
 {
 class Framebuffer;
@@ -40,7 +45,7 @@
                       public LabeledObject
 {
   public:
-    Texture(rx::TextureImpl *impl, GLuint id, GLenum target);
+    Texture(rx::ImplFactory *factory, GLuint id, GLenum target);
     ~Texture() override;
 
     void setLabel(const std::string &label) override;
@@ -180,7 +185,7 @@
     GLuint getId() const override;
 
   private:
-    rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mTexture; }
+    rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
 
     // ANGLE-only method, used internally
     friend class egl::Surface;
diff --git a/src/libANGLE/TransformFeedback.cpp b/src/libANGLE/TransformFeedback.cpp
index 6ee1700..46da469 100644
--- a/src/libANGLE/TransformFeedback.cpp
+++ b/src/libANGLE/TransformFeedback.cpp
@@ -8,6 +8,7 @@
 
 #include "libANGLE/Buffer.h"
 #include "libANGLE/Caps.h"
+#include "libANGLE/Data.h"
 #include "libANGLE/Program.h"
 #include "libANGLE/renderer/ImplFactory.h"
 #include "libANGLE/renderer/TransformFeedbackImpl.h"
diff --git a/src/libANGLE/TransformFeedback_unittest.cpp b/src/libANGLE/TransformFeedback_unittest.cpp
index 56d02e2..4303900 100644
--- a/src/libANGLE/TransformFeedback_unittest.cpp
+++ b/src/libANGLE/TransformFeedback_unittest.cpp
@@ -20,12 +20,6 @@
 namespace
 {
 
-class MockFactory : public rx::NullFactory
-{
-  public:
-    MOCK_METHOD0(createTransformFeedback, rx::TransformFeedbackImpl *());
-};
-
 class TransformFeedbackTest : public testing::Test
 {
   protected:
@@ -59,7 +53,7 @@
         testing::Mock::VerifyAndClear(mImpl);
     }
 
-    MockFactory mMockFactory;
+    rx::MockFactory mMockFactory;
     rx::MockTransformFeedbackImpl* mImpl;
     gl::TransformFeedback* mFeedback;
     gl::Caps mCaps;
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/libANGLE/renderer/d3d/RendererD3D.cpp
index da86a49..66847bb 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.cpp
+++ b/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -15,6 +15,7 @@
 #include "libANGLE/formatutils.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/TextureImpl.h"
 #include "libANGLE/renderer/d3d/BufferD3D.h"
 #include "libANGLE/renderer/d3d/DeviceD3D.h"
 #include "libANGLE/renderer/d3d/DisplayD3D.h"
@@ -440,8 +441,7 @@
         const gl::Box area(0, 0, 0, 1, 1, 1);
 
         // Skip the API layer to avoid needing to pass the Context and mess with dirty bits.
-        gl::Texture *t =
-            new gl::Texture(createTexture(type), std::numeric_limits<GLuint>::max(), type);
+        gl::Texture *t = new gl::Texture(this, std::numeric_limits<GLuint>::max(), type);
         t->setStorage(type, 1, GL_RGBA8, colorSize);
 
         if (type == GL_TEXTURE_CUBE_MAP)
diff --git a/src/libANGLE/validationES_unittest.cpp b/src/libANGLE/validationES_unittest.cpp
index ef049f9..5766c5f 100644
--- a/src/libANGLE/validationES_unittest.cpp
+++ b/src/libANGLE/validationES_unittest.cpp
@@ -26,14 +26,6 @@
 namespace
 {
 
-class MockFactory : public NullFactory
-{
-  public:
-    MOCK_METHOD1(createFramebuffer, FramebufferImpl *(const gl::Framebuffer::Data &));
-    MOCK_METHOD1(createProgram, ProgramImpl *(const gl::Program::Data &));
-    MOCK_METHOD1(createVertexArray, VertexArrayImpl *(const gl::VertexArray::Data &));
-};
-
 class MockValidationContext : public ValidationContext
 {
   public:
@@ -95,10 +87,11 @@
     state.initialize(caps, extensions, 3, false);
 
     NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
+    EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
     EXPECT_CALL(*textureImpl, setStorage(_, _, _, _)).WillOnce(Return(Error(GL_NO_ERROR)));
     EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
 
-    Texture *texture = new Texture(textureImpl, 0, GL_TEXTURE_2D);
+    Texture *texture = new Texture(&mockFactory, 0, GL_TEXTURE_2D);
     texture->addRef();
     texture->setStorage(GL_TEXTURE_2D, 1, GL_RGBA8, Extents(1, 1, 0));
 
diff --git a/src/tests/angle_unittests_utils.h b/src/tests/angle_unittests_utils.h
index b7e3882..5865680 100644
--- a/src/tests/angle_unittests_utils.h
+++ b/src/tests/angle_unittests_utils.h
@@ -52,6 +52,24 @@
     SamplerImpl *createSampler() override { return nullptr; }
 };
 
+// A class with all the factory methods mocked.
+class MockFactory : public ImplFactory
+{
+  public:
+    MOCK_METHOD0(createCompiler, CompilerImpl *());
+    MOCK_METHOD1(createShader, ShaderImpl *(const gl::Shader::Data &));
+    MOCK_METHOD1(createProgram, ProgramImpl *(const gl::Program::Data &));
+    MOCK_METHOD1(createFramebuffer, FramebufferImpl *(const gl::Framebuffer::Data &));
+    MOCK_METHOD1(createTexture, TextureImpl *(GLenum target));
+    MOCK_METHOD0(createRenderbuffer, RenderbufferImpl *());
+    MOCK_METHOD0(createBuffer, BufferImpl *());
+    MOCK_METHOD1(createVertexArray, VertexArrayImpl *(const gl::VertexArray::Data &));
+    MOCK_METHOD1(createQuery, QueryImpl *(GLenum type));
+    MOCK_METHOD0(createFenceNV, FenceNVImpl *());
+    MOCK_METHOD0(createFenceSync, FenceSyncImpl *());
+    MOCK_METHOD0(createTransformFeedback, TransformFeedbackImpl *());
+    MOCK_METHOD0(createSampler, SamplerImpl *());
+};
 }
 
 #endif // TESTS_ANGLE_UNITTESTS_UTILS_H_