//
// 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/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
{

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)
        {
            callOut << "gClientArrays[" << param.arrayClientPointerIndex << "]";
        }
        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);
    }
}

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

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::GLCompressedTexImage2DRobustANGLE:
        case EntryPoint::GLCompressedTexImage3D:
        case EntryPoint::GLCompressedTexImage3DOES:
        case EntryPoint::GLCompressedTexImage3DRobustANGLE:
        case EntryPoint::GLCompressedTexSubImage2D:
        case EntryPoint::GLCompressedTexSubImage2DRobustANGLE:
        case EntryPoint::GLCompressedTexSubImage3D:
        case EntryPoint::GLCompressedTexSubImage3DOES:
        case EntryPoint::GLCompressedTexSubImage3DRobustANGLE:
        case EntryPoint::GLCopyTexImage2D:
        case EntryPoint::GLCopyTexSubImage2D:
        case EntryPoint::GLCopyTexSubImage3D:
        case EntryPoint::GLCopyTexSubImage3DOES:
        case EntryPoint::GLCopyTexture3DANGLE:
        case EntryPoint::GLCopyTextureCHROMIUM:
        case EntryPoint::GLTexImage2D:
        case EntryPoint::GLTexImage2DExternalANGLE:
        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)
{
    switch (call.entryPoint)
    {
        case EntryPoint::GLDispatchCompute:
        case EntryPoint::GLDispatchComputeIndirect:
            return true;
        default:
            return false;
    }
}

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

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

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

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

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_UNPACK_ALIGNMENT, 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)));
        ASSERT(eglImageAttribIter != resourceTracker->getImageToAttribTable().end());
        const egl::AttributeMap &attribs = eglImageAttribIter->second;

        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 and needs to be recreated first
                    eglImageID = {maxAccessedResourceIDs[ResourceIDType::Image] + 1};
                    for (std::vector<CallCapture> *calls : texSetupCalls)
                    {
                        egl::AttributeMap attribs = egl::AttributeMap::CreateFromIntArray(nullptr);
                        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.value)));
                        CaptureCustomCreateEGLImage(context, "CreateEGLImageKHR", desc.size.width,
                                                    desc.size.height, eglCreateImageKHRCall,
                                                    *calls);
                    }
                }
                // Pass the eglImage to the texture that is bound to GL_TEXTURE_EXTERNAL_OES target
                for (std::vector<CallCapture> *calls : texSetupCalls)
                {
                    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;

        if (renderbuffer->getSamples() > 0)
        {
            // Note: We could also use extensions if available.
            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()));
            }
        }

        // 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_TEXTURE_MIN_FILTER,
                                         sampler->getMinFilter()));
        }
        if (sampler->getMagFilter() != defaultSamplerState.getMagFilter())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_MAG_FILTER,
                                         sampler->getMagFilter()));
        }
        if (sampler->getWrapS() != defaultSamplerState.getWrapS())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_WRAP_S,
                                         sampler->getWrapS()));
        }
        if (sampler->getWrapR() != defaultSamplerState.getWrapR())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_WRAP_R,
                                         sampler->getWrapR()));
        }
        if (sampler->getWrapT() != defaultSamplerState.getWrapT())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_WRAP_T,
                                         sampler->getWrapT()));
        }
        if (sampler->getMinLod() != defaultSamplerState.getMinLod())
        {
            cap(CaptureSamplerParameterf(replayState, true, samplerID, GL_TEXTURE_MIN_LOD,
                                         sampler->getMinLod()));
        }
        if (sampler->getMaxLod() != defaultSamplerState.getMaxLod())
        {
            cap(CaptureSamplerParameterf(replayState, true, samplerID, GL_TEXTURE_MAX_LOD,
                                         sampler->getMaxLod()));
        }
        if (sampler->getCompareMode() != defaultSamplerState.getCompareMode())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_COMPARE_MODE,
                                         sampler->getCompareMode()));
        }
        if (sampler->getCompareFunc() != defaultSamplerState.getCompareFunc())
        {
            cap(CaptureSamplerParameteri(replayState, true, samplerID, GL_TEXTURE_COMPARE_FUNC,
                                         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);
    }

    // Capture EGL Sync Objects
    const egl::SyncMap &eglSyncMap = context->getDisplay()->getSyncsForCapture();
    for (const auto &eglSyncIter : eglSyncMap)
    {
        egl::SyncID eglSyncID    = {eglSyncIter.first};
        const egl::Sync *eglSync = eglSyncIter.second.get();
        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);
    }

    GLint contextUnpackAlignment = context->getState().getUnpackState().alignment;
    if (currentUnpackState.alignment != contextUnpackAlignment)
    {
        cap(CapturePixelStorei(replayState, true, GL_UNPACK_ALIGNMENT, 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;
}

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_UNPACK_ALIGNMENT, 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();
        if (stateDrawFramebuffer == stateReadFramebuffer)
        {
            if (currentDrawFramebuffer != stateDrawFramebuffer ||
                currentReadFramebuffer != stateReadFramebuffer)
            {
                CaptureBindFramebufferForContext(context, setupCalls, framebufferFuncs, replayState,
                                                 GL_FRAMEBUFFER, stateDrawFramebuffer);
                currentDrawFramebuffer = currentReadFramebuffer = stateDrawFramebuffer;
            }
        }
        else
        {
            if (currentDrawFramebuffer != stateDrawFramebuffer)
            {
                CaptureBindFramebufferForContext(context, setupCalls, framebufferFuncs, replayState,
                                                 GL_DRAW_FRAMEBUFFER, stateDrawFramebuffer);
                currentDrawFramebuffer = stateDrawFramebuffer;
            }

            if (currentReadFramebuffer != stateReadFramebuffer)
            {
                CaptureBindFramebufferForContext(context, setupCalls, framebufferFuncs, replayState,
                                                 GL_READ_FRAMEBUFFER, stateReadFramebuffer);
                currentReadFramebuffer = 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);
        }

        cap(CaptureMatrixMode(replayState, true, gl::MatrixType::Projection));
        for (angle::Mat4 projectionMatrix :
             apiState.gles1().getMatrixStack(gl::MatrixType::Projection))
        {
            cap(CapturePushMatrix(replayState, true));
            cap(CaptureLoadMatrixf(replayState, true, projectionMatrix.elements().data()));
        }

        cap(CaptureMatrixMode(replayState, true, gl::MatrixType::Modelview));
        for (angle::Mat4 modelViewMatrix :
             apiState.gles1().getMatrixStack(gl::MatrixType::Modelview))
        {
            cap(CapturePushMatrix(replayState, true));
            cap(CaptureLoadMatrixf(replayState, true, modelViewMatrix.elements().data()));
        }

        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.

    // 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))
    {
        const gl::BlendState &defaultBlendState = replayState.getBlendState();
        const gl::BlendState &currentBlendState = apiState.getBlendState();

        if (currentBlendState.blend != defaultBlendState.blend)
        {
            capCap(GL_BLEND, currentBlendState.blend);
        }

        if (currentBlendState.sourceBlendRGB != defaultBlendState.sourceBlendRGB ||
            currentBlendState.destBlendRGB != defaultBlendState.destBlendRGB ||
            currentBlendState.sourceBlendAlpha != defaultBlendState.sourceBlendAlpha ||
            currentBlendState.destBlendAlpha != defaultBlendState.destBlendAlpha)
        {
            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, currentBlendState.sourceBlendRGB,
                                     currentBlendState.destBlendRGB));
                Capture(&resetCalls[angle::EntryPoint::GLBlendFunc],
                        CaptureBlendFunc(replayState, true, currentBlendState.sourceBlendRGB,
                                         currentBlendState.destBlendRGB));
            }
            else
            {
                // Always use BlendFuncSeparate for non-GLES1 as it covers all cases
                cap(CaptureBlendFuncSeparate(replayState, true, currentBlendState.sourceBlendRGB,
                                             currentBlendState.destBlendRGB,
                                             currentBlendState.sourceBlendAlpha,
                                             currentBlendState.destBlendAlpha));
                Capture(&resetCalls[angle::EntryPoint::GLBlendFuncSeparate],
                        CaptureBlendFuncSeparate(
                            replayState, true, currentBlendState.sourceBlendRGB,
                            currentBlendState.destBlendRGB, currentBlendState.sourceBlendAlpha,
                            currentBlendState.destBlendAlpha));
            }
        }

        if (currentBlendState.blendEquationRGB != defaultBlendState.blendEquationRGB ||
            currentBlendState.blendEquationAlpha != defaultBlendState.blendEquationAlpha)
        {
            // Similarly to BlendFunc, using BlendEquation in some cases complicates Reset.
            cap(CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB,
                                             currentBlendState.blendEquationAlpha));
            Capture(
                &resetCalls[angle::EntryPoint::GLBlendEquationSeparate],
                CaptureBlendEquationSeparate(replayState, true, currentBlendState.blendEquationRGB,
                                             currentBlendState.blendEquationAlpha));
        }

        if (currentBlendState.colorMaskRed != defaultBlendState.colorMaskRed ||
            currentBlendState.colorMaskGreen != defaultBlendState.colorMaskGreen ||
            currentBlendState.colorMaskBlue != defaultBlendState.colorMaskBlue ||
            currentBlendState.colorMaskAlpha != defaultBlendState.colorMaskAlpha)
        {
            cap(CaptureColorMask(replayState, true,
                                 gl::ConvertToGLBoolean(currentBlendState.colorMaskRed),
                                 gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen),
                                 gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue),
                                 gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha)));
            Capture(&resetCalls[angle::EntryPoint::GLColorMask],
                    CaptureColorMask(replayState, true,
                                     gl::ConvertToGLBoolean(currentBlendState.colorMaskRed),
                                     gl::ConvertToGLBoolean(currentBlendState.colorMaskGreen),
                                     gl::ConvertToGLBoolean(currentBlendState.colorMaskBlue),
                                     gl::ConvertToGLBoolean(currentBlendState.colorMaskAlpha)));
        }
    }
    else
    {
        // Otherwise, we must use EXT_draw_buffers_indexed features to set them independently
        const gl::BlendStateExt &defaultBlend = replayState.getBlendStateExt();
        const gl::BlendStateExt &currentBlend = apiState.getBlendStateExt();

        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_PACK_ALIGNMENT, apiState.getPackAlignment()));
        currentPackState.alignment = apiState.getPackAlignment();
    }

    if (currentPackState.rowLength != apiState.getPackRowLength())
    {
        cap(CapturePixelStorei(replayState, true, GL_PACK_ROW_LENGTH, apiState.getPackRowLength()));
        currentPackState.rowLength = apiState.getPackRowLength();
    }

    if (currentPackState.skipRows != apiState.getPackSkipRows())
    {
        cap(CapturePixelStorei(replayState, true, GL_PACK_SKIP_ROWS, apiState.getPackSkipRows()));
        currentPackState.skipRows = apiState.getPackSkipRows();
    }

    if (currentPackState.skipPixels != apiState.getPackSkipPixels())
    {
        cap(CapturePixelStorei(replayState, true, GL_PACK_SKIP_PIXELS,
                               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_UNPACK_ROW_LENGTH,
                               apiState.getUnpackRowLength()));
        currentUnpackState.rowLength = apiState.getUnpackRowLength();
    }

    if (currentUnpackState.skipRows != apiState.getUnpackSkipRows())
    {
        cap(CapturePixelStorei(replayState, true, GL_UNPACK_SKIP_ROWS,
                               apiState.getUnpackSkipRows()));
        currentUnpackState.skipRows = apiState.getUnpackSkipRows();
    }

    if (currentUnpackState.skipPixels != apiState.getUnpackSkipPixels())
    {
        cap(CapturePixelStorei(replayState, true, GL_UNPACK_SKIP_PIXELS,
                               apiState.getUnpackSkipPixels()));
        currentUnpackState.skipPixels = apiState.getUnpackSkipPixels();
    }

    if (currentUnpackState.imageHeight != apiState.getUnpackImageHeight())
    {
        cap(CapturePixelStorei(replayState, true, GL_UNPACK_IMAGE_HEIGHT,
                               apiState.getUnpackImageHeight()));
        currentUnpackState.imageHeight = apiState.getUnpackImageHeight();
    }

    if (currentUnpackState.skipImages != apiState.getUnpackSkipImages())
    {
        cap(CapturePixelStorei(replayState, true, GL_UNPACK_SKIP_IMAGES,
                               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_UNPACK_ALIGNMENT, contextUnpackAlignment));
        replayState.getMutablePrivateStateForCapture()->setUnpackAlignment(contextUnpackAlignment);
    }

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

