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

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

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(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(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
    : label(nullptr),
      target(target),
      imageIndex(GetImageIndex(target, attribs)),
      source(buffer),
      targets(),
      format(GL_NONE),
      yuv(false),
      cubeMap(false),
      size(),
      samples(),
      levelCount(1),
      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 orphaned.
        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(GL_NONE, 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;
}

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

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

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

    if (!IsExternalImageTarget(mState.sourceType))
    {
        // 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);
    mState.samples = mState.source->getAttachmentSamples(mState.imageIndex);

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

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

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

    return mState.source->setInitState(GL_NONE, 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
