// GENERATED FILE - DO NOT EDIT.
// Generated by generate_entry_points.py using data from gl.xml.
//
// Copyright 2020 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.
//
// entry_points_gles_2_0_autogen.cpp:
//   Defines the GLES 2.0 entry points.

#include "libGLESv2/entry_points_gles_2_0_autogen.h"

#include "common/entry_points_enum_autogen.h"
#include "libANGLE/Context.h"
#include "libANGLE/Context.inl.h"
#include "libANGLE/capture_gles_2_0_autogen.h"
#include "libANGLE/entry_points_utils.h"
#include "libANGLE/gl_enum_utils.h"
#include "libANGLE/validationES2.h"
#include "libGLESv2/global_state.h"

namespace gl
{
void GL_APIENTRY ActiveTexture(GLenum texture)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLActiveTexture, "context = %d, texture = %s", CID(context),
          GLenumToString(GLenumGroup::TextureUnit, texture));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateActiveTexture(context, texture));
        if (isCallValid)
        {
            context->activeTexture(texture);
        }
        ANGLE_CAPTURE(ActiveTexture, isCallValid, context, texture);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLAttachShader, "context = %d, program = %u, shader = %u", CID(context), program,
          shader);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateAttachShader(context, programPacked, shaderPacked));
        if (isCallValid)
        {
            context->attachShader(programPacked, shaderPacked);
        }
        ANGLE_CAPTURE(AttachShader, isCallValid, context, programPacked, shaderPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar *name)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBindAttribLocation,
          "context = %d, program = %u, index = %u, name = 0x%016" PRIxPTR "", CID(context), program,
          index, (uintptr_t)name);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBindAttribLocation(context, programPacked, index, name));
        if (isCallValid)
        {
            context->bindAttribLocation(programPacked, index, name);
        }
        ANGLE_CAPTURE(BindAttribLocation, isCallValid, context, programPacked, index, name);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBindBuffer, "context = %d, target = %s, buffer = %u", CID(context),
          GLenumToString(GLenumGroup::BufferTargetARB, target), buffer);

    if (context)
    {
        BufferBinding targetPacked                            = PackParam<BufferBinding>(target);
        BufferID bufferPacked                                 = PackParam<BufferID>(buffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateBindBuffer(context, targetPacked, bufferPacked));
        if (isCallValid)
        {
            context->bindBuffer(targetPacked, bufferPacked);
        }
        ANGLE_CAPTURE(BindBuffer, isCallValid, context, targetPacked, bufferPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBindFramebuffer, "context = %d, target = %s, framebuffer = %u", CID(context),
          GLenumToString(GLenumGroup::FramebufferTarget, target), framebuffer);

    if (context)
    {
        FramebufferID framebufferPacked = PackParam<FramebufferID>(framebuffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBindFramebuffer(context, target, framebufferPacked));
        if (isCallValid)
        {
            context->bindFramebuffer(target, framebufferPacked);
        }
        ANGLE_CAPTURE(BindFramebuffer, isCallValid, context, target, framebufferPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBindRenderbuffer, "context = %d, target = %s, renderbuffer = %u", CID(context),
          GLenumToString(GLenumGroup::RenderbufferTarget, target), renderbuffer);

    if (context)
    {
        RenderbufferID renderbufferPacked = PackParam<RenderbufferID>(renderbuffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBindRenderbuffer(context, target, renderbufferPacked));
        if (isCallValid)
        {
            context->bindRenderbuffer(target, renderbufferPacked);
        }
        ANGLE_CAPTURE(BindRenderbuffer, isCallValid, context, target, renderbufferPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBindTexture, "context = %d, target = %s, texture = %u", CID(context),
          GLenumToString(GLenumGroup::TextureTarget, target), texture);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        TextureID texturePacked                               = PackParam<TextureID>(texture);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBindTexture(context, targetPacked, texturePacked));
        if (isCallValid)
        {
            context->bindTexture(targetPacked, texturePacked);
        }
        ANGLE_CAPTURE(BindTexture, isCallValid, context, targetPacked, texturePacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBlendColor, "context = %d, red = %f, green = %f, blue = %f, alpha = %f",
          CID(context), red, green, blue, alpha);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateBlendColor(context, red, green, blue, alpha));
        if (isCallValid)
        {
            context->blendColor(red, green, blue, alpha);
        }
        ANGLE_CAPTURE(BlendColor, isCallValid, context, red, green, blue, alpha);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BlendEquation(GLenum mode)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBlendEquation, "context = %d, mode = %s", CID(context),
          GLenumToString(GLenumGroup::BlendEquationModeEXT, mode));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateBlendEquation(context, mode));
        if (isCallValid)
        {
            context->blendEquation(mode);
        }
        ANGLE_CAPTURE(BlendEquation, isCallValid, context, mode);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBlendEquationSeparate, "context = %d, modeRGB = %s, modeAlpha = %s",
          CID(context), GLenumToString(GLenumGroup::BlendEquationModeEXT, modeRGB),
          GLenumToString(GLenumGroup::BlendEquationModeEXT, modeAlpha));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBlendEquationSeparate(context, modeRGB, modeAlpha));
        if (isCallValid)
        {
            context->blendEquationSeparate(modeRGB, modeAlpha);
        }
        ANGLE_CAPTURE(BlendEquationSeparate, isCallValid, context, modeRGB, modeAlpha);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBlendFunc, "context = %d, sfactor = %s, dfactor = %s", CID(context),
          GLenumToString(GLenumGroup::BlendingFactor, sfactor),
          GLenumToString(GLenumGroup::BlendingFactor, dfactor));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateBlendFunc(context, sfactor, dfactor));
        if (isCallValid)
        {
            context->blendFunc(sfactor, dfactor);
        }
        ANGLE_CAPTURE(BlendFunc, isCallValid, context, sfactor, dfactor);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BlendFuncSeparate(GLenum sfactorRGB,
                                   GLenum dfactorRGB,
                                   GLenum sfactorAlpha,
                                   GLenum dfactorAlpha)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBlendFuncSeparate,
          "context = %d, sfactorRGB = %s, dfactorRGB = %s, sfactorAlpha = %s, dfactorAlpha = %s",
          CID(context), GLenumToString(GLenumGroup::BlendingFactor, sfactorRGB),
          GLenumToString(GLenumGroup::BlendingFactor, dfactorRGB),
          GLenumToString(GLenumGroup::BlendingFactor, sfactorAlpha),
          GLenumToString(GLenumGroup::BlendingFactor, dfactorAlpha));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateBlendFuncSeparate(context, sfactorRGB, dfactorRGB,
                                                                    sfactorAlpha, dfactorAlpha));
        if (isCallValid)
        {
            context->blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
        }
        ANGLE_CAPTURE(BlendFuncSeparate, isCallValid, context, sfactorRGB, dfactorRGB, sfactorAlpha,
                      dfactorAlpha);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBufferData,
          "context = %d, target = %s, size = %llu, data = 0x%016" PRIxPTR ", usage = %s",
          CID(context), GLenumToString(GLenumGroup::BufferTargetARB, target),
          static_cast<unsigned long long>(size), (uintptr_t)data,
          GLenumToString(GLenumGroup::BufferUsageARB, usage));

    if (context)
    {
        BufferBinding targetPacked                            = PackParam<BufferBinding>(target);
        BufferUsage usagePacked                               = PackParam<BufferUsage>(usage);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBufferData(context, targetPacked, size, data, usagePacked));
        if (isCallValid)
        {
            context->bufferData(targetPacked, size, data, usagePacked);
        }
        ANGLE_CAPTURE(BufferData, isCallValid, context, targetPacked, size, data, usagePacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLBufferSubData,
          "context = %d, target = %s, offset = %llu, size = %llu, data = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::BufferTargetARB, target),
          static_cast<unsigned long long>(offset), static_cast<unsigned long long>(size),
          (uintptr_t)data);

    if (context)
    {
        BufferBinding targetPacked                            = PackParam<BufferBinding>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateBufferSubData(context, targetPacked, offset, size, data));
        if (isCallValid)
        {
            context->bufferSubData(targetPacked, offset, size, data);
        }
        ANGLE_CAPTURE(BufferSubData, isCallValid, context, targetPacked, offset, size, data);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCheckFramebufferStatus, "context = %d, target = %s", CID(context),
          GLenumToString(GLenumGroup::FramebufferTarget, target));

    GLenum returnValue;
    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateCheckFramebufferStatus(context, target));
        if (isCallValid)
        {
            returnValue = context->checkFramebufferStatus(target);
        }
        else
        {
            returnValue =
                GetDefaultReturnValue<angle::EntryPoint::GLCheckFramebufferStatus, GLenum>();
        }
        ANGLE_CAPTURE(CheckFramebufferStatus, isCallValid, context, target, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLCheckFramebufferStatus, GLenum>();
    }
    return returnValue;
}

