text: // GENERATED FILE - DO NOT EDIT.
  // Generated by gen_packed_gl_enums.py using data from packed_gl_enums.json.
  //
  // 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.
  //
  // PackedGLEnums_autogen.cpp:
  //   Implements ANGLE-specific enums classes for GLenums and functions operating
  //   on them.
  
  #include "common/PackedGLEnums_autogen.h"
  #include "common/debug.h"
  
  namespace gl
  {
  
  template <>
  AlphaTestFunc FromGLenum<AlphaTestFunc>(GLenum from)
  {
      switch (from)
      {
          case GL_ALWAYS:
              return AlphaTestFunc::AlwaysPass;
          case GL_EQUAL:
              return AlphaTestFunc::Equal;
          case GL_GEQUAL:
              return AlphaTestFunc::Gequal;
          case GL_GREATER:
              return AlphaTestFunc::Greater;
          case GL_LEQUAL:
              return AlphaTestFunc::Lequal;
          case GL_LESS:
              return AlphaTestFunc::Less;
          case GL_NEVER:
              return AlphaTestFunc::Never;
          case GL_NOTEQUAL:
              return AlphaTestFunc::NotEqual;
          default:
              return AlphaTestFunc::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(AlphaTestFunc from)
  {
      switch (from)
      {
          case AlphaTestFunc::AlwaysPass:
              return GL_ALWAYS;
          case AlphaTestFunc::Equal:
              return GL_EQUAL;
          case AlphaTestFunc::Gequal:
              return GL_GEQUAL;
          case AlphaTestFunc::Greater:
              return GL_GREATER;
          case AlphaTestFunc::Lequal:
              return GL_LEQUAL;
          case AlphaTestFunc::Less:
              return GL_LESS;
          case AlphaTestFunc::Never:
              return GL_NEVER;
          case AlphaTestFunc::NotEqual:
              return GL_NOTEQUAL;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, AlphaTestFunc value)
  {
      switch (value)
      {
          case AlphaTestFunc::AlwaysPass:
              os << "GL_ALWAYS";
              break;
          case AlphaTestFunc::Equal:
              os << "GL_EQUAL";
              break;
          case AlphaTestFunc::Gequal:
              os << "GL_GEQUAL";
              break;
          case AlphaTestFunc::Greater:
              os << "GL_GREATER";
              break;
          case AlphaTestFunc::Lequal:
              os << "GL_LEQUAL";
              break;
          case AlphaTestFunc::Less:
              os << "GL_LESS";
              break;
          case AlphaTestFunc::Never:
              os << "GL_NEVER";
              break;
          case AlphaTestFunc::NotEqual:
              os << "GL_NOTEQUAL";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  BufferBinding FromGLenum<BufferBinding>(GLenum from)
  {
      switch (from)
      {
          case GL_ARRAY_BUFFER:
              return BufferBinding::Array;
          case GL_ATOMIC_COUNTER_BUFFER:
              return BufferBinding::AtomicCounter;
          case GL_COPY_READ_BUFFER:
              return BufferBinding::CopyRead;
          case GL_COPY_WRITE_BUFFER:
              return BufferBinding::CopyWrite;
          case GL_DISPATCH_INDIRECT_BUFFER:
              return BufferBinding::DispatchIndirect;
          case GL_DRAW_INDIRECT_BUFFER:
              return BufferBinding::DrawIndirect;
          case GL_ELEMENT_ARRAY_BUFFER:
              return BufferBinding::ElementArray;
          case GL_PIXEL_PACK_BUFFER:
              return BufferBinding::PixelPack;
          case GL_PIXEL_UNPACK_BUFFER:
              return BufferBinding::PixelUnpack;
          case GL_SHADER_STORAGE_BUFFER:
              return BufferBinding::ShaderStorage;
          case GL_TRANSFORM_FEEDBACK_BUFFER:
              return BufferBinding::TransformFeedback;
          case GL_UNIFORM_BUFFER:
              return BufferBinding::Uniform;
          default:
              return BufferBinding::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(BufferBinding from)
  {
      switch (from)
      {
          case BufferBinding::Array:
              return GL_ARRAY_BUFFER;
          case BufferBinding::AtomicCounter:
              return GL_ATOMIC_COUNTER_BUFFER;
          case BufferBinding::CopyRead:
              return GL_COPY_READ_BUFFER;
          case BufferBinding::CopyWrite:
              return GL_COPY_WRITE_BUFFER;
          case BufferBinding::DispatchIndirect:
              return GL_DISPATCH_INDIRECT_BUFFER;
          case BufferBinding::DrawIndirect:
              return GL_DRAW_INDIRECT_BUFFER;
          case BufferBinding::ElementArray:
              return GL_ELEMENT_ARRAY_BUFFER;
          case BufferBinding::PixelPack:
              return GL_PIXEL_PACK_BUFFER;
          case BufferBinding::PixelUnpack:
              return GL_PIXEL_UNPACK_BUFFER;
          case BufferBinding::ShaderStorage:
              return GL_SHADER_STORAGE_BUFFER;
          case BufferBinding::TransformFeedback:
              return GL_TRANSFORM_FEEDBACK_BUFFER;
          case BufferBinding::Uniform:
              return GL_UNIFORM_BUFFER;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, BufferBinding value)
  {
      switch (value)
      {
          case BufferBinding::Array:
              os << "GL_ARRAY_BUFFER";
              break;
          case BufferBinding::AtomicCounter:
              os << "GL_ATOMIC_COUNTER_BUFFER";
              break;
          case BufferBinding::CopyRead:
              os << "GL_COPY_READ_BUFFER";
              break;
          case BufferBinding::CopyWrite:
              os << "GL_COPY_WRITE_BUFFER";
              break;
          case BufferBinding::DispatchIndirect:
              os << "GL_DISPATCH_INDIRECT_BUFFER";
              break;
          case BufferBinding::DrawIndirect:
              os << "GL_DRAW_INDIRECT_BUFFER";
              break;
          case BufferBinding::ElementArray:
              os << "GL_ELEMENT_ARRAY_BUFFER";
              break;
          case BufferBinding::PixelPack:
              os << "GL_PIXEL_PACK_BUFFER";
              break;
          case BufferBinding::PixelUnpack:
              os << "GL_PIXEL_UNPACK_BUFFER";
              break;
          case BufferBinding::ShaderStorage:
              os << "GL_SHADER_STORAGE_BUFFER";
              break;
          case BufferBinding::TransformFeedback:
              os << "GL_TRANSFORM_FEEDBACK_BUFFER";
              break;
          case BufferBinding::Uniform:
              os << "GL_UNIFORM_BUFFER";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  BufferUsage FromGLenum<BufferUsage>(GLenum from)
  {
      switch (from)
      {
          case GL_DYNAMIC_COPY:
              return BufferUsage::DynamicCopy;
          case GL_DYNAMIC_DRAW:
              return BufferUsage::DynamicDraw;
          case GL_DYNAMIC_READ:
              return BufferUsage::DynamicRead;
          case GL_STATIC_COPY:
              return BufferUsage::StaticCopy;
          case GL_STATIC_DRAW:
              return BufferUsage::StaticDraw;
          case GL_STATIC_READ:
              return BufferUsage::StaticRead;
          case GL_STREAM_COPY:
              return BufferUsage::StreamCopy;
          case GL_STREAM_DRAW:
              return BufferUsage::StreamDraw;
          case GL_STREAM_READ:
              return BufferUsage::StreamRead;
          default:
              return BufferUsage::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(BufferUsage from)
  {
      switch (from)
      {
          case BufferUsage::DynamicCopy:
              return GL_DYNAMIC_COPY;
          case BufferUsage::DynamicDraw:
              return GL_DYNAMIC_DRAW;
          case BufferUsage::DynamicRead:
              return GL_DYNAMIC_READ;
          case BufferUsage::StaticCopy:
              return GL_STATIC_COPY;
          case BufferUsage::StaticDraw:
              return GL_STATIC_DRAW;
          case BufferUsage::StaticRead:
              return GL_STATIC_READ;
          case BufferUsage::StreamCopy:
              return GL_STREAM_COPY;
          case BufferUsage::StreamDraw:
              return GL_STREAM_DRAW;
          case BufferUsage::StreamRead:
              return GL_STREAM_READ;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, BufferUsage value)
  {
      switch (value)
      {
          case BufferUsage::DynamicCopy:
              os << "GL_DYNAMIC_COPY";
              break;
          case BufferUsage::DynamicDraw:
              os << "GL_DYNAMIC_DRAW";
              break;
          case BufferUsage::DynamicRead:
              os << "GL_DYNAMIC_READ";
              break;
          case BufferUsage::StaticCopy:
              os << "GL_STATIC_COPY";
              break;
          case BufferUsage::StaticDraw:
              os << "GL_STATIC_DRAW";
              break;
          case BufferUsage::StaticRead:
              os << "GL_STATIC_READ";
              break;
          case BufferUsage::StreamCopy:
              os << "GL_STREAM_COPY";
              break;
          case BufferUsage::StreamDraw:
              os << "GL_STREAM_DRAW";
              break;
          case BufferUsage::StreamRead:
              os << "GL_STREAM_READ";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  ClientVertexArrayType FromGLenum<ClientVertexArrayType>(GLenum from)
  {
      switch (from)
      {
          case GL_COLOR_ARRAY:
              return ClientVertexArrayType::Color;
          case GL_NORMAL_ARRAY:
              return ClientVertexArrayType::Normal;
          case GL_POINT_SIZE_ARRAY_OES:
              return ClientVertexArrayType::PointSize;
          case GL_TEXTURE_COORD_ARRAY:
              return ClientVertexArrayType::TextureCoord;
          case GL_VERTEX_ARRAY:
              return ClientVertexArrayType::Vertex;
          default:
              return ClientVertexArrayType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(ClientVertexArrayType from)
  {
      switch (from)
      {
          case ClientVertexArrayType::Color:
              return GL_COLOR_ARRAY;
          case ClientVertexArrayType::Normal:
              return GL_NORMAL_ARRAY;
          case ClientVertexArrayType::PointSize:
              return GL_POINT_SIZE_ARRAY_OES;
          case ClientVertexArrayType::TextureCoord:
              return GL_TEXTURE_COORD_ARRAY;
          case ClientVertexArrayType::Vertex:
              return GL_VERTEX_ARRAY;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, ClientVertexArrayType value)
  {
      switch (value)
      {
          case ClientVertexArrayType::Color:
              os << "GL_COLOR_ARRAY";
              break;
          case ClientVertexArrayType::Normal:
              os << "GL_NORMAL_ARRAY";
              break;
          case ClientVertexArrayType::PointSize:
              os << "GL_POINT_SIZE_ARRAY_OES";
              break;
          case ClientVertexArrayType::TextureCoord:
              os << "GL_TEXTURE_COORD_ARRAY";
              break;
          case ClientVertexArrayType::Vertex:
              os << "GL_VERTEX_ARRAY";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  CullFaceMode FromGLenum<CullFaceMode>(GLenum from)
  {
      switch (from)
      {
          case GL_BACK:
              return CullFaceMode::Back;
          case GL_FRONT:
              return CullFaceMode::Front;
          case GL_FRONT_AND_BACK:
              return CullFaceMode::FrontAndBack;
          default:
              return CullFaceMode::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(CullFaceMode from)
  {
      switch (from)
      {
          case CullFaceMode::Back:
              return GL_BACK;
          case CullFaceMode::Front:
              return GL_FRONT;
          case CullFaceMode::FrontAndBack:
              return GL_FRONT_AND_BACK;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, CullFaceMode value)
  {
      switch (value)
      {
          case CullFaceMode::Back:
              os << "GL_BACK";
              break;
          case CullFaceMode::Front:
              os << "GL_FRONT";
              break;
          case CullFaceMode::FrontAndBack:
              os << "GL_FRONT_AND_BACK";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  FilterMode FromGLenum<FilterMode>(GLenum from)
  {
      switch (from)
      {
          case GL_NEAREST:
              return FilterMode::Nearest;
          case GL_LINEAR:
              return FilterMode::Linear;
          case GL_NEAREST_MIPMAP_NEAREST:
              return FilterMode::NearestMipmapNearest;
          case GL_NEAREST_MIPMAP_LINEAR:
              return FilterMode::NearestMipmapLinear;
          case GL_LINEAR_MIPMAP_LINEAR:
              return FilterMode::LinearMipmapLinear;
          default:
              return FilterMode::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(FilterMode from)
  {
      switch (from)
      {
          case FilterMode::Nearest:
              return GL_NEAREST;
          case FilterMode::Linear:
              return GL_LINEAR;
          case FilterMode::NearestMipmapNearest:
              return GL_NEAREST_MIPMAP_NEAREST;
          case FilterMode::NearestMipmapLinear:
              return GL_NEAREST_MIPMAP_LINEAR;
          case FilterMode::LinearMipmapLinear:
              return GL_LINEAR_MIPMAP_LINEAR;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, FilterMode value)
  {
      switch (value)
      {
          case FilterMode::Nearest:
              os << "GL_NEAREST";
              break;
          case FilterMode::Linear:
              os << "GL_LINEAR";
              break;
          case FilterMode::NearestMipmapNearest:
              os << "GL_NEAREST_MIPMAP_NEAREST";
              break;
          case FilterMode::NearestMipmapLinear:
              os << "GL_NEAREST_MIPMAP_LINEAR";
              break;
          case FilterMode::LinearMipmapLinear:
              os << "GL_LINEAR_MIPMAP_LINEAR";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  FogMode FromGLenum<FogMode>(GLenum from)
  {
      switch (from)
      {
          case GL_EXP:
              return FogMode::Exp;
          case GL_EXP2:
              return FogMode::Exp2;
          case GL_LINEAR:
              return FogMode::Linear;
          default:
              return FogMode::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(FogMode from)
  {
      switch (from)
      {
          case FogMode::Exp:
              return GL_EXP;
          case FogMode::Exp2:
              return GL_EXP2;
          case FogMode::Linear:
              return GL_LINEAR;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, FogMode value)
  {
      switch (value)
      {
          case FogMode::Exp:
              os << "GL_EXP";
              break;
          case FogMode::Exp2:
              os << "GL_EXP2";
              break;
          case FogMode::Linear:
              os << "GL_LINEAR";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  GraphicsResetStatus FromGLenum<GraphicsResetStatus>(GLenum from)
  {
      switch (from)
      {
          case GL_NO_ERROR:
              return GraphicsResetStatus::NoError;
          case GL_GUILTY_CONTEXT_RESET:
              return GraphicsResetStatus::GuiltyContextReset;
          case GL_INNOCENT_CONTEXT_RESET:
              return GraphicsResetStatus::InnocentContextReset;
          case GL_UNKNOWN_CONTEXT_RESET:
              return GraphicsResetStatus::UnknownContextReset;
          default:
              return GraphicsResetStatus::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(GraphicsResetStatus from)
  {
      switch (from)
      {
          case GraphicsResetStatus::NoError:
              return GL_NO_ERROR;
          case GraphicsResetStatus::GuiltyContextReset:
              return GL_GUILTY_CONTEXT_RESET;
          case GraphicsResetStatus::InnocentContextReset:
              return GL_INNOCENT_CONTEXT_RESET;
          case GraphicsResetStatus::UnknownContextReset:
              return GL_UNKNOWN_CONTEXT_RESET;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, GraphicsResetStatus value)
  {
      switch (value)
      {
          case GraphicsResetStatus::NoError:
              os << "GL_NO_ERROR";
              break;
          case GraphicsResetStatus::GuiltyContextReset:
              os << "GL_GUILTY_CONTEXT_RESET";
              break;
          case GraphicsResetStatus::InnocentContextReset:
              os << "GL_INNOCENT_CONTEXT_RESET";
              break;
          case GraphicsResetStatus::UnknownContextReset:
              os << "GL_UNKNOWN_CONTEXT_RESET";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  HandleType FromGLenum<HandleType>(GLenum from)
  {
      switch (from)
      {
          case GL_HANDLE_TYPE_OPAQUE_FD_EXT:
              return HandleType::OpaqueFd;
          case GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE:
              return HandleType::ZirconVmo;
          case GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE:
              return HandleType::ZirconEvent;
          default:
              return HandleType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(HandleType from)
  {
      switch (from)
      {
          case HandleType::OpaqueFd:
              return GL_HANDLE_TYPE_OPAQUE_FD_EXT;
          case HandleType::ZirconVmo:
              return GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE;
          case HandleType::ZirconEvent:
              return GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, HandleType value)
  {
      switch (value)
      {
          case HandleType::OpaqueFd:
              os << "GL_HANDLE_TYPE_OPAQUE_FD_EXT";
              break;
          case HandleType::ZirconVmo:
              os << "GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE";
              break;
          case HandleType::ZirconEvent:
              os << "GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  HintSetting FromGLenum<HintSetting>(GLenum from)
  {
      switch (from)
      {
          case GL_DONT_CARE:
              return HintSetting::DontCare;
          case GL_FASTEST:
              return HintSetting::Fastest;
          case GL_NICEST:
              return HintSetting::Nicest;
          default:
              return HintSetting::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(HintSetting from)
  {
      switch (from)
      {
          case HintSetting::DontCare:
              return GL_DONT_CARE;
          case HintSetting::Fastest:
              return GL_FASTEST;
          case HintSetting::Nicest:
              return GL_NICEST;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, HintSetting value)
  {
      switch (value)
      {
          case HintSetting::DontCare:
              os << "GL_DONT_CARE";
              break;
          case HintSetting::Fastest:
              os << "GL_FASTEST";
              break;
          case HintSetting::Nicest:
              os << "GL_NICEST";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  ImageLayout FromGLenum<ImageLayout>(GLenum from)
  {
      switch (from)
      {
          case GL_NONE:
              return ImageLayout::Undefined;
          case GL_LAYOUT_GENERAL_EXT:
              return ImageLayout::General;
          case GL_LAYOUT_COLOR_ATTACHMENT_EXT:
              return ImageLayout::ColorAttachment;
          case GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT:
              return ImageLayout::DepthStencilAttachment;
          case GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT:
              return ImageLayout::DepthStencilReadOnlyAttachment;
          case GL_LAYOUT_SHADER_READ_ONLY_EXT:
              return ImageLayout::ShaderReadOnly;
          case GL_LAYOUT_TRANSFER_SRC_EXT:
              return ImageLayout::TransferSrc;
          case GL_LAYOUT_TRANSFER_DST_EXT:
              return ImageLayout::TransferDst;
          case GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT:
              return ImageLayout::DepthReadOnlyStencilAttachment;
          case GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT:
              return ImageLayout::DepthAttachmentStencilReadOnly;
          default:
              return ImageLayout::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(ImageLayout from)
  {
      switch (from)
      {
          case ImageLayout::Undefined:
              return GL_NONE;
          case ImageLayout::General:
              return GL_LAYOUT_GENERAL_EXT;
          case ImageLayout::ColorAttachment:
              return GL_LAYOUT_COLOR_ATTACHMENT_EXT;
          case ImageLayout::DepthStencilAttachment:
              return GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT;
          case ImageLayout::DepthStencilReadOnlyAttachment:
              return GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT;
          case ImageLayout::ShaderReadOnly:
              return GL_LAYOUT_SHADER_READ_ONLY_EXT;
          case ImageLayout::TransferSrc:
              return GL_LAYOUT_TRANSFER_SRC_EXT;
          case ImageLayout::TransferDst:
              return GL_LAYOUT_TRANSFER_DST_EXT;
          case ImageLayout::DepthReadOnlyStencilAttachment:
              return GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT;
          case ImageLayout::DepthAttachmentStencilReadOnly:
              return GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, ImageLayout value)
  {
      switch (value)
      {
          case ImageLayout::Undefined:
              os << "GL_NONE";
              break;
          case ImageLayout::General:
              os << "GL_LAYOUT_GENERAL_EXT";
              break;
          case ImageLayout::ColorAttachment:
              os << "GL_LAYOUT_COLOR_ATTACHMENT_EXT";
              break;
          case ImageLayout::DepthStencilAttachment:
              os << "GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT";
              break;
          case ImageLayout::DepthStencilReadOnlyAttachment:
              os << "GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT";
              break;
          case ImageLayout::ShaderReadOnly:
              os << "GL_LAYOUT_SHADER_READ_ONLY_EXT";
              break;
          case ImageLayout::TransferSrc:
              os << "GL_LAYOUT_TRANSFER_SRC_EXT";
              break;
          case ImageLayout::TransferDst:
              os << "GL_LAYOUT_TRANSFER_DST_EXT";
              break;
          case ImageLayout::DepthReadOnlyStencilAttachment:
              os << "GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT";
              break;
          case ImageLayout::DepthAttachmentStencilReadOnly:
              os << "GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  LightParameter FromGLenum<LightParameter>(GLenum from)
  {
      switch (from)
      {
          case GL_AMBIENT:
              return LightParameter::Ambient;
          case GL_AMBIENT_AND_DIFFUSE:
              return LightParameter::AmbientAndDiffuse;
          case GL_CONSTANT_ATTENUATION:
              return LightParameter::ConstantAttenuation;
          case GL_DIFFUSE:
              return LightParameter::Diffuse;
          case GL_LINEAR_ATTENUATION:
              return LightParameter::LinearAttenuation;
          case GL_POSITION:
              return LightParameter::Position;
          case GL_QUADRATIC_ATTENUATION:
              return LightParameter::QuadraticAttenuation;
          case GL_SPECULAR:
              return LightParameter::Specular;
          case GL_SPOT_CUTOFF:
              return LightParameter::SpotCutoff;
          case GL_SPOT_DIRECTION:
              return LightParameter::SpotDirection;
          case GL_SPOT_EXPONENT:
              return LightParameter::SpotExponent;
          default:
              return LightParameter::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(LightParameter from)
  {
      switch (from)
      {
          case LightParameter::Ambient:
              return GL_AMBIENT;
          case LightParameter::AmbientAndDiffuse:
              return GL_AMBIENT_AND_DIFFUSE;
          case LightParameter::ConstantAttenuation:
              return GL_CONSTANT_ATTENUATION;
          case LightParameter::Diffuse:
              return GL_DIFFUSE;
          case LightParameter::LinearAttenuation:
              return GL_LINEAR_ATTENUATION;
          case LightParameter::Position:
              return GL_POSITION;
          case LightParameter::QuadraticAttenuation:
              return GL_QUADRATIC_ATTENUATION;
          case LightParameter::Specular:
              return GL_SPECULAR;
          case LightParameter::SpotCutoff:
              return GL_SPOT_CUTOFF;
          case LightParameter::SpotDirection:
              return GL_SPOT_DIRECTION;
          case LightParameter::SpotExponent:
              return GL_SPOT_EXPONENT;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, LightParameter value)
  {
      switch (value)
      {
          case LightParameter::Ambient:
              os << "GL_AMBIENT";
              break;
          case LightParameter::AmbientAndDiffuse:
              os << "GL_AMBIENT_AND_DIFFUSE";
              break;
          case LightParameter::ConstantAttenuation:
              os << "GL_CONSTANT_ATTENUATION";
              break;
          case LightParameter::Diffuse:
              os << "GL_DIFFUSE";
              break;
          case LightParameter::LinearAttenuation:
              os << "GL_LINEAR_ATTENUATION";
              break;
          case LightParameter::Position:
              os << "GL_POSITION";
              break;
          case LightParameter::QuadraticAttenuation:
              os << "GL_QUADRATIC_ATTENUATION";
              break;
          case LightParameter::Specular:
              os << "GL_SPECULAR";
              break;
          case LightParameter::SpotCutoff:
              os << "GL_SPOT_CUTOFF";
              break;
          case LightParameter::SpotDirection:
              os << "GL_SPOT_DIRECTION";
              break;
          case LightParameter::SpotExponent:
              os << "GL_SPOT_EXPONENT";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  LogicalOperation FromGLenum<LogicalOperation>(GLenum from)
  {
      switch (from)
      {
          case GL_AND:
              return LogicalOperation::And;
          case GL_AND_INVERTED:
              return LogicalOperation::AndInverted;
          case GL_AND_REVERSE:
              return LogicalOperation::AndReverse;
          case GL_CLEAR:
              return LogicalOperation::Clear;
          case GL_COPY:
              return LogicalOperation::Copy;
          case GL_COPY_INVERTED:
              return LogicalOperation::CopyInverted;
          case GL_EQUIV:
              return LogicalOperation::Equiv;
          case GL_INVERT:
              return LogicalOperation::Invert;
          case GL_NAND:
              return LogicalOperation::Nand;
          case GL_NOOP:
              return LogicalOperation::Noop;
          case GL_NOR:
              return LogicalOperation::Nor;
          case GL_OR:
              return LogicalOperation::Or;
          case GL_OR_INVERTED:
              return LogicalOperation::OrInverted;
          case GL_OR_REVERSE:
              return LogicalOperation::OrReverse;
          case GL_SET:
              return LogicalOperation::Set;
          case GL_XOR:
              return LogicalOperation::Xor;
          default:
              return LogicalOperation::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(LogicalOperation from)
  {
      switch (from)
      {
          case LogicalOperation::And:
              return GL_AND;
          case LogicalOperation::AndInverted:
              return GL_AND_INVERTED;
          case LogicalOperation::AndReverse:
              return GL_AND_REVERSE;
          case LogicalOperation::Clear:
              return GL_CLEAR;
          case LogicalOperation::Copy:
              return GL_COPY;
          case LogicalOperation::CopyInverted:
              return GL_COPY_INVERTED;
          case LogicalOperation::Equiv:
              return GL_EQUIV;
          case LogicalOperation::Invert:
              return GL_INVERT;
          case LogicalOperation::Nand:
              return GL_NAND;
          case LogicalOperation::Noop:
              return GL_NOOP;
          case LogicalOperation::Nor:
              return GL_NOR;
          case LogicalOperation::Or:
              return GL_OR;
          case LogicalOperation::OrInverted:
              return GL_OR_INVERTED;
          case LogicalOperation::OrReverse:
              return GL_OR_REVERSE;
          case LogicalOperation::Set:
              return GL_SET;
          case LogicalOperation::Xor:
              return GL_XOR;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, LogicalOperation value)
  {
      switch (value)
      {
          case LogicalOperation::And:
              os << "GL_AND";
              break;
          case LogicalOperation::AndInverted:
              os << "GL_AND_INVERTED";
              break;
          case LogicalOperation::AndReverse:
              os << "GL_AND_REVERSE";
              break;
          case LogicalOperation::Clear:
              os << "GL_CLEAR";
              break;
          case LogicalOperation::Copy:
              os << "GL_COPY";
              break;
          case LogicalOperation::CopyInverted:
              os << "GL_COPY_INVERTED";
              break;
          case LogicalOperation::Equiv:
              os << "GL_EQUIV";
              break;
          case LogicalOperation::Invert:
              os << "GL_INVERT";
              break;
          case LogicalOperation::Nand:
              os << "GL_NAND";
              break;
          case LogicalOperation::Noop:
              os << "GL_NOOP";
              break;
          case LogicalOperation::Nor:
              os << "GL_NOR";
              break;
          case LogicalOperation::Or:
              os << "GL_OR";
              break;
          case LogicalOperation::OrInverted:
              os << "GL_OR_INVERTED";
              break;
          case LogicalOperation::OrReverse:
              os << "GL_OR_REVERSE";
              break;
          case LogicalOperation::Set:
              os << "GL_SET";
              break;
          case LogicalOperation::Xor:
              os << "GL_XOR";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  MaterialParameter FromGLenum<MaterialParameter>(GLenum from)
  {
      switch (from)
      {
          case GL_AMBIENT:
              return MaterialParameter::Ambient;
          case GL_AMBIENT_AND_DIFFUSE:
              return MaterialParameter::AmbientAndDiffuse;
          case GL_DIFFUSE:
              return MaterialParameter::Diffuse;
          case GL_EMISSION:
              return MaterialParameter::Emission;
          case GL_SHININESS:
              return MaterialParameter::Shininess;
          case GL_SPECULAR:
              return MaterialParameter::Specular;
          default:
              return MaterialParameter::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(MaterialParameter from)
  {
      switch (from)
      {
          case MaterialParameter::Ambient:
              return GL_AMBIENT;
          case MaterialParameter::AmbientAndDiffuse:
              return GL_AMBIENT_AND_DIFFUSE;
          case MaterialParameter::Diffuse:
              return GL_DIFFUSE;
          case MaterialParameter::Emission:
              return GL_EMISSION;
          case MaterialParameter::Shininess:
              return GL_SHININESS;
          case MaterialParameter::Specular:
              return GL_SPECULAR;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, MaterialParameter value)
  {
      switch (value)
      {
          case MaterialParameter::Ambient:
              os << "GL_AMBIENT";
              break;
          case MaterialParameter::AmbientAndDiffuse:
              os << "GL_AMBIENT_AND_DIFFUSE";
              break;
          case MaterialParameter::Diffuse:
              os << "GL_DIFFUSE";
              break;
          case MaterialParameter::Emission:
              os << "GL_EMISSION";
              break;
          case MaterialParameter::Shininess:
              os << "GL_SHININESS";
              break;
          case MaterialParameter::Specular:
              os << "GL_SPECULAR";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  MatrixType FromGLenum<MatrixType>(GLenum from)
  {
      switch (from)
      {
          case GL_MODELVIEW:
              return MatrixType::Modelview;
          case GL_PROJECTION:
              return MatrixType::Projection;
          case GL_TEXTURE:
              return MatrixType::Texture;
          default:
              return MatrixType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(MatrixType from)
  {
      switch (from)
      {
          case MatrixType::Modelview:
              return GL_MODELVIEW;
          case MatrixType::Projection:
              return GL_PROJECTION;
          case MatrixType::Texture:
              return GL_TEXTURE;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, MatrixType value)
  {
      switch (value)
      {
          case MatrixType::Modelview:
              os << "GL_MODELVIEW";
              break;
          case MatrixType::Projection:
              os << "GL_PROJECTION";
              break;
          case MatrixType::Texture:
              os << "GL_TEXTURE";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  PointParameter FromGLenum<PointParameter>(GLenum from)
  {
      switch (from)
      {
          case GL_POINT_SIZE_MIN:
              return PointParameter::PointSizeMin;
          case GL_POINT_SIZE_MAX:
              return PointParameter::PointSizeMax;
          case GL_POINT_FADE_THRESHOLD_SIZE:
              return PointParameter::PointFadeThresholdSize;
          case GL_POINT_DISTANCE_ATTENUATION:
              return PointParameter::PointDistanceAttenuation;
          default:
              return PointParameter::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(PointParameter from)
  {
      switch (from)
      {
          case PointParameter::PointSizeMin:
              return GL_POINT_SIZE_MIN;
          case PointParameter::PointSizeMax:
              return GL_POINT_SIZE_MAX;
          case PointParameter::PointFadeThresholdSize:
              return GL_POINT_FADE_THRESHOLD_SIZE;
          case PointParameter::PointDistanceAttenuation:
              return GL_POINT_DISTANCE_ATTENUATION;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, PointParameter value)
  {
      switch (value)
      {
          case PointParameter::PointSizeMin:
              os << "GL_POINT_SIZE_MIN";
              break;
          case PointParameter::PointSizeMax:
              os << "GL_POINT_SIZE_MAX";
              break;
          case PointParameter::PointFadeThresholdSize:
              os << "GL_POINT_FADE_THRESHOLD_SIZE";
              break;
          case PointParameter::PointDistanceAttenuation:
              os << "GL_POINT_DISTANCE_ATTENUATION";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  ProvokingVertexConvention FromGLenum<ProvokingVertexConvention>(GLenum from)
  {
      switch (from)
      {
          case GL_FIRST_VERTEX_CONVENTION:
              return ProvokingVertexConvention::FirstVertexConvention;
          case GL_LAST_VERTEX_CONVENTION:
              return ProvokingVertexConvention::LastVertexConvention;
          default:
              return ProvokingVertexConvention::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(ProvokingVertexConvention from)
  {
      switch (from)
      {
          case ProvokingVertexConvention::FirstVertexConvention:
              return GL_FIRST_VERTEX_CONVENTION;
          case ProvokingVertexConvention::LastVertexConvention:
              return GL_LAST_VERTEX_CONVENTION;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, ProvokingVertexConvention value)
  {
      switch (value)
      {
          case ProvokingVertexConvention::FirstVertexConvention:
              os << "GL_FIRST_VERTEX_CONVENTION";
              break;
          case ProvokingVertexConvention::LastVertexConvention:
              os << "GL_LAST_VERTEX_CONVENTION";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  QueryType FromGLenum<QueryType>(GLenum from)
  {
      switch (from)
      {
          case GL_ANY_SAMPLES_PASSED:
              return QueryType::AnySamples;
          case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
              return QueryType::AnySamplesConservative;
          case GL_COMMANDS_COMPLETED_CHROMIUM:
              return QueryType::CommandsCompleted;
          case GL_PRIMITIVES_GENERATED_EXT:
              return QueryType::PrimitivesGenerated;
          case GL_TIME_ELAPSED_EXT:
              return QueryType::TimeElapsed;
          case GL_TIMESTAMP_EXT:
              return QueryType::Timestamp;
          case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
              return QueryType::TransformFeedbackPrimitivesWritten;
          default:
              return QueryType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(QueryType from)
  {
      switch (from)
      {
          case QueryType::AnySamples:
              return GL_ANY_SAMPLES_PASSED;
          case QueryType::AnySamplesConservative:
              return GL_ANY_SAMPLES_PASSED_CONSERVATIVE;
          case QueryType::CommandsCompleted:
              return GL_COMMANDS_COMPLETED_CHROMIUM;
          case QueryType::PrimitivesGenerated:
              return GL_PRIMITIVES_GENERATED_EXT;
          case QueryType::TimeElapsed:
              return GL_TIME_ELAPSED_EXT;
          case QueryType::Timestamp:
              return GL_TIMESTAMP_EXT;
          case QueryType::TransformFeedbackPrimitivesWritten:
              return GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, QueryType value)
  {
      switch (value)
      {
          case QueryType::AnySamples:
              os << "GL_ANY_SAMPLES_PASSED";
              break;
          case QueryType::AnySamplesConservative:
              os << "GL_ANY_SAMPLES_PASSED_CONSERVATIVE";
              break;
          case QueryType::CommandsCompleted:
              os << "GL_COMMANDS_COMPLETED_CHROMIUM";
              break;
          case QueryType::PrimitivesGenerated:
              os << "GL_PRIMITIVES_GENERATED_EXT";
              break;
          case QueryType::TimeElapsed:
              os << "GL_TIME_ELAPSED_EXT";
              break;
          case QueryType::Timestamp:
              os << "GL_TIMESTAMP_EXT";
              break;
          case QueryType::TransformFeedbackPrimitivesWritten:
              os << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  ShaderType FromGLenum<ShaderType>(GLenum from)
  {
      switch (from)
      {
          case GL_VERTEX_SHADER:
              return ShaderType::Vertex;
          case GL_FRAGMENT_SHADER:
              return ShaderType::Fragment;
          case GL_GEOMETRY_SHADER_EXT:
              return ShaderType::Geometry;
          case GL_COMPUTE_SHADER:
              return ShaderType::Compute;
          default:
              return ShaderType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(ShaderType from)
  {
      switch (from)
      {
          case ShaderType::Vertex:
              return GL_VERTEX_SHADER;
          case ShaderType::Fragment:
              return GL_FRAGMENT_SHADER;
          case ShaderType::Geometry:
              return GL_GEOMETRY_SHADER_EXT;
          case ShaderType::Compute:
              return GL_COMPUTE_SHADER;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, ShaderType value)
  {
      switch (value)
      {
          case ShaderType::Vertex:
              os << "GL_VERTEX_SHADER";
              break;
          case ShaderType::Fragment:
              os << "GL_FRAGMENT_SHADER";
              break;
          case ShaderType::Geometry:
              os << "GL_GEOMETRY_SHADER_EXT";
              break;
          case ShaderType::Compute:
              os << "GL_COMPUTE_SHADER";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  ShadingModel FromGLenum<ShadingModel>(GLenum from)
  {
      switch (from)
      {
          case GL_FLAT:
              return ShadingModel::Flat;
          case GL_SMOOTH:
              return ShadingModel::Smooth;
          default:
              return ShadingModel::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(ShadingModel from)
  {
      switch (from)
      {
          case ShadingModel::Flat:
              return GL_FLAT;
          case ShadingModel::Smooth:
              return GL_SMOOTH;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, ShadingModel value)
  {
      switch (value)
      {
          case ShadingModel::Flat:
              os << "GL_FLAT";
              break;
          case ShadingModel::Smooth:
              os << "GL_SMOOTH";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureCombine FromGLenum<TextureCombine>(GLenum from)
  {
      switch (from)
      {
          case GL_ADD:
              return TextureCombine::Add;
          case GL_ADD_SIGNED:
              return TextureCombine::AddSigned;
          case GL_DOT3_RGB:
              return TextureCombine::Dot3Rgb;
          case GL_DOT3_RGBA:
              return TextureCombine::Dot3Rgba;
          case GL_INTERPOLATE:
              return TextureCombine::Interpolate;
          case GL_MODULATE:
              return TextureCombine::Modulate;
          case GL_REPLACE:
              return TextureCombine::Replace;
          case GL_SUBTRACT:
              return TextureCombine::Subtract;
          default:
              return TextureCombine::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureCombine from)
  {
      switch (from)
      {
          case TextureCombine::Add:
              return GL_ADD;
          case TextureCombine::AddSigned:
              return GL_ADD_SIGNED;
          case TextureCombine::Dot3Rgb:
              return GL_DOT3_RGB;
          case TextureCombine::Dot3Rgba:
              return GL_DOT3_RGBA;
          case TextureCombine::Interpolate:
              return GL_INTERPOLATE;
          case TextureCombine::Modulate:
              return GL_MODULATE;
          case TextureCombine::Replace:
              return GL_REPLACE;
          case TextureCombine::Subtract:
              return GL_SUBTRACT;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureCombine value)
  {
      switch (value)
      {
          case TextureCombine::Add:
              os << "GL_ADD";
              break;
          case TextureCombine::AddSigned:
              os << "GL_ADD_SIGNED";
              break;
          case TextureCombine::Dot3Rgb:
              os << "GL_DOT3_RGB";
              break;
          case TextureCombine::Dot3Rgba:
              os << "GL_DOT3_RGBA";
              break;
          case TextureCombine::Interpolate:
              os << "GL_INTERPOLATE";
              break;
          case TextureCombine::Modulate:
              os << "GL_MODULATE";
              break;
          case TextureCombine::Replace:
              os << "GL_REPLACE";
              break;
          case TextureCombine::Subtract:
              os << "GL_SUBTRACT";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureEnvMode FromGLenum<TextureEnvMode>(GLenum from)
  {
      switch (from)
      {
          case GL_ADD:
              return TextureEnvMode::Add;
          case GL_BLEND:
              return TextureEnvMode::Blend;
          case GL_COMBINE:
              return TextureEnvMode::Combine;
          case GL_DECAL:
              return TextureEnvMode::Decal;
          case GL_MODULATE:
              return TextureEnvMode::Modulate;
          case GL_REPLACE:
              return TextureEnvMode::Replace;
          default:
              return TextureEnvMode::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureEnvMode from)
  {
      switch (from)
      {
          case TextureEnvMode::Add:
              return GL_ADD;
          case TextureEnvMode::Blend:
              return GL_BLEND;
          case TextureEnvMode::Combine:
              return GL_COMBINE;
          case TextureEnvMode::Decal:
              return GL_DECAL;
          case TextureEnvMode::Modulate:
              return GL_MODULATE;
          case TextureEnvMode::Replace:
              return GL_REPLACE;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureEnvMode value)
  {
      switch (value)
      {
          case TextureEnvMode::Add:
              os << "GL_ADD";
              break;
          case TextureEnvMode::Blend:
              os << "GL_BLEND";
              break;
          case TextureEnvMode::Combine:
              os << "GL_COMBINE";
              break;
          case TextureEnvMode::Decal:
              os << "GL_DECAL";
              break;
          case TextureEnvMode::Modulate:
              os << "GL_MODULATE";
              break;
          case TextureEnvMode::Replace:
              os << "GL_REPLACE";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureEnvParameter FromGLenum<TextureEnvParameter>(GLenum from)
  {
      switch (from)
      {
          case GL_TEXTURE_ENV_MODE:
              return TextureEnvParameter::Mode;
          case GL_TEXTURE_ENV_COLOR:
              return TextureEnvParameter::Color;
          case GL_COMBINE_RGB:
              return TextureEnvParameter::CombineRgb;
          case GL_COMBINE_ALPHA:
              return TextureEnvParameter::CombineAlpha;
          case GL_RGB_SCALE:
              return TextureEnvParameter::RgbScale;
          case GL_ALPHA_SCALE:
              return TextureEnvParameter::AlphaScale;
          case GL_SRC0_RGB:
              return TextureEnvParameter::Src0Rgb;
          case GL_SRC1_RGB:
              return TextureEnvParameter::Src1Rgb;
          case GL_SRC2_RGB:
              return TextureEnvParameter::Src2Rgb;
          case GL_SRC0_ALPHA:
              return TextureEnvParameter::Src0Alpha;
          case GL_SRC1_ALPHA:
              return TextureEnvParameter::Src1Alpha;
          case GL_SRC2_ALPHA:
              return TextureEnvParameter::Src2Alpha;
          case GL_OPERAND0_RGB:
              return TextureEnvParameter::Op0Rgb;
          case GL_OPERAND1_RGB:
              return TextureEnvParameter::Op1Rgb;
          case GL_OPERAND2_RGB:
              return TextureEnvParameter::Op2Rgb;
          case GL_OPERAND0_ALPHA:
              return TextureEnvParameter::Op0Alpha;
          case GL_OPERAND1_ALPHA:
              return TextureEnvParameter::Op1Alpha;
          case GL_OPERAND2_ALPHA:
              return TextureEnvParameter::Op2Alpha;
          case GL_COORD_REPLACE_OES:
              return TextureEnvParameter::PointCoordReplace;
          default:
              return TextureEnvParameter::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureEnvParameter from)
  {
      switch (from)
      {
          case TextureEnvParameter::Mode:
              return GL_TEXTURE_ENV_MODE;
          case TextureEnvParameter::Color:
              return GL_TEXTURE_ENV_COLOR;
          case TextureEnvParameter::CombineRgb:
              return GL_COMBINE_RGB;
          case TextureEnvParameter::CombineAlpha:
              return GL_COMBINE_ALPHA;
          case TextureEnvParameter::RgbScale:
              return GL_RGB_SCALE;
          case TextureEnvParameter::AlphaScale:
              return GL_ALPHA_SCALE;
          case TextureEnvParameter::Src0Rgb:
              return GL_SRC0_RGB;
          case TextureEnvParameter::Src1Rgb:
              return GL_SRC1_RGB;
          case TextureEnvParameter::Src2Rgb:
              return GL_SRC2_RGB;
          case TextureEnvParameter::Src0Alpha:
              return GL_SRC0_ALPHA;
          case TextureEnvParameter::Src1Alpha:
              return GL_SRC1_ALPHA;
          case TextureEnvParameter::Src2Alpha:
              return GL_SRC2_ALPHA;
          case TextureEnvParameter::Op0Rgb:
              return GL_OPERAND0_RGB;
          case TextureEnvParameter::Op1Rgb:
              return GL_OPERAND1_RGB;
          case TextureEnvParameter::Op2Rgb:
              return GL_OPERAND2_RGB;
          case TextureEnvParameter::Op0Alpha:
              return GL_OPERAND0_ALPHA;
          case TextureEnvParameter::Op1Alpha:
              return GL_OPERAND1_ALPHA;
          case TextureEnvParameter::Op2Alpha:
              return GL_OPERAND2_ALPHA;
          case TextureEnvParameter::PointCoordReplace:
              return GL_COORD_REPLACE_OES;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureEnvParameter value)
  {
      switch (value)
      {
          case TextureEnvParameter::Mode:
              os << "GL_TEXTURE_ENV_MODE";
              break;
          case TextureEnvParameter::Color:
              os << "GL_TEXTURE_ENV_COLOR";
              break;
          case TextureEnvParameter::CombineRgb:
              os << "GL_COMBINE_RGB";
              break;
          case TextureEnvParameter::CombineAlpha:
              os << "GL_COMBINE_ALPHA";
              break;
          case TextureEnvParameter::RgbScale:
              os << "GL_RGB_SCALE";
              break;
          case TextureEnvParameter::AlphaScale:
              os << "GL_ALPHA_SCALE";
              break;
          case TextureEnvParameter::Src0Rgb:
              os << "GL_SRC0_RGB";
              break;
          case TextureEnvParameter::Src1Rgb:
              os << "GL_SRC1_RGB";
              break;
          case TextureEnvParameter::Src2Rgb:
              os << "GL_SRC2_RGB";
              break;
          case TextureEnvParameter::Src0Alpha:
              os << "GL_SRC0_ALPHA";
              break;
          case TextureEnvParameter::Src1Alpha:
              os << "GL_SRC1_ALPHA";
              break;
          case TextureEnvParameter::Src2Alpha:
              os << "GL_SRC2_ALPHA";
              break;
          case TextureEnvParameter::Op0Rgb:
              os << "GL_OPERAND0_RGB";
              break;
          case TextureEnvParameter::Op1Rgb:
              os << "GL_OPERAND1_RGB";
              break;
          case TextureEnvParameter::Op2Rgb:
              os << "GL_OPERAND2_RGB";
              break;
          case TextureEnvParameter::Op0Alpha:
              os << "GL_OPERAND0_ALPHA";
              break;
          case TextureEnvParameter::Op1Alpha:
              os << "GL_OPERAND1_ALPHA";
              break;
          case TextureEnvParameter::Op2Alpha:
              os << "GL_OPERAND2_ALPHA";
              break;
          case TextureEnvParameter::PointCoordReplace:
              os << "GL_COORD_REPLACE_OES";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureEnvTarget FromGLenum<TextureEnvTarget>(GLenum from)
  {
      switch (from)
      {
          case GL_TEXTURE_ENV:
              return TextureEnvTarget::Env;
          case GL_POINT_SPRITE_OES:
              return TextureEnvTarget::PointSprite;
          default:
              return TextureEnvTarget::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureEnvTarget from)
  {
      switch (from)
      {
          case TextureEnvTarget::Env:
              return GL_TEXTURE_ENV;
          case TextureEnvTarget::PointSprite:
              return GL_POINT_SPRITE_OES;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureEnvTarget value)
  {
      switch (value)
      {
          case TextureEnvTarget::Env:
              os << "GL_TEXTURE_ENV";
              break;
          case TextureEnvTarget::PointSprite:
              os << "GL_POINT_SPRITE_OES";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureOp FromGLenum<TextureOp>(GLenum from)
  {
      switch (from)
      {
          case GL_ONE_MINUS_SRC_ALPHA:
              return TextureOp::OneMinusSrcAlpha;
          case GL_ONE_MINUS_SRC_COLOR:
              return TextureOp::OneMinusSrcColor;
          case GL_SRC_ALPHA:
              return TextureOp::SrcAlpha;
          case GL_SRC_COLOR:
              return TextureOp::SrcColor;
          default:
              return TextureOp::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureOp from)
  {
      switch (from)
      {
          case TextureOp::OneMinusSrcAlpha:
              return GL_ONE_MINUS_SRC_ALPHA;
          case TextureOp::OneMinusSrcColor:
              return GL_ONE_MINUS_SRC_COLOR;
          case TextureOp::SrcAlpha:
              return GL_SRC_ALPHA;
          case TextureOp::SrcColor:
              return GL_SRC_COLOR;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureOp value)
  {
      switch (value)
      {
          case TextureOp::OneMinusSrcAlpha:
              os << "GL_ONE_MINUS_SRC_ALPHA";
              break;
          case TextureOp::OneMinusSrcColor:
              os << "GL_ONE_MINUS_SRC_COLOR";
              break;
          case TextureOp::SrcAlpha:
              os << "GL_SRC_ALPHA";
              break;
          case TextureOp::SrcColor:
              os << "GL_SRC_COLOR";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureSrc FromGLenum<TextureSrc>(GLenum from)
  {
      switch (from)
      {
          case GL_CONSTANT:
              return TextureSrc::Constant;
          case GL_PREVIOUS:
              return TextureSrc::Previous;
          case GL_PRIMARY_COLOR:
              return TextureSrc::PrimaryColor;
          case GL_TEXTURE:
              return TextureSrc::Texture;
          default:
              return TextureSrc::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureSrc from)
  {
      switch (from)
      {
          case TextureSrc::Constant:
              return GL_CONSTANT;
          case TextureSrc::Previous:
              return GL_PREVIOUS;
          case TextureSrc::PrimaryColor:
              return GL_PRIMARY_COLOR;
          case TextureSrc::Texture:
              return GL_TEXTURE;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureSrc value)
  {
      switch (value)
      {
          case TextureSrc::Constant:
              os << "GL_CONSTANT";
              break;
          case TextureSrc::Previous:
              os << "GL_PREVIOUS";
              break;
          case TextureSrc::PrimaryColor:
              os << "GL_PRIMARY_COLOR";
              break;
          case TextureSrc::Texture:
              os << "GL_TEXTURE";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureTarget FromGLenum<TextureTarget>(GLenum from)
  {
      switch (from)
      {
          case GL_TEXTURE_2D:
              return TextureTarget::_2D;
          case GL_TEXTURE_2D_ARRAY:
              return TextureTarget::_2DArray;
          case GL_TEXTURE_2D_MULTISAMPLE:
              return TextureTarget::_2DMultisample;
          case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
              return TextureTarget::_2DMultisampleArray;
          case GL_TEXTURE_3D:
              return TextureTarget::_3D;
          case GL_TEXTURE_EXTERNAL_OES:
              return TextureTarget::External;
          case GL_TEXTURE_RECTANGLE_ANGLE:
              return TextureTarget::Rectangle;
          case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
              return TextureTarget::CubeMapPositiveX;
          case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
              return TextureTarget::CubeMapNegativeX;
          case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
              return TextureTarget::CubeMapPositiveY;
          case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
              return TextureTarget::CubeMapNegativeY;
          case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
              return TextureTarget::CubeMapPositiveZ;
          case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
              return TextureTarget::CubeMapNegativeZ;
          case GL_TEXTURE_CUBE_MAP_ARRAY:
              return TextureTarget::CubeMapArray;
          case GL_TEXTURE_VIDEO_IMAGE_WEBGL:
              return TextureTarget::VideoImage;
          default:
              return TextureTarget::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureTarget from)
  {
      switch (from)
      {
          case TextureTarget::_2D:
              return GL_TEXTURE_2D;
          case TextureTarget::_2DArray:
              return GL_TEXTURE_2D_ARRAY;
          case TextureTarget::_2DMultisample:
              return GL_TEXTURE_2D_MULTISAMPLE;
          case TextureTarget::_2DMultisampleArray:
              return GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES;
          case TextureTarget::_3D:
              return GL_TEXTURE_3D;
          case TextureTarget::External:
              return GL_TEXTURE_EXTERNAL_OES;
          case TextureTarget::Rectangle:
              return GL_TEXTURE_RECTANGLE_ANGLE;
          case TextureTarget::CubeMapPositiveX:
              return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
          case TextureTarget::CubeMapNegativeX:
              return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
          case TextureTarget::CubeMapPositiveY:
              return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
          case TextureTarget::CubeMapNegativeY:
              return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
          case TextureTarget::CubeMapPositiveZ:
              return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
          case TextureTarget::CubeMapNegativeZ:
              return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
          case TextureTarget::CubeMapArray:
              return GL_TEXTURE_CUBE_MAP_ARRAY;
          case TextureTarget::VideoImage:
              return GL_TEXTURE_VIDEO_IMAGE_WEBGL;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureTarget value)
  {
      switch (value)
      {
          case TextureTarget::_2D:
              os << "GL_TEXTURE_2D";
              break;
          case TextureTarget::_2DArray:
              os << "GL_TEXTURE_2D_ARRAY";
              break;
          case TextureTarget::_2DMultisample:
              os << "GL_TEXTURE_2D_MULTISAMPLE";
              break;
          case TextureTarget::_2DMultisampleArray:
              os << "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES";
              break;
          case TextureTarget::_3D:
              os << "GL_TEXTURE_3D";
              break;
          case TextureTarget::External:
              os << "GL_TEXTURE_EXTERNAL_OES";
              break;
          case TextureTarget::Rectangle:
              os << "GL_TEXTURE_RECTANGLE_ANGLE";
              break;
          case TextureTarget::CubeMapPositiveX:
              os << "GL_TEXTURE_CUBE_MAP_POSITIVE_X";
              break;
          case TextureTarget::CubeMapNegativeX:
              os << "GL_TEXTURE_CUBE_MAP_NEGATIVE_X";
              break;
          case TextureTarget::CubeMapPositiveY:
              os << "GL_TEXTURE_CUBE_MAP_POSITIVE_Y";
              break;
          case TextureTarget::CubeMapNegativeY:
              os << "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y";
              break;
          case TextureTarget::CubeMapPositiveZ:
              os << "GL_TEXTURE_CUBE_MAP_POSITIVE_Z";
              break;
          case TextureTarget::CubeMapNegativeZ:
              os << "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z";
              break;
          case TextureTarget::CubeMapArray:
              os << "GL_TEXTURE_CUBE_MAP_ARRAY";
              break;
          case TextureTarget::VideoImage:
              os << "GL_TEXTURE_VIDEO_IMAGE_WEBGL";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  TextureType FromGLenum<TextureType>(GLenum from)
  {
      switch (from)
      {
          case GL_TEXTURE_2D:
              return TextureType::_2D;
          case GL_TEXTURE_2D_ARRAY:
              return TextureType::_2DArray;
          case GL_TEXTURE_2D_MULTISAMPLE:
              return TextureType::_2DMultisample;
          case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
              return TextureType::_2DMultisampleArray;
          case GL_TEXTURE_3D:
              return TextureType::_3D;
          case GL_TEXTURE_EXTERNAL_OES:
              return TextureType::External;
          case GL_TEXTURE_RECTANGLE_ANGLE:
              return TextureType::Rectangle;
          case GL_TEXTURE_CUBE_MAP:
              return TextureType::CubeMap;
          case GL_TEXTURE_CUBE_MAP_ARRAY:
              return TextureType::CubeMapArray;
          case GL_TEXTURE_VIDEO_IMAGE_WEBGL:
              return TextureType::VideoImage;
          default:
              return TextureType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(TextureType from)
  {
      switch (from)
      {
          case TextureType::_2D:
              return GL_TEXTURE_2D;
          case TextureType::_2DArray:
              return GL_TEXTURE_2D_ARRAY;
          case TextureType::_2DMultisample:
              return GL_TEXTURE_2D_MULTISAMPLE;
          case TextureType::_2DMultisampleArray:
              return GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES;
          case TextureType::_3D:
              return GL_TEXTURE_3D;
          case TextureType::External:
              return GL_TEXTURE_EXTERNAL_OES;
          case TextureType::Rectangle:
              return GL_TEXTURE_RECTANGLE_ANGLE;
          case TextureType::CubeMap:
              return GL_TEXTURE_CUBE_MAP;
          case TextureType::CubeMapArray:
              return GL_TEXTURE_CUBE_MAP_ARRAY;
          case TextureType::VideoImage:
              return GL_TEXTURE_VIDEO_IMAGE_WEBGL;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, TextureType value)
  {
      switch (value)
      {
          case TextureType::_2D:
              os << "GL_TEXTURE_2D";
              break;
          case TextureType::_2DArray:
              os << "GL_TEXTURE_2D_ARRAY";
              break;
          case TextureType::_2DMultisample:
              os << "GL_TEXTURE_2D_MULTISAMPLE";
              break;
          case TextureType::_2DMultisampleArray:
              os << "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES";
              break;
          case TextureType::_3D:
              os << "GL_TEXTURE_3D";
              break;
          case TextureType::External:
              os << "GL_TEXTURE_EXTERNAL_OES";
              break;
          case TextureType::Rectangle:
              os << "GL_TEXTURE_RECTANGLE_ANGLE";
              break;
          case TextureType::CubeMap:
              os << "GL_TEXTURE_CUBE_MAP";
              break;
          case TextureType::CubeMapArray:
              os << "GL_TEXTURE_CUBE_MAP_ARRAY";
              break;
          case TextureType::VideoImage:
              os << "GL_TEXTURE_VIDEO_IMAGE_WEBGL";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  VertexArrayType FromGLenum<VertexArrayType>(GLenum from)
  {
      switch (from)
      {
          case GL_COLOR_ARRAY:
              return VertexArrayType::Color;
          case GL_NORMAL_ARRAY:
              return VertexArrayType::Normal;
          case GL_POINT_SIZE_ARRAY_OES:
              return VertexArrayType::PointSize;
          case GL_TEXTURE_COORD_ARRAY:
              return VertexArrayType::TextureCoord;
          case GL_VERTEX_ARRAY:
              return VertexArrayType::Vertex;
          default:
              return VertexArrayType::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(VertexArrayType from)
  {
      switch (from)
      {
          case VertexArrayType::Color:
              return GL_COLOR_ARRAY;
          case VertexArrayType::Normal:
              return GL_NORMAL_ARRAY;
          case VertexArrayType::PointSize:
              return GL_POINT_SIZE_ARRAY_OES;
          case VertexArrayType::TextureCoord:
              return GL_TEXTURE_COORD_ARRAY;
          case VertexArrayType::Vertex:
              return GL_VERTEX_ARRAY;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, VertexArrayType value)
  {
      switch (value)
      {
          case VertexArrayType::Color:
              os << "GL_COLOR_ARRAY";
              break;
          case VertexArrayType::Normal:
              os << "GL_NORMAL_ARRAY";
              break;
          case VertexArrayType::PointSize:
              os << "GL_POINT_SIZE_ARRAY_OES";
              break;
          case VertexArrayType::TextureCoord:
              os << "GL_TEXTURE_COORD_ARRAY";
              break;
          case VertexArrayType::Vertex:
              os << "GL_VERTEX_ARRAY";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  template <>
  WrapMode FromGLenum<WrapMode>(GLenum from)
  {
      switch (from)
      {
          case GL_CLAMP_TO_EDGE:
              return WrapMode::ClampToEdge;
          case GL_CLAMP_TO_BORDER:
              return WrapMode::ClampToBorder;
          case GL_MIRRORED_REPEAT:
              return WrapMode::MirroredRepeat;
          case GL_REPEAT:
              return WrapMode::Repeat;
          default:
              return WrapMode::InvalidEnum;
      }
  }
  
  GLenum ToGLenum(WrapMode from)
  {
      switch (from)
      {
          case WrapMode::ClampToEdge:
              return GL_CLAMP_TO_EDGE;
          case WrapMode::ClampToBorder:
              return GL_CLAMP_TO_BORDER;
          case WrapMode::MirroredRepeat:
              return GL_MIRRORED_REPEAT;
          case WrapMode::Repeat:
              return GL_REPEAT;
          default:
              UNREACHABLE();
              return 0;
      }
  }
  
  std::ostream &operator<<(std::ostream &os, WrapMode value)
  {
      switch (value)
      {
          case WrapMode::ClampToEdge:
              os << "GL_CLAMP_TO_EDGE";
              break;
          case WrapMode::ClampToBorder:
              os << "GL_CLAMP_TO_BORDER";
              break;
          case WrapMode::MirroredRepeat:
              os << "GL_MIRRORED_REPEAT";
              break;
          case WrapMode::Repeat:
              os << "GL_REPEAT";
              break;
          default:
              os << "GL_INVALID_ENUM";
              break;
      }
      return os;
  }
  
  }  // namespace gl
  