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

// PixelLocalStorage.cpp: Defines the renderer-agnostic container classes
// gl::PixelLocalStorage and gl::PixelLocalStoragePlane for
// ANGLE_shader_pixel_local_storage.

#include "libANGLE/PixelLocalStorage.h"
#include "common/unsafe_buffers.h"

#include <numeric>
#include "common/FixedVector.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/context_private_call.inl.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/TextureImpl.h"

namespace gl
{
// RAII utilities for working with GL state.
namespace
{
class ScopedBindTexture2D : angle::NonCopyable
{
  public:
    ScopedBindTexture2D(Context *context, TextureID texture)
        : mContext(context),
          mSavedTexBinding2D(
              mContext->getState().getSamplerTextureId(mContext->getState().getActiveSampler(),
                                                       TextureType::_2D))
    {
        mContext->bindTexture(TextureType::_2D, texture);
    }

    ~ScopedBindTexture2D() { mContext->bindTexture(TextureType::_2D, mSavedTexBinding2D); }

  private:
    Context *const mContext;
    TextureID mSavedTexBinding2D;
};

class ScopedRestoreDrawFramebuffer : angle::NonCopyable
{
  public:
    ScopedRestoreDrawFramebuffer(Context *context)
        : mContext(context), mSavedFramebuffer(mContext->getState().getDrawFramebuffer())
    {
        ASSERT(mSavedFramebuffer);
    }

    ~ScopedRestoreDrawFramebuffer() { mContext->bindDrawFramebuffer(mSavedFramebuffer->id()); }

  private:
    Context *const mContext;
    Framebuffer *const mSavedFramebuffer;
};

class ScopedDisableScissor : angle::NonCopyable
{
  public:
    ScopedDisableScissor(Context *context)
        : mContext(context), mScissorTestEnabled(mContext->getState().isScissorTestEnabled())
    {
        if (mScissorTestEnabled)
        {
            ContextPrivateDisable(mContext->getMutablePrivateState(),
                                  mContext->getMutablePrivateStateCache(), GL_SCISSOR_TEST);
        }
    }

    ~ScopedDisableScissor()
    {
        if (mScissorTestEnabled)
        {
            ContextPrivateEnable(mContext->getMutablePrivateState(),
                                 mContext->getMutablePrivateStateCache(), GL_SCISSOR_TEST);
        }
    }

  private:
    Context *const mContext;
    const bool mScissorTestEnabled;
};

class ScopedDisableRasterizerDiscard : angle::NonCopyable
{
  public:
    ScopedDisableRasterizerDiscard(Context *context)
        : mContext(context),
          mRasterizerDiscardEnabled(mContext->getState().isRasterizerDiscardEnabled())
    {
        if (mRasterizerDiscardEnabled)
        {
            ContextPrivateDisable(mContext->getMutablePrivateState(),
                                  mContext->getMutablePrivateStateCache(), GL_RASTERIZER_DISCARD);
        }
    }

    ~ScopedDisableRasterizerDiscard()
    {
        if (mRasterizerDiscardEnabled)
        {
            ContextPrivateEnable(mContext->getMutablePrivateState(),
                                 mContext->getMutablePrivateStateCache(), GL_RASTERIZER_DISCARD);
        }
    }

  private:
    Context *const mContext;
    const bool mRasterizerDiscardEnabled;
};

class ScopedEnableColorMask : angle::NonCopyable
{
  public:
    ScopedEnableColorMask(Context *context, int firstDrawBuffer, int numDrawBuffers)
        : mContext(context), mFirstDrawBuffer(firstDrawBuffer), mNumDrawBuffers(numDrawBuffers)
    {
        const State &state = mContext->getState();
        mSavedColorMasks   = state.getBlendStateExt().getColorMaskBits();
        if (!mContext->getExtensions().drawBuffersIndexedAny())
        {
            const uint8_t colorMask =
                BlendStateExt::ColorMaskStorage::GetValueIndexed(0, mSavedColorMasks);
            if (colorMask != BlendStateExt::kColorMaskRGBA)
            {
                ContextPrivateColorMask(mContext->getMutablePrivateState(),
                                        mContext->getMutablePrivateStateCache(), GL_TRUE, GL_TRUE,
                                        GL_TRUE, GL_TRUE);
            }
        }
        else
        {
            const int endDrawBuffer = mFirstDrawBuffer + mNumDrawBuffers;
            for (int i = mFirstDrawBuffer; i < endDrawBuffer; ++i)
            {
                const uint8_t colorMask =
                    BlendStateExt::ColorMaskStorage::GetValueIndexed(i, mSavedColorMasks);
                if (colorMask != BlendStateExt::kColorMaskRGBA)
                {
                    ContextPrivateColorMaski(mContext->getMutablePrivateState(),
                                             mContext->getMutablePrivateStateCache(), i, GL_TRUE,
                                             GL_TRUE, GL_TRUE, GL_TRUE);
                }
            }
        }
    }

