//
// Copyright 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::OwnerImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
{
    if (!IsTextureTarget(eglTarget))
    {
        return gl::OwnerImageIndex::MakeInvalid();
    }

    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::OwnerImageIndex::Make3D(gl::OwnerLevel(mip), gl::OwnerLayer(layer));
    }
    else if (gl::IsCubeMapFaceTarget(target))
    {
        return gl::OwnerImageIndex::MakeCubeMapFace(target, gl::OwnerLevel(mip));
    }
    else
    {
        ASSERT(layer == 0);
        return gl::OwnerImageIndex::MakeFromTarget(target, gl::OwnerLevel(mip), 1);
    }
}

const Display *DisplayFromContext(const gl::Context *context)
{
    return (context ? context->getDisplay() : nullptr);
}

angle::SubjectIndex kExternalImageImplSubjectIndex = 0;
}  // anonymous namespace

gl::OwnerImageIndex ImageSourceAttributes::toOwnerIndex(const gl::ImageIndex &ownIndex) const
{
    // If this is not an EGL image target, the offsets are 0 and image index is unchanged.
    if (type == gl::TextureType::InvalidEnum)
    {
        ASSERT(level == 0 && zoffset == 0);
        return gl::OwnerImageIndex(ownIndex);
    }

    // If this is an EGL image target, it must be a renderbuffer or 2D texture, in which case it's
    // level and layer are both 0.
    ASSERT((!ownIndex.hasLayer() || ownIndex.getLayerIndex() == 0) &&
           ownIndex.getLevelIndex() == 0);
    return gl::OwnerImageIndex(gl::ImageIndex::MakeFromType(type, level, zoffset));
}

gl::OwnerLevel ImageSourceAttributes::toOwnerLevel(gl::LevelIndex ownLevel) const
{
    // Either this is not an EGL image target, in which case the offset is 0, or it is and the
    // texture level is 0 (because EGL image target textures can only have one level).
    ASSERT(ownLevel.get() == 0 || level == 0);
    return gl::OwnerLevel(ownLevel.get() + level);
}

gl::OwnerLayer ImageSourceAttributes::toOwnerLayer(gl::LayerIndex ownLayer) const
{
    // Either this is not an EGL image target, in which case the offset is 0, or it is and the
    // texture layer is 0 (because EGL image target textures can only have one layer).
    ASSERT(ownLayer.get() == 0 || zoffset == 0);
    return gl::OwnerLayer(ownLayer.get() + zoffset);
}

gl::OwnerLayer ImageSourceAttributes::toOwnerDepth(const gl::Offset &offset) const
{
    // zoffset only applies to 3D textures
    return type == gl::TextureType::_3D ? toOwnerLayer(gl::LayerIndex(offset.z))
                                        : gl::OwnerLayer(offset.z);
}

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,
                                  ImageSourceAttributes *attributesOut)
{
    ASSERT(imageTarget != nullptr);
    mTargetOf.set(DisplayFromContext(context), imageTarget);
    imageTarget->addTargetSibling(this);

    attributesOut->type    = imageTarget->getSourceImageIndex().getType();
    attributesOut->level   = imageTarget->getSourceImageIndex().getLevelIndex().get();
    attributesOut->zoffset = imageTarget->getSourceImageIndex().hasLayer()
                                 ? imageTarget->getSourceImageIndex().getLayerIndex().get()
                                 : 0;
}

angle::Result ImageSibling::orphanImages(const gl::Context *context,
                                         RefCountObjectReleaser<Image> *outReleaseImage)
{
    ASSERT(outReleaseImage != nullptr);

    angle::ResultAccumulator result = angle::Result::Continue;

    if (mTargetOf.get() != nullptr)
    {
        // Can't be a target and have sources.
        ASSERT(mSourcesOf.empty());

        result           = mTargetOf->orphanSibling(context, this);
        *outReleaseImage = mTargetOf.set(DisplayFromContext(context), nullptr);
    }
    else
    {
        for (Image *sourceImage : mSourcesOf)
        {
            result = sourceImage->orphanSibling(context, this);
        }
        mSourcesOf.clear();
    }

    return result;
}

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);
}

