//
// Copyright 2019 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.
//
// FrameCapture.cpp:
//   ANGLE Frame capture GL implementation.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/capture/FrameCapture.h"

#include <cerrno>
#include <cstring>
#include <fstream>
#include <queue>
#include <string>

#include "common/aligned_memory.h"
#include "common/angle_version_info.h"
#include "common/base/anglebase/no_destructor.h"
#include "common/frame_capture_utils.h"
#include "common/gl_enum_utils.h"
#include "common/mathutil.h"
#include "common/serializer/JsonSerializer.h"
#include "common/string_utils.h"
#include "common/system_utils.h"
#include "gpu_info_util/SystemInfo.h"
#include "image_util/storeimage.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Context.inl.h"
#include "libANGLE/Display.h"
#include "libANGLE/EGLSync.h"
#include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/GLES1Renderer.h"
#include "libANGLE/Query.h"
#include "libANGLE/ResourceMap.h"
#include "libANGLE/Shader.h"
#include "libANGLE/Surface.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/capture/capture_egl_autogen.h"
#include "libANGLE/capture/capture_gles_1_0_autogen.h"
#include "libANGLE/capture/capture_gles_2_0_autogen.h"
#include "libANGLE/capture/capture_gles_3_0_autogen.h"
#include "libANGLE/capture/capture_gles_3_1_autogen.h"
#include "libANGLE/capture/capture_gles_3_2_autogen.h"
#include "libANGLE/capture/capture_gles_ext_autogen.h"
#include "libANGLE/capture/serialize.h"
#include "libANGLE/entry_points_utils.h"
#include "libANGLE/queryconversions.h"
#include "libANGLE/queryutils.h"
#include "libANGLE/renderer/driver_utils.h"
#include "libANGLE/validationEGL.h"
#include "third_party/ceval/ceval.h"

#define USE_SYSTEM_ZLIB
#include "compression_utils_portable.h"

#if !ANGLE_CAPTURE_ENABLED
#    error Frame capture must be enabled to include this file.
#endif  // !ANGLE_CAPTURE_ENABLED

namespace angle
{
// Thread specific record suspension flag to prevent re-recording cmds from the fixture
static thread_local bool g_skipCapture = false;

// Check if we've found a fixture injection marker and set the skip flag
// so that neither suppression markers or marked calls are recorded
static bool MaybeSkipCapture(const CallCapture &call)
{
    if (call.entryPoint != EntryPoint::GLDebugMessageInsert &&
        call.entryPoint != EntryPoint::GLDebugMessageInsertKHR)
    {
        return false;
    }
    const GLuint markerId = call.params.getParam("id", ParamType::TGLuint, 2).value.GLuintVal;
    if (markerId == kFixtureInjectedCommandsBeginId)
    {
        g_skipCapture = true;
        return true;
    }
    if (markerId == kFixtureInjectedCommandsEndId)
    {
        g_skipCapture = false;
        return true;
    }
    return false;
}

struct FramebufferCaptureFuncs
{
    FramebufferCaptureFuncs(bool isGLES1)
    {
        if (isGLES1)
        {
            // From GL_OES_framebuffer_object
            framebufferTexture2D    = &gl::CaptureFramebufferTexture2DOES;
            framebufferRenderbuffer = &gl::CaptureFramebufferRenderbufferOES;
            bindFramebuffer         = &gl::CaptureBindFramebufferOES;
            genFramebuffers         = &gl::CaptureGenFramebuffersOES;
            bindRenderbuffer        = &gl::CaptureBindRenderbufferOES;
            genRenderbuffers        = &gl::CaptureGenRenderbuffersOES;
            renderbufferStorage     = &gl::CaptureRenderbufferStorageOES;
        }
        else
        {
            framebufferTexture2D    = &gl::CaptureFramebufferTexture2D;
            framebufferRenderbuffer = &gl::CaptureFramebufferRenderbuffer;
            bindFramebuffer         = &gl::CaptureBindFramebuffer;
            genFramebuffers         = &gl::CaptureGenFramebuffers;
            bindRenderbuffer        = &gl::CaptureBindRenderbuffer;
            genRenderbuffers        = &gl::CaptureGenRenderbuffers;
            renderbufferStorage     = &gl::CaptureRenderbufferStorage;
        }
    }

    decltype(&gl::CaptureFramebufferTexture2D) framebufferTexture2D;
    decltype(&gl::CaptureFramebufferRenderbuffer) framebufferRenderbuffer;
    decltype(&gl::CaptureBindFramebuffer) bindFramebuffer;
    decltype(&gl::CaptureGenFramebuffers) genFramebuffers;
    decltype(&gl::CaptureBindRenderbuffer) bindRenderbuffer;
    decltype(&gl::CaptureGenRenderbuffers) genRenderbuffers;
    decltype(&gl::CaptureRenderbufferStorage) renderbufferStorage;
};

struct VertexArrayCaptureFuncs
{
    VertexArrayCaptureFuncs(bool isGLES1)
    {
        if (isGLES1)
        {
            // From GL_OES_vertex_array_object
            bindVertexArray    = &gl::CaptureBindVertexArrayOES;
            deleteVertexArrays = &gl::CaptureDeleteVertexArraysOES;
            genVertexArrays    = &gl::CaptureGenVertexArraysOES;
            isVertexArray      = &gl::CaptureIsVertexArrayOES;
        }
        else
        {
            bindVertexArray    = &gl::CaptureBindVertexArray;
            deleteVertexArrays = &gl::CaptureDeleteVertexArrays;
            genVertexArrays    = &gl::CaptureGenVertexArrays;
            isVertexArray      = &gl::CaptureIsVertexArray;
        }
    }

    decltype(&gl::CaptureBindVertexArray) bindVertexArray;
    decltype(&gl::CaptureDeleteVertexArrays) deleteVertexArrays;
    decltype(&gl::CaptureGenVertexArrays) genVertexArrays;
    decltype(&gl::CaptureIsVertexArray) isVertexArray;
};

std::string GetCaptureTrigger()
{
    // Use the GetAndSet variant to improve future lookup times
    return GetAndSetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger);
}
struct FmtGetSerializedContextStateFunction
{
    FmtGetSerializedContextStateFunction(gl::ContextID contextIdIn,
                                         FuncUsage usageIn,
                                         uint32_t frameIndexIn)
        : contextId(contextIdIn), usage(usageIn), frameIndex(frameIndexIn)
    {}
    gl::ContextID contextId;
    FuncUsage usage;
    uint32_t frameIndex;
};

std::ostream &operator<<(std::ostream &os, const FmtGetSerializedContextStateFunction &fmt)
{
    os << "GetSerializedContext" << fmt.contextId << "StateFrame" << fmt.frameIndex << "Data"
       << fmt.usage;
    return os;
}

void WriteGLFloatValue(std::ostream &out, GLfloat value)
{
    // Check for non-representable values
    ASSERT(std::numeric_limits<float>::has_infinity);
    ASSERT(std::numeric_limits<float>::has_quiet_NaN);

    if (std::isinf(value))
    {
        float negativeInf = -std::numeric_limits<float>::infinity();
        if (value == negativeInf)
        {
            out << "-";
        }
        out << "INFINITY";
    }
    else if (std::isnan(value))
    {
        out << "NAN";
    }
    else
    {
        // Write a decimal point to preserve the zero sign on replay
        out << (value == 0.0 ? std::showpoint : std::noshowpoint);
        out << std::setprecision(16);
        out << value;
    }
}

void WriteStringParamReplay(ReplayWriter &replayWriter,
                            std::ostream &out,
                            std::ostream &header,
                            const CallCapture &call,
                            const ParamCapture &param,
                            FrameCaptureBinaryData *binaryData)
{
    const std::vector<uint8_t> &data = param.data[0];
    // null terminate C style string
    ASSERT(data.size() > 0 && data.back() == '\0');
    std::string str(data.begin(), data.end() - 1);

    constexpr size_t kMaxInlineStringLength = 20000;
    if (str.size() > kMaxInlineStringLength)
    {
        // Store in binary file if the string is too long.
        // Round up to 16-byte boundary for cross ABI safety.
        const size_t offset = binaryData->append(str.data(), str.size() + 1);
        out << "(const char *)GetBinaryData(" << offset << ")";
    }
    else if (str.find('\n') != std::string::npos)
    {
        std::string varName = replayWriter.getInlineVariableName(call.entryPoint, param.name);
        header << "const char " << varName << "[] = \n" << FmtMultiLineString(str) << ";";
        out << varName;
    }
    else
    {
        out << "\"" << str << "\"";
    }
}

enum class Indent
{
    Indent,
    NoIdent,
};

void UpdateResourceIDBuffer(std::ostream &out,
                            Indent indent,
                            size_t bufferIndex,
                            ResourceIDType resourceIDType,
                            gl::ContextID contextID,
                            GLuint resourceID)
{
    if (indent == Indent::Indent)
    {
        out << "    ";
    }
    out << "UpdateResourceIDBuffer(" << bufferIndex << ", g"
        << GetResourceIDTypeName(resourceIDType) << "Map";
    if (IsTrackedPerContext(resourceIDType))
    {
        out << "PerContext[" << contextID.value << "]";
    }
    out << "[" << resourceID << "]);\n";
}

template <typename ParamT>
void WriteResourceIDPointerParamReplay(ReplayWriter &replayWriter,
                                       std::ostream &out,
                                       std::ostream &header,
                                       const CallCapture &call,
                                       const ParamCapture &param,
                                       size_t *maxResourceIDBufferSize)
{
    const ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(param.type);
    ASSERT(resourceIDType != ResourceIDType::InvalidEnum);

    if (param.dataNElements > 0)
    {
        ASSERT(param.data.size() == 1);

        const ParamT *returnedIDs = reinterpret_cast<const ParamT *>(param.data[0].data());
        for (GLsizei resIndex = 0; resIndex < param.dataNElements; ++resIndex)
        {
            ParamT id = returnedIDs[resIndex];
            UpdateResourceIDBuffer(header, Indent::NoIdent, resIndex, resourceIDType,
                                   call.contextID, id.value);
        }

        *maxResourceIDBufferSize = std::max<size_t>(*maxResourceIDBufferSize, param.dataNElements);
    }

    out << "gResourceIDBuffer";
}

void WriteCppReplayForCall(const CallCapture &call,
                           ReplayWriter &replayWriter,
                           std::ostream &out,
                           std::ostream &header,
                           FrameCaptureBinaryData *binaryData,
                           size_t *maxResourceIDBufferSize)
{
    if (call.customFunctionName == "Comment")
    {
        // Just write it directly to the file and move on
        WriteComment(out, call);
        return;
    }

    std::ostringstream callOut;

    callOut << call.name() << "(";

    bool first = true;
    for (const ParamCapture &param : call.params.getParamCaptures())
    {
        if (!first)
        {
            callOut << ", ";
        }

        if (param.arrayClientPointerIndex != -1 && param.value.voidConstPointerVal != nullptr)
        {
            int clientIndex = (param.arrayClientPointerMergedIndex != -1)
                                  ? param.arrayClientPointerMergedIndex
                                  : param.arrayClientPointerIndex;
            callOut << "gClientArrays[" << clientIndex << "]";
            if (param.arrayClientPointerOffset != 0)
            {
                callOut << " + " << param.arrayClientPointerOffset;
            }
        }
        else if (param.readBufferSizeBytes > 0)
        {
            callOut << "(" << ParamTypeToString(param.type) << ")gReadBuffer";
        }
        else if (param.data.empty())
        {
            if (param.type == ParamType::TGLenum)
            {
                OutputGLenumString(callOut, param.enumGroup, param.value.GLenumVal);
            }
            else if (param.type == ParamType::TGLbitfield)
            {
                OutputGLbitfieldString(callOut, param.enumGroup, param.value.GLbitfieldVal);
            }
            else if (param.type == ParamType::TGLfloat)
            {
                WriteGLFloatValue(callOut, param.value.GLfloatVal);
            }
            else if (param.type == ParamType::TGLsync)
            {
                callOut << "gSyncMap[" << FmtPointerIndex(param.value.GLsyncVal) << "]";
            }
            else if (param.type == ParamType::TGLuint64 && param.name == "timeout")
            {
                if (param.value.GLuint64Val == GL_TIMEOUT_IGNORED)
                {
                    callOut << "GL_TIMEOUT_IGNORED";
                }
                else
                {
                    WriteParamCaptureReplay(callOut, call, param);
                }
            }
            else
            {
                WriteParamCaptureReplay(callOut, call, param);
            }
        }
        else
        {
            switch (param.type)
            {
                case ParamType::TGLcharConstPointer:
                    WriteStringParamReplay(replayWriter, callOut, header, call, param, binaryData);
                    break;
                case ParamType::TGLcharConstPointerPointer:
                    WriteStringPointerParamReplay(replayWriter, callOut, header, call, param);
                    break;
                case ParamType::TBufferIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::BufferID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TFenceNVIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::FenceNVID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TFramebufferIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::FramebufferID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TMemoryObjectIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::MemoryObjectID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TProgramPipelineIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::ProgramPipelineID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TQueryIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::QueryID>(replayWriter, callOut, out, call,
                                                                   param, maxResourceIDBufferSize);
                    break;
                case ParamType::TRenderbufferIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::RenderbufferID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TSamplerIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::SamplerID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TSemaphoreIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::SemaphoreID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TTextureIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::TextureID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TTransformFeedbackIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::TransformFeedbackID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                case ParamType::TVertexArrayIDConstPointer:
                    WriteResourceIDPointerParamReplay<gl::VertexArrayID>(
                        replayWriter, callOut, out, call, param, maxResourceIDBufferSize);
                    break;
                default:
                    WriteBinaryParamReplay(replayWriter, callOut, header, call, param, binaryData);
                    break;
            }
        }

        first = false;
    }

    callOut << ")";

    out << callOut.str();
}

size_t MaxClientArraySize(const gl::AttribArray<size_t> &clientArraySizes)
{
    size_t found = 0;
    for (size_t size : clientArraySizes)
    {
        if (size > found)
        {
            found = size;
        }
    }

    return found;
}

void WriteInitReplayCall(bool compression,
                         std::ostream &out,
                         gl::ContextID contextID,
                         const std::string &captureLabel,
                         size_t maxClientArraySize,
                         size_t readBufferSize,
                         size_t resourceIDBufferSize,
                         const PackedEnumMap<ResourceIDType, uint32_t> &maxIDs)
{
    std::string binaryDataFileName = GetBinaryDataFilePath(compression, captureLabel);

    out << "    // binaryDataFileName = " << binaryDataFileName << "\n";
    out << "    // maxClientArraySize = " << maxClientArraySize << "\n";
    out << "    // readBufferSize = " << readBufferSize << "\n";
    out << "    // resourceIDBufferSize = " << resourceIDBufferSize << "\n";
    out << "    // contextID = " << contextID << "\n";
    for (ResourceIDType resourceID : AllEnums<ResourceIDType>())
    {
        const char *name = GetResourceIDTypeName(resourceID);
        out << "    // max" << name << " = " << maxIDs[resourceID] << "\n";
    }
    out << "    InitializeReplay5(\"" << binaryDataFileName << "\", " << maxClientArraySize << ", "
        << readBufferSize << ", " << resourceIDBufferSize << ", " << contextID;

    for (ResourceIDType resourceID : AllEnums<ResourceIDType>())
    {
        // Sanity check for catching e.g. uninitialized memory reads like b/380296979
        ASSERT(maxIDs[resourceID] < 1000000);
        out << ", " << maxIDs[resourceID];
    }

    out << ");\n";
    // Load binary data
    out << "    InitializeBinaryDataLoader();\n";
}

void DeleteResourcesInReset(std::stringstream &out,
                            const gl::ContextID contextID,
                            const ResourceSet &newResources,
                            const ResourceSet &resourcesToDelete,
                            const ResourceIDType resourceIDType,
                            size_t *maxResourceIDBufferSize)
{
    if (!newResources.empty() || !resourcesToDelete.empty())
    {
        size_t count = 0;

        for (GLuint oldResource : resourcesToDelete)
        {
            UpdateResourceIDBuffer(out, Indent::Indent, count++, resourceIDType, contextID,
                                   oldResource);
        }

        for (GLuint newResource : newResources)
        {
            UpdateResourceIDBuffer(out, Indent::Indent, count++, resourceIDType, contextID,
                                   newResource);
        }

        // Delete all the new and old buffers at once
        out << "    glDelete" << GetResourceIDTypeName(resourceIDType) << "s(" << count
            << ", gResourceIDBuffer);\n";

        *maxResourceIDBufferSize = std::max(*maxResourceIDBufferSize, count);
    }
}

struct MergedAttribRanges
{
    gl::AttribArray<uintptr_t> startAddr;
    gl::AttribArray<uintptr_t> endAddr;
};

void MaybeMergeClientAttributes(const gl::VertexArray *vao,
                                const gl::AttributesMask clientVertexArrayAttrMask,
                                const gl::AttribArray<const void *> clientVertexArrayData,
                                std::vector<CallCapture> *frameCalls,
                                const std::vector<size_t> &clientVACallIndices,
                                bool shouldCaptureClientArrayData,
                                size_t vertexCount,
                                size_t instanceCount,
                                MergedAttribRanges &mergedAddrRangesOut,
                                gl::AttribArray<size_t> &mergedIndexMapOut)
{
    // In case the data should be captured (e.g., for draw time), the vertex or instance count
    // should be given for address range calculations. Otherwise, both are expected to be 0 and
    // neither is used.
    ASSERT(shouldCaptureClientArrayData || (vertexCount == 0 && instanceCount == 0));

    // Initialize the merge indices. In case there is no merging, each attribute is mapped to a
    // gClientArray with the same index.
    for (size_t i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        mergedIndexMapOut[i] = i;
    }

    if (!clientVertexArrayAttrMask.any())
    {
        // Nothing to merge.
        return;
    }

    // Collect the start and end addresses for each attribute in the attribute mask.
    gl::AttribArray<size_t> addrOffset;
    gl::AttribArray<size_t> sortedIndices;
    size_t sortedCount = 0;
    for (size_t attribIndex : clientVertexArrayAttrMask)
    {
        const gl::VertexAttribute &attrib = vao->getVertexAttribute(attribIndex);
        const gl::VertexBinding &binding  = vao->getVertexBinding(attrib.bindingIndex);

        const void *clientSideAddress = clientVertexArrayData[attribIndex];
        if (clientSideAddress == nullptr)
        {
            continue;
        }

        size_t bytesToCapture = attrib.format->pixelBytes;
        if (shouldCaptureClientArrayData)
        {
            size_t count = binding.getDivisor() > 0
                               ? rx::UnsignedCeilDivide(static_cast<uint32_t>(instanceCount),
                                                        binding.getDivisor())
                               : vertexCount;
            // The last capture element doesn't take up the full stride.
            bytesToCapture = (count - 1) * binding.getStride() + attrib.format->pixelBytes;
        }

        // Set the addresses for potential merge.
        mergedAddrRangesOut.startAddr[attribIndex] = reinterpret_cast<uintptr_t>(clientSideAddress);
        mergedAddrRangesOut.endAddr[attribIndex] =
            mergedAddrRangesOut.startAddr[attribIndex] + bytesToCapture;
        addrOffset[attribIndex]      = 0;
        sortedIndices[sortedCount++] = attribIndex;
    }

    // Determine which attributes should be merged and their relative offset with respect to the
    // leading attribute (i.e., attribute with offset 0).
    auto compareRangesFunc = [&mergedAddrRangesOut](size_t a, size_t b) -> bool {
        return mergedAddrRangesOut.startAddr[a] == mergedAddrRangesOut.startAddr[b]
                   ? mergedAddrRangesOut.endAddr[a] < mergedAddrRangesOut.endAddr[b]
                   : mergedAddrRangesOut.startAddr[a] < mergedAddrRangesOut.startAddr[b];
    };
    std::sort(sortedIndices.begin(), sortedIndices.begin() + sortedCount, compareRangesFunc);

    size_t currentMergeIndex = 0;
    if (sortedCount > 0)
    {
        currentMergeIndex                    = sortedIndices[0];
        mergedIndexMapOut[currentMergeIndex] = currentMergeIndex;
    }
    for (size_t sortedAttribIndex = 1; sortedAttribIndex < sortedCount; sortedAttribIndex++)
    {
        size_t nextAttribIndex = sortedIndices[sortedAttribIndex];

        // Check for overlap or adjacency:
        // Current leader: [Start ............ End]
        // Next:                    [Start ............ End]
        if (mergedAddrRangesOut.endAddr[currentMergeIndex] >=
            mergedAddrRangesOut.startAddr[nextAttribIndex])
        {
            // Overlap/Adjacency; the leader's end address is extended to cover the next attribute,
            // and the next attribute is now mapped to the leader index, merging the two attributes.
            // The offset of the next attribute will also be set with respect to the leader.
            mergedAddrRangesOut.endAddr[currentMergeIndex] =
                std::max(mergedAddrRangesOut.endAddr[currentMergeIndex],
                         mergedAddrRangesOut.endAddr[nextAttribIndex]);
            addrOffset[nextAttribIndex] = mergedAddrRangesOut.startAddr[nextAttribIndex] -
                                          mergedAddrRangesOut.startAddr[currentMergeIndex];
            mergedIndexMapOut[currentMergeIndex] = currentMergeIndex;
            mergedIndexMapOut[nextAttribIndex]   = currentMergeIndex;
        }
        else
        {
            // No overlap; the next attribute becomes the new leader for subsequent attributes.
            currentMergeIndex = nextAttribIndex;
        }
    }

    // Update the pointers and offsets in the captured code for the corresponding vertex attribute
    // calls. The last instance using a vertex client attribute for each called attribute should be
    // updated.
    for (size_t attribIndex : clientVertexArrayAttrMask)
    {
        size_t mergedIndex = mergedIndexMapOut[attribIndex];
        size_t offset      = addrOffset[attribIndex];

        for (auto vaIndex = clientVACallIndices.rbegin(); vaIndex != clientVACallIndices.rend();
             vaIndex++)
        {
            CallCapture &framecall = frameCalls->at(*vaIndex);
            ASSERT(framecall.params.hasClientArrayData());

            // The client pointer index is originally set to the attribute index. It should now be
            // changed to the merged index with an offset.
            ParamCapture &clientArrayPointerParams =
                framecall.params.getClientArrayPointerParameter();
            if (clientArrayPointerParams.arrayClientPointerIndex == static_cast<int>(attribIndex))
            {
                clientArrayPointerParams.arrayClientPointerMergedIndex =
                    static_cast<int>(mergedIndex);
                clientArrayPointerParams.arrayClientPointerOffset = static_cast<int>(offset);
                break;
            }
        }
    }
}

// TODO (http://anglebug.com/42263204): Reset more state on frame loop
void MaybeResetResources(egl::Display *display,
                         gl::ContextID contextID,
                         ResourceIDType resourceIDType,
                         ReplayWriter &replayWriter,
                         std::stringstream &out,
                         std::stringstream &header,
                         ResourceTracker *resourceTracker,
                         FrameCaptureBinaryData *binaryData,
                         bool &anyResourceReset,
                         size_t *maxResourceIDBufferSize)
{
    // Track the initial output position so we can detect if it has moved
    std::streampos initialOutPos = out.tellp();

    switch (resourceIDType)
    {
        case ResourceIDType::Buffer:
        {
            TrackedResource &trackedBuffers =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::Buffer);
            ResourceSet &newBuffers           = trackedBuffers.getNewResources();
            ResourceSet &buffersToDelete      = trackedBuffers.getResourcesToDelete();
            ResourceSet &buffersToRegen       = trackedBuffers.getResourcesToRegen();
            ResourceCalls &bufferRegenCalls   = trackedBuffers.getResourceRegenCalls();
            ResourceCalls &bufferRestoreCalls = trackedBuffers.getResourceRestoreCalls();

            BufferCalls &bufferMapCalls   = resourceTracker->getBufferMapCalls();
            BufferCalls &bufferUnmapCalls = resourceTracker->getBufferUnmapCalls();

            DeleteResourcesInReset(out, contextID, newBuffers, buffersToDelete, resourceIDType,
                                   maxResourceIDBufferSize);

            // If any of our starting buffers were deleted during the run, recreate them
            for (GLuint id : buffersToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : bufferRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            // If any of our starting buffers were modified during the run, restore their contents
            ResourceSet &buffersToRestore = trackedBuffers.getResourcesToRestore();
            for (GLuint id : buffersToRestore)
            {
                if (resourceTracker->getStartingBuffersMappedCurrent(id))
                {
                    // Some drivers require the buffer to be unmapped before you can update data,
                    // which violates the spec. See gl::Buffer::bufferDataImpl().
                    for (CallCapture &call : bufferUnmapCalls[id])
                    {
                        out << "    ";
                        WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                              maxResourceIDBufferSize);
                        out << ";\n";
                    }
                }

                // Emit their restore calls
                for (CallCapture &call : bufferRestoreCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";

                    // Also note that this buffer has been implicitly unmapped by this call
                    resourceTracker->setBufferUnmapped(contextID, id);
                }
            }

            // Update the map/unmap of buffers to match the starting state
            ResourceSet startingBuffers = trackedBuffers.getStartingResources();
            for (GLuint id : startingBuffers)
            {
                // If the buffer was mapped at the start, but is not mapped now, we need to map
                if (resourceTracker->getStartingBuffersMappedInitial(id) &&
                    !resourceTracker->getStartingBuffersMappedCurrent(id))
                {
                    // Emit their map calls
                    for (CallCapture &call : bufferMapCalls[id])
                    {
                        out << "    ";
                        WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                              maxResourceIDBufferSize);
                        out << ";\n";
                    }
                }
                // If the buffer was unmapped at the start, but is mapped now, we need to unmap
                if (!resourceTracker->getStartingBuffersMappedInitial(id) &&
                    resourceTracker->getStartingBuffersMappedCurrent(id))
                {
                    // Emit their unmap calls
                    for (CallCapture &call : bufferUnmapCalls[id])
                    {
                        out << "    ";
                        WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                              maxResourceIDBufferSize);
                        out << ";\n";
                    }
                }
            }
            break;
        }
        case ResourceIDType::Framebuffer:
        {
            TrackedResource &trackedFramebuffers =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::Framebuffer);
            ResourceSet &newFramebuffers           = trackedFramebuffers.getNewResources();
            ResourceSet &framebuffersToDelete      = trackedFramebuffers.getResourcesToDelete();
            ResourceSet &framebuffersToRegen       = trackedFramebuffers.getResourcesToRegen();
            ResourceCalls &framebufferRegenCalls   = trackedFramebuffers.getResourceRegenCalls();
            ResourceCalls &framebufferRestoreCalls = trackedFramebuffers.getResourceRestoreCalls();

            DeleteResourcesInReset(out, contextID, newFramebuffers, framebuffersToDelete,
                                   resourceIDType, maxResourceIDBufferSize);

            for (GLuint id : framebuffersToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : framebufferRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            // If any of our starting framebuffers were modified during the run, restore their
            // contents
            ResourceSet &framebuffersToRestore = trackedFramebuffers.getResourcesToRestore();
            for (GLuint id : framebuffersToRestore)
            {
                // Emit their restore calls
                for (CallCapture &call : framebufferRestoreCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }
            break;
        }
        case ResourceIDType::Renderbuffer:
        {
            TrackedResource &trackedRenderbuffers =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::Renderbuffer);
            ResourceSet &newRenderbuffers         = trackedRenderbuffers.getNewResources();
            ResourceSet &renderbuffersToDelete    = trackedRenderbuffers.getResourcesToDelete();
            ResourceSet &renderbuffersToRegen     = trackedRenderbuffers.getResourcesToRegen();
            ResourceCalls &renderbufferRegenCalls = trackedRenderbuffers.getResourceRegenCalls();
            ResourceCalls &renderbufferRestoreCalls =
                trackedRenderbuffers.getResourceRestoreCalls();

            DeleteResourcesInReset(out, contextID, newRenderbuffers, renderbuffersToDelete,
                                   resourceIDType, maxResourceIDBufferSize);

            for (GLuint id : renderbuffersToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : renderbufferRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            // If any of our starting renderbuffers were modified during the run, restore their
            // contents
            ResourceSet &renderbuffersToRestore = trackedRenderbuffers.getResourcesToRestore();
            for (GLuint id : renderbuffersToRestore)
            {
                // Emit their restore calls
                for (CallCapture &call : renderbufferRestoreCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }
            break;
        }
        case ResourceIDType::ShaderProgram:
        {
            TrackedResource &trackedShaderPrograms =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::ShaderProgram);
            ResourceSet &newShaderPrograms         = trackedShaderPrograms.getNewResources();
            ResourceSet &shaderProgramsToDelete    = trackedShaderPrograms.getResourcesToDelete();
            ResourceSet &shaderProgramsToRegen     = trackedShaderPrograms.getResourcesToRegen();
            ResourceSet &shaderProgramsToRestore   = trackedShaderPrograms.getResourcesToRestore();
            ResourceCalls &shaderProgramRegenCalls = trackedShaderPrograms.getResourceRegenCalls();
            ResourceCalls &shaderProgramRestoreCalls =
                trackedShaderPrograms.getResourceRestoreCalls();

            // If we have any new shaders or programs created and not deleted during the run, delete
            // them now
            for (const GLuint &newShaderProgram : newShaderPrograms)
            {
                if (resourceTracker->getShaderProgramType({newShaderProgram}) ==
                    ShaderProgramType::ShaderType)
                {
                    out << "    glDeleteShader(gShaderProgramMap[" << newShaderProgram << "]);\n";
                }
                else
                {
                    ASSERT(resourceTracker->getShaderProgramType({newShaderProgram}) ==
                           ShaderProgramType::ProgramType);
                    out << "    glDeleteProgram(gShaderProgramMap[" << newShaderProgram << "]);\n";
                }
            }

            // Do the same for shaders/programs to be deleted
            for (const GLuint &shaderProgramToDelete : shaderProgramsToDelete)
            {
                if (resourceTracker->getShaderProgramType({shaderProgramToDelete}) ==
                    ShaderProgramType::ShaderType)
                {
                    out << "    glDeleteShader(gShaderProgramMap[" << shaderProgramToDelete
                        << "]);\n";
                }
                else
                {
                    ASSERT(resourceTracker->getShaderProgramType({shaderProgramToDelete}) ==
                           ShaderProgramType::ProgramType);
                    out << "    glDeleteProgram(gShaderProgramMap[" << shaderProgramToDelete
                        << "]);\n";
                }
            }

            for (const GLuint id : shaderProgramsToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : shaderProgramRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            for (const GLuint id : shaderProgramsToRestore)
            {
                // Emit their restore calls
                for (CallCapture &call : shaderProgramRestoreCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            break;
        }
        case ResourceIDType::Texture:
        {
            TrackedResource &trackedTextures =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::Texture);
            ResourceSet &newTextures           = trackedTextures.getNewResources();
            ResourceSet &texturesToDelete      = trackedTextures.getResourcesToDelete();
            ResourceSet &texturesToRegen       = trackedTextures.getResourcesToRegen();
            ResourceCalls &textureRegenCalls   = trackedTextures.getResourceRegenCalls();
            ResourceCalls &textureRestoreCalls = trackedTextures.getResourceRestoreCalls();

            DeleteResourcesInReset(out, contextID, newTextures, texturesToDelete, resourceIDType,
                                   maxResourceIDBufferSize);

            // If any of our starting textures were deleted, regen them
            for (GLuint id : texturesToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : textureRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            // If any of our starting textures were modified during the run, restore their contents
            ResourceSet &texturesToRestore = trackedTextures.getResourcesToRestore();

            // Do some setup if we have any textures to restore
            if (texturesToRestore.size() != 0)
            {
                // We need to unbind PIXEL_UNPACK_BUFFER before restoring textures
                // The correct binding will be restored in context state reset
                gl::Context *context = display->getContext(contextID);
                if (context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack))
                {
                    out << "    // Clearing PIXEL_UNPACK_BUFFER binding for texture restore\n";
                    out << "    ";
                    WriteCppReplayForCall(CaptureBindBuffer(context->getState(), true,
                                                            gl::BufferBinding::PixelUnpack, {0}),
                                          replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            for (GLuint id : texturesToRestore)
            {
                // Emit their restore calls
                for (CallCapture &call : textureRestoreCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }
            break;
        }
        case ResourceIDType::VertexArray:
        {
            TrackedResource &trackedVertexArrays =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::VertexArray);
            ResourceSet &newVertexArrays           = trackedVertexArrays.getNewResources();
            ResourceSet &vertexArraysToDelete      = trackedVertexArrays.getResourcesToDelete();
            ResourceSet &vertexArraysToRegen       = trackedVertexArrays.getResourcesToRegen();
            ResourceSet &vertexArraysToRestore     = trackedVertexArrays.getResourcesToRestore();
            ResourceCalls &vertexArrayRegenCalls   = trackedVertexArrays.getResourceRegenCalls();
            ResourceCalls &vertexArrayRestoreCalls = trackedVertexArrays.getResourceRestoreCalls();

            DeleteResourcesInReset(out, contextID, newVertexArrays, vertexArraysToDelete,
                                   resourceIDType, maxResourceIDBufferSize);

            // If any of our starting vertex arrays were deleted during the run, recreate them
            for (GLuint id : vertexArraysToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : vertexArrayRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }

            // If any of our starting vertex arrays were modified during the run, restore their
            // contents
            for (GLuint id : vertexArraysToRestore)
            {
                // Emit their restore calls
                for (CallCapture &call : vertexArrayRestoreCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }
            break;
        }
        case ResourceIDType::egl_Sync:
        {
            TrackedResource &trackedEGLSyncs =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::egl_Sync);
            ResourceSet &newEGLSyncs         = trackedEGLSyncs.getNewResources();
            ResourceSet &eglSyncsToDelete    = trackedEGLSyncs.getResourcesToDelete();
            ResourceSet &eglSyncsToRegen     = trackedEGLSyncs.getResourcesToRegen();
            ResourceCalls &eglSyncRegenCalls = trackedEGLSyncs.getResourceRegenCalls();

            if (!newEGLSyncs.empty() || !eglSyncsToDelete.empty())
            {
                for (GLuint oldResource : eglSyncsToDelete)
                {
                    out << "    eglDestroySyncKHR(gEGLDisplay, gEGLSyncMap[" << oldResource
                        << "]);\n";
                }

                for (GLuint newResource : newEGLSyncs)
                {
                    out << "    eglDestroySyncKHR(gEGLDisplay, gEGLSyncMap[" << newResource
                        << "]);\n";
                }
            }

            // If any of our starting EGLsyncs were deleted during the run, recreate them
            for (GLuint id : eglSyncsToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : eglSyncRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }
            break;
        }
        case ResourceIDType::Image:
        {
            TrackedResource &trackedEGLImages =
                resourceTracker->getTrackedResource(contextID, ResourceIDType::Image);
            ResourceSet &newEGLImages         = trackedEGLImages.getNewResources();
            ResourceSet &eglImagesToDelete    = trackedEGLImages.getResourcesToDelete();
            ResourceSet &eglImagesToRegen     = trackedEGLImages.getResourcesToRegen();
            ResourceCalls &eglImageRegenCalls = trackedEGLImages.getResourceRegenCalls();

            if (!newEGLImages.empty() || !eglImagesToDelete.empty())
            {
                for (GLuint oldResource : eglImagesToDelete)
                {
                    out << "    DestroyEGLImageKHR(gEGLDisplay, gEGLImageMap2[" << oldResource
                        << "], " << oldResource << ");\n";
                }

                for (GLuint newResource : newEGLImages)
                {
                    out << "    DestroyEGLImageKHR(gEGLDisplay, gEGLImageMap2[" << newResource
                        << "], " << newResource << ");\n";
                }
            }
            // If any of our starting EGLImages were deleted during the run, recreate them
            for (GLuint id : eglImagesToRegen)
            {
                // Emit their regen calls
                for (CallCapture &call : eglImageRegenCalls[id])
                {
                    out << "    ";
                    WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                          maxResourceIDBufferSize);
                    out << ";\n";
                }
            }
            break;
        }
        default:
            // TODO (http://anglebug.com/42263204): Reset more resource types
            break;
    }

    // If the output position has moved, we Reset something
    anyResourceReset = (initialOutPos != out.tellp());
}

void MaybeResetFenceSyncObjects(std::stringstream &out,
                                ReplayWriter &replayWriter,
                                std::stringstream &header,
                                ResourceTracker *resourceTracker,
                                FrameCaptureBinaryData *binaryData,
                                size_t *maxResourceIDBufferSize)
{
    FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls();

    // If any of our starting fence sync objects were deleted during the run, recreate them
    FenceSyncSet &fenceSyncsToRegen = resourceTracker->getFenceSyncsToRegen();
    for (const gl::SyncID syncID : fenceSyncsToRegen)
    {
        // Emit their regen calls
        for (CallCapture &call : fenceSyncRegenCalls[syncID])
        {
            out << "    ";
            WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                  maxResourceIDBufferSize);
            out << ";\n";
        }
    }
}

// Emit external-texture EGLImage rebinds for any bindings this context changed
// during capture. Per-context placement ensures each glEGLImageTargetTexture2DOES
// runs with the originating context current, so the rebind scopes correctly
void MaybeResetEGLImageBindings(gl::ContextID contextID,
                                std::stringstream &resetStream,
                                ResourceTracker *resourceTracker,
                                bool *anyResourceReset)
{
    auto imageBinding = resourceTracker->getExternalImageBindingsToRestore().find(contextID);
    if (imageBinding != resourceTracker->getExternalImageBindingsToRestore().end() &&
        !imageBinding->second.empty())
    {
        const std::map<GLuint, egl::ImageID> &textureIDToImageTable =
            resourceTracker->getTextureIDToImageTable();
        for (GLuint textureID : imageBinding->second)
        {
            auto imageBindingMap = textureIDToImageTable.find(textureID);
            if (imageBindingMap != textureIDToImageTable.end())
            {
                resetStream << "    glBindTexture(GL_TEXTURE_EXTERNAL_OES, "
                               "gTextureMap["
                            << textureID << "]);\n";
                resetStream << "    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, "
                               "gEGLImageMap2["
                            << imageBindingMap->second.value << "]);\n";
                *anyResourceReset = true;
            }
        }
    }
}

void Capture(std::vector<CallCapture> *setupCalls, CallCapture &&call)
{
    setupCalls->emplace_back(std::move(call));
}

void CaptureUpdateCurrentContext(gl::ContextID contextID, std::vector<CallCapture> *callsOut)
{
    ParamBuffer paramBuffer;
    paramBuffer.addValueParam("context", ParamType::TGLuint, contextID.value);

    callsOut->emplace_back("UpdateCurrentContext", std::move(paramBuffer));
}

void CaptureUpdateCurrentProgram(const CallCapture &call,
                                 int programParamPos,
                                 std::vector<CallCapture> *callsOut)
{
    const ParamCapture &param =
        call.params.getParam("programPacked", ParamType::TShaderProgramID, programParamPos);
    gl::ShaderProgramID programID = param.value.ShaderProgramIDVal;

    ParamBuffer paramBuffer;
    paramBuffer.addValueParam("program", ParamType::TGLuint, programID.value);

    callsOut->emplace_back("UpdateCurrentProgramPerContext", std::move(paramBuffer));
}

bool ProgramNeedsReset(const gl::Context *context,
                       ResourceTracker *resourceTracker,
                       gl::ShaderProgramID programID)
{
    // Check whether the program is listed in programs to regen or restore
    TrackedResource &trackedShaderPrograms =
        resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram);

    ResourceSet &shaderProgramsToRegen = trackedShaderPrograms.getResourcesToRegen();
    if (shaderProgramsToRegen.count(programID.value) != 0)
    {
        return true;
    }

    ResourceSet &shaderProgramsToRestore = trackedShaderPrograms.getResourcesToRestore();
    if (shaderProgramsToRestore.count(programID.value) != 0)
    {
        return true;
    }

    // Deferred linked programs will also update their own uniforms
    FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
    if (frameCaptureShared->isDeferredLinkProgram(programID))
    {
        return true;
    }

    return false;
}

void MaybeResetDefaultUniforms(std::stringstream &out,
                               ReplayWriter &replayWriter,
                               std::stringstream &header,
                               const gl::Context *context,
                               ResourceTracker *resourceTracker,
                               FrameCaptureBinaryData *binaryData,
                               size_t *maxResourceIDBufferSize)
{
    DefaultUniformLocationsPerProgramMap &defaultUniformsToReset =
        resourceTracker->getDefaultUniformsToReset();

    for (const auto &uniformIter : defaultUniformsToReset)
    {
        gl::ShaderProgramID programID               = uniformIter.first;
        const DefaultUniformLocationsSet &locations = uniformIter.second;

        if (ProgramNeedsReset(context, resourceTracker, programID))
        {
            // Skip programs marked for reset as they will update their own uniforms
            return;
        }

        // Bind the program to update its uniforms
        std::vector<CallCapture> bindCalls;
        Capture(&bindCalls, CaptureUseProgram(context->getState(), true, programID));
        CaptureUpdateCurrentProgram((&bindCalls)->back(), 0, &bindCalls);
        for (CallCapture &call : bindCalls)
        {
            out << "    ";
            WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                  maxResourceIDBufferSize);
            out << ";\n";
        }

        DefaultUniformCallsPerLocationMap &defaultUniformResetCalls =
            resourceTracker->getDefaultUniformResetCalls(programID);

        // Uniform arrays might have been modified in the middle (i.e. location 5 out of 10)
        // We only have Reset calls for the entire array, so emit them once for the entire array
        std::set<gl::UniformLocation> alreadyReset;

        // Emit the reset calls per modified location
        for (const gl::UniformLocation &location : locations)
        {
            // If location is equal to -1, the data passed in will be silently ignored and the
            // specified uniform variable will not be changed
            if (location.value == -1)
            {
                continue;
            }
            gl::UniformLocation baseLocation =
                resourceTracker->getDefaultUniformBaseLocation(programID, location);
            if (alreadyReset.find(baseLocation) != alreadyReset.end())
            {
                // We've already Reset this array
                continue;
            }
            alreadyReset.insert(baseLocation);

            ASSERT(defaultUniformResetCalls.find(baseLocation) != defaultUniformResetCalls.end());
            std::vector<CallCapture> &callsPerLocation = defaultUniformResetCalls[baseLocation];

            for (CallCapture &call : callsPerLocation)
            {
                out << "    ";
                WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                      maxResourceIDBufferSize);
                out << ";\n";
            }
        }
    }
}

void MaybeResetOpaqueTypeObjects(ReplayWriter &replayWriter,
                                 std::stringstream &out,
                                 std::stringstream &header,
                                 const gl::Context *context,
                                 ResourceTracker *resourceTracker,
                                 FrameCaptureBinaryData *binaryData,
                                 size_t *maxResourceIDBufferSize)
{
    MaybeResetFenceSyncObjects(out, replayWriter, header, resourceTracker, binaryData,
                               maxResourceIDBufferSize);

    MaybeResetDefaultUniforms(out, replayWriter, header, context, resourceTracker, binaryData,
                              maxResourceIDBufferSize);
}

void MaybeResetContextState(ReplayWriter &replayWriter,
                            std::stringstream &out,
                            std::stringstream &header,
                            ResourceTracker *resourceTracker,
                            const gl::Context *context,
                            FrameCaptureBinaryData *binaryData,
                            StateResetHelper &stateResetHelper,
                            size_t *maxResourceIDBufferSize)
{
    // Check dirty states per entrypoint
    for (const EntryPoint &entryPoint : stateResetHelper.getDirtyEntryPoints())
    {
        const CallResetMap *resetCalls = &stateResetHelper.getResetCalls();

        // Create the default reset call for this entrypoint
        if (resetCalls->find(entryPoint) == resetCalls->end())
        {
            // If we don't have any reset calls for these entrypoints, that means we started capture
            // from the beginning, amd mid-execution capture was not invoked.
            stateResetHelper.setDefaultResetCalls(context, entryPoint);
        }

        // Emit the calls, if we added any
        if (resetCalls->find(entryPoint) != resetCalls->end())
        {
            for (const auto &call : resetCalls->at(entryPoint))
            {
                out << "    ";
                WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                      maxResourceIDBufferSize);
                out << ";\n";
            }
        }
    }

    // Reset buffer bindings that weren't bound at the beginning
    for (const gl::BufferBinding &dirtyBufferBinding : stateResetHelper.getDirtyBufferBindings())
    {
        // Check to see if dirty binding was part of starting set
        bool dirtyStartingBinding = false;
        for (const BufferBindingPair &startingBufferBinding :
             stateResetHelper.getStartingBufferBindings())
        {
            gl::BufferBinding startingBinding = startingBufferBinding.first;
            if (startingBinding == dirtyBufferBinding)
            {
                dirtyStartingBinding = true;
            }
        }

        // If the dirty binding was not part of starting bindings, clear it
        if (!dirtyStartingBinding)
        {
            out << "    ";
            WriteCppReplayForCall(
                CaptureBindBuffer(context->getState(), true, dirtyBufferBinding, {0}), replayWriter,
                out, header, binaryData, maxResourceIDBufferSize);
            out << ";\n";
        }
    }

    // Restore starting buffer bindings to initial state
    std::vector<CallCapture> &bufferBindingCalls = resourceTracker->getBufferBindingCalls();
    for (CallCapture &call : bufferBindingCalls)
    {
        out << "    ";
        WriteCppReplayForCall(call, replayWriter, out, header, binaryData, maxResourceIDBufferSize);
        out << ";\n";
    }

    // Restore texture bindings to initial state
    size_t activeTexture                 = context->getState().getActiveSampler();
    const TextureResetMap &resetBindings = stateResetHelper.getResetTextureBindings();
    for (const auto &textureBinding : stateResetHelper.getDirtyTextureBindings())
    {
        TextureResetMap::const_iterator id = resetBindings.find(textureBinding);
        if (id != resetBindings.end())
        {
            const auto &[unit, target] = textureBinding;

            // Set active texture unit if necessary
            if (unit != activeTexture)
            {
                out << "    ";
                WriteCppReplayForCall(CaptureActiveTexture(context->getState(), true,
                                                           GL_TEXTURE0 + static_cast<GLenum>(unit)),
                                      replayWriter, out, header, binaryData,
                                      maxResourceIDBufferSize);
                out << ";\n";
                activeTexture = unit;
            }

            // Bind texture for this target
            out << "    ";
            WriteCppReplayForCall(CaptureBindTexture(context->getState(), true, target, id->second),
                                  replayWriter, out, header, binaryData, maxResourceIDBufferSize);
            out << ";\n";
        }
    }

    // Restore active texture unit to initial state if necessary
    if (activeTexture != stateResetHelper.getResetActiveTexture())
    {
        out << "    ";
        WriteCppReplayForCall(
            CaptureActiveTexture(
                context->getState(), true,
                GL_TEXTURE0 + static_cast<GLenum>(stateResetHelper.getResetActiveTexture())),
            replayWriter, out, header, binaryData, maxResourceIDBufferSize);
        out << ";\n";
    }
}

void MarkResourceIDActive(ResourceIDType resourceType,
                          GLuint id,
                          std::vector<CallCapture> *setupCalls,
                          const ResourceIDToSetupCallsMap *resourceIDToSetupCallsMap)
{
    const std::map<GLuint, gl::Range<size_t>> &resourceSetupCalls =
        (*resourceIDToSetupCallsMap)[resourceType];
    const auto iter = resourceSetupCalls.find(id);
    if (iter == resourceSetupCalls.end())
    {
        return;
    }

    // Mark all of the calls that were used to initialize this resource as ACTIVE
    const gl::Range<size_t> &calls = iter->second;
    for (size_t index : calls)
    {
        (*setupCalls)[index].isActive = true;
    }
}

// Some replay functions can get quite large. If over a certain size, this method breaks up the
// function into parts to avoid overflowing the stack and causing slow compilation.
void WriteCppReplayFunctionWithParts(const gl::ContextID contextID,
                                     ReplayFunc replayFunc,
                                     ReplayWriter &replayWriter,
                                     uint32_t frameIndex,
                                     FrameCaptureBinaryData *binaryData,
                                     const std::vector<CallCapture> &calls,
                                     std::stringstream &header,
                                     std::stringstream &out,
                                     size_t *maxResourceIDBufferSize)
{
    int callCount = 0;
    int partCount = 0;

    if (calls.size() > kFunctionSizeLimit)
    {
        out << "void "
            << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, ++partCount)
            << "\n";
    }
    else
    {
        out << "void "
            << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
            << "\n";
    }

    out << "{\n";

    for (const CallCapture &call : calls)
    {
        // Process active calls for Setup and inactive calls for SetupInactive
        if ((call.isActive && replayFunc != ReplayFunc::SetupInactive) ||
            (!call.isActive && replayFunc == ReplayFunc::SetupInactive))
        {
            out << "    ";
            WriteCppReplayForCall(call, replayWriter, out, header, binaryData,
                                  maxResourceIDBufferSize);
            out << ";\n";

            if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
            {
                out << "}\n";
                out << "\n";
                out << "void "
                    << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex,
                                   ++partCount)
                    << "\n";
                out << "{\n";
            }
        }
    }
    out << "}\n";

    if (partCount > 0)
    {
        out << "\n";
        out << "void "
            << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
            << "\n";
        out << "{\n";

        // Write out the main call which calls all the parts.
        for (int i = 1; i <= partCount; i++)
        {
            out << "    " << FmtFunction(replayFunc, contextID, FuncUsage::Call, frameIndex, i)
                << ";\n";
        }

        out << "}\n";
    }
}

// Performance can be gained by reordering traced calls and grouping them by context.
// Side context calls (as opposed to main context) can be grouped together paying attention
// to synchronization points in the original call stream.
void WriteCppReplayFunctionWithPartsMultiContext(const gl::ContextID contextID,
                                                 ReplayFunc replayFunc,
                                                 ReplayWriter &replayWriter,
                                                 uint32_t frameIndex,
                                                 FrameCaptureBinaryData *binaryData,
                                                 std::vector<CallCapture> &calls,
                                                 std::stringstream &header,
                                                 std::stringstream &out,
                                                 size_t *maxResourceIDBufferSize)
{
    int callCount = 0;
    int partCount = 0;

    if (calls.size() > kFunctionSizeLimit)
    {
        out << "void "
            << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, ++partCount)
            << "\n";
    }
    else
    {
        out << "void "
            << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
            << "\n";
    }

    out << "{\n";

    std::map<gl::ContextID, std::queue<int>> sideContextCallIndices;

    // Helper lambda to write a context change command to the call stream
    auto writeMakeCurrentCall = [&](gl::ContextID cID) {
        CallCapture makeCurrentCall =
            egl::CaptureMakeCurrent(nullptr, true, nullptr, {0}, {0}, cID, EGL_TRUE);
        out << "    ";
        WriteCppReplayForCall(makeCurrentCall, replayWriter, out, header, binaryData,
                              maxResourceIDBufferSize);
        out << ";\n";
        callCount++;
        std::vector<CallCapture> updateCurrentContextCall;
        CaptureUpdateCurrentContext(cID, &updateCurrentContextCall);
        out << "    ";
        WriteCppReplayForCall(updateCurrentContextCall[0], replayWriter, out, header, binaryData,
                              maxResourceIDBufferSize);
        out << ";\n";
        callCount++;
    };

    // Helper lambda to write a call to the call stream
    auto writeCall = [&](CallCapture &outCall, gl::ContextID cID) {
        out << "    ";
        WriteCppReplayForCall(outCall, replayWriter, out, header, binaryData,
                              maxResourceIDBufferSize);
        out << ";\n";
        if (cID != contextID)
        {
            sideContextCallIndices[cID].pop();
        }
        callCount++;
    };

    int callIndex = 0;
    // Iterate through calls saving side context call indices in a per-side-context queue
    for (CallCapture &call : calls)
    {
        if (call.contextID != contextID)
        {
            sideContextCallIndices[call.contextID].push(callIndex);
        }
        callIndex++;
    }

    // At the beginning of the frame, output all side context calls occuring before a sync point.
    // If no sync points are present, all calls in that side context are written at this time
    for (auto const &sideContext : sideContextCallIndices)
    {
        gl::ContextID sideContextID = sideContext.first;

        // Make sidecontext current if there are commands before the first syncpoint
        if (!calls[sideContextCallIndices[sideContextID].front()].isSyncPoint)
        {
            writeMakeCurrentCall(sideContextID);
        }
        // Output all commands in sidecontext until a syncpoint is reached
        while (!sideContextCallIndices[sideContextID].empty() &&
               !calls[sideContextCallIndices[sideContextID].front()].isSyncPoint)
        {
            writeCall(calls[sideContextCallIndices[sideContextID].front()], sideContextID);
        }
    }

    // Make mainContext current
    writeMakeCurrentCall(contextID);

    // Iterate through calls writing out main context calls. When a sync point is reached, write the
    // next queued sequence of side context calls until another sync point is reached.
    for (CallCapture &call : calls)
    {
        if (call.contextID == contextID)
        {
            writeCall(call, call.contextID);
        }
        else
        {
            if (call.isSyncPoint)
            {
                // Make sideContext current
                writeMakeCurrentCall(call.contextID);

                do
                {
                    writeCall(calls[sideContextCallIndices[call.contextID].front()],
                              call.contextID);
                } while (!sideContextCallIndices[call.contextID].empty() &&
                         !calls[sideContextCallIndices[call.contextID].front()].isSyncPoint);

                // Make mainContext current
                writeMakeCurrentCall(contextID);

                if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
                {
                    out << "}\n";
                    out << "\n";
                    out << "void "
                        << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex,
                                       ++partCount)
                        << "\n";
                    out << "{\n";
                }
            }
        }
    }
    out << "}\n";

    if (partCount > 0)
    {
        out << "\n";
        out << "void "
            << FmtFunction(replayFunc, contextID, FuncUsage::Definition, frameIndex, kNoPartId)
            << "\n";
        out << "{\n";

        // Write out the main call which calls all the parts.
        for (int i = 1; i <= partCount; i++)
        {
            out << "    " << FmtFunction(replayFunc, contextID, FuncUsage::Call, frameIndex, i)
                << ";\n";
        }

        out << "}\n";
    }
}

// Auxiliary contexts are other contexts in the share group that aren't the context calling
// eglSwapBuffers().
void WriteAuxiliaryContextCppSetupReplay(ReplayWriter &replayWriter,
                                         bool compression,
                                         const std::string &outDir,
                                         const gl::Context *context,
                                         const std::string &captureLabel,
                                         uint32_t frameIndex,
                                         const std::vector<CallCapture> &setupCalls,
                                         FrameCaptureBinaryData *binaryData,
                                         bool serializeStateEnabled,
                                         const FrameCaptureShared &frameCaptureShared,
                                         size_t *maxResourceIDBufferSize)
{
    ASSERT(frameCaptureShared.getWindowSurfaceContextID() != context->id());

    {
        std::stringstream filenameStream;
        filenameStream << outDir << FmtCapturePrefix(context->id(), captureLabel);
        std::string filenamePattern = filenameStream.str();
        replayWriter.setFilenamePattern(filenamePattern);
    }

    {
        std::stringstream include;
        include << "#include \""
                << FmtCapturePrefix(frameCaptureShared.getWindowSurfaceContextID(), captureLabel)
                << ".h\"\n";
        include << "#include \"angle_trace_gl.h\"\n";

        std::string frameIncludes = include.str();
        replayWriter.setSourcePrologue(frameIncludes);
        replayWriter.setHeaderPrologue(frameIncludes);
    }

    {
        std::stringstream protoStream;
        std::stringstream headerStream;
        std::stringstream bodyStream;

        protoStream << "void " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Prototype);
        std::string proto = protoStream.str();

        WriteCppReplayFunctionWithParts(context->id(), ReplayFunc::Setup, replayWriter, frameIndex,
                                        binaryData, setupCalls, headerStream, bodyStream,
                                        maxResourceIDBufferSize);

        replayWriter.addPrivateFunction(proto, headerStream, bodyStream);
    }

    replayWriter.saveFrame();
}

void WriteShareGroupCppSetupReplay(ReplayWriter &replayWriter,
                                   bool compression,
                                   const std::string &outDir,
                                   const std::string &captureLabel,
                                   uint32_t frameIndex,
                                   uint32_t frameCount,
                                   const std::vector<CallCapture> &setupCalls,
                                   ResourceTracker *resourceTracker,
                                   FrameCaptureBinaryData *binaryData,
                                   bool serializeStateEnabled,
                                   gl::ContextID windowSurfaceContextID,
                                   size_t *maxResourceIDBufferSize)
{
    {

        std::stringstream include;

        include << "#include \"angle_trace_gl.h\"\n";
        include << "#include \"" << FmtCapturePrefix(windowSurfaceContextID, captureLabel)
                << ".h\"\n";

        std::string includeString = include.str();

        replayWriter.setSourcePrologue(includeString);
    }

    {
        std::stringstream protoStream;
        std::stringstream headerStream;
        std::stringstream bodyStream;

        protoStream << "void "
                    << FmtSetupFunction(kNoPartId, kSharedContextId, FuncUsage::Prototype);
        std::string proto = protoStream.str();

        WriteCppReplayFunctionWithParts(kSharedContextId, ReplayFunc::Setup, replayWriter,
                                        frameIndex, binaryData, setupCalls, headerStream,
                                        bodyStream, maxResourceIDBufferSize);

        replayWriter.addPrivateFunction(proto, headerStream, bodyStream);

        protoStream.str("");
        headerStream.str("");
        bodyStream.str("");
        protoStream << "void "
                    << FmtSetupInactiveFunction(kNoPartId, kSharedContextId, FuncUsage::Prototype);
        proto = protoStream.str();

        WriteCppReplayFunctionWithParts(kSharedContextId, ReplayFunc::SetupInactive, replayWriter,
                                        frameIndex, binaryData, setupCalls, headerStream,
                                        bodyStream, maxResourceIDBufferSize);
        replayWriter.addPrivateFunction(proto, headerStream, bodyStream);
    }

    {
        std::stringstream filenameStream;
        filenameStream << outDir << FmtCapturePrefix(kSharedContextId, captureLabel);

        std::string filenamePattern = filenameStream.str();

        replayWriter.setFilenamePattern(filenamePattern);
    }

    replayWriter.saveSetupFile();
}

ProgramSources GetAttachedProgramSources(const gl::Context *context, const gl::Program *program)
{
    ProgramSources sources;
    for (gl::ShaderType shaderType : gl::AllShaderTypes())
    {
        const gl::Shader *shader = program->getAttachedShader(shaderType);
        if (shader)
        {
            sources[shaderType] = shader->getSourceString();
        }
    }
    return sources;
}

template <typename IDType>
void CaptureUpdateResourceIDs(const gl::Context *context,
                              const CallCapture &call,
                              const ParamCapture &param,
                              ResourceTracker *resourceTracker,
                              std::vector<CallCapture> *callsOut)
{
    GLsizei n = call.params.getParamFlexName("n", "count", ParamType::TGLsizei, 0).value.GLsizeiVal;
    ASSERT(param.data.size() == 1);
    ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(param.type);
    ASSERT(resourceIDType != ResourceIDType::InvalidEnum &&
           resourceIDType != ResourceIDType::ShaderProgram);
    const char *resourceName = GetResourceIDTypeName(resourceIDType);

    std::stringstream updateFuncNameStr;
    updateFuncNameStr << "Update" << resourceName << "ID";
    bool trackedPerContext = IsTrackedPerContext(resourceIDType);
    if (trackedPerContext)
    {
        // TODO (https://issuetracker.google.com/169868803) The '2' version can be removed after all
        // context-local objects are tracked per-context
        updateFuncNameStr << "2";
    }
    std::string updateFuncName = updateFuncNameStr.str();

    const IDType *returnedIDs = reinterpret_cast<const IDType *>(param.data[0].data());

    ResourceSet &startingSet =
        resourceTracker->getTrackedResource(context->id(), resourceIDType).getStartingResources();

    for (GLsizei idIndex = 0; idIndex < n; ++idIndex)
    {
        IDType id                = returnedIDs[idIndex];
        GLsizei readBufferOffset = idIndex * sizeof(gl::RenderbufferID);
        ParamBuffer params;
        if (trackedPerContext)
        {
            params.addValueParam("contextId", ParamType::TGLuint, context->id().value);
        }
        params.addValueParam("id", ParamType::TGLuint, id.value);
        params.addValueParam("readBufferOffset", ParamType::TGLsizei, readBufferOffset);
        callsOut->emplace_back(updateFuncName, std::move(params));

        // Add only if not in starting resources.
        if (startingSet.find(id.value) == startingSet.end())
        {
            resourceTracker->getTrackedResource(context->id(), resourceIDType)
                .getNewResources()
                .insert(id.value);
        }
    }
}

void CaptureUpdateUniformLocations(const gl::Program *program, std::vector<CallCapture> *callsOut)
{
    const gl::ProgramExecutable &executable            = program->getExecutable();
    const std::vector<gl::LinkedUniform> &uniforms     = executable.getUniforms();
    const std::vector<gl::VariableLocation> &locations = executable.getUniformLocations();

    for (GLint location = 0; location < static_cast<GLint>(locations.size()); ++location)
    {
        const gl::VariableLocation &locationVar = locations[location];

        // This handles the case where the application calls glBindUniformLocationCHROMIUM
        // on an unused uniform. We must still store a -1 into gUniformLocations in case the
        // application attempts to call a glUniform* call. To do this we'll pass in a blank name to
        // force glGetUniformLocation to return -1.
        std::string name;
        int count = 1;
        ParamBuffer params;
        params.addValueParam("program", ParamType::TGLuint, program->id().value);

        if (locationVar.index >= uniforms.size())
        {
            name = "";
        }
        else
        {
            const gl::LinkedUniform &uniform = uniforms[locationVar.index];

            name = executable.getUniformNameByIndex(locationVar.index);

            if (uniform.isArray())
            {
                if (locationVar.arrayIndex > 0)
                {
                    // Non-sequential array uniform locations are not currently handled.
                    // In practice array locations shouldn't ever be non-sequential.
                    ASSERT(uniform.getLocation() == -1 ||
                           location ==
                               uniform.getLocation() + static_cast<int>(locationVar.arrayIndex));
                    continue;
                }

                name  = gl::StripLastArrayIndex(name);
                count = uniform.getBasicTypeElementCount();
            }
        }

        ParamCapture nameParam("name", ParamType::TGLcharConstPointer);
        CaptureString(name.c_str(), &nameParam);
        params.addParam(std::move(nameParam));
        params.addValueParam("location", ParamType::TGLint, location);
        params.addValueParam("count", ParamType::TGLint, static_cast<GLint>(count));
        callsOut->emplace_back("UpdateUniformLocation", std::move(params));
    }
}

void CaptureValidateSerializedState(const gl::Context *context, std::vector<CallCapture> *callsOut)
{
    INFO() << "Capturing validation checkpoint at position " << callsOut->size();

    context->finishImmutable();

    std::string serializedState;
    angle::Result result = angle::SerializeContextToString(context, &serializedState);
    if (result != angle::Result::Continue)
    {
        ERR() << "Internal error serializing context state.";
        return;
    }
    ParamCapture serializedStateParam("serializedState", ParamType::TGLcharConstPointer);
    CaptureString(serializedState.c_str(), &serializedStateParam);

    ParamBuffer params;
    params.addParam(std::move(serializedStateParam));

    callsOut->emplace_back("VALIDATE_CHECKPOINT", std::move(params));
}

void CaptureUpdateUniformBlockIndexes(const gl::Program *program,
                                      std::vector<CallCapture> *callsOut)
{
    const std::vector<gl::InterfaceBlock> &uniformBlocks =
        program->getExecutable().getUniformBlocks();

    for (GLuint index = 0; index < uniformBlocks.size(); ++index)
    {
        ParamBuffer params;

        std::string name;
        params.addValueParam("program", ParamType::TShaderProgramID, program->id());

        const std::string fullName = uniformBlocks[index].nameWithArrayIndex();
        ParamCapture nameParam("name", ParamType::TGLcharConstPointer);
        CaptureString(fullName.c_str(), &nameParam);
        params.addParam(std::move(nameParam));

        params.addValueParam("index", ParamType::TGLuint, index);
        callsOut->emplace_back("UpdateUniformBlockIndex", std::move(params));
    }
}

void CaptureDeleteUniformLocations(gl::ShaderProgramID program, std::vector<CallCapture> *callsOut)
{
    ParamBuffer params;
    params.addValueParam("program", ParamType::TShaderProgramID, program);
    callsOut->emplace_back("DeleteUniformLocations", std::move(params));
}

void MaybeCaptureUpdateResourceIDs(const gl::Context *context,
                                   ResourceTracker *resourceTracker,
                                   std::vector<CallCapture> *callsOut)
{
    const CallCapture &call = callsOut->back();

    switch (call.entryPoint)
    {
        case EntryPoint::GLGenBuffers:
        {
            const ParamCapture &buffers =
                call.params.getParam("buffersPacked", ParamType::TBufferIDPointer, 1);
            CaptureUpdateResourceIDs<gl::BufferID>(context, call, buffers, resourceTracker,
                                                   callsOut);
            break;
        }

        case EntryPoint::GLGenFencesNV:
        {
            const ParamCapture &fences =
                call.params.getParam("fencesPacked", ParamType::TFenceNVIDPointer, 1);
            CaptureUpdateResourceIDs<gl::FenceNVID>(context, call, fences, resourceTracker,
                                                    callsOut);
            break;
        }

        case EntryPoint::GLGenFramebuffers:
        case EntryPoint::GLGenFramebuffersOES:
        {
            const ParamCapture &framebuffers =
                call.params.getParam("framebuffersPacked", ParamType::TFramebufferIDPointer, 1);
            CaptureUpdateResourceIDs<gl::FramebufferID>(context, call, framebuffers,
                                                        resourceTracker, callsOut);
            break;
        }

        case EntryPoint::GLGenProgramPipelines:
        {
            const ParamCapture &pipelines =
                call.params.getParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer, 1);
            CaptureUpdateResourceIDs<gl::ProgramPipelineID>(context, call, pipelines,
                                                            resourceTracker, callsOut);
            break;
        }

        case EntryPoint::GLGenQueries:
        case EntryPoint::GLGenQueriesEXT:
        {
            const ParamCapture &queries =
                call.params.getParam("idsPacked", ParamType::TQueryIDPointer, 1);
            CaptureUpdateResourceIDs<gl::QueryID>(context, call, queries, resourceTracker,
                                                  callsOut);
            break;
        }

        case EntryPoint::GLGenRenderbuffers:
        case EntryPoint::GLGenRenderbuffersOES:
        {
            const ParamCapture &renderbuffers =
                call.params.getParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer, 1);
            CaptureUpdateResourceIDs<gl::RenderbufferID>(context, call, renderbuffers,
                                                         resourceTracker, callsOut);
            break;
        }

        case EntryPoint::GLGenSamplers:
        {
            const ParamCapture &samplers =
                call.params.getParam("samplersPacked", ParamType::TSamplerIDPointer, 1);
            CaptureUpdateResourceIDs<gl::SamplerID>(context, call, samplers, resourceTracker,
                                                    callsOut);
            break;
        }

        case EntryPoint::GLGenSemaphoresEXT:
        {
            const ParamCapture &semaphores =
                call.params.getParam("semaphoresPacked", ParamType::TSemaphoreIDPointer, 1);
            CaptureUpdateResourceIDs<gl::SemaphoreID>(context, call, semaphores, resourceTracker,
                                                      callsOut);
            break;
        }

        case EntryPoint::GLGenTextures:
        {
            const ParamCapture &textures =
                call.params.getParam("texturesPacked", ParamType::TTextureIDPointer, 1);
            CaptureUpdateResourceIDs<gl::TextureID>(context, call, textures, resourceTracker,
                                                    callsOut);
            break;
        }

        case EntryPoint::GLGenTransformFeedbacks:
        {
            const ParamCapture &xfbs =
                call.params.getParam("idsPacked", ParamType::TTransformFeedbackIDPointer, 1);
            CaptureUpdateResourceIDs<gl::TransformFeedbackID>(context, call, xfbs, resourceTracker,
                                                              callsOut);
            break;
        }

        case EntryPoint::GLGenVertexArrays:
        case EntryPoint::GLGenVertexArraysOES:
        {
            const ParamCapture &vertexArrays =
                call.params.getParam("arraysPacked", ParamType::TVertexArrayIDPointer, 1);
            CaptureUpdateResourceIDs<gl::VertexArrayID>(context, call, vertexArrays,
                                                        resourceTracker, callsOut);
            break;
        }

        case EntryPoint::GLCreateMemoryObjectsEXT:
        {
            const ParamCapture &memoryObjects =
                call.params.getParam("memoryObjectsPacked", ParamType::TMemoryObjectIDPointer, 1);
            CaptureUpdateResourceIDs<gl::MemoryObjectID>(context, call, memoryObjects,
                                                         resourceTracker, callsOut);
            break;
        }

        default:
            break;
    }
}

bool IsDefaultCurrentValue(const gl::VertexAttribCurrentValueData &currentValue)
{
    if (currentValue.Type != gl::VertexAttribType::Float)
        return false;

    return currentValue.Values.FloatValues[0] == 0.0f &&
           currentValue.Values.FloatValues[1] == 0.0f &&
           currentValue.Values.FloatValues[2] == 0.0f && currentValue.Values.FloatValues[3] == 1.0f;
}

bool IsQueryActive(const gl::State &glState, gl::QueryID &queryID)
{
    const gl::ActiveQueryMap &activeQueries = glState.getActiveQueriesForCapture();
    for (const auto &activeQueryIter : activeQueries)
    {
        const gl::Query *activeQuery = activeQueryIter.get();
        if (activeQuery && activeQuery->id() == queryID)
        {
            return true;
        }
    }

    return false;
}

bool IsTextureUpdate(CallCapture &call)
{
    switch (call.entryPoint)
    {
        case EntryPoint::GLCompressedCopyTextureCHROMIUM:
        case EntryPoint::GLCompressedTexImage2D:
        case EntryPoint::GLCompressedTexImage3D:
        case EntryPoint::GLCompressedTexImage3DOES:
        case EntryPoint::GLCompressedTexSubImage2D:
        case EntryPoint::GLCompressedTexSubImage3D:
        case EntryPoint::GLCompressedTexSubImage3DOES:
        case EntryPoint::GLCopyTexImage2D:
        case EntryPoint::GLCopyTexSubImage2D:
        case EntryPoint::GLCopyTexSubImage3D:
        case EntryPoint::GLCopyTexSubImage3DOES:
        case EntryPoint::GLCopyTexture3DANGLE:
        case EntryPoint::GLCopyTextureCHROMIUM:
        case EntryPoint::GLTexImage2D:
        case EntryPoint::GLTexImage2DRobustANGLE:
        case EntryPoint::GLTexImage3D:
        case EntryPoint::GLTexImage3DOES:
        case EntryPoint::GLTexImage3DRobustANGLE:
        case EntryPoint::GLTexSubImage2D:
        case EntryPoint::GLTexSubImage2DRobustANGLE:
        case EntryPoint::GLTexSubImage3D:
        case EntryPoint::GLTexSubImage3DOES:
        case EntryPoint::GLTexSubImage3DRobustANGLE:
        case EntryPoint::GLCopyImageSubData:
        case EntryPoint::GLCopyImageSubDataEXT:
        case EntryPoint::GLCopyImageSubDataOES:
            return true;
        default:
            return false;
    }
}

bool IsImageUpdate(CallCapture &call)
{
    return IsDispatchEntryPoint(call.entryPoint);
}

bool IsVertexArrayUpdate(CallCapture &call)
{
    switch (call.entryPoint)
    {
        case EntryPoint::GLVertexAttribFormat:
        case EntryPoint::GLVertexAttribIFormat:
        case EntryPoint::GLBindVertexBuffer:
        case EntryPoint::GLVertexAttribBinding:
        case EntryPoint::GLVertexAttribPointer:
        case EntryPoint::GLVertexAttribIPointer:
        case EntryPoint::GLEnableVertexAttribArray:
        case EntryPoint::GLDisableVertexAttribArray:
        case EntryPoint::GLVertexBindingDivisor:
        case EntryPoint::GLVertexAttribDivisor:
            return true;
        default:
            return false;
    }
}

bool IsFramebufferUpdate(CallCapture &call)
{
    return (IsDrawEntryPoint(call.entryPoint) || IsClearEntryPoint(call.entryPoint) ||
            call.entryPoint == EntryPoint::GLBlitFramebuffer);
}

bool IsSharedObjectResource(ResourceIDType type)
{
    // This helper function informs us which objects are shared vs. per context
    //
    //   OpenGL ES Version 3.2 (October 22, 2019)
    //   Chapter 5 Shared Objects and Multiple Contexts:
    //
    //   - Objects that can be shared between contexts include buffer objects, program
    //     and shader objects, renderbuffer objects, sampler objects, sync objects, and texture
    //     objects (except for the texture objects named zero).
    //   - Objects which contain references to other objects include framebuffer, program
    //     pipeline, transform feedback, and vertex array objects. Such objects are called
    //     container objects and are not shared.
    //
    // Notably absent from this list are Sync objects, which are not ResourceIDType, are handled
    // elsewhere, and are shared:
    //   - 2.6.13 Sync Objects: Sync objects may be shared.

    switch (type)
    {
        case ResourceIDType::Buffer:
            // 2.6.2 Buffer Objects: Buffer objects may be shared.
            return true;

        case ResourceIDType::Framebuffer:
            // 2.6.9 Framebuffer Objects: Framebuffer objects are container objects including
            // references to renderbuffer and / or texture objects, and are not shared.
            return false;

        case ResourceIDType::ProgramPipeline:
            // 2.6.5 Program Pipeline Objects: Program pipeline objects are container objects
            // including references to program objects, and are not shared.
            return false;

        case ResourceIDType::TransformFeedback:
            // 2.6.11 Transform Feedback Objects: Transform feedback objects are container objects
            // including references to buffer objects, and are not shared
            return false;

        case ResourceIDType::VertexArray:
            // 2.6.10 Vertex Array Objects: Vertex array objects are container objects including
            // references to buffer objects, and are not shared
            return false;

        case ResourceIDType::FenceNV:
            // From https://registry.khronos.org/OpenGL/extensions/NV/NV_fence.txt
            //  Are the fences sharable between multiple contexts?
            //   RESOLUTION: No.
            return false;

        case ResourceIDType::Renderbuffer:
            // 2.6.8 Renderbuffer Objects: Renderbuffer objects may be shared.
            return true;

        case ResourceIDType::ShaderProgram:
            // 2.6.3 Shader Objects: Shader objects may be shared.
            // 2.6.4 Program Objects: Program objects may be shared.
            return true;

        case ResourceIDType::Sampler:
            // 2.6.7 Sampler Objects: Sampler objects may be shared
            return true;

        case ResourceIDType::Sync:
            // 2.6.13 Sync Objects: Sync objects may be shared.
            return true;

        case ResourceIDType::Texture:
            // 2.6.6 Texture Objects: Texture objects may be shared
            return true;

        case ResourceIDType::Query:
            // 2.6.12 Query Objects: Query objects are not shared
            return false;

        case ResourceIDType::Semaphore:
            // From https://registry.khronos.org/OpenGL/extensions/EXT/EXT_external_objects.txt
            // 2.6.14 Semaphore Objects: Semaphore objects may be shared.
            return true;

        case ResourceIDType::MemoryObject:
            // From https://registry.khronos.org/OpenGL/extensions/EXT/EXT_external_objects.txt
            // 2.6.15 Memory Objects: Memory objects may be shared.
            return true;

        case ResourceIDType::Context:
        case ResourceIDType::Image:
        case ResourceIDType::Surface:
        case ResourceIDType::egl_Sync:
            // EGL types are associated with a display and not bound to a context
            // For the way this function is used, we can treat them as shared.
            return true;

        case ResourceIDType::EnumCount:
        default:
            ERR() << "Unhandled ResourceIDType= " << static_cast<int>(type);
            UNREACHABLE();
            return false;
    }
}

enum class DefaultUniformType
{
    None,
    CurrentProgram,
    SpecifiedProgram,
};

DefaultUniformType GetDefaultUniformType(const CallCapture &call)
{
    switch (call.entryPoint)
    {
        case EntryPoint::GLProgramUniform1f:
        case EntryPoint::GLProgramUniform1fEXT:
        case EntryPoint::GLProgramUniform1fv:
        case EntryPoint::GLProgramUniform1fvEXT:
        case EntryPoint::GLProgramUniform1i:
        case EntryPoint::GLProgramUniform1iEXT:
        case EntryPoint::GLProgramUniform1iv:
        case EntryPoint::GLProgramUniform1ivEXT:
        case EntryPoint::GLProgramUniform1ui:
        case EntryPoint::GLProgramUniform1uiEXT:
        case EntryPoint::GLProgramUniform1uiv:
        case EntryPoint::GLProgramUniform1uivEXT:
        case EntryPoint::GLProgramUniform2f:
        case EntryPoint::GLProgramUniform2fEXT:
        case EntryPoint::GLProgramUniform2fv:
        case EntryPoint::GLProgramUniform2fvEXT:
        case EntryPoint::GLProgramUniform2i:
        case EntryPoint::GLProgramUniform2iEXT:
        case EntryPoint::GLProgramUniform2iv:
        case EntryPoint::GLProgramUniform2ivEXT:
        case EntryPoint::GLProgramUniform2ui:
        case EntryPoint::GLProgramUniform2uiEXT:
        case EntryPoint::GLProgramUniform2uiv:
        case EntryPoint::GLProgramUniform2uivEXT:
        case EntryPoint::GLProgramUniform3f:
        case EntryPoint::GLProgramUniform3fEXT:
        case EntryPoint::GLProgramUniform3fv:
        case EntryPoint::GLProgramUniform3fvEXT:
        case EntryPoint::GLProgramUniform3i:
        case EntryPoint::GLProgramUniform3iEXT:
        case EntryPoint::GLProgramUniform3iv:
        case EntryPoint::GLProgramUniform3ivEXT:
        case EntryPoint::GLProgramUniform3ui:
        case EntryPoint::GLProgramUniform3uiEXT:
        case EntryPoint::GLProgramUniform3uiv:
        case EntryPoint::GLProgramUniform3uivEXT:
        case EntryPoint::GLProgramUniform4f:
        case EntryPoint::GLProgramUniform4fEXT:
        case EntryPoint::GLProgramUniform4fv:
        case EntryPoint::GLProgramUniform4fvEXT:
        case EntryPoint::GLProgramUniform4i:
        case EntryPoint::GLProgramUniform4iEXT:
        case EntryPoint::GLProgramUniform4iv:
        case EntryPoint::GLProgramUniform4ivEXT:
        case EntryPoint::GLProgramUniform4ui:
        case EntryPoint::GLProgramUniform4uiEXT:
        case EntryPoint::GLProgramUniform4uiv:
        case EntryPoint::GLProgramUniform4uivEXT:
        case EntryPoint::GLProgramUniformMatrix2fv:
        case EntryPoint::GLProgramUniformMatrix2fvEXT:
        case EntryPoint::GLProgramUniformMatrix2x3fv:
        case EntryPoint::GLProgramUniformMatrix2x3fvEXT:
        case EntryPoint::GLProgramUniformMatrix2x4fv:
        case EntryPoint::GLProgramUniformMatrix2x4fvEXT:
        case EntryPoint::GLProgramUniformMatrix3fv:
        case EntryPoint::GLProgramUniformMatrix3fvEXT:
        case EntryPoint::GLProgramUniformMatrix3x2fv:
        case EntryPoint::GLProgramUniformMatrix3x2fvEXT:
        case EntryPoint::GLProgramUniformMatrix3x4fv:
        case EntryPoint::GLProgramUniformMatrix3x4fvEXT:
        case EntryPoint::GLProgramUniformMatrix4fv:
        case EntryPoint::GLProgramUniformMatrix4fvEXT:
        case EntryPoint::GLProgramUniformMatrix4x2fv:
        case EntryPoint::GLProgramUniformMatrix4x2fvEXT:
        case EntryPoint::GLProgramUniformMatrix4x3fv:
        case EntryPoint::GLProgramUniformMatrix4x3fvEXT:
            return DefaultUniformType::SpecifiedProgram;

        case EntryPoint::GLUniform1f:
        case EntryPoint::GLUniform1fv:
        case EntryPoint::GLUniform1i:
        case EntryPoint::GLUniform1iv:
        case EntryPoint::GLUniform1ui:
        case EntryPoint::GLUniform1uiv:
        case EntryPoint::GLUniform2f:
        case EntryPoint::GLUniform2fv:
        case EntryPoint::GLUniform2i:
        case EntryPoint::GLUniform2iv:
        case EntryPoint::GLUniform2ui:
        case EntryPoint::GLUniform2uiv:
        case EntryPoint::GLUniform3f:
        case EntryPoint::GLUniform3fv:
        case EntryPoint::GLUniform3i:
        case EntryPoint::GLUniform3iv:
        case EntryPoint::GLUniform3ui:
        case EntryPoint::GLUniform3uiv:
        case EntryPoint::GLUniform4f:
        case EntryPoint::GLUniform4fv:
        case EntryPoint::GLUniform4i:
        case EntryPoint::GLUniform4iv:
        case EntryPoint::GLUniform4ui:
        case EntryPoint::GLUniform4uiv:
        case EntryPoint::GLUniformMatrix2fv:
        case EntryPoint::GLUniformMatrix2x3fv:
        case EntryPoint::GLUniformMatrix2x4fv:
        case EntryPoint::GLUniformMatrix3fv:
        case EntryPoint::GLUniformMatrix3x2fv:
        case EntryPoint::GLUniformMatrix3x4fv:
        case EntryPoint::GLUniformMatrix4fv:
        case EntryPoint::GLUniformMatrix4x2fv:
        case EntryPoint::GLUniformMatrix4x3fv:
            return DefaultUniformType::CurrentProgram;

        default:
            return DefaultUniformType::None;
    }
}

void CaptureFramebufferAttachment(std::vector<CallCapture> *setupCalls,
                                  const gl::State &replayState,
                                  const FramebufferCaptureFuncs &framebufferFuncs,
                                  const gl::FramebufferAttachment &attachment,
                                  std::vector<CallCapture> *shareGroupSetupCalls,
                                  ResourceIDToSetupCallsMap *resourceIDToSetupCalls)
{
    GLuint resourceID = attachment.getResource()->getId();

    if (attachment.type() == GL_TEXTURE)
    {
        gl::ImageIndex index = attachment.getTextureImageIndex();

        if (index.usesTex3D())
        {
            Capture(setupCalls, CaptureFramebufferTextureLayer(
                                    replayState, true, GL_FRAMEBUFFER, attachment.getBinding(),
                                    {resourceID}, index.getLevelIndex(), index.getLayerIndex()));
        }
        else
        {
            Capture(setupCalls,
                    framebufferFuncs.framebufferTexture2D(
                        replayState, true, GL_FRAMEBUFFER, attachment.getBinding(),
                        index.getTargetOrFirstCubeFace(), {resourceID}, index.getLevelIndex()));
        }

        std::vector<gl::TextureID> textureIDs;
        const CallCapture &call = setupCalls->back();
        if (FindResourceIDsInCall<gl::TextureID>(call, textureIDs))
        {
            // We skip the is active check on the assumption this call is made during MEC
            for (gl::TextureID textureID : textureIDs)
            {
                // Track that this call referenced a Texture, setting it active for Setup
                MarkResourceIDActive(ResourceIDType::Texture, textureID.value, shareGroupSetupCalls,
                                     resourceIDToSetupCalls);
            }
        }
    }
    else
    {
        ASSERT(attachment.type() == GL_RENDERBUFFER);
        Capture(setupCalls, framebufferFuncs.framebufferRenderbuffer(
                                replayState, true, GL_FRAMEBUFFER, attachment.getBinding(),
                                GL_RENDERBUFFER, {resourceID}));
    }
}

void CaptureUpdateUniformValues(const gl::State &replayState,
                                const gl::Context *context,
                                gl::Program *program,
                                ResourceTracker *resourceTracker,
                                std::vector<CallCapture> *callsOut)
{
    if (!program->isLinked())
    {
        // We can't populate uniforms if the program hasn't been linked
        return;
    }

    // We need to bind the program and update its uniforms
    if (!replayState.getProgram() || replayState.getProgram()->id() != program->id())
    {
        Capture(callsOut, CaptureUseProgram(replayState, true, program->id()));
        CaptureUpdateCurrentProgram(callsOut->back(), 0, callsOut);
    }

    const gl::ProgramExecutable &executable = program->getExecutable();

    for (GLuint uniformIndex = 0;
         uniformIndex < static_cast<GLuint>(executable.getUniforms().size()); uniformIndex++)
    {
        std::string uniformName          = executable.getUniformNameByIndex(uniformIndex);
        const gl::LinkedUniform &uniform = executable.getUniformByIndex(uniformIndex);

        int uniformCount = 1;
        if (uniform.isArray())
        {
            uniformCount = uniform.getBasicTypeElementCount();
            uniformName  = gl::StripLastArrayIndex(uniformName);
        }

        gl::UniformLocation uniformLoc      = executable.getUniformLocation(uniformName);
        const gl::UniformTypeInfo &typeInfo = gl::GetUniformTypeInfo(uniform.getType());
        int componentCount                  = typeInfo.componentCount;
        int uniformSize                     = uniformCount * componentCount;

        // For arrayed uniforms, we'll need to increment a read location
        gl::UniformLocation readLoc = uniformLoc;

        // If the uniform is unused, just continue
        if (readLoc.value == -1)
        {
            continue;
        }

        // Image uniforms are special and cannot be set this way
        if (typeInfo.isImageType)
        {
            continue;
        }

        DefaultUniformCallsPerLocationMap &resetCalls =
            resourceTracker->getDefaultUniformResetCalls(program->id());

        // Create two lists of calls for uniforms, one for Setup, one for Reset
        CallVector defaultUniformCalls({callsOut, &resetCalls[uniformLoc]});

        // Samplers should be populated with GL_INT, regardless of return type
        if (typeInfo.isSampler)
        {
            std::vector<GLint> uniformBuffer(uniformSize);
            for (int index = 0; index < uniformCount; index++, readLoc.value++)
            {
                executable.getUniformiv(context, readLoc,
                                        uniformBuffer.data() + index * componentCount);
                resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc, uniformLoc);
            }

            for (std::vector<CallCapture> *calls : defaultUniformCalls)
            {
                Capture(calls, CaptureUniform1iv(replayState, true, uniformLoc, uniformCount,
                                                 uniformBuffer.data()));
            }

            continue;
        }

        switch (typeInfo.componentType)
        {
            case GL_FLOAT:
            {
                std::vector<GLfloat> uniformBuffer(uniformSize);
                for (int index = 0; index < uniformCount; index++, readLoc.value++)
                {
                    executable.getUniformfv(context, readLoc,
                                            uniformBuffer.data() + index * componentCount);
                    resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc,
                                                                   uniformLoc);
                }
                switch (typeInfo.type)
                {
                    // Note: All matrix uniforms are populated without transpose
                    case GL_FLOAT_MAT4x3:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix4x3fv(replayState, true, uniformLoc,
                                                                     uniformCount, false,
                                                                     uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT4x2:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix4x2fv(replayState, true, uniformLoc,
                                                                     uniformCount, false,
                                                                     uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT4:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix4fv(replayState, true, uniformLoc,
                                                                   uniformCount, false,
                                                                   uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT3x4:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix3x4fv(replayState, true, uniformLoc,
                                                                     uniformCount, false,
                                                                     uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT3x2:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix3x2fv(replayState, true, uniformLoc,
                                                                     uniformCount, false,
                                                                     uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT3:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix3fv(replayState, true, uniformLoc,
                                                                   uniformCount, false,
                                                                   uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT2x4:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix2x4fv(replayState, true, uniformLoc,
                                                                     uniformCount, false,
                                                                     uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT2x3:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix2x3fv(replayState, true, uniformLoc,
                                                                     uniformCount, false,
                                                                     uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_MAT2:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniformMatrix2fv(replayState, true, uniformLoc,
                                                                   uniformCount, false,
                                                                   uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_VEC4:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform4fv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_VEC3:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform3fv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT_VEC2:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform2fv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case GL_FLOAT:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform1fv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    default:
                        UNIMPLEMENTED();
                        break;
                }
                break;
            }
            case GL_INT:
            {
                std::vector<GLint> uniformBuffer(uniformSize);
                for (int index = 0; index < uniformCount; index++, readLoc.value++)
                {
                    executable.getUniformiv(context, readLoc,
                                            uniformBuffer.data() + index * componentCount);
                    resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc,
                                                                   uniformLoc);
                }
                switch (componentCount)
                {
                    case 4:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform4iv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case 3:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform3iv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case 2:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform2iv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case 1:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform1iv(replayState, true, uniformLoc,
                                                             uniformCount, uniformBuffer.data()));
                        }
                        break;
                    default:
                        UNIMPLEMENTED();
                        break;
                }
                break;
            }
            case GL_BOOL:
            case GL_UNSIGNED_INT:
            {
                std::vector<GLuint> uniformBuffer(uniformSize);
                for (int index = 0; index < uniformCount; index++, readLoc.value++)
                {
                    executable.getUniformuiv(context, readLoc,
                                             uniformBuffer.data() + index * componentCount);
                    resourceTracker->setDefaultUniformBaseLocation(program->id(), readLoc,
                                                                   uniformLoc);
                }
                switch (componentCount)
                {
                    case 4:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform4uiv(replayState, true, uniformLoc,
                                                              uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case 3:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform3uiv(replayState, true, uniformLoc,
                                                              uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case 2:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform2uiv(replayState, true, uniformLoc,
                                                              uniformCount, uniformBuffer.data()));
                        }
                        break;
                    case 1:
                        for (std::vector<CallCapture> *calls : defaultUniformCalls)
                        {
                            Capture(calls, CaptureUniform1uiv(replayState, true, uniformLoc,
                                                              uniformCount, uniformBuffer.data()));
                        }
                        break;
                    default:
                        UNIMPLEMENTED();
                        break;
                }
                break;
            }
            default:
                UNIMPLEMENTED();
                break;
        }
    }
}

void CaptureUpdateClientArrayPointer(uint32_t attribIndex,
                                     const void *clientAttribAddress,
                                     size_t bytesToCapture,
                                     std::vector<CallCapture> *frameCalls)
{
    ParamBuffer updateParamBuffer;
    updateParamBuffer.addValueParam<GLint>("arrayIndex", ParamType::TGLint, attribIndex);

    ParamCapture updateMemory("pointer", ParamType::TvoidConstPointer);
    CaptureMemory(clientAttribAddress, bytesToCapture, &updateMemory);
    updateParamBuffer.addParam(std::move(updateMemory));

    updateParamBuffer.addValueParam<GLuint64>("size", ParamType::TGLuint64, bytesToCapture);

    frameCalls->emplace_back("UpdateClientArrayPointer", std::move(updateParamBuffer));
}

void CaptureVertexPointerES1(std::vector<CallCapture> *setupCalls,
                             gl::State *replayState,
                             GLuint attribIndex,
                             const gl::VertexAttribute &attrib,
                             const gl::VertexBinding &binding)
{
    switch (gl::GLES1Renderer::VertexArrayType(attribIndex))
    {
        case gl::ClientVertexArrayType::Vertex:
            Capture(setupCalls,
                    CaptureVertexPointer(*replayState, true, attrib.format->channelCount,
                                         attrib.format->vertexAttribType, binding.getStride(),
                                         attrib.pointer));
            break;
        case gl::ClientVertexArrayType::Normal:
            Capture(setupCalls,
                    CaptureNormalPointer(*replayState, true, attrib.format->vertexAttribType,
                                         binding.getStride(), attrib.pointer));
            break;
        case gl::ClientVertexArrayType::Color:
            Capture(setupCalls, CaptureColorPointer(*replayState, true, attrib.format->channelCount,
                                                    attrib.format->vertexAttribType,
                                                    binding.getStride(), attrib.pointer));
            break;
        case gl::ClientVertexArrayType::PointSize:
            Capture(setupCalls,
                    CapturePointSizePointerOES(*replayState, true, attrib.format->vertexAttribType,
                                               binding.getStride(), attrib.pointer));
            break;
        case gl::ClientVertexArrayType::TextureCoord:
            Capture(setupCalls,
                    CaptureTexCoordPointer(*replayState, true, attrib.format->channelCount,
                                           attrib.format->vertexAttribType, binding.getStride(),
                                           attrib.pointer));
            break;
        default:
            UNREACHABLE();
    }
}

void CaptureTextureEnvironmentState(std::vector<CallCapture> *setupCalls,
                                    gl::State *replayState,
                                    const gl::State *apiState,
                                    unsigned int unit)
{
    const gl::TextureEnvironmentParameters &currentEnv = apiState->gles1().textureEnvironment(unit);
    const gl::TextureEnvironmentParameters &defaultEnv =
        replayState->gles1().textureEnvironment(unit);

    if (currentEnv == defaultEnv)
    {
        return;
    }

    auto capIfNe = [setupCalls](auto currentState, auto defaultState, CallCapture &&call) {
        if (currentState != defaultState)
        {
            setupCalls->emplace_back(std::move(call));
        }
    };

    // When the texture env state differs on a non-default sampler unit, emit an ActiveTexture call.
    // The default sampler unit is GL_TEXTURE0.
    GLenum currentUnit = GL_TEXTURE0 + static_cast<GLenum>(unit);
    GLenum defaultUnit = GL_TEXTURE0 + static_cast<GLenum>(replayState->getActiveSampler());
    capIfNe(currentUnit, defaultUnit, CaptureActiveTexture(*replayState, true, currentUnit));

    auto capEnum = [capIfNe, replayState](gl::TextureEnvParameter pname, auto currentState,
                                          auto defaultState) {
        capIfNe(currentState, defaultState,
                CaptureTexEnvi(*replayState, true, gl::TextureEnvTarget::Env, pname,
                               ToGLenum(currentState)));
    };

    capEnum(gl::TextureEnvParameter::Mode, currentEnv.mode, defaultEnv.mode);

    capEnum(gl::TextureEnvParameter::CombineRgb, currentEnv.combineRgb, defaultEnv.combineRgb);
    capEnum(gl::TextureEnvParameter::CombineAlpha, currentEnv.combineAlpha,
            defaultEnv.combineAlpha);

    capEnum(gl::TextureEnvParameter::Src0Rgb, currentEnv.src0Rgb, defaultEnv.src0Rgb);
    capEnum(gl::TextureEnvParameter::Src1Rgb, currentEnv.src1Rgb, defaultEnv.src1Rgb);
    capEnum(gl::TextureEnvParameter::Src2Rgb, currentEnv.src2Rgb, defaultEnv.src2Rgb);

    capEnum(gl::TextureEnvParameter::Src0Alpha, currentEnv.src0Alpha, defaultEnv.src0Alpha);
    capEnum(gl::TextureEnvParameter::Src1Alpha, currentEnv.src1Alpha, defaultEnv.src1Alpha);
    capEnum(gl::TextureEnvParameter::Src2Alpha, currentEnv.src2Alpha, defaultEnv.src2Alpha);

    capEnum(gl::TextureEnvParameter::Op0Rgb, currentEnv.op0Rgb, defaultEnv.op0Rgb);
    capEnum(gl::TextureEnvParameter::Op1Rgb, currentEnv.op1Rgb, defaultEnv.op1Rgb);
    capEnum(gl::TextureEnvParameter::Op2Rgb, currentEnv.op2Rgb, defaultEnv.op2Rgb);

    capEnum(gl::TextureEnvParameter::Op0Alpha, currentEnv.op0Alpha, defaultEnv.op0Alpha);
    capEnum(gl::TextureEnvParameter::Op1Alpha, currentEnv.op1Alpha, defaultEnv.op1Alpha);
    capEnum(gl::TextureEnvParameter::Op2Alpha, currentEnv.op2Alpha, defaultEnv.op2Alpha);

    auto capFloat = [capIfNe, replayState](gl::TextureEnvParameter pname, auto currentState,
                                           auto defaultState) {
        capIfNe(currentState, defaultState,
                CaptureTexEnvf(*replayState, true, gl::TextureEnvTarget::Env, pname, currentState));
    };

    capFloat(gl::TextureEnvParameter::RgbScale, currentEnv.rgbScale, defaultEnv.rgbScale);
    capFloat(gl::TextureEnvParameter::AlphaScale, currentEnv.alphaScale, defaultEnv.alphaScale);

    capIfNe(currentEnv.color, defaultEnv.color,
            CaptureTexEnvfv(*replayState, true, gl::TextureEnvTarget::Env,
                            gl::TextureEnvParameter::Color, currentEnv.color.data()));

    // PointCoordReplace is the only parameter that uses the PointSprite TextureEnvTarget.
    capIfNe(currentEnv.pointSpriteCoordReplace, defaultEnv.pointSpriteCoordReplace,
            CaptureTexEnvi(*replayState, true, gl::TextureEnvTarget::PointSprite,
                           gl::TextureEnvParameter::PointCoordReplace,
                           currentEnv.pointSpriteCoordReplace));

    capIfNe(currentEnv.lodBias, defaultEnv.lodBias,
            CaptureTexEnvf(*replayState, true, gl::TextureEnvTarget::TextureFilterControl,
                           gl::TextureEnvParameter::LodBias, currentEnv.lodBias));

    // In case of non-default sampler units, the default unit must be set back here.
    capIfNe(currentUnit, defaultUnit, CaptureActiveTexture(*replayState, true, defaultUnit));
}

bool VertexBindingMatchesAttribStride(const gl::VertexAttribute &attrib,
                                      const gl::VertexBinding &binding)
{
    if (attrib.vertexAttribArrayStride == 0 &&
        binding.getStride() == ComputeVertexAttributeTypeSize(attrib))
    {
        return true;
    }

    return attrib.vertexAttribArrayStride == binding.getStride();
}

void CaptureVertexArrayState(std::vector<CallCapture> *setupCalls,
                             const gl::Context *context,
                             const gl::VertexArray *vertexArray,
                             gl::State *replayState)
{
    const std::vector<gl::VertexAttribute> &vertexAttribs = vertexArray->getVertexAttributes();
    const std::vector<gl::VertexBinding> &vertexBindings  = vertexArray->getVertexBindings();
    const gl::BufferManager &capturedBuffers = context->getState().getBufferManagerForCapture();

    gl::AttributesMask vertexPointerBindings;
    gl::AttributesMask clientVertexArrayMask;
    gl::AttribArray<const void *> clientVertexArrayData;
    std::vector<size_t> clientVACallIndices;

    ASSERT(vertexAttribs.size() <= vertexBindings.size());
    for (GLuint attribIndex = 0; attribIndex < vertexAttribs.size(); ++attribIndex)
    {
        const gl::VertexAttribute defaultAttrib(attribIndex);
        const gl::VertexBinding defaultBinding;

        const gl::VertexAttribute &attrib = vertexAttribs[attribIndex];
        const gl::VertexBinding &binding  = vertexBindings[attrib.bindingIndex];
        gl::Buffer *buffer                = vertexArray->getVertexArrayBuffer(attrib.bindingIndex);

        if (attrib.enabled != defaultAttrib.enabled)
        {
            if (context->isGLES1())
            {
                Capture(setupCalls,
                        CaptureEnableClientState(*replayState, false,
                                                 gl::GLES1Renderer::VertexArrayType(attribIndex)));
            }
            else
            {
                Capture(setupCalls,
                        CaptureEnableVertexAttribArray(*replayState, false, attribIndex));
            }
        }

        gl::BufferID bufferID = {0};
        if (buffer)
        {
            bufferID = buffer->id();
        }

        // Don't capture CaptureVertexAttribPointer calls when a non-default VAO is bound, the array
        // buffer is null and a non-null attrib pointer is used.
        bool skipInvalidAttrib =
            vertexArray->id().value != 0 &&
            (buffer == nullptr || !capturedBuffers.isHandleGenerated(bufferID)) &&
            attrib.pointer != nullptr;

        if (!skipInvalidAttrib &&
            (attrib.format != defaultAttrib.format || attrib.pointer != defaultAttrib.pointer ||
             binding.getStride() != defaultBinding.getStride() ||
             attrib.bindingIndex != defaultAttrib.bindingIndex || buffer != nullptr))
        {
            // Each attribute can pull from a separate buffer, so check the binding
            if (buffer != replayState->getArrayBuffer())
            {
                replayState->setBufferBinding(context, gl::BufferBinding::Array, buffer);

                Capture(setupCalls,
                        CaptureBindBuffer(*replayState, true, gl::BufferBinding::Array, bufferID));
            }

            // Establish the relationship between currently bound buffer and the VAO
            if (context->isGLES1())
            {
                // Track indexes that used ES1 calls
                vertexPointerBindings.set(attribIndex);

                CaptureVertexPointerES1(setupCalls, replayState, attribIndex, attrib, binding);
            }
            else if (attrib.bindingIndex == attribIndex &&
                     VertexBindingMatchesAttribStride(attrib, binding) &&
                     (!buffer ||
                      binding.getOffset() == reinterpret_cast<uintptr_t>(attrib.pointer)))
            {
                // Check if we can use strictly ES2 semantics, and track indexes that do.
                vertexPointerBindings.set(attribIndex);

                if (attrib.format->isPureInt())
                {
                    Capture(setupCalls, CaptureVertexAttribIPointer(*replayState, true, attribIndex,
                                                                    attrib.format->channelCount,
                                                                    attrib.format->vertexAttribType,
                                                                    attrib.vertexAttribArrayStride,
                                                                    attrib.pointer));
                }
                else
                {
                    Capture(setupCalls,
                            CaptureVertexAttribPointer(
                                *replayState, true, attribIndex, attrib.format->channelCount,
                                attrib.format->vertexAttribType, attrib.format->isNorm(),
                                attrib.vertexAttribArrayStride, attrib.pointer));
                }

                if (binding.getDivisor() != 0)
                {
                    Capture(setupCalls, CaptureVertexAttribDivisor(*replayState, true, attribIndex,
                                                                   binding.getDivisor()));
                }
            }
            else
            {
                ASSERT(context->getClientVersion() >= gl::ES_3_1);

                if (attrib.format->isPureInt())
                {
                    Capture(setupCalls, CaptureVertexAttribIFormat(*replayState, true, attribIndex,
                                                                   attrib.format->channelCount,
                                                                   attrib.format->vertexAttribType,
                                                                   attrib.relativeOffset));
                }
                else
                {
                    Capture(setupCalls, CaptureVertexAttribFormat(*replayState, true, attribIndex,
                                                                  attrib.format->channelCount,
                                                                  attrib.format->vertexAttribType,
                                                                  attrib.format->isNorm(),
                                                                  attrib.relativeOffset));
                }

                Capture(setupCalls, CaptureVertexAttribBinding(*replayState, true, attribIndex,
                                                               attrib.bindingIndex));
            }
            if (setupCalls->back().params.hasClientArrayData())
            {
                // The last call's index is kept so the call's pointer and offset can be updated if
                // its corresponding attribute is merged into another attribute later.
                ParamCapture &clientArrayPointerParams =
                    setupCalls->back().params.getClientArrayPointerParameter();
                const void *clientArrayPointer = clientArrayPointerParams.value.voidConstPointerVal;

                // If the attribute pointer is set to 0 in the setup, it should not be merged.
                if (clientArrayPointer != nullptr)
                {
                    const size_t currentSetupCallLastIndex = setupCalls->size() - 1;
                    clientVACallIndices.push_back(currentSetupCallLastIndex);
                    clientVertexArrayMask.set(clientArrayPointerParams.arrayClientPointerIndex);
                    clientVertexArrayData[clientArrayPointerParams.arrayClientPointerIndex] =
                        clientArrayPointer;
                }
            }
        }
    }

    // Merge attribute pointers in the setup if possible.
    if (clientVertexArrayMask.any())
    {
        ASSERT(!clientVACallIndices.empty());
        MergedAttribRanges mergedAddrRanges;
        gl::AttribArray<size_t> mergedIndexMap;

        MaybeMergeClientAttributes(vertexArray, clientVertexArrayMask, clientVertexArrayData,
                                   setupCalls, clientVACallIndices, false, 0, 0, mergedAddrRanges,
                                   mergedIndexMap);
    }

    // The loop below expects attribs and bindings to have equal counts
    static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
                  "Max vertex attribs and bindings count mismatch");

    // Loop through binding indices that weren't used by VertexAttribPointer
    for (size_t bindingIndex : vertexPointerBindings.flip())
    {
        const gl::VertexBinding &binding = vertexBindings[bindingIndex];
        gl::Buffer *buffer               = vertexArray->getVertexArrayBuffer(bindingIndex);

        if (buffer)
        {
            Capture(setupCalls,
                    CaptureBindVertexBuffer(
                        *replayState, true, static_cast<GLuint>(bindingIndex), buffer->id(),
                        static_cast<GLintptr>(binding.getOffset()), binding.getStride()));
        }

        if (binding.getDivisor() != 0)
        {
            Capture(setupCalls, CaptureVertexBindingDivisor(*replayState, true,
                                                            static_cast<GLuint>(bindingIndex),
                                                            binding.getDivisor()));
        }
    }

    // The element array buffer is not per attribute, but per VAO
    gl::Buffer *elementArrayBuffer = vertexArray->getElementArrayBuffer();
    if (elementArrayBuffer)
    {
        Capture(setupCalls, CaptureBindBuffer(*replayState, true, gl::BufferBinding::ElementArray,
                                              elementArrayBuffer->id()));
    }
}

void CaptureTextureStorage(std::vector<CallCapture> *setupCalls,
                           gl::State *replayState,
                           const gl::Texture *texture)
{
    // Use mip-level 0 for the base dimensions
    gl::ImageIndex imageIndex = gl::ImageIndex::MakeFromType(texture->getType(), 0);
    const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(imageIndex);

    switch (texture->getType())
    {
        case gl::TextureType::_2D:
        case gl::TextureType::CubeMap:
        {
            Capture(setupCalls, CaptureTexStorage2D(*replayState, true, texture->getType(),
                                                    texture->getImmutableLevels(),
                                                    desc.format.info->internalFormat,
                                                    desc.size.width, desc.size.height));
            break;
        }
        case gl::TextureType::_3D:
        case gl::TextureType::_2DArray:
        case gl::TextureType::CubeMapArray:
        {
            Capture(setupCalls, CaptureTexStorage3D(
                                    *replayState, true, texture->getType(),
                                    texture->getImmutableLevels(), desc.format.info->internalFormat,
                                    desc.size.width, desc.size.height, desc.size.depth));
            break;
        }
        case gl::TextureType::Buffer:
        {
            // Do nothing. This will already be captured as a buffer.
            break;
        }
        default:
            UNIMPLEMENTED();
            break;
    }
}

void CaptureTextureContents(std::vector<CallCapture> *setupCalls,
                            gl::State *replayState,
                            const gl::Texture *texture,
                            const gl::ImageIndex &index,
                            const gl::ImageDesc &desc,
                            GLuint size,
                            const void *data)
{
    const gl::InternalFormat &format = *desc.format.info;

    if (index.getType() == gl::TextureType::Buffer)
    {
        // Zero binding size indicates full buffer bound
        if (texture->getBuffer().getSize() == 0)
        {
            Capture(setupCalls,
                    CaptureTexBufferEXT(*replayState, true, index.getType(), format.internalFormat,
                                        texture->getBuffer().get()->id()));
        }
        else
        {
            Capture(setupCalls, CaptureTexBufferRangeEXT(*replayState, true, index.getType(),
                                                         format.internalFormat,
                                                         texture->getBuffer().get()->id(),
                                                         texture->getBuffer().getOffset(),
                                                         texture->getBuffer().getSize()));
        }

        // For buffers, we're done
        return;
    }

    bool is3D =
        (index.getType() == gl::TextureType::_3D || index.getType() == gl::TextureType::_2DArray ||
         index.getType() == gl::TextureType::CubeMapArray);

    if (format.compressed || format.paletted)
    {
        if (is3D)
        {
            if (texture->getImmutableFormat())
            {
                Capture(setupCalls,
                        CaptureCompressedTexSubImage3D(
                            *replayState, true, index.getTarget(), index.getLevelIndex(), 0, 0, 0,
                            desc.size.width, desc.size.height, desc.size.depth,
                            format.internalFormat, size, data));
            }
            else
            {
                Capture(setupCalls,
                        CaptureCompressedTexImage3D(*replayState, true, index.getTarget(),
                                                    index.getLevelIndex(), format.internalFormat,
                                                    desc.size.width, desc.size.height,
                                                    desc.size.depth, 0, size, data));
            }
        }
        else
        {
            if (texture->getImmutableFormat())
            {
                Capture(setupCalls,
                        CaptureCompressedTexSubImage2D(
                            *replayState, true, index.getTarget(), index.getLevelIndex(), 0, 0,
                            desc.size.width, desc.size.height, format.internalFormat, size, data));
            }
            else
            {
                Capture(setupCalls, CaptureCompressedTexImage2D(
                                        *replayState, true, index.getTarget(),
                                        index.getLevelIndex(), format.internalFormat,
                                        desc.size.width, desc.size.height, 0, size, data));
            }
        }
    }
    else
    {
        if (is3D)
        {
            if (texture->getImmutableFormat())
            {
                Capture(setupCalls,
                        CaptureTexSubImage3D(*replayState, true, index.getTarget(),
                                             index.getLevelIndex(), 0, 0, 0, desc.size.width,
                                             desc.size.height, desc.size.depth, format.format,
                                             format.type, data));
            }
            else
            {
                Capture(
                    setupCalls,
                    CaptureTexImage3D(*replayState, true, index.getTarget(), index.getLevelIndex(),
                                      format.internalFormat, desc.size.width, desc.size.height,
                                      desc.size.depth, 0, format.format, format.type, data));
            }
        }
        else
        {
            if (texture->getImmutableFormat())
            {
                Capture(setupCalls,
                        CaptureTexSubImage2D(*replayState, true, index.getTarget(),
                                             index.getLevelIndex(), 0, 0, desc.size.width,
                                             desc.size.height, format.format, format.type, data));
            }
            else
            {
                Capture(setupCalls, CaptureTexImage2D(*replayState, true, index.getTarget(),
                                                      index.getLevelIndex(), format.internalFormat,
                                                      desc.size.width, desc.size.height, 0,
                                                      format.format, format.type, data));
            }
        }
    }
}

void CaptureCustomUniformBlockBinding(const CallCapture &callIn, std::vector<CallCapture> &callsOut)
{
    const ParamBuffer &paramsIn = callIn.params;

    const ParamCapture &programID =
        paramsIn.getParam("programPacked", ParamType::TShaderProgramID, 0);
    const ParamCapture &blockIndex =
        paramsIn.getParam("uniformBlockIndexPacked", ParamType::TUniformBlockIndex, 1);
    const ParamCapture &blockBinding =
        paramsIn.getParam("uniformBlockBinding", ParamType::TGLuint, 2);

    ParamBuffer params;
    params.addValueParam("program", ParamType::TGLuint, programID.value.ShaderProgramIDVal.value);
    params.addValueParam("uniformBlockIndex", ParamType::TGLuint,
                         blockIndex.value.UniformBlockIndexVal.value);
    params.addValueParam("uniformBlockBinding", ParamType::TGLuint, blockBinding.value.GLuintVal);

    callsOut.emplace_back("UniformBlockBinding", std::move(params));
}

void CaptureCustomMapBuffer(const char *entryPointName,
                            CallCapture &call,
                            std::vector<CallCapture> &callsOut,
                            gl::BufferID mappedBufferID)
{
    call.params.addValueParam("buffer", ParamType::TGLuint, mappedBufferID.value);
    callsOut.emplace_back(entryPointName, std::move(call.params));
}

void CaptureCustomShaderProgram(const char *name,
                                CallCapture &call,
                                std::vector<CallCapture> &callsOut)
{
    call.params.addValueParam("shaderProgram", ParamType::TGLuint,
                              call.params.getReturnValue().value.GLuintVal);
    call.customFunctionName = name;
    callsOut.emplace_back(std::move(call));
}

void CaptureCustomFenceSync(CallCapture &call, std::vector<CallCapture> &callsOut)
{
    ParamBuffer &&params = std::move(call.params);
    params.addValueParam("fenceSync", ParamType::TGLuint64,
                         params.getReturnValue().value.GLuint64Val);
    call.customFunctionName = "FenceSync2";
    callsOut.emplace_back(std::move(call));
}

void CaptureCustomClientWaitSync(CallCapture &call, std::vector<CallCapture> &callsOut)
{
    ParamBuffer &&params = std::move(call.params);
    GLenum returnValue   = params.getReturnValue().value.GLenumVal;
    params.addValueParam("capturedReturnValue", ParamType::TGLenum, returnValue);
    call.customFunctionName = "ClientWaitSync";
    call.params             = std::move(params);
    callsOut.emplace_back(std::move(call));
}

const egl::Image *GetImageFromParam(const gl::Context *context, const ParamCapture &param)
{
    const egl::ImageID eglImageID = egl::PackParam<egl::ImageID>(param.value.EGLImageVal);
    const egl::Image *eglImage    = context->getDisplay()->getImage(eglImageID);
    ASSERT(eglImage != nullptr);
    return eglImage;
}

void CaptureCustomCreateEGLImage(const gl::Context *context,
                                 const char *name,
                                 size_t width,
                                 size_t height,
                                 CallCapture &call,
                                 std::vector<CallCapture> &callsOut)
{
    ParamBuffer &&params    = std::move(call.params);
    EGLImage returnVal      = params.getReturnValue().value.EGLImageVal;
    egl::ImageID imageID    = egl::PackParam<egl::ImageID>(returnVal);
    call.customFunctionName = name;

    // Clear client buffer value if it is a pointer to a hardware buffer. It is
    // not used by replay and will not be portable to 32-bit builds
    if (params.getParam("target", ParamType::TEGLenum, 2).value.EGLenumVal ==
        EGL_NATIVE_BUFFER_ANDROID)
    {
        params.setValueParamAtIndex("buffer", ParamType::TEGLClientBuffer,
                                    reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(0)),
                                    3);
    }

    // Record image dimensions in case a backing resource needs to be created during replay
    params.addValueParam("width", ParamType::TGLsizei, static_cast<GLsizei>(width));
    params.addValueParam("height", ParamType::TGLsizei, static_cast<GLsizei>(height));

    params.addValueParam("image", ParamType::TGLuint, imageID.value);
    callsOut.emplace_back(std::move(call));
}

void CaptureCustomDestroyEGLImage(const char *name,
                                  CallCapture &call,
                                  std::vector<CallCapture> &callsOut)
{
    call.customFunctionName = name;
    ParamBuffer &&params    = std::move(call.params);

    const ParamCapture &imageID = params.getParam("imagePacked", ParamType::TImageID, 1);
    params.addValueParam("imageID", ParamType::TGLuint, imageID.value.ImageIDVal.value);

    callsOut.emplace_back(std::move(call));
}

void CaptureCustomCreateEGLSync(const char *name,
                                CallCapture &call,
                                std::vector<CallCapture> &callsOut)
{
    ParamBuffer &&params = std::move(call.params);
    EGLSync returnVal    = params.getReturnValue().value.EGLSyncVal;
    egl::SyncID syncID   = egl::PackParam<egl::SyncID>(returnVal);
    params.addValueParam("sync", ParamType::TGLuint, syncID.value);
    call.customFunctionName = name;
    callsOut.emplace_back(std::move(call));
}

void CaptureCustomCreatePbufferSurface(CallCapture &call, std::vector<CallCapture> &callsOut)
{
    ParamBuffer &&params     = std::move(call.params);
    EGLSurface returnVal     = params.getReturnValue().value.EGLSurfaceVal;
    egl::SurfaceID surfaceID = egl::PackParam<egl::SurfaceID>(returnVal);

    params.addValueParam("surface", ParamType::TGLuint, surfaceID.value);
    call.customFunctionName = "CreatePbufferSurface";
    callsOut.emplace_back(std::move(call));
}

void CaptureCustomCreateNativeClientbuffer(CallCapture &call, std::vector<CallCapture> &callsOut)
{
    ParamBuffer &&params = std::move(call.params);
    params.addValueParam("clientBuffer", ParamType::TEGLClientBuffer,
                         params.getReturnValue().value.EGLClientBufferVal);
    call.customFunctionName = "CreateNativeClientBufferANDROID";
    callsOut.emplace_back(std::move(call));
}

void GenerateLinkedProgram(const gl::Context *context,
                           const gl::State &replayState,
                           ResourceTracker *resourceTracker,
                           std::vector<CallCapture> *setupCalls,
                           gl::Program *program,
                           gl::ShaderProgramID id,
                           gl::ShaderProgramID tempIDStart,
                           const ProgramSources &linkedSources)
{
    // A map to store the gShaderProgram map lookup index of the temp shaders we attached below. We
    // need this map to retrieve the lookup index to pass to CaptureDetachShader calls at the end of
    // GenerateLinkedProgram.
    PackedEnumMap<gl::ShaderType, gl::ShaderProgramID> tempShaderIDTracker;

    const gl::ProgramExecutable &executable = program->getExecutable();

    // Compile with last linked sources.
    for (gl::ShaderType shaderType : executable.getLinkedShaderStages())
    {
        // Bump the max shader program id for each new tempIDStart we use to create, compile, and
        // attach the temp shader object.
        resourceTracker->onShaderProgramAccess(tempIDStart);
        // Store the tempIDStart in the tempShaderIDTracker to retrieve for CaptureDetachShader
        // calls later.
        tempShaderIDTracker[shaderType] = tempIDStart;
        const std::string &sourceString = linkedSources[shaderType];
        const char *sourcePointer       = sourceString.c_str();

        if (sourceString.empty())
        {
            // If we don't have source for this shader, that means it was populated by the app
            // using glProgramBinary.  We need to look it up from our cached copy.
            const ProgramSources &cachedLinkedSources =
                context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id);

            const std::string &cachedSourceString = cachedLinkedSources[shaderType];
            sourcePointer                         = cachedSourceString.c_str();
            ASSERT(!cachedSourceString.empty());
        }

        // Compile and attach the temporary shader. Then free it immediately.
        CallCapture createShader =
            CaptureCreateShader(replayState, true, shaderType, tempIDStart.value);
        CaptureCustomShaderProgram("CreateShader", createShader, *setupCalls);
        Capture(setupCalls,
                CaptureShaderSource(replayState, true, tempIDStart, 1, &sourcePointer, nullptr));
        Capture(setupCalls, CaptureCompileShader(replayState, true, tempIDStart));
        Capture(setupCalls, CaptureAttachShader(replayState, true, id, tempIDStart));
        // Increment tempIDStart to get a new gShaderProgram map index for the next linked stage
        // shader object. We can't reuse the same tempIDStart as we need to retrieve the index of
        // each attached shader object later to pass to CaptureDetachShader calls.
        tempIDStart.value += 1;
    }

    // Gather XFB varyings
    std::vector<std::string> xfbVaryings;
    for (const gl::TransformFeedbackVarying &xfbVarying :
         executable.getLinkedTransformFeedbackVaryings())
    {
        xfbVaryings.push_back(xfbVarying.nameWithArrayIndex());
    }

    if (!xfbVaryings.empty())
    {
        std::vector<const char *> varyingsStrings;
        for (const std::string &varyingString : xfbVaryings)
        {
            varyingsStrings.push_back(varyingString.data());
        }

        GLenum xfbMode = executable.getTransformFeedbackBufferMode();
        Capture(setupCalls, CaptureTransformFeedbackVaryings(replayState, true, id,
                                                             static_cast<GLint>(xfbVaryings.size()),
                                                             varyingsStrings.data(), xfbMode));
    }

    // Force the attributes to be bound the same way as in the existing program.
    // This can affect attributes that are optimized out in some implementations.
    for (const gl::ProgramInput &attrib : executable.getProgramInputs())
    {
        if (gl::IsBuiltInName(attrib.name))
        {
            // Don't try to bind built-in attributes
            continue;
        }

        // Separable programs may not have a VS, meaning it may not have attributes.
        if (executable.hasLinkedShaderStage(gl::ShaderType::Vertex))
        {
            ASSERT(attrib.getLocation() != -1);
            Capture(setupCalls, CaptureBindAttribLocation(replayState, true, id,
                                                          static_cast<GLuint>(attrib.getLocation()),
                                                          attrib.name.c_str()));
        }
    }

    if (program->isSeparable())
    {
        // MEC manually recreates separable programs, rather than attempting to recreate a call
        // to glCreateShaderProgramv(), so insert a call to mark it separable.
        Capture(setupCalls,
                CaptureProgramParameteri(replayState, true, id, GL_PROGRAM_SEPARABLE, GL_TRUE));
    }

    Capture(setupCalls, CaptureLinkProgram(replayState, true, id));
    CaptureUpdateUniformLocations(program, setupCalls);
    CaptureUpdateUniformValues(replayState, context, program, resourceTracker, setupCalls);
    CaptureUpdateUniformBlockIndexes(program, setupCalls);

    // Capture uniform block bindings for each program
    for (uint32_t uniformBlockIndex = 0;
         uniformBlockIndex < static_cast<uint32_t>(executable.getUniformBlocks().size());
         uniformBlockIndex++)
    {
        // Ensure that runtime API bindings are picked up
        GLuint blockBinding = executable.getUniformBlockBinding(uniformBlockIndex);
        CallCapture updateCallCapture =
            CaptureUniformBlockBinding(replayState, true, id, {uniformBlockIndex}, blockBinding);
        CaptureCustomUniformBlockBinding(updateCallCapture, *setupCalls);
    }

    // Add DetachShader call if that's what the app does, so that the
    // ResourceManagerBase::mHandleAllocator can release the ShaderProgramID handle assigned to the
    // shader object when glDeleteShader is called. This ensures the ShaderProgramID handles used in
    // SetupReplayContextShared() are consistent with the ShaderProgramID handles used by the app.
    for (gl::ShaderType shaderType : executable.getLinkedShaderStages())
    {
        gl::Shader *attachedShader = program->getAttachedShader(shaderType);
        if (attachedShader == nullptr)
        {
            Capture(setupCalls,
                    CaptureDetachShader(replayState, true, id, tempShaderIDTracker[shaderType]));
        }
        Capture(setupCalls,
                CaptureDeleteShader(replayState, true, tempShaderIDTracker[shaderType]));
    }
}

// TODO(http://anglebug.com/42263204): Improve reset/restore call generation
// There are multiple ways to track reset calls for individual resources. For now, we are tracking
// separate lists of instructions that mirror the calls created during mid-execution setup. Other
// methods could involve passing the original CallCaptures to this function, or tracking the
// indices of original setup calls.
void CaptureBufferResetCalls(const gl::Context *context,
                             const gl::State &replayState,
                             ResourceTracker *resourceTracker,
                             gl::BufferID *id,
                             const gl::Buffer *buffer)
{
    GLuint bufferID = (*id).value;

    // Track this as a starting resource that may need to be restored.
    TrackedResource &trackedBuffers =
        resourceTracker->getTrackedResource(context->id(), ResourceIDType::Buffer);

    // Track calls to regenerate a given buffer
    ResourceCalls &bufferRegenCalls = trackedBuffers.getResourceRegenCalls();
    Capture(&bufferRegenCalls[bufferID], CaptureGenBuffers(replayState, true, 1, id));
    MaybeCaptureUpdateResourceIDs(context, resourceTracker, &bufferRegenCalls[bufferID]);

    // Call glBufferStorageEXT when regenerating immutable buffers,
    // as we can't call glBufferData on restore.
    if (buffer->isImmutable())
    {
        Capture(&bufferRegenCalls[bufferID],
                CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));
        Capture(
            &bufferRegenCalls[bufferID],
            CaptureBufferStorageEXT(replayState, true, gl::BufferBinding::Array,
                                    static_cast<GLsizeiptr>(buffer->getSize()),
                                    buffer->getMapPointer(), buffer->getStorageExtUsageFlags()));
    }

    // Track calls to restore a given buffer's contents
    ResourceCalls &bufferRestoreCalls = trackedBuffers.getResourceRestoreCalls();
    Capture(&bufferRestoreCalls[bufferID],
            CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));

    // Mutable buffers will be restored here using glBufferData.
    // Immutable buffers need to be restored below, after maping.
    if (!buffer->isImmutable())
    {
        Capture(&bufferRestoreCalls[bufferID],
                CaptureBufferData(replayState, true, gl::BufferBinding::Array,
                                  static_cast<GLsizeiptr>(buffer->getSize()),
                                  buffer->getMapPointer(), buffer->getUsage()));
    }

    if (buffer->isMapped())
    {
        // Track calls to remap a buffer that started as mapped
        BufferCalls &bufferMapCalls = resourceTracker->getBufferMapCalls();

        Capture(&bufferMapCalls[bufferID],
                CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));

        void *dontCare             = nullptr;
        CallCapture mapBufferRange = CaptureMapBufferRange(
            replayState, true, gl::BufferBinding::Array,
            static_cast<GLsizeiptr>(buffer->getMapOffset()),
            static_cast<GLsizeiptr>(buffer->getMapLength()), buffer->getAccessFlags(), dontCare);
        CaptureCustomMapBuffer("MapBufferRange", mapBufferRange, bufferMapCalls[bufferID],
                               buffer->id());

        // Restore immutable mapped buffers. Needs to happen after mapping.
        if (buffer->isImmutable())
        {
            ParamBuffer dataParamBuffer;
            dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);
            ParamCapture captureData("source", ParamType::TvoidConstPointer);
            CaptureMemory(buffer->getMapPointer(), static_cast<GLsizeiptr>(buffer->getSize()),
                          &captureData);
            dataParamBuffer.addParam(std::move(captureData));
            dataParamBuffer.addValueParam<GLsizeiptr>("size", ParamType::TGLsizeiptr,
                                                      static_cast<GLsizeiptr>(buffer->getSize()));
            bufferMapCalls[bufferID].emplace_back("UpdateClientBufferData",
                                                  std::move(dataParamBuffer));
        }
    }

    // Track calls unmap a buffer that started as unmapped
    BufferCalls &bufferUnmapCalls = resourceTracker->getBufferUnmapCalls();
    Capture(&bufferUnmapCalls[bufferID],
            CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, *id));
    Capture(&bufferUnmapCalls[bufferID],
            CaptureUnmapBuffer(replayState, true, gl::BufferBinding::Array, GL_TRUE));
}

void CaptureFenceSyncResetCalls(const gl::Context *context,
                                const gl::State &replayState,
                                ResourceTracker *resourceTracker,
                                gl::SyncID syncID,
                                GLsync syncObject,
                                const gl::Sync *sync)
{
    // Track calls to regenerate a given fence sync
    FenceSyncCalls &fenceSyncRegenCalls = resourceTracker->getFenceSyncRegenCalls();
    CallCapture fenceSync =
        CaptureFenceSync(replayState, true, sync->getCondition(), sync->getFlags(), syncObject);
    CaptureCustomFenceSync(fenceSync, fenceSyncRegenCalls[syncID]);
    MaybeCaptureUpdateResourceIDs(context, resourceTracker, &fenceSyncRegenCalls[syncID]);
}

void CaptureEGLSyncResetCalls(const gl::Context *context,
                              const gl::State &replayState,
                              ResourceTracker *resourceTracker,
                              egl::SyncID eglSyncID,
                              EGLSync eglSyncObject,
                              const egl::Sync *eglSync)
{
    // Track this as a starting resource that may need to be restored.
    TrackedResource &trackedEGLSyncs =
        resourceTracker->getTrackedResource(context->id(), ResourceIDType::egl_Sync);

    // Track calls to regenerate a given buffer
    ResourceCalls &eglSyncRegenCalls = trackedEGLSyncs.getResourceRegenCalls();

    CallCapture createEGLSync =
        CaptureCreateSyncKHR(nullptr, true, context->getDisplay(), eglSync->getType(),
                             eglSync->getAttributeMap(), eglSyncObject);
    CaptureCustomCreateEGLSync("CreateEGLSyncKHR", createEGLSync,
                               eglSyncRegenCalls[eglSyncID.value]);
    MaybeCaptureUpdateResourceIDs(context, resourceTracker, &eglSyncRegenCalls[eglSyncID.value]);
}

void CaptureBufferBindingResetCalls(const gl::State &replayState,
                                    ResourceTracker *resourceTracker,
                                    gl::BufferBinding binding,
                                    gl::BufferID id)
{
    // Track the calls to reset it
    std::vector<CallCapture> &bufferBindingCalls = resourceTracker->getBufferBindingCalls();
    Capture(&bufferBindingCalls, CaptureBindBuffer(replayState, true, binding, id));
}

void CaptureIndexedBuffers(const gl::State &glState,
                           const gl::BufferVector &indexedBuffers,
                           gl::BufferBinding binding,
                           std::vector<CallCapture> *setupCalls)
{
    for (unsigned int index = 0; index < indexedBuffers.size(); ++index)
    {
        const gl::OffsetBindingPointer<gl::Buffer> &buffer = indexedBuffers[index];

        if (buffer.get() == nullptr)
        {
            continue;
        }

        GLintptr offset       = buffer.getOffset();
        GLsizeiptr size       = buffer.getSize();
        gl::BufferID bufferID = buffer.get()->id();

        // Context::bindBufferBase() calls Context::bindBufferRange() with size and offset = 0.
        if ((offset == 0) && (size == 0))
        {
            Capture(setupCalls, CaptureBindBufferBase(glState, true, binding, index, bufferID));
        }
        else
        {
            Capture(setupCalls,
                    CaptureBindBufferRange(glState, true, binding, index, bufferID, offset, size));
        }
    }
}

void CaptureDefaultVertexAttribs(const gl::State &replayState,
                                 const gl::State &apiState,
                                 std::vector<CallCapture> *setupCalls)
{
    const std::vector<gl::VertexAttribCurrentValueData> &currentValues =
        apiState.getVertexAttribCurrentValues();

    for (GLuint attribIndex = 0; attribIndex < currentValues.size(); ++attribIndex)
    {
        const gl::VertexAttribCurrentValueData &defaultValue = currentValues[attribIndex];
        if (!IsDefaultCurrentValue(defaultValue))
        {
            Capture(setupCalls, CaptureVertexAttrib4fv(replayState, true, attribIndex,
                                                       defaultValue.Values.FloatValues));
        }
    }
}

void CaptureBindFramebufferForContext(const gl::Context *context,
                                      std::vector<CallCapture> *calls,
                                      FramebufferCaptureFuncs &framebufferFuncs,
                                      const gl::State &glState,
                                      GLenum target,
                                      const gl::FramebufferID &id)
{
    Capture(calls, framebufferFuncs.bindFramebuffer(glState, true, target, id));

    // Set current context for this CallCapture since we track these in gFramebufferMapPerContext
    calls->back().contextID = context->id();
}

void CompressPalettedTexture(angle::MemoryBuffer &data,
                             angle::MemoryBuffer &tmp,
                             const gl::InternalFormat &compressedFormat,
                             const gl::Extents &extents)
{
    constexpr int uncompressedChannelCount = 4;

    uint32_t indexBits = 0, redBlueBits = 0, greenBits = 0, alphaBits = 0;
    switch (compressedFormat.internalFormat)
    {
        case GL_PALETTE4_RGB8_OES:
            indexBits   = 4;
            redBlueBits = 8;
            greenBits   = 8;
            alphaBits   = 0;
            break;
        case GL_PALETTE4_RGBA8_OES:
            indexBits   = 4;
            redBlueBits = 8;
            greenBits   = 8;
            alphaBits   = 8;
            break;
        case GL_PALETTE4_R5_G6_B5_OES:
            indexBits   = 4;
            redBlueBits = 5;
            greenBits   = 6;
            alphaBits   = 0;
            break;
        case GL_PALETTE4_RGBA4_OES:
            indexBits   = 4;
            redBlueBits = 4;
            greenBits   = 4;
            alphaBits   = 4;
            break;
        case GL_PALETTE4_RGB5_A1_OES:
            indexBits   = 4;
            redBlueBits = 5;
            greenBits   = 5;
            alphaBits   = 1;
            break;
        case GL_PALETTE8_RGB8_OES:
            indexBits   = 8;
            redBlueBits = 8;
            greenBits   = 8;
            alphaBits   = 0;
            break;
        case GL_PALETTE8_RGBA8_OES:
            indexBits   = 8;
            redBlueBits = 8;
            greenBits   = 8;
            alphaBits   = 8;
            break;
        case GL_PALETTE8_R5_G6_B5_OES:
            indexBits   = 8;
            redBlueBits = 5;
            greenBits   = 6;
            alphaBits   = 0;
            break;
        case GL_PALETTE8_RGBA4_OES:
            indexBits   = 8;
            redBlueBits = 4;
            greenBits   = 4;
            alphaBits   = 4;
            break;
        case GL_PALETTE8_RGB5_A1_OES:
            indexBits   = 8;
            redBlueBits = 5;
            greenBits   = 5;
            alphaBits   = 1;
            break;

        default:
            UNREACHABLE();
            break;
    }

    bool result = data.resize(
        // Palette size
        (1 << indexBits) * (2 * redBlueBits + greenBits + alphaBits) / 8 +
        // Texels size
        indexBits * extents.width * extents.height * extents.depth / 8);
    ASSERT(result);

    angle::StoreRGBA8ToPalettedImpl(
        extents.width, extents.height, extents.depth, indexBits, redBlueBits, greenBits, alphaBits,
        tmp.data(),
        uncompressedChannelCount * extents.width,                   // inputRowPitch
        uncompressedChannelCount * extents.width * extents.height,  // inputDepthPitch
        data.data(),                                                // output
        indexBits * extents.width / 8,                              // outputRowPitch
        indexBits * extents.width * extents.height / 8              // outputDepthPitch
    );
}

bool BlendStateEqualPerDrawBuffer(const gl::State &currentState)
{
    const gl::BlendStateExt &currentBlend = currentState.getBlendStateExt();

    // For each buffer, compare again the zero buffer state
    for (unsigned int idx = 1; idx < currentBlend.getDrawBufferCount(); idx++)
    {
        if (currentBlend.getEnabledMask().test(0) != currentBlend.getEnabledMask().test(idx))
        {
            return false;
        }

        if (currentBlend.getSrcColorIndexed(0) != currentBlend.getSrcColorIndexed(idx) ||
            currentBlend.getDstColorIndexed(0) != currentBlend.getDstColorIndexed(idx) ||
            currentBlend.getSrcAlphaIndexed(0) != currentBlend.getSrcAlphaIndexed(idx) ||
            currentBlend.getDstAlphaIndexed(0) != currentBlend.getDstAlphaIndexed(idx))
        {
            return false;
        }

        if (currentBlend.getEquationColorIndexed(0) != currentBlend.getEquationColorIndexed(idx) ||
            currentBlend.getEquationAlphaIndexed(0) != currentBlend.getEquationAlphaIndexed(idx))
        {
            return false;
        }

        if (currentBlend.getColorMaskIndexed(0) != currentBlend.getColorMaskIndexed(idx))
        {
            return false;
        }
    }

    // If we reach here, all buffer blend states match the zero buffer
    return true;
}

// Capture the setup of the state that's shared by all of the contexts in the share group
// See IsSharedObjectResource for the list of objects covered here.
void CaptureShareGroupMidExecutionSetup(
    gl::Context *context,
    std::vector<CallCapture> *setupCalls,
    ResourceTracker *resourceTracker,
    gl::State &replayState,
    const PackedEnumMap<ResourceIDType, uint32_t> &maxAccessedResourceIDs)
{
    FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
    const gl::State &apiState              = context->getState();

    // Small helper function to make the code more readable.
    auto cap = [setupCalls](CallCapture &&call) { setupCalls->emplace_back(std::move(call)); };

    // Capture Buffer data.
    const gl::BufferManager &buffers = apiState.getBufferManagerForCapture();
    for (const auto &bufferIter : gl::UnsafeResourceMapIter(buffers.getResourcesForCapture()))
    {
        gl::BufferID id    = {bufferIter.first};
        gl::Buffer *buffer = bufferIter.second;

        if (id.value == 0)
        {
            continue;
        }

        // Generate binding.
        cap(CaptureGenBuffers(replayState, true, 1, &id));

        resourceTracker->getTrackedResource(context->id(), ResourceIDType::Buffer)
            .getStartingResources()
            .insert(id.value);

        MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);

        // glBufferData. Would possibly be better implemented using a getData impl method.
        // Saving buffers that are mapped during a swap is not yet handled.
        if (buffer->getSize() == 0)
        {
            resourceTracker->setStartingBufferMapped(buffer->id().value, false);
            continue;
        }

        // Remember if the buffer was already mapped
        GLboolean bufferMapped = buffer->isMapped();

        // If needed, map the buffer so we can capture its contents
        if (!bufferMapped)
        {
            (void)buffer->mapRange(context, 0, static_cast<GLsizeiptr>(buffer->getSize()),
                                   GL_MAP_READ_BIT);
        }

        // Always use the array buffer binding point to upload data to keep things simple.
        if (buffer != replayState.getArrayBuffer())
        {
            replayState.setBufferBinding(context, gl::BufferBinding::Array, buffer);
            cap(CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, id));
        }

        if (buffer->isImmutable())
        {
            cap(CaptureBufferStorageEXT(replayState, true, gl::BufferBinding::Array,
                                        static_cast<GLsizeiptr>(buffer->getSize()),
                                        buffer->getMapPointer(),
                                        buffer->getStorageExtUsageFlags()));
        }
        else
        {
            cap(CaptureBufferData(replayState, true, gl::BufferBinding::Array,
                                  static_cast<GLsizeiptr>(buffer->getSize()),
                                  buffer->getMapPointer(), buffer->getUsage()));
        }

        if (bufferMapped)
        {
            void *dontCare = nullptr;
            CallCapture mapBufferRange =
                CaptureMapBufferRange(replayState, true, gl::BufferBinding::Array,
                                      static_cast<GLsizeiptr>(buffer->getMapOffset()),
                                      static_cast<GLsizeiptr>(buffer->getMapLength()),
                                      buffer->getAccessFlags(), dontCare);
            CaptureCustomMapBuffer("MapBufferRange", mapBufferRange, *setupCalls, buffer->id());

            resourceTracker->setStartingBufferMapped(buffer->id().value, true);

            frameCaptureShared->trackBufferMapping(
                context, &setupCalls->back(), buffer->id(), buffer,
                static_cast<GLsizeiptr>(buffer->getMapOffset()),
                static_cast<GLsizeiptr>(buffer->getMapLength()),
                (buffer->getAccessFlags() & GL_MAP_WRITE_BIT) != 0,
                (buffer->getStorageExtUsageFlags() & GL_MAP_COHERENT_BIT_EXT) != 0,
                (buffer->getStorageExtUsageFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0);
        }
        else
        {
            resourceTracker->setStartingBufferMapped(buffer->id().value, false);
        }

        // Generate the calls needed to restore this buffer to original state for frame looping
        CaptureBufferResetCalls(context, replayState, resourceTracker, &id, buffer);

        // Unmap the buffer if it wasn't already mapped
        if (!bufferMapped)
        {
            GLboolean dontCare;
            (void)buffer->unmap(context, &dontCare);
        }
    }

    // Clear the array buffer binding.
    if (replayState.getTargetBuffer(gl::BufferBinding::Array))
    {
        cap(CaptureBindBuffer(replayState, true, gl::BufferBinding::Array, {0}));
        replayState.setBufferBinding(context, gl::BufferBinding::Array, nullptr);
    }

    // Set a unpack alignment of 1. Otherwise, computeRowPitch() will compute the wrong value,
    // leading to a crash in memcpy() when capturing the texture contents.
    gl::PixelUnpackState &currentUnpackState = replayState.getUnpackState();
    if (currentUnpackState.alignment != 1)
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackAlignment, 1));
        replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(1);
    }

    const egl::ImageMap eglImageMap = context->getDisplay()->getImagesForCapture();
    for (const auto &[eglImageID, eglImage] : eglImageMap)
    {
        // Track this as a starting resource that may need to be restored.
        TrackedResource &trackedImages =
            resourceTracker->getTrackedResource(context->id(), ResourceIDType::Image);
        trackedImages.getStartingResources().insert(eglImageID);

        ResourceCalls &imageRegenCalls = trackedImages.getResourceRegenCalls();
        CallVector imageGenCalls({setupCalls, &imageRegenCalls[eglImageID]});

        auto eglImageAttribIter = resourceTracker->getImageToAttribTable().find(
            reinterpret_cast<EGLImage>(static_cast<uintptr_t>(eglImageID)));

        // EGLCreateImage calls commonly specify no attribs so use an empty default
        // if needed
        static const angle::base::NoDestructor<egl::AttributeMap> kDefaultAttribs;
        const egl::AttributeMap &attribs =
            (eglImageAttribIter != resourceTracker->getImageToAttribTable().end())
                ? eglImageAttribIter->second
                : *kDefaultAttribs;

        for (std::vector<CallCapture> *calls : imageGenCalls)
        {
            // Create the image on demand with the same attrib retrieved above
            CallCapture eglCreateImageKHRCall = egl::CaptureCreateImageKHR(
                nullptr, true, nullptr, context->id(), EGL_GL_TEXTURE_2D,
                reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(0)), attribs,
                reinterpret_cast<EGLImage>(static_cast<uintptr_t>(eglImageID)));

            // Convert the CaptureCreateImageKHR CallCapture to the customized CallCapture
            CaptureCustomCreateEGLImage(context, "CreateEGLImageKHR", eglImage->getWidth(),
                                        eglImage->getHeight(), eglCreateImageKHRCall, *calls);
        }
    }

    // Capture Texture setup and data.
    const gl::TextureManager &textures = apiState.getTextureManagerForCapture();

    for (const auto &textureIter : gl::UnsafeResourceMapIter(textures.getResourcesForCapture()))
    {
        gl::TextureID id     = {textureIter.first};
        gl::Texture *texture = textureIter.second;

        if (id.value == 0 || texture == nullptr)
        {
            continue;
        }

        size_t textureSetupStart = setupCalls->size();

        // Track this as a starting resource that may need to be restored.
        TrackedResource &trackedTextures =
            resourceTracker->getTrackedResource(context->id(), ResourceIDType::Texture);
        ResourceSet &startingTextures = trackedTextures.getStartingResources();
        startingTextures.insert(id.value);

        // For the initial texture creation calls, track in the generate list
        ResourceCalls &textureRegenCalls = trackedTextures.getResourceRegenCalls();
        CallVector texGenCalls({setupCalls, &textureRegenCalls[id.value]});

        // Gen the Texture.
        for (std::vector<CallCapture> *calls : texGenCalls)
        {
            Capture(calls, CaptureGenTextures(replayState, true, 1, &id));
            MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
        }

        // For the remaining texture setup calls, track in the restore list
        ResourceCalls &textureRestoreCalls = trackedTextures.getResourceRestoreCalls();
        CallVector texSetupCalls({setupCalls, &textureRestoreCalls[id.value]});

        // For each texture, set the correct active texture and binding
        // There is similar code in CaptureMidExecutionSetup for per-context setup
        const gl::TextureBindingMap &currentBoundTextures = apiState.getBoundTexturesForCapture();
        const gl::TextureBindingVector &currentBindings = currentBoundTextures[texture->getType()];
        const gl::TextureBindingVector &replayBindings =
            replayState.getBoundTexturesForCapture()[texture->getType()];
        ASSERT(currentBindings.size() == replayBindings.size());

        // Look up the replay binding
        size_t replayActiveTexture = replayState.getActiveSampler();
        // If there ends up being no binding, just use the replay binding
        // TODO: We may want to start using index 0 for everything, mark it dirty, and restore it
        size_t currentActiveTexture = replayActiveTexture;

        // Iterate through current bindings and find the correct index for this texture ID
        for (size_t bindingIndex = 0; bindingIndex < currentBindings.size(); ++bindingIndex)
        {
            gl::TextureID currentTextureID = currentBindings[bindingIndex].id();
            gl::TextureID replayTextureID  = replayBindings[bindingIndex].id();

            // Only check the texture we care about
            if (currentTextureID == texture->id())
            {
                // If the binding doesn't match, track it
                if (currentTextureID != replayTextureID)
                {
                    currentActiveTexture = bindingIndex;
                }

                break;
            }
        }

        // Set the correct active texture before performing any state changes, including binding
        if (currentActiveTexture != replayActiveTexture)
        {
            for (std::vector<CallCapture> *calls : texSetupCalls)
            {
                Capture(calls, CaptureActiveTexture(
                                   replayState, true,
                                   GL_TEXTURE0 + static_cast<GLenum>(currentActiveTexture)));
            }
            replayState.getMutablePrivateStateForCapture()->setActiveSampler(
                static_cast<unsigned int>(currentActiveTexture));
        }

        for (std::vector<CallCapture> *calls : texSetupCalls)
        {
            Capture(calls, CaptureBindTexture(replayState, true, texture->getType(), id));
        }
        replayState.setSamplerTexture(context, texture->getType(), texture);

        // Capture sampler parameter states.
        // TODO(jmadill): More sampler / texture states. http://anglebug.com/42262323
        gl::SamplerState defaultSamplerState =
            gl::SamplerState::CreateDefaultForTarget(texture->getType());
        const gl::SamplerState &textureSamplerState = texture->getSamplerState();

        auto capTexParam = [&replayState, texture, &texSetupCalls](GLenum pname, GLint param) {
            for (std::vector<CallCapture> *calls : texSetupCalls)
            {
                Capture(calls,
                        CaptureTexParameteri(replayState, true, texture->getType(), pname, param));
            }
        };

        auto capTexParamf = [&replayState, texture, &texSetupCalls](GLenum pname, GLfloat param) {
            for (std::vector<CallCapture> *calls : texSetupCalls)
            {
                Capture(calls,
                        CaptureTexParameterf(replayState, true, texture->getType(), pname, param));
            }
        };

        auto capTexParams = [&replayState, texture, &texSetupCalls](GLenum pname,
                                                                    const GLint *params) {
            for (std::vector<CallCapture> *calls : texSetupCalls)
            {
                Capture(calls, CaptureTexParameteriv(replayState, true, texture->getType(), pname,
                                                     params));
            }
        };

        if (textureSamplerState.getMinFilter() != defaultSamplerState.getMinFilter())
        {
            capTexParam(GL_TEXTURE_MIN_FILTER, textureSamplerState.getMinFilter());
        }

        if (textureSamplerState.getMagFilter() != defaultSamplerState.getMagFilter())
        {
            capTexParam(GL_TEXTURE_MAG_FILTER, textureSamplerState.getMagFilter());
        }

        if (textureSamplerState.getWrapR() != defaultSamplerState.getWrapR())
        {
            capTexParam(GL_TEXTURE_WRAP_R, textureSamplerState.getWrapR());
        }

        if (textureSamplerState.getWrapS() != defaultSamplerState.getWrapS())
        {
            capTexParam(GL_TEXTURE_WRAP_S, textureSamplerState.getWrapS());
        }

        if (textureSamplerState.getWrapT() != defaultSamplerState.getWrapT())
        {
            capTexParam(GL_TEXTURE_WRAP_T, textureSamplerState.getWrapT());
        }

        if (textureSamplerState.getMinLod() != defaultSamplerState.getMinLod())
        {
            capTexParamf(GL_TEXTURE_MIN_LOD, textureSamplerState.getMinLod());
        }

        if (textureSamplerState.getMaxLod() != defaultSamplerState.getMaxLod())
        {
            capTexParamf(GL_TEXTURE_MAX_LOD, textureSamplerState.getMaxLod());
        }

        if (textureSamplerState.getCompareMode() != defaultSamplerState.getCompareMode())
        {
            capTexParam(GL_TEXTURE_COMPARE_MODE, textureSamplerState.getCompareMode());
        }

        if (textureSamplerState.getCompareFunc() != defaultSamplerState.getCompareFunc())
        {
            capTexParam(GL_TEXTURE_COMPARE_FUNC, textureSamplerState.getCompareFunc());
        }

        // Texture parameters
        if (texture->getSwizzleRed() != GL_RED)
        {
            capTexParam(GL_TEXTURE_SWIZZLE_R, texture->getSwizzleRed());
        }

        if (texture->getSwizzleGreen() != GL_GREEN)
        {
            capTexParam(GL_TEXTURE_SWIZZLE_G, texture->getSwizzleGreen());
        }

        if (texture->getSwizzleBlue() != GL_BLUE)
        {
            capTexParam(GL_TEXTURE_SWIZZLE_B, texture->getSwizzleBlue());
        }

        if (texture->getSwizzleAlpha() != GL_ALPHA)
        {
            capTexParam(GL_TEXTURE_SWIZZLE_A, texture->getSwizzleAlpha());
        }

        if (texture->getBaseLevel() != 0)
        {
            capTexParam(GL_TEXTURE_BASE_LEVEL, texture->getBaseLevel());
        }

        if (texture->getMaxLevel() != 1000)
        {
            capTexParam(GL_TEXTURE_MAX_LEVEL, texture->getMaxLevel());
        }

        if (context->isGLES1() && texture->getCrop() != gl::Rectangle())
        {
            const gl::Rectangle &crop = texture->getCrop();
            const GLint params[4]{crop.x, crop.y, crop.width, crop.height};
            capTexParams(GL_TEXTURE_CROP_RECT_OES, params);
        }

        // If the texture is immutable, initialize it with TexStorage
        if (texture->getImmutableFormat())
        {
            // We can only call TexStorage *once* on an immutable texture, so it needs special
            // handling. To solve this, immutable textures will have a BindTexture and TexStorage as
            // part of their textureRegenCalls. The resulting regen sequence will be:
            //
            //    const GLuint glDeleteTextures_texturesPacked_0[] = { gTextureMap[52] };
            //    glDeleteTextures(1, glDeleteTextures_texturesPacked_0);
            //    glGenTextures(1, reinterpret_cast<GLuint *>(gReadBuffer));
            //    UpdateTextureID(52, 0);
            //    glBindTexture(GL_TEXTURE_2D, gTextureMap[52]);
            //    glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8, 256, 512);

            // Bind the texture first just for textureRegenCalls
            Capture(&textureRegenCalls[id.value],
                    CaptureBindTexture(replayState, true, texture->getType(), id));

            // Then add TexStorage to texGenCalls instead of texSetupCalls
            for (std::vector<CallCapture> *calls : texGenCalls)
            {
                CaptureTextureStorage(calls, &replayState, texture);
            }
        }

        // Iterate texture levels and layers.
        gl::ImageIndexIterator imageIter = gl::ImageIndexIterator::MakeGeneric(
            texture->getType(), 0, texture->getMipmapMaxLevel() + 1, gl::ImageIndex::kEntireLevel,
            gl::ImageIndex::kEntireLevel);
        while (imageIter.hasNext())
        {
            gl::ImageIndex index = imageIter.next();

            const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(index);

            if (desc.size.empty())
            {
                continue;
            }

            const gl::InternalFormat &format = *desc.format.info;

            bool supportedType = (index.getType() == gl::TextureType::_2D ||
                                  index.getType() == gl::TextureType::_3D ||
                                  index.getType() == gl::TextureType::_2DArray ||
                                  index.getType() == gl::TextureType::Buffer ||
                                  index.getType() == gl::TextureType::CubeMap ||
                                  index.getType() == gl::TextureType::CubeMapArray ||
                                  index.getType() == gl::TextureType::External);

            // Check for supported textures
            if (!supportedType)
            {
                ERR() << "Unsupported texture type: " << index.getType();
                UNREACHABLE();
            }

            if (index.getType() == gl::TextureType::Buffer)
            {
                // The buffer contents are already backed up, but we need to emit the TexBuffer
                // binding calls
                for (std::vector<CallCapture> *calls : texSetupCalls)
                {
                    CaptureTextureContents(calls, &replayState, texture, index, desc, 0, 0);
                }
                continue;
            }

            if (index.getType() == gl::TextureType::External)
            {
                // Lookup the eglImage ID associated with this texture when the app issued
                // glEGLImageTargetTexture2DOES()
                auto eglImageIter = resourceTracker->getTextureIDToImageTable().find(id.value);
                egl::ImageID eglImageID;
                if (eglImageIter != resourceTracker->getTextureIDToImageTable().end())
                {
                    eglImageID = eglImageIter->second;
                }
                else
                {
                    // Original image was deleted, just use a placeholder ID for now.
                    // UpdateEGLImageData() will create the staging texture at bind
                    // time
                    eglImageID = {maxAccessedResourceIDs[ResourceIDType::Image] + 1};
                }

                // Output an UpdateEGLImageData() call immediately before the external bind call to
                // prepare a texture with either a representation of the AHB or a default texture
                // if AHB retrieval fails
                for (std::vector<CallCapture> *calls : texSetupCalls)
                {
                    auto imageEntry = resourceTracker->getImageDataMap().find(eglImageID);

                    ParamBuffer params;
                    params.addValueParam("imageID", ParamType::TGLuint, eglImageID.value);
                    params.addValueParam("width", ParamType::TGLsizei,
                                         static_cast<GLsizei>(desc.size.width));
                    params.addValueParam("height", ParamType::TGLsizei,
                                         static_cast<GLsizei>(desc.size.height));

                    ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer);
                    if (imageEntry != resourceTracker->getImageDataMap().end())
                    {
                        pixelsParam.value.voidConstPointerVal = imageEntry->second.data();
                        pixelsParam.data.push_back(imageEntry->second);
                    }
                    else
                    {
                        pixelsParam.value.voidConstPointerVal = nullptr;
                    }
                    params.addParam(std::move(pixelsParam));

                    calls->emplace_back("UpdateEGLImageData", std::move(params));

                    Capture(calls, CaptureEGLImageTargetTexture2DOES(
                                       replayState, true, gl::TextureType::External, eglImageID));
                }
            }
            else if (context->getExtensions().getImageANGLE)
            {
                // Use ANGLE_get_image to read back pixel data.
                angle::MemoryBuffer data;

                const gl::Extents extents(desc.size.width, desc.size.height, desc.size.depth);

                gl::PixelPackState packState;
                packState.alignment = 1;

                if (format.paletted)
                {
                    // Read back the uncompressed texture, then re-compress it
                    // to store in the trace.

                    angle::MemoryBuffer tmp;

                    // The uncompressed format (R8G8B8A8) is 4 bytes per texel
                    bool result = tmp.resize(4 * extents.width * extents.height * extents.depth);
                    ASSERT(result);

                    (void)texture->getTexImage(context, packState, nullptr, index.getTarget(),
                                               index.getLevelIndex(), GL_RGBA, GL_UNSIGNED_BYTE,
                                               tmp.data());

                    CompressPalettedTexture(data, tmp, format, extents);
                }
                else if (format.compressed)
                {
                    // Calculate the size needed to store the compressed level
                    GLuint sizeInBytes;
                    bool result = format.computeCompressedImageSize(extents, &sizeInBytes);
                    ASSERT(result);

                    result = data.resize(sizeInBytes);
                    ASSERT(result);

                    (void)texture->getCompressedTexImage(context, packState, nullptr,
                                                         index.getTarget(), index.getLevelIndex(),
                                                         data.data());
                }
                else
                {
                    GLenum getFormat = format.format;
                    GLenum getType   = format.type;

                    const gl::PixelUnpackState &unpack = apiState.getUnpackState();

                    GLuint endByte = 0;
                    bool unpackSize =
                        format.computePackUnpackEndByte(getType, extents, unpack, true, &endByte);
                    ASSERT(unpackSize);

                    bool result = data.resize(endByte);
                    ASSERT(result);

                    (void)texture->getTexImage(context, packState, nullptr, index.getTarget(),
                                               index.getLevelIndex(), getFormat, getType,
                                               data.data());
                }

                for (std::vector<CallCapture> *calls : texSetupCalls)
                {
                    CaptureTextureContents(calls, &replayState, texture, index, desc,
                                           static_cast<GLuint>(data.size()), data.data());
                }
            }
            else
            {
                for (std::vector<CallCapture> *calls : texSetupCalls)
                {
                    CaptureTextureContents(calls, &replayState, texture, index, desc, 0, nullptr);
                }
            }
        }

        size_t textureSetupEnd = setupCalls->size();

        // Mark the range of calls used to setup this texture
        frameCaptureShared->markResourceSetupCallsInactive(
            setupCalls, ResourceIDType::Texture, id.value,
            gl::Range<size_t>(textureSetupStart, textureSetupEnd));
    }

    // Capture Renderbuffers.
    const gl::RenderbufferManager &renderbuffers = apiState.getRenderbufferManagerForCapture();
    FramebufferCaptureFuncs framebufferFuncs(context->isGLES1());

    for (const auto &renderbufIter :
         gl::UnsafeResourceMapIter(renderbuffers.getResourcesForCapture()))
    {
        gl::RenderbufferID id                = {renderbufIter.first};
        const gl::Renderbuffer *renderbuffer = renderbufIter.second;

        // Track this as a starting resource that may need to be restored.
        TrackedResource &trackedRenderbuffers =
            resourceTracker->getTrackedResource(context->id(), ResourceIDType::Renderbuffer);
        ResourceSet &startingRenderbuffers = trackedRenderbuffers.getStartingResources();
        startingRenderbuffers.insert(id.value);

        // For the initial renderbuffer creation calls, track in the generate list
        ResourceCalls &renderbufferRegenCalls = trackedRenderbuffers.getResourceRegenCalls();
        CallVector rbGenCalls({setupCalls, &renderbufferRegenCalls[id.value]});

        // Generate renderbuffer id.
        for (std::vector<CallCapture> *calls : rbGenCalls)
        {
            Capture(calls, framebufferFuncs.genRenderbuffers(replayState, true, 1, &id));
            MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
            Capture(calls,
                    framebufferFuncs.bindRenderbuffer(replayState, true, GL_RENDERBUFFER, id));
        }

        GLenum internalformat = renderbuffer->getFormat().info->internalFormat;

        // Depending on the multisampling mode, we have to issue different commands
        switch (renderbuffer->getMultisamplingMode())
        {
            case gl::MultisamplingMode::Regular:
                if (renderbuffer->getSamples() > 0)
                {
                    for (std::vector<CallCapture> *calls : rbGenCalls)
                    {
                        Capture(calls, CaptureRenderbufferStorageMultisample(
                                           replayState, true, GL_RENDERBUFFER,
                                           renderbuffer->getSamples(), internalformat,
                                           renderbuffer->getWidth(), renderbuffer->getHeight()));
                    }
                }
                else
                {
                    for (std::vector<CallCapture> *calls : rbGenCalls)
                    {
                        Capture(calls, framebufferFuncs.renderbufferStorage(
                                           replayState, true, GL_RENDERBUFFER, internalformat,
                                           renderbuffer->getWidth(), renderbuffer->getHeight()));
                    }
                }
                break;
            case gl::MultisamplingMode::MultisampledRenderToTexture:
                // Note we use getState().getSamples() here because MSRTT means this reports as
                // single sampled, but was created with <n> samples internally, and we have to
                // recreate that.
                for (std::vector<CallCapture> *calls : rbGenCalls)
                {
                    Capture(calls, CaptureRenderbufferStorageMultisampleEXT(
                                       replayState, true, GL_RENDERBUFFER,
                                       renderbuffer->getState().getSamples(), internalformat,
                                       renderbuffer->getWidth(), renderbuffer->getHeight()));
                }
                break;
            default:
                UNREACHABLE();
                break;
        }

        // TODO: Capture renderbuffer contents. http://anglebug.com/42262323
    }

    // Capture Shaders and Programs.
    const gl::ShaderProgramManager &shadersAndPrograms =
        apiState.getShaderProgramManagerForCapture();
    const gl::ResourceMap<gl::Shader, gl::ShaderProgramID> &shaders =
        shadersAndPrograms.getShadersForCapture();
    const gl::ResourceMap<gl::Program, gl::ShaderProgramID> &programs =
        shadersAndPrograms.getProgramsForCaptureAndPerf();

    TrackedResource &trackedShaderPrograms =
        resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram);

    // Capture Program binary state.
    gl::ShaderProgramID tempShaderStartID = {resourceTracker->getMaxShaderPrograms()};
    std::map<gl::ShaderProgramID, std::vector<gl::ShaderProgramID>> deferredAttachCalls;
    for (const auto &programIter : gl::UnsafeResourceMapIter(programs))
    {
        gl::ShaderProgramID id = {programIter.first};
        gl::Program *program   = programIter.second;

        // Unlinked programs don't have an executable so track in case linking is deferred
        // Programs are shared by contexts in the share group and only need to be captured once.
        if (!program->isLinked())
        {
            frameCaptureShared->setDeferredLinkProgram(id);

            if (program->getAttachedShadersCount() > 0)
            {
                // AttachShader calls will be generated at shader-handling time
                for (gl::ShaderType shaderType : gl::AllShaderTypes())
                {
                    gl::Shader *shader = program->getAttachedShader(shaderType);
                    if (shader != nullptr)
                    {
                        deferredAttachCalls[shader->getHandle()].push_back(id);
                    }
                }
            }
            else
            {
                WARN() << "Deferred attachment of shaders is not yet supported";
            }
        }

        size_t programSetupStart = setupCalls->size();

        // Create two lists for program regen calls
        ResourceCalls &shaderProgramRegenCalls = trackedShaderPrograms.getResourceRegenCalls();
        CallVector programRegenCalls({setupCalls, &shaderProgramRegenCalls[id.value]});

        for (std::vector<CallCapture> *calls : programRegenCalls)
        {
            CallCapture createProgram = CaptureCreateProgram(replayState, true, id.value);
            CaptureCustomShaderProgram("CreateProgram", createProgram, *calls);
        }

        if (program->isLinked())
        {
            // Get last linked shader source.
            const ProgramSources &linkedSources =
                context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id);

            // Create two lists for program restore calls
            ResourceCalls &shaderProgramRestoreCalls =
                trackedShaderPrograms.getResourceRestoreCalls();
            CallVector programRestoreCalls({setupCalls, &shaderProgramRestoreCalls[id.value]});

            for (std::vector<CallCapture> *calls : programRestoreCalls)
            {
                GenerateLinkedProgram(context, replayState, resourceTracker, calls, program, id,
                                      tempShaderStartID, linkedSources);
            }

            // Update the program in replayState
            if (!replayState.getProgram() || replayState.getProgram()->id() != program->id())
            {
                // Note: We don't do this in GenerateLinkedProgram because it can't modify state
                (void)replayState.setProgram(context, program);
            }
        }

        resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram)
            .getStartingResources()
            .insert(id.value);
        resourceTracker->setShaderProgramType(id, ShaderProgramType::ProgramType);

        // Mark linked programs/shaders as inactive, leaving deferred-linked programs/shaders marked
        // as active
        if (!frameCaptureShared->isDeferredLinkProgram(id))
        {
            size_t programSetupEnd = setupCalls->size();

            // Mark the range of calls used to setup this program
            frameCaptureShared->markResourceSetupCallsInactive(
                setupCalls, ResourceIDType::ShaderProgram, id.value,
                gl::Range<size_t>(programSetupStart, programSetupEnd));
        }
    }

    // Handle shaders.
    for (const auto &shaderIter : gl::UnsafeResourceMapIter(shaders))
    {
        gl::ShaderProgramID id = {shaderIter.first};
        gl::Shader *shader     = shaderIter.second;

        // Skip shaders scheduled for deletion.
        // Shaders are shared by contexts in the share group and only need to be captured once.
        if (shader->hasBeenDeleted())
        {
            continue;
        }

        size_t shaderSetupStart = setupCalls->size();

        // Create two lists for shader regen calls
        ResourceCalls &shaderProgramRegenCalls = trackedShaderPrograms.getResourceRegenCalls();
        CallVector shaderRegenCalls({setupCalls, &shaderProgramRegenCalls[id.value]});

        for (std::vector<CallCapture> *calls : shaderRegenCalls)
        {
            CallCapture createShader =
                CaptureCreateShader(replayState, true, shader->getType(), id.value);
            CaptureCustomShaderProgram("CreateShader", createShader, *calls);

            // If unlinked programs have been created which reference this shader emit corresponding
            // attach calls
            for (const auto deferredAttachedProgramID : deferredAttachCalls[id])
            {
                CallCapture attachShader =
                    CaptureAttachShader(replayState, true, deferredAttachedProgramID, id);
                calls->emplace_back(std::move(attachShader));
            }
        }

        std::string shaderSource  = shader->getSourceString();
        const char *sourcePointer = shaderSource.empty() ? nullptr : shaderSource.c_str();

        // Create two lists for shader restore calls
        ResourceCalls &shaderProgramRestoreCalls = trackedShaderPrograms.getResourceRestoreCalls();
        CallVector shaderRestoreCalls({setupCalls, &shaderProgramRestoreCalls[id.value]});

        // This does not handle some more tricky situations like attaching and then deleting a
        // shader.
        // TODO(jmadill): Handle trickier program uses. http://anglebug.com/42262323
        if (shader->isCompiled(context))
        {
            const std::string &capturedSource =
                context->getShareGroup()->getFrameCaptureShared()->getShaderSource(id);
            if (capturedSource != shaderSource)
            {
                ASSERT(!capturedSource.empty());
                sourcePointer = capturedSource.c_str();
            }

            for (std::vector<CallCapture> *calls : shaderRestoreCalls)
            {
                Capture(calls,
                        CaptureShaderSource(replayState, true, id, 1, &sourcePointer, nullptr));
                Capture(calls, CaptureCompileShader(replayState, true, id));
            }
        }

        if (sourcePointer &&
            (!shader->isCompiled(context) || sourcePointer != shaderSource.c_str()))
        {
            for (std::vector<CallCapture> *calls : shaderRestoreCalls)
            {
                Capture(calls,
                        CaptureShaderSource(replayState, true, id, 1, &sourcePointer, nullptr));
            }
        }

        // Deferred-linked programs/shaders must be left marked as active
        if (deferredAttachCalls[id].empty())
        {
            // Mark the range of calls used to setup this shader
            frameCaptureShared->markResourceSetupCallsInactive(
                setupCalls, ResourceIDType::ShaderProgram, id.value,
                gl::Range<size_t>(shaderSetupStart, setupCalls->size()));
        }

        resourceTracker->getTrackedResource(context->id(), ResourceIDType::ShaderProgram)
            .getStartingResources()
            .insert(id.value);
        resourceTracker->setShaderProgramType(id, ShaderProgramType::ShaderType);
    }

    // Capture Sampler Objects
    const gl::SamplerManager &samplers = apiState.getSamplerManagerForCapture();
    for (const auto &samplerIter : gl::UnsafeResourceMapIter(samplers.getResourcesForCapture()))
    {
        gl::SamplerID samplerID = {samplerIter.first};

        // Don't gen the sampler if we've seen it before, since they are shared across the context
        // share group.
        cap(CaptureGenSamplers(replayState, true, 1, &samplerID));
        MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);

        gl::Sampler *sampler = samplerIter.second;
        if (!sampler)
        {
            continue;
        }

        gl::SamplerState defaultSamplerState;
        if (sampler->getMinFilter() != defaultSamplerState.getMinFilter())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID,
                                         gl::SamplerParameter::MinFilter, sampler->getMinFilter()));
        }
        if (sampler->getMagFilter() != defaultSamplerState.getMagFilter())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID,
                                         gl::SamplerParameter::MagFilter, sampler->getMagFilter()));
        }
        if (sampler->getWrapS() != defaultSamplerState.getWrapS())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, gl::SamplerParameter::WrapS,
                                         sampler->getWrapS()));
        }
        if (sampler->getWrapR() != defaultSamplerState.getWrapR())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, gl::SamplerParameter::WrapR,
                                         sampler->getWrapR()));
        }
        if (sampler->getWrapT() != defaultSamplerState.getWrapT())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, gl::SamplerParameter::WrapT,
                                         sampler->getWrapT()));
        }
        if (sampler->getMinLod() != defaultSamplerState.getMinLod())
        {
            cap(CaptureSamplerParameterf(replayState, true, samplerID, gl::SamplerParameter::MinLod,
                                         sampler->getMinLod()));
        }
        if (sampler->getMaxLod() != defaultSamplerState.getMaxLod())
        {
            cap(CaptureSamplerParameterf(replayState, true, samplerID, gl::SamplerParameter::MaxLod,
                                         sampler->getMaxLod()));
        }
        if (sampler->getCompareMode() != defaultSamplerState.getCompareMode())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID,
                                         gl::SamplerParameter::CompareMode,
                                         sampler->getCompareMode()));
        }
        if (sampler->getCompareFunc() != defaultSamplerState.getCompareFunc())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID,
                                         gl::SamplerParameter::CompareFunc,
                                         sampler->getCompareFunc()));
        }
    }

    // Capture Sync Objects
    const gl::SyncManager &syncs = apiState.getSyncManagerForCapture();
    for (const auto &syncIter : gl::UnsafeResourceMapIter(syncs.getResourcesForCapture()))
    {
        gl::SyncID syncID    = {syncIter.first};
        const gl::Sync *sync = syncIter.second;
        GLsync syncObject    = gl::unsafe_int_to_pointer_cast<GLsync>(syncID.value);

        if (!sync)
        {
            continue;
        }
        CallCapture fenceSync =
            CaptureFenceSync(replayState, true, sync->getCondition(), sync->getFlags(), syncObject);
        CaptureCustomFenceSync(fenceSync, *setupCalls);
        CaptureFenceSyncResetCalls(context, replayState, resourceTracker, syncID, syncObject, sync);
        resourceTracker->getStartingFenceSyncs().insert(syncID);
        frameCaptureShared->markGLSyncEmitted(syncID);
    }

    // Capture EGL Sync Objects
    const egl::ScopedSyncMap eglSyncMap = context->getDisplay()->getSyncsForCapture();
    for (const auto &eglSyncIter : eglSyncMap)
    {
        egl::SyncID eglSyncID    = {eglSyncIter.first};
        const egl::Sync *eglSync = eglSyncIter.second;
        EGLSync eglSyncObject    = gl::unsafe_int_to_pointer_cast<EGLSync>(eglSyncID.value);

        if (!eglSync)
        {
            continue;
        }
        CallCapture createEGLSync =
            CaptureCreateSync(nullptr, true, context->getDisplay(), eglSync->getType(),
                              eglSync->getAttributeMap(), eglSyncObject);
        CaptureCustomCreateEGLSync("CreateEGLSyncKHR", createEGLSync, *setupCalls);
        CaptureEGLSyncResetCalls(context, replayState, resourceTracker, eglSyncID, eglSyncObject,
                                 eglSync);
        resourceTracker->getTrackedResource(context->id(), ResourceIDType::egl_Sync)
            .getStartingResources()
            .insert(eglSyncID.value);
        frameCaptureShared->markEGLSyncEmitted(eglSyncID);
    }

    GLint contextUnpackAlignment = context->getState().getUnpackState().alignment;
    if (currentUnpackState.alignment != contextUnpackAlignment)
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackAlignment,
                               contextUnpackAlignment));
        replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(contextUnpackAlignment);
    }
}

// Detects zombie bindings caused by texture ID reuse across shared contexts.
// Zombie bindings may exist at capture-time but should not be added as part
// of capture Setup(). See http://issuetracker.google.com/471189378.
bool IsZombieTextureBinding(const gl::State &state,
                            gl::TextureType type,
                            size_t unit,
                            gl::TextureID textureID)
{
    // Texture held by the context's specific hardware sampler slot
    const gl::Texture *boundTexture = state.getSamplerTexture(static_cast<GLuint>(unit), type);

    if (boundTexture)
    {
        uint64_t boundSerial = boundTexture->serial().getValue();

        // Texture from the current Resource Manager state
        const gl::TextureManager &textureManager = state.getTextureManagerForCapture();
        const gl::Texture *currentTexture        = textureManager.getTexture(textureID);
        uint64_t currentSerial                   = currentTexture->serial().getValue();

        // If the ANGLE unique object IDs differ this object has been deleted
        return (boundSerial != currentSerial);
    }
    return false;
}

// GLES1 Modelview and Projection matrix stacks are initialized with an identity entry, so skip
// the push before the first load to keep from adding a glPushMatrix call in each trace upgrade
void CaptureGLES1Matrices(std::vector<CallCapture> *setupCalls,
                          const gl::State &replayState,
                          const gl::State &apiState,
                          gl::MatrixType mode)
{
    Capture(setupCalls, CaptureMatrixMode(replayState, true, mode));
    bool firstPush = true;
    for (angle::Mat4 matrix : apiState.gles1().getMatrixStack(mode))
    {
        if (!firstPush)
        {
            Capture(setupCalls, CapturePushMatrix(replayState, true));
        }
        Capture(setupCalls, CaptureLoadMatrixf(replayState, true, matrix.elements().data()));
        firstPush = false;
    }
}

void CaptureMidExecutionSetup(const gl::Context *context,
                              std::vector<CallCapture> *setupCalls,
                              StateResetHelper &resetHelper,
                              std::vector<CallCapture> *shareGroupSetupCalls,
                              ResourceIDToSetupCallsMap *resourceIDToSetupCalls,
                              ResourceTracker *resourceTracker,
                              gl::State &replayState,
                              bool validationEnabled)
{
    const gl::State &apiState = context->getState();

    // Small helper function to make the code more readable.
    auto cap = [setupCalls](CallCapture &&call) { setupCalls->emplace_back(std::move(call)); };

    cap(egl::CaptureMakeCurrent(nullptr, true, nullptr, {0}, {0}, context->id(), EGL_TRUE));
    CaptureUpdateCurrentContext(context->id(), setupCalls);

    // Vertex input states. Must happen after buffer data initialization. Do not capture on GLES1.
    if (!context->isGLES1())
    {
        CaptureDefaultVertexAttribs(replayState, apiState, setupCalls);
    }

    // Capture vertex array objects
    VertexArrayCaptureFuncs vertexArrayFuncs(context->isGLES1());

    const gl::VertexArrayMap &vertexArrayMap = context->getVertexArraysForCapture();
    gl::VertexArrayID boundVertexArrayID     = {0};
    for (const auto &vertexArrayIter : gl::UnsafeResourceMapIter(vertexArrayMap))
    {
        TrackedResource &trackedVertexArrays =
            resourceTracker->getTrackedResource(context->id(), ResourceIDType::VertexArray);

        gl::VertexArrayID vertexArrayID = {vertexArrayIter.first};

        // Track this as a starting resource that may need to be restored
        resourceTracker->getTrackedResource(context->id(), ResourceIDType::VertexArray)
            .getStartingResources()
            .insert(vertexArrayID.value);

        // Create two lists of calls for initial setup
        ResourceCalls &vertexArrayRegenCalls = trackedVertexArrays.getResourceRegenCalls();
        CallVector vertexArrayGenCalls({setupCalls, &vertexArrayRegenCalls[vertexArrayID.value]});

        if (vertexArrayID.value != 0)
        {
            // Gen the vertex array
            for (std::vector<CallCapture> *calls : vertexArrayGenCalls)
            {
                Capture(calls,
                        vertexArrayFuncs.genVertexArrays(replayState, true, 1, &vertexArrayID));
                MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
            }
        }

        // Create two lists of calls for populating the vertex array
        ResourceCalls &vertexArrayRestoreCalls = trackedVertexArrays.getResourceRestoreCalls();
        CallVector vertexArraySetupCalls(
            {setupCalls, &vertexArrayRestoreCalls[vertexArrayID.value]});

        if (vertexArrayIter.second)
        {
            const gl::VertexArray *vertexArray = vertexArrayIter.second;

            // Populate the vertex array
            for (std::vector<CallCapture> *calls : vertexArraySetupCalls)
            {
                // Bind the vertexArray (if needed) and populate it
                if (vertexArrayID != boundVertexArrayID)
                {
                    Capture(calls,
                            vertexArrayFuncs.bindVertexArray(replayState, true, vertexArrayID));
                }
                CaptureVertexArrayState(calls, context, vertexArray, &replayState);
            }
            boundVertexArrayID = vertexArrayID;
        }
    }

    // Bind the current vertex array
    const gl::VertexArray *currentVertexArray = apiState.getVertexArray();
    if (currentVertexArray->id() != boundVertexArrayID)
    {
        cap(vertexArrayFuncs.bindVertexArray(replayState, true, currentVertexArray->id()));
    }

    // Track the calls necessary to bind the vertex array back to initial state
    CallResetMap &resetCalls = resetHelper.getResetCalls();
    Capture(&resetCalls[angle::EntryPoint::GLBindVertexArray],
            vertexArrayFuncs.bindVertexArray(replayState, true, currentVertexArray->id()));
    gl::Buffer *elementArrayBuffer = currentVertexArray->getElementArrayBuffer();
    if (elementArrayBuffer)
    {
        resetHelper.setStartingBufferBinding(gl::BufferBinding::ElementArray,
                                             currentVertexArray->getElementArrayBuffer()->id());
    }

    // Capture indexed buffer bindings.
    const gl::BufferVector &uniformIndexedBuffers =
        apiState.getOffsetBindingPointerUniformBuffers();
    const gl::BufferVector &atomicCounterIndexedBuffers =
        apiState.getOffsetBindingPointerAtomicCounterBuffers();
    const gl::BufferVector &shaderStorageIndexedBuffers =
        apiState.getOffsetBindingPointerShaderStorageBuffers();
    CaptureIndexedBuffers(replayState, uniformIndexedBuffers, gl::BufferBinding::Uniform,
                          setupCalls);
    CaptureIndexedBuffers(replayState, atomicCounterIndexedBuffers,
                          gl::BufferBinding::AtomicCounter, setupCalls);
    CaptureIndexedBuffers(replayState, shaderStorageIndexedBuffers,
                          gl::BufferBinding::ShaderStorage, setupCalls);

    // Capture Buffer bindings.
    const gl::BoundBufferMap &boundBuffers = apiState.getBoundBuffersForCapture();
    for (gl::BufferBinding binding : angle::AllEnums<gl::BufferBinding>())
    {
        gl::BufferID bufferID = boundBuffers[binding].id();

        // Filter out redundant buffer binding commands. Note that the code in the previous section
        // only binds to ARRAY_BUFFER. Therefore we only check the array binding against the binding
        // we set earlier.
        const gl::Buffer *arrayBuffer = replayState.getArrayBuffer();
        bool isArray                  = binding == gl::BufferBinding::Array;
        bool isArrayBufferChanging    = isArray && arrayBuffer && arrayBuffer->id() != bufferID;
        if (isArrayBufferChanging || (!isArray && bufferID.value != 0))
        {
            cap(CaptureBindBuffer(replayState, true, binding, bufferID));
            replayState.setBufferBinding(context, binding, boundBuffers[binding].get());
        }

        // Restore all buffer bindings for Reset
        if (bufferID.value != 0 || isArrayBufferChanging)
        {
            CaptureBufferBindingResetCalls(replayState, resourceTracker, binding, bufferID);

            // Track this as a starting binding
            resetHelper.setStartingBufferBinding(binding, bufferID);
        }
    }

    // Set a unpack alignment of 1. Otherwise, computeRowPitch() will compute the wrong value,
    // leading to a crash in memcpy() when capturing the texture contents.
    gl::PixelUnpackState &currentUnpackState = replayState.getUnpackState();
    if (currentUnpackState.alignment != 1)
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackAlignment, 1));
        replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(1);
    }

    // Capture Texture setup and data.
    const gl::TextureBindingMap &apiBoundTextures = apiState.getBoundTexturesForCapture();
    resetHelper.setResetActiveTexture(apiState.getActiveSampler());

    // Set Texture bindings.
    for (gl::TextureType textureType : angle::AllEnums<gl::TextureType>())
    {
        const gl::TextureBindingVector &apiBindings = apiBoundTextures[textureType];
        const gl::TextureBindingVector &replayBindings =
            replayState.getBoundTexturesForCapture()[textureType];
        ASSERT(apiBindings.size() == replayBindings.size());
        for (size_t bindingIndex = 0; bindingIndex < apiBindings.size(); ++bindingIndex)
        {
            gl::TextureID apiTextureID    = apiBindings[bindingIndex].id();
            gl::TextureID replayTextureID = replayBindings[bindingIndex].id();

            if (apiTextureID != replayTextureID)
            {
                if (apiTextureID.value &&
                    IsZombieTextureBinding(apiState, textureType, bindingIndex, apiTextureID))
                {
                    INFO() << "Skipping setup of partially deleted/unbound zombie texture.";
                    continue;
                }

                if (replayState.getActiveSampler() != bindingIndex)
                {
                    cap(CaptureActiveTexture(replayState, true,
                                             GL_TEXTURE0 + static_cast<GLenum>(bindingIndex)));
                    replayState.getMutablePrivateStateForCapture()->setActiveSampler(
                        static_cast<unsigned int>(bindingIndex));
                }

                cap(CaptureBindTexture(replayState, true, textureType, apiTextureID));
                replayState.setSamplerTexture(context, textureType,
                                              apiBindings[bindingIndex].get());
            }

            if (apiTextureID.value)
            {
                // Set this texture as active so it will be generated in Setup
                MarkResourceIDActive(ResourceIDType::Texture, apiTextureID.value,
                                     shareGroupSetupCalls, resourceIDToSetupCalls);
                // Save currently bound textures for reset
                resetHelper.getResetTextureBindings().emplace(
                    std::make_pair(bindingIndex, textureType), apiTextureID);
            }
        }
    }

    // Capture Texture Environment
    if (context->isGLES1())
    {
        const gl::Caps &caps = context->getCaps();
        for (GLuint unit = 0; unit < caps.maxMultitextureUnits; ++unit)
        {
            CaptureTextureEnvironmentState(setupCalls, &replayState, &apiState, unit);
        }
    }

    // Set active Texture.
    if (replayState.getActiveSampler() != apiState.getActiveSampler())
    {
        cap(CaptureActiveTexture(replayState, true,
                                 GL_TEXTURE0 + static_cast<GLenum>(apiState.getActiveSampler())));
        replayState.getMutablePrivateStateForCapture()->setActiveSampler(
            apiState.getActiveSampler());
    }

    // Set Renderbuffer binding.
    FramebufferCaptureFuncs framebufferFuncs(context->isGLES1());

    const gl::RenderbufferManager &renderbuffers = apiState.getRenderbufferManagerForCapture();
    gl::RenderbufferID currentRenderbuffer       = {0};
    for (const auto &renderbufIter :
         gl::UnsafeResourceMapIter(renderbuffers.getResourcesForCapture()))
    {
        currentRenderbuffer = renderbufIter.second->id();
    }

    if (currentRenderbuffer != apiState.getRenderbufferId())
    {
        cap(framebufferFuncs.bindRenderbuffer(replayState, true, GL_RENDERBUFFER,
                                              apiState.getRenderbufferId()));
    }

    // Capture Framebuffers.
    const gl::FramebufferManager &framebuffers = apiState.getFramebufferManagerForCapture();

    gl::FramebufferID currentDrawFramebuffer = {0};
    gl::FramebufferID currentReadFramebuffer = {0};

    for (const auto &framebufferIter :
         gl::UnsafeResourceMapIter(framebuffers.getResourcesForCapture()))
    {
        gl::FramebufferID id               = {framebufferIter.first};
        const gl::Framebuffer *framebuffer = framebufferIter.second;

        // The default Framebuffer exists (by default).
        if (framebuffer->isDefault())
        {
            continue;
        }

        // Track this as a starting resource that may need to be restored
        TrackedResource &trackedFramebuffers =
            resourceTracker->getTrackedResource(context->id(), ResourceIDType::Framebuffer);
        ResourceSet &startingFramebuffers = trackedFramebuffers.getStartingResources();
        startingFramebuffers.insert(id.value);

        // Create two lists of calls for initial setup
        ResourceCalls &framebufferRegenCalls = trackedFramebuffers.getResourceRegenCalls();
        CallVector framebufferGenCalls({setupCalls, &framebufferRegenCalls[id.value]});

        // Gen the framebuffer
        for (std::vector<CallCapture> *calls : framebufferGenCalls)
        {
            Capture(calls, framebufferFuncs.genFramebuffers(replayState, true, 1, &id));
            MaybeCaptureUpdateResourceIDs(context, resourceTracker, calls);
        }

        // Create two lists of calls for remaining setup calls.  One for setup, and one for restore
        // during reset.
        ResourceCalls &framebufferRestoreCalls = trackedFramebuffers.getResourceRestoreCalls();
        CallVector framebufferSetupCalls({setupCalls, &framebufferRestoreCalls[id.value]});

        for (std::vector<CallCapture> *calls : framebufferSetupCalls)
        {
            CaptureBindFramebufferForContext(context, calls, framebufferFuncs, replayState,
                                             GL_FRAMEBUFFER, id);
        }
        currentDrawFramebuffer = currentReadFramebuffer = id;

        // Color Attachments.
        for (const gl::FramebufferAttachment &colorAttachment : framebuffer->getColorAttachments())
        {
            if (!colorAttachment.isAttached())
            {
                continue;
            }

            for (std::vector<CallCapture> *calls : framebufferSetupCalls)
            {
                CaptureFramebufferAttachment(calls, replayState, framebufferFuncs, colorAttachment,
                                             shareGroupSetupCalls, resourceIDToSetupCalls);
            }
        }

        const gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthAttachment();
        if (depthAttachment)
        {
            ASSERT(depthAttachment->getBinding() == GL_DEPTH_ATTACHMENT ||
                   depthAttachment->getBinding() == GL_DEPTH_STENCIL_ATTACHMENT);
            for (std::vector<CallCapture> *calls : framebufferSetupCalls)
            {
                CaptureFramebufferAttachment(calls, replayState, framebufferFuncs, *depthAttachment,
                                             shareGroupSetupCalls, resourceIDToSetupCalls);
            }
        }

        const gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilAttachment();
        if (stencilAttachment)
        {
            ASSERT(stencilAttachment->getBinding() == GL_STENCIL_ATTACHMENT ||
                   depthAttachment->getBinding() == GL_DEPTH_STENCIL_ATTACHMENT);
            for (std::vector<CallCapture> *calls : framebufferSetupCalls)
            {
                CaptureFramebufferAttachment(calls, replayState, framebufferFuncs,
                                             *stencilAttachment, shareGroupSetupCalls,
                                             resourceIDToSetupCalls);
            }
        }

        gl::FramebufferState defaultFramebufferState(
            context->getCaps(), framebuffer->getState().id(),
            framebuffer->getState().getFramebufferSerial());
        const gl::DrawBuffersVector<GLenum> &defaultDrawBufferStates =
            defaultFramebufferState.getDrawBufferStates();
        const gl::DrawBuffersVector<GLenum> &drawBufferStates = framebuffer->getDrawBufferStates();

        if (drawBufferStates != defaultDrawBufferStates)
        {
            for (std::vector<CallCapture> *calls : framebufferSetupCalls)
            {
                Capture(calls, CaptureDrawBuffers(replayState, true,
                                                  static_cast<GLsizei>(drawBufferStates.size()),
                                                  drawBufferStates.data()));
            }
        }
    }

    // Capture framebuffer bindings.
    if (apiState.getDrawFramebuffer())
    {
        ASSERT(apiState.getReadFramebuffer());
        gl::FramebufferID stateReadFramebuffer = apiState.getReadFramebuffer()->id();
        gl::FramebufferID stateDrawFramebuffer = apiState.getDrawFramebuffer()->id();

        // For reset, always restore framebuffer bindings since they may change
        std::vector<CallCapture> *resetBindFramebufferCalls =
            &resetHelper.getResetCalls()[angle::EntryPoint::GLBindFramebuffer];

        if (stateDrawFramebuffer == stateReadFramebuffer)
        {
            if (currentDrawFramebuffer != stateDrawFramebuffer ||
                currentReadFramebuffer != stateReadFramebuffer)
            {
                CaptureBindFramebufferForContext(context, setupCalls, framebufferFuncs, replayState,
                                                 GL_FRAMEBUFFER, stateDrawFramebuffer);
                currentDrawFramebuffer = currentReadFramebuffer = stateDrawFramebuffer;
            }
            CaptureBindFramebufferForContext(context, resetBindFramebufferCalls, framebufferFuncs,
                                             replayState, GL_FRAMEBUFFER, stateDrawFramebuffer);
        }
        else
        {
            if (currentDrawFramebuffer != stateDrawFramebuffer)
            {
                CaptureBindFramebufferForContext(context, setupCalls, framebufferFuncs, replayState,
                                                 GL_DRAW_FRAMEBUFFER, stateDrawFramebuffer);
                currentDrawFramebuffer = stateDrawFramebuffer;
            }
            CaptureBindFramebufferForContext(context, resetBindFramebufferCalls, framebufferFuncs,
                                             replayState, GL_DRAW_FRAMEBUFFER,
                                             stateDrawFramebuffer);

            if (currentReadFramebuffer != stateReadFramebuffer)
            {
                CaptureBindFramebufferForContext(context, setupCalls, framebufferFuncs, replayState,
                                                 GL_READ_FRAMEBUFFER, stateReadFramebuffer);
                currentReadFramebuffer = stateReadFramebuffer;
            }
            CaptureBindFramebufferForContext(context, resetBindFramebufferCalls, framebufferFuncs,
                                             replayState, GL_READ_FRAMEBUFFER,
                                             stateReadFramebuffer);
        }
    }

    // Capture Program Pipelines
    const gl::ProgramPipelineManager *programPipelineManager =
        apiState.getProgramPipelineManagerForCapture();

    for (const auto &ppoIterator :
         gl::UnsafeResourceMapIter(programPipelineManager->getResourcesForCapture()))
    {
        gl::ProgramPipeline *pipeline = ppoIterator.second;
        gl::ProgramPipelineID id      = {ppoIterator.first};
        cap(CaptureGenProgramPipelines(replayState, true, 1, &id));
        MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);

        // PPOs can contain graphics and compute programs, so loop through all shader types rather
        // than just the linked ones since getLinkedShaderStages() will return either only graphics
        // or compute stages.
        for (gl::ShaderType shaderType : gl::AllShaderTypes())
        {
            const gl::Program *program = pipeline->getShaderProgram(shaderType);
            if (!program)
            {
                continue;
            }
            ASSERT(program->isLinked());
            GLbitfield gLbitfield = GetBitfieldFromShaderType(shaderType);
            cap(CaptureUseProgramStages(replayState, true, pipeline->id(), gLbitfield,
                                        program->id()));

            // Set this program as active so it will be generated in Setup
            // Note: We aren't filtering ProgramPipelines, so this could be setting programs
            // active that aren't actually used.
            MarkResourceIDActive(ResourceIDType::ShaderProgram, program->id().value,
                                 shareGroupSetupCalls, resourceIDToSetupCalls);
        }

        gl::Program *program = pipeline->getActiveShaderProgram();
        if (program)
        {
            cap(CaptureActiveShaderProgram(replayState, true, id, program->id()));
        }
    }

    // For now we assume the installed program executable is the same as the current program.
    // TODO(jmadill): Handle installed program executable. http://anglebug.com/42262323
    if (!context->isGLES1())
    {
        // If we have a program bound in the API, or if there is no program bound to the API at
        // time of capture and we bound a program for uniform updates during MEC, we must add
        // a set program call to replay the correct states.
        GLuint currentProgram = 0;
        if (apiState.getProgram())
        {
            cap(CaptureUseProgram(replayState, true, apiState.getProgram()->id()));
            CaptureUpdateCurrentProgram(setupCalls->back(), 0, setupCalls);
            (void)replayState.setProgram(context, apiState.getProgram());

            // Set this program as active so it will be generated in Setup
            MarkResourceIDActive(ResourceIDType::ShaderProgram, apiState.getProgram()->id().value,
                                 shareGroupSetupCalls, resourceIDToSetupCalls);

            currentProgram = apiState.getProgram()->id().value;
        }
        else if (replayState.getProgram())
        {
            cap(CaptureUseProgram(replayState, true, {0}));
            CaptureUpdateCurrentProgram(setupCalls->back(), 0, setupCalls);
            (void)replayState.setProgram(context, nullptr);
        }

        // Track the calls necessary to reset active program back to initial state
        Capture(&resetCalls[angle::EntryPoint::GLUseProgram],
                CaptureUseProgram(replayState, true, {currentProgram}));
        CaptureUpdateCurrentProgram((&resetCalls[angle::EntryPoint::GLUseProgram])->back(), 0,
                                    &resetCalls[angle::EntryPoint::GLUseProgram]);

        // Same for program pipelines as for programs, see comment above.
        if (apiState.getProgramPipeline())
        {
            cap(CaptureBindProgramPipeline(replayState, true, apiState.getProgramPipeline()->id()));
        }
        else if (replayState.getProgramPipeline())
        {
            cap(CaptureBindProgramPipeline(replayState, true, {0}));
        }
    }

    // Capture Queries
    const gl::QueryMap &queryMap = context->getQueriesForCapture();

    // Create existing queries. Note that queries may be genned and not yet started. In that
    // case the queries will exist in the query map as nullptr entries.
    // If any queries are active between frames, we want to defer creation and do them last,
    // otherwise you'll get GL errors about starting a query while one is already active.
    for (gl::QueryMap::Iterator queryIter = gl::UnsafeResourceMapIter(queryMap).beginWithNull(),
                                endIter   = gl::UnsafeResourceMapIter(queryMap).endWithNull();
         queryIter != endIter; ++queryIter)
    {
        ASSERT(queryIter->first);
        gl::QueryID queryID = {queryIter->first};

        cap(CaptureGenQueries(replayState, true, 1, &queryID));
        MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);

        gl::Query *query = queryIter->second;
        if (query)
        {
            // Defer active queries until we've created them all
            if (IsQueryActive(apiState, queryID))
            {
                continue;
            }

            gl::QueryType queryType = query->getType();
            switch (queryType)
            {
                case gl::QueryType::AnySamples:
                case gl::QueryType::AnySamplesConservative:
                case gl::QueryType::PrimitivesGenerated:
                case gl::QueryType::TransformFeedbackPrimitivesWritten:
                case gl::QueryType::TimeElapsed:
                    // Begin the query to generate the object
                    cap(CaptureBeginQuery(replayState, true, queryType, queryID));
                    // End the query since it is not active
                    cap(CaptureEndQuery(replayState, true, queryType));
                    break;

                case gl::QueryType::Timestamp:
                    // Issue the query to create the object
                    cap(CaptureQueryCounterEXT(replayState, true, queryID, queryType));
                    break;

                default:
                    UNREACHABLE();
                    break;
            }
        }
    }

    const gl::ActiveQueryMap &activeQueries = apiState.getActiveQueriesForCapture();
    for (const auto &activeQueryIter : activeQueries)
    {
        const gl::Query *activeQuery = activeQueryIter.get();
        if (activeQuery)
        {
            cap(CaptureBeginQuery(replayState, true, activeQuery->getType(), activeQuery->id()));
        }
    }

    // Transform Feedback
    const gl::TransformFeedbackMap &xfbMap = context->getTransformFeedbacksForCapture();
    for (const auto &xfbIter : gl::UnsafeResourceMapIter(xfbMap))
    {
        gl::TransformFeedbackID xfbID = {xfbIter.first};

        // Do not capture the default XFB object.
        if (xfbID.value == 0)
        {
            continue;
        }

        cap(CaptureGenTransformFeedbacks(replayState, true, 1, &xfbID));
        MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);

        gl::TransformFeedback *xfb = xfbIter.second;
        if (!xfb)
        {
            // The object was never created
            continue;
        }

        // Bind XFB to create the object
        cap(CaptureBindTransformFeedback(replayState, true, GL_TRANSFORM_FEEDBACK, xfbID));

        // Bind the buffers associated with this XFB object
        for (size_t i = 0; i < xfb->getIndexedBufferCount(); ++i)
        {
            const gl::OffsetBindingPointer<gl::Buffer> &xfbBuffer = xfb->getIndexedBuffer(i);

            // Note: Buffers bound with BindBufferBase can be used with BindBuffer
            cap(CaptureBindBufferRange(replayState, true, gl::BufferBinding::TransformFeedback, 0,
                                       xfbBuffer.id(), xfbBuffer.getOffset(), xfbBuffer.getSize()));
        }

        if (xfb->isActive() || xfb->isPaused())
        {
            // We don't support active XFB in MEC yet
            UNIMPLEMENTED();
        }
    }

    // Bind the current XFB buffer after populating XFB objects
    gl::TransformFeedback *currentXFB = apiState.getCurrentTransformFeedback();
    if (currentXFB)
    {
        cap(CaptureBindTransformFeedback(replayState, true, GL_TRANSFORM_FEEDBACK,
                                         currentXFB->id()));
    }

    // Bind samplers
    const gl::SamplerBindingVector &samplerBindings = apiState.getSamplers();
    for (GLuint bindingIndex = 0; bindingIndex < static_cast<GLuint>(samplerBindings.size());
         ++bindingIndex)
    {
        gl::SamplerID samplerID = samplerBindings[bindingIndex].id();
        if (samplerID.value != 0)
        {
            cap(CaptureBindSampler(replayState, true, bindingIndex, samplerID));
        }
    }

    // Capture Image Texture bindings
    const std::vector<gl::ImageUnit> &imageUnits = apiState.getImageUnits();
    for (GLuint bindingIndex = 0; bindingIndex < static_cast<GLuint>(imageUnits.size());
         ++bindingIndex)
    {
        const gl::ImageUnit &imageUnit = imageUnits[bindingIndex];

        if (imageUnit.texture == 0)
        {
            continue;
        }

        cap(CaptureBindImageTexture(replayState, true, bindingIndex, imageUnit.texture.id(),
                                    imageUnit.level, imageUnit.layered, imageUnit.layer,
                                    imageUnit.access, imageUnit.format));
    }

    // Capture GL Context states.
    auto capCap = [cap, &replayState](GLenum capEnum, bool capValue) {
        if (capValue)
        {
            cap(CaptureEnable(replayState, true, capEnum));
        }
        else
        {
            cap(CaptureDisable(replayState, true, capEnum));
        }
    };

    // Capture GLES1 context states.
    if (context->isGLES1())
    {
        const bool currentTextureState = apiState.getEnableFeature(GL_TEXTURE_2D);
        const bool defaultTextureState = replayState.getEnableFeature(GL_TEXTURE_2D);
        if (currentTextureState != defaultTextureState)
        {
            capCap(GL_TEXTURE_2D, currentTextureState);
        }

        CaptureGLES1Matrices(setupCalls, replayState, apiState, gl::MatrixType::Projection);
        CaptureGLES1Matrices(setupCalls, replayState, apiState, gl::MatrixType::Modelview);

        gl::MatrixType currentMatrixMode = apiState.gles1().getMatrixMode();
        if (currentMatrixMode != gl::MatrixType::Modelview)
        {
            cap(CaptureMatrixMode(replayState, true, currentMatrixMode));
        }

        // Alpha Test state
        const bool currentAlphaTestState = apiState.getEnableFeature(GL_ALPHA_TEST);
        const bool defaultAlphaTestState = replayState.getEnableFeature(GL_ALPHA_TEST);

        if (currentAlphaTestState != defaultAlphaTestState)
        {
            capCap(GL_ALPHA_TEST, currentAlphaTestState);
        }

        const gl::AlphaTestParameters currentAlphaTestParameters =
            apiState.gles1().getAlphaTestParameters();
        const gl::AlphaTestParameters defaultAlphaTestParameters =
            replayState.gles1().getAlphaTestParameters();

        if (currentAlphaTestParameters != defaultAlphaTestParameters)
        {
            cap(CaptureAlphaFunc(replayState, true, currentAlphaTestParameters.func,
                                 currentAlphaTestParameters.ref));
        }
    }

    // Rasterizer state. Missing ES 3.x features.
    const gl::RasterizerState &defaultRasterState = replayState.getRasterizerState();
    const gl::RasterizerState &currentRasterState = apiState.getRasterizerState();
    if (currentRasterState.cullFace != defaultRasterState.cullFace)
    {
        capCap(GL_CULL_FACE, currentRasterState.cullFace);
    }

    if (currentRasterState.cullMode != defaultRasterState.cullMode)
    {
        cap(CaptureCullFace(replayState, true, currentRasterState.cullMode));
    }

    if (currentRasterState.frontFace != defaultRasterState.frontFace)
    {
        cap(CaptureFrontFace(replayState, true, currentRasterState.frontFace));
    }

    if (currentRasterState.polygonMode != defaultRasterState.polygonMode)
    {
        if (context->getExtensions().polygonModeNV)
        {
            cap(CapturePolygonModeNV(replayState, true, GL_FRONT_AND_BACK,
                                     currentRasterState.polygonMode));
        }
        else if (context->getExtensions().polygonModeANGLE)
        {
            cap(CapturePolygonModeANGLE(replayState, true, GL_FRONT_AND_BACK,
                                        currentRasterState.polygonMode));
        }
        else
        {
            UNREACHABLE();
        }
    }

    if (currentRasterState.polygonOffsetPoint != defaultRasterState.polygonOffsetPoint)
    {
        capCap(GL_POLYGON_OFFSET_POINT_NV, currentRasterState.polygonOffsetPoint);
    }

    if (currentRasterState.polygonOffsetLine != defaultRasterState.polygonOffsetLine)
    {
        capCap(GL_POLYGON_OFFSET_LINE_NV, currentRasterState.polygonOffsetLine);
    }

    if (currentRasterState.polygonOffsetFill != defaultRasterState.polygonOffsetFill)
    {
        capCap(GL_POLYGON_OFFSET_FILL, currentRasterState.polygonOffsetFill);
    }

    if (currentRasterState.polygonOffsetFactor != defaultRasterState.polygonOffsetFactor ||
        currentRasterState.polygonOffsetUnits != defaultRasterState.polygonOffsetUnits ||
        currentRasterState.polygonOffsetClamp != defaultRasterState.polygonOffsetClamp)
    {
        if (currentRasterState.polygonOffsetClamp == 0.0f)
        {
            cap(CapturePolygonOffset(replayState, true, currentRasterState.polygonOffsetFactor,
                                     currentRasterState.polygonOffsetUnits));
        }
        else
        {
            cap(CapturePolygonOffsetClampEXT(
                replayState, true, currentRasterState.polygonOffsetFactor,
                currentRasterState.polygonOffsetUnits, currentRasterState.polygonOffsetClamp));
        }
    }

    if (currentRasterState.depthClamp != defaultRasterState.depthClamp)
    {
        capCap(GL_DEPTH_CLAMP_EXT, currentRasterState.depthClamp);
    }

    // pointDrawMode/multiSample are only used in the D3D back-end right now.

    if (currentRasterState.rasterizerDiscard != defaultRasterState.rasterizerDiscard)
    {
        capCap(GL_RASTERIZER_DISCARD, currentRasterState.rasterizerDiscard);
    }

    if (currentRasterState.dither != defaultRasterState.dither)
    {
        capCap(GL_DITHER, currentRasterState.dither);
    }

    // Depth/stencil state.
    const gl::DepthStencilState &defaultDSState = replayState.getDepthStencilState();
    const gl::DepthStencilState &currentDSState = apiState.getDepthStencilState();
    if (defaultDSState.depthFunc != currentDSState.depthFunc)
    {
        cap(CaptureDepthFunc(replayState, true, currentDSState.depthFunc));
    }

    if (defaultDSState.depthMask != currentDSState.depthMask)
    {
        cap(CaptureDepthMask(replayState, true, gl::ConvertToGLBoolean(currentDSState.depthMask)));
    }

    if (defaultDSState.depthTest != currentDSState.depthTest)
    {
        capCap(GL_DEPTH_TEST, currentDSState.depthTest);
    }

    if (defaultDSState.stencilTest != currentDSState.stencilTest)
    {
        capCap(GL_STENCIL_TEST, currentDSState.stencilTest);
    }

    if (currentDSState.stencilFunc == currentDSState.stencilBackFunc &&
        currentDSState.stencilMask == currentDSState.stencilBackMask)
    {
        // Front and back are equal
        if (defaultDSState.stencilFunc != currentDSState.stencilFunc ||
            defaultDSState.stencilMask != currentDSState.stencilMask ||
            apiState.getStencilRef() != 0)
        {
            cap(CaptureStencilFunc(replayState, true, currentDSState.stencilFunc,
                                   apiState.getStencilRef(), currentDSState.stencilMask));
        }
    }
    else
    {
        // Front and back are separate
        if (defaultDSState.stencilFunc != currentDSState.stencilFunc ||
            defaultDSState.stencilMask != currentDSState.stencilMask ||
            apiState.getStencilRef() != 0)
        {
            cap(CaptureStencilFuncSeparate(replayState, true, GL_FRONT, currentDSState.stencilFunc,
                                           apiState.getStencilRef(), currentDSState.stencilMask));
        }

        if (defaultDSState.stencilBackFunc != currentDSState.stencilBackFunc ||
            defaultDSState.stencilBackMask != currentDSState.stencilBackMask ||
            apiState.getStencilBackRef() != 0)
        {
            cap(CaptureStencilFuncSeparate(
                replayState, true, GL_BACK, currentDSState.stencilBackFunc,
                apiState.getStencilBackRef(), currentDSState.stencilBackMask));
        }
    }

    if (currentDSState.stencilFail == currentDSState.stencilBackFail &&
        currentDSState.stencilPassDepthFail == currentDSState.stencilBackPassDepthFail &&
        currentDSState.stencilPassDepthPass == currentDSState.stencilBackPassDepthPass)
    {
        // Front and back are equal
        if (defaultDSState.stencilFail != currentDSState.stencilFail ||
            defaultDSState.stencilPassDepthFail != currentDSState.stencilPassDepthFail ||
            defaultDSState.stencilPassDepthPass != currentDSState.stencilPassDepthPass)
        {
            cap(CaptureStencilOp(replayState, true, currentDSState.stencilFail,
                                 currentDSState.stencilPassDepthFail,
                                 currentDSState.stencilPassDepthPass));
        }
    }
    else
    {
        // Front and back are separate
        if (defaultDSState.stencilFail != currentDSState.stencilFail ||
            defaultDSState.stencilPassDepthFail != currentDSState.stencilPassDepthFail ||
            defaultDSState.stencilPassDepthPass != currentDSState.stencilPassDepthPass)
        {
            cap(CaptureStencilOpSeparate(replayState, true, GL_FRONT, currentDSState.stencilFail,
                                         currentDSState.stencilPassDepthFail,
                                         currentDSState.stencilPassDepthPass));
        }

        if (defaultDSState.stencilBackFail != currentDSState.stencilBackFail ||
            defaultDSState.stencilBackPassDepthFail != currentDSState.stencilBackPassDepthFail ||
            defaultDSState.stencilBackPassDepthPass != currentDSState.stencilBackPassDepthPass)
        {
            cap(CaptureStencilOpSeparate(replayState, true, GL_BACK, currentDSState.stencilBackFail,
                                         currentDSState.stencilBackPassDepthFail,
                                         currentDSState.stencilBackPassDepthPass));
        }
    }

    if (currentDSState.stencilWritemask == currentDSState.stencilBackWritemask)
    {
        // Front and back are equal
        if (defaultDSState.stencilWritemask != currentDSState.stencilWritemask)
        {
            cap(CaptureStencilMask(replayState, true, currentDSState.stencilWritemask));
        }
    }
    else
    {
        // Front and back are separate
        if (defaultDSState.stencilWritemask != currentDSState.stencilWritemask)
        {
            cap(CaptureStencilMaskSeparate(replayState, true, GL_FRONT,
                                           currentDSState.stencilWritemask));
        }

        if (defaultDSState.stencilBackWritemask != currentDSState.stencilBackWritemask)
        {
            cap(CaptureStencilMaskSeparate(replayState, true, GL_BACK,
                                           currentDSState.stencilBackWritemask));
        }
    }

    // Blend state.
    const gl::BlendStateExt &defaultBlend = replayState.getBlendStateExt();
    const gl::BlendStateExt &currentBlend = apiState.getBlendStateExt();

    // First, check if every draw buffer blend state matches zero buffer.
    // If so, we can set them all the same using calls available before ES 3.2
    if (BlendStateEqualPerDrawBuffer(apiState))
    {
        if (currentBlend.getEnabledMask().test(0) != defaultBlend.getEnabledMask().test(0))
        {
            capCap(GL_BLEND, currentBlend.getEnabledMask().test(0));
        }

        if (currentBlend.getSrcColorIndexed(0) != defaultBlend.getSrcColorIndexed(0) ||
            currentBlend.getDstColorIndexed(0) != defaultBlend.getDstColorIndexed(0) ||
            currentBlend.getSrcAlphaIndexed(0) != defaultBlend.getSrcAlphaIndexed(0) ||
            currentBlend.getDstAlphaIndexed(0) != defaultBlend.getDstAlphaIndexed(0))
        {
            GLenum srcColor = ToGLenum(currentBlend.getSrcColorIndexed(0));
            GLenum dstColor = ToGLenum(currentBlend.getDstColorIndexed(0));
            GLenum srcAlpha = ToGLenum(currentBlend.getSrcAlphaIndexed(0));
            GLenum dstAlpha = ToGLenum(currentBlend.getDstAlphaIndexed(0));

            if (context->isGLES1())
            {
                // Even though their states are tracked independently, in GLES1 blendAlpha
                // and blendRGB cannot be set separately and are always equal
                cap(CaptureBlendFunc(replayState, true, srcColor, dstColor));
                Capture(&resetCalls[angle::EntryPoint::GLBlendFunc],
                        CaptureBlendFunc(replayState, true, srcColor, dstColor));
            }
            else
            {
                // Always use BlendFuncSeparate for non-GLES1 as it covers all cases
                cap(CaptureBlendFuncSeparate(replayState, true, srcColor, dstColor, srcAlpha,
                                             dstAlpha));
                Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate],
                        CaptureBlendFuncSeparate(replayState, true, srcColor, dstColor, srcAlpha,
                                                 dstAlpha));
            }
        }

        if (currentBlend.getEquationColorIndexed(0) != defaultBlend.getEquationColorIndexed(0) ||
            currentBlend.getEquationAlphaIndexed(0) != defaultBlend.getEquationAlphaIndexed(0))
        {
            GLenum eqColor = ToGLenum(currentBlend.getEquationColorIndexed(0));
            GLenum eqAlpha = ToGLenum(currentBlend.getEquationAlphaIndexed(0));

            // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset.
            cap(CaptureBlendEquationSeparate(replayState, true, eqColor, eqAlpha));
            Capture(&resetCalls[angle::EntryPoint::GLBlendEquationSeparate],
                    CaptureBlendEquationSeparate(replayState, true, eqColor, eqAlpha));
        }

        bool defaultColorMaskRed, defaultColorMaskGreen, defaultColorMaskBlue,
            defaultColorMaskAlpha;
        defaultBlend.getColorMaskIndexed(0, &defaultColorMaskRed, &defaultColorMaskGreen,
                                         &defaultColorMaskBlue, &defaultColorMaskAlpha);

        bool currentColorMaskRed, currentColorMaskGreen, currentColorMaskBlue,
            currentColorMaskAlpha;
        currentBlend.getColorMaskIndexed(0, &currentColorMaskRed, &currentColorMaskGreen,
                                         &currentColorMaskBlue, &currentColorMaskAlpha);

        if (currentColorMaskRed != defaultColorMaskRed ||
            currentColorMaskGreen != defaultColorMaskGreen ||
            currentColorMaskBlue != defaultColorMaskBlue ||
            currentColorMaskAlpha != defaultColorMaskAlpha)
        {
            cap(CaptureColorMask(replayState, true, gl::ConvertToGLBoolean(currentColorMaskRed),
                                 gl::ConvertToGLBoolean(currentColorMaskGreen),
                                 gl::ConvertToGLBoolean(currentColorMaskBlue),
                                 gl::ConvertToGLBoolean(currentColorMaskAlpha)));
            Capture(&resetCalls[angle::EntryPoint::GLColorMask],
                    CaptureColorMask(replayState, true, gl::ConvertToGLBoolean(currentColorMaskRed),
                                     gl::ConvertToGLBoolean(currentColorMaskGreen),
                                     gl::ConvertToGLBoolean(currentColorMaskBlue),
                                     gl::ConvertToGLBoolean(currentColorMaskAlpha)));
        }
    }
    else
    {
        // Otherwise, we must use EXT_draw_buffers_indexed features to set them independently
        for (int idx = 0; idx < currentBlend.getDrawBufferCount(); idx++)
        {
            if (currentBlend.getEnabledMask().test(idx) != defaultBlend.getEnabledMask().test(idx))
            {
                if (currentBlend.getEnabledMask().test(idx))
                {
                    cap(CaptureEnableiEXT(replayState, true, GL_BLEND, static_cast<GLint>(idx)));
                }
                else
                {
                    cap(CaptureDisableiEXT(replayState, true, GL_BLEND, static_cast<GLint>(idx)));
                }
            }

            if (currentBlend.getSrcColorIndexed(idx) != defaultBlend.getSrcColorIndexed(idx) ||
                currentBlend.getDstColorIndexed(idx) != defaultBlend.getDstColorIndexed(idx) ||
                currentBlend.getSrcAlphaIndexed(idx) != defaultBlend.getSrcAlphaIndexed(idx) ||
                currentBlend.getDstAlphaIndexed(idx) != defaultBlend.getDstAlphaIndexed(idx))
            {
                // Always use BlendFuncSeparate as it covers all cases
                cap(CaptureBlendFuncSeparateiEXT(replayState, true, idx,
                                                 ToGLenum(currentBlend.getSrcColorIndexed(idx)),
                                                 ToGLenum(currentBlend.getDstColorIndexed(idx)),
                                                 ToGLenum(currentBlend.getSrcAlphaIndexed(idx)),
                                                 ToGLenum(currentBlend.getDstAlphaIndexed(idx))));
                Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate],
                        CaptureBlendFuncSeparateiEXT(
                            replayState, true, idx, ToGLenum(currentBlend.getSrcColorIndexed(idx)),
                            ToGLenum(currentBlend.getDstColorIndexed(idx)),
                            ToGLenum(currentBlend.getSrcAlphaIndexed(idx)),
                            ToGLenum(currentBlend.getDstAlphaIndexed(idx))));
            }

            if (currentBlend.getEquationColorIndexed(idx) !=
                    defaultBlend.getEquationColorIndexed(idx) ||
                currentBlend.getEquationAlphaIndexed(idx) !=
                    defaultBlend.getEquationAlphaIndexed(idx))
            {
                // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset.
                cap(CaptureBlendEquationSeparateiEXT(
                    replayState, true, idx, ToGLenum(currentBlend.getEquationColorIndexed(idx)),
                    ToGLenum(currentBlend.getEquationAlphaIndexed(idx))));
                Capture(
                    &resetCalls[angle::EntryPoint::GLBlendEquationSeparate],
                    CaptureBlendEquationSeparateiEXT(
                        replayState, true, idx, ToGLenum(currentBlend.getEquationColorIndexed(idx)),
                        ToGLenum(currentBlend.getEquationAlphaIndexed(idx))));
            }

            if (currentBlend.getColorMaskIndexed(idx) != defaultBlend.getColorMaskIndexed(idx))
            {
                cap(CaptureColorMaskiEXT(
                    replayState, true, idx,
                    gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 1),
                    gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 2),
                    gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 4),
                    gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 8)));
                Capture(&resetCalls[angle::EntryPoint::GLColorMask],
                        CaptureColorMaskiEXT(
                            replayState, true, idx,
                            gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 1),
                            gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 2),
                            gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 4),
                            gl::ConvertToGLBoolean(currentBlend.getColorMaskIndexed(idx) & 8)));
            }
        }
    }

    const gl::ColorF &currentBlendColor = apiState.getBlendColor();
    if (currentBlendColor != gl::ColorF())
    {
        cap(CaptureBlendColor(replayState, true, currentBlendColor.red, currentBlendColor.green,
                              currentBlendColor.blue, currentBlendColor.alpha));
        Capture(&resetCalls[angle::EntryPoint::GLBlendColor],
                CaptureBlendColor(replayState, true, currentBlendColor.red, currentBlendColor.green,
                                  currentBlendColor.blue, currentBlendColor.alpha));
    }

    // Pixel storage states.
    gl::PixelPackState &currentPackState = replayState.getPackState();
    if (currentPackState.alignment != apiState.getPackAlignment())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::PackAlignment,
                               apiState.getPackAlignment()));
        currentPackState.alignment = apiState.getPackAlignment();
    }

    if (currentPackState.rowLength != apiState.getPackRowLength())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::PackRowLength,
                               apiState.getPackRowLength()));
        currentPackState.rowLength = apiState.getPackRowLength();
    }

    if (currentPackState.skipRows != apiState.getPackSkipRows())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::PackSkipRows,
                               apiState.getPackSkipRows()));
        currentPackState.skipRows = apiState.getPackSkipRows();
    }

    if (currentPackState.skipPixels != apiState.getPackSkipPixels())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::PackSkipPixels,
                               apiState.getPackSkipPixels()));
        currentPackState.skipPixels = apiState.getPackSkipPixels();
    }

    // We set unpack alignment above, no need to change it here
    ASSERT(currentUnpackState.alignment == 1);
    if (currentUnpackState.rowLength != apiState.getUnpackRowLength())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackRowLength,
                               apiState.getUnpackRowLength()));
        currentUnpackState.rowLength = apiState.getUnpackRowLength();
    }

    if (currentUnpackState.skipRows != apiState.getUnpackSkipRows())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackSkipRows,
                               apiState.getUnpackSkipRows()));
        currentUnpackState.skipRows = apiState.getUnpackSkipRows();
    }

    if (currentUnpackState.skipPixels != apiState.getUnpackSkipPixels())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackSkipPixels,
                               apiState.getUnpackSkipPixels()));
        currentUnpackState.skipPixels = apiState.getUnpackSkipPixels();
    }

    if (currentUnpackState.imageHeight != apiState.getUnpackImageHeight())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackImageHeight,
                               apiState.getUnpackImageHeight()));
        currentUnpackState.imageHeight = apiState.getUnpackImageHeight();
    }

    if (currentUnpackState.skipImages != apiState.getUnpackSkipImages())
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackSkipImages,
                               apiState.getUnpackSkipImages()));
        currentUnpackState.skipImages = apiState.getUnpackSkipImages();
    }

    // Clear state. Missing ES 3.x features.
    // TODO(http://anglebug.com/42262323): Complete state capture.
    const gl::ColorF &currentClearColor = apiState.getColorClearValue();
    if (currentClearColor != gl::ColorF())
    {
        cap(CaptureClearColor(replayState, true, currentClearColor.red, currentClearColor.green,
                              currentClearColor.blue, currentClearColor.alpha));
    }

    if (apiState.getDepthClearValue() != 1.0f)
    {
        cap(CaptureClearDepthf(replayState, true, apiState.getDepthClearValue()));
    }

    if (apiState.getStencilClearValue() != 0)
    {
        cap(CaptureClearStencil(replayState, true, apiState.getStencilClearValue()));
    }

    // Viewport / scissor / clipping planes.
    const gl::Rectangle &currentViewport = apiState.getViewport();
    if (currentViewport != gl::Rectangle())
    {
        cap(CaptureViewport(replayState, true, currentViewport.x, currentViewport.y,
                            currentViewport.width, currentViewport.height));
    }

    if (apiState.getNearPlane() != 0.0f || apiState.getFarPlane() != 1.0f)
    {
        cap(CaptureDepthRangef(replayState, true, apiState.getNearPlane(), apiState.getFarPlane()));
    }

    if (apiState.getClipOrigin() != gl::ClipOrigin::LowerLeft ||
        apiState.getClipDepthMode() != gl::ClipDepthMode::NegativeOneToOne)
    {
        cap(CaptureClipControlEXT(replayState, true, apiState.getClipOrigin(),
                                  apiState.getClipDepthMode()));
    }

    if (apiState.isScissorTestEnabled())
    {
        capCap(GL_SCISSOR_TEST, apiState.isScissorTestEnabled());
    }

    const gl::Rectangle &currentScissor = apiState.getScissor();
    if (currentScissor != gl::Rectangle())
    {
        cap(CaptureScissor(replayState, true, currentScissor.x, currentScissor.y,
                           currentScissor.width, currentScissor.height));
    }

    // Allow the replayState object to be destroyed conveniently.
    replayState.setBufferBinding(context, gl::BufferBinding::Array, nullptr);

    // Clean up the replay state.
    replayState.reset(context);

    GLint contextUnpackAlignment = context->getState().getUnpackState().alignment;
    if (currentUnpackState.alignment != contextUnpackAlignment)
    {
        cap(CapturePixelStorei(replayState, true, gl::PackUnpackParameter::UnpackAlignment,
                               contextUnpackAlignment));
        replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(contextUnpackAlignment);
    }

    if (validationEnabled)
    {
        CaptureValidateSerializedState(context, setupCalls);
    }
}

bool SkipCall(const CallCapture &call)
{
    // Skip capture of fixture-injected calls to keep retraces clean
    if (MaybeSkipCapture(call) || g_skipCapture)
    {
        return true;
    }

    switch (call.entryPoint)
    {
        case EntryPoint::GLDebugMessageCallback:
        case EntryPoint::GLDebugMessageCallbackKHR:
        case EntryPoint::GLDebugMessageControl:
        case EntryPoint::GLDebugMessageControlKHR:
        case EntryPoint::GLDebugMessageInsert:
        case EntryPoint::GLDebugMessageInsertKHR:
        case EntryPoint::GLGetDebugMessageLog:
        case EntryPoint::GLGetDebugMessageLogKHR:
        case EntryPoint::GLGetObjectLabel:
        case EntryPoint::GLGetObjectLabelEXT:
        case EntryPoint::GLGetObjectLabelKHR:
        case EntryPoint::GLGetObjectPtrLabelKHR:
        case EntryPoint::GLGetPointervKHR:
        case EntryPoint::GLInsertEventMarkerEXT:
        case EntryPoint::GLLabelObjectEXT:
        case EntryPoint::GLObjectLabel:
        case EntryPoint::GLObjectLabelKHR:
        case EntryPoint::GLObjectPtrLabelKHR:
        case EntryPoint::GLPopDebugGroupKHR:
        case EntryPoint::GLPopGroupMarkerEXT:
        case EntryPoint::GLPushDebugGroupKHR:
        case EntryPoint::GLPushGroupMarkerEXT:
            // Purposefully skip entry points from:
            // - KHR_debug
            // - EXT_debug_label
            // - EXT_debug_marker
            // There is no need to capture these for replaying a trace in our harness
            return true;

        case EntryPoint::GLGetActiveUniform:
        case EntryPoint::GLGetActiveUniformsiv:
            // Skip these calls because:
            // - We don't use the return values.
            // - Active uniform counts can vary between platforms due to cross stage optimizations
            //   and asking about uniforms above GL_ACTIVE_UNIFORMS triggers errors.
            return true;

        case EntryPoint::GLGetActiveAttrib:
            // Skip these calls because:
            // - We don't use the return values.
            // - Same as uniforms, the value can vary, asking above GL_ACTIVE_ATTRIBUTES is an error
            return true;

        case EntryPoint::GLGetActiveUniformBlockiv:
        case EntryPoint::GLGetActiveUniformBlockName:
            // Skip these calls because:
            // - We don't use the return values.
            // - It reduces the number of references to the uniform block index map.
            return true;

        case EntryPoint::EGLChooseConfig:
        case EntryPoint::EGLGetProcAddress:
        case EntryPoint::EGLGetConfigAttrib:
        case EntryPoint::EGLGetConfigs:
        case EntryPoint::EGLGetSyncAttrib:
        case EntryPoint::EGLGetSyncAttribKHR:
        case EntryPoint::EGLQueryContext:
        case EntryPoint::EGLQuerySurface:
            // Skip these calls because:
            // - We don't use the return values.
            // - Some EGL types and pointer parameters aren't yet implemented in EGL capture.
            return true;

        case EntryPoint::EGLPrepareSwapBuffersANGLE:
            // Skip this call because:
            // - eglPrepareSwapBuffersANGLE is automatically called by eglSwapBuffers
            return true;

        case EntryPoint::EGLSwapBuffers:
            // Skip these calls because:
            // - Swap is handled specially by the trace harness.
            return true;

        default:
            break;
    }

    return false;
}

PageRange::PageRange(size_t start, size_t end) : start(start), end(end) {}
PageRange::~PageRange() = default;

AddressRange::AddressRange() {}
AddressRange::AddressRange(uintptr_t start, size_t size) : start(start), size(size) {}
AddressRange::~AddressRange() = default;

uintptr_t AddressRange::end()
{
    return start + size;
}

bool IsTrackedPerContext(ResourceIDType type)
{
    // This helper function informs us which context-local (not shared) objects are tracked
    // with per-context object maps.
    if (IsSharedObjectResource(type))
    {
        return false;
    }

    // TODO (https://issuetracker.google.com/169868803): Remaining context-local resources (VAOs,
    // PPOs, Transform Feedback Objects, and Query Objects) must also tracked per-context. Once all
    // per-context resource handling is correctly updated then this function can be replaced with
    // !IsSharedObjectResource().
    switch (type)
    {
        case ResourceIDType::Framebuffer:
            return true;

        default:
            return false;
    }
}

CoherentBuffer::CoherentBuffer(uintptr_t start,
                               size_t size,
                               size_t pageSize,
                               bool isShadowMemoryEnabled)
    : mPageSize(pageSize),
      mShadowMemoryEnabled(isShadowMemoryEnabled),
      mBufferStart(start),
      mShadowMemory(nullptr),
      mShadowDirty(false)
{
    if (mShadowMemoryEnabled)
    {
        // Shadow memory needs to have at least the size of one page, to not protect outside.
        size_t numShadowPages = (size / pageSize) + 1;
        mShadowMemory         = AlignedAlloc(numShadowPages * pageSize, pageSize);
        ASSERT(mShadowMemory != nullptr);
        start = reinterpret_cast<uintptr_t>(mShadowMemory);
    }

    mRange.start           = start;
    mRange.size            = size;
    mProtectionRange.start = rx::roundDownPow2(start, pageSize);

    uintptr_t protectionEnd = rx::roundUpPow2(start + size, pageSize);

    mProtectionRange.size = protectionEnd - mProtectionRange.start;
    mPageCount            = mProtectionRange.size / pageSize;

    mProtectionStartPage = mProtectionRange.start / mPageSize;
    mProtectionEndPage   = mProtectionStartPage + mPageCount;

    mDirtyPages = std::vector<bool>(mPageCount);
    mDirtyPages.assign(mPageCount, true);
}

std::vector<PageRange> CoherentBuffer::getDirtyPageRanges()
{
    std::vector<PageRange> dirtyPageRanges;

    bool inDirty = false;
    for (size_t i = 0; i < mPageCount; i++)
    {
        if (!inDirty && mDirtyPages[i])
        {
            // Found start of a dirty range
            inDirty = true;
            // Set end page as last page initially
            dirtyPageRanges.push_back(PageRange(i, mPageCount));
        }
        else if (inDirty && !mDirtyPages[i])
        {
            // Found end of a dirty range
            inDirty                    = false;
            dirtyPageRanges.back().end = i;
        }
    }

    return dirtyPageRanges;
}

AddressRange CoherentBuffer::getRange()
{
    return mRange;
}

AddressRange CoherentBuffer::getDirtyAddressRange(const PageRange &dirtyPageRange)
{
    AddressRange range;

    if (dirtyPageRange.start == 0)
    {
        // First page, use non page aligned buffer start.
        range.start = mRange.start;
    }
    else
    {
        range.start = mProtectionRange.start + dirtyPageRange.start * mPageSize;
    }

    if (dirtyPageRange.end == mPageCount)
    {
        // Last page, use non page aligned buffer end.
        range.size = mRange.end() - range.start;
    }
    else
    {
        range.size = (dirtyPageRange.end - dirtyPageRange.start) * mPageSize;
        // This occurs when a buffer occupies 2 pages, but is smaller than a page.
        if (mRange.end() < range.end())
        {
            range.size = mRange.end() - range.start;
        }
    }

    // Dirty range must be in buffer
    ASSERT(range.start >= mRange.start && mRange.end() >= range.end());

    return range;
}

CoherentBuffer::~CoherentBuffer()
{
    if (mShadowMemory != nullptr)
    {
        AlignedFree(mShadowMemory);
    }
}

bool CoherentBuffer::isDirty()
{
    return std::find(mDirtyPages.begin(), mDirtyPages.end(), true) != mDirtyPages.end();
}

bool CoherentBuffer::contains(size_t page, size_t *relativePage)
{
    bool isInProtectionRange = page >= mProtectionStartPage && page < mProtectionEndPage;
    if (!isInProtectionRange)
    {
        return false;
    }

    *relativePage = page - mProtectionStartPage;

    ASSERT(page >= mProtectionStartPage);

    return true;
}

void CoherentBuffer::protectPageRange(const PageRange &pageRange)
{
    for (size_t i = pageRange.start; i < pageRange.end; i++)
    {
        setDirty(i, false);
    }
}

void CoherentBuffer::protectAll()
{
    for (size_t i = 0; i < mPageCount; i++)
    {
        setDirty(i, false);
    }
}

void CoherentBuffer::updateBufferMemory()
{
    memcpy(reinterpret_cast<void *>(mBufferStart), reinterpret_cast<void *>(mRange.start),
           mRange.size);
}

void CoherentBuffer::updateShadowMemory()
{
    memcpy(reinterpret_cast<void *>(mRange.start), reinterpret_cast<void *>(mBufferStart),
           mRange.size);
    mShadowDirty = false;
}

void CoherentBuffer::setDirty(size_t relativePage, bool dirty)
{
    if (mDirtyPages[relativePage] == dirty)
    {
        // The page is already set.
        // This can happen when tracked buffers overlap in a page.
        return;
    }

    uintptr_t pageStart = mProtectionRange.start + relativePage * mPageSize;

    // Last page end must be the same as protection end
    if (relativePage + 1 == mPageCount)
    {
        ASSERT(mProtectionRange.end() == pageStart + mPageSize);
    }

    bool ret;
    if (dirty)
    {
        ret = UnprotectMemory(pageStart, mPageSize);
    }
    else
    {
        ret = ProtectMemory(pageStart, mPageSize);
    }

    if (!ret)
    {
        ERR() << "Could not set protection for buffer page " << relativePage << " at "
              << reinterpret_cast<void *>(pageStart) << " with size " << mPageSize;
    }
    mDirtyPages[relativePage] = dirty;
}

void CoherentBuffer::removeProtection(PageSharingType sharingType)
{
    uintptr_t start = mProtectionRange.start;
    size_t size     = mProtectionRange.size;

    switch (sharingType)
    {
        case PageSharingType::FirstShared:
        case PageSharingType::FirstAndLastShared:
            start += mPageSize;
            break;
        default:
            break;
    }

    switch (sharingType)
    {
        case PageSharingType::FirstShared:
        case PageSharingType::LastShared:
            size -= mPageSize;
            break;
        case PageSharingType::FirstAndLastShared:
            size -= (2 * mPageSize);
            break;
        default:
            break;
    }

    if (size == 0)
    {
        return;
    }

    if (!UnprotectMemory(start, size))
    {
        ERR() << "Could not remove protection for buffer at " << start << " with size " << size;
    }
}

bool CoherentBufferTracker::canProtectDirectly(gl::Context *context)
{
    return context->canProtectCoherentMemoryDirectly();
}

PageFaultHandlerRangeType CoherentBufferTracker::handleWrite(uintptr_t address)
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);
    auto pagesInBuffers = getBufferPagesForAddress(address);

    if (pagesInBuffers.empty())
    {
        ERR() << "Didn't find a tracked buffer containing " << reinterpret_cast<void *>(address);
    }

    for (const auto &page : pagesInBuffers)
    {
        std::shared_ptr<CoherentBuffer> buffer = page.first;
        size_t relativePage                    = page.second;
        buffer->setDirty(relativePage, true);
    }

    return pagesInBuffers.empty() ? PageFaultHandlerRangeType::OutOfRange
                                  : PageFaultHandlerRangeType::InRange;
}

HashMap<std::shared_ptr<CoherentBuffer>, size_t> CoherentBufferTracker::getBufferPagesForAddress(
    uintptr_t address)
{
    HashMap<std::shared_ptr<CoherentBuffer>, size_t> foundPages;

#if defined(ANGLE_PLATFORM_ANDROID)
    size_t page;
    if (mShadowMemoryEnabled)
    {
        // Starting with Android 11 heap pointers get a tag which is stripped by the POSIX mprotect
        // callback. We need to add this tag manually to the untagged pointer in order to determine
        // the corresponding page.
        // See: https://source.android.com/docs/security/test/tagged-pointers
        // TODO(http://anglebug.com/42265874): Determine when heap pointer tagging is not enabled.
        constexpr unsigned long long POINTER_TAG = 0xb400000000000000;
        unsigned long long taggedAddress         = address | POINTER_TAG;
        page                                     = static_cast<size_t>(taggedAddress / mPageSize);
    }
    else
    {
        // VMA allocated memory pointers are not tagged.
        page = address / mPageSize;
    }
#else
    size_t page = address / mPageSize;
#endif

    for (const auto &pair : mBuffers)
    {
        std::shared_ptr<CoherentBuffer> buffer = pair.second;
        size_t relativePage;
        if (buffer->contains(page, &relativePage))
        {
            foundPages.insert(std::make_pair(buffer, relativePage));
        }
    }

    return foundPages;
}

bool CoherentBufferTracker::isDirty(gl::BufferID id)
{
    return mBuffers[id.value]->isDirty();
}

void CoherentBufferTracker::enable()
{
    if (mEnabled)
    {
        return;
    }

    PageFaultCallback callback = [this](uintptr_t address) { return handleWrite(address); };

    // This needs to be initialized after canProtectDirectly ran and can only be initialized once.
    if (!mPageFaultHandler)
    {
        mPageFaultHandler = std::unique_ptr<PageFaultHandler>(CreatePageFaultHandler(callback));
    }

    bool ret = mPageFaultHandler->enable();
    if (ret)
    {
        mEnabled = true;
    }
    else
    {
        ERR() << "Could not enable page fault handler.";
    }
}

bool CoherentBufferTracker::haveBuffer(gl::BufferID id)
{
    return mBuffers.find(id.value) != mBuffers.end();
}

void CoherentBufferTracker::onEndFrame()
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);

    if (!mEnabled)
    {
        return;
    }

    mHasBeenReset = true;

    // Remove protection from all buffers
    for (const auto &pair : mBuffers)
    {
        std::shared_ptr<CoherentBuffer> buffer = pair.second;
        buffer->removeProtection(PageSharingType::NoneShared);
    }

    disable();
}

uintptr_t CoherentBufferTracker::addBuffer(gl::BufferID id, uintptr_t start, size_t size)
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);

    if (haveBuffer(id))
    {
        auto buffer = mBuffers[id.value];
        return buffer->getRange().start;
    }

    auto buffer = std::make_shared<CoherentBuffer>(start, size, mPageSize, mShadowMemoryEnabled);
    uintptr_t realOrShadowStart = buffer->getRange().start;

    mBuffers.insert(std::make_pair(id.value, std::move(buffer)));

    return realOrShadowStart;
}

void CoherentBufferTracker::maybeUpdateShadowMemory()
{
    for (const auto &pair : mBuffers)
    {
        std::shared_ptr<CoherentBuffer> cb = pair.second;
        if (cb->isShadowDirty())
        {
            cb->removeProtection(PageSharingType::NoneShared);
            cb->updateShadowMemory();
            cb->protectAll();
        }
    }
}

void CoherentBufferTracker::markAllShadowDirty()
{
    for (const auto &pair : mBuffers)
    {
        std::shared_ptr<CoherentBuffer> cb = pair.second;
        cb->markShadowDirty();
    }
}

PageSharingType CoherentBufferTracker::doesBufferSharePage(gl::BufferID id)
{
    bool firstPageShared = false;
    bool lastPageShared  = false;

    std::shared_ptr<CoherentBuffer> buffer = mBuffers[id.value];

    AddressRange range = buffer->getRange();

    size_t firstPage = range.start / mPageSize;
    size_t lastPage  = range.end() / mPageSize;

    for (const auto &pair : mBuffers)
    {
        gl::BufferID otherId = {pair.first};
        if (otherId != id)
        {
            std::shared_ptr<CoherentBuffer> otherBuffer = pair.second;
            size_t relativePage;
            if (otherBuffer->contains(firstPage, &relativePage))
            {
                firstPageShared = true;
            }
            else if (otherBuffer->contains(lastPage, &relativePage))
            {
                lastPageShared = true;
            }
        }
    }

    if (firstPageShared && !lastPageShared)
    {
        return PageSharingType::FirstShared;
    }
    else if (!firstPageShared && lastPageShared)
    {
        return PageSharingType::LastShared;
    }
    else if (firstPageShared && lastPageShared)
    {
        return PageSharingType::FirstAndLastShared;
    }
    else
    {
        return PageSharingType::NoneShared;
    }
}

void CoherentBufferTracker::removeBuffer(gl::BufferID id)
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);

    if (!haveBuffer(id))
    {
        return;
    }

    // Synchronize graphics buffer memory before the buffer is removed from the tracker.
    if (mShadowMemoryEnabled)
    {
        mBuffers[id.value]->updateBufferMemory();
    }

    // If the buffer shares pages with other tracked buffers,
    // don't unprotect the overlapping pages.
    PageSharingType sharingType = doesBufferSharePage(id);
    mBuffers[id.value]->removeProtection(sharingType);
    mBuffers.erase(id.value);
}

void *FrameCaptureShared::maybeGetShadowMemoryPointer(gl::Buffer *buffer,
                                                      GLsizeiptr length,
                                                      GLbitfield access)
{
    if (!(access & GL_MAP_COHERENT_BIT_EXT) || !mCoherentBufferTracker.isShadowMemoryEnabled())
    {
        return buffer->getMapPointer();
    }

    mCoherentBufferTracker.enable();
    uintptr_t realMapPointer = reinterpret_cast<uintptr_t>(buffer->getMapPointer());
    return (void *)mCoherentBufferTracker.addBuffer(buffer->id(), realMapPointer, length);
}

void FrameCaptureShared::determineMemoryProtectionSupport(gl::Context *context)
{
    // Skip this test if shadow memory was force enabled or shadow memory requirement was detected
    // previously
    if (mCoherentBufferTracker.isShadowMemoryEnabled())
    {
        return;
    }

    // These known devices must use shadow memory
    HashMap<std::string, std::vector<std::string>> denyList = {
        {"Google", {"Pixel 6", "Pixel 6 Pro", "Pixel 6a", "Pixel 7", "Pixel 7 Pro"}},
    };

    angle::SystemInfo info;
    angle::GetSystemInfo(&info);
    bool isDeviceDenyListed = false;

    if (rx::GetAndroidSDKVersion() < 34)
    {
        // Before Android 14, there was a bug in Mali based Pixel preventing mprotect
        // on Vulkan surfaces. (https://b.corp.google.com/issues/269535398)
        // Check the denylist in this case.
        if (denyList.find(info.machineManufacturer) != denyList.end())
        {
            const std::vector<std::string> &models = denyList[info.machineManufacturer];
            isDeviceDenyListed =
                std::find(models.begin(), models.end(), info.machineModelName) != models.end();
        }
    }

    if (isDeviceDenyListed)
    {
        WARN() << "Direct memory protection not possible on deny listed device '"
               << info.machineModelName
               << "', enabling shadow memory for coherent buffer tracking.";
        mCoherentBufferTracker.enableShadowMemory();
    }
    else
    {
        // Device is not on deny listed. Run a test if we actually can protect directly. Do this
        // only on assertion enabled builds.
        ASSERT(mCoherentBufferTracker.canProtectDirectly(context));
    }
}

void FrameCaptureShared::trackBufferMapping(const gl::Context *context,
                                            CallCapture *call,
                                            gl::BufferID id,
                                            gl::Buffer *buffer,
                                            GLintptr offset,
                                            GLsizeiptr length,
                                            bool writable,
                                            bool coherent,
                                            bool persistent)
{
    // Track that the buffer was mapped
    mResourceTracker.setBufferMapped(context->id(), id.value);

    if (writable)
    {
        // If this buffer was mapped writable, we don't have any visibility into what
        // happens to it. Therefore, remember the details about it, and we'll read it back
        // on Unmap to repopulate it during replay.
        mBufferDataMap[id] = std::make_pair(offset, length);

        // Track that this buffer was potentially modified
        mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Buffer)
            .setModifiedResource(id.value);

        // Track coherent buffer
        // Check if capture is active to not initialize the coherent buffer tracker on the
        // first coherent glMapBufferRange call.
        if ((coherent || persistent) && isCaptureActive())
        {
            if (mCoherentBufferTracker.hasBeenReset())
            {
                FATAL() << "Multi-capture not supprted for apps using persistent coherent memory";
            }

            // To allow for incomplete synchronization seen in popular apps, treat persistent
            // writable memory as coherent. See http://issuetracker.google.com/460704266.
            if (!coherent)
            {
                WARN() << "Treating persistent, non-coherent buffer " << id.value << " as coherent";
            }

            mCoherentBufferTracker.enable();
            // When not using shadow memory, adding buffers to the tracking happens here instead of
            // during mapping
            if (!mCoherentBufferTracker.isShadowMemoryEnabled())
            {
                uintptr_t data = reinterpret_cast<uintptr_t>(buffer->getMapPointer());
                mCoherentBufferTracker.addBuffer(id, data, length);
            }
        }
    }
}

void FrameCaptureShared::trackTextureUpdate(const gl::Context *context, const CallCapture &call)
{
    int index             = 0;
    std::string paramName = "targetPacked";
    ParamType paramType   = ParamType::TTextureTarget;

    // Some calls provide the textureID directly
    // For the rest, look it up based on the currently bound texture
    switch (call.entryPoint)
    {
        case EntryPoint::GLCompressedCopyTextureCHROMIUM:
            index     = 1;
            paramName = "destIdPacked";
            paramType = ParamType::TTextureID;
            break;
        case EntryPoint::GLCopyTextureCHROMIUM:
        case EntryPoint::GLCopySubTextureCHROMIUM:
        case EntryPoint::GLCopyTexture3DANGLE:
            index     = 3;
            paramName = "destIdPacked";
            paramType = ParamType::TTextureID;
            break;
        case EntryPoint::GLCopyImageSubData:
        case EntryPoint::GLCopyImageSubDataEXT:
        case EntryPoint::GLCopyImageSubDataOES:
            index     = 7;
            paramName = "dstTarget";
            paramType = ParamType::TGLenum;
            break;
        default:
            break;
    }

    GLuint id = 0;
    switch (paramType)
    {
        case ParamType::TTextureTarget:
        {
            gl::TextureTarget targetPacked =
                call.params.getParam(paramName.c_str(), ParamType::TTextureTarget, index)
                    .value.TextureTargetVal;
            gl::TextureType textureType = gl::TextureTargetToType(targetPacked);
            gl::Texture *texture        = context->getState().getTargetTexture(textureType);
            id                          = texture->id().value;
            break;
        }
        case ParamType::TTextureID:
        {
            gl::TextureID destIDPacked =
                call.params.getParam(paramName.c_str(), ParamType::TTextureID, index)
                    .value.TextureIDVal;
            id = destIDPacked.value;
            break;
        }
        case ParamType::TGLenum:
        {
            GLenum target =
                call.params.getParam(paramName.c_str(), ParamType::TGLenum, index).value.GLenumVal;

            if (target == GL_TEXTURE_CUBE_MAP)
            {
                // CopyImageSubData doesn't support cube faces, but PackedParams requires one
                target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
            }

            gl::TextureTarget targetPacked = gl::PackParam<gl::TextureTarget>(target);
            gl::TextureType textureType    = gl::TextureTargetToType(targetPacked);
            gl::Texture *texture           = context->getState().getTargetTexture(textureType);
            id                             = texture->id().value;
            break;
        }
        default:
            ERR() << "Unhandled paramType= " << static_cast<int>(paramType);
            UNREACHABLE();
            break;
    }

    // Mark it as modified
    mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Texture)
        .setModifiedResource(id);
}

// Identify and mark texture-based framebuffer attachments as modified
void FrameCaptureShared::trackFramebufferAttachmentUpdate(const gl::Context *context,
                                                          const CallCapture &call)
{
    const gl::State &state                 = context->getState();
    const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();

    // Only FBOs can have attachments that we need to track
    if (drawFramebuffer->isDefault())
    {
        return;
    }

    bool colorModified          = false;
    bool depthModified          = false;
    bool stencilModified        = false;
    const EntryPoint entryPoint = call.entryPoint;

    if (IsDrawEntryPoint(entryPoint))
    {
        // Based on the current draw call, determine if any attachments are modified
        colorModified = drawFramebuffer->getDrawBufferMask().any() &&
                        !state.allActiveDrawBufferChannelsMasked();
        depthModified   = drawFramebuffer->getDepthAttachment() && state.isDepthWriteEnabled();
        stencilModified = drawFramebuffer->getStencilAttachment() &&
                          state.isStencilWriteEnabled(drawFramebuffer->getStencilBitCount());
    }
    else
    {
        switch (entryPoint)
        {
            case EntryPoint::GLClear:
            case EntryPoint::GLBlitFramebuffer:
            {
                // BlitFramebuffer mask is at index 8, Clear mask is at index 0
                int maskIndex   = (entryPoint == EntryPoint::GLClear) ? 0 : 8;
                GLbitfield mask = call.params.getParam("mask", ParamType::TGLbitfield, maskIndex)
                                      .value.GLbitfieldVal;
                colorModified   = (mask & GL_COLOR_BUFFER_BIT);
                depthModified   = (mask & GL_DEPTH_BUFFER_BIT);
                stencilModified = (mask & GL_STENCIL_BUFFER_BIT);
                break;
            }
            case EntryPoint::GLClearBufferfi:
                depthModified   = true;
                stencilModified = true;
                break;
            case EntryPoint::GLClearBufferfv:
            case EntryPoint::GLClearBufferiv:
            case EntryPoint::GLClearBufferuiv:
            {
                GLenum buffer =
                    call.params.getParam("buffer", ParamType::TGLenum, 0).value.GLenumVal;
                colorModified   = (buffer == GL_COLOR);
                depthModified   = (buffer == GL_DEPTH || buffer == GL_DEPTH_STENCIL);
                stencilModified = (buffer == GL_STENCIL || buffer == GL_DEPTH_STENCIL);
                break;
            }
            case EntryPoint::GLInvalidateFramebuffer:
            case EntryPoint::GLDiscardFramebufferEXT:
            {
                GLsizei numAttachments =
                    call.params.getParam("numAttachments", ParamType::TGLsizei, 1).value.GLsizeiVal;
                const GLenum *attachments =
                    call.params.getParam("attachments", ParamType::TGLenumConstPointer, 2)
                        .value.GLenumConstPointerVal;
                for (GLsizei i = 0; i < numAttachments; ++i)
                {
                    if (attachments[i] == GL_DEPTH_ATTACHMENT ||
                        attachments[i] == GL_DEPTH_STENCIL_ATTACHMENT)
                    {
                        depthModified = true;
                    }
                    if (attachments[i] == GL_STENCIL_ATTACHMENT ||
                        attachments[i] == GL_DEPTH_STENCIL_ATTACHMENT)
                    {
                        stencilModified = true;
                    }
                    if (attachments[i] == GL_COLOR || (attachments[i] >= GL_COLOR_ATTACHMENT0 &&
                                                       attachments[i] <= GL_COLOR_ATTACHMENT31))
                    {
                        colorModified = true;
                    }
                }
                break;
            }
            default:
                return;
        }
    }

    if (!colorModified && !depthModified && !stencilModified)
    {
        return;
    }

    auto &textureTracker =
        mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Texture);

    // Helper for marking texture attachment as modified
    auto markModified = [&](const gl::FramebufferAttachment *attachment) {
        if (attachment && attachment->type() == GL_TEXTURE)
        {
            textureTracker.setModifiedResource(attachment->getTexture()->id().value);
        }
    };

    // Mark the identified textures as modified
    if (depthModified)
    {
        markModified(drawFramebuffer->getDepthAttachment());
    }
    if (stencilModified)
    {
        markModified(drawFramebuffer->getStencilAttachment());
    }
    if (colorModified)
    {
        gl::DrawBufferMask colorMask = drawFramebuffer->getDrawBufferMask();
        // If it's a draw mark only the buffers the shader actually writes to
        if (IsDrawEntryPoint(entryPoint))
        {
            colorMask &= state.getBlendStateExt().compareColorMask(0);
        }
        for (size_t i : colorMask)
        {
            markModified(drawFramebuffer->getColorAttachment(i));
        }
    }
}

// Identify and mark writeable shader image textures as modified
void FrameCaptureShared::trackImageUpdate(const gl::Context *context, const CallCapture &call)
{
    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
    for (const gl::ImageBinding &imageBinding : executable->getImageBindings())
    {
        for (GLuint binding : imageBinding.boundImageUnits)
        {
            const gl::ImageUnit &imageUnit = context->getState().getImageUnit(binding);
            if (imageUnit.access != GL_READ_ONLY)
            {
                // Get image binding texture id and mark it as modified
                GLuint id = imageUnit.texture.id().value;
                mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Texture)
                    .setModifiedResource(id);
            }
        }
    }
}

void FrameCaptureShared::trackDefaultUniformUpdate(const gl::Context *context,
                                                   const CallCapture &call)
{
    DefaultUniformType defaultUniformType = GetDefaultUniformType(call);

    GLuint programID = 0;
    int location     = 0;

    // We track default uniform updates by program and location, so look them up in parameters
    if (defaultUniformType == DefaultUniformType::CurrentProgram)
    {
        programID = context->getActiveLinkedProgram()->id().value;

        location = call.params.getParam("locationPacked", ParamType::TUniformLocation, 0)
                       .value.UniformLocationVal.value;
    }
    else
    {
        ASSERT(defaultUniformType == DefaultUniformType::SpecifiedProgram);

        programID = call.params.getParam("programPacked", ParamType::TShaderProgramID, 0)
                        .value.ShaderProgramIDVal.value;

        location = call.params.getParam("locationPacked", ParamType::TUniformLocation, 1)
                       .value.UniformLocationVal.value;
    }

    const TrackedResource &trackedShaderProgram =
        mResourceTracker.getTrackedResource(context->id(), ResourceIDType::ShaderProgram);
    const ResourceSet &startingPrograms = trackedShaderProgram.getStartingResources();
    const ResourceSet &programsToRegen  = trackedShaderProgram.getResourcesToRegen();

    // If this program was in our starting set, track its uniform updates. Unless it was deleted,
    // then its uniforms will all be regenned along wih with the program.
    if (startingPrograms.find(programID) != startingPrograms.end() &&
        programsToRegen.find(programID) == programsToRegen.end())
    {
        // Track that we need to set this default uniform value again
        mResourceTracker.setModifiedDefaultUniform({programID}, {location});
    }
}

void FrameCaptureShared::trackVertexArrayUpdate(const gl::Context *context, const CallCapture &call)
{
    // Look up the currently bound vertex array
    gl::VertexArrayID id = context->getState().getVertexArray()->id();

    // Mark it as modified
    mResourceTracker.getTrackedResource(context->id(), ResourceIDType::VertexArray)
        .setModifiedResource(id.value);
}

void FrameCaptureShared::updateCopyImageSubData(CallCapture &call)
{
    // This call modifies srcName and dstName to no longer be object IDs (GLuint), but actual
    // packed types that can remapped using gTextureMap and gRenderbufferMap

    GLint srcName    = call.params.getParam("srcName", ParamType::TGLuint, 0).value.GLuintVal;
    GLenum srcTarget = call.params.getParam("srcTarget", ParamType::TGLenum, 1).value.GLenumVal;
    switch (srcTarget)
    {
        case GL_RENDERBUFFER:
        {
            // Convert the GLuint to RenderbufferID
            gl::RenderbufferID srcRenderbufferID = {static_cast<GLuint>(srcName)};
            call.params.setValueParamAtIndex("srcName", ParamType::TRenderbufferID,
                                             srcRenderbufferID, 0);
            break;
        }
        case GL_TEXTURE_2D:
        case GL_TEXTURE_2D_ARRAY:
        case GL_TEXTURE_3D:
        case GL_TEXTURE_CUBE_MAP:
        case GL_TEXTURE_CUBE_MAP_ARRAY:
        case GL_TEXTURE_EXTERNAL_OES:
        case GL_TEXTURE_2D_MULTISAMPLE:
        case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
        {
            // Convert the GLuint to TextureID
            gl::TextureID srcTextureID = {static_cast<GLuint>(srcName)};
            call.params.setValueParamAtIndex("srcName", ParamType::TTextureID, srcTextureID, 0);
            break;
        }
        default:
            ERR() << "Unhandled srcTarget = " << srcTarget;
            UNREACHABLE();
            break;
    }

    // Change dstName to the appropriate type based on dstTarget
    GLint dstName    = call.params.getParam("dstName", ParamType::TGLuint, 6).value.GLuintVal;
    GLenum dstTarget = call.params.getParam("dstTarget", ParamType::TGLenum, 7).value.GLenumVal;
    switch (dstTarget)
    {
        case GL_RENDERBUFFER:
        {
            // Convert the GLuint to RenderbufferID
            gl::RenderbufferID dstRenderbufferID = {static_cast<GLuint>(dstName)};
            call.params.setValueParamAtIndex("dstName", ParamType::TRenderbufferID,
                                             dstRenderbufferID, 6);
            break;
        }
        case GL_TEXTURE_2D:
        case GL_TEXTURE_2D_ARRAY:
        case GL_TEXTURE_3D:
        case GL_TEXTURE_CUBE_MAP:
        case GL_TEXTURE_CUBE_MAP_ARRAY:
        case GL_TEXTURE_EXTERNAL_OES:
        case GL_TEXTURE_2D_MULTISAMPLE:
        case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
        {
            // Convert the GLuint to TextureID
            gl::TextureID dstTextureID = {static_cast<GLuint>(dstName)};
            call.params.setValueParamAtIndex("dstName", ParamType::TTextureID, dstTextureID, 6);
            break;
        }
        default:
            ERR() << "Unhandled dstTarget = " << dstTarget;
            UNREACHABLE();
            break;
    }
}

void FrameCaptureShared::overrideProgramBinary(const gl::Context *context,
                                               CallCapture &inCall,
                                               std::vector<CallCapture> &outCalls)
{
    // Program binaries are inherently non-portable, even between two ANGLE builds.
    // If an application is using glProgramBinary in the middle of a trace, we need to replace
    // those calls with an equivalent sequence of portable calls.
    //
    // For example, here is a sequence an app could use for glProgramBinary:
    //
    //   gShaderProgramMap[42] = glCreateProgram();
    //   glProgramBinary(gShaderProgramMap[42], GL_PROGRAM_BINARY_ANGLE, gBinaryData[x], 1000);
    //   glGetProgramiv(gShaderProgramMap[42], GL_LINK_STATUS, gReadBuffer);
    //   glGetProgramiv(gShaderProgramMap[42], GL_PROGRAM_BINARY_LENGTH, gReadBuffer);
    //
    // With this override, the glProgramBinary call will be replaced like so:
    //
    //   gShaderProgramMap[42] = glCreateProgram();
    //   === Begin override ===
    //   gShaderProgramMap[43] = glCreateShader(GL_VERTEX_SHADER);
    //   glShaderSource(gShaderProgramMap[43], 1, string_0, &gBinaryData[100]);
    //   glCompileShader(gShaderProgramMap[43]);
    //   glAttachShader(gShaderProgramMap[42], gShaderProgramMap[43]);
    //   glDeleteShader(gShaderProgramMap[43]);
    //   gShaderProgramMap[43] = glCreateShader(GL_FRAGMENT_SHADER);
    //   glShaderSource(gShaderProgramMap[43], 1, string_1, &gBinaryData[200]);
    //   glCompileShader(gShaderProgramMap[43]);
    //   glAttachShader(gShaderProgramMap[42], gShaderProgramMap[43]);
    //   glDeleteShader(gShaderProgramMap[43]);
    //   glBindAttribLocation(gShaderProgramMap[42], 0, "attrib1");
    //   glBindAttribLocation(gShaderProgramMap[42], 1, "attrib2");
    //   glLinkProgram(gShaderProgramMap[42]);
    //   UpdateUniformLocation(gShaderProgramMap[42], "foo", 0, 20);
    //   UpdateUniformLocation(gShaderProgramMap[42], "bar", 72, 1);
    //   glUseProgram(gShaderProgramMap[42]);
    //   UpdateCurrentProgram(gShaderProgramMap[42]);
    //   glUniform4fv(gUniformLocations[gCurrentProgram][0], 20, &gBinaryData[300]);
    //   glUniform1iv(gUniformLocations[gCurrentProgram][72], 1, &gBinaryData[400]);
    //   === End override ===
    //   glGetProgramiv(gShaderProgramMap[42], GL_LINK_STATUS, gReadBuffer);
    //   glGetProgramiv(gShaderProgramMap[42], GL_PROGRAM_BINARY_LENGTH, gReadBuffer);
    //
    // To facilitate this override, we are serializing each shader stage source into the binary
    // itself.  See Program::serialize and Program::deserialize.  Once extracted from the binary,
    // they will be available via getProgramSources.

    gl::ShaderProgramID id = inCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0)
                                 .value.ShaderProgramIDVal;

    gl::Program *program = context->getProgramResolveLink(id);
    ASSERT(program);

    mResourceTracker.onShaderProgramAccess(id);
    gl::ShaderProgramID tempShaderStartID = {mResourceTracker.getMaxShaderPrograms()};
    GenerateLinkedProgram(context, context->getState(), &mResourceTracker, &outCalls, program, id,
                          tempShaderStartID, getProgramSources(id));
}

void FrameCaptureShared::captureCustomMapBufferFromContext(const gl::Context *context,
                                                           const char *entryPointName,
                                                           CallCapture &call,
                                                           std::vector<CallCapture> &callsOut)
{
    gl::BufferBinding binding =
        call.params.getParam("targetPacked", ParamType::TBufferBinding, 0).value.BufferBindingVal;
    gl::Buffer *buffer = context->getState().getTargetBuffer(binding);

    if (call.entryPoint == EntryPoint::GLMapBufferRange ||
        call.entryPoint == EntryPoint::GLMapBufferRangeEXT)
    {
        GLintptr offset = call.params.getParam("offset", ParamType::TGLintptr, 1).value.GLintptrVal;
        GLsizeiptr length =
            call.params.getParam("length", ParamType::TGLsizeiptr, 2).value.GLsizeiptrVal;
        GLbitfield access =
            call.params.getParam("access", ParamType::TGLbitfield, 3).value.GLbitfieldVal;

        trackBufferMapping(context, &call, buffer->id(), buffer, offset, length,
                           access & GL_MAP_WRITE_BIT, access & GL_MAP_COHERENT_BIT_EXT,
                           access & GL_MAP_PERSISTENT_BIT_EXT);
    }
    else
    {
        ASSERT(call.entryPoint == EntryPoint::GLMapBufferOES);
        GLenum access = call.params.getParam("access", ParamType::TGLenum, 1).value.GLenumVal;
        bool writeAccess =
            (access == GL_WRITE_ONLY_OES || access == GL_WRITE_ONLY || access == GL_READ_WRITE);
        trackBufferMapping(context, &call, buffer->id(), buffer, 0,
                           static_cast<GLsizeiptr>(buffer->getSize()), writeAccess, false, false);
    }

    CaptureCustomMapBuffer(entryPointName, call, callsOut, buffer->id());
}

// Drop wait/destroy calls on sync IDs for which the creation was never seen by capture, as when
// AR apps import sync objects from the camera process. If the sync object is not recognized,
// skip the Sync call and add a trace comment instead
bool FilterImportedSyncs(bool captureActive,
                         GLuint syncID,
                         bool emitted,
                         const char *api,
                         const CallCapture &inCall,
                         std::vector<CallCapture> &outCalls)
{
    if (!captureActive || syncID == 0 || emitted)
    {
        return false;
    }
    std::stringstream msg;
    msg << "Dropping " << GetEntryPointName(inCall.entryPoint) << " on possibly external " << api
        << " sync ID " << syncID;
    AddComment(&outCalls, msg.str());
    WARN() << msg.str();
    return true;
}

void FrameCaptureShared::maybeOverrideEntryPoint(const gl::Context *context,
                                                 CallCapture &inCall,
                                                 std::vector<CallCapture> &outCalls)
{
    switch (inCall.entryPoint)
    {
        case EntryPoint::GLCopyImageSubData:
        case EntryPoint::GLCopyImageSubDataEXT:
        case EntryPoint::GLCopyImageSubDataOES:
        {
            // We must look at the src and dst target types to determine which remap table to use
            updateCopyImageSubData(inCall);
            outCalls.emplace_back(std::move(inCall));
            break;
        }
        case EntryPoint::GLProgramBinary:
        case EntryPoint::GLProgramBinaryOES:
        {
            // Binary formats are not portable at all, so replace the calls with full linking
            // sequence
            overrideProgramBinary(context, inCall, outCalls);
            break;
        }
        case EntryPoint::GLUniformBlockBinding:
        {
            CaptureCustomUniformBlockBinding(inCall, outCalls);
            break;
        }
        case EntryPoint::GLMapBufferRange:
        {
            captureCustomMapBufferFromContext(context, "MapBufferRange", inCall, outCalls);
            break;
        }
        case EntryPoint::GLMapBufferRangeEXT:
        {
            captureCustomMapBufferFromContext(context, "MapBufferRangeEXT", inCall, outCalls);
            break;
        }
        case EntryPoint::GLMapBufferOES:
        {
            captureCustomMapBufferFromContext(context, "MapBufferOES", inCall, outCalls);
            break;
        }
        case EntryPoint::GLCreateShader:
        {
            CaptureCustomShaderProgram("CreateShader", inCall, outCalls);
            break;
        }
        case EntryPoint::GLCreateProgram:
        {
            CaptureCustomShaderProgram("CreateProgram", inCall, outCalls);
            break;
        }
        case EntryPoint::GLCreateShaderProgramv:
        {
            CaptureCustomShaderProgram("CreateShaderProgramv", inCall, outCalls);
            break;
        }
        case EntryPoint::GLFenceSync:
        {
            CaptureCustomFenceSync(inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreateImage:
        {
            const egl::Image *eglImage = GetImageFromParam(context, inCall.params.getReturnValue());
            CaptureCustomCreateEGLImage(context, "CreateEGLImage", eglImage->getWidth(),
                                        eglImage->getHeight(), inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreateImageKHR:
        {
            const egl::Image *eglImage = GetImageFromParam(context, inCall.params.getReturnValue());
            CaptureCustomCreateEGLImage(context, "CreateEGLImageKHR", eglImage->getWidth(),
                                        eglImage->getHeight(), inCall, outCalls);
            break;
        }
        case EntryPoint::EGLDestroyImage:
        {
            CaptureCustomDestroyEGLImage("DestroyEGLImage", inCall, outCalls);
            break;
        }
        case EntryPoint::EGLDestroyImageKHR:
        {
            CaptureCustomDestroyEGLImage("DestroyEGLImageKHR", inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreateSync:
        {
            CaptureCustomCreateEGLSync("CreateEGLSync", inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreateSyncKHR:
        {
            CaptureCustomCreateEGLSync("CreateEGLSyncKHR", inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreatePbufferSurface:
        {
            CaptureCustomCreatePbufferSurface(inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreateNativeClientBufferANDROID:
        {
            CaptureCustomCreateNativeClientbuffer(inCall, outCalls);
            break;
        }
        case EntryPoint::GLWaitSync:
        case EntryPoint::GLDeleteSync:
        {
            gl::SyncID syncID =
                inCall.params.getParam("syncPacked", ParamType::TSyncID, 0).value.SyncIDVal;
            if (!FilterImportedSyncs(isCaptureActive(), syncID.value, isGLSyncEmitted(syncID), "GL",
                                     inCall, outCalls))
            {
                outCalls.emplace_back(std::move(inCall));
            }
            break;
        }
        case EntryPoint::GLClientWaitSync:
        {
            gl::SyncID syncID =
                inCall.params.getParam("syncPacked", ParamType::TSyncID, 0).value.SyncIDVal;
            if (!FilterImportedSyncs(isCaptureActive(), syncID.value, isGLSyncEmitted(syncID), "GL",
                                     inCall, outCalls))
            {
                CaptureCustomClientWaitSync(inCall, outCalls);
            }
            break;
        }
        case EntryPoint::EGLWaitSync:
        case EntryPoint::EGLWaitSyncKHR:
        case EntryPoint::EGLClientWaitSync:
        case EntryPoint::EGLClientWaitSyncKHR:
        case EntryPoint::EGLDestroySync:
        case EntryPoint::EGLDestroySyncKHR:
        {
            egl::SyncID syncID =
                inCall.params.getParam("syncPacked", ParamType::Tegl_SyncID, 1).value.egl_SyncIDVal;
            if (!FilterImportedSyncs(isCaptureActive(), syncID.value, isEGLSyncEmitted(syncID),
                                     "EGL", inCall, outCalls))
            {
                outCalls.emplace_back(std::move(inCall));
            }
            break;
        }
        default:
        {
            // Pass the single call through
            outCalls.emplace_back(std::move(inCall));
            break;
        }
    }
}

// Set flag if call is a syncpoint. Syncpoints are created in support of
// context call grouping in which calls from side-contexts are group together
// to minimize context transitions. Sidecontext calls are typically replayed
// first in a frame followed by calls in the main context. However, some calls
// affect global state and need to occur in their originally recorded
// position. An example of this would be if in a side-context a shader was
// deleted, but in the original trace the delete occurred in the middle of the
// frame. Replaying all of the side-context calls before the main context calls
// could result in a race condition for the shader's lifetime.
// If any of the entrypoints below occurs in a side context:
//   - the side-context replay will be interrupted
//   - the context will be switched to the main context to replay those calls
//   - at the point in the call stream where the side-context call originally
//     appeared is reached, the context will switch back to the side-context
//     and those calls will be replayed until the side-context is complete or
//     until another syncpoint is found.
// The intent is to ensure entrypoints that affect global state occur in their
// proper order.
void FrameCaptureShared::maybeSetSyncPoint(CallCapture &inCall)
{
    switch (inCall.entryPoint)
    {
        case EntryPoint::GLFenceSync:
        case EntryPoint::GLCreateShader:
        case EntryPoint::GLCreateProgram:
        case EntryPoint::GLCreateShaderProgramv:
        case EntryPoint::GLAttachShader:
        case EntryPoint::GLDeleteShader:
        case EntryPoint::GLDeleteProgram:
        case EntryPoint::GLLinkProgram:
        case EntryPoint::GLWaitSync:
        case EntryPoint::GLClientWaitSync:
        case EntryPoint::GLDeleteSync:
        case EntryPoint::EGLCreateSync:
        case EntryPoint::EGLCreateSyncKHR:
        case EntryPoint::EGLWaitSync:
        case EntryPoint::EGLWaitSyncKHR:
        case EntryPoint::EGLClientWaitSync:
        case EntryPoint::EGLClientWaitSyncKHR:
        case EntryPoint::EGLDestroySync:
        case EntryPoint::EGLDestroySyncKHR:
        case EntryPoint::GLEGLImageTargetTexture2DOES:
        {
            inCall.isSyncPoint = true;
            break;
        }
        default:
        {
            break;
        }
    }
}

void FrameCaptureShared::maybeCaptureCoherentBuffers(const gl::Context *context)
{
    if (!isCaptureActive())
    {
        return;
    }

    std::lock_guard<angle::SimpleMutex> lock(mCoherentBufferTracker.mMutex);

    for (const auto &pair : mCoherentBufferTracker.mBuffers)
    {
        gl::BufferID id = {pair.first};
        if (mCoherentBufferTracker.isDirty(id))
        {
            captureCoherentBufferSnapshot(context, id);
        }
    }
}

void FrameCaptureShared::maybeCaptureDrawArraysClientData(const gl::Context *context,
                                                          CallCapture &call,
                                                          size_t instanceCount)
{
    if (!context->hasAnyActiveClientAttrib())
    {
        return;
    }

    // Get counts from paramBuffer.
    GLint firstVertex =
        call.params.getParamFlexName("first", "start", ParamType::TGLint, 1).value.GLintVal;
    GLsizei drawCount = call.params.getParam("count", ParamType::TGLsizei, 2).value.GLsizeiVal;
    captureClientArraySnapshot(context, firstVertex + drawCount, instanceCount);
}

void FrameCaptureShared::maybeCaptureDrawElementsClientData(const gl::Context *context,
                                                            CallCapture &call,
                                                            size_t instanceCount)
{
    if (!context->hasAnyActiveClientAttrib())
    {
        return;
    }

    // if the count is zero then the index evaluation is not valid and we wouldn't be drawing
    // anything anyway, so skip capturing
    GLsizei count = call.params.getParam("count", ParamType::TGLsizei, 1).value.GLsizeiVal;
    if (count == 0)
    {
        return;
    }

    gl::DrawElementsType drawElementsType =
        call.params.getParam("typePacked", ParamType::TDrawElementsType, 2)
            .value.DrawElementsTypeVal;
    const void *indices =
        call.params.getParam("indices", ParamType::TvoidConstPointer, 3).value.voidConstPointerVal;

    gl::IndexRange indexRange;

    bool restart = context->getState().isPrimitiveRestartEnabled();

    gl::Buffer *elementArrayBuffer = context->getState().getVertexArray()->getElementArrayBuffer();
    if (elementArrayBuffer)
    {
        size_t offset = reinterpret_cast<size_t>(indices);
        (void)elementArrayBuffer->getIndexRange(context, drawElementsType, offset, count, restart,
                                                &indexRange);
    }
    else
    {
        ASSERT(indices);
        indexRange = gl::ComputeIndexRange(drawElementsType, indices, count, restart);
    }

    // index starts from 0
    captureClientArraySnapshot(context, indexRange.end() + 1, instanceCount);
}

template <typename AttribT, typename FactoryT>
void CreateEGLImagePreCallUpdate(const CallCapture &call,
                                 ResourceTracker &resourceTracker,
                                 ParamType paramType,
                                 FactoryT factory)
{
    EGLImage image            = call.params.getReturnValue().value.EGLImageVal;
    const ParamCapture &param = call.params.getParam("attrib_list", paramType, 4);
    const AttribT *attribs =
        param.data.empty() ? nullptr : reinterpret_cast<const AttribT *>(param.data[0].data());
    egl::AttributeMap attributeMap = factory(attribs);
    attributeMap.initializeWithoutValidation();
    resourceTracker.getImageToAttribTable().insert(
        std::pair<EGLImage, egl::AttributeMap>(image, attributeMap));
}

void FrameCaptureShared::maybeCapturePreCallUpdates(
    const gl::Context *context,
    CallCapture &call,
    std::vector<CallCapture> *shareGroupSetupCalls,
    ResourceIDToSetupCallsMap *resourceIDToSetupCalls)
{
    switch (call.entryPoint)
    {
        case EntryPoint::GLVertexAttribPointer:
        case EntryPoint::GLVertexPointer:
        case EntryPoint::GLColorPointer:
        case EntryPoint::GLTexCoordPointer:
        case EntryPoint::GLNormalPointer:
        case EntryPoint::GLPointSizePointerOES:
        {
            // Get array location
            GLuint index = 0;
            if (call.entryPoint == EntryPoint::GLVertexAttribPointer)
            {
                index = call.params.getParam("index", ParamType::TGLuint, 0).value.GLuintVal;
            }
            else
            {
                gl::ClientVertexArrayType type;
                switch (call.entryPoint)
                {
                    case EntryPoint::GLVertexPointer:
                        type = gl::ClientVertexArrayType::Vertex;
                        break;
                    case EntryPoint::GLColorPointer:
                        type = gl::ClientVertexArrayType::Color;
                        break;
                    case EntryPoint::GLTexCoordPointer:
                        type = gl::ClientVertexArrayType::TextureCoord;
                        break;
                    case EntryPoint::GLNormalPointer:
                        type = gl::ClientVertexArrayType::Normal;
                        break;
                    case EntryPoint::GLPointSizePointerOES:
                        type = gl::ClientVertexArrayType::PointSize;
                        break;
                    default:
                        UNREACHABLE();
                        type = gl::ClientVertexArrayType::InvalidEnum;
                }
                index = gl::GLES1Renderer::VertexArrayIndex(type, context->getState().gles1());
            }

            if (call.params.hasClientArrayData())
            {
                mClientVertexArrayData[index] =
                    call.params.getClientArrayPointerParameter().value.voidConstPointerVal;
            }
            else
            {
                mClientVertexArrayData[index] = nullptr;
            }
            break;
        }

        case EntryPoint::GLGenFramebuffers:
        case EntryPoint::GLGenFramebuffersOES:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::FramebufferID *framebufferIDs =
                call.params.getParam("framebuffersPacked", ParamType::TFramebufferIDPointer, 1)
                    .value.FramebufferIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                handleGennedResource(context, framebufferIDs[i]);
            }
            break;
        }

        case EntryPoint::GLBindFramebuffer:
        case EntryPoint::GLBindFramebufferOES:
            maybeGenResourceOnBind<gl::FramebufferID>(context, call);
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLBindFramebuffer);
            }
            break;

        case EntryPoint::GLGenRenderbuffers:
        case EntryPoint::GLGenRenderbuffersOES:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::RenderbufferID *renderbufferIDs =
                call.params.getParam("renderbuffersPacked", ParamType::TRenderbufferIDPointer, 1)
                    .value.RenderbufferIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                handleGennedResource(context, renderbufferIDs[i]);
            }
            break;
        }

        case EntryPoint::GLBindRenderbuffer:
        case EntryPoint::GLBindRenderbufferOES:
            maybeGenResourceOnBind<gl::RenderbufferID>(context, call);
            break;

        case EntryPoint::GLDeleteRenderbuffers:
        case EntryPoint::GLDeleteRenderbuffersOES:
        {
            // Look up how many renderbuffers are being deleted
            GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;

            // Look up the pointer to list of renderbuffers
            const gl::RenderbufferID *renderbufferIDs =
                call.params
                    .getParam("renderbuffersPacked", ParamType::TRenderbufferIDConstPointer, 1)
                    .value.RenderbufferIDConstPointerVal;

            // For each renderbuffer listed for deletion
            for (int32_t i = 0; i < n; ++i)
            {
                // If we're capturing, track what renderbuffers have been deleted
                handleDeletedResource(context, renderbufferIDs[i]);
            }
            break;
        }

        case EntryPoint::GLGenTextures:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::TextureID *textureIDs =
                call.params.getParam("texturesPacked", ParamType::TTextureIDPointer, 1)
                    .value.TextureIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                // If we're capturing, track what new textures have been genned
                handleGennedResource(context, textureIDs[i]);
            }
            break;
        }

        case EntryPoint::GLBindTexture:
            maybeGenResourceOnBind<gl::TextureID>(context, call);
            if (isCaptureActive())
            {
                gl::TextureType target =
                    call.params.getParam("targetPacked", ParamType::TTextureType, 0)
                        .value.TextureTypeVal;
                context->getFrameCapture()->getStateResetHelper().setTextureBindingDirty(
                    context->getState().getActiveSampler(), target);
            }
            break;

        case EntryPoint::GLDeleteBuffers:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::BufferID *bufferIDs =
                call.params.getParam("buffersPacked", ParamType::TBufferIDConstPointer, 1)
                    .value.BufferIDConstPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                // For each buffer being deleted, check our backup of data and remove it
                const auto &bufferDataInfo = mBufferDataMap.find(bufferIDs[i]);
                if (bufferDataInfo != mBufferDataMap.end())
                {
                    mBufferDataMap.erase(bufferDataInfo);
                }
                // If we're capturing, track what buffers have been deleted
                handleDeletedResource(context, bufferIDs[i]);
            }
            break;
        }

        case EntryPoint::GLGenBuffers:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::BufferID *bufferIDs =
                call.params.getParam("buffersPacked", ParamType::TBufferIDPointer, 1)
                    .value.BufferIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                handleGennedResource(context, bufferIDs[i]);
            }
            break;
        }

        case EntryPoint::GLBindBuffer:
            maybeGenResourceOnBind<gl::BufferID>(context, call);
            if (isCaptureActive())
            {
                gl::BufferBinding binding =
                    call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
                        .value.BufferBindingVal;

                context->getFrameCapture()->getStateResetHelper().setBufferBindingDirty(binding);
            }
            break;

        case EntryPoint::GLBindBufferBase:
        case EntryPoint::GLBindBufferRange:
            if (isCaptureActive())
            {
                WARN() << "Indexed buffer binding changed during capture, Reset doesn't handle it "
                          "yet.";
            }
            break;

        case EntryPoint::GLDeleteProgramPipelines:
        case EntryPoint::GLDeleteProgramPipelinesEXT:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::ProgramPipelineID *pipelineIDs =
                call.params
                    .getParam("pipelinesPacked", ParamType::TProgramPipelineIDConstPointer, 1)
                    .value.ProgramPipelineIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                handleDeletedResource(context, pipelineIDs[i]);
            }
            break;
        }

        case EntryPoint::GLGenProgramPipelines:
        case EntryPoint::GLGenProgramPipelinesEXT:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::ProgramPipelineID *pipelineIDs =
                call.params.getParam("pipelinesPacked", ParamType::TProgramPipelineIDPointer, 1)
                    .value.ProgramPipelineIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                handleGennedResource(context, pipelineIDs[i]);
            }
            break;
        }

        case EntryPoint::GLDeleteSync:
        {
            gl::SyncID sync =
                call.params.getParam("syncPacked", ParamType::TSyncID, 0).value.SyncIDVal;
            FrameCaptureShared *frameCaptureShared =
                context->getShareGroup()->getFrameCaptureShared();
            // If we're capturing, track which fence sync has been deleted
            if (frameCaptureShared->isCaptureActive())
            {
                mResourceTracker.setDeletedFenceSync(sync);
            }
            break;
        }

        case EntryPoint::GLDrawArrays:
        {
            maybeCaptureDrawArraysClientData(context, call, 1);
            maybeCaptureCoherentBuffers(context);
            break;
        }

        case EntryPoint::GLDrawArraysInstanced:
        case EntryPoint::GLDrawArraysInstancedANGLE:
        case EntryPoint::GLDrawArraysInstancedEXT:
        {
            GLsizei instancecount =
                call.params.getParamFlexName("instancecount", "primcount", ParamType::TGLsizei, 3)
                    .value.GLsizeiVal;

            maybeCaptureDrawArraysClientData(context, call, instancecount);
            maybeCaptureCoherentBuffers(context);
            break;
        }

        case EntryPoint::GLDrawElements:
        {
            maybeCaptureDrawElementsClientData(context, call, 1);
            maybeCaptureCoherentBuffers(context);
            break;
        }

        case EntryPoint::GLDrawElementsInstanced:
        case EntryPoint::GLDrawElementsInstancedANGLE:
        case EntryPoint::GLDrawElementsInstancedEXT:
        {
            GLsizei instancecount =
                call.params.getParamFlexName("instancecount", "primcount", ParamType::TGLsizei, 4)
                    .value.GLsizeiVal;

            maybeCaptureDrawElementsClientData(context, call, instancecount);
            maybeCaptureCoherentBuffers(context);
            break;
        }

        case EntryPoint::GLCreateShaderProgramv:
        {
            // Refresh the cached shader sources.
            // The command CreateShaderProgramv() creates a stand-alone program from an array of
            // null-terminated source code strings for a single shader type, so we need update the
            // Shader and Program sources, similar to GLCompileShader + GLLinkProgram handling.
            gl::ShaderProgramID programID = {call.params.getReturnValue().value.GLuintVal};
            const ParamCapture &paramCapture =
                call.params.getParam("typePacked", ParamType::TShaderType, 0);
            const ParamCapture &lineCount = call.params.getParam("count", ParamType::TGLsizei, 1);
            const ParamCapture &strings =
                call.params.getParam("strings", ParamType::TGLcharConstPointerPointer, 2);

            std::ostringstream sourceString;
            for (int i = 0; i < lineCount.value.GLsizeiVal; ++i)
            {
                sourceString << strings.value.GLcharConstPointerPointerVal[i];
            }

            gl::ShaderType shaderType = paramCapture.value.ShaderTypeVal;
            ProgramSources source;
            source[shaderType] = sourceString.str();
            setProgramSources(programID, source);
            handleGennedResource(context, programID);
            mResourceTracker.setShaderProgramType(programID, ShaderProgramType::ProgramType);
            break;
        }

        case EntryPoint::GLCreateProgram:
        {
            // If we're capturing, track which programs have been created
            gl::ShaderProgramID programID = {call.params.getReturnValue().value.GLuintVal};
            handleGennedResource(context, programID);

            mResourceTracker.setShaderProgramType(programID, ShaderProgramType::ProgramType);
            break;
        }

        case EntryPoint::GLDeleteProgram:
        {
            // If we're capturing, track which programs have been deleted
            const ParamCapture &param =
                call.params.getParam("programPacked", ParamType::TShaderProgramID, 0);
            if (param.value.ShaderProgramIDVal.value == 0)
            {
                break;  // no-op
            }
            handleDeletedResource(context, param.value.ShaderProgramIDVal);

            // If this assert fires, it means a ShaderProgramID has changed from program to shader
            // which is unsupported
            ASSERT(mResourceTracker.getShaderProgramType(param.value.ShaderProgramIDVal) ==
                   ShaderProgramType::ProgramType);

            break;
        }

        case EntryPoint::GLCreateShader:
        {
            // If we're capturing, track which shaders have been created
            gl::ShaderProgramID shaderID = {call.params.getReturnValue().value.GLuintVal};
            handleGennedResource(context, shaderID);

            mResourceTracker.setShaderProgramType(shaderID, ShaderProgramType::ShaderType);
            break;
        }

        case EntryPoint::GLDeleteShader:
        {
            // If we're capturing, track which shaders have been deleted
            const ParamCapture &param =
                call.params.getParam("shaderPacked", ParamType::TShaderProgramID, 0);
            if (param.value.ShaderProgramIDVal.value == 0)
            {
                break;  // no-op
            }
            handleDeletedResource(context, param.value.ShaderProgramIDVal);

            // If this assert fires, it means a ShaderProgramID has changed from shader to program
            // which is unsupported
            ASSERT(mResourceTracker.getShaderProgramType(param.value.ShaderProgramIDVal) ==
                   ShaderProgramType::ShaderType);
            break;
        }

        case EntryPoint::GLCompileShader:
        {
            // Refresh the cached shader sources.
            gl::ShaderProgramID shaderID =
                call.params.getParam("shaderPacked", ParamType::TShaderProgramID, 0)
                    .value.ShaderProgramIDVal;
            const gl::Shader *shader = context->getShaderNoResolveCompile(shaderID);
            // Shaders compiled for ProgramBinary will not have a shader created
            if (shader)
            {
                setShaderSource(shaderID, shader->getSourceString());
            }
            break;
        }

        case EntryPoint::GLLinkProgram:
        {
            // Refresh the cached program sources.
            gl::ShaderProgramID programID =
                call.params.getParam("programPacked", ParamType::TShaderProgramID, 0)
                    .value.ShaderProgramIDVal;
            const gl::Program *program = context->getProgramResolveLink(programID);
            // Programs linked in support of ProgramBinary will not have attached shaders
            if (program->getState().hasAnyAttachedShader())
            {
                setProgramSources(programID, GetAttachedProgramSources(context, program));
            }
            break;
        }

        case EntryPoint::GLDeleteTextures:
        {
            // Free any TextureLevelDataMap entries being tracked for this texture
            // This is to cover the scenario where a texture has been created, its
            // levels cached, then texture deleted and recreated, receiving the same ID

            // Look up how many textures are being deleted
            GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;

            // Look up the pointer to list of textures
            const gl::TextureID *textureIDs =
                call.params.getParam("texturesPacked", ParamType::TTextureIDConstPointer, 1)
                    .value.TextureIDConstPointerVal;

            // For each texture listed for deletion
            for (int32_t i = 0; i < n; ++i)
            {
                // If we're capturing, track what textures have been deleted
                handleDeletedResource(context, textureIDs[i]);
            }
            break;
        }

        case EntryPoint::GLMapBufferOES:
        {
            gl::BufferBinding target =
                call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
                    .value.BufferBindingVal;

            GLbitfield access =
                call.params.getParam("access", ParamType::TGLenum, 1).value.GLenumVal;

            gl::Buffer *buffer = context->getState().getTargetBuffer(target);

            GLintptr offset   = 0;
            GLsizeiptr length = static_cast<GLsizeiptr>(buffer->getSize());

            bool writable =
                access == GL_WRITE_ONLY_OES || access == GL_WRITE_ONLY || access == GL_READ_WRITE;

            FrameCaptureShared *frameCaptureShared =
                context->getShareGroup()->getFrameCaptureShared();
            frameCaptureShared->trackBufferMapping(context, &call, buffer->id(), buffer, offset,
                                                   length, writable, false, false);
            break;
        }

        case EntryPoint::GLUnmapBuffer:
        case EntryPoint::GLUnmapBufferOES:
        {
            // See if we need to capture the buffer contents
            captureMappedBufferSnapshot(context, call);

            // Track that the buffer was unmapped, for use during state reset
            gl::BufferBinding target =
                call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
                    .value.BufferBindingVal;
            gl::Buffer *buffer = context->getState().getTargetBuffer(target);
            mResourceTracker.setBufferUnmapped(context->id(), buffer->id().value);

            // Remove from CoherentBufferTracker
            mCoherentBufferTracker.removeBuffer(buffer->id());
            break;
        }

        case EntryPoint::GLBufferData:
        case EntryPoint::GLBufferSubData:
        {
            gl::BufferBinding target =
                call.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
                    .value.BufferBindingVal;

            gl::Buffer *buffer = context->getState().getTargetBuffer(target);

            // Track that this buffer's contents have been modified
            mResourceTracker.getTrackedResource(context->id(), ResourceIDType::Buffer)
                .setModifiedResource(buffer->id().value);

            // BufferData is equivalent to UnmapBuffer, for what we're tracking.
            // From the ES 3.1 spec in BufferData section:
            //     If any portion of the buffer object is mapped in the current context or any
            //     context current to another thread, it is as though UnmapBuffer (see section
            //     6.3.1) is executed in each such context prior to deleting the existing data
            //     store.
            // Track that the buffer was unmapped, for use during state reset
            mResourceTracker.setBufferUnmapped(context->id(), buffer->id().value);

            break;
        }

        case EntryPoint::GLCopyBufferSubData:
        {
            maybeCaptureCoherentBuffers(context);
            break;
        }
        case EntryPoint::GLFinish:
        {
            // When using shadow memory we might need to synchronize it here.
            if (mCoherentBufferTracker.isShadowMemoryEnabled())
            {
                mCoherentBufferTracker.maybeUpdateShadowMemory();
            }
            break;
        }
        case EntryPoint::GLDeleteFramebuffers:
        case EntryPoint::GLDeleteFramebuffersOES:
        {
            // Look up how many framebuffers are being deleted
            GLsizei n = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;

            // Look up the pointer to list of framebuffers
            const gl::FramebufferID *framebufferIDs =
                call.params.getParam("framebuffersPacked", ParamType::TFramebufferIDConstPointer, 1)
                    .value.FramebufferIDConstPointerVal;

            // For each framebuffer listed for deletion
            for (int32_t i = 0; i < n; ++i)
            {
                // If we're capturing, track what framebuffers have been deleted
                handleDeletedResource(context, framebufferIDs[i]);
            }
            break;
        }

        case EntryPoint::GLUseProgram:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLUseProgram);
            }
            break;
        }

        case EntryPoint::GLGenVertexArrays:
        case EntryPoint::GLGenVertexArraysOES:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::VertexArrayID *arrayIDs =
                call.params.getParam("arraysPacked", ParamType::TVertexArrayIDPointer, 1)
                    .value.VertexArrayIDPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                handleGennedResource(context, arrayIDs[i]);
            }
            break;
        }

        case EntryPoint::GLDeleteVertexArrays:
        case EntryPoint::GLDeleteVertexArraysOES:
        {
            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
            const gl::VertexArrayID *arrayIDs =
                call.params.getParam("arraysPacked", ParamType::TVertexArrayIDConstPointer, 1)
                    .value.VertexArrayIDConstPointerVal;
            for (GLsizei i = 0; i < count; i++)
            {
                // If we're capturing, track which vertex arrays have been deleted
                handleDeletedResource(context, arrayIDs[i]);
            }
            break;
        }

        case EntryPoint::GLBindVertexArray:
        case EntryPoint::GLBindVertexArrayOES:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLBindVertexArray);
            }
            break;
        }
        case EntryPoint::GLBlendFunc:
        case EntryPoint::GLBlendFuncSeparate:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLBlendFuncSeparate);
            }
            break;
        }
        case EntryPoint::GLBlendEquation:
        case EntryPoint::GLBlendEquationSeparate:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLBlendEquationSeparate);
            }
            break;
        }
        case EntryPoint::GLColorMask:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLColorMask);
            }
            break;
        }
        case EntryPoint::GLBlendColor:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLBlendColor);
            }
            break;
        }

        case EntryPoint::GLEGLImageTargetTexture2DOES:
        {
            gl::TextureType target =
                call.params.getParam("targetPacked", ParamType::TTextureType, 0)
                    .value.TextureTypeVal;
            egl::ImageID imageID =
                call.params.getParam("imagePacked", ParamType::TImageID, 1).value.ImageIDVal;
            GLuint textureID            = context->getState().getTargetTexture(target)->getId();
            auto &textureIDToImageTable = mResourceTracker.getTextureIDToImageTable();
            auto existingBinding        = textureIDToImageTable.find(textureID);
            if (isCaptureActive() && existingBinding != textureIDToImageTable.end() &&
                existingBinding->second != imageID)
            {
                mResourceTracker.getExternalImageBindingsToRestore()[context->id()].insert(
                    textureID);
            }
            textureIDToImageTable.insert(std::pair<GLuint, egl::ImageID>(textureID, imageID));
            break;
        }

        case EntryPoint::EGLCreateImage:
        {
            CreateEGLImagePreCallUpdate<EGLAttrib>(call, mResourceTracker,
                                                   ParamType::TEGLAttribPointer,
                                                   egl::AttributeMap::CreateFromAttribArray);
            if (isCaptureActive())
            {
                EGLImage eglImage    = call.params.getReturnValue().value.EGLImageVal;
                egl::ImageID imageID = egl::PackParam<egl::ImageID>(eglImage);
                handleGennedResource(context, imageID);
            }
            break;
        }
        case EntryPoint::EGLCreateImageKHR:
        {
            CreateEGLImagePreCallUpdate<EGLint>(call, mResourceTracker, ParamType::TEGLintPointer,
                                                egl::AttributeMap::CreateFromIntArray);
            if (isCaptureActive())
            {
                EGLImageKHR eglImage = call.params.getReturnValue().value.EGLImageKHRVal;
                egl::ImageID imageID = egl::PackParam<egl::ImageID>(eglImage);
                handleGennedResource(context, imageID);
            }
            break;
        }
        case EntryPoint::EGLDestroyImage:
        case EntryPoint::EGLDestroyImageKHR:
        {
            egl::ImageID eglImageID =
                call.params.getParam("imagePacked", ParamType::TImageID, 1).value.ImageIDVal;

            // Clear any texture->image mappings that involve this image
            for (auto texImageIter = mResourceTracker.getTextureIDToImageTable().begin();
                 texImageIter != mResourceTracker.getTextureIDToImageTable().end();)
            {
                if (texImageIter->second == eglImageID)
                {
                    texImageIter = mResourceTracker.getTextureIDToImageTable().erase(texImageIter);
                }
                else
                {
                    ++texImageIter;
                }
            }

            mResourceTracker.getImageDataMap().erase(eglImageID);

            FrameCaptureShared *frameCaptureShared =
                context->getShareGroup()->getFrameCaptureShared();
            if (frameCaptureShared->isCaptureActive())
            {
                handleDeletedResource(context, eglImageID);
            }
            break;
        }
        case EntryPoint::EGLCreateSync:
        case EntryPoint::EGLCreateSyncKHR:
        {
            egl::SyncID eglSyncID = call.params.getReturnValue().value.egl_SyncIDVal;
            FrameCaptureShared *frameCaptureShared =
                context->getShareGroup()->getFrameCaptureShared();
            // If we're capturing, track which egl sync has been created
            if (frameCaptureShared->isCaptureActive())
            {
                handleGennedResource(context, eglSyncID);
                markEGLSyncEmitted(eglSyncID);
            }
            break;
        }
        case EntryPoint::GLFenceSync:
        {
            gl::SyncID syncID = call.params.getReturnValue().value.SyncIDVal;
            FrameCaptureShared *frameCaptureShared =
                context->getShareGroup()->getFrameCaptureShared();
            if (frameCaptureShared->isCaptureActive())
            {
                markGLSyncEmitted(syncID);
            }
            break;
        }
        case EntryPoint::EGLDestroySync:
        case EntryPoint::EGLDestroySyncKHR:
        {
            egl::SyncID eglSyncID =
                call.params.getParam("syncPacked", ParamType::Tegl_SyncID, 1).value.egl_SyncIDVal;
            FrameCaptureShared *frameCaptureShared =
                context->getShareGroup()->getFrameCaptureShared();
            // If we're capturing, track which EGL sync has been deleted
            if (frameCaptureShared->isCaptureActive())
            {
                handleDeletedResource(context, eglSyncID);
            }
            break;
        }
        case EntryPoint::GLDispatchCompute:
        {
            // When using shadow memory we need to update the real memory here
            if (mCoherentBufferTracker.isShadowMemoryEnabled())
            {
                maybeCaptureCoherentBuffers(context);
            }
            break;
        }
        default:
            break;
    }

    if (IsTextureUpdate(call))
    {
        // If this call modified texture contents, track it for possible reset
        trackTextureUpdate(context, call);
    }

    if (IsFramebufferUpdate(call))
    {
        // If this call modified framebuffer contents, track its drawable attachments for possible
        // update
        trackFramebufferAttachmentUpdate(context, call);
    }

    if (IsImageUpdate(call))
    {
        // If this call modified shader image contents, track it for possible reset
        trackImageUpdate(context, call);
    }

    if (isCaptureActive() && GetDefaultUniformType(call) != DefaultUniformType::None)
    {
        trackDefaultUniformUpdate(context, call);
    }

    if (IsVertexArrayUpdate(call))
    {
        trackVertexArrayUpdate(context, call);
    }

    updateReadBufferSize(call.params.getReadBufferSize());

    std::vector<gl::ShaderProgramID> shaderProgramIDs;
    if (FindResourceIDsInCall<gl::ShaderProgramID>(call, shaderProgramIDs))
    {
        for (gl::ShaderProgramID shaderProgramID : shaderProgramIDs)
        {
            mResourceTracker.onShaderProgramAccess(shaderProgramID);

            if (isCaptureActive())
            {
                // Track that this call referenced a ShaderProgram, setting it active for Setup
                MarkResourceIDActive(ResourceIDType::ShaderProgram, shaderProgramID.value,
                                     shareGroupSetupCalls, resourceIDToSetupCalls);
            }
        }
    }

    std::vector<gl::TextureID> textureIDs;
    if (FindResourceIDsInCall<gl::TextureID>(call, textureIDs))
    {
        for (gl::TextureID textureID : textureIDs)
        {
            if (isCaptureActive())
            {
                // Track that this call referenced a Texture, setting it active for Setup
                MarkResourceIDActive(ResourceIDType::Texture, textureID.value, shareGroupSetupCalls,
                                     resourceIDToSetupCalls);
            }
        }
    }
}

template <typename ParamValueType>
void FrameCaptureShared::maybeGenResourceOnBind(const gl::Context *context, CallCapture &call)
{
    const char *paramName     = ParamValueTrait<ParamValueType>::name;
    const ParamType paramType = ParamValueTrait<ParamValueType>::typeID;

    const ParamCapture &param = call.params.getParam(paramName, paramType, 1);
    const ParamValueType id   = AccessParamValue<ParamValueType>(paramType, param.value);

    // Don't inject the default resource or resources that are already generated
    if (id.value != 0 && !resourceIsGenerated(context, id))
    {
        handleGennedResource(context, id);

        ResourceIDType resourceIDType = GetResourceIDTypeFromParamType(param.type);
        const char *resourceName      = GetResourceIDTypeName(resourceIDType);

        std::stringstream updateFuncNameStr;
        updateFuncNameStr << "Set" << resourceName << "ID";
        ParamBuffer params;
        if (IsTrackedPerContext(resourceIDType))
        {
            // TODO (https://issuetracker.google.com/169868803) The '2' version can be removed after
            // all context-local objects are tracked per-context
            updateFuncNameStr << "2";
            params.addValueParam("contextID", ParamType::TGLuint, context->id().value);
        }
        std::string updateFuncName = updateFuncNameStr.str();
        params.addValueParam("id", ParamType::TGLuint, id.value);
        mFrameCalls.emplace_back(updateFuncName, std::move(params));
    }
}

void FrameCaptureShared::updateResourceCountsFromParamCapture(const ParamCapture &param,
                                                              ResourceIDType idType)
{
    if (idType != ResourceIDType::InvalidEnum)
    {
        mHasResourceType.set(idType);

        // Lambda to update the max accessed resource if ID was valid
        auto updateMaxAccessedID = [&](GLuint id) -> void {
            // We could check each ID using calls like isHandleGenerated or Context::isTexture,
            // but let's keep it simple (and fast) for now.
            constexpr unsigned int kMaxTrackedResourceID = 1000000;
            if (id >= kMaxTrackedResourceID)
            {
                INFO() << "Not tracking potentially invalid resourceID (" << id << ") for idType "
                       << GetResourceIDTypeName(idType);
                return;
            }
            mMaxAccessedResourceIDs[idType] = std::max(mMaxAccessedResourceIDs[idType], id);
        };

        // Capture resource IDs for non-pointer types.
        if (strcmp(ParamTypeToString(param.type), "GLuint") == 0)
        {
            updateMaxAccessedID(param.value.GLuintVal);
        }
        // Capture resource IDs for pointer types.
        if (strstr(ParamTypeToString(param.type), "GLuint *") != nullptr)
        {
            if (param.data.size() == 1u)
            {
                const GLuint *dataPtr = reinterpret_cast<const GLuint *>(param.data[0].data());
                size_t numHandles     = param.data[0].size() / sizeof(GLuint);
                for (size_t handleIndex = 0; handleIndex < numHandles; ++handleIndex)
                {
                    updateMaxAccessedID(dataPtr[handleIndex]);
                }
            }
        }
        if (idType == ResourceIDType::Sync)
        {
            updateMaxAccessedID(param.value.GLuintVal);
        }
    }
}

void FrameCaptureShared::updateResourceCountsFromCallCapture(const CallCapture &call)
{

    for (const ParamCapture &param : call.params.getParamCaptures())
    {
        ResourceIDType idType = GetResourceIDTypeFromParamType(param.type);
        updateResourceCountsFromParamCapture(param, idType);
    }

    // Update resource IDs in the return value. Return values types are not stored as resource IDs,
    // but instead are stored as GLuints. Therefore we need to explicitly label the resource ID type
    // when we call update. Currently only shader and program creation are explicitly tracked.
    switch (call.entryPoint)
    {
        case EntryPoint::GLCreateShader:
        case EntryPoint::GLCreateProgram:
            updateResourceCountsFromParamCapture(call.params.getReturnValue(),
                                                 ResourceIDType::ShaderProgram);
            break;

        case EntryPoint::GLFenceSync:
            updateResourceCountsFromParamCapture(call.params.getReturnValue(),
                                                 ResourceIDType::Sync);
            break;
        case EntryPoint::EGLCreateSync:
        case EntryPoint::EGLCreateSyncKHR:
            updateResourceCountsFromParamCapture(call.params.getReturnValue(),
                                                 ResourceIDType::egl_Sync);
            break;
        default:
            break;
    }
}

void FrameCaptureShared::captureCall(gl::Context *context, CallCapture &&inCall, bool isCallValid)
{
    if (SkipCall(inCall))
    {
        return;
    }

    if (isCallValid)
    {
        // Save the call's contextID
        inCall.contextID = context->id();

        // Update resource counts before we override entry points with custom calls.
        updateResourceCountsFromCallCapture(inCall);

        size_t j = mFrameCalls.size();

        maybeSetSyncPoint(inCall);
        std::vector<CallCapture> outCalls;
        maybeOverrideEntryPoint(context, inCall, outCalls);

        // Need to loop on any new calls we added during override
        for (CallCapture &call : outCalls)
        {
            // During capture, consider all frame calls active
            if (isCaptureActive())
            {
                call.isActive = true;
            }

            maybeCapturePreCallUpdates(context, call, &mShareGroupSetupCalls,
                                       &mResourceIDToSetupCalls);
            mFrameCalls.emplace_back(std::move(call));
            maybeCapturePostCallUpdates(context);
        }

        // Tag all 'added' commands with this context
        for (size_t k = j; k < mFrameCalls.size(); k++)
        {
            mFrameCalls[k].contextID = context->id();
        }

        // Evaluate the validation expression to determine if we insert a validation checkpoint.
        // This lets the user pick a subset of calls to check instead of checking every call.
        if (mValidateSerializedState && !mValidationExpression.empty())
        {
            // Example substitution for frame #2, call #110:
            // Before: (call == 2) && (frame >= 100) && (frame <= 120) && ((frame % 10) == 0)
            // After:  (2 == 2) && (110 >= 100) && (110 <= 120) && ((110 % 10) == 0)
            // Evaluates to 1.0.
            std::string expression = mValidationExpression;

            angle::ReplaceAllSubstrings(&expression, "frame", std::to_string(mFrameIndex));
            angle::ReplaceAllSubstrings(&expression, "call", std::to_string(mFrameCalls.size()));

            double result = ceval_result(expression);
            if (result > 0)
            {
                CaptureValidateSerializedState(context, &mFrameCalls);
            }
        }
    }
    else
    {
        const int maxInvalidCallLogs = 3;
        size_t &callCount = isCaptureActive() ? mInvalidCallCountsActive[inCall.entryPoint]
                                              : mInvalidCallCountsInactive[inCall.entryPoint];
        callCount++;
        if (callCount <= maxInvalidCallLogs)
        {
            std::ostringstream msg;
            msg << "FrameCapture (capture " << (isCaptureActive() ? "active" : "inactive")
                << "): Not capturing invalid call to " << GetEntryPointName(inCall.entryPoint);
            if (callCount == maxInvalidCallLogs)
            {
                msg << " (will no longer repeat for this entry point)";
            }
            INFO() << msg.str();
        }

        std::stringstream skipCall;
        skipCall << "Skipping invalid call to " << GetEntryPointName(inCall.entryPoint)
                 << " with error: "
                 << gl::GLenumToString(gl::GLESEnum::ErrorCode, context->getErrorForCapture());
        AddComment(&mFrameCalls, skipCall.str());
    }
}

void FrameCaptureShared::maybeCapturePostCallUpdates(const gl::Context *context)
{
    // Process resource ID updates.
    if (isCaptureActive())
    {
        MaybeCaptureUpdateResourceIDs(context, &mResourceTracker, &mFrameCalls);
    }

    CallCapture &lastCall = mFrameCalls.back();
    switch (lastCall.entryPoint)
    {
        case EntryPoint::GLCreateShaderProgramv:
        {
            gl::ShaderProgramID programId;
            programId.value            = lastCall.params.getReturnValue().value.GLuintVal;
            const gl::Program *program = context->getProgramResolveLink(programId);
            CaptureUpdateUniformLocations(program, &mFrameCalls);
            CaptureUpdateUniformBlockIndexes(program, &mFrameCalls);
            break;
        }
        case EntryPoint::GLLinkProgram:
        {
            const ParamCapture &param =
                lastCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0);
            const gl::Program *program =
                context->getProgramResolveLink(param.value.ShaderProgramIDVal);
            CaptureUpdateUniformLocations(program, &mFrameCalls);
            CaptureUpdateUniformBlockIndexes(program, &mFrameCalls);
            break;
        }
        case EntryPoint::GLEGLImageTargetTexture2DOES:
        {
            gl::TextureType target =
                lastCall.params.getParam("targetPacked", ParamType::TTextureType, 0)
                    .value.TextureTypeVal;
            egl::ImageID imageID =
                lastCall.params.getParam("imagePacked", ParamType::TImageID, 1).value.ImageIDVal;

            const egl::Image *eglImage = context->getDisplay()->getImage(imageID);
            if (!eglImage)
            {
                break;
            }

            size_t width  = eglImage->getWidth();
            size_t height = eglImage->getHeight();

            // Try to read back AHB contents. External textures are normally unreadable in
            // GLES but the ANGLE Vulkan backend supports this. If unsupported, output
            // UpdateEGLImageData(..., nullptr) which will then default to a fallback green
            // placeholder texture.
            bool imageDataCaptured = false;
            gl::Texture *texture   = context->getState().getTargetTexture(target);
            if (texture && context->getExtensions().getImageANGLE)
            {
                std::vector<uint8_t> imagePixels(width * height * 4);
                gl::PixelPackState packState;
                packState.alignment = 1;
                if (texture->getTexImage(
                        context, packState, nullptr, gl::NonCubeTextureTypeToTarget(target), 0,
                        GL_RGBA, GL_UNSIGNED_BYTE, imagePixels.data()) == angle::Result::Continue)
                {
                    mResourceTracker.getImageDataMap()[imageID] = std::move(imagePixels);
                    imageDataCaptured                           = true;
                }
            }

            ParamBuffer params;
            params.addValueParam("imageID", ParamType::TGLuint, imageID.value);
            params.addValueParam("width", ParamType::TGLsizei, static_cast<GLsizei>(width));
            params.addValueParam("height", ParamType::TGLsizei, static_cast<GLsizei>(height));

            ParamCapture pixelsParam("pixels", ParamType::TvoidConstPointer);
            if (imageDataCaptured)
            {
                auto &storedImagePixels               = mResourceTracker.getImageDataMap()[imageID];
                pixelsParam.value.voidConstPointerVal = storedImagePixels.data();
                pixelsParam.data.push_back(storedImagePixels);
            }
            else
            {
                pixelsParam.value.voidConstPointerVal = nullptr;
            }
            params.addParam(std::move(pixelsParam));

            // Insert UpdateEGLImageData so the EGLImage and data are valid for the
            // glEGLImageTargetTexture2DOES() bind call
            mFrameCalls.emplace(mFrameCalls.end() - 1, "UpdateEGLImageData", std::move(params));
            break;
        }
        case EntryPoint::GLUseProgram:
            CaptureUpdateCurrentProgram(lastCall, 0, &mFrameCalls);
            break;
        case EntryPoint::GLActiveShaderProgram:
            CaptureUpdateCurrentProgram(lastCall, 1, &mFrameCalls);
            break;
        case EntryPoint::GLDeleteProgram:
        {
            const ParamCapture &param =
                lastCall.params.getParam("programPacked", ParamType::TShaderProgramID, 0);
            if (param.value.ShaderProgramIDVal.value == 0)
            {
                break;  // no-op
            }
            CaptureDeleteUniformLocations(param.value.ShaderProgramIDVal, &mFrameCalls);
            break;
        }
        case EntryPoint::GLShaderSource:
        {
            lastCall.params.setValueParamAtIndex("count", ParamType::TGLsizei, 1, 1);

            ParamCapture &paramLength =
                lastCall.params.getParam("length", ParamType::TGLintConstPointer, 3);
            paramLength.data.resize(1);
            // Set the length parameter to {-1} to signal that the actual string length
            // is to be used. Since we store the parameter blob as an array of four uint8_t
            // values, we have to pass the binary equivalent of -1.
            paramLength.data[0] = {0xff, 0xff, 0xff, 0xff};
            break;
        }
        case EntryPoint::GLBufferData:
        case EntryPoint::GLBufferSubData:
        {
            // When using shadow memory we need to update it from real memory here
            if (mCoherentBufferTracker.isShadowMemoryEnabled())
            {
                gl::BufferBinding target =
                    lastCall.params.getParam("targetPacked", ParamType::TBufferBinding, 0)
                        .value.BufferBindingVal;

                gl::Buffer *buffer = context->getState().getTargetBuffer(target);
                if (mCoherentBufferTracker.haveBuffer(buffer->id()))
                {
                    std::shared_ptr<CoherentBuffer> cb =
                        mCoherentBufferTracker.mBuffers[buffer->id().value];
                    cb->removeProtection(PageSharingType::NoneShared);
                    cb->updateShadowMemory();
                    cb->protectAll();
                }
            }
            break;
        }

        case EntryPoint::GLCopyBufferSubData:
        {
            // When using shadow memory, we need to mark the buffer shadowDirty bit to true
            // so it will be synchronized with real memory on the next glFinish call.
            if (mCoherentBufferTracker.isShadowMemoryEnabled())
            {
                gl::BufferBinding target =
                    lastCall.params.getParam("writeTargetPacked", ParamType::TBufferBinding, 1)
                        .value.BufferBindingVal;

                gl::Buffer *buffer = context->getState().getTargetBuffer(target);
                if (mCoherentBufferTracker.haveBuffer(buffer->id()))
                {
                    std::shared_ptr<CoherentBuffer> cb =
                        mCoherentBufferTracker.mBuffers[buffer->id().value];
                    // This needs to be synced on glFinish
                    cb->markShadowDirty();
                }
            }
            break;
        }
        case EntryPoint::GLDispatchCompute:
        {
            // When using shadow memory, we need to mark all buffer's shadowDirty bit to true
            // so they will be synchronized with real memory on the next glFinish call.
            if (mCoherentBufferTracker.isShadowMemoryEnabled())
            {
                mCoherentBufferTracker.markAllShadowDirty();
            }
            break;
        }
        case EntryPoint::GLVertexAttribPointer:
        case EntryPoint::GLVertexAttribIPointer:
        case EntryPoint::GLVertexPointer:
        case EntryPoint::GLNormalPointer:
        case EntryPoint::GLColorPointer:
        case EntryPoint::GLPointSizePointerOES:
        case EntryPoint::GLTexCoordPointer:
        {
            if (lastCall.params.hasClientArrayData())
            {
                // The last call's index is kept so the call's pointer and offset can be updated if
                // its corresponding attribute is merged into another attribute later.
                const size_t currentFrameCallsLastIndex = mFrameCalls.size() - 1;
                mClientVertexArrayCallIndices.push_back(currentFrameCallsLastIndex);
                mClientVertexArrayDirtyAttribMask.set(
                    lastCall.params.getClientArrayPointerParameter().arrayClientPointerIndex);
            }
            break;
        }
        default:
            break;
    }
}

void FrameCaptureShared::captureClientArraySnapshot(const gl::Context *context,
                                                    size_t vertexCount,
                                                    size_t instanceCount)
{
    if (vertexCount == 0)
    {
        // Nothing to capture
        return;
    }

    // Capture client array data. If the address ranges for the vertex attribute pointers overlap,
    // they should use a single memory space with different offsets.
    MergedAttribRanges mergedAddrRanges;
    gl::AttribArray<size_t> mergedIndexMap;

    // For draw time, the data active client attributes should always be copied, even if there is no
    // new call in the beginning of the frame to set the attribute pointer.
    gl::AttributesMask clientVADirtyAndActiveAttribsMask =
        mClientVertexArrayDirtyAttribMask | context->getActiveClientAttribsMask();

    // If any updated attribute since the beginning or the last draw call is currently not using a
    // client address (at draw time), there is no need for merging it.
    for (size_t attribIndex : clientVADirtyAndActiveAttribsMask)
    {
        if (mClientVertexArrayData[attribIndex] == nullptr)
        {
            clientVADirtyAndActiveAttribsMask.set(attribIndex, 0);
        }
    }

    // Merge attribute pointers at draw if possible.
    const gl::VertexArray *vao = context->getState().getVertexArray();
    MaybeMergeClientAttributes(vao, clientVADirtyAndActiveAttribsMask, mClientVertexArrayData,
                               &mFrameCalls, mClientVertexArrayCallIndices, true, vertexCount,
                               instanceCount, mergedAddrRanges, mergedIndexMap);

    // Capture the data used by the active vertex attribute pointers. So a merged attribute index is
    // marked as active if at least one attribute merged into it is active. This ensures that only
    // the data necessary for the draw is copied.
    gl::AttributesMask activeMergedAttrMask;
    for (size_t attribIndex : clientVADirtyAndActiveAttribsMask)
    {
        if (context->getActiveClientAttribsMask().test(attribIndex))
        {
            activeMergedAttrMask.set(mergedIndexMap[attribIndex]);
        }
    }
    for (size_t attribIndex : activeMergedAttrMask)
    {
        size_t bytesToCapture =
            mergedAddrRanges.endAddr[attribIndex] - mergedAddrRanges.startAddr[attribIndex];
        CaptureUpdateClientArrayPointer(
            static_cast<uint32_t>(attribIndex),
            reinterpret_cast<const void *>(mergedAddrRanges.startAddr[attribIndex]), bytesToCapture,
            &mFrameCalls);
        mClientArraySizes[attribIndex] = std::max(mClientArraySizes[attribIndex], bytesToCapture);
    }

    // Clear the vertex attribute pointer calls after the merge processing is finished.
    mClientVertexArrayCallIndices.clear();
    mClientVertexArrayDirtyAttribMask.reset();
}

void FrameCaptureShared::captureCoherentBufferSnapshot(const gl::Context *context, gl::BufferID id)
{
    if (!hasBufferData(id))
    {
        // This buffer was not marked writable
        return;
    }

    const gl::State &apiState        = context->getState();
    const gl::BufferManager &buffers = apiState.getBufferManagerForCapture();
    gl::Buffer *buffer               = buffers.getBuffer(id);
    if (!buffer)
    {
        // Could not find buffer binding
        return;
    }

    ASSERT(buffer->isMapped());

    std::shared_ptr<angle::CoherentBuffer> coherentBuffer =
        mCoherentBufferTracker.mBuffers[id.value];

    std::vector<PageRange> dirtyPageRanges = coherentBuffer->getDirtyPageRanges();

    if (mCoherentBufferTracker.isShadowMemoryEnabled() && !dirtyPageRanges.empty())
    {
        coherentBuffer->updateBufferMemory();
    }

    AddressRange wholeRange = coherentBuffer->getRange();

    for (PageRange &pageRange : dirtyPageRanges)
    {
        // Write protect the memory already, so the app is blocked on writing during our capture
        coherentBuffer->protectPageRange(pageRange);

        // Create the parameters to our helper for use during replay
        ParamBuffer dataParamBuffer;

        // Pass in the target buffer ID
        dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);

        // Capture the current buffer data with a binary param
        ParamCapture captureData("source", ParamType::TvoidConstPointer);

        AddressRange dirtyRange = coherentBuffer->getDirtyAddressRange(pageRange);
        CaptureMemory(reinterpret_cast<void *>(dirtyRange.start), dirtyRange.size, &captureData);
        dataParamBuffer.addParam(std::move(captureData));

        // Also track its size for use with memcpy
        dataParamBuffer.addValueParam<GLsizeiptr>("size", ParamType::TGLsizeiptr,
                                                  static_cast<GLsizeiptr>(dirtyRange.size));

        if (wholeRange.start != dirtyRange.start)
        {
            // Capture with offset
            GLsizeiptr offset = dirtyRange.start - wholeRange.start;

            ASSERT(offset > 0);

            // The dirty page range is not at the start of the buffer, track the offset.
            dataParamBuffer.addValueParam<GLsizeiptr>("offset", ParamType::TGLsizeiptr, offset);

            // Call the helper that populates the buffer with captured data
            mFrameCalls.emplace_back("UpdateClientBufferDataWithOffset",
                                     std::move(dataParamBuffer));
        }
        else
        {
            // Call the helper that populates the buffer with captured data
            mFrameCalls.emplace_back("UpdateClientBufferData", std::move(dataParamBuffer));
        }
    }
}

void FrameCaptureShared::captureMappedBufferSnapshot(const gl::Context *context,
                                                     const CallCapture &call)
{
    // If the buffer was mapped writable, we need to restore its data, since we have no
    // visibility into what the client did to the buffer while mapped.
    // This sequence will result in replay calls like this:
    //   ...
    //   gMappedBufferData[gBufferMap[42]] = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 65536,
    //                                                        GL_MAP_WRITE_BIT);
    //   ...
    //   UpdateClientBufferData(42, &gBinaryData[164631024], 65536);
    //   glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    //   ...

    // Re-map the buffer, using the info we tracked about the buffer
    gl::BufferBinding target =
        call.params.getParam("targetPacked", ParamType::TBufferBinding, 0).value.BufferBindingVal;

    FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
    gl::Buffer *buffer                     = context->getState().getTargetBuffer(target);
    if (!frameCaptureShared->hasBufferData(buffer->id()))
    {
        // This buffer was not marked writable, so we did not back it up
        return;
    }

    std::pair<GLintptr, GLsizeiptr> bufferDataOffsetAndLength =
        frameCaptureShared->getBufferDataOffsetAndLength(buffer->id());
    GLintptr offset   = bufferDataOffsetAndLength.first;
    GLsizeiptr length = bufferDataOffsetAndLength.second;

    // Map the buffer so we can copy its contents out
    ASSERT(!buffer->isMapped());
    angle::Result result = buffer->mapRange(context, offset, length, GL_MAP_READ_BIT);
    if (result != angle::Result::Continue)
    {
        ERR() << "Failed to mapRange of buffer" << std::endl;
    }
    const uint8_t *data = reinterpret_cast<const uint8_t *>(buffer->getMapPointer());

    // Create the parameters to our helper for use during replay
    ParamBuffer dataParamBuffer;

    // Pass in the target buffer ID
    dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);

    // Capture the current buffer data with a binary param
    ParamCapture captureData("source", ParamType::TvoidConstPointer);
    CaptureMemory(data, length, &captureData);
    dataParamBuffer.addParam(std::move(captureData));

    // Also track its size for use with memcpy
    dataParamBuffer.addValueParam<GLsizeiptr>("size", ParamType::TGLsizeiptr, length);

    // Call the helper that populates the buffer with captured data
    mFrameCalls.emplace_back("UpdateClientBufferData", std::move(dataParamBuffer));

    // Unmap the buffer and move on
    GLboolean dontCare;
    (void)buffer->unmap(context, &dontCare);
}

void FrameCaptureShared::checkForCaptureTrigger()
{
    // Determine if trigger has changed
    std::string captureTriggerStr = GetCaptureTrigger();
    if (captureTriggerStr.empty())
    {
        return;
    }

    // If the value has changed, use the original value as the frame count
    uint32_t captureTrigger = atoi(captureTriggerStr.c_str());
    if ((mCaptureTrigger > 0) && (captureTrigger == 0))
    {
        // Start mid-execution capture for the current frame
        mCaptureStartFrame = mFrameIndex + 1;

        // Use the original trigger value as the frame count
        mCaptureEndFrame = mCaptureStartFrame + mCaptureTrigger - 1;

        INFO() << "Capture triggered after frame " << mFrameIndex << " for " << mCaptureTrigger
               << " frames";

        // Stop polling
        mCaptureTrigger = 0;
    }
    else if (captureTrigger > 0)
    {
        // Update number of frames to capture in MEC
        mCaptureTrigger = captureTrigger;
    }
}

void FrameCaptureShared::scanSetupCalls(std::vector<CallCapture> &setupCalls)
{
    // Scan all the instructions in the list for tracking
    for (CallCapture &call : setupCalls)
    {
        updateReadBufferSize(call.params.getReadBufferSize());
        updateResourceCountsFromCallCapture(call);
    }
}

void FrameCaptureShared::runMidExecutionCapture(gl::Context *mainContext)
{
    // Set the capture active to ensure all GLES commands issued by the next frame are
    // handled correctly by maybeCapturePreCallUpdates() and maybeCapturePostCallUpdates().
    setCaptureActive();

    // Make sure all pending work for every Context in the share group has completed so all data
    // (buffers, textures, etc.) has been updated and no resources are in use.
    egl::ShareGroup *shareGroup = mainContext->getShareGroup();
    shareGroup->finishAllContexts();

    const gl::State &contextState = mainContext->getState();
    gl::State mainContextReplayState(
        nullptr, nullptr, nullptr, nullptr, nullptr, contextState.getClientVersion(), false, true,
        true, true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG, contextState.hasRobustAccess(),
        contextState.hasProtectedContent(), false, false);
    mainContextReplayState.initializeForCapture(mainContext);

    CaptureShareGroupMidExecutionSetup(mainContext, &mShareGroupSetupCalls, &mResourceTracker,
                                       mainContextReplayState, mMaxAccessedResourceIDs);

    scanSetupCalls(mShareGroupSetupCalls);

    egl::Display *display = mainContext->getDisplay();
    egl::Surface *draw    = mainContext->getCurrentDrawSurface();
    egl::Surface *read    = mainContext->getCurrentReadSurface();

    shareGroup->getContexts().forEach([&](gl::Context *shareContext) {
        FrameCapture *frameCapture = shareContext->getFrameCapture();
        ASSERT(frameCapture->getSetupCalls().empty());

        if (shareContext->id() == mainContext->id())
        {
            CaptureMidExecutionSetup(shareContext, &frameCapture->getSetupCalls(),
                                     frameCapture->getStateResetHelper(), &mShareGroupSetupCalls,
                                     &mResourceIDToSetupCalls, &mResourceTracker,
                                     mainContextReplayState, mValidateSerializedState);
            scanSetupCalls(frameCapture->getSetupCalls());

            std::stringstream protoStream;
            std::stringstream headerStream;
            std::stringstream bodyStream;

            protoStream << "void "
                        << FmtSetupFunction(kNoPartId, mainContext->id(), FuncUsage::Prototype);
            std::string proto = protoStream.str();

            WriteCppReplayFunctionWithParts(mainContext->id(), ReplayFunc::Setup, mReplayWriter, 1,
                                            &mBinaryData, frameCapture->getSetupCalls(),
                                            headerStream, bodyStream, &mResourceIDBufferSize);

            mReplayWriter.addPrivateFunction(proto, headerStream, bodyStream);
        }
        else
        {
            const gl::State &shareContextState = shareContext->getState();
            gl::State auxContextReplayState(nullptr, nullptr, nullptr, nullptr, nullptr,
                                            shareContextState.getClientVersion(), false, true, true,
                                            true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG,
                                            shareContextState.hasRobustAccess(),
                                            shareContextState.hasProtectedContent(), false, false);
            auxContextReplayState.initializeForCapture(shareContext);

            egl::Error error = shareContext->makeCurrent(display, draw, read);
            if (error.isError())
            {
                INFO() << "MEC unable to make secondary context current";
            }

            CaptureMidExecutionSetup(shareContext, &frameCapture->getSetupCalls(),
                                     frameCapture->getStateResetHelper(), &mShareGroupSetupCalls,
                                     &mResourceIDToSetupCalls, &mResourceTracker,
                                     auxContextReplayState, mValidateSerializedState);

            scanSetupCalls(frameCapture->getSetupCalls());

            WriteAuxiliaryContextCppSetupReplay(
                mReplayWriter, mCompression, mOutDirectory, shareContext, mCaptureLabel, 1,
                frameCapture->getSetupCalls(), &mBinaryData, mSerializeStateEnabled, *this,
                &mResourceIDBufferSize);

            // Release the previously-bound window surface so the side context does not keep a
            // reference. Otherwise surface's isReferenced() stays true and the app's other thread
            // gets EGL_BAD_ACCESS "Surface can only be current on one thread" when trying to get
            // the surface on capture start, leading to lost context/bad glBindFramebuffer calls
            egl::Error unmakeError = shareContext->unMakeCurrent(display);
            if (unmakeError.isError())
            {
                INFO() << "MEC unMakeCurrent failed on secondary context "
                       << shareContext->id().value;
            }
        }
        // Track that this context was created before MEC started
        mActiveContexts.insert(shareContext->id().value);
    });

    egl::Error error = mainContext->makeCurrent(display, draw, read);
    if (error.isError())
    {
        INFO() << "MEC unable to make main context current again";
    }
}

void FrameCaptureShared::onEndFrame(gl::Context *context)
{
    // Grab the frame-capture mutex to avoid GL/EGL capture races
    std::lock_guard<angle::SimpleMutex> lock(mFrameCaptureMutex);

    if (!enabled() || mFrameIndex > mCaptureEndFrame)
    {
        setCaptureInactive();

        // Note: If this call were deferred until shutdown, multi-capture could be
        // supported for traces using persistent/coherent mapped memory, see
        // http://issuetracker.google.com/394107532
        mCoherentBufferTracker.onEndFrame();
        if (enabled())
        {
            resetMidExecutionCapture(context);
        }
        resetCaptureStartEndFrames();
        mFrameIndex++;
        return;
    }

    FrameCapture *frameCapture = context->getFrameCapture();

    // Count resource IDs. This is also done on every frame. It could probably be done by
    // checking the GL state instead of the calls.
    for (const CallCapture &call : mFrameCalls)
    {
        for (const ParamCapture &param : call.params.getParamCaptures())
        {
            ResourceIDType idType = GetResourceIDTypeFromParamType(param.type);
            if (idType != ResourceIDType::InvalidEnum)
            {
                mHasResourceType.set(idType);
            }
        }
    }

    mWindowSurfaceContextID = context->id();

    // On Android, we can trigger a capture during the run
    checkForCaptureTrigger();
    checkForCaptureEnd();

    // Check for MEC. Done after checkForCaptureTrigger(), since that can modify mCaptureStartFrame.
    if (mFrameIndex < mCaptureStartFrame)
    {
        if (mFrameIndex == mCaptureStartFrame - 1)
        {
            initalizeTraceStorage();
            // Trigger MEC.
            runMidExecutionCapture(context);
        }
        mFrameIndex++;
        reset();
        return;
    }

    // If not MEC, initialize capture storage
    if (mFrameIndex == 1 && mCaptureStartFrame == 1)
    {
        initalizeTraceStorage();
    }

    ASSERT(isCaptureActive());

    if (!mFrameCalls.empty())
    {
        mActiveFrameIndices.push_back(getReplayFrameIndex());
    }

    // Make sure all pending work for every Context in the share group has completed so all data
    // (buffers, textures, etc.) has been updated and no resources are in use.
    egl::ShareGroup *shareGroup = context->getShareGroup();
    shareGroup->finishAllContexts();

    // Only validate the first frame for now to save on retracing time.
    if (mValidateSerializedState && mFrameIndex == mCaptureStartFrame)
    {
        CaptureValidateSerializedState(context, &mFrameCalls);
    }

    // Merge attribute pointers in the end of the frame if possible.
    if (mClientVertexArrayDirtyAttribMask.any())
    {
        ASSERT(!mClientVertexArrayCallIndices.empty());
        MergedAttribRanges mergedAddrRanges;
        gl::AttribArray<size_t> mergedIndexMap;
        const gl::VertexArray *vao = context->getState().getVertexArray();

        // If any updated attribute since the beginning or the last draw call is currently not using
        // a client address at the end of the frame, there is no need for merging it.
        for (size_t attribIndex : mClientVertexArrayDirtyAttribMask)
        {
            const void *clientSideAddress = mClientVertexArrayData[attribIndex];
            if (clientSideAddress == nullptr)
            {
                mClientVertexArrayDirtyAttribMask.set(attribIndex, 0);
            }
        }

        MaybeMergeClientAttributes(vao, mClientVertexArrayDirtyAttribMask, mClientVertexArrayData,
                                   &mFrameCalls, mClientVertexArrayCallIndices, false, 0, 0,
                                   mergedAddrRanges, mergedIndexMap);

        // Clear the vertex attribute pointer calls after the merge processing is finished.
        mClientVertexArrayCallIndices.clear();
        mClientVertexArrayDirtyAttribMask.reset();
    }

    writeMainContextCppReplay(context, frameCapture->getSetupCalls(),
                              frameCapture->getStateResetHelper());

    if (mFrameIndex == mCaptureEndFrame)
    {
        // Write shared MEC after frame sequence so we can eliminate unused assets like programs
        WriteShareGroupCppSetupReplay(mReplayWriter, mCompression, mOutDirectory, mCaptureLabel, 1,
                                      1, mShareGroupSetupCalls, &mResourceTracker, &mBinaryData,
                                      mSerializeStateEnabled, mWindowSurfaceContextID,
                                      &mResourceIDBufferSize);

        // Save the index files after the last frame.
        writeCppReplayIndexFiles(context, false);

        mWroteIndexFile = true;
        INFO() << "Finished recording graphics API capture";
    }

    reset();
    mFrameIndex++;
}

void FrameCaptureShared::onDestroyContext(const gl::Context *context)
{
    if (!mEnabled)
    {
        return;
    }
    if (!mWroteIndexFile && mFrameIndex > mCaptureStartFrame)
    {
        // If context is destroyed before end frame is reached and at least
        // 1 frame has been recorded, then write the index files.
        // It doesn't make sense to write the index files when no frame has been recorded
        mFrameIndex -= 1;
        mCaptureEndFrame = mFrameIndex;
        writeCppReplayIndexFiles(context, true);

        mWroteIndexFile = true;
    }
}

void FrameCaptureShared::onMakeCurrent(const gl::Context *context,
                                       const egl::Surface *drawSurface,
                                       EGLint surfaceWidth,
                                       EGLint surfaceHeight)
{
    if (!drawSurface)
    {
        return;
    }

    // Track the width, height, type and color space of the draw surface as provided to
    // makeCurrent.
    SurfaceParams &params = mDrawSurfaceParams[context->id()];
    params.extents        = gl::Extents(surfaceWidth, surfaceHeight, 1);
    params.type           = drawSurface->getType();
    params.colorSpace     = egl::FromEGLenum<egl::ColorSpace>(drawSurface->getGLColorspace());
}

void FrameCaptureShared::initalizeTraceStorage()
{
    // Update output directory location
    getOutputDirectory();
    std::string fileName = GetBinaryDataFilePath(mCompression, mCaptureLabel);
    mBinaryData.initializeBinaryDataStore(mCompression, mOutDirectory, fileName);
}

void StateResetHelper::setDefaultResetCalls(const gl::Context *context,
                                            angle::EntryPoint entryPoint)
{
    // Populate default reset calls for entrypoints to support looping to beginning
    switch (entryPoint)
    {
        case angle::EntryPoint::GLUseProgram:
        {
            if (context->getActiveLinkedProgram() &&
                context->getActiveLinkedProgram()->id().value != 0)
            {
                Capture(&mResetCalls[angle::EntryPoint::GLUseProgram],
                        gl::CaptureUseProgram(context->getState(), true, {0}));
            }
            break;
        }
        case angle::EntryPoint::GLBindVertexArray:
        {
            if (context->getState().getVertexArray()->id().value != 0)
            {
                VertexArrayCaptureFuncs vertexArrayFuncs(context->isGLES1());
                Capture(&mResetCalls[angle::EntryPoint::GLBindVertexArray],
                        vertexArrayFuncs.bindVertexArray(context->getState(), true, {0}));
            }
            break;
        }
        case angle::EntryPoint::GLBlendFunc:
        case angle::EntryPoint::GLBlendFuncSeparate:
        {
            // Though BlendFunc state tracking is unified, exclusively use BlendFuncSeparate for
            // non-GLES1 apps as it covers all cases
            if (context->isGLES1())
            {
                Capture(&mResetCalls[angle::EntryPoint::GLBlendFunc],
                        CaptureBlendFunc(context->getState(), true, GL_ONE, GL_ZERO));
            }
            else
            {
                Capture(&mResetCalls[angle::EntryPoint::GLBlendFuncSeparate],
                        CaptureBlendFuncSeparate(context->getState(), true, GL_ONE, GL_ZERO, GL_ONE,
                                                 GL_ZERO));
            }
            break;
        }
        case angle::EntryPoint::GLBlendEquation:
        {
            UNREACHABLE();  // GLBlendEquationSeparate is always used instead
            break;
        }
        case angle::EntryPoint::GLBlendEquationSeparate:
        {
            Capture(
                &mResetCalls[angle::EntryPoint::GLBlendEquationSeparate],
                CaptureBlendEquationSeparate(context->getState(), true, GL_FUNC_ADD, GL_FUNC_ADD));
            break;
        }
        case angle::EntryPoint::GLColorMask:
        {
            Capture(
                &mResetCalls[angle::EntryPoint::GLColorMask],
                CaptureColorMask(context->getState(), true, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
            break;
        }
        case angle::EntryPoint::GLBlendColor:
        {
            Capture(&mResetCalls[angle::EntryPoint::GLBlendColor],
                    CaptureBlendColor(context->getState(), true, 0, 0, 0, 0));
            break;
        }
        case angle::EntryPoint::GLBindFramebuffer:
        {
            FramebufferCaptureFuncs framebufferFuncs(context->isGLES1());
            Capture(
                &mResetCalls[angle::EntryPoint::GLBindFramebuffer],
                framebufferFuncs.bindFramebuffer(context->getState(), true, GL_FRAMEBUFFER, {0}));
            break;
        }
        default:
            ERR() << "Unhandled entry point in setDefaultResetCalls: "
                  << GetEntryPointName(entryPoint);
            UNREACHABLE();
            break;
    }
}

void ResourceTracker::setDeletedFenceSync(gl::SyncID sync)
{
    ASSERT(sync.value != 0);
    if (mStartingFenceSyncs.find(sync) == mStartingFenceSyncs.end())
    {
        // This is a fence sync created after MEC was initialized. Ignore it.
        return;
    }

    // In this case, the app is deleting a fence sync we started with, we need to regen on loop.
    mFenceSyncsToRegen.insert(sync);
}

void ResourceTracker::setModifiedDefaultUniform(gl::ShaderProgramID programID,
                                                gl::UniformLocation location)
{
    // Pull up or create the list of uniform locations for this program and mark one dirty
    mDefaultUniformsToReset[programID].insert(location);
}

void ResourceTracker::setDefaultUniformBaseLocation(gl::ShaderProgramID programID,
                                                    gl::UniformLocation location,
                                                    gl::UniformLocation baseLocation)
{
    // Track the base location used to populate arrayed uniforms in Setup
    mDefaultUniformBaseLocations[{programID, location}] = baseLocation;
}

TrackedResource &ResourceTracker::getTrackedResource(gl::ContextID contextID, ResourceIDType type)
{
    if (IsSharedObjectResource(type))
    {
        // No need to index with context if shared
        return mTrackedResourcesShared[static_cast<uint32_t>(type)];
    }
    else
    {
        // For per-context objects, track the resource per-context
        return mTrackedResourcesPerContext[contextID][static_cast<uint32_t>(type)];
    }
}

void ResourceTracker::getContextIDs(std::set<gl::ContextID> &idsOut)
{
    for (const auto &trackedResourceIterator : mTrackedResourcesPerContext)
    {
        gl::ContextID contextID = trackedResourceIterator.first;
        idsOut.insert(contextID);
    }
}

void TrackedResource::setGennedResource(GLuint id)
{
    if (mStartingResources.find(id) == mStartingResources.end())
    {
        // This is a resource created after MEC was initialized, track it
        mNewResources.insert(id);
    }
    else
    {
        // In this case, the app is genning a resource with starting ID after previously deleting it
        ASSERT(mResourcesToRegen.find(id) != mResourcesToRegen.end());

        // For this, we need to delete it again to recreate it.
        mResourcesToDelete.insert(id);
    }
}

bool TrackedResource::resourceIsGenerated(GLuint id)
{
    return mStartingResources.find(id) != mStartingResources.end() ||
           mNewResources.find(id) != mNewResources.end();
}

void TrackedResource::setDeletedResource(GLuint id)
{
    if (id == 0)
    {
        // Ignore ID 0
        return;
    }

    if (mNewResources.find(id) != mNewResources.end())
    {
        // This is a resource created after MEC was initialized, just clear it, since there will be
        // no actions required for it to return to starting state.
        mNewResources.erase(id);
        return;
    }

    if (mStartingResources.find(id) != mStartingResources.end())
    {
        // In this case, the app is deleting a resource we started with, we need to regen on loop

        // Mark that we don't need to delete this
        mResourcesToDelete.erase(id);

        // Generate the resource again
        mResourcesToRegen.insert(id);

        // Also restore its contents
        mResourcesToRestore.insert(id);
    }

    // If none of the above is true, the app is deleting a resource that was never genned.
}

void TrackedResource::setModifiedResource(GLuint id)
{
    // If this was a starting resource, we need to track it for restore
    if (mStartingResources.find(id) != mStartingResources.end())
    {
        mResourcesToRestore.insert(id);
    }
}

void ResourceTracker::setBufferMapped(gl::ContextID contextID, GLuint id)
{
    // If this was a starting buffer, we may need to restore it to original state during Reset.
    // Skip buffers that were deleted after the starting point.
    const TrackedResource &trackedBuffers = getTrackedResource(contextID, ResourceIDType::Buffer);
    const ResourceSet &startingBuffers    = trackedBuffers.getStartingResources();
    const ResourceSet &buffersToRegen     = trackedBuffers.getResourcesToRegen();
    if (startingBuffers.find(id) != startingBuffers.end() &&
        buffersToRegen.find(id) == buffersToRegen.end())
    {
        // Track that its current state is mapped (true)
        mStartingBuffersMappedCurrent[id] = true;
    }
}

void ResourceTracker::setBufferUnmapped(gl::ContextID contextID, GLuint id)
{
    // If this was a starting buffer, we may need to restore it to original state during Reset.
    // Skip buffers that were deleted after the starting point.
    const TrackedResource &trackedBuffers = getTrackedResource(contextID, ResourceIDType::Buffer);
    const ResourceSet &startingBuffers    = trackedBuffers.getStartingResources();
    const ResourceSet &buffersToRegen     = trackedBuffers.getResourcesToRegen();
    if (startingBuffers.find(id) != startingBuffers.end() &&
        buffersToRegen.find(id) == buffersToRegen.end())
    {
        // Track that its current state is unmapped (false)
        mStartingBuffersMappedCurrent[id] = false;
    }
}

bool ResourceTracker::getStartingBuffersMappedCurrent(GLuint id) const
{
    const auto &foundBool = mStartingBuffersMappedCurrent.find(id);
    ASSERT(foundBool != mStartingBuffersMappedCurrent.end());
    return foundBool->second;
}

bool ResourceTracker::getStartingBuffersMappedInitial(GLuint id) const
{
    const auto &foundBool = mStartingBuffersMappedInitial.find(id);
    ASSERT(foundBool != mStartingBuffersMappedInitial.end());
    return foundBool->second;
}

void ResourceTracker::onShaderProgramAccess(gl::ShaderProgramID shaderProgramID)
{
    mMaxShaderPrograms = std::max(mMaxShaderPrograms, shaderProgramID.value + 1);
}

// Serialize trace metadata into a JSON file. The JSON file will be named "trace_prefix.json".
//
// As of writing, it will have the format like so:
// {
//     "TraceMetadata":
//     {
//         "AreClientArraysEnabled" : 1, "CaptureRevision" : 16631, "ConfigAlphaBits" : 8,
//             "ConfigBlueBits" : 8, "ConfigDepthBits" : 24, "ConfigGreenBits" : 8,
// ... etc ...
void FrameCaptureShared::writeJSON(const gl::Context *context)
{
    SurfaceParams noSurface;
    noSurface.extents.width  = 16;
    noSurface.extents.height = 9;
    noSurface.colorSpace     = egl::ColorSpace::sRGB;

    const gl::ContextID contextId           = context->id();
    const SurfaceParams &surfaceParams =
        mDrawSurfaceParams.find(contextId) != mDrawSurfaceParams.end()
            ? mDrawSurfaceParams.at(contextId)
            : noSurface;
    const gl::State &glState                = context->getState();
    const egl::Config *config               = context->getConfig();
    const egl::AttributeMap &displayAttribs = context->getDisplay()->getAttributeMap();

    unsigned int frameCount = getFrameCount();

    JsonSerializer json;
    json.startGroup("TraceMetadata");
    json.addScalar("CaptureRevision", GetANGLERevision());
    json.addScalar("ContextClientMajorVersion", context->getClientVersion().getMajor());
    json.addScalar("ContextClientMinorVersion", context->getClientVersion().getMinor());
    json.addHexValue("DisplayPlatformType", displayAttribs.getAsInt(EGL_PLATFORM_ANGLE_TYPE_ANGLE));
    json.addHexValue("DisplayDeviceType",
                     displayAttribs.getAsInt(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE));
    json.addScalar("FrameStart", 1);
    json.addScalar("FrameEnd", frameCount);
    json.addScalar("DrawSurfaceWidth", surfaceParams.extents.width);
    json.addScalar("DrawSurfaceHeight", surfaceParams.extents.height);
    json.addHexValue("DrawSurfaceColorSpace", ToEGLenum(surfaceParams.colorSpace));
    if (config)
    {
        json.addScalar("ConfigRedBits", config->redSize);
        json.addScalar("ConfigGreenBits", config->greenSize);
        json.addScalar("ConfigBlueBits", config->blueSize);
        json.addScalar("ConfigAlphaBits", config->alphaSize);
        json.addScalar("ConfigDepthBits", config->depthSize);
        json.addScalar("ConfigStencilBits", config->stencilSize);
    }
    else
    {
        json.addScalar("ConfigRedBits", EGL_DONT_CARE);
        json.addScalar("ConfigGreenBits", EGL_DONT_CARE);
        json.addScalar("ConfigBlueBits", EGL_DONT_CARE);
        json.addScalar("ConfigAlphaBits", EGL_DONT_CARE);
        json.addScalar("ConfigDepthBits", EGL_DONT_CARE);
        json.addScalar("ConfigStencilBits", EGL_DONT_CARE);
    }
    json.addBool("IsRobustAccessEnabled", context->isRobustnessEnabled());
    json.addBool("IsBinaryDataCompressed", mCompression);
    json.addBool("AreClientArraysEnabled", glState.areClientArraysEnabled());
    json.addBool("IsBindGeneratesResourcesEnabled", glState.isBindGeneratesResourceEnabled());
    json.addBool("IsWebGLCompatibilityEnabled", glState.isWebGL());
    json.addBool("IsHardenedContextEnabled", context->isHardenedContext());
    json.addBool("IsRobustResourceInitEnabled", glState.isRobustResourceInitEnabled());
    json.addBool("AreExtensionsEnabled", context->getExtensionsEnabled());
    json.endGroup();

    json.startGroup("BinaryMetadata");
    json.addScalar("Version", mIndexInfo.version);
    json.addScalar("BlockCount", mIndexInfo.blockCount);
    // These values are handled as strings to avoid json-related underflows
    std::stringstream blockSizeString;
    blockSizeString << mIndexInfo.blockSize;
    json.addString("BlockSize", blockSizeString.str());
    std::stringstream resSizeString;
    resSizeString << mIndexInfo.residentSize;
    json.addString("ResidentSize", resSizeString.str());
    std::stringstream offsetString;
    offsetString << mIndexInfo.indexOffset;
    json.addString("IndexOffset", offsetString.str());
    json.endGroup();

    {
        const std::vector<std::string> &traceFiles = mReplayWriter.getAndResetWrittenFiles();
        json.addVectorOfStrings("TraceFiles", traceFiles);
    }

    json.addScalar("WindowSurfaceContextID", contextId.value);

    {
        std::stringstream jsonFileNameStream;
        jsonFileNameStream << mOutDirectory << FmtCapturePrefix(kNoContextId, mCaptureLabel)
                           << ".json";
        std::string jsonFileName = jsonFileNameStream.str();

        SaveFileHelper saveData(jsonFileName);
        saveData.write(reinterpret_cast<const uint8_t *>(json.data()), json.length());
    }
}

void FrameCaptureShared::writeCppReplayIndexFiles(const gl::Context *context,
                                                  bool writeResetContextCall)
{
    // Ensure the last frame is written. This will no-op if the frame is already written.
    mReplayWriter.saveFrame();

    const gl::ContextID contextId = context->id();

    {
        std::stringstream header;

        header << "#pragma once\n";
        header << "\n";
        header << "#include <EGL/egl.h>\n";
        header << "#include <stdint.h>\n";

        std::string includes = header.str();
        mReplayWriter.setHeaderPrologue(includes);
    }

    {
        std::stringstream source;

        source << "#include \"" << FmtCapturePrefix(contextId, mCaptureLabel) << ".h\"\n";
        source << "#include \"trace_fixture.h\"\n";
        source << "#include \"angle_trace_gl.h\"\n";

        std::string sourcePrologue = source.str();
        mReplayWriter.setSourcePrologue(sourcePrologue);
    }

    {
        std::string proto = "void InitReplay(void)";

        std::stringstream source;
        source << proto << "\n";
        source << "{\n";
        WriteInitReplayCall(mCompression, source, context->id(), mCaptureLabel,
                            MaxClientArraySize(mClientArraySizes), mReadBufferSize,
                            mResourceIDBufferSize, mMaxAccessedResourceIDs);
        source << "}\n";

        mReplayWriter.addPrivateFunction(proto, std::stringstream(), source);
    }

    {
        std::string proto = "void ReplayFrame(uint32_t frameIndex)";

        std::stringstream source;

        source << proto << "\n";
        source << "{\n";
        source << "    switch (frameIndex)\n";
        source << "    {\n";
        for (uint32_t frameIndex : mActiveFrameIndices)
        {
            source << "        case " << frameIndex << ":\n";
            source << "            " << FmtReplayFunction(contextId, FuncUsage::Call, frameIndex)
                   << ";\n";
            source << "            break;\n";
        }
        source << "        default:\n";
        source << "            break;\n";
        source << "    }\n";
        source << "}\n";

        mReplayWriter.addPublicFunction(proto, std::stringstream(), source);
    }

    if (writeResetContextCall)
    {
        std::string proto = "void ResetReplay(void)";

        std::stringstream source;

        source << proto << "\n";
        source << "{\n";
        source << "    // Reset context is empty because context is destroyed before end "
                  "frame is reached\n";
        source << "}\n";

        mReplayWriter.addPublicFunction(proto, std::stringstream(), source);
    }

    if (mSerializeStateEnabled)
    {
        std::string proto = "const char *GetSerializedContextState(uint32_t frameIndex)";

        std::stringstream source;

        source << proto << "\n";
        source << "{\n";
        source << "    switch (frameIndex)\n";
        source << "    {\n";
        for (uint32_t frameIndex = 1; frameIndex <= getFrameCount(); ++frameIndex)
        {
            source << "        case " << frameIndex << ":\n";
            source << "            return "
                   << FmtGetSerializedContextStateFunction(contextId, FuncUsage::Call, frameIndex)
                   << ";\n";
        }
        source << "        default:\n";
        source << "            return NULL;\n";
        source << "    }\n";
        source << "}\n";

        mReplayWriter.addPublicFunction(proto, std::stringstream(), source);
    }

    {
        std::stringstream fnameStream;
        fnameStream << mOutDirectory << FmtCapturePrefix(contextId, mCaptureLabel);
        std::string fnamePattern = fnameStream.str();

        mReplayWriter.setFilenamePattern(fnamePattern);
    }

    mReplayWriter.saveIndexFilesAndHeader();

    // Finalize binary data file
    mIndexInfo = mBinaryData.closeBinaryDataStore();
    writeJSON(context);
}

void FrameCaptureShared::writeMainContextCppReplay(const gl::Context *context,
                                                   const std::vector<CallCapture> &setupCalls,
                                                   StateResetHelper &stateResetHelper)
{
    ASSERT(mWindowSurfaceContextID == context->id());

    {
        std::stringstream header;

        header << "#include \"" << FmtCapturePrefix(context->id(), mCaptureLabel) << ".h\"\n";
        header << "#include \"angle_trace_gl.h\"\n";

        std::string headerString = header.str();
        mReplayWriter.setSourcePrologue(headerString);
    }

    uint32_t frameCount = getFrameCount();
    uint32_t frameIndex = getReplayFrameIndex();

    if (frameIndex == 1)
    {
        {
            std::string proto = "void SetupReplay(void)";

            std::stringstream out;
            std::stringstream outMainContextSetupCall;

            out << proto << "\n";
            out << "{\n";

            // Setup all of the shared objects.
            out << "    InitReplay();\n";
            if (usesMidExecutionCapture())
            {
                out << "    " << FmtSetupFunction(kNoPartId, kSharedContextId, FuncUsage::Call)
                    << ";\n";
                out << "    "
                    << FmtSetupInactiveFunction(kNoPartId, kSharedContextId, FuncUsage::Call)
                    << "\n";
                // Make sure that the current context is mapped correctly
                out << "    SetCurrentContextID(" << context->id() << ");\n";
            }

            // Setup each of the auxiliary contexts.
            egl::ShareGroup *shareGroup                  = context->getShareGroup();
            const egl::SharedContextMap &shareContextMap = shareGroup->getContexts();
            shareContextMap.forEach([&](gl::Context *shareContext) {
                if (shareContext->id() == context->id())
                {
                    if (usesMidExecutionCapture())
                    {
                        // Setup the presentation (this) context last
                        outMainContextSetupCall
                            << "    " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Call)
                            << ";\n";
                        outMainContextSetupCall << "\n";
                    }

                    return;
                }

                // The SetupReplayContextXX() calls only exist if this is a mid-execution capture
                // and we can only call them if they exist, so only output the calls if this is a
                // MEC.
                if (usesMidExecutionCapture())
                {
                    // Only call SetupReplayContext for secondary contexts that were current before
                    // MEC started
                    if (mActiveContexts.find(shareContext->id().value) != mActiveContexts.end())
                    {
                        // TODO(http://anglebug.com/42264418): Support capture/replay of
                        // eglCreateContext() so this block can be moved into SetupReplayContextXX()
                        // by injecting them into the beginning of the setup call stream.
                        out << "    CreateContext(" << shareContext->id().value << ");\n";

                        out << "    "
                            << FmtSetupFunction(kNoPartId, shareContext->id(), FuncUsage::Call)
                            << ";\n";
                    }
                }
            });
            out << outMainContextSetupCall.str();

            // If there are other contexts that were initialized, we need to make the main context
            // current again.
            if (shareContextMap.size() > 1)
            {
                out << "\n";
                out << "    eglMakeCurrent(NULL, NULL, NULL, gContextMap2[" << context->id()
                    << "]);\n";
                out << "    UpdateCurrentContext(" << context->id() << ");\n";
            }

            out << "}\n";

            mReplayWriter.addPublicFunction(proto, std::stringstream(), out);
        }
    }

    // Emit code to reset back to starting state
    if (frameIndex == frameCount)
    {
        std::stringstream resetProtoStream;
        std::stringstream resetHeaderStream;
        std::stringstream resetBodyStream;

        resetProtoStream << "void ResetReplay(void)";

        resetBodyStream << resetProtoStream.str() << "\n";
        resetBodyStream << "{\n";

        // Grab the list of contexts to be reset
        std::set<gl::ContextID> contextIDs;
        mResourceTracker.getContextIDs(contextIDs);

        // TODO(http://anglebug.com/42264418): Look at moving this into the shared context file
        // since it's resetting shared objects.

        // TODO(http://anglebug.com/42263204): Support function parts when writing Reset functions

        // Track whether anything was written during Reset
        bool anyResourceReset = false;

        // Track whether we changed contexts during Reset
        bool contextChanged = false;

        // First emit shared object reset, including opaque and context state
        {
            std::stringstream protoStream;
            std::stringstream headerStream;
            std::stringstream bodyStream;

            protoStream << "void "
                        << FmtResetFunction(kNoPartId, kSharedContextId, FuncUsage::Prototype);
            bodyStream << protoStream.str() << "\n";
            bodyStream << "{\n";

            for (ResourceIDType resourceType : AllEnums<ResourceIDType>())
            {
                if (!IsSharedObjectResource(resourceType))
                {
                    continue;
                }
                // Use current context for shared reset
                MaybeResetResources(context->getDisplay(), context->id(), resourceType,
                                    mReplayWriter, bodyStream, headerStream, &mResourceTracker,
                                    &mBinaryData, anyResourceReset, &mResourceIDBufferSize);
            }

            // Reset opaque type objects that don't have IDs, so are not ResourceIDTypes.
            MaybeResetOpaqueTypeObjects(mReplayWriter, bodyStream, headerStream, context,
                                        &mResourceTracker, &mBinaryData, &mResourceIDBufferSize);

            bodyStream << "}\n";

            mReplayWriter.addPrivateFunction(protoStream.str(), headerStream, bodyStream);
        }

        // Emit the call to shared object reset
        resetBodyStream << "    " << FmtResetFunction(kNoPartId, kSharedContextId, FuncUsage::Call)
                        << ";\n";

        // Reset our output tracker (Note: This was unused during shared reset)
        anyResourceReset = false;

        // Walk through all contexts that need Reset
        for (const gl::ContextID &contextID : contextIDs)
        {
            // Create a function to reset each context's non-shared objects
            {
                std::stringstream protoStream;
                std::stringstream headerStream;
                std::stringstream bodyStream;

                protoStream << "void "
                            << FmtResetFunction(kNoPartId, contextID, FuncUsage::Prototype);
                bodyStream << protoStream.str() << "\n";
                bodyStream << "{\n";

                // Build the Reset calls in a separate stream so we can insert before them
                std::stringstream resetStream;

                for (ResourceIDType resourceType : AllEnums<ResourceIDType>())
                {
                    if (IsSharedObjectResource(resourceType))
                    {
                        continue;
                    }
                    MaybeResetResources(context->getDisplay(), contextID, resourceType,
                                        mReplayWriter, resetStream, headerStream, &mResourceTracker,
                                        &mBinaryData, anyResourceReset, &mResourceIDBufferSize);
                }

                MaybeResetEGLImageBindings(contextID, resetStream, &mResourceTracker,
                                           &anyResourceReset);

                // Only call eglMakeCurrent if anything was actually reset in the function and the
                // context differs from current
                if (anyResourceReset && contextID != context->id())
                {
                    contextChanged = true;
                    bodyStream << "    eglMakeCurrent(NULL, NULL, NULL, gContextMap2["
                               << contextID.value << "]);\n";
                    bodyStream << "    UpdateCurrentContext(" << contextID.value << ");\n\n";
                }

                // Then append the Reset calls
                bodyStream << resetStream.str();

                bodyStream << "}\n";
                mReplayWriter.addPrivateFunction(protoStream.str(), headerStream, bodyStream);
            }

            // Emit a call to reset each context's non-shared objects
            resetBodyStream << "    " << FmtResetFunction(kNoPartId, contextID, FuncUsage::Call)
                            << ";\n";
        }

        // Bind the main context again if we bound any additional contexts
        if (contextChanged)
        {
            resetBodyStream << "    eglMakeCurrent(NULL, NULL, NULL, gContextMap2["
                            << context->id().value << "]);\n";
            resetBodyStream << "    UpdateCurrentContext(" << context->id().value << ");\n";
        }

        // Now that we're back on the main context, reset any additional state
        resetBodyStream << "\n    // Reset main context state\n";
        MaybeResetContextState(mReplayWriter, resetBodyStream, resetHeaderStream, &mResourceTracker,
                               context, &mBinaryData, stateResetHelper, &mResourceIDBufferSize);

        resetBodyStream << "}\n";

        mReplayWriter.addPublicFunction(resetProtoStream.str(), resetHeaderStream, resetBodyStream);
    }

    if (!mFrameCalls.empty())
    {
        std::stringstream protoStream;
        protoStream << "void "
                    << FmtReplayFunction(context->id(), FuncUsage::Prototype, frameIndex);
        std::string proto = protoStream.str();
        std::stringstream headerStream;
        std::stringstream bodyStream;

        if (context->getShareGroup()->getContexts().size() > 1)
        {
            // Only ReplayFunc::Replay trace file output functions are affected by multi-context
            // call grouping so they can safely be special-cased here.
            WriteCppReplayFunctionWithPartsMultiContext(
                context->id(), ReplayFunc::Replay, mReplayWriter, frameIndex, &mBinaryData,
                mFrameCalls, headerStream, bodyStream, &mResourceIDBufferSize);
        }
        else
        {
            WriteCppReplayFunctionWithParts(context->id(), ReplayFunc::Replay, mReplayWriter,
                                            frameIndex, &mBinaryData, mFrameCalls, headerStream,
                                            bodyStream, &mResourceIDBufferSize);
        }
        mReplayWriter.addPrivateFunction(proto, headerStream, bodyStream);
    }

    if (mSerializeStateEnabled)
    {
        std::string serializedContextString;
        if (SerializeContextToString(const_cast<gl::Context *>(context),
                                     &serializedContextString) == Result::Continue)
        {
            std::stringstream protoStream;
            protoStream << "const char *"
                        << FmtGetSerializedContextStateFunction(context->id(), FuncUsage::Prototype,
                                                                frameIndex);
            std::string proto = protoStream.str();

            std::stringstream bodyStream;
            bodyStream << proto << "\n";
            bodyStream << "{\n";
            bodyStream << "    return " << FmtMultiLineString(serializedContextString) << ";\n";
            bodyStream << "}\n";

            mReplayWriter.addPrivateFunction(proto, std::stringstream(), bodyStream);
        }
    }

    {
        std::stringstream fnamePatternStream;
        fnamePatternStream << mOutDirectory << FmtCapturePrefix(context->id(), mCaptureLabel);
        std::string fnamePattern = fnamePatternStream.str();

        mReplayWriter.setFilenamePattern(fnamePattern);
    }

    if (mFrameIndex == mCaptureEndFrame)
    {
        mReplayWriter.saveFrame();
    }
    else
    {
        mReplayWriter.saveFrameIfFull();
    }
}

const std::string &FrameCaptureShared::getShaderSource(gl::ShaderProgramID id) const
{
    const auto &foundSources = mCachedShaderSource.find(id);
    ASSERT(foundSources != mCachedShaderSource.end());
    return foundSources->second;
}

void FrameCaptureShared::setShaderSource(gl::ShaderProgramID id, std::string source)
{
    mCachedShaderSource[id] = source;
}

const ProgramSources &FrameCaptureShared::getProgramSources(gl::ShaderProgramID id) const
{
    const auto &foundSources = mCachedProgramSources.find(id);
    ASSERT(foundSources != mCachedProgramSources.end());
    return foundSources->second;
}

void FrameCaptureShared::setProgramSources(gl::ShaderProgramID id, ProgramSources sources)
{
    mCachedProgramSources[id] = sources;
}

void FrameCaptureShared::markResourceSetupCallsInactive(std::vector<CallCapture> *setupCalls,
                                                        ResourceIDType type,
                                                        GLuint id,
                                                        gl::Range<size_t> range)
{
    ASSERT(mResourceIDToSetupCalls[type].find(id) == mResourceIDToSetupCalls[type].end());

    // Mark all of the calls that were used to initialize this resource as INACTIVE
    for (size_t index : range)
    {
        (*setupCalls)[index].isActive = false;
    }

    mResourceIDToSetupCalls[type][id] = range;
}

void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture)
{
    // Write the incoming string up to limit, including null terminator
    size_t length = strlen(str) + 1;

    if (length > limit)
    {
        // If too many characters, resize the string to fit in the limit
        std::string newStr = str;
        newStr.resize(limit - 1);
        CaptureString(newStr.c_str(), paramCapture);
    }
    else
    {
        CaptureMemory(str, length, paramCapture);
    }
}

void CaptureVertexPointerGLES1(const gl::State &glState,
                               gl::ClientVertexArrayType type,
                               const void *pointer,
                               ParamCapture *paramCapture)
{
    paramCapture->value.voidConstPointerVal = pointer;
    if (!glState.getTargetBuffer(gl::BufferBinding::Array))
    {
        paramCapture->arrayClientPointerIndex =
            gl::GLES1Renderer::VertexArrayIndex(type, glState.gles1());
    }
}

gl::Program *GetProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle)
{
    gl::Program *program = glState.getShaderProgramManagerForCapture().getProgram(handle);
    return program;
}

void CaptureGetActiveUniformBlockivParameters(const gl::State &glState,
                                              gl::ShaderProgramID programPacked,
                                              gl::UniformBlockIndex uniformBlockIndexPacked,
                                              gl::UniformBlockParameter pnamePacked,
                                              ParamCapture *paramCapture)
{
    int numParams = 1;

    // From the OpenGL ES 3.0 spec:
    // If pname is UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, then a list of the
    // active uniform indices for the uniform block identified by uniformBlockIndex is
    // returned. The number of elements that will be written to params is the value of
    // UNIFORM_BLOCK_ACTIVE_UNIFORMS for uniformBlockIndex
    if (pnamePacked == gl::UniformBlockParameter::ActiveUniformIndices)
    {
        gl::Program *programObject = GetProgramForCapture(glState, programPacked);
        if (programObject != nullptr)
        {
            gl::QueryActiveUniformBlockiv(programObject, uniformBlockIndexPacked,
                                          gl::UniformBlockParameter::ActiveUniforms, nullptr,
                                          &numParams);
        }
    }

    paramCapture->readBufferSizeBytes = sizeof(GLint) * numParams;
}

void CaptureGetParameter(const gl::State &glState,
                         GLenum pname,
                         size_t typeSize,
                         ParamCapture *paramCapture)
{
    // kMaxReportedCapabilities is the biggest array we'll need to hold data from glGet calls.
    // This value needs to be updated if any new extensions are introduced that would allow for
    // more compressed texture formats. The current value is taken from:
    // http://opengles.gpuinfo.org/displaycapability.php?name=GL_NUM_COMPRESSED_TEXTURE_FORMATS&esversion=2
    constexpr unsigned int kMaxReportedCapabilities = 69;
    paramCapture->readBufferSizeBytes               = typeSize * kMaxReportedCapabilities;
}

void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCapture)
{
    paramCapture->readBufferSizeBytes = sizeof(GLuint) * n;
    CaptureMemory(handles, paramCapture->readBufferSizeBytes, paramCapture);
}

void CaptureShaderStrings(GLsizei count,
                          const GLchar *const *strings,
                          const GLint *length,
                          ParamCapture *paramCapture)
{
    // Concat the array elements of the string into one data vector,
    // append the terminating zero and use this as the captured shader
    // string. The string count and the length array are adjusted
    // accordingly in the capture post-processing

    std::vector<uint8_t> data;
    size_t offset = 0;
    for (GLsizei index = 0; index < count; ++index)
    {
        size_t len = ((length && length[index] >= 0) ? length[index] : strlen(strings[index]));

        // Count trailing zeros
        uint32_t i = 1;
        while (i < len && strings[index][len - i] == 0)
        {
            i++;
        }

        // Don't copy trailing zeros
        len -= (i - 1);

        data.resize(offset + len);
        std::copy(strings[index], strings[index] + len, data.begin() + offset);
        offset += len;
    }

    data.push_back(0);
    paramCapture->data.emplace_back(std::move(data));
}

}  // namespace angle

namespace egl
{
angle::ParamCapture CaptureAttributeMap(const egl::AttributeMap &attribMap)
{
    // It is common for EGL entrypoints to take NULL attribute lists, for instance
    // eglCreateImage()
    if (attribMap.getType() == AttributeMapType::Invalid || attribMap.isEmpty())
    {
        angle::ParamCapture paramCapture("attrib_list", angle::ParamType::TEGLintPointer);
        paramCapture.value.EGLintPointerVal = nullptr;
        return paramCapture;
    }

    switch (attribMap.getType())
    {
        case AttributeMapType::Attrib:
        {
            angle::ParamCapture paramCapture("attrib_list", angle::ParamType::TEGLAttribPointer);
            if (attribMap.isEmpty())
            {
                paramCapture.value.EGLAttribPointerVal = nullptr;
            }
            else
            {
                std::vector<EGLAttrib> attribs;
                for (const auto &[key, value] : attribMap)
                {
                    attribs.push_back(key);
                    attribs.push_back(value);
                }
                attribs.push_back(EGL_NONE);

                angle::CaptureMemory(attribs.data(), attribs.size() * sizeof(EGLAttrib),
                                     &paramCapture);
            }
            return paramCapture;
        }

        case AttributeMapType::Int:
        {
            angle::ParamCapture paramCapture("attrib_list", angle::ParamType::TEGLintPointer);
            if (attribMap.isEmpty())
            {
                paramCapture.value.EGLintPointerVal = nullptr;
            }
            else
            {
                std::vector<EGLint> attribs;
                for (const auto &[key, value] : attribMap)
                {
                    attribs.push_back(static_cast<EGLint>(key));
                    attribs.push_back(static_cast<EGLint>(value));
                }
                attribs.push_back(EGL_NONE);

                angle::CaptureMemory(attribs.data(), attribs.size() * sizeof(EGLint),
                                     &paramCapture);
            }
            return paramCapture;
        }

        default:
            UNREACHABLE();
            return angle::ParamCapture();
    }
}
}  // namespace egl