    ~ScopedEnableColorMask()
    {
        bool r, g, b, a;
        if (!mContext->getExtensions().drawBuffersIndexedAny())
        {
            const uint8_t colorMask =
                BlendStateExt::ColorMaskStorage::GetValueIndexed(0, mSavedColorMasks);
            if (colorMask != BlendStateExt::kColorMaskRGBA)
            {
                BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a);
                ContextPrivateColorMask(mContext->getMutablePrivateState(),
                                        mContext->getMutablePrivateStateCache(), r, g, b, a);
            }
        }
        else
        {
            const int endDrawBuffer = mFirstDrawBuffer + mNumDrawBuffers;
            for (int i = mFirstDrawBuffer; i < endDrawBuffer; ++i)
            {
                const uint8_t colorMask =
                    BlendStateExt::ColorMaskStorage::GetValueIndexed(i, mSavedColorMasks);
                if (colorMask != BlendStateExt::kColorMaskRGBA)
                {
                    BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a);
                    ContextPrivateColorMaski(mContext->getMutablePrivateState(),
                                             mContext->getMutablePrivateStateCache(), i, r, g, b,
                                             a);
                }
            }
        }
    }

  private:
    Context *const mContext;
    const int mFirstDrawBuffer;
    const int mNumDrawBuffers;
    BlendStateExt::ColorMaskStorage::Type mSavedColorMasks;
};
}  // namespace

PixelLocalStoragePlane::PixelLocalStoragePlane() : mTextureObserver(this, 0) {}

PixelLocalStoragePlane::~PixelLocalStoragePlane()
{
    // Call deinitialize or onContextObjectsLost first!
    // (PixelLocalStorage::deleteContextObjects calls deinitialize.)
    ASSERT(isDeinitialized());
    // We can always expect to receive angle::SubjectMessage::TextureIDDeleted, even if our texture
    // isn't deleted until context teardown. For this reason, we don't need to hold a ref on the
    // underlying texture that is the subject of mTextureObserver.
    ASSERT(mTextureObserver.getSubject() == nullptr);
}

void PixelLocalStoragePlane::onContextObjectsLost()
{
    // We normally call deleteTexture on the memoryless plane texture ID, since we own it, but in
    // this case we can let it go.
    mTextureID = TextureID();
    deinitialize(nullptr);
}

void PixelLocalStoragePlane::deinitialize(Context *context)
{
    if (mMemoryless && mTextureID.value != 0)
    {
        ASSERT(context);
        context->deleteTexture(mTextureID);  // Will deinitialize the texture via observers.
    }
    else
    {
        mInternalformat = GL_NONE;
        mMemoryless     = false;
        mTextureID      = TextureID();
        mTextureObserver.reset();
        mTextureImageIndex = ImageIndex();
        mUsage             = 0;
    }
    ASSERT(isDeinitialized());
}

void PixelLocalStoragePlane::setMemoryless(Context *context,
                                           GLenum internalformat,
                                           GLbitfield usage)
{
    deinitialize(context);
    mInternalformat = internalformat;
    mMemoryless     = true;
    // The backing texture will get allocated lazily, once we know what dimensions it should be.
    ASSERT(mTextureID.value == 0);
    mTextureImageIndex = ImageIndex::Make2D(0);
    mUsage             = usage;
}

void PixelLocalStoragePlane::setTextureBacked(Context *context,
                                              Texture *tex,
                                              int level,
                                              int layer,
                                              GLbitfield usage)
{
    deinitialize(context);
    ASSERT(tex->getImmutableFormat());
    mInternalformat = tex->getState().getBaseLevelDesc().format.info->internalFormat;
    mMemoryless     = false;
    mTextureID      = tex->id();
    mTextureObserver.bind(tex);
    mTextureImageIndex = tex->getType() == TextureType::_2D
                             ? ImageIndex::Make2D(level)
                             : ImageIndex::MakeFromType(tex->getType(), level, layer);
    ASSERT(tex->getType() != TextureType::_2D || !mTextureImageIndex.hasLayer());
    mUsage = usage;
}

void PixelLocalStoragePlane::onSubjectStateChange(angle::SubjectIndex index,
                                                  angle::SubjectMessage message)
{
    ASSERT(index == 0);
    switch (message)
    {
        case angle::SubjectMessage::TextureIDDeleted:
            // When a texture object is deleted, any pixel local storage plane to which it is bound
            // is automatically deinitialized.
            ASSERT(mTextureID.value != 0);
            mTextureID = TextureID();
            deinitialize(nullptr);
            break;
        default:
            break;
    }
}

