Use a shared state for egl::Image.

This allows us to stop duplicating some information in the impl.

BUG=angleproject:1635

Change-Id: If8f7d2418571c3254729f48c463814ec18ed2644
Reviewed-on: https://chromium-review.googlesource.com/469153
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp
index 718480b..1a39304 100644
--- a/src/libANGLE/Image.cpp
+++ b/src/libANGLE/Image.cpp
@@ -14,10 +14,37 @@
 #include "libANGLE/formatutils.h"
 #include "libANGLE/Texture.h"
 #include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
 #include "libANGLE/renderer/ImageImpl.h"
 
 namespace egl
 {
+
+namespace
+{
+gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
+{
+    if (eglTarget == EGL_GL_RENDERBUFFER)
+    {
+        return gl::ImageIndex::MakeInvalid();
+    }
+
+    GLenum target = egl_gl::EGLImageTargetToGLTextureTarget(eglTarget);
+    GLint mip     = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0));
+    GLint layer   = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0));
+
+    if (target == GL_TEXTURE_3D)
+    {
+        return gl::ImageIndex::Make3D(mip, layer);
+    }
+    else
+    {
+        ASSERT(layer == 0);
+        return gl::ImageIndex::MakeGeneric(target, mip);
+    }
+}
+}  // anonymous namespace
+
 ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), mSourcesOf(), mTargetOf()
 {
 }
@@ -44,23 +71,14 @@
         // Can't be a target and have sources.
         ASSERT(mSourcesOf.empty());
 
-        gl::Error error = mTargetOf->orphanSibling(this);
-        if (error.isError())
-        {
-            return error;
-        }
-
+        ANGLE_TRY(mTargetOf->orphanSibling(this));
         mTargetOf.set(nullptr);
     }
     else
     {
         for (auto &sourceImage : mSourcesOf)
         {
-            gl::Error error = sourceImage->orphanSibling(this);
-            if (error.isError())
-            {
-                return error;
-            }
+            ANGLE_TRY(sourceImage->orphanSibling(this));
         }
         mSourcesOf.clear();
     }
@@ -80,25 +98,32 @@
     mSourcesOf.erase(imageSource);
 }
 
-Image::Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+    : imageIndex(GetImageIndex(target, attribs)), source(), targets()
+{
+    source.set(buffer);
+}
+
+Image::Image(rx::EGLImplFactory *factory,
+             EGLenum target,
+             ImageSibling *buffer,
+             const AttributeMap &attribs)
     : RefCountObject(0),
-      mImplementation(impl),
+      mState(target, buffer, attribs),
+      mImplementation(factory->createImage(mState, target, attribs)),
       mFormat(gl::Format::Invalid()),
       mWidth(0),
       mHeight(0),
-      mSamples(0),
-      mSource(),
-      mTargets()
+      mSamples(0)
 {
     ASSERT(mImplementation != nullptr);
     ASSERT(buffer != nullptr);
 
-    mSource.set(buffer);
-    mSource->addImageSource(this);
+    mState.source->addImageSource(this);
 
     if (IsTextureTarget(target))
     {
-        gl::Texture *texture = rx::GetAs<gl::Texture>(mSource.get());
+        gl::Texture *texture = rx::GetAs<gl::Texture>(mState.source.get());
         GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target);
         size_t level         = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
         mFormat              = texture->getFormat(textureTarget, level);
@@ -108,7 +133,7 @@
     }
     else if (IsRenderbufferTarget(target))
     {
-        gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mSource.get());
+        gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mState.source.get());
         mFormat                        = renderbuffer->getFormat();
         mWidth                         = renderbuffer->getWidth();
         mHeight                        = renderbuffer->getHeight();
@@ -126,39 +151,38 @@
 
     // All targets should hold a ref to the egl image and it should not be deleted until there are
     // no siblings left.
-    ASSERT(mTargets.empty());
+    ASSERT(mState.targets.empty());
 
     // Tell the source that it is no longer used by this image
-    if (mSource.get() != nullptr)
+    if (mState.source.get() != nullptr)
     {
-        mSource->removeImageSource(this);
-        mSource.set(nullptr);
+        mState.source->removeImageSource(this);
+        mState.source.set(nullptr);
     }
 }
 
 void Image::addTargetSibling(ImageSibling *sibling)
 {
-    mTargets.insert(sibling);
+    mState.targets.insert(sibling);
 }
 
 gl::Error Image::orphanSibling(ImageSibling *sibling)
 {
     // notify impl
-    gl::Error error = mImplementation->orphan(sibling);
+    ANGLE_TRY(mImplementation->orphan(sibling));
 
-    if (mSource.get() == sibling)
+    if (mState.source.get() == sibling)
     {
         // If the sibling is the source, it cannot be a target.
-        ASSERT(mTargets.find(sibling) == mTargets.end());
-
-        mSource.set(nullptr);
+        ASSERT(mState.targets.find(sibling) == mState.targets.end());
+        mState.source.set(nullptr);
     }
     else
     {
-        mTargets.erase(sibling);
+        mState.targets.erase(sibling);
     }
 
-    return error;
+    return gl::NoError();
 }
 
 const gl::Format &Image::getFormat() const
@@ -181,13 +205,14 @@
     return mSamples;
 }
 
-rx::ImageImpl *Image::getImplementation()
+rx::ImageImpl *Image::getImplementation() const
 {
     return mImplementation;
 }
 
-const rx::ImageImpl *Image::getImplementation() const
+Error Image::initialize()
 {
-    return mImplementation;
+    return mImplementation->initialize();
 }
+
 }  // namespace egl