bool SkipCall(EntryPoint entryPoint)
{
    switch (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)
{
    gl::BufferID bufferId;
    if (!context->createBuffer(&bufferId))
    {
        ERR() << "Failed to allocate buffer ID.";
    }

    gl::BufferBinding targetPacked = gl::BufferBinding::Array;
    context->bindBuffer(targetPacked, bufferId);

    // Allocate 2 pages so we will always have a full aligned page to protect
    GLsizei size = static_cast<GLsizei>(mPageSize * 2);

    context->bufferStorage(targetPacked, size, nullptr,
                           GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT |
                               GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);

    gl::Buffer *buffer = context->getBuffer(bufferId);

    angle::Result result = buffer->mapRange(
        context, 0, size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
    if (result != angle::Result::Continue)
    {
        ERR() << "Failed to mapRange of buffer.";
    }

    void *map = buffer->getMapPointer();
    if (map == nullptr)
    {
        ERR() << "Failed to getMapPointer of buffer.";
    }

    // Test mprotect
    auto start = reinterpret_cast<uintptr_t>(map);

    // Only protect a whole page inside the allocated memory
    uintptr_t protectionStart = rx::roundUpPow2(start, mPageSize);
    uintptr_t protectionEnd   = protectionStart + mPageSize;

    ASSERT(protectionStart < protectionEnd);

    angle::PageFaultCallback callback = [](uintptr_t address) {
        return angle::PageFaultHandlerRangeType::InRange;
    };

    std::unique_ptr<angle::PageFaultHandler> handler(CreatePageFaultHandler(callback));

    if (!handler->enable())
    {
        GLboolean unmapResult;
        if (buffer->unmap(context, &unmapResult) != angle::Result::Continue)
        {
            ERR() << "Could not unmap buffer.";
        }
        context->bindBuffer(targetPacked, {0});

        // Page fault handler could not be enabled, memory can't be protected directly.
        return false;
    }

    size_t protectionSize = protectionEnd - protectionStart;

    ASSERT(protectionSize == mPageSize);

    bool canProtect = angle::ProtectMemory(protectionStart, protectionSize);
    if (canProtect)
    {
        angle::UnprotectMemory(protectionStart, protectionSize);
    }

    // Clean up
    handler->disable();

    GLboolean unmapResult;
    if (buffer->unmap(context, &unmapResult) != angle::Result::Continue)
    {
        ERR() << "Could not unmap buffer.";
    }
    context->bindBuffer(targetPacked, {0});
    context->deleteBuffer(buffer->id());

    return canProtect;
}

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

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;
        }
        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:
        {
            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())
            {
                mClientVertexArrayMap[index] = static_cast<int>(mFrameCalls.size());
            }
            else
            {
                mClientVertexArrayMap[index] = -1;
            }
            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);
            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:
        {
            if (isCaptureActive())
            {
                context->getFrameCapture()->getStateResetHelper().setEntryPointDirty(
                    EntryPoint::GLBlendFunc);
            }
            break;
        }
        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;
            mResourceTracker.getTextureIDToImageTable().insert(std::pair<GLuint, egl::ImageID>(
                context->getState().getTargetTexture(target)->getId(), 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;
                }
            }

            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);
            }
            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 (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.entryPoint))
    {
        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::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;
        }
        default:
            break;
    }
}