bool PixelLocalStoragePlane::isDeinitialized() const
{
    if (mInternalformat == GL_NONE)
    {
        ASSERT(!isMemoryless());
        ASSERT(mTextureID.value == 0);
        ASSERT(mTextureObserver.getSubject() == nullptr);
        return true;
    }
    return false;
}

bool PixelLocalStoragePlane::getTextureImageExtents(const Context *context, Extents *extents) const
{
    ASSERT(!isDeinitialized());
    if (isMemoryless())
    {
        return false;
    }
    Texture *tex = context->getTexture(mTextureID);
    ASSERT(tex != nullptr);
    *extents = tex->getExtents(mTextureImageIndex.getTarget(), mTextureImageIndex.getLevelIndex());
    extents->depth = 0;
    return true;
}

void PixelLocalStoragePlane::ensureBackingTextureIfMemoryless(Context *context, Extents plsExtents)
{
    ASSERT(!isDeinitialized());
    if (!isMemoryless())
    {
        ASSERT(mTextureID.value != 0);
        return;
    }

    // Internal textures backing memoryless planes are always 2D and not mipmapped.
    ASSERT(mTextureImageIndex.getType() == TextureType::_2D);
    ASSERT(mTextureImageIndex.getLevelIndex() == 0);
    ASSERT(!mTextureImageIndex.hasLayer());

    Texture *tex = nullptr;
    if (mTextureID.value != 0)
    {
        tex = context->getTexture(mTextureID);
        ASSERT(tex != nullptr);
    }

    // Do we need to allocate a new backing texture?
    if (tex == nullptr ||
        static_cast<GLsizei>(tex->getWidth(TextureTarget::_2D, 0)) != plsExtents.width ||
        static_cast<GLsizei>(tex->getHeight(TextureTarget::_2D, 0)) != plsExtents.height)
    {
        // Call setMemoryless() to release our current data, if any.
        setMemoryless(context, mInternalformat, mUsage);
        ASSERT(mTextureID.value == 0);

        // Create a new texture that backs the memoryless plane.
        if (!context->createTexture(&mTextureID))
        {
            context->handleExhaustionError(angle::EntryPoint::GLBeginPixelLocalStorageANGLE);
            return;
        }

        {
            ScopedBindTexture2D scopedBindTexture2D(context, mTextureID);
            context->bindTexture(TextureType::_2D, mTextureID);
            context->texStorage2D(TextureType::_2D, 1, mInternalformat, plsExtents.width,
                                  plsExtents.height);
        }

        tex = context->getTexture(mTextureID);
        ASSERT(tex != nullptr);
        ASSERT(tex->id() == mTextureID);
        mTextureObserver.bind(tex);
    }
}

void PixelLocalStoragePlane::attachToDrawFramebuffer(Context *context, GLenum colorAttachment) const
{
    ASSERT(!isDeinitialized());
    // Call ensureBackingTextureIfMemoryless() first!
    ASSERT(mTextureID.value != 0 && context->getTexture(mTextureID) != nullptr);
    if (mTextureImageIndex.usesTex3D())  // GL_TEXTURE_2D_ARRAY or GL_TEXTURE_CUBE_MAP_ARRAY
    {
        context->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment, mTextureID,
                                         mTextureImageIndex.getLevelIndex(),
                                         mTextureImageIndex.getLayerIndex());
    }
    else  // GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP
    {
        context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER, colorAttachment,
                                      mTextureImageIndex.getTarget(), mTextureID,
                                      mTextureImageIndex.getLevelIndex());
    }
}

// Clears the draw buffer at 0-based index 'drawBufferIdx' on the current framebuffer.
class ClearBufferCommands : public PixelLocalStoragePlane::ClearCommands
{
  public:
    ClearBufferCommands(Context *context) : mContext(context) {}

    void clearfv(int drawBufferIdx, const GLfloat value[]) const override
    {
        mContext->clearBufferfv(GL_COLOR, drawBufferIdx, value);
    }

    void cleariv(int drawBufferIdx, const GLint value[]) const override
    {
        mContext->clearBufferiv(GL_COLOR, drawBufferIdx, value);
    }

    void clearuiv(int drawBufferIdx, const GLuint value[]) const override
    {
        mContext->clearBufferuiv(GL_COLOR, drawBufferIdx, value);
    }

  private:
    Context *const mContext;
};

template <typename T, size_t N>
void ClampArray(std::array<T, N> &arr, T lo, T hi)
{
    for (T &x : arr)
    {
        x = std::clamp(x, lo, hi);
    }
}

