//
// Copyright 2002 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.
//

// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class,
// GL renderbuffer objects and related functionality.
// [OpenGL ES 2.0.24] section 4.4.3 page 108.

#include "libANGLE/Renderbuffer.h"

#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Image.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/GLImplFactory.h"

namespace gl
{
namespace
{
angle::SubjectIndex kRenderbufferImplSubjectIndex = 0;

InitState DetermineInitState(const Context *context)
{
    return (context && context->isRobustResourceInitEnabled()) ? InitState::MayNeedInit
                                                               : InitState::Initialized;
}
}  // namespace

// RenderbufferState implementation.
RenderbufferState::RenderbufferState()
    : mWidth(0),
      mHeight(0),
      mFormat(GL_NONE),
      mSamples(0),
      mMultisamplingMode(MultisamplingMode::Regular),
      mHasProtectedContent(false),
      mInitState(InitState::Initialized)
{}

RenderbufferState::~RenderbufferState() {}

GLsizei RenderbufferState::getWidth() const
{
    return mWidth;
}

GLsizei RenderbufferState::getHeight() const
{
    return mHeight;
}

const Format &RenderbufferState::getFormat() const
{
    return mFormat;
}

GLsizei RenderbufferState::getSamples() const
{
    return mSamples;
}

MultisamplingMode RenderbufferState::getMultisamplingMode() const
{
    return mMultisamplingMode;
}

InitState RenderbufferState::getInitState() const
{
    return mInitState;
}

void RenderbufferState::update(GLsizei width,
                               GLsizei height,
                               const Format &format,
                               GLsizei samples,
                               MultisamplingMode multisamplingMode,
                               InitState initState)
{
    mWidth               = width;
    mHeight              = height;
    mFormat              = format;
    mSamples             = samples;
    mMultisamplingMode   = multisamplingMode;
    mInitState           = initState;
    mHasProtectedContent = false;
}

void RenderbufferState::setProtectedContent(bool hasProtectedContent)
{
    mHasProtectedContent = hasProtectedContent;
}

// Renderbuffer implementation.
Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
    : RefCountObject(implFactory->generateSerial(), id),
      mState(),
      mImplementation(implFactory->createRenderbuffer(mState)),
      mLabel(),
      mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
{
    mImplObserverBinding.bind(mImplementation.get());
}

void Renderbuffer::onDestroy(const Context *context)
{
    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    (void)orphanImages(context, &releaseImage);

    if (context && context->retainIdUntilObjectDestroyed())
    {
        context->onRenderbufferDestroy(this);
    }

    if (mImplementation)
    {
        mImplementation->onDestroy(context);
    }
}

Renderbuffer::~Renderbuffer() {}

angle::Result Renderbuffer::setLabel(const Context *context, const std::string &label)
{
    mLabel = label;

    if (mImplementation)
    {
        return mImplementation->onLabelUpdate(context);
    }
    return angle::Result::Continue;
}

const std::string &Renderbuffer::getLabel() const
{
    return mLabel;
}

angle::Result Renderbuffer::setStorage(const Context *context,
                                       GLenum internalformat,
                                       GLsizei width,
                                       GLsizei height)
{

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));

    mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
                  DetermineInitState(context));
    onStateChange(angle::SubjectMessage::SubjectChanged);

    return angle::Result::Continue;
}

angle::Result Renderbuffer::setStorageMultisample(const Context *context,
                                                  GLsizei samplesIn,
                                                  GLenum internalformat,
                                                  GLsizei width,
                                                  GLsizei height,
                                                  MultisamplingMode mode)
{
    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    // Potentially adjust "samplesIn" to a supported value
    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
    GLsizei samples               = formatCaps.sampleCounts.getNearestSamples(samplesIn);

    ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
                                                     height, mode));

    mState.update(width, height, Format(internalformat), samples, mode,
                  DetermineInitState(context));
    onStateChange(angle::SubjectMessage::SubjectChanged);

    return angle::Result::Continue;
}

angle::Result Renderbuffer::orphanImages(const gl::Context *context,
                                         egl::RefCountObjectReleaser<egl::Image> *outReleaseImage)
{
    ANGLE_TRY(ImageSibling::orphanImages(context, outReleaseImage));
    mState.mEGLImageSourceAttributes = egl::ImageSourceAttributes{};
    return angle::Result::Continue;
}

angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
{
    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));

    setTargetImage(context, image, &mState.mEGLImageSourceAttributes);

    mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
                  Format(image->getFormat()), 0, MultisamplingMode::Regular,
                  image->sourceInitState());
    mState.setProtectedContent(image->hasProtectedContent());

    onStateChange(angle::SubjectMessage::SubjectChanged);

    return angle::Result::Continue;
}

angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
                                                    const gl::Renderbuffer *srcBuffer,
                                                    GLint srcX,
                                                    GLint srcY,
                                                    GLint dstX,
                                                    GLint dstY,
                                                    GLsizei srcWidth,
                                                    GLsizei srcHeight)
{
    ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcX, srcY, dstX, dstY,
                                                       srcWidth, srcHeight));

    return angle::Result::Continue;
}

angle::Result Renderbuffer::copyTextureSubData(Context *context,
                                               const gl::Texture *srcTexture,
                                               GLint srcLevel,
                                               GLint srcX,
                                               GLint srcY,
                                               GLint srcZ,
                                               GLint dstX,
                                               GLint dstY,
                                               GLsizei srcWidth,
                                               GLsizei srcHeight)
{
    ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, LevelIndex(srcLevel), srcX,
                                                  srcY, LayerIndex(srcZ), dstX, dstY, srcWidth,
                                                  srcHeight));

    return angle::Result::Continue;
}

rx::RenderbufferImpl *Renderbuffer::getImplementation() const
{
    ASSERT(mImplementation);
    return mImplementation.get();
}

GLsizei Renderbuffer::getWidth() const
{
    return mState.mWidth;
}

GLsizei Renderbuffer::getHeight() const
{
    return mState.mHeight;
}

const Format &Renderbuffer::getFormat() const
{
    return mState.mFormat;
}

GLsizei Renderbuffer::getSamples() const
{
    return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
}

MultisamplingMode Renderbuffer::getMultisamplingMode() const
{
    return mState.mMultisamplingMode;
}

GLuint Renderbuffer::getRedSize() const
{
    return mState.mFormat.info->redBits;
}

GLuint Renderbuffer::getGreenSize() const
{
    return mState.mFormat.info->greenBits;
}

GLuint Renderbuffer::getBlueSize() const
{
    return mState.mFormat.info->blueBits;
}

GLuint Renderbuffer::getAlphaSize() const
{
    return mState.mFormat.info->alphaBits;
}

GLuint Renderbuffer::getDepthSize() const
{
    return mState.mFormat.info->depthBits;
}

GLuint Renderbuffer::getStencilSize() const
{
    return mState.mFormat.info->stencilBits;
}

const RenderbufferState &Renderbuffer::getState() const
{
    return mState;
}

GLint Renderbuffer::getMemorySize() const
{
    GLint implSize = mImplementation->getMemorySize();
    if (implSize > 0)
    {
        return implSize;
    }

    // Assume allocated size is around width * height * samples * pixelBytes
    angle::CheckedNumeric<GLint> size = 1;
    size *= mState.mFormat.info->pixelBytes;
    size *= mState.mWidth;
    size *= mState.mHeight;
    size *= std::max(mState.mSamples, 1);
    return size.ValueOrDefault(std::numeric_limits<GLint>::max());
}

void Renderbuffer::onAttach(const Context *context, rx::UniqueSerial framebufferSerial)
{
    addRef();
}

void Renderbuffer::onDetach(const Context *context, rx::UniqueSerial framebufferSerial)
{
    release(context);
}

GLuint Renderbuffer::getId() const
{
    return id().value;
}

Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
{
    return Extents(mState.mWidth, mState.mHeight, 1);
}

Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
                                         const ImageIndex & /*imageIndex*/) const
{
    return getFormat();
}
GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
{
    return getSamples();
}

bool Renderbuffer::isRenderable(const Context *context,
                                GLenum binding,
                                const ImageIndex &imageIndex) const
{
    if (isEGLImageTarget())
    {
        return ImageSibling::isRenderable(context, binding, imageIndex);
    }
    return getFormat().info->renderbufferSupport(context->getClientVersion(),
                                                 context->getExtensions());
}

bool Renderbuffer::isEGLImageSource() const
{
    return !getSiblingSourcesOf().empty();
}

InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const
{
    if (isEGLImageTarget())
    {
        return sourceEGLImageInitState();
    }

    return mState.mInitState;
}

void Renderbuffer::setInitState(GLenum /*binding*/,
                                const gl::ImageIndex & /*imageIndex*/,
                                InitState initState)
{
    if (isEGLImageTarget())
    {
        setSourceEGLImageInitState(initState);
    }
    else
    {
        mState.mInitState = initState;
    }
}

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

GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
{
    return mImplementation->getColorReadFormat(context);
}

GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
{
    return mImplementation->getColorReadType(context);
}

angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
                                                 const PixelPackState &packState,
                                                 Buffer *packBuffer,
                                                 GLenum format,
                                                 GLenum type,
                                                 void *pixels) const
{
    return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
                                                 pixels);
}

void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    if (message == angle::SubjectMessage::ObjectReallocated)
    {
        onStateChange(angle::SubjectMessage::ObjectReallocated);
        return;
    }
    ASSERT(message == angle::SubjectMessage::SubjectChanged);
    onStateChange(angle::SubjectMessage::ContentsChanged);
}
}  // namespace gl
