//
// 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::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
{
    if (!IsTextureTarget(eglTarget))
    {
        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, 1);
    }
}

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

angle::SubjectIndex kExternalImageImplSubjectIndex = 0;
}  // 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);
}

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

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

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

    return angle::Result::Continue;
}

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

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

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

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::hasProtectedContent() const
{
    return mImplementation->hasProtectedContent();
}

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

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

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

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

void ExternalImageSibling::setInitState(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(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
    : label(nullptr),
      target(target),
      imageIndex(GetImageIndex(target, attribs)),
      source(buffer),
      targets(),
      format(GL_NONE),
      yuv(false),
      size(),
      samples(),
      sourceType(target),
      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,
             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());

    // 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.sourceType))
        {
            ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
            externalSibling->onDestroy(display);
            delete externalSibling;
        }

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

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

    // notify impl
    ANGLE_TRY(mImplementation->orphan(context, sibling));

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

        // 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 angle::Result::Continue;
}

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());
    }
    else if (IsRenderbufferTarget(mState.sourceType))
    {
        return mState.format.info->renderbufferSupport(context->getClientVersion(),
                                                       context->getExtensions());
    }
    else if (IsExternalImageTarget(mState.sourceType))
    {
        ASSERT(mState.source != nullptr);
        return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
    }

    UNREACHABLE();
    return false;
}

bool Image::isTexturable(const gl::Context *context) const
{
    if (IsTextureTarget(mState.sourceType))
    {
        return mState.format.info->textureSupport(context->getClientVersion(),
                                                  context->getExtensions());
    }
    else if (IsRenderbufferTarget(mState.sourceType))
    {
        return true;
    }
    else if (IsExternalImageTarget(mState.sourceType))
    {
        ASSERT(mState.source != nullptr);
        return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
    }

    UNREACHABLE();
    return false;
}

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

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

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

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

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

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

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

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

        mState.hasProtectedContent = externalSibling->hasProtectedContent();

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

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

    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::EglBadMatch();
        }
        mState.format = gl::Format(nonLinearFormat);
    }

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

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

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

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

}  // namespace egl
