Edit

kc3-lang/angle/src/libANGLE/Image.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2018-10-10 16:13:02
    Hash : 1c7f08c3
    Message : Inline RefCountObject::release. Also don't return errors from the object release methods. Not returning errors reduces the amount of code generated. Also we shouldn't be exiting early from destructor type functions. Increases object binding performance. Bug: angleproject:2877 Change-Id: Ieb8120d885b946915e355419825e1f52f31d7b49 Reviewed-on: https://chromium-review.googlesource.com/c/1270218 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/Image.cpp
  • //
    // 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/Context.h"
    #include "libANGLE/Renderbuffer.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/angletypes.h"
    #include "libANGLE/formatutils.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();
        }
    
        gl::TextureTarget target = egl_gl::EGLImageTargetToTextureTarget(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::TextureTarget::_3D)
        {
            return gl::ImageIndex::Make3D(mip, layer);
        }
        else
        {
            ASSERT(layer == 0);
            return gl::ImageIndex::MakeFromTarget(target, mip);
        }
    }
    
    const Display *DisplayFromContext(const gl::Context *context)
    {
        return (context ? context->getCurrentDisplay() : nullptr);
    }
    
    }  // anonymous namespace
    
    ImageSibling::ImageSibling() : FramebufferAttachmentObject(), 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.
        // Child class should orphan images before destruction.
        ASSERT(mSourcesOf.empty());
        ASSERT(mTargetOf.get() == nullptr);
    }
    
    void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
    {
        ASSERT(imageTarget != nullptr);
        mTargetOf.set(DisplayFromContext(context), imageTarget);
        imageTarget->addTargetSibling(this);
    }
    
    gl::Error ImageSibling::orphanImages(const gl::Context *context)
    {
        if (mTargetOf.get() != nullptr)
        {
            // Can't be a target and have sources.
            ASSERT(mSourcesOf.empty());
    
            ANGLE_TRY(mTargetOf->orphanSibling(context, this));
            mTargetOf.set(DisplayFromContext(context), nullptr);
        }
        else
        {
            for (Image *sourceImage : mSourcesOf)
            {
                ANGLE_TRY(sourceImage->orphanSibling(context, this));
            }
            mSourcesOf.clear();
        }
    
        return gl::NoError();
    }
    
    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);
    }
    
    bool ImageSibling::isEGLImageTarget() const
    {
        return (mTargetOf.get() != nullptr);
    }
    
    gl::InitState ImageSibling::sourceEGLImageInitState() const
    {
        ASSERT(isEGLImageTarget());
        return mTargetOf->sourceInitState();
    }
    
    void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
    {
        ASSERT(isEGLImageTarget());
        mTargetOf->setInitState(initState);
    }
    
    bool ImageSibling::isRenderable(const gl::Context *context,
                                    GLenum binding,
                                    const gl::ImageIndex &imageIndex) const
    {
        ASSERT(isEGLImageTarget());
        return mTargetOf->isRenderable(context);
    }
    
    ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
        : label(nullptr),
          imageIndex(GetImageIndex(target, attribs)),
          source(buffer),
          targets(),
          format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
          size(buffer->getAttachmentSize(imageIndex)),
          samples(buffer->getAttachmentSamples(imageIndex)),
          sourceType(target)
    {
    }
    
    ImageState::~ImageState()
    {
    }
    
    Image::Image(rx::EGLImplFactory *factory,
                 const gl::Context *context,
                 EGLenum target,
                 ImageSibling *buffer,
                 const AttributeMap &attribs)
        : mState(target, buffer, attribs),
          mImplementation(factory->createImage(mState, context, target, attribs)),
          mOrphanedAndNeedsInit(false)
    {
        ASSERT(mImplementation != nullptr);
        ASSERT(buffer != nullptr);
    
        mState.source->addImageSource(this);
    }
    
    void Image::onDestroy(const Display *display)
    {
        // All targets should hold a ref to the egl image and it should not be deleted until there are
        // no siblings left.
        ASSERT(mState.targets.empty());
    
        // Tell the source that it is no longer used by this image
        if (mState.source != nullptr)
        {
            mState.source->removeImageSource(this);
            mState.source = nullptr;
        }
    }
    
    Image::~Image()
    {
        SafeDelete(mImplementation);
    }
    
    void Image::setLabel(EGLLabelKHR label)
    {
        mState.label = label;
    }
    
    EGLLabelKHR Image::getLabel() const
    {
        return mState.label;
    }
    
    void Image::addTargetSibling(ImageSibling *sibling)
    {
        mState.targets.insert(sibling);
    }
    
    gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
    {
        ASSERT(sibling != nullptr);
    
        // notify impl
        ANGLE_TRY(mImplementation->orphan(context, sibling));
    
        if (mState.source == sibling)
        {
            // If the sibling is the source, it cannot be a target.
            ASSERT(mState.targets.find(sibling) == mState.targets.end());
            mState.source = nullptr;
            mOrphanedAndNeedsInit =
                (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
        }
        else
        {
            mState.targets.erase(sibling);
        }
    
        return gl::NoError();
    }
    
    const gl::Format &Image::getFormat() const
    {
        return mState.format;
    }
    
    bool Image::isRenderable(const gl::Context *context) const
    {
        if (IsTextureTarget(mState.sourceType))
        {
            return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
                                                                context->getExtensions());
        }
        if (IsRenderbufferTarget(mState.sourceType))
        {
            return mState.format.info->renderbufferSupport(context->getClientVersion(),
                                                           context->getExtensions());
        }
    
        UNREACHABLE();
        return false;
    }
    
    bool Image::isTexturable(const gl::Context *context) const
    {
        if (IsTextureTarget(mState.sourceType))
        {
            return mState.format.info->textureSupport(context->getClientVersion(),
                                                      context->getExtensions());
        }
        if (IsRenderbufferTarget(mState.sourceType))
        {
            return true;
        }
    
        UNREACHABLE();
        return false;
    }
    
    size_t Image::getWidth() const
    {
        return mState.size.width;
    }
    
    size_t Image::getHeight() const
    {
        return mState.size.height;
    }
    
    size_t Image::getSamples() const
    {
        return mState.samples;
    }
    
    rx::ImageImpl *Image::getImplementation() const
    {
        return mImplementation;
    }
    
    Error Image::initialize(const Display *display)
    {
        return mImplementation->initialize(display);
    }
    
    bool Image::orphaned() const
    {
        return (mState.source == nullptr);
    }
    
    gl::InitState Image::sourceInitState() const
    {
        if (orphaned())
        {
            return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
        }
    
        return mState.source->initState(mState.imageIndex);
    }
    
    void Image::setInitState(gl::InitState initState)
    {
        if (orphaned())
        {
            mOrphanedAndNeedsInit = false;
        }
    
        return mState.source->setInitState(mState.imageIndex, initState);
    }
    
    }  // namespace egl