diff options
Diffstat (limited to 'gfx/angle/src/libANGLE/Image.cpp')
-rwxr-xr-x | gfx/angle/src/libANGLE/Image.cpp | 193 |
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 |