void GL_APIENTRY Clear(GLbitfield mask)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLClear, "context = %d, mask = %s", CID(context),
          GLbitfieldToString(GLenumGroup::ClearBufferMask, mask).c_str());

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateClear(context, mask));
        if (isCallValid)
        {
            context->clear(mask);
        }
        ANGLE_CAPTURE(Clear, isCallValid, context, mask);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLClearColor, "context = %d, red = %f, green = %f, blue = %f, alpha = %f",
          CID(context), red, green, blue, alpha);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateClearColor(context, red, green, blue, alpha));
        if (isCallValid)
        {
            context->clearColor(red, green, blue, alpha);
        }
        ANGLE_CAPTURE(ClearColor, isCallValid, context, red, green, blue, alpha);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ClearDepthf(GLfloat d)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLClearDepthf, "context = %d, d = %f", CID(context), d);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateClearDepthf(context, d));
        if (isCallValid)
        {
            context->clearDepthf(d);
        }
        ANGLE_CAPTURE(ClearDepthf, isCallValid, context, d);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ClearStencil(GLint s)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLClearStencil, "context = %d, s = %d", CID(context), s);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateClearStencil(context, s));
        if (isCallValid)
        {
            context->clearStencil(s);
        }
        ANGLE_CAPTURE(ClearStencil, isCallValid, context, s);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLColorMask, "context = %d, red = %s, green = %s, blue = %s, alpha = %s",
          CID(context), GLbooleanToString(red), GLbooleanToString(green), GLbooleanToString(blue),
          GLbooleanToString(alpha));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateColorMask(context, red, green, blue, alpha));
        if (isCallValid)
        {
            context->colorMask(red, green, blue, alpha);
        }
        ANGLE_CAPTURE(ColorMask, isCallValid, context, red, green, blue, alpha);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY CompileShader(GLuint shader)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCompileShader, "context = %d, shader = %u", CID(context), shader);

    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateCompileShader(context, shaderPacked));
        if (isCallValid)
        {
            context->compileShader(shaderPacked);
        }
        ANGLE_CAPTURE(CompileShader, isCallValid, context, shaderPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY CompressedTexImage2D(GLenum target,
                                      GLint level,
                                      GLenum internalformat,
                                      GLsizei width,
                                      GLsizei height,
                                      GLint border,
                                      GLsizei imageSize,
                                      const void *data)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCompressedTexImage2D,
          "context = %d, target = %s, level = %d, internalformat = %s, width = %d, height = %d, "
          "border = %d, imageSize = %d, data = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), level,
          GLenumToString(GLenumGroup::InternalFormat, internalformat), width, height, border,
          imageSize, (uintptr_t)data);

    if (context)
    {
        TextureTarget targetPacked                            = PackParam<TextureTarget>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateCompressedTexImage2D(context, targetPacked, level, internalformat, width,
                                          height, border, imageSize, data));
        if (isCallValid)
        {
            context->compressedTexImage2D(targetPacked, level, internalformat, width, height,
                                          border, imageSize, data);
        }
        ANGLE_CAPTURE(CompressedTexImage2D, isCallValid, context, targetPacked, level,
                      internalformat, width, height, border, imageSize, data);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY CompressedTexSubImage2D(GLenum target,
                                         GLint level,
                                         GLint xoffset,
                                         GLint yoffset,
                                         GLsizei width,
                                         GLsizei height,
                                         GLenum format,
                                         GLsizei imageSize,
                                         const void *data)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCompressedTexSubImage2D,
          "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = "
          "%d, format = %s, imageSize = %d, data = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), level, xoffset, yoffset,
          width, height, GLenumToString(GLenumGroup::PixelFormat, format), imageSize,
          (uintptr_t)data);

    if (context)
    {
        TextureTarget targetPacked                            = PackParam<TextureTarget>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateCompressedTexSubImage2D(context, targetPacked, level, xoffset, yoffset, width,
                                             height, format, imageSize, data));
        if (isCallValid)
        {
            context->compressedTexSubImage2D(targetPacked, level, xoffset, yoffset, width, height,
                                             format, imageSize, data);
        }
        ANGLE_CAPTURE(CompressedTexSubImage2D, isCallValid, context, targetPacked, level, xoffset,
                      yoffset, width, height, format, imageSize, data);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY CopyTexImage2D(GLenum target,
                                GLint level,
                                GLenum internalformat,
                                GLint x,
                                GLint y,
                                GLsizei width,
                                GLsizei height,
                                GLint border)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCopyTexImage2D,
          "context = %d, target = %s, level = %d, internalformat = %s, x = %d, y = %d, width = %d, "
          "height = %d, border = %d",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), level,
          GLenumToString(GLenumGroup::InternalFormat, internalformat), x, y, width, height, border);

    if (context)
    {
        TextureTarget targetPacked                            = PackParam<TextureTarget>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateCopyTexImage2D(context, targetPacked, level, internalformat, x,
                                                   y, width, height, border));
        if (isCallValid)
        {
            context->copyTexImage2D(targetPacked, level, internalformat, x, y, width, height,
                                    border);
        }
        ANGLE_CAPTURE(CopyTexImage2D, isCallValid, context, targetPacked, level, internalformat, x,
                      y, width, height, border);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY CopyTexSubImage2D(GLenum target,
                                   GLint level,
                                   GLint xoffset,
                                   GLint yoffset,
                                   GLint x,
                                   GLint y,
                                   GLsizei width,
                                   GLsizei height)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCopyTexSubImage2D,
          "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, x = %d, y = %d, "
          "width = %d, height = %d",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), level, xoffset, yoffset,
          x, y, width, height);

    if (context)
    {
        TextureTarget targetPacked                            = PackParam<TextureTarget>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateCopyTexSubImage2D(context, targetPacked, level, xoffset,
                                                      yoffset, x, y, width, height));
        if (isCallValid)
        {
            context->copyTexSubImage2D(targetPacked, level, xoffset, yoffset, x, y, width, height);
        }
        ANGLE_CAPTURE(CopyTexSubImage2D, isCallValid, context, targetPacked, level, xoffset,
                      yoffset, x, y, width, height);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

GLuint GL_APIENTRY CreateProgram()
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCreateProgram, "context = %d", CID(context));

    GLuint returnValue;
    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateCreateProgram(context));
        if (isCallValid)
        {
            returnValue = context->createProgram();
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLCreateProgram, GLuint>();
        }
        ANGLE_CAPTURE(CreateProgram, isCallValid, context, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLCreateProgram, GLuint>();
    }
    return returnValue;
}

GLuint GL_APIENTRY CreateShader(GLenum type)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCreateShader, "context = %d, type = %s", CID(context),
          GLenumToString(GLenumGroup::ShaderType, type));

    GLuint returnValue;
    if (context)
    {
        ShaderType typePacked                                 = PackParam<ShaderType>(type);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateCreateShader(context, typePacked));
        if (isCallValid)
        {
            returnValue = context->createShader(typePacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLCreateShader, GLuint>();
        }
        ANGLE_CAPTURE(CreateShader, isCallValid, context, typePacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLCreateShader, GLuint>();
    }
    return returnValue;
}

