#pragma once

#include <AK/Assertions.h>
#include <AK/StdLibExtras.h>
#include <AK/StringView.h>
#include <AK/Types.h>
#include <LibWeb/Export.h>
#include <LibWeb/WebGL/GLFunctions.h>

namespace Web::WebGL {

#define ENUMERATE_WEBGL_COMMANDS(V) \
    V(ActiveTexture) \
    V(AttachShader) \
    V(BeginQuery) \
    V(BeginTransformFeedback) \
    V(BindAttribLocation) \
    V(BindBuffer) \
    V(BindBufferBase) \
    V(BindBufferRange) \
    V(BindFramebuffer) \
    V(BindRenderbuffer) \
    V(BindSampler) \
    V(BindTexture) \
    V(BindTransformFeedback) \
    V(BindVertexArray) \
    V(BindVertexArrayOES) \
    V(BlendColor) \
    V(BlendEquation) \
    V(BlendEquationSeparate) \
    V(BlendFunc) \
    V(BlendFuncSeparate) \
    V(BlitFramebuffer) \
    V(BufferData) \
    V(BufferSubData) \
    V(Clear) \
    V(ClearBufferfi) \
    V(ClearBufferfv) \
    V(ClearBufferiv) \
    V(ClearBufferuiv) \
    V(ClearColor) \
    V(ClearDepthf) \
    V(ClearStencil) \
    V(ColorMask) \
    V(CompileShader) \
    V(CompressedTexImage2DRobustANGLE) \
    V(CompressedTexImage3DRobustANGLE) \
    V(CompressedTexSubImage2DRobustANGLE) \
    V(CompressedTexSubImage3DRobustANGLE) \
    V(CopyBufferSubData) \
    V(CopyTexImage2D) \
    V(CopyTexSubImage2D) \
    V(CreateProgram) \
    V(CreateShader) \
    V(CullFace) \
    V(DeleteBuffers) \
    V(DeleteFramebuffers) \
    V(DeleteProgram) \
    V(DeleteQueries) \
    V(DeleteRenderbuffers) \
    V(DeleteSamplers) \
    V(DeleteShader) \
    V(DeleteSync) \
    V(DeleteTextures) \
    V(DeleteTransformFeedbacks) \
    V(DeleteVertexArrays) \
    V(DeleteVertexArraysOES) \
    V(DepthFunc) \
    V(DepthMask) \
    V(DepthRangef) \
    V(DetachShader) \
    V(Disable) \
    V(DisableVertexAttribArray) \
    V(DrawArrays) \
    V(DrawArraysInstanced) \
    V(DrawArraysInstancedANGLE) \
    V(DrawBuffers) \
    V(DrawBuffersEXT) \
    V(DrawElements) \
    V(DrawElementsInstanced) \
    V(DrawElementsInstancedANGLE) \
    V(DrawRangeElements) \
    V(Enable) \
    V(EnableVertexAttribArray) \
    V(EndQuery) \
    V(EndTransformFeedback) \
    V(FenceSync) \
    V(Flush) \
    V(FramebufferRenderbuffer) \
    V(FramebufferTexture2D) \
    V(FramebufferTextureLayer) \
    V(FrontFace) \
    V(GenBuffers) \
    V(GenFramebuffers) \
    V(GenQueries) \
    V(GenRenderbuffers) \
    V(GenSamplers) \
    V(GenTextures) \
    V(GenTransformFeedbacks) \
    V(GenVertexArrays) \
    V(GenVertexArraysOES) \
    V(GenerateMipmap) \
    V(Hint) \
    V(InvalidateFramebuffer) \
    V(InvalidateSubFramebuffer) \
    V(LineWidth) \
    V(LinkProgram) \
    V(PauseTransformFeedback) \
    V(PixelStorei) \
    V(PolygonOffset) \
    V(ReadBuffer) \
    V(RenderbufferStorage) \
    V(RenderbufferStorageMultisample) \
    V(RequestExtensionANGLE) \
    V(ResumeTransformFeedback) \
    V(SampleCoverage) \
    V(SamplerParameterf) \
    V(SamplerParameteri) \
    V(Scissor) \
    V(ShaderSource) \
    V(StencilFunc) \
    V(StencilFuncSeparate) \
    V(StencilMask) \
    V(StencilMaskSeparate) \
    V(StencilOp) \
    V(StencilOpSeparate) \
    V(TexImage2DRobustANGLE) \
    V(TexImage3DRobustANGLE) \
    V(TexParameterf) \
    V(TexParameteri) \
    V(TexStorage2D) \
    V(TexStorage3D) \
    V(TexSubImage2DRobustANGLE) \
    V(TexSubImage3DRobustANGLE) \
    V(TransformFeedbackVaryings) \
    V(Uniform1f) \
    V(Uniform1fv) \
    V(Uniform1i) \
    V(Uniform1iv) \
    V(Uniform1ui) \
    V(Uniform1uiv) \
    V(Uniform2f) \
    V(Uniform2fv) \
    V(Uniform2i) \
    V(Uniform2iv) \
    V(Uniform2ui) \
    V(Uniform2uiv) \
    V(Uniform3f) \
    V(Uniform3fv) \
    V(Uniform3i) \
    V(Uniform3iv) \
    V(Uniform3ui) \
    V(Uniform3uiv) \
    V(Uniform4f) \
    V(Uniform4fv) \
    V(Uniform4i) \
    V(Uniform4iv) \
    V(Uniform4ui) \
    V(Uniform4uiv) \
    V(UniformBlockBinding) \
    V(UniformMatrix2fv) \
    V(UniformMatrix2x3fv) \
    V(UniformMatrix2x4fv) \
    V(UniformMatrix3fv) \
    V(UniformMatrix3x2fv) \
    V(UniformMatrix3x4fv) \
    V(UniformMatrix4fv) \
    V(UniformMatrix4x2fv) \
    V(UniformMatrix4x3fv) \
    V(UseProgram) \
    V(ValidateProgram) \
    V(VertexAttrib1f) \
    V(VertexAttrib1fv) \
    V(VertexAttrib2f) \
    V(VertexAttrib2fv) \
    V(VertexAttrib3f) \
    V(VertexAttrib3fv) \
    V(VertexAttrib4f) \
    V(VertexAttrib4fv) \
    V(VertexAttribDivisor) \
    V(VertexAttribDivisorANGLE) \
    V(VertexAttribI4i) \
    V(VertexAttribI4iv) \
    V(VertexAttribI4ui) \
    V(VertexAttribI4uiv) \
    V(VertexAttribIPointer) \
    V(VertexAttribPointer) \
    V(Viewport) \
    V(WaitSync) \
    V(SetDrawingBufferSize) \
    V(ReadPixelsIntoPixelPackBuffer) \
    V(TexImage2DFromBitmap) \
    V(TexSubImage2DFromBitmap) \
    V(TexImage3DFromBitmap) \
    V(TexSubImage3DFromBitmap) \

enum class WebGLCommandType : u16 {
#define __ENUMERATE(name) name,
    ENUMERATE_WEBGL_COMMANDS(__ENUMERATE)
#undef __ENUMERATE
};

inline constexpr u16 webgl_command_type_count = 183;

WEB_API StringView to_string(WebGLCommandType);

namespace Commands {

struct ActiveTexture {
    static constexpr auto command_type = WebGLCommandType::ActiveTexture;
    GLenum texture {};
};

struct AttachShader {
    static constexpr auto command_type = WebGLCommandType::AttachShader;
    WebGLObjectId program {};
    WebGLObjectId shader {};
};

struct BeginQuery {
    static constexpr auto command_type = WebGLCommandType::BeginQuery;
    GLenum target {};
    WebGLObjectId id {};
};

struct BeginTransformFeedback {
    static constexpr auto command_type = WebGLCommandType::BeginTransformFeedback;
    GLenum primitive_mode {};
};

struct BindAttribLocation {
    static constexpr auto command_type = WebGLCommandType::BindAttribLocation;
    WebGLObjectId program {};
    GLuint index {};
    WebGLDataSpan name {};
};

struct BindBuffer {
    static constexpr auto command_type = WebGLCommandType::BindBuffer;
    GLenum target {};
    WebGLObjectId buffer {};
};

struct BindBufferBase {
    static constexpr auto command_type = WebGLCommandType::BindBufferBase;
    GLenum target {};
    GLuint index {};
    WebGLObjectId buffer {};
};

struct BindBufferRange {
    static constexpr auto command_type = WebGLCommandType::BindBufferRange;
    GLenum target {};
    GLuint index {};
    WebGLObjectId buffer {};
    GLintptr offset {};
    GLsizeiptr size {};
};

struct BindFramebuffer {
    static constexpr auto command_type = WebGLCommandType::BindFramebuffer;
    GLenum target {};
    WebGLObjectId framebuffer {};
};

struct BindRenderbuffer {
    static constexpr auto command_type = WebGLCommandType::BindRenderbuffer;
    GLenum target {};
    WebGLObjectId renderbuffer {};
};

struct BindSampler {
    static constexpr auto command_type = WebGLCommandType::BindSampler;
    GLuint unit {};
    WebGLObjectId sampler {};
};

struct BindTexture {
    static constexpr auto command_type = WebGLCommandType::BindTexture;
    GLenum target {};
    WebGLObjectId texture {};
};

struct BindTransformFeedback {
    static constexpr auto command_type = WebGLCommandType::BindTransformFeedback;
    GLenum target {};
    WebGLObjectId id {};
};

struct BindVertexArray {
    static constexpr auto command_type = WebGLCommandType::BindVertexArray;
    WebGLObjectId array {};
};

struct BindVertexArrayOES {
    static constexpr auto command_type = WebGLCommandType::BindVertexArrayOES;
    WebGLObjectId array {};
};

struct BlendColor {
    static constexpr auto command_type = WebGLCommandType::BlendColor;
    GLfloat red {};
    GLfloat green {};
    GLfloat blue {};
    GLfloat alpha {};
};

struct BlendEquation {
    static constexpr auto command_type = WebGLCommandType::BlendEquation;
    GLenum mode {};
};

struct BlendEquationSeparate {
    static constexpr auto command_type = WebGLCommandType::BlendEquationSeparate;
    GLenum mode_rgb {};
    GLenum mode_alpha {};
};

struct BlendFunc {
    static constexpr auto command_type = WebGLCommandType::BlendFunc;
    GLenum sfactor {};
    GLenum dfactor {};
};

struct BlendFuncSeparate {
    static constexpr auto command_type = WebGLCommandType::BlendFuncSeparate;
    GLenum sfactor_rgb {};
    GLenum dfactor_rgb {};
    GLenum sfactor_alpha {};
    GLenum dfactor_alpha {};
};

struct BlitFramebuffer {
    static constexpr auto command_type = WebGLCommandType::BlitFramebuffer;
    GLint src_x0 {};
    GLint src_y0 {};
    GLint src_x1 {};
    GLint src_y1 {};
    GLint dst_x0 {};
    GLint dst_y0 {};
    GLint dst_x1 {};
    GLint dst_y1 {};
    GLbitfield mask {};
    GLenum filter {};
};

struct BufferData {
    static constexpr auto command_type = WebGLCommandType::BufferData;
    GLenum target {};
    GLsizeiptr size {};
    bool has_data {};
    WebGLDataSpan data {};
    GLenum usage {};
};

struct BufferSubData {
    static constexpr auto command_type = WebGLCommandType::BufferSubData;
    GLenum target {};
    GLintptr offset {};
    GLsizeiptr size {};
    WebGLDataSpan data {};
};

struct Clear {
    static constexpr auto command_type = WebGLCommandType::Clear;
    GLbitfield mask {};
};

struct ClearBufferfi {
    static constexpr auto command_type = WebGLCommandType::ClearBufferfi;
    GLenum buffer {};
    GLint drawbuffer {};
    GLfloat depth {};
    GLint stencil {};
};

struct ClearBufferfv {
    static constexpr auto command_type = WebGLCommandType::ClearBufferfv;
    GLenum buffer {};
    GLint drawbuffer {};
    WebGLDataSpan value {};
};

struct ClearBufferiv {
    static constexpr auto command_type = WebGLCommandType::ClearBufferiv;
    GLenum buffer {};
    GLint drawbuffer {};
    WebGLDataSpan value {};
};

struct ClearBufferuiv {
    static constexpr auto command_type = WebGLCommandType::ClearBufferuiv;
    GLenum buffer {};
    GLint drawbuffer {};
    WebGLDataSpan value {};
};

struct ClearColor {
    static constexpr auto command_type = WebGLCommandType::ClearColor;
    GLfloat red {};
    GLfloat green {};
    GLfloat blue {};
    GLfloat alpha {};
};

struct ClearDepthf {
    static constexpr auto command_type = WebGLCommandType::ClearDepthf;
    GLfloat d {};
};

struct ClearStencil {
    static constexpr auto command_type = WebGLCommandType::ClearStencil;
    GLint s {};
};

struct ColorMask {
    static constexpr auto command_type = WebGLCommandType::ColorMask;
    GLboolean red {};
    GLboolean green {};
    GLboolean blue {};
    GLboolean alpha {};
};

struct CompileShader {
    static constexpr auto command_type = WebGLCommandType::CompileShader;
    WebGLObjectId shader {};
};

struct CompressedTexImage2DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::CompressedTexImage2DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLenum internalformat {};
    GLsizei width {};
    GLsizei height {};
    GLint border {};
    GLsizei image_size {};
    GLsizei buf_size {};
    WebGLDataSpan data {};
};

struct CompressedTexImage3DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::CompressedTexImage3DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLenum internalformat {};
    GLsizei width {};
    GLsizei height {};
    GLsizei depth {};
    GLint border {};
    GLsizei image_size {};
    GLsizei buf_size {};
    WebGLDataSpan data {};
};

