summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/Image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/libANGLE/Image.cpp')
-rwxr-xr-xgfx/angle/src/libANGLE/Image.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/Image.cpp b/gfx/angle/src/libANGLE/Image.cpp
new file mode 100755
index 000000000..828f86238
--- /dev/null
+++ b/gfx/angle/src/libANGLE/Image.cpp
@@ -0,0 +1,193 @@
+//
+// Copyright (c) 2015 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.
+//
+
+// Image.cpp: Implements the egl::Image class representing the EGLimage object.
+
+#include "libANGLE/Image.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace egl
+{
+ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), mSourcesOf(), mTargetOf()
+{
+}
+
+ImageSibling::~ImageSibling()
+{
+ // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
+ // while it is attached to an EGL image.
+ ASSERT(mSourcesOf.empty());
+ orphanImages();
+}
+
+void ImageSibling::setTargetImage(egl::Image *imageTarget)
+{
+ ASSERT(imageTarget != nullptr);
+ mTargetOf.set(imageTarget);
+ imageTarget->addTargetSibling(this);
+}
+
+gl::Error ImageSibling::orphanImages()
+{
+ if (mTargetOf.get() != nullptr)
+ {
+ // Can't be a target and have sources.
+ ASSERT(mSourcesOf.empty());
+
+ gl::Error error = mTargetOf->orphanSibling(this);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mTargetOf.set(nullptr);
+ }
+ else
+ {
+ for (auto &sourceImage : mSourcesOf)
+ {
+ gl::Error error = sourceImage->orphanSibling(this);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ mSourcesOf.clear();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void ImageSibling::addImageSource(egl::Image *imageSource)
+{
+ ASSERT(imageSource != nullptr);
+ mSourcesOf.insert(imageSource);
+}
+
+void ImageSibling::removeImageSource(egl::Image *imageSource)
+{
+ ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
+ mSourcesOf.erase(imageSource);
+}
+
+Image::Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+ : RefCountObject(0),
+ mImplementation(impl),
+ mFormat(gl::Format::Invalid()),
+ mWidth(0),
+ mHeight(0),
+ mSamples(0),
+ mSource(),
+ mTargets()
+{
+ ASSERT(mImplementation != nullptr);
+ ASSERT(buffer != nullptr);
+
+ mSource.set(buffer);
+ mSource->addImageSource(this);
+
+ if (IsTextureTarget(target))
+ {
+ gl::Texture *texture = rx::GetAs<gl::Texture>(mSource.get());
+ GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target);
+ size_t level = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ mFormat = texture->getFormat(textureTarget, level);
+ mWidth = texture->getWidth(textureTarget, level);
+ mHeight = texture->getHeight(textureTarget, level);
+ mSamples = 0;
+ }
+ else if (IsRenderbufferTarget(target))
+ {
+ gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mSource.get());
+ mFormat = renderbuffer->getFormat();
+ mWidth = renderbuffer->getWidth();
+ mHeight = renderbuffer->getHeight();
+ mSamples = renderbuffer->getSamples();
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+Image::~Image()
+{
+ SafeDelete(mImplementation);
+
+ // 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());
+
+ // Tell the source that it is no longer used by this image
+ if (mSource.get() != nullptr)
+ {
+ mSource->removeImageSource(this);
+ mSource.set(nullptr);
+ }
+}
+
+void Image::addTargetSibling(ImageSibling *sibling)
+{
+ mTargets.insert(sibling);
+}
+
+gl::Error Image::orphanSibling(ImageSibling *sibling)
+{
+ // notify impl
+ gl::Error error = mImplementation->orphan(sibling);
+
+ if (mSource.get() == sibling)
+ {
+ // If the sibling is the source, it cannot be a target.
+ ASSERT(mTargets.find(sibling) == mTargets.end());
+
+ mSource.set(nullptr);
+ }
+ else
+ {
+ mTargets.erase(sibling);
+ }
+
+ return error;
+}
+
+const gl::Format &Image::getFormat() const
+{
+ return mFormat;
+}
+
+size_t Image::getWidth() const
+{
+ return mWidth;
+}
+
+size_t Image::getHeight() const
+{
+ return mHeight;
+}
+
+size_t Image::getSamples() const
+{
+ return mSamples;
+}
+
+rx::ImageImpl *Image::getImplementation()
+{
+ return mImplementation;
+}
+
+const rx::ImageImpl *Image::getImplementation() const
+{
+ return mImplementation;
+}
+} // namespace egl