| // | |
| // 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 |