Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2016-07-22 22:13:26
    Hash : a3944d4f
    Message : Add gl::Format to represent a texture/rb/surface format. This has a few advantages: it preserves all the information of the internal format, such as if it is sized or unsized. It also saves looking up the format multiple times in the table, which should improve speed in some cases. The extra sized-ness information will allow us to perform the correct validation in CopyTexSubImage calls. BUG=angleproject:1228 Change-Id: I42954771b0a9a968f5d787b8cf6e0af721791855 Reviewed-on: https://chromium-review.googlesource.com/362626 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/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