//
// 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 implementation.
//

#include "libANGLE/capture/FrameCapture.h"

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

#include "sys/stat.h"

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

// TODO: Consolidate to C output and remove option. http://anglebug.com/7753

constexpr char kEnabledVarName[]        = "ANGLE_CAPTURE_ENABLED";
constexpr char kOutDirectoryVarName[]   = "ANGLE_CAPTURE_OUT_DIR";
constexpr char kFrameStartVarName[]     = "ANGLE_CAPTURE_FRAME_START";
constexpr char kFrameEndVarName[]       = "ANGLE_CAPTURE_FRAME_END";
constexpr char kTriggerVarName[]        = "ANGLE_CAPTURE_TRIGGER";
constexpr char kCaptureLabelVarName[]   = "ANGLE_CAPTURE_LABEL";
constexpr char kCompressionVarName[]    = "ANGLE_CAPTURE_COMPRESSION";
constexpr char kSerializeStateVarName[] = "ANGLE_CAPTURE_SERIALIZE_STATE";
constexpr char kValidationVarName[]     = "ANGLE_CAPTURE_VALIDATION";
constexpr char kValidationExprVarName[] = "ANGLE_CAPTURE_VALIDATION_EXPR";
constexpr char kTrimEnabledVarName[]    = "ANGLE_CAPTURE_TRIM_ENABLED";
constexpr char kSourceExtVarName[]      = "ANGLE_CAPTURE_SOURCE_EXT";
constexpr char kSourceSizeVarName[]     = "ANGLE_CAPTURE_SOURCE_SIZE";
constexpr char kForceShadowVarName[]    = "ANGLE_CAPTURE_FORCE_SHADOW";

constexpr size_t kBinaryAlignment   = 16;
constexpr size_t kFunctionSizeLimit = 5000;

// Limit based on MSVC Compiler Error C2026
constexpr size_t kStringLengthLimit = 16380;

// Default limit to number of bytes in a capture source files.
constexpr char kDefaultSourceFileExt[]           = "cpp";
constexpr size_t kDefaultSourceFileSizeThreshold = 400000;

// Android debug properties that correspond to the above environment variables
constexpr char kAndroidEnabled[]        = "debug.angle.capture.enabled";
constexpr char kAndroidOutDir[]         = "debug.angle.capture.out_dir";
constexpr char kAndroidFrameStart[]     = "debug.angle.capture.frame_start";
constexpr char kAndroidFrameEnd[]       = "debug.angle.capture.frame_end";
constexpr char kAndroidTrigger[]        = "debug.angle.capture.trigger";
constexpr char kAndroidCaptureLabel[]   = "debug.angle.capture.label";
constexpr char kAndroidCompression[]    = "debug.angle.capture.compression";
constexpr char kAndroidValidation[]     = "debug.angle.capture.validation";
constexpr char kAndroidValidationExpr[] = "debug.angle.capture.validation_expr";
constexpr char kAndroidTrimEnabled[]    = "debug.angle.capture.trim_enabled";
constexpr char kAndroidSourceExt[]      = "debug.angle.capture.source_ext";
constexpr char kAndroidSourceSize[]     = "debug.angle.capture.source_size";
constexpr char kAndroidForceShadow[]    = "debug.angle.capture.force_shadow";

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 GetDefaultOutDirectory()
{
#if defined(ANGLE_PLATFORM_ANDROID)
    std::string path = "/sdcard/Android/data/";

    // Linux interface to get application id of the running process
    FILE *cmdline = fopen("/proc/self/cmdline", "r");
    char applicationId[512];
    if (cmdline)
    {
        fread(applicationId, 1, sizeof(applicationId), cmdline);
        fclose(cmdline);

        // Some package may have application id as <app_name>:<cmd_name>
        char *colonSep = strchr(applicationId, ':');
        if (colonSep)
        {
            *colonSep = '\0';
        }
    }
    else
    {
        ERR() << "not able to lookup application id";
    }

    constexpr char kAndroidOutputSubdir[] = "/angle_capture/";
    path += std::string(applicationId) + kAndroidOutputSubdir;

    // Check for existence of output path
    struct stat dir_stat;
    if (stat(path.c_str(), &dir_stat) == -1)
    {
        ERR() << "Output directory '" << path
              << "' does not exist.  Create it over adb using mkdir.";
    }

    return path;
#else
    return std::string("./");
#endif  // defined(ANGLE_PLATFORM_ANDROID)
}

std::string GetCaptureTrigger()
{
    // Use the GetAndSet variant to improve future lookup times
    return GetAndSetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger);
}

std::ostream &operator<<(std::ostream &os, gl::ContextID contextId)
{
    os << static_cast<int>(contextId.value);
    return os;
}

// Used to indicate that "shared" should be used to identify the files.
constexpr gl::ContextID kSharedContextId = {0};
// Used to indicate no context ID should be output.
constexpr gl::ContextID kNoContextId = {std::numeric_limits<uint32_t>::max()};

struct FmtCapturePrefix
{
    FmtCapturePrefix(gl::ContextID contextIdIn, const std::string &captureLabelIn)
        : contextId(contextIdIn), captureLabel(captureLabelIn)
    {}
    gl::ContextID contextId;
    const std::string &captureLabel;
};

std::ostream &operator<<(std::ostream &os, const FmtCapturePrefix &fmt)
{
    if (fmt.captureLabel.empty())
    {
        os << "angle_capture";
    }
    else
    {
        os << fmt.captureLabel;
    }

    if (fmt.contextId == kSharedContextId)
    {
        os << "_shared";
    }

    return os;
}

enum class ReplayFunc
{
    Replay,
    Setup,
    Reset,
};

constexpr uint32_t kNoPartId = std::numeric_limits<uint32_t>::max();

// In C, when you declare or define a function that takes no parameters, you must explicitly say the
// function takes "void" parameters. When you're calling the function you omit this void. It's
// therefore necessary to know how we're using a function to know if we should emi the "void".
enum FuncUsage
{
    Prototype,
    Definition,
    Call,
};

std::ostream &operator<<(std::ostream &os, FuncUsage usage)
{
    os << "(";
    if (usage != FuncUsage::Call)
    {
        os << "void";
    }
    os << ")";
    return os;
}

struct FmtReplayFunction
{
    FmtReplayFunction(gl::ContextID contextIdIn,
                      FuncUsage usageIn,
                      uint32_t frameIndexIn,
                      uint32_t partIdIn = kNoPartId)
        : contextId(contextIdIn), usage(usageIn), frameIndex(frameIndexIn), partId(partIdIn)
    {}
    gl::ContextID contextId;
    FuncUsage usage;
    uint32_t frameIndex;
    uint32_t partId;
};

std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt)
{
    os << "Replay";

    if (fmt.contextId == kSharedContextId)
    {
        os << "Shared";
    }

    os << "Frame" << fmt.frameIndex;

    if (fmt.partId != kNoPartId)
    {
        os << "Part" << fmt.partId;
    }
    os << fmt.usage;
    return os;
}

struct FmtSetupFunction
{
    FmtSetupFunction(uint32_t partIdIn, gl::ContextID contextIdIn, FuncUsage usageIn)
        : partId(partIdIn), contextId(contextIdIn), usage(usageIn)
    {}

    uint32_t partId;
    gl::ContextID contextId;
    FuncUsage usage;
};

std::ostream &operator<<(std::ostream &os, const FmtSetupFunction &fmt)
{
    os << "SetupReplayContext";

    if (fmt.contextId == kSharedContextId)
    {
        os << "Shared";
    }
    else
    {
        os << fmt.contextId;
    }

    if (fmt.partId != kNoPartId)
    {
        os << "Part" << fmt.partId;
    }
    os << fmt.usage;
    return os;
}

struct FmtResetFunction
{
    FmtResetFunction(uint32_t partIdIn, gl::ContextID contextIdIn, FuncUsage usageIn)
        : partId(partIdIn), contextId(contextIdIn), usage(usageIn)
    {}

    uint32_t partId;
    gl::ContextID contextId;
    FuncUsage usage;
};

