Move incomplete texture logic to shared helper.

The incomplete texture handling is similar between the D3D and Vulkan
back-ends. We create 1x1 textures, initialize them to black, and bind
them when we detect incomplete textures. We would also bind incomplete
textures when we detect feedback loops. In the GL back-end, we
wouldn't detect feedback loops, and would allow the driver to handle
incompleteness.

Instead implement this in a shared helper class, and do the feedback
loop detection in the front-end for every back-end. This makes our
behaviour more consistent between back-ends, and prevents undefined
behaviour.

Because initializing multisample textures is tricky (they
can't be updated with TexImage calls) we do a bit of a workaround so
the back-end can clear the incomplete multisample texture initially.

This progresses the initial Vulkan textures implementation.

BUG=angleproject:2167

Change-Id: I79ddcc0711fcc986f2578a52ac6f701231d241ac
Reviewed-on: https://chromium-review.googlesource.com/700993
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/renderer/renderer_utils.h b/src/libANGLE/renderer/renderer_utils.h
index 37ca1de..d4aabf3 100644
--- a/src/libANGLE/renderer/renderer_utils.h
+++ b/src/libANGLE/renderer/renderer_utils.h
@@ -217,6 +217,37 @@
                        bool unpackPremultiplyAlpha,
                        bool unpackUnmultiplyAlpha);
 
+// Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
+// This helper class encapsulates handling incomplete textures. Because the GL back-end
+// can take advantage of the driver's incomplete textures, and because clearing multisample
+// textures is so difficult, we can keep an instance of this class in the back-end instead
+// of moving the logic to the Context front-end.
+
+// This interface allows us to call-back to init a multisample texture.
+class MultisampleTextureInitializer
+{
+  public:
+    virtual gl::Error initializeMultisampleTextureToBlack(const gl::Context *context,
+                                                          gl::Texture *glTexture) = 0;
+};
+
+class IncompleteTextureSet final : angle::NonCopyable
+{
+  public:
+    IncompleteTextureSet();
+    ~IncompleteTextureSet();
+
+    void onDestroy(const gl::Context *context);
+
+    gl::Error getIncompleteTexture(const gl::Context *context,
+                                   GLenum type,
+                                   MultisampleTextureInitializer *multisampleInitializer,
+                                   gl::Texture **textureOut);
+
+  private:
+    gl::TextureMap mIncompleteTextures;
+};
+
 }  // namespace rx
 
 #endif  // LIBANGLE_RENDERER_RENDERER_UTILS_H_