void GL_APIENTRY CullFace(GLenum mode)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLCullFace, "context = %d, mode = %s", CID(context),
          GLenumToString(GLenumGroup::CullFaceMode, mode));

    if (context)
    {
        CullFaceMode modePacked                               = PackParam<CullFaceMode>(mode);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateCullFace(context, modePacked));
        if (isCallValid)
        {
            context->cullFace(modePacked);
        }
        ANGLE_CAPTURE(CullFace, isCallValid, context, modePacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint *buffers)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDeleteBuffers, "context = %d, n = %d, buffers = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)buffers);

    if (context)
    {
        const BufferID *buffersPacked = PackParam<const BufferID *>(buffers);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDeleteBuffers(context, n, buffersPacked));
        if (isCallValid)
        {
            context->deleteBuffers(n, buffersPacked);
        }
        ANGLE_CAPTURE(DeleteBuffers, isCallValid, context, n, buffersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDeleteFramebuffers, "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)framebuffers);

    if (context)
    {
        const FramebufferID *framebuffersPacked = PackParam<const FramebufferID *>(framebuffers);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateDeleteFramebuffers(context, n, framebuffersPacked));
        if (isCallValid)
        {
            context->deleteFramebuffers(n, framebuffersPacked);
        }
        ANGLE_CAPTURE(DeleteFramebuffers, isCallValid, context, n, framebuffersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DeleteProgram(GLuint program)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDeleteProgram, "context = %d, program = %u", CID(context), program);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDeleteProgram(context, programPacked));
        if (isCallValid)
        {
            context->deleteProgram(programPacked);
        }
        ANGLE_CAPTURE(DeleteProgram, isCallValid, context, programPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDeleteRenderbuffers, "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)renderbuffers);

    if (context)
    {
        const RenderbufferID *renderbuffersPacked =
            PackParam<const RenderbufferID *>(renderbuffers);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateDeleteRenderbuffers(context, n, renderbuffersPacked));
        if (isCallValid)
        {
            context->deleteRenderbuffers(n, renderbuffersPacked);
        }
        ANGLE_CAPTURE(DeleteRenderbuffers, isCallValid, context, n, renderbuffersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DeleteShader(GLuint shader)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDeleteShader, "context = %d, shader = %u", CID(context), shader);

    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDeleteShader(context, shaderPacked));
        if (isCallValid)
        {
            context->deleteShader(shaderPacked);
        }
        ANGLE_CAPTURE(DeleteShader, isCallValid, context, shaderPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint *textures)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDeleteTextures, "context = %d, n = %d, textures = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)textures);

    if (context)
    {
        const TextureID *texturesPacked = PackParam<const TextureID *>(textures);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDeleteTextures(context, n, texturesPacked));
        if (isCallValid)
        {
            context->deleteTextures(n, texturesPacked);
        }
        ANGLE_CAPTURE(DeleteTextures, isCallValid, context, n, texturesPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DepthFunc(GLenum func)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDepthFunc, "context = %d, func = %s", CID(context),
          GLenumToString(GLenumGroup::DepthFunction, func));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateDepthFunc(context, func));
        if (isCallValid)
        {
            context->depthFunc(func);
        }
        ANGLE_CAPTURE(DepthFunc, isCallValid, context, func);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DepthMask(GLboolean flag)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDepthMask, "context = %d, flag = %s", CID(context), GLbooleanToString(flag));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateDepthMask(context, flag));
        if (isCallValid)
        {
            context->depthMask(flag);
        }
        ANGLE_CAPTURE(DepthMask, isCallValid, context, flag);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDepthRangef, "context = %d, n = %f, f = %f", CID(context), n, f);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateDepthRangef(context, n, f));
        if (isCallValid)
        {
            context->depthRangef(n, f);
        }
        ANGLE_CAPTURE(DepthRangef, isCallValid, context, n, f);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDetachShader, "context = %d, program = %u, shader = %u", CID(context), program,
          shader);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateDetachShader(context, programPacked, shaderPacked));
        if (isCallValid)
        {
            context->detachShader(programPacked, shaderPacked);
        }
        ANGLE_CAPTURE(DetachShader, isCallValid, context, programPacked, shaderPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Disable(GLenum cap)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDisable, "context = %d, cap = %s", CID(context),
          GLenumToString(GLenumGroup::EnableCap, cap));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateDisable(context, cap));
        if (isCallValid)
        {
            context->disable(cap);
        }
        ANGLE_CAPTURE(Disable, isCallValid, context, cap);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DisableVertexAttribArray(GLuint index)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDisableVertexAttribArray, "context = %d, index = %u", CID(context), index);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDisableVertexAttribArray(context, index));
        if (isCallValid)
        {
            context->disableVertexAttribArray(index);
        }
        ANGLE_CAPTURE(DisableVertexAttribArray, isCallValid, context, index);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDrawArrays, "context = %d, mode = %s, first = %d, count = %d", CID(context),
          GLenumToString(GLenumGroup::PrimitiveType, mode), first, count);

    if (context)
    {
        PrimitiveMode modePacked                              = PackParam<PrimitiveMode>(mode);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDrawArrays(context, modePacked, first, count));
        if (isCallValid)
        {
            context->drawArrays(modePacked, first, count);
        }
        ANGLE_CAPTURE(DrawArrays, isCallValid, context, modePacked, first, count);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLDrawElements,
          "context = %d, mode = %s, count = %d, type = %s, indices = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::PrimitiveType, mode), count,
          GLenumToString(GLenumGroup::DrawElementsType, type), (uintptr_t)indices);

    if (context)
    {
        PrimitiveMode modePacked                              = PackParam<PrimitiveMode>(mode);
        DrawElementsType typePacked                           = PackParam<DrawElementsType>(type);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateDrawElements(context, modePacked, count, typePacked, indices));
        if (isCallValid)
        {
            context->drawElements(modePacked, count, typePacked, indices);
        }
        ANGLE_CAPTURE(DrawElements, isCallValid, context, modePacked, count, typePacked, indices);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Enable(GLenum cap)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLEnable, "context = %d, cap = %s", CID(context),
          GLenumToString(GLenumGroup::EnableCap, cap));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateEnable(context, cap));
        if (isCallValid)
        {
            context->enable(cap);
        }
        ANGLE_CAPTURE(Enable, isCallValid, context, cap);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY EnableVertexAttribArray(GLuint index)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLEnableVertexAttribArray, "context = %d, index = %u", CID(context), index);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateEnableVertexAttribArray(context, index));
        if (isCallValid)
        {
            context->enableVertexAttribArray(index);
        }
        ANGLE_CAPTURE(EnableVertexAttribArray, isCallValid, context, index);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Finish()
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLFinish, "context = %d", CID(context));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateFinish(context));
        if (isCallValid)
        {
            context->finish();
        }
        ANGLE_CAPTURE(Finish, isCallValid, context);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Flush()
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLFlush, "context = %d", CID(context));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateFlush(context));
        if (isCallValid)
        {
            context->flush();
        }
        ANGLE_CAPTURE(Flush, isCallValid, context);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY FramebufferRenderbuffer(GLenum target,
                                         GLenum attachment,
                                         GLenum renderbuffertarget,
                                         GLuint renderbuffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLFramebufferRenderbuffer,
          "context = %d, target = %s, attachment = %s, renderbuffertarget = %s, renderbuffer = %u",
          CID(context), GLenumToString(GLenumGroup::FramebufferTarget, target),
          GLenumToString(GLenumGroup::FramebufferAttachment, attachment),
          GLenumToString(GLenumGroup::RenderbufferTarget, renderbuffertarget), renderbuffer);

    if (context)
    {
        RenderbufferID renderbufferPacked = PackParam<RenderbufferID>(renderbuffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateFramebufferRenderbuffer(context, target, attachment, renderbuffertarget,
                                             renderbufferPacked));
        if (isCallValid)
        {
            context->framebufferRenderbuffer(target, attachment, renderbuffertarget,
                                             renderbufferPacked);
        }
        ANGLE_CAPTURE(FramebufferRenderbuffer, isCallValid, context, target, attachment,
                      renderbuffertarget, renderbufferPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY FramebufferTexture2D(GLenum target,
                                      GLenum attachment,
                                      GLenum textarget,
                                      GLuint texture,
                                      GLint level)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLFramebufferTexture2D,
          "context = %d, target = %s, attachment = %s, textarget = %s, texture = %u, level = %d",
          CID(context), GLenumToString(GLenumGroup::FramebufferTarget, target),
          GLenumToString(GLenumGroup::FramebufferAttachment, attachment),
          GLenumToString(GLenumGroup::TextureTarget, textarget), texture, level);

    if (context)
    {
        TextureTarget textargetPacked                         = PackParam<TextureTarget>(textarget);
        TextureID texturePacked                               = PackParam<TextureID>(texture);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateFramebufferTexture2D(context, target, attachment,
                                                         textargetPacked, texturePacked, level));
        if (isCallValid)
        {
            context->framebufferTexture2D(target, attachment, textargetPacked, texturePacked,
                                          level);
        }
        ANGLE_CAPTURE(FramebufferTexture2D, isCallValid, context, target, attachment,
                      textargetPacked, texturePacked, level);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY FrontFace(GLenum mode)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLFrontFace, "context = %d, mode = %s", CID(context),
          GLenumToString(GLenumGroup::FrontFaceDirection, mode));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateFrontFace(context, mode));
        if (isCallValid)
        {
            context->frontFace(mode);
        }
        ANGLE_CAPTURE(FrontFace, isCallValid, context, mode);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GenBuffers(GLsizei n, GLuint *buffers)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGenBuffers, "context = %d, n = %d, buffers = 0x%016" PRIxPTR "", CID(context),
          n, (uintptr_t)buffers);

    if (context)
    {
        BufferID *buffersPacked                               = PackParam<BufferID *>(buffers);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGenBuffers(context, n, buffersPacked));
        if (isCallValid)
        {
            context->genBuffers(n, buffersPacked);
        }
        ANGLE_CAPTURE(GenBuffers, isCallValid, context, n, buffersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint *framebuffers)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGenFramebuffers, "context = %d, n = %d, framebuffers = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)framebuffers);

    if (context)
    {
        FramebufferID *framebuffersPacked = PackParam<FramebufferID *>(framebuffers);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGenFramebuffers(context, n, framebuffersPacked));
        if (isCallValid)
        {
            context->genFramebuffers(n, framebuffersPacked);
        }
        ANGLE_CAPTURE(GenFramebuffers, isCallValid, context, n, framebuffersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGenRenderbuffers, "context = %d, n = %d, renderbuffers = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)renderbuffers);

    if (context)
    {
        RenderbufferID *renderbuffersPacked = PackParam<RenderbufferID *>(renderbuffers);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGenRenderbuffers(context, n, renderbuffersPacked));
        if (isCallValid)
        {
            context->genRenderbuffers(n, renderbuffersPacked);
        }
        ANGLE_CAPTURE(GenRenderbuffers, isCallValid, context, n, renderbuffersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GenTextures(GLsizei n, GLuint *textures)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGenTextures, "context = %d, n = %d, textures = 0x%016" PRIxPTR "",
          CID(context), n, (uintptr_t)textures);

    if (context)
    {
        TextureID *texturesPacked                             = PackParam<TextureID *>(textures);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGenTextures(context, n, texturesPacked));
        if (isCallValid)
        {
            context->genTextures(n, texturesPacked);
        }
        ANGLE_CAPTURE(GenTextures, isCallValid, context, n, texturesPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GenerateMipmap(GLenum target)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGenerateMipmap, "context = %d, target = %s", CID(context),
          GLenumToString(GLenumGroup::TextureTarget, target));

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGenerateMipmap(context, targetPacked));
        if (isCallValid)
        {
            context->generateMipmap(targetPacked);
        }
        ANGLE_CAPTURE(GenerateMipmap, isCallValid, context, targetPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetActiveAttrib(GLuint program,
                                 GLuint index,
                                 GLsizei bufSize,
                                 GLsizei *length,
                                 GLint *size,
                                 GLenum *type,
                                 GLchar *name)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetActiveAttrib,
          "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR
          ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "",
          CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size,
          (uintptr_t)type, (uintptr_t)name);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetActiveAttrib(context, programPacked, index, bufSize, length,
                                                    size, type, name));
        if (isCallValid)
        {
            context->getActiveAttrib(programPacked, index, bufSize, length, size, type, name);
        }
        ANGLE_CAPTURE(GetActiveAttrib, isCallValid, context, programPacked, index, bufSize, length,
                      size, type, name);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetActiveUniform(GLuint program,
                                  GLuint index,
                                  GLsizei bufSize,
                                  GLsizei *length,
                                  GLint *size,
                                  GLenum *type,
                                  GLchar *name)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetActiveUniform,
          "context = %d, program = %u, index = %u, bufSize = %d, length = 0x%016" PRIxPTR
          ", size = 0x%016" PRIxPTR ", type = 0x%016" PRIxPTR ", name = 0x%016" PRIxPTR "",
          CID(context), program, index, bufSize, (uintptr_t)length, (uintptr_t)size,
          (uintptr_t)type, (uintptr_t)name);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetActiveUniform(context, programPacked, index, bufSize, length,
                                                     size, type, name));
        if (isCallValid)
        {
            context->getActiveUniform(programPacked, index, bufSize, length, size, type, name);
        }
        ANGLE_CAPTURE(GetActiveUniform, isCallValid, context, programPacked, index, bufSize, length,
                      size, type, name);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetAttachedShaders(GLuint program,
                                    GLsizei maxCount,
                                    GLsizei *count,
                                    GLuint *shaders)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetAttachedShaders,
          "context = %d, program = %u, maxCount = %d, count = 0x%016" PRIxPTR
          ", shaders = 0x%016" PRIxPTR "",
          CID(context), program, maxCount, (uintptr_t)count, (uintptr_t)shaders);

    if (context)
    {
        ShaderProgramID programPacked  = PackParam<ShaderProgramID>(program);
        ShaderProgramID *shadersPacked = PackParam<ShaderProgramID *>(shaders);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateGetAttachedShaders(context, programPacked, maxCount, count, shadersPacked));
        if (isCallValid)
        {
            context->getAttachedShaders(programPacked, maxCount, count, shadersPacked);
        }
        ANGLE_CAPTURE(GetAttachedShaders, isCallValid, context, programPacked, maxCount, count,
                      shadersPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar *name)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetAttribLocation, "context = %d, program = %u, name = 0x%016" PRIxPTR "",
          CID(context), program, (uintptr_t)name);

    GLint returnValue;
    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGetAttribLocation(context, programPacked, name));
        if (isCallValid)
        {
            returnValue = context->getAttribLocation(programPacked, name);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetAttribLocation, GLint>();
        }
        ANGLE_CAPTURE(GetAttribLocation, isCallValid, context, programPacked, name, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetAttribLocation, GLint>();
    }
    return returnValue;
}