void PixelLocalStoragePlane::issueClearCommand(ClearCommands *clearCommands,
                                               int target,
                                               GLenum loadop) const
{
    switch (mInternalformat)
    {
        case GL_RGBA8:
        case GL_R32F:
        {
            std::array<GLfloat, 4> clearValue = {0, 0, 0, 0};
            if (loadop == GL_LOAD_OP_CLEAR_ANGLE)
            {
                clearValue = mClearValuef;
                if (mInternalformat == GL_RGBA8)
                {
                    ClampArray(clearValue, 0.f, 1.f);
                }
            }
            clearCommands->clearfv(target, clearValue.data());
            break;
        }
        case GL_RGBA8I:
        case GL_R32I:
        {
            std::array<GLint, 4> clearValue = {0, 0, 0, 0};
            if (loadop == GL_LOAD_OP_CLEAR_ANGLE)
            {
                clearValue = mClearValuei;
                if (mInternalformat == GL_RGBA8I)
                {
                    ClampArray(clearValue, -128, 127);
                }
            }
            clearCommands->cleariv(target, clearValue.data());
            break;
        }
        case GL_RGBA8UI:
        case GL_R32UI:
        {
            std::array<GLuint, 4> clearValue = {0, 0, 0, 0};
            if (loadop == GL_LOAD_OP_CLEAR_ANGLE)
            {
                clearValue = mClearValueui;
                if (mInternalformat == GL_RGBA8UI)
                {
                    ClampArray(clearValue, 0u, 255u);
                }
            }
            clearCommands->clearuiv(target, clearValue.data());
            break;
        }
        default:
            // Invalid PLS internalformats should not have made it this far.
            UNREACHABLE();
    }
}

void PixelLocalStoragePlane::bindToImage(Context *context, GLuint unit, bool needsR32Packing) const
{
    ASSERT(!isDeinitialized());
    // Call ensureBackingTextureIfMemoryless() first!
    ASSERT(mTextureID.value != 0 && context->getTexture(mTextureID) != nullptr);
    GLenum imageBindingFormat = mInternalformat;
    if (needsR32Packing)
    {
        // D3D and ES require us to pack all PLS formats into r32f, r32i, or r32ui images.
        switch (imageBindingFormat)
        {
            case GL_RGBA8:
            case GL_RGBA8UI:
                imageBindingFormat = GL_R32UI;
                break;
            case GL_RGBA8I:
                imageBindingFormat = GL_R32I;
                break;
        }
    }
    context->bindImageTexture(unit, mTextureID, mTextureImageIndex.getLevelIndex(), GL_FALSE,
                              getTextureLayer(), GL_READ_WRITE, imageBindingFormat);
}

const Texture *PixelLocalStoragePlane::getBackingTexture(const Context *context) const
{
    ASSERT(!isDeinitialized());
    ASSERT(!isMemoryless());
    const Texture *tex = context->getTexture(mTextureID);
    ASSERT(tex != nullptr);
    return tex;
}

PixelLocalStorage::PixelLocalStorage(const ShPixelLocalStorageOptions &plsOptions, const Caps &caps)
    : mPLSOptions(plsOptions), mPlanes(caps.maxPixelLocalStoragePlanes)
{}

PixelLocalStorage::~PixelLocalStorage() {}

namespace
{
bool AllPlanesDeinitialized(
    const angle::FixedVector<PixelLocalStoragePlane, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES>
        &planes,
    const Context *context)
{
    for (const PixelLocalStoragePlane &plane : planes)
    {
        if (!plane.isDeinitialized())
        {
            return false;
        }
    }
    return true;
}
}  // namespace

void PixelLocalStorage::onFramebufferDestroyed(const Context *context)
{
    if (!context->isReferenced())
    {
        // If the Context's refcount is zero, we know it's in a teardown state and we can just let
        // go of our GL objects -- they get cleaned up as part of context teardown. Otherwise, the
        // Context should have called deleteContextObjects before reaching this point.
        onContextObjectsLost();
        for (PixelLocalStoragePlane &plane : mPlanes)
        {
            plane.onContextObjectsLost();
        }
    }
    // Call deleteContextObjects() when a Framebuffer is destroyed outside of context teardown!
    ASSERT(AllPlanesDeinitialized(mPlanes, context));
}

void PixelLocalStorage::deleteContextObjects(Context *context)
{
    onDeleteContextObjects(context);
    for (PixelLocalStoragePlane &plane : mPlanes)
    {
        plane.deinitialize(context);
    }
}

void PixelLocalStorage::begin(Context *context, GLsizei n, const GLenum loadops[])
{
    ASSERT(mPLSOptions.type == ShPixelLocalStorageType::ImageLoadStore ||
           mPLSOptions.type == ShPixelLocalStorageType::FramebufferFetch);

    // Find the pixel local storage rendering dimensions.
    Extents plsExtents;
    bool hasPLSExtents = false;
    for (GLsizei i = 0; i < n; ++i)
    {
        PixelLocalStoragePlane &plane = mPlanes[i];
        if (plane.getTextureImageExtents(context, &plsExtents))
        {
            hasPLSExtents = true;
            break;
        }
    }
    if (!hasPLSExtents)
    {
        // All PLS planes are memoryless. Use the rendering area of the framebuffer instead.
        plsExtents =
            context->getState().getDrawFramebuffer()->getState().getAttachmentExtentsIntersection();
        ASSERT(plsExtents.depth == 0);
    }
    for (GLsizei i = 0; i < n; ++i)
    {
        PixelLocalStoragePlane &plane = mPlanes[i];
        plane.ensureBackingTextureIfMemoryless(context, plsExtents);
        plane.markActive(true);
    }

    onBegin(context, n, loadops, plsExtents);
}