std::ostream &operator<<(std::ostream &os, const FmtResetFunction &fmt)
{
    os << "ResetReplayContext";

    if (fmt.contextId == kSharedContextId)
    {
        os << "Shared";
    }
    else
    {
        os << fmt.contextId;
    }

    if (fmt.partId != kNoPartId)
    {
        os << "Part" << fmt.partId;
    }
    os << fmt.usage;
    return os;
}

struct FmtFunction
{
    FmtFunction(ReplayFunc funcTypeIn,
                gl::ContextID contextIdIn,
                FuncUsage usageIn,
                uint32_t frameIndexIn,
                uint32_t partIdIn)
        : funcType(funcTypeIn),
          contextId(contextIdIn),
          usage(usageIn),
          frameIndex(frameIndexIn),
          partId(partIdIn)
    {}

    ReplayFunc funcType;
    gl::ContextID contextId;
    FuncUsage usage;
    uint32_t frameIndex;
    uint32_t partId;
};

std::ostream &operator<<(std::ostream &os, const FmtFunction &fmt)
{
    switch (fmt.funcType)
    {
        case ReplayFunc::Replay:
            os << FmtReplayFunction(fmt.contextId, fmt.usage, fmt.frameIndex, fmt.partId);
            break;

        case ReplayFunc::Setup:
            os << FmtSetupFunction(fmt.partId, fmt.contextId, fmt.usage);
            break;

        case ReplayFunc::Reset:
            os << FmtResetFunction(fmt.partId, fmt.contextId, fmt.usage);
            break;

        default:
            UNREACHABLE();
            break;
    }

    return os;
}

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
    {
        out << std::setprecision(16);
        out << value;
    }
}

template <typename T, typename CastT = T>
void WriteInlineData(const std::vector<uint8_t> &vec, std::ostream &out)
{
    const T *data = reinterpret_cast<const T *>(vec.data());
    size_t count  = vec.size() / sizeof(T);

    if (data == nullptr)
    {
        return;
    }

    out << static_cast<CastT>(data[0]);

    for (size_t dataIndex = 1; dataIndex < count; ++dataIndex)
    {
        out << ", " << static_cast<CastT>(data[dataIndex]);
    }
}

template <>
void WriteInlineData<GLchar>(const std::vector<uint8_t> &vec, std::ostream &out)
{
    const GLchar *data = reinterpret_cast<const GLchar *>(vec.data());
    size_t count       = vec.size() / sizeof(GLchar);

    if (data == nullptr || data[0] == '\0')
    {
        return;
    }

    out << "\"";

    for (size_t dataIndex = 0; dataIndex < count; ++dataIndex)
    {
        if (data[dataIndex] == '\0')
            break;

        out << static_cast<GLchar>(data[dataIndex]);
    }

    out << "\"";
}

// For compatibility with C, which does not have multi-line string literals, we break strings up
// into multiple lines like:
//
//   const char *str[] = {
//   "multiple\n"
//   "line\n"
//   "strings may have \"quotes\"\n"
//   "and \\slashes\\\n",
//   };
//
// Note we need to emit extra escapes to ensure quotes and other special characters are preserved.
struct FmtMultiLineString
{
    FmtMultiLineString(const std::string &str) : strings()
    {
        std::string str2;

        // Strip any carriage returns before splitting, for consistency
        if (str.find("\r") != std::string::npos)
        {
            // str is const, so have to make a copy of it first
            str2 = str;
            ReplaceAllSubstrings(&str2, "\r", "");
        }

        strings =
            angle::SplitString(str2.empty() ? str : str2, "\n", WhitespaceHandling::KEEP_WHITESPACE,
                               SplitResult::SPLIT_WANT_ALL);
    }

    std::vector<std::string> strings;
};

std::string EscapeString(const std::string &string)
{
    std::stringstream strstr;

    for (char c : string)
    {
        if (c == '\"' || c == '\\')
        {
            strstr << "\\";
        }
        strstr << c;
    }

    return strstr.str();
}

std::ostream &operator<<(std::ostream &ostr, const FmtMultiLineString &fmt)
{
    ASSERT(!fmt.strings.empty());
    bool first = true;
    for (const std::string &string : fmt.strings)
    {
        if (first)
        {
            first = false;
        }
        else
        {
            ostr << "\\n\"\n";
        }

        ostr << "\"" << EscapeString(string);
    }

    ostr << "\"";

    return ostr;
}

void WriteStringParamReplay(ReplayWriter &replayWriter,
                            std::ostream &out,
                            std::ostream &header,
                            const CallCapture &call,
                            const ParamCapture &param,
                            std::vector<uint8_t> *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.
        size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment);
        binaryData->resize(offset + str.size() + 1);
        memcpy(binaryData->data() + offset, str.data(), str.size() + 1);
        out << "(const char *)&gBinaryData[" << 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 << "\"";
    }
}

void WriteStringPointerParamReplay(ReplayWriter &replayWriter,
                                   std::ostream &out,
                                   std::ostream &header,
                                   const CallCapture &call,
                                   const ParamCapture &param)
{
    // Concatenate the strings to ensure we get an accurate counter
    std::vector<std::string> strings;
    for (const std::vector<uint8_t> &data : param.data)
    {
        // null terminate C style string
        ASSERT(data.size() > 0 && data.back() == '\0');
        strings.emplace_back(data.begin(), data.end() - 1);
    }

    bool isNewEntry     = false;
    std::string varName = replayWriter.getInlineStringSetVariableName(call.entryPoint, param.name,
                                                                      strings, &isNewEntry);

    if (isNewEntry)
    {
        header << "const char *const " << varName << "[] = { \n";

        for (const std::string &str : strings)
        {
            // Break up long strings for MSVC
            size_t copyLength = 0;
            std::string separator;
            for (size_t i = 0; i < str.length(); i += kStringLengthLimit)
            {
                if ((str.length() - i) <= kStringLengthLimit)
                {
                    copyLength = str.length() - i;
                    separator  = ",";
                }
                else
                {
                    copyLength = kStringLengthLimit;
                    separator  = "";
                }

                header << FmtMultiLineString(str.substr(i, copyLength)) << separator << "\n";
            }
        }

        header << "};\n";
    }

    out << varName;
}

enum class Indent
{
    Indent,
    NoIdent,
};

void UpdateResourceIDBuffer(std::ostream &out,
                            Indent indent,
                            size_t bufferIndex,
                            const char *mapName,
                            GLuint resourceID)
{
    if (indent == Indent::Indent)
    {
        out << "    ";
    }
    out << "UpdateResourceIDBuffer(" << bufferIndex << ", g" << mapName << "Map[" << 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);
    const char *name = GetResourceIDTypeName(resourceIDType);

    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, name, id.value);
        }

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

    out << "gResourceIDBuffer";
}

void WriteBinaryParamReplay(ReplayWriter &replayWriter,
                            std::ostream &out,
                            std::ostream &header,
                            const CallCapture &call,
                            const ParamCapture &param,
                            std::vector<uint8_t> *binaryData)
{
    std::string varName = replayWriter.getInlineVariableName(call.entryPoint, param.name);

    ASSERT(param.data.size() == 1);
    const std::vector<uint8_t> &data = param.data[0];

    // Only inline strings (shaders) to simplify the C code.
    ParamType overrideType = param.type;
    if (param.type == ParamType::TvoidConstPointer)
    {
        overrideType = ParamType::TGLubyteConstPointer;
    }
    if (overrideType == ParamType::TGLcharPointer)
    {
        // Inline if data is of type string
        std::string paramTypeString = ParamTypeToString(param.type);
        header << paramTypeString.substr(0, paramTypeString.length() - 1) << varName << "[] = { ";
        WriteInlineData<GLchar>(data, header);
        header << " };\n";
        out << varName;
    }
    else
    {
        // Store in binary file if data are not of type string
        // Round up to 16-byte boundary for cross ABI safety
        size_t offset = rx::roundUpPow2(binaryData->size(), kBinaryAlignment);
        binaryData->resize(offset + data.size());
        memcpy(binaryData->data() + offset, data.data(), data.size());
        out << "(" << ParamTypeToString(overrideType) << ")&gBinaryData[" << offset << "]";
    }
}

