//
// Copyright 2018 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.
//
// RenderTargetCache:
// The RenderTargetCache pattern is used in the D3D9, D3D11, Vulkan, and WebGPU back-ends. It is a
// cache of the various back-end objects (RenderTargets) associated with each Framebuffer
// attachment, be they Textures, Renderbuffers, or Surfaces. The cache is updated in Framebuffer's
// syncState method.
//

#ifndef LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
#define LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_

#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"

namespace rx
{

template <typename RenderTargetT>
class RenderTargetCache final : angle::NonCopyable
{
  public:
    RenderTargetCache();
    ~RenderTargetCache();

    // Update all RenderTargets from the dirty bits.
    angle::Result update(const gl::Context *context,
                         const gl::FramebufferState &state,
                         const gl::Framebuffer::DirtyBits &dirtyBits);

    // Update individual RenderTargets.
    angle::Result updateReadColorRenderTarget(const gl::Context *context,
                                              const gl::FramebufferState &state);
    // |readColorTargetUpdatedOut| must be initialized to false before a sequence of updates. It is
    // set to true when the read color target is also updated.
    angle::Result updateColorRenderTarget(const gl::Context *context,
                                          const gl::FramebufferState &state,
                                          size_t colorIndex,
                                          bool *readColorTargetUpdatedOut);
    angle::Result updateDepthStencilRenderTarget(const gl::Context *context,
                                                 const gl::FramebufferState &state);

    using RenderTargetArray = gl::AttachmentArray<RenderTargetT *>;

    const RenderTargetArray &getColors() const;
    RenderTargetT *getDepthStencil() const;

    RenderTargetT *getColorDraw(const gl::FramebufferState &state, size_t colorIndex) const;
    RenderTargetT *getColorRead(const gl::FramebufferState &state) const;

  private:
    angle::Result updateCachedRenderTarget(const gl::Context *context,
                                           const gl::FramebufferAttachment *attachment,
                                           RenderTargetT **cachedRenderTarget);

    RenderTargetT *mReadRenderTarget                         = nullptr;
    gl::AttachmentArray<RenderTargetT *> mColorRenderTargets = {};
    // We only support a single Depth/Stencil RenderTarget currently.
    RenderTargetT *mDepthStencilRenderTarget = nullptr;
};

template <typename RenderTargetT>
RenderTargetCache<RenderTargetT>::RenderTargetCache() = default;

template <typename RenderTargetT>
RenderTargetCache<RenderTargetT>::~RenderTargetCache() = default;

template <typename RenderTargetT>
angle::Result RenderTargetCache<RenderTargetT>::update(const gl::Context *context,
                                                       const gl::FramebufferState &state,
                                                       const gl::Framebuffer::DirtyBits &dirtyBits)
{
    for (auto dirtyBit : dirtyBits)
    {
        switch (dirtyBit)
        {
            case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
            case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
                ANGLE_TRY(updateDepthStencilRenderTarget(context, state));
                break;
            case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
                ANGLE_TRY(updateReadColorRenderTarget(context, state));
                break;
            case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
            case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
                break;
            default:
            {
                static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
                if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
                {
                    size_t colorIndex = static_cast<size_t>(
                        dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
                    bool readColorTargetUpdated = false;
                    ANGLE_TRY(updateColorRenderTarget(context, state, colorIndex,
                                                      &readColorTargetUpdated));
                }
                break;
            }
        }
    }

    return angle::Result::Continue;
}

template <typename RenderTargetT>
const gl::AttachmentArray<RenderTargetT *> &RenderTargetCache<RenderTargetT>::getColors() const
{
    return mColorRenderTargets;
}

template <typename RenderTargetT>
RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil() const
{
    return mDepthStencilRenderTarget;
}

template <typename RenderTargetT>
angle::Result RenderTargetCache<RenderTargetT>::updateReadColorRenderTarget(
    const gl::Context *context,
    const gl::FramebufferState &state)
{
    return updateCachedRenderTarget(context, state.getReadAttachment(), &mReadRenderTarget);
}

template <typename RenderTargetT>
angle::Result RenderTargetCache<RenderTargetT>::updateColorRenderTarget(
    const gl::Context *context,
    const gl::FramebufferState &state,
    size_t colorIndex,
    bool *readColorTargetUpdatedOut)
{
    ASSERT(readColorTargetUpdatedOut != nullptr);

    const gl::FramebufferAttachment *colorAttachment = state.getColorAttachment(colorIndex);
    ANGLE_TRY(updateCachedRenderTarget(context, colorAttachment, &mColorRenderTargets[colorIndex]));

    // If the color render target we're updating is also the read buffer, make sure we update the
    // read render target also so it's not stale.
    if (state.getReadBufferState() != GL_NONE && state.getReadIndex() == colorIndex)
    {
        if (colorAttachment == state.getReadAttachment())
        {
            mReadRenderTarget = mColorRenderTargets[colorIndex];
        }
        else
        {
            ANGLE_TRY(updateReadColorRenderTarget(context, state));
        }

        *readColorTargetUpdatedOut = true;
    }

    return angle::Result::Continue;
}

template <typename RenderTargetT>
angle::Result RenderTargetCache<RenderTargetT>::updateDepthStencilRenderTarget(
    const gl::Context *context,
    const gl::FramebufferState &state)
{
    return updateCachedRenderTarget(context, state.getDepthOrStencilAttachment(),
                                    &mDepthStencilRenderTarget);
}

template <typename RenderTargetT>
angle::Result RenderTargetCache<RenderTargetT>::updateCachedRenderTarget(
    const gl::Context *context,
    const gl::FramebufferAttachment *attachment,
    RenderTargetT **cachedRenderTarget)
{
    RenderTargetT *newRenderTarget = nullptr;
    if (attachment)
    {
        ASSERT(attachment->isAttached());
        ANGLE_TRY(attachment->getRenderTarget(context, attachment->getRenderToTextureSamples(),
                                              &newRenderTarget));
    }
    *cachedRenderTarget = newRenderTarget;
    return angle::Result::Continue;
}

template <typename RenderTargetT>
RenderTargetT *RenderTargetCache<RenderTargetT>::getColorDraw(const gl::FramebufferState &state,
                                                              size_t colorIndex) const
{
    return mColorRenderTargets[colorIndex];
}

template <typename RenderTargetT>
RenderTargetT *RenderTargetCache<RenderTargetT>::getColorRead(
    const gl::FramebufferState &state) const
{
    return mReadRenderTarget;
}

}  // namespace rx

#endif  // LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