void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean *data)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetBooleanv, "context = %d, pname = %s, data = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::GetPName, pname), (uintptr_t)data);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateGetBooleanv(context, pname, data));
        if (isCallValid)
        {
            context->getBooleanv(pname, data);
        }
        ANGLE_CAPTURE(GetBooleanv, isCallValid, context, pname, data);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetBufferParameteriv,
          "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::BufferTargetARB, target),
          GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)params);

    if (context)
    {
        BufferBinding targetPacked                            = PackParam<BufferBinding>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetBufferParameteriv(context, targetPacked, pname, params));
        if (isCallValid)
        {
            context->getBufferParameteriv(targetPacked, pname, params);
        }
        ANGLE_CAPTURE(GetBufferParameteriv, isCallValid, context, targetPacked, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

GLenum GL_APIENTRY GetError()
{
    Context *context = GetGlobalContext();
    EVENT(context, GLGetError, "context = %d", CID(context));

    GLenum returnValue;
    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateGetError(context));
        if (isCallValid)
        {
            returnValue = context->getError();
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetError, GLenum>();
        }
        ANGLE_CAPTURE(GetError, isCallValid, context, returnValue);
    }
    else
    {

        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetError, GLenum>();
    }
    return returnValue;
}

void GL_APIENTRY GetFloatv(GLenum pname, GLfloat *data)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetFloatv, "context = %d, pname = %s, data = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::GetPName, pname), (uintptr_t)data);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateGetFloatv(context, pname, data));
        if (isCallValid)
        {
            context->getFloatv(pname, data);
        }
        ANGLE_CAPTURE(GetFloatv, isCallValid, context, pname, data);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target,
                                                     GLenum attachment,
                                                     GLenum pname,
                                                     GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetFramebufferAttachmentParameteriv,
          "context = %d, target = %s, attachment = %s, pname = %s, params = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::FramebufferTarget, target),
          GLenumToString(GLenumGroup::FramebufferAttachment, attachment),
          GLenumToString(GLenumGroup::FramebufferAttachmentParameterName, pname),
          (uintptr_t)params);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGetFramebufferAttachmentParameteriv(
                                              context, target, attachment, pname, params));
        if (isCallValid)
        {
            context->getFramebufferAttachmentParameteriv(target, attachment, pname, params);
        }
        ANGLE_CAPTURE(GetFramebufferAttachmentParameteriv, isCallValid, context, target, attachment,
                      pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetIntegerv(GLenum pname, GLint *data)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetIntegerv, "context = %d, pname = %s, data = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::GetPName, pname), (uintptr_t)data);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateGetIntegerv(context, pname, data));
        if (isCallValid)
        {
            context->getIntegerv(pname, data);
        }
        ANGLE_CAPTURE(GetIntegerv, isCallValid, context, pname, data);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetProgramInfoLog(GLuint program,
                                   GLsizei bufSize,
                                   GLsizei *length,
                                   GLchar *infoLog)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetProgramInfoLog,
          "context = %d, program = %u, bufSize = %d, length = 0x%016" PRIxPTR
          ", infoLog = 0x%016" PRIxPTR "",
          CID(context), program, bufSize, (uintptr_t)length, (uintptr_t)infoLog);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateGetProgramInfoLog(context, programPacked, bufSize, length, infoLog));
        if (isCallValid)
        {
            context->getProgramInfoLog(programPacked, bufSize, length, infoLog);
        }
        ANGLE_CAPTURE(GetProgramInfoLog, isCallValid, context, programPacked, bufSize, length,
                      infoLog);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint *params)
{
    Context *context = GetGlobalContext();
    EVENT(context, GLGetProgramiv,
          "context = %d, program = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          program, GLenumToString(GLenumGroup::ProgramPropertyARB, pname), (uintptr_t)params);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetProgramiv(context, programPacked, pname, params));
        if (isCallValid)
        {
            context->getProgramiv(programPacked, pname, params);
        }
        ANGLE_CAPTURE(GetProgramiv, isCallValid, context, programPacked, pname, params);
    }
    else
    {}
}