void WriteCppReplayForCall(const CallCapture &call,
                           ReplayWriter &replayWriter,
                           std::ostream &out,
                           std::ostream &header,
                           std::vector<uint8_t> *binaryData,
                           size_t *maxResourceIDBufferSize)
{
    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;
}

std::string GetBinaryDataFilePath(bool compression, const std::string &captureLabel)
{
    std::stringstream fnameStream;
    fnameStream << FmtCapturePrefix(kNoContextId, captureLabel) << ".angledata";
    if (compression)
    {
        fnameStream << ".gz";
    }
    return fnameStream.str();
}

void SaveBinaryData(bool compression,
                    const std::string &outDir,
                    gl::ContextID contextId,
                    const std::string &captureLabel,
                    const std::vector<uint8_t> &binaryData)
{
    std::string binaryDataFileName = GetBinaryDataFilePath(compression, captureLabel);
    std::string dataFilepath       = outDir + binaryDataFileName;

    SaveFileHelper saveData(dataFilepath);

    if (compression)
    {
        // Save compressed data.
        uLong uncompressedSize       = static_cast<uLong>(binaryData.size());
        uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize);

        std::vector<uint8_t> compressedData(expectedCompressedSize, 0);

        uLong compressedSize = expectedCompressedSize;
        int zResult = zlib_internal::GzipCompressHelper(compressedData.data(), &compressedSize,
                                                        binaryData.data(), uncompressedSize,
                                                        nullptr, nullptr);

        if (zResult != Z_OK)
        {
            FATAL() << "Error compressing binary data: " << zResult;
        }

        saveData.write(compressedData.data(), compressedSize);
    }
    else
    {
        saveData.write(binaryData.data(), binaryData.size());
    }
}

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 << "    // 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 << "    InitializeReplay4(\"" << binaryDataFileName << "\", " << maxClientArraySize << ", "
        << readBufferSize << ", " << resourceIDBufferSize << ", " << contextID;

    for (ResourceIDType resourceID : AllEnums<ResourceIDType>())
    {
        out << ", " << maxIDs[resourceID];
    }

    out << ");\n";
}

void DeleteResourcesInReset(std::stringstream &out,
                            const ResourceSet &newResources,
                            const ResourceSet &resourcesToDelete,
                            const char *resourceName,
                            size_t *maxResourceIDBufferSize)
{
    if (!newResources.empty() || !resourcesToDelete.empty())
    {
        size_t count = 0;

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

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

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

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

// TODO (http://anglebug.com/4599): Reset more state on frame loop
void MaybeResetResources(gl::ContextID contextID,
                         ResourceIDType resourceIDType,
                         ReplayWriter &replayWriter,
                         std::stringstream &out,
                         std::stringstream &header,
                         ResourceTracker *resourceTracker,
                         std::vector<uint8_t> *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, newBuffers, buffersToDelete, "Buffer",
                                   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";
                    }
                }
            }

            // Restore buffer bindings as seen during MEC
            std::vector<CallCapture> &bufferBindingCalls = resourceTracker->getBufferBindingCalls();
            for (CallCapture &call : bufferBindingCalls)
            {
                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, newFramebuffers, framebuffersToDelete, "Framebuffer",
                                   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, newRenderbuffers, renderbuffersToDelete, "Renderbuffer",
                                   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, newTextures, texturesToDelete, "Texture",
                                   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();
            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, newVertexArrays, vertexArraysToDelete, "VertexArray",
                                   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;
        }
        default:
            // TODO (http://anglebug.com/4599): 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,
                                std::vector<uint8_t> *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 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("UpdateCurrentProgram", std::move(paramBuffer));
}

bool ProgramNeedsReset(const gl::ContextID contextID,
                       ResourceTracker *resourceTracker,
                       gl::ShaderProgramID programID)
{
    // Check whether the program is listed in programs to regen or restore
    TrackedResource &trackedShaderPrograms =
        resourceTracker->getTrackedResource(contextID, 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;
    }

    return false;
}

void MaybeResetDefaultUniforms(std::stringstream &out,
                               ReplayWriter &replayWriter,
                               std::stringstream &header,
                               const gl::Context *context,
                               ResourceTracker *resourceTracker,
                               std::vector<uint8_t> *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->id(), 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)
        {
            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,
                                 std::vector<uint8_t> *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,
                            std::vector<uint8_t> *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
        for (const auto &call : resetCalls->at(entryPoint))
        {
            out << "    ";
            WriteCppReplayForCall(call, 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,
                                     std::vector<uint8_t> *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)
    {
        if (!call.isActive)
        {
            // Don't write setup calls for inactive resources
            continue;
        }

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

// 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,
                                         std::vector<uint8_t> *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,
                                   std::vector<uint8_t> *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);
    }

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

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

        replayWriter.setFilenamePattern(filenamePattern);
    }

    replayWriter.saveSetupFile();
}