struct CompressedTexSubImage2DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::CompressedTexSubImage2DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLsizei width {};
    GLsizei height {};
    GLenum format {};
    GLsizei image_size {};
    GLsizei buf_size {};
    WebGLDataSpan data {};
};

struct CompressedTexSubImage3DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::CompressedTexSubImage3DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLint zoffset {};
    GLsizei width {};
    GLsizei height {};
    GLsizei depth {};
    GLenum format {};
    GLsizei image_size {};
    GLsizei buf_size {};
    WebGLDataSpan data {};
};

struct CopyBufferSubData {
    static constexpr auto command_type = WebGLCommandType::CopyBufferSubData;
    GLenum read_target {};
    GLenum write_target {};
    GLintptr read_offset {};
    GLintptr write_offset {};
    GLsizeiptr size {};
};

struct CopyTexImage2D {
    static constexpr auto command_type = WebGLCommandType::CopyTexImage2D;
    GLenum target {};
    GLint level {};
    GLenum internalformat {};
    GLint x {};
    GLint y {};
    GLsizei width {};
    GLsizei height {};
    GLint border {};
};

struct CopyTexSubImage2D {
    static constexpr auto command_type = WebGLCommandType::CopyTexSubImage2D;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLint x {};
    GLint y {};
    GLsizei width {};
    GLsizei height {};
};