void PixelLocalStorage::end(Context *context, GLsizei n, const GLenum storeops[])
{
    onEnd(context, n, storeops);

    for (GLsizei i = 0; i < n; ++i)
    {
        mPlanes[i].markActive(false);
    }
}

void PixelLocalStorage::barrier(Context *context)
{
    if (mPLSOptions.supportsNoncoherent)
    {
        onBarrier(context);
    }
}

void PixelLocalStorage::interrupt(Context *context)
{
    if (mInterruptCount == 0)
    {
        mActivePlanesAtInterrupt = context->getState().getPixelLocalStorageActivePlanes();
        ASSERT(0 <= mActivePlanesAtInterrupt &&
               mActivePlanesAtInterrupt <= IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
        if (mActivePlanesAtInterrupt != 0)
        {
            context->endPixelLocalStorageImplicit();
        }
    }
    ++mInterruptCount;
    ASSERT(mInterruptCount > 0);
}

void PixelLocalStorage::restore(Context *context)
{
    ASSERT(mInterruptCount > 0);
    --mInterruptCount;
    ASSERT(0 <= mActivePlanesAtInterrupt &&
           mActivePlanesAtInterrupt <= IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
    if (mInterruptCount == 0 && mActivePlanesAtInterrupt >= 1)
    {
        angle::FixedVector<GLenum, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES> loadops(
            mActivePlanesAtInterrupt);
        for (GLsizei i = 0; i < mActivePlanesAtInterrupt; ++i)
        {
            loadops[i] = mPlanes[i].isMemoryless() ? GL_DONT_CARE : GL_LOAD_OP_LOAD_ANGLE;
        }
        context->beginPixelLocalStorage(mActivePlanesAtInterrupt, loadops.data());
    }
}

namespace
{
// Implements pixel local storage with image load/store shader operations.
class PixelLocalStorageImageLoadStore : public PixelLocalStorage
{
  public:
    PixelLocalStorageImageLoadStore(const ShPixelLocalStorageOptions &plsOptions, const Caps &caps)
        : PixelLocalStorage(plsOptions, caps)
    {
        ASSERT(mPLSOptions.type == ShPixelLocalStorageType::ImageLoadStore);
    }

    // Call deleteContextObjects or onContextObjectsLost first!
    ~PixelLocalStorageImageLoadStore() override
    {
        ASSERT(mScratchFramebufferForClearing.value == 0);
    }

    void onContextObjectsLost() override
    {
        mScratchFramebufferForClearing = FramebufferID();  // Let go of GL objects.
    }

    void onDeleteContextObjects(Context *context) override
    {
        if (mScratchFramebufferForClearing.value != 0)
        {
            context->deleteFramebuffer(mScratchFramebufferForClearing);
            mScratchFramebufferForClearing = FramebufferID();
        }
    }

    void onBegin(Context *context, GLsizei n, const GLenum loadops[], Extents plsExtents) override
    {
        const State &state = context->getState();
        ASSERT(static_cast<size_t>(n) <= state.getImageUnits().size());

        Framebuffer *framebuffer = state.getDrawFramebuffer();
        if (context->getLimitations().noRasterOrderGroupWithoutAttachmentZero)
        {
            // anglebug.com/42266263 -- Metal [[raster_order_group()]] does not work for read_write
            // textures on AMD when the render pass doesn't have a color attachment on slot 0. To
            // work around this we attach one of the PLS textures to GL_COLOR_ATTACHMENT0, if there
            // isn't one already.
            // It's important to keep the attachment enabled so that it's set in the corresponding
            // MTLRenderPassAttachmentDescriptor. As the fragment shader does not have any output
            // bound to this attachment, set the color write mask to all-disabled.
            // Note that the PLS extension disallows simultaneously binding a single texture image
            // to a PLS plane and attaching it to the draw framebuffer. Enabling this workaround on
            // any other platform would yield incorrect results.
            // This flag is set to true iff the framebuffer has an attachment 0 and it is enabled.
            mHadColorAttachment0 = framebuffer->getColorAttachment(0) != nullptr;
            if (!mHadColorAttachment0)
            {
                // Indexed color masks are always available on Metal.
                ASSERT(context->getExtensions().drawBuffersIndexedAny());
                // Remember the current draw buffer 0 color mask and set it to all-disabled.
                state.getBlendStateExt().getColorMaskIndexed(
                    0, &mSavedColorMask[0], &mSavedColorMask[1], &mSavedColorMask[2],
                    &mSavedColorMask[3]);
                ContextPrivateColorMaski(context->getMutablePrivateState(),
                                         context->getMutablePrivateStateCache(), 0, false, false,
                                         false, false);

                // Remember the current draw buffer state so we can restore it during onEnd().
                const DrawBuffersVector<GLenum> &appDrawBuffers =
                    framebuffer->getDrawBufferStates();
                mSavedDrawBuffers.resize(appDrawBuffers.size());
                std::copy(appDrawBuffers.begin(), appDrawBuffers.end(), mSavedDrawBuffers.begin());

                // Turn on draw buffer 0.
                if (mSavedDrawBuffers[0] != GL_COLOR_ATTACHMENT0)
                {
                    GLenum drawBuffer0   = mSavedDrawBuffers[0];
                    mSavedDrawBuffers[0] = GL_COLOR_ATTACHMENT0;
                    context->drawBuffers(static_cast<GLsizei>(mSavedDrawBuffers.size()),
                                         mSavedDrawBuffers.data());
                    mSavedDrawBuffers[0] = drawBuffer0;
                }

                // Attach one of the PLS textures to GL_COLOR_ATTACHMENT0.
                getPlane(0).attachToDrawFramebuffer(context, GL_COLOR_ATTACHMENT0);
            }
        }
        else
        {
            // Specify the framebuffer width/height explicitly in case we end up rendering
            // exclusively to shader images.
            framebuffer->setDefaultWidth(context, plsExtents.width);
            framebuffer->setDefaultHeight(context, plsExtents.height);
        }

        // Guard GL state and bind a scratch framebuffer in case we need to reallocate or clear any
        // PLS planes.
        const size_t maxDrawBuffers = context->getCaps().maxDrawBuffers;
        ScopedRestoreDrawFramebuffer ScopedRestoreDrawFramebuffer(context);
        if (mScratchFramebufferForClearing.value == 0)
        {
            context->genFramebuffers(1, &mScratchFramebufferForClearing);
            context->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mScratchFramebufferForClearing);
            // Turn on all draw buffers on the scratch framebuffer for clearing.
            DrawBuffersVector<GLenum> drawBuffers(maxDrawBuffers);
            std::iota(drawBuffers.begin(), drawBuffers.end(), GL_COLOR_ATTACHMENT0);
            context->drawBuffers(static_cast<int>(drawBuffers.size()), drawBuffers.data());
        }
        else
        {
            context->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mScratchFramebufferForClearing);
        }
        ScopedDisableScissor scopedDisableScissor(context);
        ScopedDisableRasterizerDiscard scopedDisableRasterizerDiscard(context);

        // Bind and clear the PLS planes.
        size_t maxClearedAttachments = 0;
        for (GLsizei i = 0; i < n;)
        {
            DrawBuffersVector<int> pendingClears;
            for (; pendingClears.size() < maxDrawBuffers && i < n; ++i)
            {
                GLenum loadop                       = ANGLE_UNSAFE_TODO(loadops[i]);
                const PixelLocalStoragePlane &plane = getPlane(i);
                plane.bindToImage(context, i, !mPLSOptions.supportsNativeRGBA8ImageFormats);
                if (loadop == GL_LOAD_OP_ZERO_ANGLE || loadop == GL_LOAD_OP_CLEAR_ANGLE)
                {
                    plane.attachToDrawFramebuffer(
                        context, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(pendingClears.size()));
                    pendingClears.push_back(i);  // Defer the clear for later.
                }
            }
            // Clear in batches in order to be more efficient with GL state.
            ScopedEnableColorMask scopedEnableColorMask(context, 0,
                                                        static_cast<int>(pendingClears.size()));
            ClearBufferCommands clearBufferCommands(context);
            for (size_t drawBufferIdx = 0; drawBufferIdx < pendingClears.size(); ++drawBufferIdx)
            {
                int plsIdx = pendingClears[drawBufferIdx];
                getPlane(plsIdx).issueClearCommand(&clearBufferCommands,
                                                   static_cast<int>(drawBufferIdx),
                                                   ANGLE_UNSAFE_TODO(loadops[plsIdx]));
            }
            maxClearedAttachments = std::max(maxClearedAttachments, pendingClears.size());
        }

        // Detach the cleared PLS textures from the scratch framebuffer.
        for (size_t i = 0; i < maxClearedAttachments; ++i)
        {
            context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER,
                                          GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(i),
                                          TextureTarget::_2D, TextureID(), 0);
        }

        // Unlike other barriers, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT also synchronizes all types of
        // memory accesses that happened before the barrier:
        //
        //   SHADER_IMAGE_ACCESS_BARRIER_BIT: Memory accesses using shader built-in image load and
        //   store functions issued after the barrier will reflect data written by shaders prior to
        //   the barrier. Additionally, image stores issued after the barrier will not execute until
        //   all memory accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated
        //   prior to the barrier complete.
        //
        // So we don't any barriers other than GL_SHADER_IMAGE_ACCESS_BARRIER_BIT during begin().
        context->memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
    }

    void onEnd(Context *context, GLsizei n, const GLenum storeops[]) override
    {
        for (GLsizei unit = 0; unit < n; ++unit)
        {
            context->bindImageTexture(unit, PackParam<TextureID>(0u), 0, GL_FALSE, 0, GL_READ_ONLY,
                                      GL_R32UI);
        }

        if (context->getLimitations().noRasterOrderGroupWithoutAttachmentZero)
        {
            if (!mHadColorAttachment0)
            {
                // Detach the PLS texture we attached to GL_COLOR_ATTACHMENT0.
                context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                              TextureTarget::_2D, TextureID(), 0);

                // Restore the draw buffer state from before PLS was enabled.
                if (mSavedDrawBuffers[0] != GL_COLOR_ATTACHMENT0)
                {
                    context->drawBuffers(static_cast<GLsizei>(mSavedDrawBuffers.size()),
                                         mSavedDrawBuffers.data());
                }
                mSavedDrawBuffers.clear();

                // Restore the draw buffer 0 color mask.
                ContextPrivateColorMaski(
                    context->getMutablePrivateState(), context->getMutablePrivateStateCache(), 0,
                    mSavedColorMask[0], mSavedColorMask[1], mSavedColorMask[2], mSavedColorMask[3]);
            }
        }
        else
        {
            // Restore the default framebuffer width/height.
            Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
            framebuffer->setDefaultWidth(context, 0);
            framebuffer->setDefaultHeight(context, 0);
        }

        // We need ALL_BARRIER_BITS during end() because GL_SHADER_IMAGE_ACCESS_BARRIER_BIT doesn't
        // synchronize all types of memory accesses that can happen after the barrier.
        context->memoryBarrier(GL_ALL_BARRIER_BITS);
    }

    void onBarrier(Context *context) override
    {
        context->memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
    }

  private:
    // D3D and ES require us to pack all PLS formats into r32f, r32i, or r32ui images.
    FramebufferID mScratchFramebufferForClearing{};

    // If mPLSOptions.plsRenderPassNeedsColorAttachmentWorkaround.
    bool mHadColorAttachment0;
    std::array<bool, 4> mSavedColorMask;
    DrawBuffersVector<GLenum> mSavedDrawBuffers;
};