angle::Result ImageSibling::ensureSizeResolved(const gl::Context *context) const
{
    return angle::Result::Continue;
}

bool ImageSibling::isAttachmentSpecified(const gl::ImageIndex &imageIndex) const
{
    return !getAttachmentSize(imageIndex).empty();
}

bool ImageSibling::isRenderable(const gl::Context *context,
                                GLenum binding,
                                const gl::ImageIndex &imageIndex) const
{
    ASSERT(isEGLImageTarget());
    return mTargetOf->isRenderable(context);
}

bool ImageSibling::isYUV() const
{
    return mTargetOf.get() && mTargetOf->isYUV();
}

bool ImageSibling::isExternalImageWithoutIndividualSync() const
{
    return mTargetOf.get() && mTargetOf->isExternalImageWithoutIndividualSync();
}

bool ImageSibling::hasFrontBufferUsage() const
{
    return mTargetOf.get() && mTargetOf->hasFrontBufferUsage();
}

bool ImageSibling::hasProtectedContent() const
{
    return mTargetOf.get() && mTargetOf->hasProtectedContent();
}

void ImageSibling::notifySiblings(angle::SubjectMessage message)
{
    if (mTargetOf.get())
    {
        mTargetOf->notifySiblings(this, message);
    }
    for (Image *source : mSourcesOf)
    {
        source->notifySiblings(this, message);
    }
}

ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
                                           const gl::Context *context,
                                           EGLenum target,
                                           EGLClientBuffer buffer,
                                           const AttributeMap &attribs)
    : mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs)),
      mImplObserverBinding(this, kExternalImageImplSubjectIndex)
{
    mImplObserverBinding.bind(mImplementation.get());
}

ExternalImageSibling::~ExternalImageSibling() = default;

void ExternalImageSibling::onDestroy(const egl::Display *display)
{
    mImplementation->onDestroy(display);
}

Error ExternalImageSibling::initialize(const egl::Display *display, const gl::Context *context)
{
    return mImplementation->initialize(display);
}

gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
{
    return mImplementation->getSize();
}

gl::Format ExternalImageSibling::getAttachmentFormat(GLenum binding,
                                                     const gl::ImageIndex &imageIndex) const
{
    return mImplementation->getFormat();
}

GLsizei ExternalImageSibling::getAttachmentSamples(const gl::ImageIndex &imageIndex) const
{
    return static_cast<GLsizei>(mImplementation->getSamples());
}

GLuint ExternalImageSibling::getLevelCount() const
{
    return static_cast<GLuint>(mImplementation->getLevelCount());
}

bool ExternalImageSibling::isRenderable(const gl::Context *context,
                                        GLenum binding,
                                        const gl::ImageIndex &imageIndex) const
{
    return mImplementation->isRenderable(context);
}

bool ExternalImageSibling::isTextureable(const gl::Context *context) const
{
    return mImplementation->isTexturable(context);
}

bool ExternalImageSibling::isYUV() const
{
    return mImplementation->isYUV();
}

bool ExternalImageSibling::hasFrontBufferUsage() const
{
    return mImplementation->hasFrontBufferUsage();
}

bool ExternalImageSibling::isCubeMap() const
{
    return mImplementation->isCubeMap();
}

bool ExternalImageSibling::hasProtectedContent() const
{
    return mImplementation->hasProtectedContent();
}

void ExternalImageSibling::onAttach(const gl::Context *context, rx::UniqueSerial framebufferSerial)
{}

void ExternalImageSibling::onDetach(const gl::Context *context, rx::UniqueSerial framebufferSerial)
{}

GLuint ExternalImageSibling::getId() const
{
    UNREACHABLE();
    return 0;
}

gl::InitState ExternalImageSibling::initState(GLenum binding,
                                              const gl::ImageIndex &imageIndex) const
{
    return gl::InitState::Initialized;
}

void ExternalImageSibling::setInitState(GLenum binding,
                                        const gl::ImageIndex &imageIndex,
                                        gl::InitState initState)
{}

rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
{
    return mImplementation.get();
}

void ExternalImageSibling::onSubjectStateChange(angle::SubjectIndex index,
                                                angle::SubjectMessage message)
{
    onStateChange(message);
}

rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
{
    return mImplementation.get();
}

ImageState::ImageState(ImageID id,
                       EGLenum target,
                       ImageSibling *buffer,
                       const AttributeMap &attribs)
    : id(id),
      label(nullptr),
      target(target),
      imageIndex(GetImageIndex(target, attribs)),
      source(buffer),
      format(GL_NONE),
      yuv(false),
      cubeMap(false),
      size(),
      samples(),
      levelCount(1),
      colorspace(
          static_cast<EGLenum>(attribs.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_DEFAULT_EXT))),
      hasProtectedContent(static_cast<bool>(attribs.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE)))
{}

ImageState::~ImageState() {}

Image::Image(rx::EGLImplFactory *factory,
             ImageID id,
             const gl::Context *context,
             EGLenum target,
             ImageSibling *buffer,
             const AttributeMap &attribs)
    : mState(id, target, buffer, attribs),
      mImplementation(factory->createImage(mState, context, target, attribs)),
      mOrphanedAndNeedsInit(false),
      mContextMutex(nullptr)
{
    ASSERT(mImplementation != nullptr);
    ASSERT(buffer != nullptr);

    if (kIsContextMutexEnabled)
    {
        if (context != nullptr)
        {
            mContextMutex = context->getContextMutex().getRoot();
            ASSERT(mContextMutex->isReferenced());
        }
        else
        {
            mContextMutex = new ContextMutex();
        }
        mContextMutex->addRef();
    }

    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([&] {
        std::unique_lock lock(mState.targetsLock);
        return mState.targets.empty();
    }());

    // Make sure the implementation gets a chance to clean up before we delete the source.
    mImplementation->onDestroy(display);

    // Tell the source that it is no longer used by this image
    if (mState.source != nullptr)
    {
        mState.source->removeImageSource(this);

        // If the source is an external object, delete it
        if (IsExternalImageTarget(mState.target))
        {
            ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
            externalSibling->onDestroy(display);
            delete externalSibling;
        }

        mState.source = nullptr;
    }
}

Image::~Image()
{
    SafeDelete(mImplementation);

    if (mContextMutex != nullptr)
    {
        mContextMutex->release();
        mContextMutex = nullptr;
    }
}

void Image::setLabel(EGLLabelKHR label)
{
    mState.label = label;
}

EGLLabelKHR Image::getLabel() const
{
    return mState.label;
}

void Image::addTargetSibling(ImageSibling *sibling)
{
    std::unique_lock lock(mState.targetsLock);
    mState.targets.insert(sibling);
}

angle::Result Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
{
    ASSERT(sibling != nullptr);

    angle::Result result = mImplementation->orphan(context, sibling);

    if (mState.source == sibling)
    {
        // The external source of an image cannot be redefined so it cannot be orphaned.
        ASSERT(!IsExternalImageTarget(mState.target));

        // If the sibling is the source, it cannot be a target.
        ASSERT([&] {
            std::unique_lock lock(mState.targetsLock);
            return mState.targets.find(sibling) == mState.targets.end();
        }());
        mState.source = nullptr;
        mOrphanedAndNeedsInit =
            (sibling->initState(GL_NONE, mState.imageIndex.get()) == gl::InitState::MayNeedInit);
    }
    else
    {
        std::unique_lock lock(mState.targetsLock);
        mState.targets.erase(sibling);
    }

    return result;
}

const gl::Format &Image::getFormat() const
{
    return mState.format;
}

bool Image::isRenderable(const gl::Context *context) const
{
    return mIsRenderable;
}

bool Image::isTexturable(const gl::Context *context) const
{
    return mIsTexturable;
}

bool Image::isYUV() const
{
    return mState.yuv;
}

bool Image::isExternalImageWithoutIndividualSync() const
{
    // Only Vulkan images are individually synced.
    return IsExternalImageTarget(mState.target) && mState.target != EGL_VULKAN_IMAGE_ANGLE;
}

bool Image::hasFrontBufferUsage() const
{
    if (IsExternalImageTarget(mState.target))
    {
        ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
        return externalSibling->hasFrontBufferUsage();
    }

    return false;
}

bool Image::isCubeMap() const
{
    return mState.cubeMap;
}