void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetRenderbufferParameteriv,
          "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::RenderbufferTarget, target),
          GLenumToString(GLenumGroup::RenderbufferParameterName, pname), (uintptr_t)params);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetRenderbufferParameteriv(context, target, pname, params));
        if (isCallValid)
        {
            context->getRenderbufferParameteriv(target, pname, params);
        }
        ANGLE_CAPTURE(GetRenderbufferParameteriv, isCallValid, context, target, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetShaderInfoLog,
          "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR
          ", infoLog = 0x%016" PRIxPTR "",
          CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)infoLog);

    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateGetShaderInfoLog(context, shaderPacked, bufSize, length, infoLog));
        if (isCallValid)
        {
            context->getShaderInfoLog(shaderPacked, bufSize, length, infoLog);
        }
        ANGLE_CAPTURE(GetShaderInfoLog, isCallValid, context, shaderPacked, bufSize, length,
                      infoLog);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype,
                                          GLenum precisiontype,
                                          GLint *range,
                                          GLint *precision)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetShaderPrecisionFormat,
          "context = %d, shadertype = %s, precisiontype = %s, range = 0x%016" PRIxPTR
          ", precision = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::ShaderType, shadertype),
          GLenumToString(GLenumGroup::PrecisionType, precisiontype), (uintptr_t)range,
          (uintptr_t)precision);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetShaderPrecisionFormat(context, shadertype, precisiontype,
                                                             range, precision));
        if (isCallValid)
        {
            context->getShaderPrecisionFormat(shadertype, precisiontype, range, precision);
        }
        ANGLE_CAPTURE(GetShaderPrecisionFormat, isCallValid, context, shadertype, precisiontype,
                      range, precision);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetShaderSource,
          "context = %d, shader = %u, bufSize = %d, length = 0x%016" PRIxPTR
          ", source = 0x%016" PRIxPTR "",
          CID(context), shader, bufSize, (uintptr_t)length, (uintptr_t)source);

    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateGetShaderSource(context, shaderPacked, bufSize, length, source));
        if (isCallValid)
        {
            context->getShaderSource(shaderPacked, bufSize, length, source);
        }
        ANGLE_CAPTURE(GetShaderSource, isCallValid, context, shaderPacked, bufSize, length, source);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint *params)
{
    Context *context = GetGlobalContext();
    EVENT(context, GLGetShaderiv,
          "context = %d, shader = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), shader,
          GLenumToString(GLenumGroup::ShaderParameterName, pname), (uintptr_t)params);

    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetShaderiv(context, shaderPacked, pname, params));
        if (isCallValid)
        {
            context->getShaderiv(shaderPacked, pname, params);
        }
        ANGLE_CAPTURE(GetShaderiv, isCallValid, context, shaderPacked, pname, params);
    }
    else
    {}
}

const GLubyte *GL_APIENTRY GetString(GLenum name)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetString, "context = %d, name = %s", CID(context),
          GLenumToString(GLenumGroup::StringName, name));

    const GLubyte *returnValue;
    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateGetString(context, name));
        if (isCallValid)
        {
            returnValue = context->getString(name);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetString, const GLubyte *>();
        }
        ANGLE_CAPTURE(GetString, isCallValid, context, name, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetString, const GLubyte *>();
    }
    return returnValue;
}

void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetTexParameterfv,
          "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::GetTextureParameter, pname), (uintptr_t)params);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetTexParameterfv(context, targetPacked, pname, params));
        if (isCallValid)
        {
            context->getTexParameterfv(targetPacked, pname, params);
        }
        ANGLE_CAPTURE(GetTexParameterfv, isCallValid, context, targetPacked, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetTexParameteriv,
          "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::GetTextureParameter, pname), (uintptr_t)params);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetTexParameteriv(context, targetPacked, pname, params));
        if (isCallValid)
        {
            context->getTexParameteriv(targetPacked, pname, params);
        }
        ANGLE_CAPTURE(GetTexParameteriv, isCallValid, context, targetPacked, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar *name)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetUniformLocation, "context = %d, program = %u, name = 0x%016" PRIxPTR "",
          CID(context), program, (uintptr_t)name);

    GLint returnValue;
    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGetUniformLocation(context, programPacked, name));
        if (isCallValid)
        {
            returnValue = context->getUniformLocation(programPacked, name);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetUniformLocation, GLint>();
        }
        ANGLE_CAPTURE(GetUniformLocation, isCallValid, context, programPacked, name, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLGetUniformLocation, GLint>();
    }
    return returnValue;
}

void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetUniformfv,
          "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", CID(context),
          program, location, (uintptr_t)params);

    if (context)
    {
        ShaderProgramID programPacked  = PackParam<ShaderProgramID>(program);
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetUniformfv(context, programPacked, locationPacked, params));
        if (isCallValid)
        {
            context->getUniformfv(programPacked, locationPacked, params);
        }
        ANGLE_CAPTURE(GetUniformfv, isCallValid, context, programPacked, locationPacked, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetUniformiv,
          "context = %d, program = %u, location = %d, params = 0x%016" PRIxPTR "", CID(context),
          program, location, (uintptr_t)params);

    if (context)
    {
        ShaderProgramID programPacked  = PackParam<ShaderProgramID>(program);
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetUniformiv(context, programPacked, locationPacked, params));
        if (isCallValid)
        {
            context->getUniformiv(programPacked, locationPacked, params);
        }
        ANGLE_CAPTURE(GetUniformiv, isCallValid, context, programPacked, locationPacked, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetVertexAttribPointerv,
          "context = %d, index = %u, pname = %s, pointer = 0x%016" PRIxPTR "", CID(context), index,
          GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)pointer);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateGetVertexAttribPointerv(context, index, pname, pointer));
        if (isCallValid)
        {
            context->getVertexAttribPointerv(index, pname, pointer);
        }
        ANGLE_CAPTURE(GetVertexAttribPointerv, isCallValid, context, index, pname, pointer);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetVertexAttribfv,
          "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), index,
          GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)params);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGetVertexAttribfv(context, index, pname, params));
        if (isCallValid)
        {
            context->getVertexAttribfv(index, pname, params);
        }
        ANGLE_CAPTURE(GetVertexAttribfv, isCallValid, context, index, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLGetVertexAttribiv,
          "context = %d, index = %u, pname = %s, params = 0x%016" PRIxPTR "", CID(context), index,
          GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)params);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGetVertexAttribiv(context, index, pname, params));
        if (isCallValid)
        {
            context->getVertexAttribiv(index, pname, params);
        }
        ANGLE_CAPTURE(GetVertexAttribiv, isCallValid, context, index, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Hint(GLenum target, GLenum mode)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLHint, "context = %d, target = %s, mode = %s", CID(context),
          GLenumToString(GLenumGroup::HintTarget, target),
          GLenumToString(GLenumGroup::HintMode, mode));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateHint(context, target, mode));
        if (isCallValid)
        {
            context->hint(target, mode);
        }
        ANGLE_CAPTURE(Hint, isCallValid, context, target, mode);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsBuffer, "context = %d, buffer = %u", CID(context), buffer);

    GLboolean returnValue;
    if (context)
    {
        BufferID bufferPacked                                 = PackParam<BufferID>(buffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateIsBuffer(context, bufferPacked));
        if (isCallValid)
        {
            returnValue = context->isBuffer(bufferPacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsBuffer, GLboolean>();
        }
        ANGLE_CAPTURE(IsBuffer, isCallValid, context, bufferPacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsBuffer, GLboolean>();
    }
    return returnValue;
}

GLboolean GL_APIENTRY IsEnabled(GLenum cap)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsEnabled, "context = %d, cap = %s", CID(context),
          GLenumToString(GLenumGroup::EnableCap, cap));

    GLboolean returnValue;
    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateIsEnabled(context, cap));
        if (isCallValid)
        {
            returnValue = context->isEnabled(cap);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsEnabled, GLboolean>();
        }
        ANGLE_CAPTURE(IsEnabled, isCallValid, context, cap, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsEnabled, GLboolean>();
    }
    return returnValue;
}

GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsFramebuffer, "context = %d, framebuffer = %u", CID(context), framebuffer);

    GLboolean returnValue;
    if (context)
    {
        FramebufferID framebufferPacked = PackParam<FramebufferID>(framebuffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateIsFramebuffer(context, framebufferPacked));
        if (isCallValid)
        {
            returnValue = context->isFramebuffer(framebufferPacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsFramebuffer, GLboolean>();
        }
        ANGLE_CAPTURE(IsFramebuffer, isCallValid, context, framebufferPacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsFramebuffer, GLboolean>();
    }
    return returnValue;
}

GLboolean GL_APIENTRY IsProgram(GLuint program)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsProgram, "context = %d, program = %u", CID(context), program);

    GLboolean returnValue;
    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateIsProgram(context, programPacked));
        if (isCallValid)
        {
            returnValue = context->isProgram(programPacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsProgram, GLboolean>();
        }
        ANGLE_CAPTURE(IsProgram, isCallValid, context, programPacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsProgram, GLboolean>();
    }
    return returnValue;
}

GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsRenderbuffer, "context = %d, renderbuffer = %u", CID(context), renderbuffer);

    GLboolean returnValue;
    if (context)
    {
        RenderbufferID renderbufferPacked = PackParam<RenderbufferID>(renderbuffer);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateIsRenderbuffer(context, renderbufferPacked));
        if (isCallValid)
        {
            returnValue = context->isRenderbuffer(renderbufferPacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsRenderbuffer, GLboolean>();
        }
        ANGLE_CAPTURE(IsRenderbuffer, isCallValid, context, renderbufferPacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsRenderbuffer, GLboolean>();
    }
    return returnValue;
}

GLboolean GL_APIENTRY IsShader(GLuint shader)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsShader, "context = %d, shader = %u", CID(context), shader);

    GLboolean returnValue;
    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateIsShader(context, shaderPacked));
        if (isCallValid)
        {
            returnValue = context->isShader(shaderPacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsShader, GLboolean>();
        }
        ANGLE_CAPTURE(IsShader, isCallValid, context, shaderPacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsShader, GLboolean>();
    }
    return returnValue;
}

GLboolean GL_APIENTRY IsTexture(GLuint texture)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLIsTexture, "context = %d, texture = %u", CID(context), texture);

    GLboolean returnValue;
    if (context)
    {
        TextureID texturePacked                               = PackParam<TextureID>(texture);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateIsTexture(context, texturePacked));
        if (isCallValid)
        {
            returnValue = context->isTexture(texturePacked);
        }
        else
        {
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsTexture, GLboolean>();
        }
        ANGLE_CAPTURE(IsTexture, isCallValid, context, texturePacked, returnValue);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
        returnValue = GetDefaultReturnValue<angle::EntryPoint::GLIsTexture, GLboolean>();
    }
    return returnValue;
}

