// GENERATED FILE - DO NOT EDIT.
// Generated by generate_entry_points.py using data from gl.xml.
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// entry_points_gl_4_2_autogen.cpp:
//   Defines the GL 4.2 entry points.

#include "libGL/entry_points_gl_4_2_autogen.h"

#include "libANGLE/Context.h"
#include "libANGLE/Context.inl.h"
#include "libANGLE/entry_points_utils.h"
#include "libANGLE/gl_enum_utils.h"
#include "libANGLE/validationEGL.h"
#include "libANGLE/validationES.h"
#include "libANGLE/validationES1.h"
#include "libANGLE/validationES2.h"
#include "libANGLE/validationES3.h"
#include "libANGLE/validationES31.h"
#include "libANGLE/validationES32.h"
#include "libANGLE/validationESEXT.h"
#include "libANGLE/validationGL42_autogen.h"
#include "libGLESv2/global_state.h"

namespace gl
{
void GL_APIENTRY BindImageTexture(GLuint unit,
                                  GLuint texture,
                                  GLint level,
                                  GLboolean layered,
                                  GLint layer,
                                  GLenum access,
                                  GLenum format)
{
    Context *context = GetValidGlobalContext();
    EVENT("glBindImageTexture",
          "context = %d, GLuint unit = %u, GLuint texture = %u, GLint level = %d, GLboolean "
          "layered = %s, GLint layer = %d, GLenum access = %s, GLenum format = %s",
          CID(context), unit, texture, level, GLbooleanToString(layered), layer,
          GLenumToString(GLenumGroup::BufferAccessARB, access),
          GLenumToString(GLenumGroup::InternalFormat, format));

    if (context)
    {
        TextureID texturePacked                       = FromGL<TextureID>(texture);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                              = (context->skipValidation() ||
                            ValidateBindImageTexture(context, unit, texturePacked, level, layered,
                                                     layer, access, format));
        if (isCallValid)
        {
            context->bindImageTexture(unit, texturePacked, level, layered, layer, access, format);
        }
        ANGLE_CAPTURE(BindImageTexture, isCallValid, context, unit, texturePacked, level, layered,
                      layer, access, format);
    }
}

void GL_APIENTRY DrawArraysInstancedBaseInstance(GLenum mode,
                                                 GLint first,
                                                 GLsizei count,
                                                 GLsizei instancecount,
                                                 GLuint baseinstance)
{
    Context *context = GetValidGlobalContext();
    EVENT("glDrawArraysInstancedBaseInstance",
          "context = %d, GLenum mode = %s, GLint first = %d, GLsizei count = %d, GLsizei "
          "instancecount = %d, GLuint baseinstance = %u",
          CID(context), GLenumToString(GLenumGroup::PrimitiveType, mode), first, count,
          instancecount, baseinstance);

    if (context)
    {
        PrimitiveMode modePacked                      = FromGL<PrimitiveMode>(mode);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                              = (context->skipValidation() ||
                            ValidateDrawArraysInstancedBaseInstance(
                                context, modePacked, first, count, instancecount, baseinstance));
        if (isCallValid)
        {
            context->drawArraysInstancedBaseInstance(modePacked, first, count, instancecount,
                                                     baseinstance);
        }
        ANGLE_CAPTURE(DrawArraysInstancedBaseInstance, isCallValid, context, modePacked, first,
                      count, instancecount, baseinstance);
    }
}

void GL_APIENTRY DrawElementsInstancedBaseInstance(GLenum mode,
                                                   GLsizei count,
                                                   GLenum type,
                                                   const void *indices,
                                                   GLsizei instancecount,
                                                   GLuint baseinstance)
{
    Context *context = GetValidGlobalContext();
    EVENT("glDrawElementsInstancedBaseInstance",
          "context = %d, GLenum mode = %s, GLsizei count = %d, GLenum type = %s, const void "
          "*indices = 0x%016" PRIxPTR ", GLsizei instancecount = %d, GLuint baseinstance = %u",
          CID(context), GLenumToString(GLenumGroup::PrimitiveType, mode), count,
          GLenumToString(GLenumGroup::PrimitiveType, type), (uintptr_t)indices, instancecount,
          baseinstance);

    if (context)
    {
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                              = (context->skipValidation() ||
                            ValidateDrawElementsInstancedBaseInstance(
                                context, mode, count, type, indices, instancecount, baseinstance));
        if (isCallValid)
        {
            context->drawElementsInstancedBaseInstance(mode, count, type, indices, instancecount,
                                                       baseinstance);
        }
        ANGLE_CAPTURE(DrawElementsInstancedBaseInstance, isCallValid, context, mode, count, type,
                      indices, instancecount, baseinstance);
    }
}

void GL_APIENTRY DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
                                                             GLsizei count,
                                                             GLenum type,
                                                             const void *indices,
                                                             GLsizei instancecount,
                                                             GLint basevertex,
                                                             GLuint baseinstance)
{
    Context *context = GetValidGlobalContext();
    EVENT("glDrawElementsInstancedBaseVertexBaseInstance",
          "context = %d, GLenum mode = %s, GLsizei count = %d, GLenum type = %s, const void "
          "*indices = 0x%016" PRIxPTR
          ", GLsizei instancecount = %d, GLint basevertex = %d, GLuint baseinstance = %u",
          CID(context), GLenumToString(GLenumGroup::PrimitiveType, mode), count,
          GLenumToString(GLenumGroup::PrimitiveType, type), (uintptr_t)indices, instancecount,
          basevertex, baseinstance);

    if (context)
    {
        PrimitiveMode modePacked                      = FromGL<PrimitiveMode>(mode);
        DrawElementsType typePacked                   = FromGL<DrawElementsType>(type);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDrawElementsInstancedBaseVertexBaseInstance(
                                              context, modePacked, count, typePacked, indices,
                                              instancecount, basevertex, baseinstance));
        if (isCallValid)
        {
            context->drawElementsInstancedBaseVertexBaseInstance(
                modePacked, count, typePacked, indices, instancecount, basevertex, baseinstance);
        }
        ANGLE_CAPTURE(DrawElementsInstancedBaseVertexBaseInstance, isCallValid, context, modePacked,
                      count, typePacked, indices, instancecount, basevertex, baseinstance);
    }
}