ProgramSources GetAttachedProgramSources(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";
    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;
        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 std::vector<gl::LinkedUniform> &uniforms     = program->getState().getUniforms();
    const std::vector<gl::VariableLocation> &locations = program->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 = uniform.name;

            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.location == -1 ||
                           location == uniform.location + static_cast<int>(locationVar.arrayIndex));
                    continue;
                }

                if (uniform.isArrayOfArrays())
                {
                    UNIMPLEMENTED();
                }

                name  = gl::StripLastArrayIndex(name);
                count = uniform.arraySizes[0];
            }
        }

        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->getState().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::GLCompressedTexImage1D:
        case EntryPoint::GLCompressedTexImage2D:
        case EntryPoint::GLCompressedTexImage2DRobustANGLE:
        case EntryPoint::GLCompressedTexImage3D:
        case EntryPoint::GLCompressedTexImage3DOES:
        case EntryPoint::GLCompressedTexImage3DRobustANGLE:
        case EntryPoint::GLCompressedTexSubImage1D:
        case EntryPoint::GLCompressedTexSubImage2D:
        case EntryPoint::GLCompressedTexSubImage2DRobustANGLE:
        case EntryPoint::GLCompressedTexSubImage3D:
        case EntryPoint::GLCompressedTexSubImage3DOES:
        case EntryPoint::GLCompressedTexSubImage3DRobustANGLE:
        case EntryPoint::GLCompressedTextureSubImage1D:
        case EntryPoint::GLCompressedTextureSubImage2D:
        case EntryPoint::GLCompressedTextureSubImage3D:
        case EntryPoint::GLCopyTexImage1D:
        case EntryPoint::GLCopyTexImage2D:
        case EntryPoint::GLCopyTexSubImage1D:
        case EntryPoint::GLCopyTexSubImage2D:
        case EntryPoint::GLCopyTexSubImage3D:
        case EntryPoint::GLCopyTexSubImage3DOES:
        case EntryPoint::GLCopyTexture3DANGLE:
        case EntryPoint::GLCopyTextureCHROMIUM:
        case EntryPoint::GLCopyTextureSubImage1D:
        case EntryPoint::GLCopyTextureSubImage2D:
        case EntryPoint::GLCopyTextureSubImage3D:
        case EntryPoint::GLTexImage1D:
        case EntryPoint::GLTexImage2D:
        case EntryPoint::GLTexImage2DExternalANGLE:
        case EntryPoint::GLTexImage2DMultisample:
        case EntryPoint::GLTexImage2DRobustANGLE:
        case EntryPoint::GLTexImage3D:
        case EntryPoint::GLTexImage3DMultisample:
        case EntryPoint::GLTexImage3DOES:
        case EntryPoint::GLTexImage3DRobustANGLE:
        case EntryPoint::GLTexSubImage1D:
        case EntryPoint::GLTexSubImage2D:
        case EntryPoint::GLTexSubImage2DRobustANGLE:
        case EntryPoint::GLTexSubImage3D:
        case EntryPoint::GLTexSubImage3DOES:
        case EntryPoint::GLTexSubImage3DRobustANGLE:
        case EntryPoint::GLTextureSubImage1D:
        case EntryPoint::GLTextureSubImage2D:
        case EntryPoint::GLTextureSubImage3D:
        case EntryPoint::GLCopyImageSubData:
        case EntryPoint::GLCopyImageSubDataEXT:
        case EntryPoint::GLCopyImageSubDataOES:
            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::GLProgramUniform1d:
        case EntryPoint::GLProgramUniform1dv:
        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::GLProgramUniform2d:
        case EntryPoint::GLProgramUniform2dv:
        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::GLProgramUniform3d:
        case EntryPoint::GLProgramUniform3dv:
        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::GLProgramUniform4d:
        case EntryPoint::GLProgramUniform4dv:
        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::GLProgramUniformMatrix2dv:
        case EntryPoint::GLProgramUniformMatrix2fv:
        case EntryPoint::GLProgramUniformMatrix2fvEXT:
        case EntryPoint::GLProgramUniformMatrix2x3dv:
        case EntryPoint::GLProgramUniformMatrix2x3fv:
        case EntryPoint::GLProgramUniformMatrix2x3fvEXT:
        case EntryPoint::GLProgramUniformMatrix2x4dv:
        case EntryPoint::GLProgramUniformMatrix2x4fv:
        case EntryPoint::GLProgramUniformMatrix2x4fvEXT:
        case EntryPoint::GLProgramUniformMatrix3dv:
        case EntryPoint::GLProgramUniformMatrix3fv:
        case EntryPoint::GLProgramUniformMatrix3fvEXT:
        case EntryPoint::GLProgramUniformMatrix3x2dv:
        case EntryPoint::GLProgramUniformMatrix3x2fv:
        case EntryPoint::GLProgramUniformMatrix3x2fvEXT:
        case EntryPoint::GLProgramUniformMatrix3x4dv:
        case EntryPoint::GLProgramUniformMatrix3x4fv:
        case EntryPoint::GLProgramUniformMatrix3x4fvEXT:
        case EntryPoint::GLProgramUniformMatrix4dv:
        case EntryPoint::GLProgramUniformMatrix4fv:
        case EntryPoint::GLProgramUniformMatrix4fvEXT:
        case EntryPoint::GLProgramUniformMatrix4x2dv:
        case EntryPoint::GLProgramUniformMatrix4x2fv:
        case EntryPoint::GLProgramUniformMatrix4x2fvEXT:
        case EntryPoint::GLProgramUniformMatrix4x3dv:
        case EntryPoint::GLProgramUniformMatrix4x3fv:
        case EntryPoint::GLProgramUniformMatrix4x3fvEXT:
            return DefaultUniformType::SpecifiedProgram;

        case EntryPoint::GLUniform1d:
        case EntryPoint::GLUniform1dv:
        case EntryPoint::GLUniform1f:
        case EntryPoint::GLUniform1fv:
        case EntryPoint::GLUniform1i:
        case EntryPoint::GLUniform1iv:
        case EntryPoint::GLUniform1ui:
        case EntryPoint::GLUniform1uiv:
        case EntryPoint::GLUniform2d:
        case EntryPoint::GLUniform2dv:
        case EntryPoint::GLUniform2f:
        case EntryPoint::GLUniform2fv:
        case EntryPoint::GLUniform2i:
        case EntryPoint::GLUniform2iv:
        case EntryPoint::GLUniform2ui:
        case EntryPoint::GLUniform2uiv:
        case EntryPoint::GLUniform3d:
        case EntryPoint::GLUniform3dv:
        case EntryPoint::GLUniform3f:
        case EntryPoint::GLUniform3fv:
        case EntryPoint::GLUniform3i:
        case EntryPoint::GLUniform3iv:
        case EntryPoint::GLUniform3ui:
        case EntryPoint::GLUniform3uiv:
        case EntryPoint::GLUniform4d:
        case EntryPoint::GLUniform4dv:
        case EntryPoint::GLUniform4f:
        case EntryPoint::GLUniform4fv:
        case EntryPoint::GLUniform4i:
        case EntryPoint::GLUniform4iv:
        case EntryPoint::GLUniform4ui:
        case EntryPoint::GLUniform4uiv:
        case EntryPoint::GLUniformMatrix2dv:
        case EntryPoint::GLUniformMatrix2fv:
        case EntryPoint::GLUniformMatrix2x3dv:
        case EntryPoint::GLUniformMatrix2x3fv:
        case EntryPoint::GLUniformMatrix2x4dv:
        case EntryPoint::GLUniformMatrix2x4fv:
        case EntryPoint::GLUniformMatrix3dv:
        case EntryPoint::GLUniformMatrix3fv:
        case EntryPoint::GLUniformMatrix3x2dv:
        case EntryPoint::GLUniformMatrix3x2fv:
        case EntryPoint::GLUniformMatrix3x4dv:
        case EntryPoint::GLUniformMatrix3x4fv:
        case EntryPoint::GLUniformMatrix4dv:
        case EntryPoint::GLUniformMatrix4fv:
        case EntryPoint::GLUniformMatrix4x2dv:
        case EntryPoint::GLUniformMatrix4x2fv:
        case EntryPoint::GLUniformMatrix4x3dv:
        case EntryPoint::GLUniformMatrix4x3fv:
        case EntryPoint::GLUniformSubroutinesuiv:
            return DefaultUniformType::CurrentProgram;

        default:
            return DefaultUniformType::None;
    }
}