size_t Image::getWidth() const
{
    return mState.size.width;
}

size_t Image::getHeight() const
{
    return mState.size.height;
}

const gl::Extents &Image::getExtents() const
{
    return mState.size;
}

bool Image::isLayered() const
{
    return mState.imageIndex.isLayered();
}

size_t Image::getSamples() const
{
    return mState.samples;
}

GLuint Image::getLevelCount() const
{
    return mState.levelCount;
}

bool Image::hasProtectedContent() const
{
    return mState.hasProtectedContent;
}

bool Image::isFixedRatedCompression(const gl::Context *context) const
{
    return mImplementation->isFixedRatedCompression(context);
}

rx::ImageImpl *Image::getImplementation() const
{
    return mImplementation;
}

Error Image::initialize(const Display *display, const gl::Context *context)
{
    if (IsExternalImageTarget(mState.target))
    {
        ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
        ANGLE_TRY(externalSibling->initialize(display, context));

        mState.hasProtectedContent = externalSibling->hasProtectedContent();
        mState.levelCount          = externalSibling->getLevelCount();
        mState.cubeMap             = externalSibling->isCubeMap();

        // External siblings can be YUV
        mState.yuv = externalSibling->isYUV();
    }

    mState.format = mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex.get());

    if (mState.colorspace != EGL_GL_COLORSPACE_DEFAULT_EXT)
    {
        GLenum nonLinearFormat = mState.format.info->sizedInternalFormat;
        if (!gl::ColorspaceFormatOverride(mState.colorspace, &nonLinearFormat))
        {
            // the colorspace format is not supported
            return egl::Error(EGL_BAD_MATCH);
        }
        mState.format = gl::Format(nonLinearFormat);
    }

    if (!IsExternalImageTarget(mState.target))
    {
        // Account for the fact that GL_ANGLE_yuv_internal_format extension maybe enabled,
        // in which case the internal format itself could be YUV.
        mState.yuv = gl::IsYuvFormat(mState.format.info->sizedInternalFormat);
    }

    mState.size    = mState.source->getAttachmentSize(mState.imageIndex.get());
    mState.samples = mState.source->getAttachmentSamples(mState.imageIndex.get());

    if (IsTextureTarget(mState.target))
    {
        mState.size.depth = 1;
    }

    Error error = mImplementation->initialize(display);
    if (error.isError())
    {
        return error;
    }

    if (IsTextureTarget(mState.target))
    {
        mIsTexturable = true;
        mIsRenderable = mState.format.info->textureAttachmentSupport(context->getClientVersion(),
                                                                     context->getExtensions());
    }
    else if (IsRenderbufferTarget(mState.target))
    {
        mIsTexturable = true;
        mIsRenderable = mState.format.info->renderbufferSupport(context->getClientVersion(),
                                                                context->getExtensions());
    }
    else if (IsExternalImageTarget(mState.target))
    {
        ASSERT(mState.source != nullptr);
        mIsTexturable = rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
        mIsRenderable = rx::GetAs<ExternalImageSibling>(mState.source)
                            ->isRenderable(context, GL_NONE, gl::ImageIndex());
    }
    else
    {
        UNREACHABLE();
    }

    return NoError();
}

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(GL_NONE, mState.imageIndex.get());
}

void Image::setInitState(gl::InitState initState)
{
    if (orphaned())
    {
        mOrphanedAndNeedsInit = false;
    }

    return mState.source->setInitState(GL_NONE, mState.imageIndex.get(), initState);
}

Error Image::exportVkImage(void *vkImage, void *vkImageCreateInfo)
{
    return mImplementation->exportVkImage(vkImage, vkImageCreateInfo);
}

void Image::notifySiblings(const ImageSibling *notifier, angle::SubjectMessage message)
{
    if (mState.source && mState.source != notifier)
    {
        mState.source->onSubjectStateChange(rx::kTextureImageSiblingMessageIndex, message);
    }

    std::unique_lock lock(mState.targetsLock);
    for (ImageSibling *target : mState.targets)
    {
        if (target != notifier)
        {
            target->onSubjectStateChange(rx::kTextureImageSiblingMessageIndex, message);
        }
    }
}

}  // namespace egl