// Implements pixel local storage via framebuffer fetch.
class PixelLocalStorageFramebufferFetch : public PixelLocalStorage
{
  public:
    PixelLocalStorageFramebufferFetch(const ShPixelLocalStorageOptions &plsOptions,
                                      const Caps &caps)
        : PixelLocalStorage(plsOptions, caps)
    {
        ASSERT(mPLSOptions.type == ShPixelLocalStorageType::FramebufferFetch);
    }

    void onContextObjectsLost() override {}

    void onDeleteContextObjects(Context *) override {}

    void onBegin(Context *context, GLsizei n, const GLenum loadops[], Extents plsExtents) override
    {
        const Caps &caps                                = context->getCaps();
        Framebuffer *framebuffer                        = context->getState().getDrawFramebuffer();
        const DrawBuffersVector<GLenum> &appDrawBuffers = framebuffer->getDrawBufferStates();

        // Remember the current draw buffer state so we can restore it during onEnd().
        mSavedDrawBuffers.resize(appDrawBuffers.size());
        std::copy(appDrawBuffers.begin(), appDrawBuffers.end(), mSavedDrawBuffers.begin());

        // Set up new draw buffers for PLS.
        int firstPLSDrawBuffer = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - n;
        int numAppDrawBuffers =
            std::min(static_cast<int>(appDrawBuffers.size()), firstPLSDrawBuffer);
        DrawBuffersArray<GLenum> plsDrawBuffers;
        std::copy(appDrawBuffers.begin(), appDrawBuffers.begin() + numAppDrawBuffers,
                  plsDrawBuffers.begin());
        std::fill(plsDrawBuffers.begin() + numAppDrawBuffers,
                  plsDrawBuffers.begin() + firstPLSDrawBuffer, GL_NONE);

        bool needsClear = false;
        for (GLsizei i = 0; i < n; ++i)
        {
            GLuint drawBufferIdx                = GetDrawBufferIdx(caps, i);
            GLenum loadop                       = ANGLE_UNSAFE_TODO(loadops[i]);
            const PixelLocalStoragePlane &plane = getPlane(i);
            ASSERT(!plane.isDeinitialized());

            // Attach our PLS texture to the framebuffer. Validation should have already ensured
            // nothing else was attached at this point.
            GLenum colorAttachment = GL_COLOR_ATTACHMENT0 + drawBufferIdx;
            ASSERT(!framebuffer->getAttachment(context, colorAttachment));
            plane.attachToDrawFramebuffer(context, colorAttachment);
            plsDrawBuffers[drawBufferIdx] = colorAttachment;

            needsClear = needsClear || (loadop != GL_LOAD_OP_LOAD_ANGLE);
        }

        // Turn on the PLS draw buffers.
        context->drawBuffers(caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes,
                             plsDrawBuffers.data());

        // Clear the non-LOAD_OP_LOAD PLS planes now that their draw buffers are turned on.
        if (needsClear)
        {
            ScopedDisableScissor scopedDisableScissor(context);
            ScopedDisableRasterizerDiscard scopedDisableRasterizerDiscard(context);
            ClearBufferCommands clearBufferCommands(context);
            for (GLsizei i = 0; i < n; ++i)
            {
                GLenum loadop = ANGLE_UNSAFE_TODO(loadops[i]);
                if (loadop != GL_LOAD_OP_LOAD_ANGLE)
                {
                    GLuint drawBufferIdx = GetDrawBufferIdx(caps, i);
                    ScopedEnableColorMask scopedEnableColorMask(context, drawBufferIdx, 1);
                    getPlane(i).issueClearCommand(&clearBufferCommands, drawBufferIdx, loadop);
                }
            }
        }

        // Insert a barrier in case the app performs any noncoherent accesses, since the textures
        // may have been accessed as attachments immediately before this call.
        barrier(context);
    }

