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

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 (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