void CaptureFramebufferAttachment(std::vector<CallCapture> *setupCalls,
                                  const gl::State &replayState,
                                  const FramebufferCaptureFuncs &framebufferFuncs,
                                  const gl::FramebufferAttachment &attachment)
{
    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()));
        }
    }
    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 std::vector<gl::LinkedUniform> &uniforms = program->getState().getUniforms();

    for (const gl::LinkedUniform &uniform : uniforms)
    {
        std::string uniformName = uniform.name;

        int uniformCount = 1;
        if (uniform.isArray())
        {
            if (uniform.isArrayOfArrays())
            {
                UNIMPLEMENTED();
                continue;
            }

            uniformCount = uniform.arraySizes[0];
            uniformName  = gl::StripLastArrayIndex(uniformName);
        }

        gl::UniformLocation uniformLoc      = program->getUniformLocation(uniformName);
        const gl::UniformTypeInfo *typeInfo = uniform.typeInfo;
        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++)
            {
                program->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++)
                {
                    program->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++)
                {
                    program->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++)
                {
                    program->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();

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

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

        // 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 &&
                                 binding.getBuffer().get() == nullptr && attrib.pointer != nullptr;

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

                gl::BufferID bufferID = {0};
                if (buffer)
                {
                    bufferID = buffer->id();
                }
                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];

        if (binding.getBuffer().id().value != 0)
        {
            Capture(setupCalls,
                    CaptureBindVertexBuffer(*replayState, true, static_cast<GLuint>(bindingIndex),
                                            binding.getBuffer().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;
    }

    if (index.getType() == gl::TextureType::External)
    {
        // The generated glTexImage2D call is for creating the staging texture
        Capture(setupCalls,
                CaptureTexImage2D(*replayState, true, gl::TextureTarget::_2D, index.getLevelIndex(),
                                  format.internalFormat, desc.size.width, desc.size.height, 0,
                                  format.format, format.type, data));

        // For external textures, we're done
        return;
    }

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

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

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

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

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

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

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

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

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

void CaptureCustomCreateEGLImage(const char *name,
                                 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);
    params.addValueParam("image", ParamType::TGLuint, imageID.value);
    call.customFunctionName = name;
    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;

    // Compile with last linked sources.
    for (gl::ShaderType shaderType : program->getExecutable().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 :
         program->getState().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 = program->getState().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 sh::ShaderVariable &attrib : program->getState().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 (program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Vertex))
        {
            ASSERT(attrib.location != -1);
            Capture(setupCalls, CaptureBindAttribLocation(replayState, true, id,
                                                          static_cast<GLuint>(attrib.location),
                                                          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 (unsigned int uniformBlockIndex = 0;
         uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
    {
        GLuint blockBinding = program->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 : program->getExecutable().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/4599): 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)
{
    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 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
    );
}

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

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

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

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

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

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

            // create a staging GL_TEXTURE_2D texture to create the eglImage with
            gl::TextureID stagingTexId = {maxAccessedResourceIDs[ResourceIDType::Texture] + 1};
            if (index.getType() == gl::TextureType::External)
            {
                Capture(setupCalls, CaptureGenTextures(replayState, true, 1, &stagingTexId));
                MaybeCaptureUpdateResourceIDs(context, resourceTracker, setupCalls);
                Capture(setupCalls,
                        CaptureBindTexture(replayState, true, gl::TextureType::_2D, stagingTexId));
                Capture(setupCalls, CaptureTexParameteri(replayState, true, gl::TextureType::_2D,
                                                         GL_TEXTURE_MIN_FILTER, GL_NEAREST));
                Capture(setupCalls, CaptureTexParameteri(replayState, true, gl::TextureType::_2D,
                                                         GL_TEXTURE_MAG_FILTER, GL_NEAREST));
            }

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

                if (index.getType() == gl::TextureType::External)
                {
                    // Look up the attribs used when the image was created
                    // Firstly, lookup the eglImage ID associated with this texture when the app
                    // issued glEGLImageTargetTexture2DOES()
                    auto eglImageIter = resourceTracker->getTextureIDToImageTable().find(id.value);
                    ASSERT(eglImageIter != resourceTracker->getTextureIDToImageTable().end());

                    const egl::ImageID eglImageID = eglImageIter->second;
                    const EGLImage eglImage =
                        reinterpret_cast<EGLImage>(static_cast<uintptr_t>(eglImageID.value));

                    // Secondly, lookup the attrib we used to create the eglImage
                    auto eglImageAttribIter =
                        resourceTracker->getImageToAttribTable().find(eglImage);
                    ASSERT(eglImageAttribIter != resourceTracker->getImageToAttribTable().end());

                    const egl::AttributeMap &retrievedAttribs = eglImageAttribIter->second;

                    // Create the image on demand with the same attrib retrieved above
                    CallCapture eglCreateImageKHRCall = egl::CaptureCreateImageKHR(
                        nullptr, true, nullptr, context->id(), EGL_GL_TEXTURE_2D_KHR,
                        reinterpret_cast<EGLClientBuffer>(
                            static_cast<GLuint64>(stagingTexId.value)),
                        retrievedAttribs, eglImage);

                    // Convert the CaptureCreateImageKHR CallCapture to the customized CallCapture
                    std::vector<CallCapture> eglCustomCreateImageKHRCall;
                    CaptureCustomCreateEGLImage("CreateEGLImageKHR", eglCreateImageKHRCall,
                                                eglCustomCreateImageKHRCall);
                    ASSERT(eglCustomCreateImageKHRCall.size() > 0);

                    // Append the customized CallCapture to the setupCalls list
                    Capture(setupCalls, std::move(eglCustomCreateImageKHRCall[0]));

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

                    // Delete the staging texture
                    Capture(setupCalls, CaptureDeleteTextures(replayState, true, 1, &stagingTexId));
                }
            }
            else
            {
                for (std::vector<CallCapture> *calls : texSetupCalls)
                {
                    CaptureTextureContents(calls, &replayState, texture, index, desc, 0, nullptr);
                }
            }
        }
    }

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

    for (const auto &renderbufIter : renderbuffers)
    {
        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/3662
    }

    // 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()};
    for (const auto &programIter : programs)
    {
        gl::ShaderProgramID id = {programIter.first};
        gl::Program *program   = programIter.second;

        // Unlinked programs don't have an executable. Thus they don't need to be captured.
        // Programs are shared by contexts in the share group and only need to be captured once.
        if (!program->isLinked())
        {
            continue;
        }

        size_t programSetupStart = setupCalls->size();

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

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

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

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

        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 shaders to a non-linked
        // program. Or attaching uncompiled shaders. Or attaching and then deleting a shader.
        // TODO(jmadill): Handle trickier program uses. http://anglebug.com/3662
        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));
            }
        }

        size_t shaderSetupEnd = setupCalls->size();

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

        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 : samplers)
    {
        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 : syncs)
    {
        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;
        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,
                              CallResetMap &resetCalls,
                              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));

    // 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 : 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
    Capture(&resetCalls[angle::EntryPoint::GLBindVertexArray],
            vertexArrayFuncs.bindVertexArray(replayState, true, currentVertexArray->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.
        bool isArray                  = binding == gl::BufferBinding::Array;
        const gl::Buffer *arrayBuffer = replayState.getArrayBuffer();
        if ((isArray && arrayBuffer && arrayBuffer->id() != bufferID) ||
            (!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)
        {
            CaptureBufferBindingResetCalls(replayState, resourceTracker, 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();

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

    // 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 : renderbuffers)
    {
        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 : framebuffers)
    {
        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)
        {
            Capture(calls, framebufferFuncs.bindFramebuffer(replayState, true, 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);
            }
        }

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

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

        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)
            {
                cap(framebufferFuncs.bindFramebuffer(replayState, true, GL_FRAMEBUFFER,
                                                     stateDrawFramebuffer));
                currentDrawFramebuffer = currentReadFramebuffer = stateDrawFramebuffer;
            }
        }
        else
        {
            if (currentDrawFramebuffer != stateDrawFramebuffer)
            {
                cap(framebufferFuncs.bindFramebuffer(replayState, true, GL_DRAW_FRAMEBUFFER,
                                                     currentDrawFramebuffer));
                currentDrawFramebuffer = stateDrawFramebuffer;
            }

            if (currentReadFramebuffer != stateReadFramebuffer)
            {
                cap(framebufferFuncs.bindFramebuffer(replayState, true, GL_READ_FRAMEBUFFER,
                                                     replayState.getReadFramebuffer()->id()));
                currentReadFramebuffer = stateReadFramebuffer;
            }
        }
    }

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

    for (const auto &ppoIterator : *programPipelineManager)
    {
        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())
        {
            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/3662
    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}));
        }
    }

    // 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.
    const gl::QueryMap &queryMap = context->getQueriesForCapture();
    for (gl::QueryMap::Iterator queryIter = queryMap.beginWithNull();
         queryIter != queryMap.endWithNull(); ++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)
        {
            gl::QueryType queryType = query->getType();

            // Begin the query to generate the object
            cap(CaptureBeginQuery(replayState, true, queryType, queryID));

            // End the query if it was not active
            if (!IsQueryActive(apiState, queryID))
            {
                cap(CaptureEndQuery(replayState, true, queryType));
            }
        }
    }

    // Transform Feedback
    const gl::TransformFeedbackMap &xfbMap = context->getTransformFeedbacksForCapture();
    for (const auto &xfbIter : 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.
    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)));
    }

    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/3662): 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::GLGetActiveUniformName:
        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::EGLQuerySurface:
            // Skip these calls because:
            // - 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;
}

template <typename ParamValueType>
struct ParamValueTrait
{
    static_assert(sizeof(ParamValueType) == 0, "invalid ParamValueType");
};

template <>
struct ParamValueTrait<gl::FramebufferID>
{
    static constexpr const char *name = "framebufferPacked";
    static const ParamType typeID     = ParamType::TFramebufferID;
};

std::string GetBaseName(const std::string &nameWithPath)
{
    std::vector<std::string> result = angle::SplitString(
        nameWithPath, "/\\", WhitespaceHandling::TRIM_WHITESPACE, SplitResult::SPLIT_WANT_NONEMPTY);
    ASSERT(!result.empty());
    return result.back();
}

template <>
struct ParamValueTrait<gl::BufferID>
{
    static constexpr const char *name = "bufferPacked";
    static const ParamType typeID     = ParamType::TBufferID;
};

template <>
struct ParamValueTrait<gl::RenderbufferID>
{
    static constexpr const char *name = "renderbufferPacked";
    static const ParamType typeID     = ParamType::TRenderbufferID;
};

template <>
struct ParamValueTrait<gl::TextureID>
{
    static constexpr const char *name = "texturePacked";
    static const ParamType typeID     = ParamType::TTextureID;
};
}  // namespace

FrameCapture::FrameCapture()  = default;
FrameCapture::~FrameCapture() = default;

void FrameCapture::reset()
{
    mSetupCalls.clear();
}