    void onEnd(Context *context, GLsizei n, const GLenum storeops[]) override
    {
        const Caps &caps = context->getCaps();

        // Invalidate the non-preserved PLS attachments.
        DrawBuffersVector<GLenum> invalidateList;
        for (GLsizei i = n - 1; i >= 0; --i)
        {
            if (!getPlane(i).isActive())
            {
                continue;
            }
            if (ANGLE_UNSAFE_TODO(storeops[i]) != GL_STORE_OP_STORE_ANGLE ||
                getPlane(i).isMemoryless())
            {
                int drawBufferIdx = GetDrawBufferIdx(caps, i);
                invalidateList.push_back(GL_COLOR_ATTACHMENT0 + drawBufferIdx);
            }
        }
        if (!invalidateList.empty())
        {
            context->invalidateFramebuffer(GL_DRAW_FRAMEBUFFER,
                                           static_cast<GLsizei>(invalidateList.size()),
                                           invalidateList.data());
        }

        for (GLsizei i = 0; i < n; ++i)
        {
            // Reset color attachments where PLS was attached. Validation should have already
            // ensured nothing was attached at these points when we activated pixel local storage,
            // and that nothing got attached during.
            GLuint drawBufferIdx   = GetDrawBufferIdx(caps, i);
            GLenum colorAttachment = GL_COLOR_ATTACHMENT0 + drawBufferIdx;
            context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER, colorAttachment, TextureTarget::_2D,
                                          TextureID(), 0);
        }