void FrameCaptureShared::captureClientArraySnapshot(const gl::Context *context,
                                                    size_t vertexCount,
                                                    size_t instanceCount)
{
    if (vertexCount == 0)
    {
        // Nothing to capture
        return;
    }

    const gl::VertexArray *vao = context->getState().getVertexArray();

    // Capture client array data.
    for (size_t attribIndex : context->getActiveClientAttribsMask())
    {
        const gl::VertexAttribute &attrib = vao->getVertexAttribute(attribIndex);
        const gl::VertexBinding &binding  = vao->getVertexBinding(attrib.bindingIndex);

        int callIndex = mClientVertexArrayMap[attribIndex];

        if (callIndex != -1)
        {
            size_t count = vertexCount;

            if (binding.getDivisor() > 0)
            {
                count = rx::UnsignedCeilDivide(static_cast<uint32_t>(instanceCount),
                                               binding.getDivisor());
            }

            // The last capture element doesn't take up the full stride.
            size_t bytesToCapture = (count - 1) * binding.getStride() + attrib.format->pixelBytes;

            CallCapture &call   = mFrameCalls[callIndex];
            ParamCapture &param = call.params.getClientArrayPointerParameter();
            ASSERT(param.type == ParamType::TvoidConstPointer);

            ParamBuffer updateParamBuffer;
            updateParamBuffer.addValueParam<GLint>("arrayIndex", ParamType::TGLint,
                                                   static_cast<uint32_t>(attribIndex));

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

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

            mFrameCalls.emplace_back("UpdateClientArrayPointer", std::move(updateParamBuffer));

            mClientArraySizes[attribIndex] =
                std::max(mClientArraySizes[attribIndex], bytesToCapture);
        }
    }
}

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

    for (auto shareContext : shareGroup->getContexts())
    {
        FrameCapture *frameCapture = shareContext.second->getFrameCapture();
        ASSERT(frameCapture->getSetupCalls().empty());

        if (shareContext.second->id() == mainContext->id())
        {
            CaptureMidExecutionSetup(shareContext.second, &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.second->getState();
            gl::State auxContextReplayState(nullptr, 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.second);

            egl::Error error = shareContext.second->makeCurrent(display, draw, read);
            if (error.isError())
            {
                INFO() << "MEC unable to make secondary context current";
            }

            CaptureMidExecutionSetup(shareContext.second, &frameCapture->getSetupCalls(),
                                     frameCapture->getStateResetHelper(), &mShareGroupSetupCalls,
                                     &mResourceIDToSetupCalls, &mResourceTracker,
                                     auxContextReplayState, mValidateSerializedState);

            scanSetupCalls(frameCapture->getSetupCalls());

            WriteAuxiliaryContextCppSetupReplay(
                mReplayWriter, mCompression, mOutDirectory, shareContext.second, mCaptureLabel, 1,
                frameCapture->getSetupCalls(), &mBinaryData, mSerializeStateEnabled, *this,
                &mResourceIDBufferSize);
        }
        // Track that this context was created before MEC started
        mActiveContexts.insert(shareContext.first);
    }

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

    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 and color space of the draw surface as provided to makeCurrent
    SurfaceParams &params = mDrawSurfaceParams[context->id()];
    params.extents        = gl::Extents(surfaceWidth, surfaceHeight, 1);
    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)
{
    static const gl::BlendState kDefaultBlendState;

    // 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:
        {
            Capture(&mResetCalls[angle::EntryPoint::GLBlendFunc],
                    CaptureBlendFunc(context->getState(), true, kDefaultBlendState.sourceBlendRGB,
                                     kDefaultBlendState.destBlendRGB));
            break;
        }
        case angle::EntryPoint::GLBlendFuncSeparate:
        {
            Capture(&mResetCalls[angle::EntryPoint::GLBlendFuncSeparate],
                    CaptureBlendFuncSeparate(
                        context->getState(), true, kDefaultBlendState.sourceBlendRGB,
                        kDefaultBlendState.destBlendRGB, kDefaultBlendState.sourceBlendAlpha,
                        kDefaultBlendState.destBlendAlpha));
            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,
                                                 kDefaultBlendState.blendEquationRGB,
                                                 kDefaultBlendState.blendEquationAlpha));
            break;
        }
        case angle::EntryPoint::GLColorMask:
        {
            Capture(&mResetCalls[angle::EntryPoint::GLColorMask],
                    CaptureColorMask(context->getState(), true,
                                     gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskRed),
                                     gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskGreen),
                                     gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskBlue),
                                     gl::ConvertToGLBoolean(kDefaultBlendState.colorMaskAlpha)));
            break;
        }
        case angle::EntryPoint::GLBlendColor:
        {
            Capture(&mResetCalls[angle::EntryPoint::GLBlendColor],
                    CaptureBlendColor(context->getState(), true, 0, 0, 0, 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("IsBinaryDataCompressed", mCompression);
    json.addBool("AreClientArraysEnabled", glState.areClientArraysEnabled());
    json.addBool("IsBindGeneratesResourcesEnabled", glState.isBindGeneratesResourceEnabled());
    json.addBool("IsWebGLCompatibilityEnabled", glState.isWebGL());
    json.addBool("IsRobustResourceInitEnabled", glState.isRobustResourceInitEnabled());
    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::ContextMap &shareContextMap = shareGroup->getContexts();
            for (auto shareContext : shareContextMap)
            {
                if (shareContext.first == context->id().value)
                {
                    if (usesMidExecutionCapture())
                    {
                        // Setup the presentation (this) context last
                        outMainContextSetupCall
                            << "    " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Call)
                            << ";\n";
                        outMainContextSetupCall << "\n";
                    }

                    continue;
                }

                // 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.first) != 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.first << ");\n";

                        out << "    "
                            << FmtSetupFunction(kNoPartId, shareContext.second->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);
                }

                // 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 handle,
                                              gl::UniformBlockIndex uniformBlockIndex,
                                              GLenum pname,
                                              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 (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
    {
        gl::Program *program = GetProgramForCapture(glState, handle);
        if (program)
        {
            gl::QueryActiveUniformBlockiv(program, uniformBlockIndex,
                                          GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &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)
{
    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