FrameCaptureShared::FrameCaptureShared()
    : mLastContextId{0},
      mEnabled(true),
      mSerializeStateEnabled(false),
      mCompression(true),
      mClientVertexArrayMap{},
      mFrameIndex(1),
      mCaptureStartFrame(1),
      mCaptureEndFrame(0),
      mClientArraySizes{},
      mReadBufferSize(0),
      mResourceIDBufferSize(0),
      mHasResourceType{},
      mResourceIDToSetupCalls{},
      mMaxAccessedResourceIDs{},
      mCaptureTrigger(0),
      mCaptureActive(false),
      mWindowSurfaceContextID({0})
{
    reset();

    std::string enabledFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kEnabledVarName, kAndroidEnabled);
    if (enabledFromEnv == "0")
    {
        mEnabled = false;
    }

    std::string pathFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kOutDirectoryVarName, kAndroidOutDir);
    if (pathFromEnv.empty())
    {
        mOutDirectory = GetDefaultOutDirectory();
    }
    else
    {
        mOutDirectory = pathFromEnv;
    }

    // Ensure the capture path ends with a slash.
    if (mOutDirectory.back() != '\\' && mOutDirectory.back() != '/')
    {
        mOutDirectory += '/';
    }

    std::string startFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kFrameStartVarName, kAndroidFrameStart);
    if (!startFromEnv.empty())
    {
        mCaptureStartFrame = atoi(startFromEnv.c_str());
    }
    if (mCaptureStartFrame < 1)
    {
        WARN() << "Cannot use a capture start frame less than 1.";
        mCaptureStartFrame = 1;
    }

    std::string endFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kFrameEndVarName, kAndroidFrameEnd);
    if (!endFromEnv.empty())
    {
        mCaptureEndFrame = atoi(endFromEnv.c_str());
    }

    std::string captureTriggerFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kTriggerVarName, kAndroidTrigger);
    if (!captureTriggerFromEnv.empty())
    {
        mCaptureTrigger = atoi(captureTriggerFromEnv.c_str());

        // If the trigger has been populated, ignore the other frame range variables by setting them
        // to unreasonable values. This isn't perfect, but it is effective.
        mCaptureStartFrame = mCaptureEndFrame = std::numeric_limits<uint32_t>::max();
        INFO() << "Capture trigger detected, disabling capture start/end frame.";
    }

    std::string labelFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kCaptureLabelVarName, kAndroidCaptureLabel);
    if (!labelFromEnv.empty())
    {
        // Optional label to provide unique file names and namespaces
        mCaptureLabel = labelFromEnv;
    }

    std::string compressionFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kCompressionVarName, kAndroidCompression);
    if (compressionFromEnv == "0")
    {
        mCompression = false;
    }
    std::string serializeStateFromEnv = angle::GetEnvironmentVar(kSerializeStateVarName);
    if (serializeStateFromEnv == "1")
    {
        mSerializeStateEnabled = true;
    }

    std::string validateSerialiedStateFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kValidationVarName, kAndroidValidation);
    if (validateSerialiedStateFromEnv == "1")
    {
        mValidateSerializedState = true;
    }

    mValidationExpression =
        GetEnvironmentVarOrUnCachedAndroidProperty(kValidationExprVarName, kAndroidValidationExpr);

    if (!mValidationExpression.empty())
    {
        INFO() << "Validation expression is " << kValidationExprVarName;
    }

    std::string trimEnabledFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kTrimEnabledVarName, kAndroidTrimEnabled);
    if (trimEnabledFromEnv == "0")
    {
        mTrimEnabled = false;
    }

    // TODO: Remove. http://anglebug.com/7753
    std::string sourceExtFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kSourceExtVarName, kAndroidSourceExt);
    if (!sourceExtFromEnv.empty())
    {
        if (sourceExtFromEnv == "c" || sourceExtFromEnv == "cpp")
        {
            mReplayWriter.setSourceFileExtension(sourceExtFromEnv.c_str());
        }
        else
        {
            WARN() << "Invalid capture source extension: " << sourceExtFromEnv;
        }
    }

    std::string sourceSizeFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kSourceSizeVarName, kAndroidSourceSize);
    if (!sourceSizeFromEnv.empty())
    {
        int sourceSize = atoi(sourceSizeFromEnv.c_str());
        if (sourceSize < 0)
        {
            WARN() << "Invalid capture source size: " << sourceSize;
        }
        else
        {
            mReplayWriter.setSourceFileSizeThreshold(sourceSize);
        }
    }

    std::string forceShadowFromEnv =
        GetEnvironmentVarOrUnCachedAndroidProperty(kForceShadowVarName, kAndroidForceShadow);
    if (forceShadowFromEnv == "1")
    {
        INFO() << "Force enabling shadow memory for coherent buffer tracking.";
        mCoherentBufferTracker.enableShadowMemory();
    }

    if (mFrameIndex == mCaptureStartFrame)
    {
        // Capture is starting from the first frame, so set the capture active to ensure all GLES
        // commands issued are handled correctly by maybeCapturePreCallUpdates() and
        // maybeCapturePostCallUpdates().
        setCaptureActive();
    }

    if (mCaptureEndFrame < mCaptureStartFrame)
    {
        mEnabled = false;
    }

    mReplayWriter.setCaptureLabel(mCaptureLabel);
}

FrameCaptureShared::~FrameCaptureShared() = default;

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

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 = context->createBuffer();

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

CoherentBufferTracker::CoherentBufferTracker() : mEnabled(false), mShadowMemoryEnabled(false)
{
    mPageSize = GetPageSize();
}

CoherentBufferTracker::~CoherentBufferTracker()
{
    disable();
}

PageFaultHandlerRangeType CoherentBufferTracker::handleWrite(uintptr_t address)
{
    std::lock_guard<std::mutex> 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/7402): 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<std::mutex> lock(mMutex);

    if (!mEnabled)
    {
        return;
    }

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

    disable();
}

void CoherentBufferTracker::disable()
{
    if (!mEnabled)
    {
        return;
    }

    if (mPageFaultHandler->disable())
    {
        mEnabled = false;
    }
    else
    {
        ERR() << "Could not disable page fault handler.";
    }

    if (mShadowMemoryEnabled && mBuffers.size() > 0)
    {
        WARN() << "Disabling coherent buffer tracking while leaving shadow memory without "
                  "synchronization. Expect rendering artifacts after capture ends.";
    }
}