        // Restore the draw buffer state from before PLS was enabled.
        context->drawBuffers(static_cast<GLsizei>(mSavedDrawBuffers.size()),
                             mSavedDrawBuffers.data());
        mSavedDrawBuffers.clear();

        // Insert a barrier in case the app performed any noncoherent accesses, since the textures
        // may be accessed as attachments immediately after this call.
        barrier(context);
    }

    void onBarrier(Context *context) override { context->framebufferFetchBarrier(); }

  private:
    static GLuint GetDrawBufferIdx(const Caps &caps, GLuint plsPlaneIdx)
    {
        // Bind the PLS attachments in reverse order from the rear. This way, the shader translator
        // doesn't need to know how many planes are going to be active in order to figure out plane
        // indices.
        return caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - plsPlaneIdx - 1;
    }

    DrawBuffersVector<GLenum> mSavedDrawBuffers;
};

}  // namespace

std::unique_ptr<PixelLocalStorage> PixelLocalStorage::Make(const Context *context)
{
    const ShPixelLocalStorageOptions &plsOptions =
        context->getImplementation()->getNativePixelLocalStorageOptions();
    const Caps &caps = context->getState().getCaps();
    switch (plsOptions.type)
    {
        case ShPixelLocalStorageType::ImageLoadStore:
            return std::make_unique<PixelLocalStorageImageLoadStore>(plsOptions, caps);
        case ShPixelLocalStorageType::FramebufferFetch:
            return std::make_unique<PixelLocalStorageFramebufferFetch>(plsOptions, caps);
        default:
            UNREACHABLE();
            return nullptr;
    }
}
}  // namespace gl