void GL_APIENTRY DrawTransformFeedbackInstanced(GLenum mode, GLuint id, GLsizei instancecount)
{
    Context *context = GetValidGlobalContext();
    EVENT("glDrawTransformFeedbackInstanced",
          "context = %d, GLenum mode = %s, GLuint id = %u, GLsizei instancecount = %d",
          CID(context), GLenumToString(GLenumGroup::PrimitiveType, mode), id, instancecount);

    if (context)
    {
        TransformFeedbackID idPacked                  = FromGL<TransformFeedbackID>(id);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateDrawTransformFeedbackInstanced(context, mode, idPacked, instancecount));
        if (isCallValid)
        {
            context->drawTransformFeedbackInstanced(mode, idPacked, instancecount);
        }
        ANGLE_CAPTURE(DrawTransformFeedbackInstanced, isCallValid, context, mode, idPacked,
                      instancecount);
    }
}

void GL_APIENTRY DrawTransformFeedbackStreamInstanced(GLenum mode,
                                                      GLuint id,
                                                      GLuint stream,
                                                      GLsizei instancecount)
{
    Context *context = GetValidGlobalContext();
    EVENT("glDrawTransformFeedbackStreamInstanced",
          "context = %d, GLenum mode = %s, GLuint id = %u, GLuint stream = %u, GLsizei "
          "instancecount = %d",
          CID(context), GLenumToString(GLenumGroup::PrimitiveType, mode), id, stream,
          instancecount);

    if (context)
    {
        TransformFeedbackID idPacked                  = FromGL<TransformFeedbackID>(id);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateDrawTransformFeedbackStreamInstanced(
                                              context, mode, idPacked, stream, instancecount));
        if (isCallValid)
        {
            context->drawTransformFeedbackStreamInstanced(mode, idPacked, stream, instancecount);
        }
        ANGLE_CAPTURE(DrawTransformFeedbackStreamInstanced, isCallValid, context, mode, idPacked,
                      stream, instancecount);
    }
}

void GL_APIENTRY GetActiveAtomicCounterBufferiv(GLuint program,
                                                GLuint bufferIndex,
                                                GLenum pname,
                                                GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT("glGetActiveAtomicCounterBufferiv",
          "context = %d, GLuint program = %u, GLuint bufferIndex = %u, GLenum pname = %s, GLint "
          "*params = 0x%016" PRIxPTR "",
          CID(context), program, bufferIndex,
          GLenumToString(GLenumGroup::AtomicCounterBufferPName, pname), (uintptr_t)params);

    if (context)
    {
        ShaderProgramID programPacked                 = FromGL<ShaderProgramID>(program);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() || ValidateGetActiveAtomicCounterBufferiv(
                                              context, programPacked, bufferIndex, pname, params));
        if (isCallValid)
        {
            context->getActiveAtomicCounterBufferiv(programPacked, bufferIndex, pname, params);
        }
        ANGLE_CAPTURE(GetActiveAtomicCounterBufferiv, isCallValid, context, programPacked,
                      bufferIndex, pname, params);
    }
}