void GL_APIENTRY LineWidth(GLfloat width)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLLineWidth, "context = %d, width = %f", CID(context), width);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateLineWidth(context, width));
        if (isCallValid)
        {
            context->lineWidth(width);
        }
        ANGLE_CAPTURE(LineWidth, isCallValid, context, width);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY LinkProgram(GLuint program)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLLinkProgram, "context = %d, program = %u", CID(context), program);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateLinkProgram(context, programPacked));
        if (isCallValid)
        {
            context->linkProgram(programPacked);
        }
        ANGLE_CAPTURE(LinkProgram, isCallValid, context, programPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLPixelStorei, "context = %d, pname = %s, param = %d", CID(context),
          GLenumToString(GLenumGroup::PixelStoreParameter, pname), param);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidatePixelStorei(context, pname, param));
        if (isCallValid)
        {
            context->pixelStorei(pname, param);
        }
        ANGLE_CAPTURE(PixelStorei, isCallValid, context, pname, param);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLPolygonOffset, "context = %d, factor = %f, units = %f", CID(context), factor,
          units);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidatePolygonOffset(context, factor, units));
        if (isCallValid)
        {
            context->polygonOffset(factor, units);
        }
        ANGLE_CAPTURE(PolygonOffset, isCallValid, context, factor, units);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ReadPixels(GLint x,
                            GLint y,
                            GLsizei width,
                            GLsizei height,
                            GLenum format,
                            GLenum type,
                            void *pixels)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLReadPixels,
          "context = %d, x = %d, y = %d, width = %d, height = %d, format = %s, type = %s, pixels = "
          "0x%016" PRIxPTR "",
          CID(context), x, y, width, height, GLenumToString(GLenumGroup::PixelFormat, format),
          GLenumToString(GLenumGroup::PixelType, type), (uintptr_t)pixels);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateReadPixels(context, x, y, width, height, format, type, pixels));
        if (isCallValid)
        {
            context->readPixels(x, y, width, height, format, type, pixels);
        }
        ANGLE_CAPTURE(ReadPixels, isCallValid, context, x, y, width, height, format, type, pixels);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ReleaseShaderCompiler()
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLReleaseShaderCompiler, "context = %d", CID(context));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateReleaseShaderCompiler(context));
        if (isCallValid)
        {
            context->releaseShaderCompiler();
        }
        ANGLE_CAPTURE(ReleaseShaderCompiler, isCallValid, context);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY RenderbufferStorage(GLenum target,
                                     GLenum internalformat,
                                     GLsizei width,
                                     GLsizei height)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLRenderbufferStorage,
          "context = %d, target = %s, internalformat = %s, width = %d, height = %d", CID(context),
          GLenumToString(GLenumGroup::RenderbufferTarget, target),
          GLenumToString(GLenumGroup::InternalFormat, internalformat), width, height);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateRenderbufferStorage(context, target, internalformat, width, height));
        if (isCallValid)
        {
            context->renderbufferStorage(target, internalformat, width, height);
        }
        ANGLE_CAPTURE(RenderbufferStorage, isCallValid, context, target, internalformat, width,
                      height);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLSampleCoverage, "context = %d, value = %f, invert = %s", CID(context), value,
          GLbooleanToString(invert));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateSampleCoverage(context, value, invert));
        if (isCallValid)
        {
            context->sampleCoverage(value, invert);
        }
        ANGLE_CAPTURE(SampleCoverage, isCallValid, context, value, invert);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLScissor, "context = %d, x = %d, y = %d, width = %d, height = %d", CID(context),
          x, y, width, height);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateScissor(context, x, y, width, height));
        if (isCallValid)
        {
            context->scissor(x, y, width, height);
        }
        ANGLE_CAPTURE(Scissor, isCallValid, context, x, y, width, height);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ShaderBinary(GLsizei count,
                              const GLuint *shaders,
                              GLenum binaryformat,
                              const void *binary,
                              GLsizei length)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLShaderBinary,
          "context = %d, count = %d, shaders = 0x%016" PRIxPTR
          ", binaryformat = %s, binary = 0x%016" PRIxPTR ", length = %d",
          CID(context), count, (uintptr_t)shaders,
          GLenumToString(GLenumGroup::DefaultGroup, binaryformat), (uintptr_t)binary, length);

    if (context)
    {
        const ShaderProgramID *shadersPacked = PackParam<const ShaderProgramID *>(shaders);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateShaderBinary(context, count, shadersPacked, binaryformat, binary, length));
        if (isCallValid)
        {
            context->shaderBinary(count, shadersPacked, binaryformat, binary, length);
        }
        ANGLE_CAPTURE(ShaderBinary, isCallValid, context, count, shadersPacked, binaryformat,
                      binary, length);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ShaderSource(GLuint shader,
                              GLsizei count,
                              const GLchar *const *string,
                              const GLint *length)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLShaderSource,
          "context = %d, shader = %u, count = %d, string = 0x%016" PRIxPTR
          ", length = 0x%016" PRIxPTR "",
          CID(context), shader, count, (uintptr_t)string, (uintptr_t)length);

    if (context)
    {
        ShaderProgramID shaderPacked                          = PackParam<ShaderProgramID>(shader);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateShaderSource(context, shaderPacked, count, string, length));
        if (isCallValid)
        {
            context->shaderSource(shaderPacked, count, string, length);
        }
        ANGLE_CAPTURE(ShaderSource, isCallValid, context, shaderPacked, count, string, length);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLStencilFunc, "context = %d, func = %s, ref = %d, mask = %u", CID(context),
          GLenumToString(GLenumGroup::StencilFunction, func), ref, mask);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateStencilFunc(context, func, ref, mask));
        if (isCallValid)
        {
            context->stencilFunc(func, ref, mask);
        }
        ANGLE_CAPTURE(StencilFunc, isCallValid, context, func, ref, mask);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLStencilFuncSeparate, "context = %d, face = %s, func = %s, ref = %d, mask = %u",
          CID(context), GLenumToString(GLenumGroup::StencilFaceDirection, face),
          GLenumToString(GLenumGroup::StencilFunction, func), ref, mask);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateStencilFuncSeparate(context, face, func, ref, mask));
        if (isCallValid)
        {
            context->stencilFuncSeparate(face, func, ref, mask);
        }
        ANGLE_CAPTURE(StencilFuncSeparate, isCallValid, context, face, func, ref, mask);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY StencilMask(GLuint mask)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLStencilMask, "context = %d, mask = %u", CID(context), mask);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateStencilMask(context, mask));
        if (isCallValid)
        {
            context->stencilMask(mask);
        }
        ANGLE_CAPTURE(StencilMask, isCallValid, context, mask);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLStencilMaskSeparate, "context = %d, face = %s, mask = %u", CID(context),
          GLenumToString(GLenumGroup::StencilFaceDirection, face), mask);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateStencilMaskSeparate(context, face, mask));
        if (isCallValid)
        {
            context->stencilMaskSeparate(face, mask);
        }
        ANGLE_CAPTURE(StencilMaskSeparate, isCallValid, context, face, mask);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLStencilOp, "context = %d, fail = %s, zfail = %s, zpass = %s", CID(context),
          GLenumToString(GLenumGroup::StencilOp, fail),
          GLenumToString(GLenumGroup::StencilOp, zfail),
          GLenumToString(GLenumGroup::StencilOp, zpass));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateStencilOp(context, fail, zfail, zpass));
        if (isCallValid)
        {
            context->stencilOp(fail, zfail, zpass);
        }
        ANGLE_CAPTURE(StencilOp, isCallValid, context, fail, zfail, zpass);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLStencilOpSeparate,
          "context = %d, face = %s, sfail = %s, dpfail = %s, dppass = %s", CID(context),
          GLenumToString(GLenumGroup::StencilFaceDirection, face),
          GLenumToString(GLenumGroup::StencilOp, sfail),
          GLenumToString(GLenumGroup::StencilOp, dpfail),
          GLenumToString(GLenumGroup::StencilOp, dppass));

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateStencilOpSeparate(context, face, sfail, dpfail, dppass));
        if (isCallValid)
        {
            context->stencilOpSeparate(face, sfail, dpfail, dppass);
        }
        ANGLE_CAPTURE(StencilOpSeparate, isCallValid, context, face, sfail, dpfail, dppass);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY TexImage2D(GLenum target,
                            GLint level,
                            GLint internalformat,
                            GLsizei width,
                            GLsizei height,
                            GLint border,
                            GLenum format,
                            GLenum type,
                            const void *pixels)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLTexImage2D,
          "context = %d, target = %s, level = %d, internalformat = %d, width = %d, height = %d, "
          "border = %d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), level, internalformat,
          width, height, border, GLenumToString(GLenumGroup::PixelFormat, format),
          GLenumToString(GLenumGroup::PixelType, type), (uintptr_t)pixels);

    if (context)
    {
        TextureTarget targetPacked                            = PackParam<TextureTarget>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateTexImage2D(context, targetPacked, level, internalformat, width,
                                               height, border, format, type, pixels));
        if (isCallValid)
        {
            context->texImage2D(targetPacked, level, internalformat, width, height, border, format,
                                type, pixels);
        }
        ANGLE_CAPTURE(TexImage2D, isCallValid, context, targetPacked, level, internalformat, width,
                      height, border, format, type, pixels);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLTexParameterf, "context = %d, target = %s, pname = %s, param = %f",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::TextureParameterName, pname), param);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateTexParameterf(context, targetPacked, pname, param));
        if (isCallValid)
        {
            context->texParameterf(targetPacked, pname, param);
        }
        ANGLE_CAPTURE(TexParameterf, isCallValid, context, targetPacked, pname, param);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLTexParameterfv,
          "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::TextureParameterName, pname), (uintptr_t)params);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateTexParameterfv(context, targetPacked, pname, params));
        if (isCallValid)
        {
            context->texParameterfv(targetPacked, pname, params);
        }
        ANGLE_CAPTURE(TexParameterfv, isCallValid, context, targetPacked, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLTexParameteri, "context = %d, target = %s, pname = %s, param = %d",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::TextureParameterName, pname), param);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateTexParameteri(context, targetPacked, pname, param));
        if (isCallValid)
        {
            context->texParameteri(targetPacked, pname, param);
        }
        ANGLE_CAPTURE(TexParameteri, isCallValid, context, targetPacked, pname, param);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLTexParameteriv,
          "context = %d, target = %s, pname = %s, params = 0x%016" PRIxPTR "", CID(context),
          GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::TextureParameterName, pname), (uintptr_t)params);

    if (context)
    {
        TextureType targetPacked                              = PackParam<TextureType>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateTexParameteriv(context, targetPacked, pname, params));
        if (isCallValid)
        {
            context->texParameteriv(targetPacked, pname, params);
        }
        ANGLE_CAPTURE(TexParameteriv, isCallValid, context, targetPacked, pname, params);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY TexSubImage2D(GLenum target,
                               GLint level,
                               GLint xoffset,
                               GLint yoffset,
                               GLsizei width,
                               GLsizei height,
                               GLenum format,
                               GLenum type,
                               const void *pixels)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLTexSubImage2D,
          "context = %d, target = %s, level = %d, xoffset = %d, yoffset = %d, width = %d, height = "
          "%d, format = %s, type = %s, pixels = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), level, xoffset, yoffset,
          width, height, GLenumToString(GLenumGroup::PixelFormat, format),
          GLenumToString(GLenumGroup::PixelType, type), (uintptr_t)pixels);

    if (context)
    {
        TextureTarget targetPacked                            = PackParam<TextureTarget>(target);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateTexSubImage2D(context, targetPacked, level, xoffset, yoffset,
                                                  width, height, format, type, pixels));
        if (isCallValid)
        {
            context->texSubImage2D(targetPacked, level, xoffset, yoffset, width, height, format,
                                   type, pixels);
        }
        ANGLE_CAPTURE(TexSubImage2D, isCallValid, context, targetPacked, level, xoffset, yoffset,
                      width, height, format, type, pixels);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform1f(GLint location, GLfloat v0)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform1f, "context = %d, location = %d, v0 = %f", CID(context), location, v0);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUniform1f(context, locationPacked, v0));
        if (isCallValid)
        {
            context->uniform1f(locationPacked, v0);
        }
        ANGLE_CAPTURE(Uniform1f, isCallValid, context, locationPacked, v0);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform1fv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform1fv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform1fv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform1fv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform1i(GLint location, GLint v0)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform1i, "context = %d, location = %d, v0 = %d", CID(context), location, v0);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUniform1i(context, locationPacked, v0));
        if (isCallValid)
        {
            context->uniform1i(locationPacked, v0);
        }
        ANGLE_CAPTURE(Uniform1i, isCallValid, context, locationPacked, v0);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform1iv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform1iv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform1iv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform1iv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform2f(GLint location, GLfloat v0, GLfloat v1)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform2f, "context = %d, location = %d, v0 = %f, v1 = %f", CID(context),
          location, v0, v1);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUniform2f(context, locationPacked, v0, v1));
        if (isCallValid)
        {
            context->uniform2f(locationPacked, v0, v1);
        }
        ANGLE_CAPTURE(Uniform2f, isCallValid, context, locationPacked, v0, v1);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform2fv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform2fv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform2fv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform2fv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform2i(GLint location, GLint v0, GLint v1)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform2i, "context = %d, location = %d, v0 = %d, v1 = %d", CID(context),
          location, v0, v1);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUniform2i(context, locationPacked, v0, v1));
        if (isCallValid)
        {
            context->uniform2i(locationPacked, v0, v1);
        }
        ANGLE_CAPTURE(Uniform2i, isCallValid, context, locationPacked, v0, v1);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform2iv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform2iv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform2iv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform2iv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform3f, "context = %d, location = %d, v0 = %f, v1 = %f, v2 = %f",
          CID(context), location, v0, v1, v2);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUniform3f(context, locationPacked, v0, v1, v2));
        if (isCallValid)
        {
            context->uniform3f(locationPacked, v0, v1, v2);
        }
        ANGLE_CAPTURE(Uniform3f, isCallValid, context, locationPacked, v0, v1, v2);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform3fv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform3fv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform3fv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform3fv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform3i(GLint location, GLint v0, GLint v1, GLint v2)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform3i, "context = %d, location = %d, v0 = %d, v1 = %d, v2 = %d",
          CID(context), location, v0, v1, v2);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUniform3i(context, locationPacked, v0, v1, v2));
        if (isCallValid)
        {
            context->uniform3i(locationPacked, v0, v1, v2);
        }
        ANGLE_CAPTURE(Uniform3i, isCallValid, context, locationPacked, v0, v1, v2);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform3iv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform3iv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform3iv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform3iv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform4f, "context = %d, location = %d, v0 = %f, v1 = %f, v2 = %f, v3 = %f",
          CID(context), location, v0, v1, v2, v3);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform4f(context, locationPacked, v0, v1, v2, v3));
        if (isCallValid)
        {
            context->uniform4f(locationPacked, v0, v1, v2, v3);
        }
        ANGLE_CAPTURE(Uniform4f, isCallValid, context, locationPacked, v0, v1, v2, v3);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform4fv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform4fv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform4fv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform4fv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform4i, "context = %d, location = %d, v0 = %d, v1 = %d, v2 = %d, v3 = %d",
          CID(context), location, v0, v1, v2, v3);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform4i(context, locationPacked, v0, v1, v2, v3));
        if (isCallValid)
        {
            context->uniform4i(locationPacked, v0, v1, v2, v3);
        }
        ANGLE_CAPTURE(Uniform4i, isCallValid, context, locationPacked, v0, v1, v2, v3);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniform4iv,
          "context = %d, location = %d, count = %d, value = 0x%016" PRIxPTR "", CID(context),
          location, count, (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateUniform4iv(context, locationPacked, count, value));
        if (isCallValid)
        {
            context->uniform4iv(locationPacked, count, value);
        }
        ANGLE_CAPTURE(Uniform4iv, isCallValid, context, locationPacked, count, value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY UniformMatrix2fv(GLint location,
                                  GLsizei count,
                                  GLboolean transpose,
                                  const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniformMatrix2fv,
          "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "",
          CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateUniformMatrix2fv(context, locationPacked, count, transpose, value));
        if (isCallValid)
        {
            context->uniformMatrix2fv(locationPacked, count, transpose, value);
        }
        ANGLE_CAPTURE(UniformMatrix2fv, isCallValid, context, locationPacked, count, transpose,
                      value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY UniformMatrix3fv(GLint location,
                                  GLsizei count,
                                  GLboolean transpose,
                                  const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniformMatrix3fv,
          "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "",
          CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateUniformMatrix3fv(context, locationPacked, count, transpose, value));
        if (isCallValid)
        {
            context->uniformMatrix3fv(locationPacked, count, transpose, value);
        }
        ANGLE_CAPTURE(UniformMatrix3fv, isCallValid, context, locationPacked, count, transpose,
                      value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY UniformMatrix4fv(GLint location,
                                  GLsizei count,
                                  GLboolean transpose,
                                  const GLfloat *value)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUniformMatrix4fv,
          "context = %d, location = %d, count = %d, transpose = %s, value = 0x%016" PRIxPTR "",
          CID(context), location, count, GLbooleanToString(transpose), (uintptr_t)value);

    if (context)
    {
        UniformLocation locationPacked = PackParam<UniformLocation>(location);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateUniformMatrix4fv(context, locationPacked, count, transpose, value));
        if (isCallValid)
        {
            context->uniformMatrix4fv(locationPacked, count, transpose, value);
        }
        ANGLE_CAPTURE(UniformMatrix4fv, isCallValid, context, locationPacked, count, transpose,
                      value);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY UseProgram(GLuint program)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLUseProgram, "context = %d, program = %u", CID(context), program);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateUseProgram(context, programPacked));
        if (isCallValid)
        {
            context->useProgram(programPacked);
        }
        ANGLE_CAPTURE(UseProgram, isCallValid, context, programPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY ValidateProgram(GLuint program)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLValidateProgram, "context = %d, program = %u", CID(context), program);

    if (context)
    {
        ShaderProgramID programPacked                         = PackParam<ShaderProgramID>(program);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateValidateProgram(context, programPacked));
        if (isCallValid)
        {
            context->validateProgram(programPacked);
        }
        ANGLE_CAPTURE(ValidateProgram, isCallValid, context, programPacked);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib1f, "context = %d, index = %u, x = %f", CID(context), index, x);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateVertexAttrib1f(context, index, x));
        if (isCallValid)
        {
            context->vertexAttrib1f(index, x);
        }
        ANGLE_CAPTURE(VertexAttrib1f, isCallValid, context, index, x);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat *v)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib1fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "",
          CID(context), index, (uintptr_t)v);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib1fv(context, index, v));
        if (isCallValid)
        {
            context->vertexAttrib1fv(index, v);
        }
        ANGLE_CAPTURE(VertexAttrib1fv, isCallValid, context, index, v);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib2f, "context = %d, index = %u, x = %f, y = %f", CID(context),
          index, x, y);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib2f(context, index, x, y));
        if (isCallValid)
        {
            context->vertexAttrib2f(index, x, y);
        }
        ANGLE_CAPTURE(VertexAttrib2f, isCallValid, context, index, x, y);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat *v)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib2fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "",
          CID(context), index, (uintptr_t)v);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib2fv(context, index, v));
        if (isCallValid)
        {
            context->vertexAttrib2fv(index, v);
        }
        ANGLE_CAPTURE(VertexAttrib2fv, isCallValid, context, index, v);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib3f, "context = %d, index = %u, x = %f, y = %f, z = %f",
          CID(context), index, x, y, z);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib3f(context, index, x, y, z));
        if (isCallValid)
        {
            context->vertexAttrib3f(index, x, y, z);
        }
        ANGLE_CAPTURE(VertexAttrib3f, isCallValid, context, index, x, y, z);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat *v)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib3fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "",
          CID(context), index, (uintptr_t)v);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib3fv(context, index, v));
        if (isCallValid)
        {
            context->vertexAttrib3fv(index, v);
        }
        ANGLE_CAPTURE(VertexAttrib3fv, isCallValid, context, index, v);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib4f, "context = %d, index = %u, x = %f, y = %f, z = %f, w = %f",
          CID(context), index, x, y, z, w);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib4f(context, index, x, y, z, w));
        if (isCallValid)
        {
            context->vertexAttrib4f(index, x, y, z, w);
        }
        ANGLE_CAPTURE(VertexAttrib4f, isCallValid, context, index, x, y, z, w);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat *v)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttrib4fv, "context = %d, index = %u, v = 0x%016" PRIxPTR "",
          CID(context), index, (uintptr_t)v);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateVertexAttrib4fv(context, index, v));
        if (isCallValid)
        {
            context->vertexAttrib4fv(index, v);
        }
        ANGLE_CAPTURE(VertexAttrib4fv, isCallValid, context, index, v);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY VertexAttribPointer(GLuint index,
                                     GLint size,
                                     GLenum type,
                                     GLboolean normalized,
                                     GLsizei stride,
                                     const void *pointer)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLVertexAttribPointer,
          "context = %d, index = %u, size = %d, type = %s, normalized = %s, stride = %d, pointer = "
          "0x%016" PRIxPTR "",
          CID(context), index, size, GLenumToString(GLenumGroup::VertexAttribPointerType, type),
          GLbooleanToString(normalized), stride, (uintptr_t)pointer);

    if (context)
    {
        VertexAttribType typePacked                           = PackParam<VertexAttribType>(type);
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                                      = (context->skipValidation() ||
                            ValidateVertexAttribPointer(context, index, size, typePacked,
                                                        normalized, stride, pointer));
        if (isCallValid)
        {
            context->vertexAttribPointer(index, size, typePacked, normalized, stride, pointer);
        }
        ANGLE_CAPTURE(VertexAttribPointer, isCallValid, context, index, size, typePacked,
                      normalized, stride, pointer);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}

void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
    Context *context = GetValidGlobalContext();
    EVENT(context, GLViewport, "context = %d, x = %d, y = %d, width = %d, height = %d",
          CID(context), x, y, width, height);

    if (context)
    {
        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateViewport(context, x, y, width, height));
        if (isCallValid)
        {
            context->viewport(x, y, width, height);
        }
        ANGLE_CAPTURE(Viewport, isCallValid, context, x, y, width, height);
    }
    else
    {
        GenerateContextLostErrorOnCurrentGlobalContext();
    }
}
}  // namespace gl