struct CreateProgram {
    static constexpr auto command_type = WebGLCommandType::CreateProgram;
    WebGLObjectId id {};
};

struct CreateShader {
    static constexpr auto command_type = WebGLCommandType::CreateShader;
    WebGLObjectId id {};
    GLenum type {};
};

struct CullFace {
    static constexpr auto command_type = WebGLCommandType::CullFace;
    GLenum mode {};
};

struct DeleteBuffers {
    static constexpr auto command_type = WebGLCommandType::DeleteBuffers;
    GLsizei n {};
    WebGLDataSpan buffers {};
};

struct DeleteFramebuffers {
    static constexpr auto command_type = WebGLCommandType::DeleteFramebuffers;
    GLsizei n {};
    WebGLDataSpan framebuffers {};
};

struct DeleteProgram {
    static constexpr auto command_type = WebGLCommandType::DeleteProgram;
    WebGLObjectId program {};
};

struct DeleteQueries {
    static constexpr auto command_type = WebGLCommandType::DeleteQueries;
    GLsizei n {};
    WebGLDataSpan ids {};
};

struct DeleteRenderbuffers {
    static constexpr auto command_type = WebGLCommandType::DeleteRenderbuffers;
    GLsizei n {};
    WebGLDataSpan renderbuffers {};
};

struct DeleteSamplers {
    static constexpr auto command_type = WebGLCommandType::DeleteSamplers;
    GLsizei count {};
    WebGLDataSpan samplers {};
};

struct DeleteShader {
    static constexpr auto command_type = WebGLCommandType::DeleteShader;
    WebGLObjectId shader {};
};

struct DeleteSync {
    static constexpr auto command_type = WebGLCommandType::DeleteSync;
    WebGLObjectId sync {};
};

struct DeleteTextures {
    static constexpr auto command_type = WebGLCommandType::DeleteTextures;
    GLsizei n {};
    WebGLDataSpan textures {};
};

struct DeleteTransformFeedbacks {
    static constexpr auto command_type = WebGLCommandType::DeleteTransformFeedbacks;
    GLsizei n {};
    WebGLDataSpan ids {};
};

struct DeleteVertexArrays {
    static constexpr auto command_type = WebGLCommandType::DeleteVertexArrays;
    GLsizei n {};
    WebGLDataSpan arrays {};
};

struct DeleteVertexArraysOES {
    static constexpr auto command_type = WebGLCommandType::DeleteVertexArraysOES;
    GLsizei n {};
    WebGLDataSpan arrays {};
};

struct DepthFunc {
    static constexpr auto command_type = WebGLCommandType::DepthFunc;
    GLenum func {};
};

struct DepthMask {
    static constexpr auto command_type = WebGLCommandType::DepthMask;
    GLboolean flag {};
};

struct DepthRangef {
    static constexpr auto command_type = WebGLCommandType::DepthRangef;
    GLfloat n {};
    GLfloat f {};
};

struct DetachShader {
    static constexpr auto command_type = WebGLCommandType::DetachShader;
    WebGLObjectId program {};
    WebGLObjectId shader {};
};

struct Disable {
    static constexpr auto command_type = WebGLCommandType::Disable;
    GLenum cap {};
};

struct DisableVertexAttribArray {
    static constexpr auto command_type = WebGLCommandType::DisableVertexAttribArray;
    GLuint index {};
};

struct DrawArrays {
    static constexpr auto command_type = WebGLCommandType::DrawArrays;
    GLenum mode {};
    GLint first {};
    GLsizei count {};
};

struct DrawArraysInstanced {
    static constexpr auto command_type = WebGLCommandType::DrawArraysInstanced;
    GLenum mode {};
    GLint first {};
    GLsizei count {};
    GLsizei instancecount {};
};

struct DrawArraysInstancedANGLE {
    static constexpr auto command_type = WebGLCommandType::DrawArraysInstancedANGLE;
    GLenum mode {};
    GLint first {};
    GLsizei count {};
    GLsizei primcount {};
};

struct DrawBuffers {
    static constexpr auto command_type = WebGLCommandType::DrawBuffers;
    GLsizei n {};
    WebGLDataSpan bufs {};
};

struct DrawBuffersEXT {
    static constexpr auto command_type = WebGLCommandType::DrawBuffersEXT;
    GLsizei n {};
    WebGLDataSpan bufs {};
};

struct DrawElements {
    static constexpr auto command_type = WebGLCommandType::DrawElements;
    GLenum mode {};
    GLsizei count {};
    GLenum type {};
    GLintptr indices {};
};