void GL_APIENTRY GetInternalformativ(GLenum target,
                                     GLenum internalformat,
                                     GLenum pname,
                                     GLsizei bufSize,
                                     GLint *params)
{
    Context *context = GetValidGlobalContext();
    EVENT("glGetInternalformativ",
          "context = %d, GLenum target = %s, GLenum internalformat = %s, GLenum pname = %s, "
          "GLsizei bufSize = %d, GLint *params = 0x%016" PRIxPTR "",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target),
          GLenumToString(GLenumGroup::InternalFormat, internalformat),
          GLenumToString(GLenumGroup::InternalFormatPName, pname), bufSize, (uintptr_t)params);

    if (context)
    {
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateGetInternalformativ(context, target, internalformat, pname, bufSize, params));
        if (isCallValid)
        {
            context->getInternalformativ(target, internalformat, pname, bufSize, params);
        }
        ANGLE_CAPTURE(GetInternalformativ, isCallValid, context, target, internalformat, pname,
                      bufSize, params);
    }
}

void GL_APIENTRY MemoryBarrier(GLbitfield barriers)
{
    Context *context = GetValidGlobalContext();
    EVENT("glMemoryBarrier", "context = %d, GLbitfield barriers = %s", CID(context),
          GLbitfieldToString(GLenumGroup::MemoryBarrierMask, barriers).c_str());

    if (context)
    {
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid = (context->skipValidation() || ValidateMemoryBarrier(context, barriers));
        if (isCallValid)
        {
            context->memoryBarrier(barriers);
        }
        ANGLE_CAPTURE(MemoryBarrier, isCallValid, context, barriers);
    }
}

void GL_APIENTRY TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
{
    Context *context = GetValidGlobalContext();
    EVENT("glTexStorage1D",
          "context = %d, GLenum target = %s, GLsizei levels = %d, GLenum internalformat = %s, "
          "GLsizei width = %d",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), levels,
          GLenumToString(GLenumGroup::InternalFormat, internalformat), width);

    if (context)
    {
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                              = (context->skipValidation() ||
                            ValidateTexStorage1D(context, target, levels, internalformat, width));
        if (isCallValid)
        {
            context->texStorage1D(target, levels, internalformat, width);
        }
        ANGLE_CAPTURE(TexStorage1D, isCallValid, context, target, levels, internalformat, width);
    }
}

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

    if (context)
    {
        TextureType targetPacked                      = FromGL<TextureType>(target);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid =
            (context->skipValidation() ||
             ValidateTexStorage2D(context, targetPacked, levels, internalformat, width, height));
        if (isCallValid)
        {
            context->texStorage2D(targetPacked, levels, internalformat, width, height);
        }
        ANGLE_CAPTURE(TexStorage2D, isCallValid, context, targetPacked, levels, internalformat,
                      width, height);
    }
}

void GL_APIENTRY TexStorage3D(GLenum target,
                              GLsizei levels,
                              GLenum internalformat,
                              GLsizei width,
                              GLsizei height,
                              GLsizei depth)
{
    Context *context = GetValidGlobalContext();
    EVENT("glTexStorage3D",
          "context = %d, GLenum target = %s, GLsizei levels = %d, GLenum internalformat = %s, "
          "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d",
          CID(context), GLenumToString(GLenumGroup::TextureTarget, target), levels,
          GLenumToString(GLenumGroup::InternalFormat, internalformat), width, height, depth);

    if (context)
    {
        TextureType targetPacked                      = FromGL<TextureType>(target);
        std::unique_lock<std::mutex> shareContextLock = GetShareGroupLock(context);
        bool isCallValid                              = (context->skipValidation() ||
                            ValidateTexStorage3D(context, targetPacked, levels, internalformat,
                                                 width, height, depth));
        if (isCallValid)
        {
            context->texStorage3D(targetPacked, levels, internalformat, width, height, depth);
        }
        ANGLE_CAPTURE(TexStorage3D, isCallValid, context, targetPacked, levels, internalformat,
                      width, height, depth);
    }
}
}  // namespace gl