uintptr_t CoherentBufferTracker::addBuffer(gl::BufferID id, uintptr_t start, size_t size)
{
    std::lock_guard<std::mutex> 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<std::mutex> 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 (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)
{
    // 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 && isCaptureActive())
        {
            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);
}

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

    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::GLMapBuffer:
        {
            // Currently desktop GL is not implemented.
            UNREACHABLE();
            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:
        {
            CaptureCustomCreateEGLImage("CreateEGLImage", inCall, outCalls);
            break;
        }
        case EntryPoint::EGLCreateImageKHR:
        {
            CaptureCustomCreateEGLImage("CreateEGLImageKHR", 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;
        }
    }
}

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

    std::lock_guard<std::mutex> 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->getStateCache().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->getStateCache().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);
            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);
            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);
            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);
            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->getShader(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().hasAttachedShader())
            {
                setProgramSources(programID, GetAttachedProgramSources(program));
            }
            break;
        }

        case EntryPoint::GLCompressedTexImage1D:
        case EntryPoint::GLCompressedTexSubImage1D:
        {
            UNIMPLEMENTED();
            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::GLMapBuffer:
        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);
            break;
        }

        case EntryPoint::GLUnmapNamedBuffer:
        {
            UNIMPLEMENTED();
            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);
            break;
        }
        case EntryPoint::EGLCreateImageKHR:
        {
            CreateEGLImagePreCallUpdate<EGLint>(call, mResourceTracker, ParamType::TEGLintPointer,
                                                egl::AttributeMap::CreateFromIntArray);
            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 (isCaptureActive() && GetDefaultUniformType(call) != DefaultUniformType::None)
    {
        trackDefaultUniformUpdate(context, call);
    }

    if (IsVertexArrayUpdate(call))
    {
        trackVertexArrayUpdate(context, call);
    }

    updateReadBufferSize(call.params.getReadBufferSize());

    std::vector<gl::ShaderProgramID> shaderProgramIDs;
    if (FindShaderProgramIDsInCall(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);
            }
        }
    }
}

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";
        std::string updateFuncName = updateFuncNameStr.str();

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

        // Capture resource IDs for non-pointer types.
        if (strcmp(ParamTypeToString(param.type), "GLuint") == 0)
        {
            mMaxAccessedResourceIDs[idType] =
                std::max(mMaxAccessedResourceIDs[idType], 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)
                {
                    mMaxAccessedResourceIDs[idType] =
                        std::max(mMaxAccessedResourceIDs[idType], dataPtr[handleIndex]);
                }
            }
        }
        if (idType == ResourceIDType::Sync)
        {
            mMaxAccessedResourceIDs[idType] =
                std::max(mMaxAccessedResourceIDs[idType], 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)
    {
        // If the context ID has changed, then we need to inject an eglMakeCurrent() call. Only do
        // this if there is more than 1 context in the share group to avoid unnecessary
        // eglMakeCurrent() calls.
        size_t contextCount = context->getShareGroup()->getContexts().size();
        if (contextCount > 1 && mLastContextId != context->id())
        {
            // Inject the eglMakeCurrent() call. Ignore the display and surface.
            CallCapture makeCurrentCall =
                egl::CaptureMakeCurrent(nullptr, true, nullptr, {0}, {0}, context->id(), EGL_TRUE);
            mFrameCalls.emplace_back(std::move(makeCurrentCall));
            mLastContextId = context->id();
        }

        // Update resource counts before we override entry points with custom calls.
        updateResourceCountsFromCallCapture(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);
        }

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

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);
            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)
{
    const gl::VertexArray *vao = context->getState().getVertexArray();

    // Capture client array data.
    for (size_t attribIndex : context->getStateCache().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()
{
    // If the capture trigger has not been set, move on
    if (mCaptureTrigger == 0)
    {
        return;
    }

    // Otherwise, poll the value for a change
    std::string captureTriggerStr = GetCaptureTrigger();
    if (captureTriggerStr.empty())
    {
        return;
    }

    // If the value has changed, use the original value as the frame count
    // TODO (anglebug.com/4949): Improve capture at unknown frame time. It is good to
    // avoid polling if the feature is not enabled, but not entirely intuitive to set
    // a value to zero when you want to trigger it.
    uint32_t captureTrigger = atoi(captureTriggerStr.c_str());
    if (captureTrigger != mCaptureTrigger)
    {
        // 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;
    }
}

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, nullptr, contextState.getClientType(),
        contextState.getClientVersion(), contextState.getProfileMask(), false, true, true, true,
        false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG, contextState.hasRobustAccess(),
        contextState.hasProtectedContent());
    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().getResetCalls(),
                                     &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, nullptr,
                shareContextState.getClientType(), shareContextState.getClientVersion(),
                shareContextState.getProfileMask(), false, true, true, true, false,
                EGL_CONTEXT_PRIORITY_MEDIUM_IMG, shareContextState.hasRobustAccess(),
                shareContextState.hasProtectedContent());
            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().getResetCalls(),
                                     &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();
        mCoherentBufferTracker.onEndFrame();
        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();

    // Check for MEC. Done after checkForCaptureTrigger(), since that can modify mCaptureStartFrame.
    if (mFrameIndex < mCaptureStartFrame)
    {
        if (mFrameIndex == mCaptureStartFrame - 1)
        {
            // Trigger MEC.
            runMidExecutionCapture(context);
        }
        mFrameIndex++;
        reset();
        return;
    }

    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);
        SaveBinaryData(mCompression, mOutDirectory, kSharedContextId, mCaptureLabel, mBinaryData);
        mBinaryData.clear();
        mWroteIndexFile = true;
    }

    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);
        SaveBinaryData(mCompression, mOutDirectory, kSharedContextId, mCaptureLabel, mBinaryData);
        mBinaryData.clear();
        mWroteIndexFile = true;
    }
}

void FrameCaptureShared::onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface)
{
    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(drawSurface->getWidth(), drawSurface->getHeight(), 1);
    params.colorSpace     = egl::FromEGLenum<egl::ColorSpace>(drawSurface->getGLColorspace());
}

DataCounters::DataCounters() = default;

DataCounters::~DataCounters() = default;

int DataCounters::getAndIncrement(EntryPoint entryPoint, const std::string &paramName)
{
    Counter counterKey = {entryPoint, paramName};
    return mData[counterKey]++;
}

DataTracker::DataTracker() = default;

DataTracker::~DataTracker() = default;

StringCounters::StringCounters() = default;

StringCounters::~StringCounters() = default;

int StringCounters::getStringCounter(const std::vector<std::string> &strings)
{
    const auto &id = mStringCounterMap.find(strings);
    if (id == mStringCounterMap.end())
    {
        return kStringsNotFound;
    }
    else
    {
        return mStringCounterMap[strings];
    }
}

void StringCounters::setStringCounter(const std::vector<std::string> &strings, int &counter)
{
    ASSERT(counter >= 0);
    mStringCounterMap[strings] = counter;
}

TrackedResource::TrackedResource() = default;

TrackedResource::~TrackedResource() = default;

ResourceTracker::ResourceTracker() = default;

ResourceTracker::~ResourceTracker() = default;

StateResetHelper::StateResetHelper()  = default;
StateResetHelper::~StateResetHelper() = default;

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

bool FrameCaptureShared::isCapturing() const
{
    // Currently we will always do a capture up until the last frame. In the future we could improve
    // mid execution capture by only capturing between the start and end frames. The only necessary
    // reason we need to capture before the start is for attached program and shader sources.
    return mEnabled && mFrameIndex <= mCaptureEndFrame;
}

uint32_t FrameCaptureShared::getFrameCount() const
{
    return mCaptureEndFrame - mCaptureStartFrame + 1;
}

uint32_t FrameCaptureShared::getReplayFrameIndex() const
{
    return mFrameIndex - mCaptureStartFrame + 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)
{
    const gl::ContextID contextId           = context->id();
    const SurfaceParams &surfaceParams      = mDrawSurfaceParams.at(contextId);
    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->getClientMajorVersion());
    json.addScalar("ContextClientMinorVersion", context->getClientMinorVersion());
    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.addBool("IsTrimmingEnabled", mTrimEnabled);
    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();

    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;

            out << proto << "\n";
            out << "{\n";

            // Setup all of the shared objects.
            out << "    InitReplay();\n";
            if (usesMidExecutionCapture())
            {
                out << "    " << FmtSetupFunction(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 first.
                        out << "    " << FmtSetupFunction(kNoPartId, context->id(), FuncUsage::Call)
                            << ";\n";
                        out << "\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/5878): 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";
                    }
                }
            }

            // 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 << "}\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/5878): Look at moving this into the shared context file since
        // it's resetting shared objects.

        // TODO(http://anglebug.com/4599): 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->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(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\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";
        }

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

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

void FrameCaptureShared::reset()
{
    mFrameCalls.clear();
    mClientVertexArrayMap.fill(-1);

    // Do not reset replay-specific settings like the maximum read buffer size, client array sizes,
    // or the 'has seen' type map. We could refine this into per-frame and per-capture maximums if
    // necessary.
}

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)
{
    if (!mTrimEnabled)
    {
        return;
    }

    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 CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture)
{
    std::vector<uint8_t> data(size);
    memcpy(data.data(), source, size);
    paramCapture->data.emplace_back(std::move(data));
}

void CaptureString(const GLchar *str, ParamCapture *paramCapture)
{
    // include the '\0' suffix
    CaptureMemory(str, strlen(str) + 1, paramCapture);
}

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

// ReplayWriter implementation.
ReplayWriter::ReplayWriter()
    : mSourceFileExtension(kDefaultSourceFileExt),
      mSourceFileSizeThreshold(kDefaultSourceFileSizeThreshold),
      mFrameIndex(1)
{}