struct DrawElementsInstanced {
    static constexpr auto command_type = WebGLCommandType::DrawElementsInstanced;
    GLenum mode {};
    GLsizei count {};
    GLenum type {};
    GLintptr indices {};
    GLsizei instancecount {};
};

struct DrawElementsInstancedANGLE {
    static constexpr auto command_type = WebGLCommandType::DrawElementsInstancedANGLE;
    GLenum mode {};
    GLsizei count {};
    GLenum type {};
    GLintptr indices {};
    GLsizei primcount {};
};

struct DrawRangeElements {
    static constexpr auto command_type = WebGLCommandType::DrawRangeElements;
    GLenum mode {};
    GLuint start {};
    GLuint end {};
    GLsizei count {};
    GLenum type {};
    GLintptr indices {};
};

struct Enable {
    static constexpr auto command_type = WebGLCommandType::Enable;
    GLenum cap {};
};

struct EnableVertexAttribArray {
    static constexpr auto command_type = WebGLCommandType::EnableVertexAttribArray;
    GLuint index {};
};

struct EndQuery {
    static constexpr auto command_type = WebGLCommandType::EndQuery;
    GLenum target {};
};

struct EndTransformFeedback {
    static constexpr auto command_type = WebGLCommandType::EndTransformFeedback;
};

struct FenceSync {
    static constexpr auto command_type = WebGLCommandType::FenceSync;
    WebGLObjectId id {};
    GLenum condition {};
    GLbitfield flags {};
};

struct Flush {
    static constexpr auto command_type = WebGLCommandType::Flush;
};

struct FramebufferRenderbuffer {
    static constexpr auto command_type = WebGLCommandType::FramebufferRenderbuffer;
    GLenum target {};
    GLenum attachment {};
    GLenum renderbuffertarget {};
    WebGLObjectId renderbuffer {};
};

struct FramebufferTexture2D {
    static constexpr auto command_type = WebGLCommandType::FramebufferTexture2D;
    GLenum target {};
    GLenum attachment {};
    GLenum textarget {};
    WebGLObjectId texture {};
    GLint level {};
};

struct FramebufferTextureLayer {
    static constexpr auto command_type = WebGLCommandType::FramebufferTextureLayer;
    GLenum target {};
    GLenum attachment {};
    WebGLObjectId texture {};
    GLint level {};
    GLint layer {};
};

struct FrontFace {
    static constexpr auto command_type = WebGLCommandType::FrontFace;
    GLenum mode {};
};

struct GenBuffers {
    static constexpr auto command_type = WebGLCommandType::GenBuffers;
    GLsizei n {};
    WebGLDataSpan buffers {};
};

struct GenFramebuffers {
    static constexpr auto command_type = WebGLCommandType::GenFramebuffers;
    GLsizei n {};
    WebGLDataSpan framebuffers {};
};

struct GenQueries {
    static constexpr auto command_type = WebGLCommandType::GenQueries;
    GLsizei n {};
    WebGLDataSpan ids {};
};

struct GenRenderbuffers {
    static constexpr auto command_type = WebGLCommandType::GenRenderbuffers;
    GLsizei n {};
    WebGLDataSpan renderbuffers {};
};

struct GenSamplers {
    static constexpr auto command_type = WebGLCommandType::GenSamplers;
    GLsizei count {};
    WebGLDataSpan samplers {};
};

struct GenTextures {
    static constexpr auto command_type = WebGLCommandType::GenTextures;
    GLsizei n {};
    WebGLDataSpan textures {};
};

struct GenTransformFeedbacks {
    static constexpr auto command_type = WebGLCommandType::GenTransformFeedbacks;
    GLsizei n {};
    WebGLDataSpan ids {};
};

struct GenVertexArrays {
    static constexpr auto command_type = WebGLCommandType::GenVertexArrays;
    GLsizei n {};
    WebGLDataSpan arrays {};
};

struct GenVertexArraysOES {
    static constexpr auto command_type = WebGLCommandType::GenVertexArraysOES;
    GLsizei n {};
    WebGLDataSpan arrays {};
};

struct GenerateMipmap {
    static constexpr auto command_type = WebGLCommandType::GenerateMipmap;
    GLenum target {};
};

struct Hint {
    static constexpr auto command_type = WebGLCommandType::Hint;
    GLenum target {};
    GLenum mode {};
};

struct InvalidateFramebuffer {
    static constexpr auto command_type = WebGLCommandType::InvalidateFramebuffer;
    GLenum target {};
    GLsizei num_attachments {};
    WebGLDataSpan attachments {};
};

struct InvalidateSubFramebuffer {
    static constexpr auto command_type = WebGLCommandType::InvalidateSubFramebuffer;
    GLenum target {};
    GLsizei num_attachments {};
    WebGLDataSpan attachments {};
    GLint x {};
    GLint y {};
    GLsizei width {};
    GLsizei height {};
};

struct LineWidth {
    static constexpr auto command_type = WebGLCommandType::LineWidth;
    GLfloat width {};
};

struct LinkProgram {
    static constexpr auto command_type = WebGLCommandType::LinkProgram;
    WebGLObjectId program {};
};

struct PauseTransformFeedback {
    static constexpr auto command_type = WebGLCommandType::PauseTransformFeedback;
};

struct PixelStorei {
    static constexpr auto command_type = WebGLCommandType::PixelStorei;
    GLenum pname {};
    GLint param {};
};

struct PolygonOffset {
    static constexpr auto command_type = WebGLCommandType::PolygonOffset;
    GLfloat factor {};
    GLfloat units {};
};

struct ReadBuffer {
    static constexpr auto command_type = WebGLCommandType::ReadBuffer;
    GLenum src {};
};

struct RenderbufferStorage {
    static constexpr auto command_type = WebGLCommandType::RenderbufferStorage;
    GLenum target {};
    GLenum internalformat {};
    GLsizei width {};
    GLsizei height {};
};

struct RenderbufferStorageMultisample {
    static constexpr auto command_type = WebGLCommandType::RenderbufferStorageMultisample;
    GLenum target {};
    GLsizei samples {};
    GLenum internalformat {};
    GLsizei width {};
    GLsizei height {};
};

struct RequestExtensionANGLE {
    static constexpr auto command_type = WebGLCommandType::RequestExtensionANGLE;
    WebGLDataSpan name {};
};

struct ResumeTransformFeedback {
    static constexpr auto command_type = WebGLCommandType::ResumeTransformFeedback;
};

struct SampleCoverage {
    static constexpr auto command_type = WebGLCommandType::SampleCoverage;
    GLfloat value {};
    GLboolean invert {};
};

struct SamplerParameterf {
    static constexpr auto command_type = WebGLCommandType::SamplerParameterf;
    WebGLObjectId sampler {};
    GLenum pname {};
    GLfloat param {};
};

struct SamplerParameteri {
    static constexpr auto command_type = WebGLCommandType::SamplerParameteri;
    WebGLObjectId sampler {};
    GLenum pname {};
    GLint param {};
};

struct Scissor {
    static constexpr auto command_type = WebGLCommandType::Scissor;
    GLint x {};
    GLint y {};
    GLsizei width {};
    GLsizei height {};
};

struct ShaderSource {
    static constexpr auto command_type = WebGLCommandType::ShaderSource;
    WebGLObjectId shader {};
    WebGLDataSpan source {};
};

struct StencilFunc {
    static constexpr auto command_type = WebGLCommandType::StencilFunc;
    GLenum func {};
    GLint ref {};
    GLuint mask {};
};

struct StencilFuncSeparate {
    static constexpr auto command_type = WebGLCommandType::StencilFuncSeparate;
    GLenum face {};
    GLenum func {};
    GLint ref {};
    GLuint mask {};
};

struct StencilMask {
    static constexpr auto command_type = WebGLCommandType::StencilMask;
    GLuint mask {};
};

struct StencilMaskSeparate {
    static constexpr auto command_type = WebGLCommandType::StencilMaskSeparate;
    GLenum face {};
    GLuint mask {};
};

struct StencilOp {
    static constexpr auto command_type = WebGLCommandType::StencilOp;
    GLenum fail {};
    GLenum zfail {};
    GLenum zpass {};
};

struct StencilOpSeparate {
    static constexpr auto command_type = WebGLCommandType::StencilOpSeparate;
    GLenum face {};
    GLenum sfail {};
    GLenum dpfail {};
    GLenum dppass {};
};

struct TexImage2DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::TexImage2DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLint internalformat {};
    GLsizei width {};
    GLsizei height {};
    GLint border {};
    GLenum format {};
    GLenum type {};
    GLsizei buf_size {};
    bool has_pixels {};
    WebGLDataSpan pixels {};
};

struct TexImage3DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::TexImage3DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLint internalformat {};
    GLsizei width {};
    GLsizei height {};
    GLsizei depth {};
    GLint border {};
    GLenum format {};
    GLenum type {};
    GLsizei buf_size {};
    bool has_pixels {};
    WebGLDataSpan pixels {};
};

struct TexParameterf {
    static constexpr auto command_type = WebGLCommandType::TexParameterf;
    GLenum target {};
    GLenum pname {};
    GLfloat param {};
};

struct TexParameteri {
    static constexpr auto command_type = WebGLCommandType::TexParameteri;
    GLenum target {};
    GLenum pname {};
    GLint param {};
};

struct TexStorage2D {
    static constexpr auto command_type = WebGLCommandType::TexStorage2D;
    GLenum target {};
    GLsizei levels {};
    GLenum internalformat {};
    GLsizei width {};
    GLsizei height {};
};

struct TexStorage3D {
    static constexpr auto command_type = WebGLCommandType::TexStorage3D;
    GLenum target {};
    GLsizei levels {};
    GLenum internalformat {};
    GLsizei width {};
    GLsizei height {};
    GLsizei depth {};
};

struct TexSubImage2DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::TexSubImage2DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLsizei width {};
    GLsizei height {};
    GLenum format {};
    GLenum type {};
    GLsizei buf_size {};
    bool has_pixels {};
    WebGLDataSpan pixels {};
};

struct TexSubImage3DRobustANGLE {
    static constexpr auto command_type = WebGLCommandType::TexSubImage3DRobustANGLE;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLint zoffset {};
    GLsizei width {};
    GLsizei height {};
    GLsizei depth {};
    GLenum format {};
    GLenum type {};
    GLsizei buf_size {};
    bool has_pixels {};
    WebGLDataSpan pixels {};
};

struct TransformFeedbackVaryings {
    static constexpr auto command_type = WebGLCommandType::TransformFeedbackVaryings;
    WebGLObjectId program {};
    GLsizei count {};
    WebGLDataSpan varyings {};
    GLenum buffer_mode {};
};

struct Uniform1f {
    static constexpr auto command_type = WebGLCommandType::Uniform1f;
    GLint location {};
    GLfloat v0 {};
};