ReplayWriter::~ReplayWriter()
{
    ASSERT(mPrivateFunctionPrototypes.empty());
    ASSERT(mPublicFunctionPrototypes.empty());
    ASSERT(mPrivateFunctions.empty());
    ASSERT(mPublicFunctions.empty());
    ASSERT(mGlobalVariableDeclarations.empty());
    ASSERT(mReplayHeaders.empty());
}

void ReplayWriter::setSourceFileExtension(const char *ext)
{
    mSourceFileExtension = ext;
}

void ReplayWriter::setSourceFileSizeThreshold(size_t sourceFileSizeThreshold)
{
    mSourceFileSizeThreshold = sourceFileSizeThreshold;
}

void ReplayWriter::setFilenamePattern(const std::string &pattern)
{
    if (mFilenamePattern != pattern)
    {
        mFilenamePattern = pattern;
    }
}

void ReplayWriter::setCaptureLabel(const std::string &label)
{
    mCaptureLabel = label;
}

void ReplayWriter::setSourcePrologue(const std::string &prologue)
{
    mSourcePrologue = prologue;
}

void ReplayWriter::setHeaderPrologue(const std::string &prologue)
{
    mHeaderPrologue = prologue;
}

void ReplayWriter::addPublicFunction(const std::string &functionProto,
                                     const std::stringstream &headerStream,
                                     const std::stringstream &bodyStream)
{
    mPublicFunctionPrototypes.push_back(functionProto);

    std::string header = headerStream.str();
    std::string body   = bodyStream.str();

    if (!header.empty())
    {
        mReplayHeaders.emplace_back(header);
    }

    if (!body.empty())
    {
        mPublicFunctions.emplace_back(body);
    }
}

void ReplayWriter::addPrivateFunction(const std::string &functionProto,
                                      const std::stringstream &headerStream,
                                      const std::stringstream &bodyStream)
{
    mPrivateFunctionPrototypes.push_back(functionProto);

    std::string header = headerStream.str();
    std::string body   = bodyStream.str();

    if (!header.empty())
    {
        mReplayHeaders.emplace_back(header);
    }

    if (!body.empty())
    {
        mPrivateFunctions.emplace_back(body);
    }
}

std::string ReplayWriter::getInlineVariableName(EntryPoint entryPoint, const std::string &paramName)
{
    int counter = mDataTracker.getCounters().getAndIncrement(entryPoint, paramName);
    return GetVarName(entryPoint, paramName, counter);
}

std::string ReplayWriter::getInlineStringSetVariableName(EntryPoint entryPoint,
                                                         const std::string &paramName,
                                                         const std::vector<std::string> &strings,
                                                         bool *isNewEntryOut)
{
    int counter    = mDataTracker.getStringCounters().getStringCounter(strings);
    *isNewEntryOut = (counter == kStringsNotFound);
    if (*isNewEntryOut)
    {
        // This is a unique set of strings, so set up their declaration and update the counter
        counter = mDataTracker.getCounters().getAndIncrement(entryPoint, paramName);
        mDataTracker.getStringCounters().setStringCounter(strings, counter);

        std::string varName = GetVarName(entryPoint, paramName, counter);

        std::stringstream declStream;
        declStream << "const char *const " << varName << "[]";
        std::string decl = declStream.str();

        mGlobalVariableDeclarations.push_back(decl);

        return varName;
    }
    else
    {
        return GetVarName(entryPoint, paramName, counter);
    }
}

size_t ReplayWriter::getStoredReplaySourceSize() const
{
    size_t sum = 0;
    for (const std::string &header : mReplayHeaders)
    {
        sum += header.size();
    }
    for (const std::string &publicFunc : mPublicFunctions)
    {
        sum += publicFunc.size();
    }
    for (const std::string &privateFunc : mPrivateFunctions)
    {
        sum += privateFunc.size();
    }
    return sum;
}

// static
std::string ReplayWriter::GetVarName(EntryPoint entryPoint,
                                     const std::string &paramName,
                                     int counter)
{
    std::stringstream strstr;
    strstr << GetEntryPointName(entryPoint) << "_" << paramName << "_" << counter;
    return strstr.str();
}

void ReplayWriter::saveFrame()
{
    if (mReplayHeaders.empty() && mPublicFunctions.empty() && mPrivateFunctions.empty())
    {
        return;
    }

    ASSERT(!mSourceFileExtension.empty());

    std::stringstream strstr;
    strstr << mFilenamePattern << "_" << std::setfill('0') << std::setw(3) << mFrameIndex++ << "."
           << mSourceFileExtension;

    std::string frameFilePath = strstr.str();

    writeReplaySource(frameFilePath);
}

void ReplayWriter::saveFrameIfFull()
{
    if (getStoredReplaySourceSize() < mSourceFileSizeThreshold)
    {
        INFO() << "Merging captured frame: " << getStoredReplaySourceSize()
               << " less than threshold of " << mSourceFileSizeThreshold << " bytes";
        return;
    }

    saveFrame();
}

void ReplayWriter::saveHeader()
{
    std::stringstream headerPathStream;
    headerPathStream << mFilenamePattern << ".h";
    std::string headerPath = headerPathStream.str();

    SaveFileHelper saveH(headerPath);

    saveH << mHeaderPrologue << "\n";

    saveH << "// Public functions are declared in trace_fixture.h.\n";
    saveH << "\n";
    saveH << "// Private Functions\n";
    saveH << "\n";

    for (const std::string &proto : mPrivateFunctionPrototypes)
    {
        saveH << proto << ";\n";
    }

    saveH << "\n";
    saveH << "// Global variables\n";
    saveH << "\n";

    for (const std::string &globalVar : mGlobalVariableDeclarations)
    {
        saveH << "extern " << globalVar << ";\n";
    }

    mPublicFunctionPrototypes.clear();
    mPrivateFunctionPrototypes.clear();
    mGlobalVariableDeclarations.clear();

    addWrittenFile(headerPath);
}

void ReplayWriter::saveIndexFilesAndHeader()
{
    ASSERT(!mSourceFileExtension.empty());

    std::stringstream sourcePathStream;
    sourcePathStream << mFilenamePattern << "." << mSourceFileExtension;
    std::string sourcePath = sourcePathStream.str();

    writeReplaySource(sourcePath);
    saveHeader();
}

void ReplayWriter::saveSetupFile()
{
    ASSERT(!mSourceFileExtension.empty());

    std::stringstream strstr;
    strstr << mFilenamePattern << "." << mSourceFileExtension;

    std::string frameFilePath = strstr.str();

    writeReplaySource(frameFilePath);
}

void ReplayWriter::writeReplaySource(const std::string &filename)
{
    SaveFileHelper saveCpp(filename);

    saveCpp << mSourcePrologue << "\n";

    for (const std::string &header : mReplayHeaders)
    {
        saveCpp << header << "\n";
    }

    saveCpp << "// Private Functions\n";
    saveCpp << "\n";

    for (const std::string &func : mPrivateFunctions)
    {
        saveCpp << func << "\n";
    }

    saveCpp << "// Public Functions\n";
    saveCpp << "\n";

    if (mFilenamePattern == "cpp")
    {
        saveCpp << "extern \"C\"\n";
        saveCpp << "{\n";
    }

    for (const std::string &func : mPublicFunctions)
    {
        saveCpp << func << "\n";
    }

    if (mFilenamePattern == "cpp")
    {
        saveCpp << "}  // extern \"C\"\n";
    }

    mReplayHeaders.clear();
    mPrivateFunctions.clear();
    mPublicFunctions.clear();

    addWrittenFile(filename);
}

void ReplayWriter::addWrittenFile(const std::string &filename)
{
    std::string writtenFile = GetBaseName(filename);
    ASSERT(std::find(mWrittenFiles.begin(), mWrittenFiles.end(), writtenFile) ==
           mWrittenFiles.end());
    mWrittenFiles.push_back(writtenFile);
}

std::vector<std::string> ReplayWriter::getAndResetWrittenFiles()
{
    std::vector<std::string> results = std::move(mWrittenFiles);
    std::sort(results.begin(), results.end());
    ASSERT(mWrittenFiles.empty());
    return results;
}
}  // 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