struct Uniform1fv {
    static constexpr auto command_type = WebGLCommandType::Uniform1fv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform1i {
    static constexpr auto command_type = WebGLCommandType::Uniform1i;
    GLint location {};
    GLint v0 {};
};

struct Uniform1iv {
    static constexpr auto command_type = WebGLCommandType::Uniform1iv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform1ui {
    static constexpr auto command_type = WebGLCommandType::Uniform1ui;
    GLint location {};
    GLuint v0 {};
};

struct Uniform1uiv {
    static constexpr auto command_type = WebGLCommandType::Uniform1uiv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform2f {
    static constexpr auto command_type = WebGLCommandType::Uniform2f;
    GLint location {};
    GLfloat v0 {};
    GLfloat v1 {};
};

struct Uniform2fv {
    static constexpr auto command_type = WebGLCommandType::Uniform2fv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform2i {
    static constexpr auto command_type = WebGLCommandType::Uniform2i;
    GLint location {};
    GLint v0 {};
    GLint v1 {};
};

struct Uniform2iv {
    static constexpr auto command_type = WebGLCommandType::Uniform2iv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform2ui {
    static constexpr auto command_type = WebGLCommandType::Uniform2ui;
    GLint location {};
    GLuint v0 {};
    GLuint v1 {};
};

struct Uniform2uiv {
    static constexpr auto command_type = WebGLCommandType::Uniform2uiv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform3f {
    static constexpr auto command_type = WebGLCommandType::Uniform3f;
    GLint location {};
    GLfloat v0 {};
    GLfloat v1 {};
    GLfloat v2 {};
};

struct Uniform3fv {
    static constexpr auto command_type = WebGLCommandType::Uniform3fv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform3i {
    static constexpr auto command_type = WebGLCommandType::Uniform3i;
    GLint location {};
    GLint v0 {};
    GLint v1 {};
    GLint v2 {};
};

struct Uniform3iv {
    static constexpr auto command_type = WebGLCommandType::Uniform3iv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform3ui {
    static constexpr auto command_type = WebGLCommandType::Uniform3ui;
    GLint location {};
    GLuint v0 {};
    GLuint v1 {};
    GLuint v2 {};
};

struct Uniform3uiv {
    static constexpr auto command_type = WebGLCommandType::Uniform3uiv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform4f {
    static constexpr auto command_type = WebGLCommandType::Uniform4f;
    GLint location {};
    GLfloat v0 {};
    GLfloat v1 {};
    GLfloat v2 {};
    GLfloat v3 {};
};

struct Uniform4fv {
    static constexpr auto command_type = WebGLCommandType::Uniform4fv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform4i {
    static constexpr auto command_type = WebGLCommandType::Uniform4i;
    GLint location {};
    GLint v0 {};
    GLint v1 {};
    GLint v2 {};
    GLint v3 {};
};

struct Uniform4iv {
    static constexpr auto command_type = WebGLCommandType::Uniform4iv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct Uniform4ui {
    static constexpr auto command_type = WebGLCommandType::Uniform4ui;
    GLint location {};
    GLuint v0 {};
    GLuint v1 {};
    GLuint v2 {};
    GLuint v3 {};
};

struct Uniform4uiv {
    static constexpr auto command_type = WebGLCommandType::Uniform4uiv;
    GLint location {};
    GLsizei count {};
    WebGLDataSpan value {};
};

struct UniformBlockBinding {
    static constexpr auto command_type = WebGLCommandType::UniformBlockBinding;
    WebGLObjectId program {};
    GLuint uniform_block_index {};
    GLuint uniform_block_binding {};
};

struct UniformMatrix2fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix2fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix2x3fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix2x3fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix2x4fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix2x4fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix3fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix3fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix3x2fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix3x2fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix3x4fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix3x4fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix4fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix4fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix4x2fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix4x2fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UniformMatrix4x3fv {
    static constexpr auto command_type = WebGLCommandType::UniformMatrix4x3fv;
    GLint location {};
    GLsizei count {};
    GLboolean transpose {};
    WebGLDataSpan value {};
};

struct UseProgram {
    static constexpr auto command_type = WebGLCommandType::UseProgram;
    WebGLObjectId program {};
};

struct ValidateProgram {
    static constexpr auto command_type = WebGLCommandType::ValidateProgram;
    WebGLObjectId program {};
};

struct VertexAttrib1f {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib1f;
    GLuint index {};
    GLfloat x {};
};

struct VertexAttrib1fv {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib1fv;
    GLuint index {};
    WebGLDataSpan v {};
};

struct VertexAttrib2f {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib2f;
    GLuint index {};
    GLfloat x {};
    GLfloat y {};
};

struct VertexAttrib2fv {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib2fv;
    GLuint index {};
    WebGLDataSpan v {};
};

struct VertexAttrib3f {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib3f;
    GLuint index {};
    GLfloat x {};
    GLfloat y {};
    GLfloat z {};
};

struct VertexAttrib3fv {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib3fv;
    GLuint index {};
    WebGLDataSpan v {};
};

struct VertexAttrib4f {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib4f;
    GLuint index {};
    GLfloat x {};
    GLfloat y {};
    GLfloat z {};
    GLfloat w {};
};

struct VertexAttrib4fv {
    static constexpr auto command_type = WebGLCommandType::VertexAttrib4fv;
    GLuint index {};
    WebGLDataSpan v {};
};

struct VertexAttribDivisor {
    static constexpr auto command_type = WebGLCommandType::VertexAttribDivisor;
    GLuint index {};
    GLuint divisor {};
};

struct VertexAttribDivisorANGLE {
    static constexpr auto command_type = WebGLCommandType::VertexAttribDivisorANGLE;
    GLuint index {};
    GLuint divisor {};
};

struct VertexAttribI4i {
    static constexpr auto command_type = WebGLCommandType::VertexAttribI4i;
    GLuint index {};
    GLint x {};
    GLint y {};
    GLint z {};
    GLint w {};
};

struct VertexAttribI4iv {
    static constexpr auto command_type = WebGLCommandType::VertexAttribI4iv;
    GLuint index {};
    WebGLDataSpan v {};
};

struct VertexAttribI4ui {
    static constexpr auto command_type = WebGLCommandType::VertexAttribI4ui;
    GLuint index {};
    GLuint x {};
    GLuint y {};
    GLuint z {};
    GLuint w {};
};

struct VertexAttribI4uiv {
    static constexpr auto command_type = WebGLCommandType::VertexAttribI4uiv;
    GLuint index {};
    WebGLDataSpan v {};
};

struct VertexAttribIPointer {
    static constexpr auto command_type = WebGLCommandType::VertexAttribIPointer;
    GLuint index {};
    GLint size {};
    GLenum type {};
    GLsizei stride {};
    GLintptr pointer {};
};

struct VertexAttribPointer {
    static constexpr auto command_type = WebGLCommandType::VertexAttribPointer;
    GLuint index {};
    GLint size {};
    GLenum type {};
    GLboolean normalized {};
    GLsizei stride {};
    GLintptr pointer {};
};

struct Viewport {
    static constexpr auto command_type = WebGLCommandType::Viewport;
    GLint x {};
    GLint y {};
    GLsizei width {};
    GLsizei height {};
};

struct WaitSync {
    static constexpr auto command_type = WebGLCommandType::WaitSync;
    WebGLObjectId sync {};
    GLbitfield flags {};
    GLuint64 timeout {};
};

struct SetDrawingBufferSize {
    static constexpr auto command_type = WebGLCommandType::SetDrawingBufferSize;
    int width {};
    int height {};
};

struct ReadPixelsIntoPixelPackBuffer {
    static constexpr auto command_type = WebGLCommandType::ReadPixelsIntoPixelPackBuffer;
    GLint x {};
    GLint y {};
    GLsizei width {};
    GLsizei height {};
    GLenum format {};
    GLenum type {};
    GLintptr offset {};
};

struct TexImage2DFromBitmap {
    static constexpr auto command_type = WebGLCommandType::TexImage2DFromBitmap;
    GLenum target {};
    GLint level {};
    GLint internalformat {};
    GLenum format {};
    GLenum type {};
    u32 bitmap_index {};
    bool has_explicit_destination_size {};
    GLsizei destination_width {};
    GLsizei destination_height {};
    bool flip_y {};
    bool premultiply_alpha {};
};

struct TexSubImage2DFromBitmap {
    static constexpr auto command_type = WebGLCommandType::TexSubImage2DFromBitmap;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLenum format {};
    GLenum type {};
    u32 bitmap_index {};
    bool has_explicit_destination_size {};
    GLsizei destination_width {};
    GLsizei destination_height {};
    bool flip_y {};
    bool premultiply_alpha {};
};

struct TexImage3DFromBitmap {
    static constexpr auto command_type = WebGLCommandType::TexImage3DFromBitmap;
    GLenum target {};
    GLint level {};
    GLint internalformat {};
    GLsizei depth {};
    GLenum format {};
    GLenum type {};
    u32 bitmap_index {};
    bool has_explicit_destination_size {};
    GLsizei destination_width {};
    GLsizei destination_height {};
    bool flip_y {};
    bool premultiply_alpha {};
};

struct TexSubImage3DFromBitmap {
    static constexpr auto command_type = WebGLCommandType::TexSubImage3DFromBitmap;
    GLenum target {};
    GLint level {};
    GLint xoffset {};
    GLint yoffset {};
    GLint zoffset {};
    GLsizei depth {};
    GLenum format {};
    GLenum type {};
    u32 bitmap_index {};
    bool has_explicit_destination_size {};
    GLsizei destination_width {};
    GLsizei destination_height {};
    bool flip_y {};
    bool premultiply_alpha {};
};

}

template<typename Callback>
decltype(auto) visit_webgl_command_type(WebGLCommandType type, Callback&& callback)
{
    switch (type) {
#define __ENUMERATE(name) \
    case WebGLCommandType::name: \
        return callback.template operator()<Commands::name>();
        ENUMERATE_WEBGL_COMMANDS(__ENUMERATE)
#undef __ENUMERATE
    }
    VERIFY_NOT_REACHED();
}

#define __ENUMERATE(name) static_assert(IsTriviallyCopyable<Commands::name>);
ENUMERATE_WEBGL_COMMANDS(__ENUMERATE)
#undef __ENUMERATE

#define ENUMERATE_WEBGL_SYNC_CALLS(V) \
    V(CheckFramebufferStatus) \
    V(ClientWaitSync) \
    V(Finish) \
    V(GetActiveAttrib) \
    V(GetActiveUniform) \
    V(GetActiveUniformBlockName) \
    V(GetActiveUniformBlockivRobustANGLE) \
    V(GetActiveUniformsiv) \
    V(GetAttribLocation) \
    V(GetBooleanvRobustANGLE) \
    V(GetBufferParameterivRobustANGLE) \
    V(GetError) \
    V(GetFloatvRobustANGLE) \
    V(GetInteger64vRobustANGLE) \
    V(GetIntegervRobustANGLE) \
    V(GetInternalformativRobustANGLE) \
    V(GetProgramInfoLog) \
    V(GetProgramiv) \
    V(GetProgramivRobustANGLE) \
    V(GetQueryObjectuivRobustANGLE) \
    V(GetRenderbufferParameterivRobustANGLE) \
    V(GetShaderInfoLog) \
    V(GetShaderPrecisionFormat) \
    V(GetShaderSource) \
    V(GetShaderiv) \
    V(GetShaderivRobustANGLE) \
    V(GetString) \
    V(GetSynciv) \
    V(GetTexParameterfvRobustANGLE) \
    V(GetTexParameterivRobustANGLE) \
    V(GetUniformBlockIndex) \
    V(GetUniformIndices) \
    V(GetUniformLocation) \
    V(GetVertexAttribPointervRobustANGLE) \
    V(GetVertexAttribfvRobustANGLE) \
    V(GetVertexAttribivRobustANGLE) \
    V(IsBuffer) \
    V(IsEnabled) \
    V(IsFramebuffer) \
    V(IsProgram) \
    V(IsRenderbuffer) \
    V(IsShader) \
    V(IsTexture) \
    V(IsVertexArray) \
    V(IsVertexArrayOES) \

enum class WebGLSyncCallType : u16 {
#define __ENUMERATE(name) name,
    ENUMERATE_WEBGL_SYNC_CALLS(__ENUMERATE)
#undef __ENUMERATE
};

inline constexpr u16 webgl_sync_call_type_count = 45;

WEB_API StringView to_string(WebGLSyncCallType);

namespace SyncCalls {

struct CheckFramebufferStatus {
    static constexpr auto call_type = WebGLSyncCallType::CheckFramebufferStatus;
    struct Request {
        GLenum target {};
    };
    struct Reply {
        GLenum return_value {};
    };
};

struct ClientWaitSync {
    static constexpr auto call_type = WebGLSyncCallType::ClientWaitSync;
    struct Request {
        WebGLObjectId sync {};
        GLbitfield flags {};
        GLuint64 timeout {};
    };
    struct Reply {
        GLenum return_value {};
    };
};

struct Finish {
    static constexpr auto call_type = WebGLSyncCallType::Finish;
    struct Request {
    };
    struct Reply {
    };
};

struct GetActiveAttrib {
    static constexpr auto call_type = WebGLSyncCallType::GetActiveAttrib;
    struct Request {
        WebGLObjectId program {};
        GLuint index {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        GLint size {};
        GLenum type {};
        WebGLDataSpan name {};
    };
};

struct GetActiveUniform {
    static constexpr auto call_type = WebGLSyncCallType::GetActiveUniform;
    struct Request {
        WebGLObjectId program {};
        GLuint index {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        GLint size {};
        GLenum type {};
        WebGLDataSpan name {};
    };
};

struct GetActiveUniformBlockName {
    static constexpr auto call_type = WebGLSyncCallType::GetActiveUniformBlockName;
    struct Request {
        WebGLObjectId program {};
        GLuint uniform_block_index {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan uniform_block_name {};
    };
};

struct GetActiveUniformBlockivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetActiveUniformBlockivRobustANGLE;
    struct Request {
        WebGLObjectId program {};
        GLuint uniform_block_index {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetActiveUniformsiv {
    static constexpr auto call_type = WebGLSyncCallType::GetActiveUniformsiv;
    struct Request {
        WebGLObjectId program {};
        GLsizei uniform_count {};
        WebGLDataSpan uniform_indices {};
        GLenum pname {};
    };
    struct Reply {
        WebGLDataSpan params {};
    };
};

struct GetAttribLocation {
    static constexpr auto call_type = WebGLSyncCallType::GetAttribLocation;
    struct Request {
        WebGLObjectId program {};
        WebGLDataSpan name {};
    };
    struct Reply {
        GLint return_value {};
    };
};

struct GetBooleanvRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetBooleanvRobustANGLE;
    struct Request {
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan data {};
    };
};

struct GetBufferParameterivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetBufferParameterivRobustANGLE;
    struct Request {
        GLenum target {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetError {
    static constexpr auto call_type = WebGLSyncCallType::GetError;
    struct Request {
    };
    struct Reply {
        GLenum return_value {};
    };
};

struct GetFloatvRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetFloatvRobustANGLE;
    struct Request {
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan data {};
    };
};

struct GetInteger64vRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetInteger64vRobustANGLE;
    struct Request {
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan data {};
    };
};

struct GetIntegervRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetIntegervRobustANGLE;
    struct Request {
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan data {};
    };
};

struct GetInternalformativRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetInternalformativRobustANGLE;
    struct Request {
        GLenum target {};
        GLenum internalformat {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetProgramInfoLog {
    static constexpr auto call_type = WebGLSyncCallType::GetProgramInfoLog;
    struct Request {
        WebGLObjectId program {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan info_log {};
    };
};

struct GetProgramiv {
    static constexpr auto call_type = WebGLSyncCallType::GetProgramiv;
    struct Request {
        WebGLObjectId program {};
        GLenum pname {};
    };
    struct Reply {
        WebGLDataSpan params {};
    };
};

struct GetProgramivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetProgramivRobustANGLE;
    struct Request {
        WebGLObjectId program {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetQueryObjectuivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetQueryObjectuivRobustANGLE;
    struct Request {
        WebGLObjectId id {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetRenderbufferParameterivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetRenderbufferParameterivRobustANGLE;
    struct Request {
        GLenum target {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetShaderInfoLog {
    static constexpr auto call_type = WebGLSyncCallType::GetShaderInfoLog;
    struct Request {
        WebGLObjectId shader {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan info_log {};
    };
};

struct GetShaderPrecisionFormat {
    static constexpr auto call_type = WebGLSyncCallType::GetShaderPrecisionFormat;
    struct Request {
        GLenum shadertype {};
        GLenum precisiontype {};
    };
    struct Reply {
        WebGLDataSpan range {};
        WebGLDataSpan precision {};
    };
};

struct GetShaderSource {
    static constexpr auto call_type = WebGLSyncCallType::GetShaderSource;
    struct Request {
        WebGLObjectId shader {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan source {};
    };
};

struct GetShaderiv {
    static constexpr auto call_type = WebGLSyncCallType::GetShaderiv;
    struct Request {
        WebGLObjectId shader {};
        GLenum pname {};
    };
    struct Reply {
        WebGLDataSpan params {};
    };
};

struct GetShaderivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetShaderivRobustANGLE;
    struct Request {
        WebGLObjectId shader {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetString {
    static constexpr auto call_type = WebGLSyncCallType::GetString;
    struct Request {
        GLenum name {};
    };
    struct Reply {
        WebGLDataSpan value {};
    };
};

struct GetSynciv {
    static constexpr auto call_type = WebGLSyncCallType::GetSynciv;
    struct Request {
        WebGLObjectId sync {};
        GLenum pname {};
        GLsizei count {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan values {};
    };
};

struct GetTexParameterfvRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetTexParameterfvRobustANGLE;
    struct Request {
        GLenum target {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetTexParameterivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetTexParameterivRobustANGLE;
    struct Request {
        GLenum target {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetUniformBlockIndex {
    static constexpr auto call_type = WebGLSyncCallType::GetUniformBlockIndex;
    struct Request {
        WebGLObjectId program {};
        WebGLDataSpan uniform_block_name {};
    };
    struct Reply {
        GLuint return_value {};
    };
};

struct GetUniformIndices {
    static constexpr auto call_type = WebGLSyncCallType::GetUniformIndices;
    struct Request {
        WebGLObjectId program {};
        GLsizei uniform_count {};
        WebGLDataSpan uniform_names {};
    };
    struct Reply {
        WebGLDataSpan uniform_indices {};
    };
};

struct GetUniformLocation {
    static constexpr auto call_type = WebGLSyncCallType::GetUniformLocation;
    struct Request {
        WebGLObjectId program {};
        WebGLDataSpan name {};
    };
    struct Reply {
        GLint return_value {};
    };
};

struct GetVertexAttribPointervRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetVertexAttribPointervRobustANGLE;
    struct Request {
        GLuint index {};
        GLenum pname {};
    };
    struct Reply {
        GLintptr pointer {};
    };
};

struct GetVertexAttribfvRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetVertexAttribfvRobustANGLE;
    struct Request {
        GLuint index {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct GetVertexAttribivRobustANGLE {
    static constexpr auto call_type = WebGLSyncCallType::GetVertexAttribivRobustANGLE;
    struct Request {
        GLuint index {};
        GLenum pname {};
        GLsizei buf_size {};
    };
    struct Reply {
        GLsizei length {};
        WebGLDataSpan params {};
    };
};

struct IsBuffer {
    static constexpr auto call_type = WebGLSyncCallType::IsBuffer;
    struct Request {
        WebGLObjectId buffer {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsEnabled {
    static constexpr auto call_type = WebGLSyncCallType::IsEnabled;
    struct Request {
        GLenum cap {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsFramebuffer {
    static constexpr auto call_type = WebGLSyncCallType::IsFramebuffer;
    struct Request {
        WebGLObjectId framebuffer {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsProgram {
    static constexpr auto call_type = WebGLSyncCallType::IsProgram;
    struct Request {
        WebGLObjectId program {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsRenderbuffer {
    static constexpr auto call_type = WebGLSyncCallType::IsRenderbuffer;
    struct Request {
        WebGLObjectId renderbuffer {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsShader {
    static constexpr auto call_type = WebGLSyncCallType::IsShader;
    struct Request {
        WebGLObjectId shader {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsTexture {
    static constexpr auto call_type = WebGLSyncCallType::IsTexture;
    struct Request {
        WebGLObjectId texture {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsVertexArray {
    static constexpr auto call_type = WebGLSyncCallType::IsVertexArray;
    struct Request {
        WebGLObjectId array {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

struct IsVertexArrayOES {
    static constexpr auto call_type = WebGLSyncCallType::IsVertexArrayOES;
    struct Request {
        WebGLObjectId array {};
    };
    struct Reply {
        GLboolean return_value {};
    };
};

}

template<typename Callback>
decltype(auto) visit_webgl_sync_call_type(WebGLSyncCallType type, Callback&& callback)
{
    switch (type) {
#define __ENUMERATE(name) \
    case WebGLSyncCallType::name: \
        return callback.template operator()<SyncCalls::name>();
        ENUMERATE_WEBGL_SYNC_CALLS(__ENUMERATE)
#undef __ENUMERATE
    }
    VERIFY_NOT_REACHED();
}

#define __ENUMERATE(name) static_assert(IsTriviallyCopyable<SyncCalls::name::Request>); static_assert(IsTriviallyCopyable<SyncCalls::name::Reply>);
ENUMERATE_WEBGL_SYNC_CALLS(__ENUMERATE)
#undef __ENUMERATE

}
