// Copyright 2013 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "Common/GL/GLExtensions/GLExtensions.h"

#include <sstream>
#include <unordered_map>

#include "Common/GL/GLContext.h"
#include "Common/Logging/Log.h"

#if defined(__linux__) || defined(__APPLE__)
#include <dlfcn.h>
#endif

// gl_1_1
PFNDOLCLEARINDEXPROC dolClearIndex;
PFNDOLCLEARCOLORPROC dolClearColor;
PFNDOLCLEARPROC dolClear;
PFNDOLINDEXMASKPROC dolIndexMask;
PFNDOLCOLORMASKPROC dolColorMask;
PFNDOLALPHAFUNCPROC dolAlphaFunc;
PFNDOLBLENDFUNCPROC dolBlendFunc;
PFNDOLLOGICOPPROC dolLogicOp;
PFNDOLCULLFACEPROC dolCullFace;
PFNDOLFRONTFACEPROC dolFrontFace;
PFNDOLPOINTSIZEPROC dolPointSize;
PFNDOLLINEWIDTHPROC dolLineWidth;
PFNDOLLINESTIPPLEPROC dolLineStipple;
PFNDOLPOLYGONMODEPROC dolPolygonMode;
PFNDOLPOLYGONOFFSETPROC dolPolygonOffset;
PFNDOLPOLYGONSTIPPLEPROC dolPolygonStipple;
PFNDOLGETPOLYGONSTIPPLEPROC dolGetPolygonStipple;
PFNDOLEDGEFLAGPROC dolEdgeFlag;
PFNDOLEDGEFLAGVPROC dolEdgeFlagv;
PFNDOLSCISSORPROC dolScissor;
PFNDOLCLIPPLANEPROC dolClipPlane;
PFNDOLGETCLIPPLANEPROC dolGetClipPlane;
PFNDOLDRAWBUFFERPROC dolDrawBuffer;
PFNDOLREADBUFFERPROC dolReadBuffer;
PFNDOLENABLEPROC dolEnable;
PFNDOLDISABLEPROC dolDisable;
PFNDOLISENABLEDPROC dolIsEnabled;
PFNDOLENABLECLIENTSTATEPROC dolEnableClientState;
PFNDOLDISABLECLIENTSTATEPROC dolDisableClientState;
PFNDOLGETBOOLEANVPROC dolGetBooleanv;
PFNDOLGETDOUBLEVPROC dolGetDoublev;
PFNDOLGETFLOATVPROC dolGetFloatv;
PFNDOLGETINTEGERVPROC dolGetIntegerv;
PFNDOLPUSHATTRIBPROC dolPushAttrib;
PFNDOLPOPATTRIBPROC dolPopAttrib;
PFNDOLPUSHCLIENTATTRIBPROC dolPushClientAttrib;
PFNDOLPOPCLIENTATTRIBPROC dolPopClientAttrib;
PFNDOLRENDERMODEPROC dolRenderMode;
PFNDOLGETERRORPROC dolGetError;
PFNDOLGETSTRINGPROC dolGetString;
PFNDOLFINISHPROC dolFinish;
PFNDOLFLUSHPROC dolFlush;
PFNDOLHINTPROC dolHint;
PFNDOLCLEARDEPTHPROC dolClearDepth;
PFNDOLDEPTHFUNCPROC dolDepthFunc;
PFNDOLDEPTHMASKPROC dolDepthMask;
PFNDOLDEPTHRANGEPROC dolDepthRange;
PFNDOLCLEARACCUMPROC dolClearAccum;
PFNDOLACCUMPROC dolAccum;
PFNDOLMATRIXMODEPROC dolMatrixMode;
PFNDOLORTHOPROC dolOrtho;
PFNDOLFRUSTUMPROC dolFrustum;
PFNDOLVIEWPORTPROC dolViewport;
PFNDOLPUSHMATRIXPROC dolPushMatrix;
PFNDOLPOPMATRIXPROC dolPopMatrix;
PFNDOLLOADIDENTITYPROC dolLoadIdentity;
PFNDOLLOADMATRIXDPROC dolLoadMatrixd;
PFNDOLLOADMATRIXFPROC dolLoadMatrixf;
PFNDOLMULTMATRIXDPROC dolMultMatrixd;
PFNDOLMULTMATRIXFPROC dolMultMatrixf;
PFNDOLROTATEDPROC dolRotated;
PFNDOLROTATEFPROC dolRotatef;
PFNDOLSCALEDPROC dolScaled;
PFNDOLSCALEFPROC dolScalef;
PFNDOLTRANSLATEDPROC dolTranslated;
PFNDOLTRANSLATEFPROC dolTranslatef;
PFNDOLISLISTPROC dolIsList;
PFNDOLDELETELISTSPROC dolDeleteLists;
PFNDOLGENLISTSPROC dolGenLists;
PFNDOLNEWLISTPROC dolNewList;
PFNDOLENDLISTPROC dolEndList;
PFNDOLCALLLISTPROC dolCallList;
PFNDOLCALLLISTSPROC dolCallLists;
PFNDOLLISTBASEPROC dolListBase;
PFNDOLBEGINPROC dolBegin;
PFNDOLENDPROC dolEnd;
PFNDOLVERTEX2DPROC dolVertex2d;
PFNDOLVERTEX2FPROC dolVertex2f;
PFNDOLVERTEX2IPROC dolVertex2i;
PFNDOLVERTEX2SPROC dolVertex2s;
PFNDOLVERTEX3DPROC dolVertex3d;
PFNDOLVERTEX3FPROC dolVertex3f;
PFNDOLVERTEX3IPROC dolVertex3i;
PFNDOLVERTEX3SPROC dolVertex3s;
PFNDOLVERTEX4DPROC dolVertex4d;
PFNDOLVERTEX4FPROC dolVertex4f;
PFNDOLVERTEX4IPROC dolVertex4i;
PFNDOLVERTEX4SPROC dolVertex4s;
PFNDOLVERTEX2DVPROC dolVertex2dv;
PFNDOLVERTEX2FVPROC dolVertex2fv;
PFNDOLVERTEX2IVPROC dolVertex2iv;
PFNDOLVERTEX2SVPROC dolVertex2sv;
PFNDOLVERTEX3DVPROC dolVertex3dv;
PFNDOLVERTEX3FVPROC dolVertex3fv;
PFNDOLVERTEX3IVPROC dolVertex3iv;
PFNDOLVERTEX3SVPROC dolVertex3sv;
PFNDOLVERTEX4DVPROC dolVertex4dv;
PFNDOLVERTEX4FVPROC dolVertex4fv;
PFNDOLVERTEX4IVPROC dolVertex4iv;
PFNDOLVERTEX4SVPROC dolVertex4sv;
PFNDOLNORMAL3BPROC dolNormal3b;
PFNDOLNORMAL3DPROC dolNormal3d;
PFNDOLNORMAL3FPROC dolNormal3f;
PFNDOLNORMAL3IPROC dolNormal3i;
PFNDOLNORMAL3SPROC dolNormal3s;
PFNDOLNORMAL3BVPROC dolNormal3bv;
PFNDOLNORMAL3DVPROC dolNormal3dv;
PFNDOLNORMAL3FVPROC dolNormal3fv;
PFNDOLNORMAL3IVPROC dolNormal3iv;
PFNDOLNORMAL3SVPROC dolNormal3sv;
PFNDOLINDEXDPROC dolIndexd;
PFNDOLINDEXFPROC dolIndexf;
PFNDOLINDEXIPROC dolIndexi;
PFNDOLINDEXSPROC dolIndexs;
PFNDOLINDEXUBPROC dolIndexub;
PFNDOLINDEXDVPROC dolIndexdv;
PFNDOLINDEXFVPROC dolIndexfv;
PFNDOLINDEXIVPROC dolIndexiv;
PFNDOLINDEXSVPROC dolIndexsv;
PFNDOLINDEXUBVPROC dolIndexubv;
PFNDOLCOLOR3BPROC dolColor3b;
PFNDOLCOLOR3DPROC dolColor3d;
PFNDOLCOLOR3FPROC dolColor3f;
PFNDOLCOLOR3IPROC dolColor3i;
PFNDOLCOLOR3SPROC dolColor3s;
PFNDOLCOLOR3UBPROC dolColor3ub;
PFNDOLCOLOR3UIPROC dolColor3ui;
PFNDOLCOLOR3USPROC dolColor3us;
PFNDOLCOLOR4BPROC dolColor4b;
PFNDOLCOLOR4DPROC dolColor4d;
PFNDOLCOLOR4FPROC dolColor4f;
PFNDOLCOLOR4IPROC dolColor4i;
PFNDOLCOLOR4SPROC dolColor4s;
PFNDOLCOLOR4UBPROC dolColor4ub;
PFNDOLCOLOR4UIPROC dolColor4ui;
PFNDOLCOLOR4USPROC dolColor4us;
PFNDOLCOLOR3BVPROC dolColor3bv;
PFNDOLCOLOR3DVPROC dolColor3dv;
PFNDOLCOLOR3FVPROC dolColor3fv;
PFNDOLCOLOR3IVPROC dolColor3iv;
PFNDOLCOLOR3SVPROC dolColor3sv;
PFNDOLCOLOR3UBVPROC dolColor3ubv;
PFNDOLCOLOR3UIVPROC dolColor3uiv;
PFNDOLCOLOR3USVPROC dolColor3usv;
PFNDOLCOLOR4BVPROC dolColor4bv;
PFNDOLCOLOR4DVPROC dolColor4dv;
PFNDOLCOLOR4FVPROC dolColor4fv;
PFNDOLCOLOR4IVPROC dolColor4iv;
PFNDOLCOLOR4SVPROC dolColor4sv;
PFNDOLCOLOR4UBVPROC dolColor4ubv;
PFNDOLCOLOR4UIVPROC dolColor4uiv;
PFNDOLCOLOR4USVPROC dolColor4usv;
PFNDOLTEXCOORD1DPROC dolTexCoord1d;
PFNDOLTEXCOORD1FPROC dolTexCoord1f;
PFNDOLTEXCOORD1IPROC dolTexCoord1i;
PFNDOLTEXCOORD1SPROC dolTexCoord1s;
PFNDOLTEXCOORD2DPROC dolTexCoord2d;
PFNDOLTEXCOORD2FPROC dolTexCoord2f;
PFNDOLTEXCOORD2IPROC dolTexCoord2i;
PFNDOLTEXCOORD2SPROC dolTexCoord2s;
PFNDOLTEXCOORD3DPROC dolTexCoord3d;
PFNDOLTEXCOORD3FPROC dolTexCoord3f;
PFNDOLTEXCOORD3IPROC dolTexCoord3i;
PFNDOLTEXCOORD3SPROC dolTexCoord3s;
PFNDOLTEXCOORD4DPROC dolTexCoord4d;
PFNDOLTEXCOORD4FPROC dolTexCoord4f;
PFNDOLTEXCOORD4IPROC dolTexCoord4i;
PFNDOLTEXCOORD4SPROC dolTexCoord4s;
PFNDOLTEXCOORD1DVPROC dolTexCoord1dv;
PFNDOLTEXCOORD1FVPROC dolTexCoord1fv;
PFNDOLTEXCOORD1IVPROC dolTexCoord1iv;
PFNDOLTEXCOORD1SVPROC dolTexCoord1sv;
PFNDOLTEXCOORD2DVPROC dolTexCoord2dv;
PFNDOLTEXCOORD2FVPROC dolTexCoord2fv;
PFNDOLTEXCOORD2IVPROC dolTexCoord2iv;
PFNDOLTEXCOORD2SVPROC dolTexCoord2sv;
PFNDOLTEXCOORD3DVPROC dolTexCoord3dv;
PFNDOLTEXCOORD3FVPROC dolTexCoord3fv;
PFNDOLTEXCOORD3IVPROC dolTexCoord3iv;
PFNDOLTEXCOORD3SVPROC dolTexCoord3sv;
PFNDOLTEXCOORD4DVPROC dolTexCoord4dv;
PFNDOLTEXCOORD4FVPROC dolTexCoord4fv;
PFNDOLTEXCOORD4IVPROC dolTexCoord4iv;
PFNDOLTEXCOORD4SVPROC dolTexCoord4sv;
PFNDOLRASTERPOS2DPROC dolRasterPos2d;
PFNDOLRASTERPOS2FPROC dolRasterPos2f;
PFNDOLRASTERPOS2IPROC dolRasterPos2i;
PFNDOLRASTERPOS2SPROC dolRasterPos2s;
PFNDOLRASTERPOS3DPROC dolRasterPos3d;
PFNDOLRASTERPOS3FPROC dolRasterPos3f;
PFNDOLRASTERPOS3IPROC dolRasterPos3i;
PFNDOLRASTERPOS3SPROC dolRasterPos3s;
PFNDOLRASTERPOS4DPROC dolRasterPos4d;
PFNDOLRASTERPOS4FPROC dolRasterPos4f;
PFNDOLRASTERPOS4IPROC dolRasterPos4i;
PFNDOLRASTERPOS4SPROC dolRasterPos4s;
PFNDOLRASTERPOS2DVPROC dolRasterPos2dv;
PFNDOLRASTERPOS2FVPROC dolRasterPos2fv;
PFNDOLRASTERPOS2IVPROC dolRasterPos2iv;
PFNDOLRASTERPOS2SVPROC dolRasterPos2sv;
PFNDOLRASTERPOS3DVPROC dolRasterPos3dv;
PFNDOLRASTERPOS3FVPROC dolRasterPos3fv;
PFNDOLRASTERPOS3IVPROC dolRasterPos3iv;
PFNDOLRASTERPOS3SVPROC dolRasterPos3sv;
PFNDOLRASTERPOS4DVPROC dolRasterPos4dv;
PFNDOLRASTERPOS4FVPROC dolRasterPos4fv;
PFNDOLRASTERPOS4IVPROC dolRasterPos4iv;
PFNDOLRASTERPOS4SVPROC dolRasterPos4sv;
PFNDOLRECTDPROC dolRectd;
PFNDOLRECTFPROC dolRectf;
PFNDOLRECTIPROC dolRecti;
PFNDOLRECTSPROC dolRects;
PFNDOLRECTDVPROC dolRectdv;
PFNDOLRECTFVPROC dolRectfv;
PFNDOLRECTIVPROC dolRectiv;
PFNDOLRECTSVPROC dolRectsv;
PFNDOLVERTEXPOINTERPROC dolVertexPointer;
PFNDOLNORMALPOINTERPROC dolNormalPointer;
PFNDOLCOLORPOINTERPROC dolColorPointer;
PFNDOLINDEXPOINTERPROC dolIndexPointer;
PFNDOLTEXCOORDPOINTERPROC dolTexCoordPointer;
PFNDOLEDGEFLAGPOINTERPROC dolEdgeFlagPointer;
PFNDOLGETPOINTERVPROC dolGetPointerv;
PFNDOLARRAYELEMENTPROC dolArrayElement;
PFNDOLDRAWARRAYSPROC dolDrawArrays;
PFNDOLDRAWELEMENTSPROC dolDrawElements;
PFNDOLINTERLEAVEDARRAYSPROC dolInterleavedArrays;
PFNDOLSHADEMODELPROC dolShadeModel;
PFNDOLLIGHTFPROC dolLightf;
PFNDOLLIGHTIPROC dolLighti;
PFNDOLLIGHTFVPROC dolLightfv;
PFNDOLLIGHTIVPROC dolLightiv;
PFNDOLGETLIGHTFVPROC dolGetLightfv;
PFNDOLGETLIGHTIVPROC dolGetLightiv;
PFNDOLLIGHTMODELFPROC dolLightModelf;
PFNDOLLIGHTMODELIPROC dolLightModeli;
PFNDOLLIGHTMODELFVPROC dolLightModelfv;
PFNDOLLIGHTMODELIVPROC dolLightModeliv;
PFNDOLMATERIALFPROC dolMaterialf;
PFNDOLMATERIALIPROC dolMateriali;
PFNDOLMATERIALFVPROC dolMaterialfv;
PFNDOLMATERIALIVPROC dolMaterialiv;
PFNDOLGETMATERIALFVPROC dolGetMaterialfv;
PFNDOLGETMATERIALIVPROC dolGetMaterialiv;
PFNDOLCOLORMATERIALPROC dolColorMaterial;
PFNDOLPIXELZOOMPROC dolPixelZoom;
PFNDOLPIXELSTOREFPROC dolPixelStoref;
PFNDOLPIXELSTOREIPROC dolPixelStorei;
PFNDOLPIXELTRANSFERFPROC dolPixelTransferf;
PFNDOLPIXELTRANSFERIPROC dolPixelTransferi;
PFNDOLPIXELMAPFVPROC dolPixelMapfv;
PFNDOLPIXELMAPUIVPROC dolPixelMapuiv;
PFNDOLPIXELMAPUSVPROC dolPixelMapusv;
PFNDOLGETPIXELMAPFVPROC dolGetPixelMapfv;
PFNDOLGETPIXELMAPUIVPROC dolGetPixelMapuiv;
PFNDOLGETPIXELMAPUSVPROC dolGetPixelMapusv;
PFNDOLBITMAPPROC dolBitmap;
PFNDOLREADPIXELSPROC dolReadPixels;
PFNDOLDRAWPIXELSPROC dolDrawPixels;
PFNDOLCOPYPIXELSPROC dolCopyPixels;
PFNDOLSTENCILFUNCPROC dolStencilFunc;
PFNDOLSTENCILMASKPROC dolStencilMask;
PFNDOLSTENCILOPPROC dolStencilOp;
PFNDOLCLEARSTENCILPROC dolClearStencil;
PFNDOLTEXGENDPROC dolTexGend;
PFNDOLTEXGENFPROC dolTexGenf;
PFNDOLTEXGENIPROC dolTexGeni;
PFNDOLTEXGENDVPROC dolTexGendv;
PFNDOLTEXGENFVPROC dolTexGenfv;
PFNDOLTEXGENIVPROC dolTexGeniv;
PFNDOLGETTEXGENDVPROC dolGetTexGendv;
PFNDOLGETTEXGENFVPROC dolGetTexGenfv;
PFNDOLGETTEXGENIVPROC dolGetTexGeniv;
PFNDOLTEXENVFPROC dolTexEnvf;
PFNDOLTEXENVIPROC dolTexEnvi;
PFNDOLTEXENVFVPROC dolTexEnvfv;
PFNDOLTEXENVIVPROC dolTexEnviv;
PFNDOLGETTEXENVFVPROC dolGetTexEnvfv;
PFNDOLGETTEXENVIVPROC dolGetTexEnviv;
PFNDOLTEXPARAMETERFPROC dolTexParameterf;
PFNDOLTEXPARAMETERIPROC dolTexParameteri;
PFNDOLTEXPARAMETERFVPROC dolTexParameterfv;
PFNDOLTEXPARAMETERIVPROC dolTexParameteriv;
PFNDOLGETTEXPARAMETERFVPROC dolGetTexParameterfv;
PFNDOLGETTEXPARAMETERIVPROC dolGetTexParameteriv;
PFNDOLGETTEXLEVELPARAMETERFVPROC dolGetTexLevelParameterfv;
PFNDOLGETTEXLEVELPARAMETERIVPROC dolGetTexLevelParameteriv;
PFNDOLTEXIMAGE1DPROC dolTexImage1D;
PFNDOLTEXIMAGE2DPROC dolTexImage2D;
PFNDOLGETTEXIMAGEPROC dolGetTexImage;
PFNDOLGENTEXTURESPROC dolGenTextures;
PFNDOLDELETETEXTURESPROC dolDeleteTextures;
PFNDOLBINDTEXTUREPROC dolBindTexture;
PFNDOLPRIORITIZETEXTURESPROC dolPrioritizeTextures;
PFNDOLARETEXTURESRESIDENTPROC dolAreTexturesResident;
PFNDOLISTEXTUREPROC dolIsTexture;
PFNDOLTEXSUBIMAGE1DPROC dolTexSubImage1D;
PFNDOLTEXSUBIMAGE2DPROC dolTexSubImage2D;
PFNDOLCOPYTEXIMAGE1DPROC dolCopyTexImage1D;
PFNDOLCOPYTEXIMAGE2DPROC dolCopyTexImage2D;
PFNDOLCOPYTEXSUBIMAGE1DPROC dolCopyTexSubImage1D;
PFNDOLCOPYTEXSUBIMAGE2DPROC dolCopyTexSubImage2D;
PFNDOLMAP1DPROC dolMap1d;
PFNDOLMAP1FPROC dolMap1f;
PFNDOLMAP2DPROC dolMap2d;
PFNDOLMAP2FPROC dolMap2f;
PFNDOLGETMAPDVPROC dolGetMapdv;
PFNDOLGETMAPFVPROC dolGetMapfv;
PFNDOLGETMAPIVPROC dolGetMapiv;
PFNDOLEVALCOORD1DPROC dolEvalCoord1d;
PFNDOLEVALCOORD1FPROC dolEvalCoord1f;
PFNDOLEVALCOORD1DVPROC dolEvalCoord1dv;
PFNDOLEVALCOORD1FVPROC dolEvalCoord1fv;
PFNDOLEVALCOORD2DPROC dolEvalCoord2d;
PFNDOLEVALCOORD2FPROC dolEvalCoord2f;
PFNDOLEVALCOORD2DVPROC dolEvalCoord2dv;
PFNDOLEVALCOORD2FVPROC dolEvalCoord2fv;
PFNDOLMAPGRID1DPROC dolMapGrid1d;
PFNDOLMAPGRID1FPROC dolMapGrid1f;
PFNDOLMAPGRID2DPROC dolMapGrid2d;
PFNDOLMAPGRID2FPROC dolMapGrid2f;
PFNDOLEVALPOINT1PROC dolEvalPoint1;
PFNDOLEVALPOINT2PROC dolEvalPoint2;
PFNDOLEVALMESH1PROC dolEvalMesh1;
PFNDOLEVALMESH2PROC dolEvalMesh2;
PFNDOLFOGFPROC dolFogf;
PFNDOLFOGIPROC dolFogi;
PFNDOLFOGFVPROC dolFogfv;
PFNDOLFOGIVPROC dolFogiv;
PFNDOLFEEDBACKBUFFERPROC dolFeedbackBuffer;
PFNDOLPASSTHROUGHPROC dolPassThrough;
PFNDOLSELECTBUFFERPROC dolSelectBuffer;
PFNDOLINITNAMESPROC dolInitNames;
PFNDOLLOADNAMEPROC dolLoadName;
PFNDOLPUSHNAMEPROC dolPushName;
PFNDOLPOPNAMEPROC dolPopName;

// gl_1_2
PFNDOLCOPYTEXSUBIMAGE3DPROC dolCopyTexSubImage3D;
PFNDOLDRAWRANGEELEMENTSPROC dolDrawRangeElements;
PFNDOLTEXIMAGE3DPROC dolTexImage3D;
PFNDOLTEXSUBIMAGE3DPROC dolTexSubImage3D;

// gl_1_3
PFNDOLACTIVETEXTUREARBPROC dolActiveTexture;
PFNDOLCLIENTACTIVETEXTUREARBPROC dolClientActiveTexture;
PFNDOLCOMPRESSEDTEXIMAGE1DPROC dolCompressedTexImage1D;
PFNDOLCOMPRESSEDTEXIMAGE2DPROC dolCompressedTexImage2D;
PFNDOLCOMPRESSEDTEXIMAGE3DPROC dolCompressedTexImage3D;
PFNDOLCOMPRESSEDTEXSUBIMAGE1DPROC dolCompressedTexSubImage1D;
PFNDOLCOMPRESSEDTEXSUBIMAGE2DPROC dolCompressedTexSubImage2D;
PFNDOLCOMPRESSEDTEXSUBIMAGE3DPROC dolCompressedTexSubImage3D;
PFNDOLGETCOMPRESSEDTEXIMAGEPROC dolGetCompressedTexImage;
PFNDOLLOADTRANSPOSEMATRIXDARBPROC dolLoadTransposeMatrixd;
PFNDOLLOADTRANSPOSEMATRIXFARBPROC dolLoadTransposeMatrixf;
PFNDOLMULTTRANSPOSEMATRIXDARBPROC dolMultTransposeMatrixd;
PFNDOLMULTTRANSPOSEMATRIXFARBPROC dolMultTransposeMatrixf;
PFNDOLMULTITEXCOORD1DARBPROC dolMultiTexCoord1d;
PFNDOLMULTITEXCOORD1DVARBPROC dolMultiTexCoord1dv;
PFNDOLMULTITEXCOORD1FARBPROC dolMultiTexCoord1f;
PFNDOLMULTITEXCOORD1FVARBPROC dolMultiTexCoord1fv;
PFNDOLMULTITEXCOORD1IARBPROC dolMultiTexCoord1i;
PFNDOLMULTITEXCOORD1IVARBPROC dolMultiTexCoord1iv;
PFNDOLMULTITEXCOORD1SARBPROC dolMultiTexCoord1s;
PFNDOLMULTITEXCOORD1SVARBPROC dolMultiTexCoord1sv;
PFNDOLMULTITEXCOORD2DARBPROC dolMultiTexCoord2d;
PFNDOLMULTITEXCOORD2DVARBPROC dolMultiTexCoord2dv;
PFNDOLMULTITEXCOORD2FARBPROC dolMultiTexCoord2f;
PFNDOLMULTITEXCOORD2FVARBPROC dolMultiTexCoord2fv;
PFNDOLMULTITEXCOORD2IARBPROC dolMultiTexCoord2i;
PFNDOLMULTITEXCOORD2IVARBPROC dolMultiTexCoord2iv;
PFNDOLMULTITEXCOORD2SARBPROC dolMultiTexCoord2s;
PFNDOLMULTITEXCOORD2SVARBPROC dolMultiTexCoord2sv;
PFNDOLMULTITEXCOORD3DARBPROC dolMultiTexCoord3d;
PFNDOLMULTITEXCOORD3DVARBPROC dolMultiTexCoord3dv;
PFNDOLMULTITEXCOORD3FARBPROC dolMultiTexCoord3f;
PFNDOLMULTITEXCOORD3FVARBPROC dolMultiTexCoord3fv;
PFNDOLMULTITEXCOORD3IARBPROC dolMultiTexCoord3i;
PFNDOLMULTITEXCOORD3IVARBPROC dolMultiTexCoord3iv;
PFNDOLMULTITEXCOORD3SARBPROC dolMultiTexCoord3s;
PFNDOLMULTITEXCOORD3SVARBPROC dolMultiTexCoord3sv;
PFNDOLMULTITEXCOORD4DARBPROC dolMultiTexCoord4d;
PFNDOLMULTITEXCOORD4DVARBPROC dolMultiTexCoord4dv;
PFNDOLMULTITEXCOORD4FARBPROC dolMultiTexCoord4f;
PFNDOLMULTITEXCOORD4FVARBPROC dolMultiTexCoord4fv;
PFNDOLMULTITEXCOORD4IARBPROC dolMultiTexCoord4i;
PFNDOLMULTITEXCOORD4IVARBPROC dolMultiTexCoord4iv;
PFNDOLMULTITEXCOORD4SARBPROC dolMultiTexCoord4s;
PFNDOLMULTITEXCOORD4SVARBPROC dolMultiTexCoord4sv;
PFNDOLSAMPLECOVERAGEARBPROC dolSampleCoverage;

// gl_1_4
PFNDOLBLENDCOLORPROC dolBlendColor;
PFNDOLBLENDEQUATIONPROC dolBlendEquation;
PFNDOLBLENDFUNCSEPARATEPROC dolBlendFuncSeparate;
PFNDOLFOGCOORDPOINTERPROC dolFogCoordPointer;
PFNDOLFOGCOORDDPROC dolFogCoordd;
PFNDOLFOGCOORDDVPROC dolFogCoorddv;
PFNDOLFOGCOORDFPROC dolFogCoordf;
PFNDOLFOGCOORDFVPROC dolFogCoordfv;
PFNDOLMULTIDRAWARRAYSPROC dolMultiDrawArrays;
PFNDOLMULTIDRAWELEMENTSPROC dolMultiDrawElements;
PFNDOLPOINTPARAMETERFPROC dolPointParameterf;
PFNDOLPOINTPARAMETERFVPROC dolPointParameterfv;
PFNDOLPOINTPARAMETERIPROC dolPointParameteri;
PFNDOLPOINTPARAMETERIVPROC dolPointParameteriv;
PFNDOLSECONDARYCOLOR3BPROC dolSecondaryColor3b;
PFNDOLSECONDARYCOLOR3BVPROC dolSecondaryColor3bv;
PFNDOLSECONDARYCOLOR3DPROC dolSecondaryColor3d;
PFNDOLSECONDARYCOLOR3DVPROC dolSecondaryColor3dv;
PFNDOLSECONDARYCOLOR3FPROC dolSecondaryColor3f;
PFNDOLSECONDARYCOLOR3FVPROC dolSecondaryColor3fv;
PFNDOLSECONDARYCOLOR3IPROC dolSecondaryColor3i;
PFNDOLSECONDARYCOLOR3IVPROC dolSecondaryColor3iv;
PFNDOLSECONDARYCOLOR3SPROC dolSecondaryColor3s;
PFNDOLSECONDARYCOLOR3SVPROC dolSecondaryColor3sv;
PFNDOLSECONDARYCOLOR3UBPROC dolSecondaryColor3ub;
PFNDOLSECONDARYCOLOR3UBVPROC dolSecondaryColor3ubv;
PFNDOLSECONDARYCOLOR3UIPROC dolSecondaryColor3ui;
PFNDOLSECONDARYCOLOR3UIVPROC dolSecondaryColor3uiv;
PFNDOLSECONDARYCOLOR3USPROC dolSecondaryColor3us;
PFNDOLSECONDARYCOLOR3USVPROC dolSecondaryColor3usv;
PFNDOLSECONDARYCOLORPOINTERPROC dolSecondaryColorPointer;
PFNDOLWINDOWPOS2DPROC dolWindowPos2d;
PFNDOLWINDOWPOS2DVPROC dolWindowPos2dv;
PFNDOLWINDOWPOS2FPROC dolWindowPos2f;
PFNDOLWINDOWPOS2FVPROC dolWindowPos2fv;
PFNDOLWINDOWPOS2IPROC dolWindowPos2i;
PFNDOLWINDOWPOS2IVPROC dolWindowPos2iv;
PFNDOLWINDOWPOS2SPROC dolWindowPos2s;
PFNDOLWINDOWPOS2SVPROC dolWindowPos2sv;
PFNDOLWINDOWPOS3DPROC dolWindowPos3d;
PFNDOLWINDOWPOS3DVPROC dolWindowPos3dv;
PFNDOLWINDOWPOS3FPROC dolWindowPos3f;
PFNDOLWINDOWPOS3FVPROC dolWindowPos3fv;
PFNDOLWINDOWPOS3IPROC dolWindowPos3i;
PFNDOLWINDOWPOS3IVPROC dolWindowPos3iv;
PFNDOLWINDOWPOS3SPROC dolWindowPos3s;
PFNDOLWINDOWPOS3SVPROC dolWindowPos3sv;

// gl_1_5
PFNDOLBEGINQUERYPROC dolBeginQuery;
PFNDOLBINDBUFFERPROC dolBindBuffer;
PFNDOLBUFFERDATAPROC dolBufferData;
PFNDOLBUFFERSUBDATAPROC dolBufferSubData;
PFNDOLDELETEBUFFERSPROC dolDeleteBuffers;
PFNDOLDELETEQUERIESPROC dolDeleteQueries;
PFNDOLENDQUERYPROC dolEndQuery;
PFNDOLGENBUFFERSPROC dolGenBuffers;
PFNDOLGENQUERIESPROC dolGenQueries;
PFNDOLGETBUFFERPARAMETERIVPROC dolGetBufferParameteriv;
PFNDOLGETBUFFERPOINTERVPROC dolGetBufferPointerv;
PFNDOLGETBUFFERSUBDATAPROC dolGetBufferSubData;
PFNDOLGETQUERYOBJECTIVPROC dolGetQueryObjectiv;
PFNDOLGETQUERYOBJECTUIVPROC dolGetQueryObjectuiv;
PFNDOLGETQUERYIVPROC dolGetQueryiv;
PFNDOLISBUFFERPROC dolIsBuffer;
PFNDOLISQUERYPROC dolIsQuery;
PFNDOLMAPBUFFERPROC dolMapBuffer;
PFNDOLUNMAPBUFFERPROC dolUnmapBuffer;

// gl_2_0
PFNDOLATTACHSHADERPROC dolAttachShader;
PFNDOLBINDATTRIBLOCATIONPROC dolBindAttribLocation;
PFNDOLBLENDEQUATIONSEPARATEPROC dolBlendEquationSeparate;
PFNDOLCOMPILESHADERPROC dolCompileShader;
PFNDOLCREATEPROGRAMPROC dolCreateProgram;
PFNDOLCREATESHADERPROC dolCreateShader;
PFNDOLDELETEPROGRAMPROC dolDeleteProgram;
PFNDOLDELETESHADERPROC dolDeleteShader;
PFNDOLDETACHSHADERPROC dolDetachShader;
PFNDOLDISABLEVERTEXATTRIBARRAYPROC dolDisableVertexAttribArray;
PFNDOLDRAWBUFFERSPROC dolDrawBuffers;
PFNDOLENABLEVERTEXATTRIBARRAYPROC dolEnableVertexAttribArray;
PFNDOLGETACTIVEATTRIBPROC dolGetActiveAttrib;
PFNDOLGETACTIVEUNIFORMPROC dolGetActiveUniform;
PFNDOLGETATTACHEDSHADERSPROC dolGetAttachedShaders;
PFNDOLGETATTRIBLOCATIONPROC dolGetAttribLocation;
PFNDOLGETPROGRAMINFOLOGPROC dolGetProgramInfoLog;
PFNDOLGETPROGRAMIVPROC dolGetProgramiv;
PFNDOLGETSHADERINFOLOGPROC dolGetShaderInfoLog;
PFNDOLGETSHADERSOURCEPROC dolGetShaderSource;
PFNDOLGETSHADERIVPROC dolGetShaderiv;
PFNDOLGETUNIFORMLOCATIONPROC dolGetUniformLocation;
PFNDOLGETUNIFORMFVPROC dolGetUniformfv;
PFNDOLGETUNIFORMIVPROC dolGetUniformiv;
PFNDOLGETVERTEXATTRIBPOINTERVPROC dolGetVertexAttribPointerv;
PFNDOLGETVERTEXATTRIBDVPROC dolGetVertexAttribdv;
PFNDOLGETVERTEXATTRIBFVPROC dolGetVertexAttribfv;
PFNDOLGETVERTEXATTRIBIVPROC dolGetVertexAttribiv;
PFNDOLISPROGRAMPROC dolIsProgram;
PFNDOLISSHADERPROC dolIsShader;
PFNDOLLINKPROGRAMPROC dolLinkProgram;
PFNDOLSHADERSOURCEPROC dolShaderSource;
PFNDOLSTENCILFUNCSEPARATEPROC dolStencilFuncSeparate;
PFNDOLSTENCILMASKSEPARATEPROC dolStencilMaskSeparate;
PFNDOLSTENCILOPSEPARATEPROC dolStencilOpSeparate;
PFNDOLUNIFORM1FPROC dolUniform1f;
PFNDOLUNIFORM1FVPROC dolUniform1fv;
PFNDOLUNIFORM1IPROC dolUniform1i;
PFNDOLUNIFORM1IVPROC dolUniform1iv;
PFNDOLUNIFORM2FPROC dolUniform2f;
PFNDOLUNIFORM2FVPROC dolUniform2fv;
PFNDOLUNIFORM2IPROC dolUniform2i;
PFNDOLUNIFORM2IVPROC dolUniform2iv;
PFNDOLUNIFORM3FPROC dolUniform3f;
PFNDOLUNIFORM3FVPROC dolUniform3fv;
PFNDOLUNIFORM3IPROC dolUniform3i;
PFNDOLUNIFORM3IVPROC dolUniform3iv;
PFNDOLUNIFORM4FPROC dolUniform4f;
PFNDOLUNIFORM4FVPROC dolUniform4fv;
PFNDOLUNIFORM4IPROC dolUniform4i;
PFNDOLUNIFORM4IVPROC dolUniform4iv;
PFNDOLUNIFORMMATRIX2FVPROC dolUniformMatrix2fv;
PFNDOLUNIFORMMATRIX3FVPROC dolUniformMatrix3fv;
PFNDOLUNIFORMMATRIX4FVPROC dolUniformMatrix4fv;
PFNDOLUSEPROGRAMPROC dolUseProgram;
PFNDOLVALIDATEPROGRAMPROC dolValidateProgram;
PFNDOLVERTEXATTRIB1DPROC dolVertexAttrib1d;
PFNDOLVERTEXATTRIB1DVPROC dolVertexAttrib1dv;
PFNDOLVERTEXATTRIB1FPROC dolVertexAttrib1f;
PFNDOLVERTEXATTRIB1FVPROC dolVertexAttrib1fv;
PFNDOLVERTEXATTRIB1SPROC dolVertexAttrib1s;
PFNDOLVERTEXATTRIB1SVPROC dolVertexAttrib1sv;
PFNDOLVERTEXATTRIB2DPROC dolVertexAttrib2d;
PFNDOLVERTEXATTRIB2DVPROC dolVertexAttrib2dv;
PFNDOLVERTEXATTRIB2FPROC dolVertexAttrib2f;
PFNDOLVERTEXATTRIB2FVPROC dolVertexAttrib2fv;
PFNDOLVERTEXATTRIB2SPROC dolVertexAttrib2s;
PFNDOLVERTEXATTRIB2SVPROC dolVertexAttrib2sv;
PFNDOLVERTEXATTRIB3DPROC dolVertexAttrib3d;
PFNDOLVERTEXATTRIB3DVPROC dolVertexAttrib3dv;
PFNDOLVERTEXATTRIB3FPROC dolVertexAttrib3f;
PFNDOLVERTEXATTRIB3FVPROC dolVertexAttrib3fv;
PFNDOLVERTEXATTRIB3SPROC dolVertexAttrib3s;
PFNDOLVERTEXATTRIB3SVPROC dolVertexAttrib3sv;
PFNDOLVERTEXATTRIB4NBVPROC dolVertexAttrib4Nbv;
PFNDOLVERTEXATTRIB4NIVPROC dolVertexAttrib4Niv;
PFNDOLVERTEXATTRIB4NSVPROC dolVertexAttrib4Nsv;
PFNDOLVERTEXATTRIB4NUBPROC dolVertexAttrib4Nub;
PFNDOLVERTEXATTRIB4NUBVPROC dolVertexAttrib4Nubv;
PFNDOLVERTEXATTRIB4NUIVPROC dolVertexAttrib4Nuiv;
PFNDOLVERTEXATTRIB4NUSVPROC dolVertexAttrib4Nusv;
PFNDOLVERTEXATTRIB4BVPROC dolVertexAttrib4bv;
PFNDOLVERTEXATTRIB4DPROC dolVertexAttrib4d;
PFNDOLVERTEXATTRIB4DVPROC dolVertexAttrib4dv;
PFNDOLVERTEXATTRIB4FPROC dolVertexAttrib4f;
PFNDOLVERTEXATTRIB4FVPROC dolVertexAttrib4fv;
PFNDOLVERTEXATTRIB4IVPROC dolVertexAttrib4iv;
PFNDOLVERTEXATTRIB4SPROC dolVertexAttrib4s;
PFNDOLVERTEXATTRIB4SVPROC dolVertexAttrib4sv;
PFNDOLVERTEXATTRIB4UBVPROC dolVertexAttrib4ubv;
PFNDOLVERTEXATTRIB4UIVPROC dolVertexAttrib4uiv;
PFNDOLVERTEXATTRIB4USVPROC dolVertexAttrib4usv;
PFNDOLVERTEXATTRIBPOINTERPROC dolVertexAttribPointer;

// gl_2_1
PFNDOLUNIFORMMATRIX2X3FVPROC dolUniformMatrix2x3fv;
PFNDOLUNIFORMMATRIX2X4FVPROC dolUniformMatrix2x4fv;
PFNDOLUNIFORMMATRIX3X2FVPROC dolUniformMatrix3x2fv;
PFNDOLUNIFORMMATRIX3X4FVPROC dolUniformMatrix3x4fv;
PFNDOLUNIFORMMATRIX4X2FVPROC dolUniformMatrix4x2fv;
PFNDOLUNIFORMMATRIX4X3FVPROC dolUniformMatrix4x3fv;

// gl_3_0
PFNDOLBEGINCONDITIONALRENDERPROC dolBeginConditionalRender;
PFNDOLBEGINTRANSFORMFEEDBACKPROC dolBeginTransformFeedback;
PFNDOLBINDFRAGDATALOCATIONPROC dolBindFragDataLocation;
PFNDOLCLAMPCOLORPROC dolClampColor;
PFNDOLCLEARBUFFERFIPROC dolClearBufferfi;
PFNDOLCLEARBUFFERFVPROC dolClearBufferfv;
PFNDOLCLEARBUFFERIVPROC dolClearBufferiv;
PFNDOLCLEARBUFFERUIVPROC dolClearBufferuiv;
PFNDOLCOLORMASKIPROC dolColorMaski;
PFNDOLDISABLEIPROC dolDisablei;
PFNDOLENABLEIPROC dolEnablei;
PFNDOLENDCONDITIONALRENDERPROC dolEndConditionalRender;
PFNDOLENDTRANSFORMFEEDBACKPROC dolEndTransformFeedback;
PFNDOLGETBOOLEANI_VPROC dolGetBooleani_v;
PFNDOLGETFRAGDATALOCATIONPROC dolGetFragDataLocation;
PFNDOLGETSTRINGIPROC dolGetStringi;
PFNDOLGETTEXPARAMETERIIVPROC dolGetTexParameterIiv;
PFNDOLGETTEXPARAMETERIUIVPROC dolGetTexParameterIuiv;
PFNDOLGETTRANSFORMFEEDBACKVARYINGPROC dolGetTransformFeedbackVarying;
PFNDOLGETUNIFORMUIVPROC dolGetUniformuiv;
PFNDOLGETVERTEXATTRIBIIVPROC dolGetVertexAttribIiv;
PFNDOLGETVERTEXATTRIBIUIVPROC dolGetVertexAttribIuiv;
PFNDOLISENABLEDIPROC dolIsEnabledi;
PFNDOLTEXPARAMETERIIVPROC dolTexParameterIiv;
PFNDOLTEXPARAMETERIUIVPROC dolTexParameterIuiv;
PFNDOLTRANSFORMFEEDBACKVARYINGSPROC dolTransformFeedbackVaryings;
PFNDOLUNIFORM1UIPROC dolUniform1ui;
PFNDOLUNIFORM1UIVPROC dolUniform1uiv;
PFNDOLUNIFORM2UIPROC dolUniform2ui;
PFNDOLUNIFORM2UIVPROC dolUniform2uiv;
PFNDOLUNIFORM3UIPROC dolUniform3ui;
PFNDOLUNIFORM3UIVPROC dolUniform3uiv;
PFNDOLUNIFORM4UIPROC dolUniform4ui;
PFNDOLUNIFORM4UIVPROC dolUniform4uiv;
PFNDOLVERTEXATTRIBI1IPROC dolVertexAttribI1i;
PFNDOLVERTEXATTRIBI1IVPROC dolVertexAttribI1iv;
PFNDOLVERTEXATTRIBI1UIPROC dolVertexAttribI1ui;
PFNDOLVERTEXATTRIBI1UIVPROC dolVertexAttribI1uiv;
PFNDOLVERTEXATTRIBI2IPROC dolVertexAttribI2i;
PFNDOLVERTEXATTRIBI2IVPROC dolVertexAttribI2iv;
PFNDOLVERTEXATTRIBI2UIPROC dolVertexAttribI2ui;
PFNDOLVERTEXATTRIBI2UIVPROC dolVertexAttribI2uiv;
PFNDOLVERTEXATTRIBI3IPROC dolVertexAttribI3i;
PFNDOLVERTEXATTRIBI3IVPROC dolVertexAttribI3iv;
PFNDOLVERTEXATTRIBI3UIPROC dolVertexAttribI3ui;
PFNDOLVERTEXATTRIBI3UIVPROC dolVertexAttribI3uiv;
PFNDOLVERTEXATTRIBI4BVPROC dolVertexAttribI4bv;
PFNDOLVERTEXATTRIBI4IPROC dolVertexAttribI4i;
PFNDOLVERTEXATTRIBI4IVPROC dolVertexAttribI4iv;
PFNDOLVERTEXATTRIBI4SVPROC dolVertexAttribI4sv;
PFNDOLVERTEXATTRIBI4UBVPROC dolVertexAttribI4ubv;
PFNDOLVERTEXATTRIBI4UIPROC dolVertexAttribI4ui;
PFNDOLVERTEXATTRIBI4UIVPROC dolVertexAttribI4uiv;
PFNDOLVERTEXATTRIBI4USVPROC dolVertexAttribI4usv;
PFNDOLVERTEXATTRIBIPOINTERPROC dolVertexAttribIPointer;

// gl_3_1
PFNDOLDRAWARRAYSINSTANCEDPROC dolDrawArraysInstanced;
PFNDOLDRAWELEMENTSINSTANCEDPROC dolDrawElementsInstanced;
PFNDOLPRIMITIVERESTARTINDEXPROC dolPrimitiveRestartIndex;
PFNDOLTEXBUFFERPROC dolTexBuffer;

// gl_3_2
PFNDOLFRAMEBUFFERTEXTUREPROC dolFramebufferTexture;
PFNDOLGETBUFFERPARAMETERI64VPROC dolGetBufferParameteri64v;
PFNDOLGETINTEGER64I_VPROC dolGetInteger64i_v;

// gl 4_2
PFNDOLDRAWARRAYSINSTANCEDBASEINSTANCEPROC dolDrawArraysInstancedBaseInstance;
PFNDOLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC dolDrawElementsInstancedBaseInstance;
PFNDOLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC
dolDrawElementsInstancedBaseVertexBaseInstance;
PFNDOLGETINTERNALFORMATIVPROC dolGetInternalformativ;
PFNDOLGETACTIVEATOMICCOUNTERBUFFERIVPROC dolGetActiveAtomicCounterBufferiv;
PFNDOLDRAWTRANSFORMFEEDBACKINSTANCEDPROC dolDrawTransformFeedbackInstanced;
PFNDOLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC dolDrawTransformFeedbackStreamInstanced;

// gl_4_3
PFNDOLCLEARBUFFERDATAPROC dolClearBufferData;
PFNDOLCLEARBUFFERSUBDATAPROC dolClearBufferSubData;
PFNDOLFRAMEBUFFERPARAMETERIPROC dolFramebufferParameteri;
PFNDOLGETFRAMEBUFFERPARAMETERIVPROC dolGetFramebufferParameteriv;
PFNDOLGETINTERNALFORMATI64VPROC dolGetInternalformati64v;
PFNDOLINVALIDATETEXSUBIMAGEPROC dolInvalidateTexSubImage;
PFNDOLINVALIDATETEXIMAGEPROC dolInvalidateTexImage;
PFNDOLINVALIDATEBUFFERSUBDATAPROC dolInvalidateBufferSubData;
PFNDOLINVALIDATEBUFFERDATAPROC dolInvalidateBufferData;
PFNDOLINVALIDATEFRAMEBUFFERPROC dolInvalidateFramebuffer;
PFNDOLINVALIDATESUBFRAMEBUFFERPROC dolInvalidateSubFramebuffer;
PFNDOLMULTIDRAWARRAYSINDIRECTPROC dolMultiDrawArraysIndirect;
PFNDOLMULTIDRAWELEMENTSINDIRECTPROC dolMultiDrawElementsIndirect;
PFNDOLGETPROGRAMINTERFACEIVPROC dolGetProgramInterfaceiv;
PFNDOLGETPROGRAMRESOURCEINDEXPROC dolGetProgramResourceIndex;
PFNDOLGETPROGRAMRESOURCENAMEPROC dolGetProgramResourceName;
PFNDOLGETPROGRAMRESOURCEIVPROC dolGetProgramResourceiv;
PFNDOLGETPROGRAMRESOURCELOCATIONPROC dolGetProgramResourceLocation;
PFNDOLGETPROGRAMRESOURCELOCATIONINDEXPROC dolGetProgramResourceLocationIndex;
PFNDOLTEXBUFFERRANGEPROC dolTexBufferRange;
PFNDOLTEXTUREVIEWPROC dolTextureView;
PFNDOLBINDVERTEXBUFFERPROC dolBindVertexBuffer;
PFNDOLVERTEXATTRIBFORMATPROC dolVertexAttribFormat;
PFNDOLVERTEXATTRIBIFORMATPROC dolVertexAttribIFormat;
PFNDOLVERTEXATTRIBLFORMATPROC dolVertexAttribLFormat;
PFNDOLVERTEXATTRIBBINDINGPROC dolVertexAttribBinding;
PFNDOLVERTEXBINDINGDIVISORPROC dolVertexBindingDivisor;

// gl_4_4
PFNDOLCLEARTEXIMAGEPROC dolClearTexImage;
PFNDOLCLEARTEXSUBIMAGEPROC dolClearTexSubImage;
PFNDOLBINDBUFFERSBASEPROC dolBindBuffersBase;
PFNDOLBINDBUFFERSRANGEPROC dolBindBuffersRange;
PFNDOLBINDTEXTURESPROC dolBindTextures;
PFNDOLBINDSAMPLERSPROC dolBindSamplers;
PFNDOLBINDIMAGETEXTURESPROC dolBindImageTextures;
PFNDOLBINDVERTEXBUFFERSPROC dolBindVertexBuffers;

// gl_4_5
PFNDOLCREATETRANSFORMFEEDBACKSPROC dolCreateTransformFeedbacks;
PFNDOLTRANSFORMFEEDBACKBUFFERBASEPROC dolTransformFeedbackBufferBase;
PFNDOLTRANSFORMFEEDBACKBUFFERRANGEPROC dolTransformFeedbackBufferRange;
PFNDOLGETTRANSFORMFEEDBACKIVPROC dolGetTransformFeedbackiv;
PFNDOLGETTRANSFORMFEEDBACKI_VPROC dolGetTransformFeedbacki_v;
PFNDOLGETTRANSFORMFEEDBACKI64_VPROC dolGetTransformFeedbacki64_v;
PFNDOLCREATEBUFFERSPROC dolCreateBuffers;
PFNDOLNAMEDBUFFERSTORAGEPROC dolNamedBufferStorage;
PFNDOLNAMEDBUFFERDATAPROC dolNamedBufferData;
PFNDOLNAMEDBUFFERSUBDATAPROC dolNamedBufferSubData;
PFNDOLCOPYNAMEDBUFFERSUBDATAPROC dolCopyNamedBufferSubData;
PFNDOLCLEARNAMEDBUFFERDATAPROC dolClearNamedBufferData;
PFNDOLCLEARNAMEDBUFFERSUBDATAPROC dolClearNamedBufferSubData;
PFNDOLMAPNAMEDBUFFERPROC dolMapNamedBuffer;
PFNDOLMAPNAMEDBUFFERRANGEPROC dolMapNamedBufferRange;
PFNDOLUNMAPNAMEDBUFFERPROC dolUnmapNamedBuffer;
PFNDOLFLUSHMAPPEDNAMEDBUFFERRANGEPROC dolFlushMappedNamedBufferRange;
PFNDOLGETNAMEDBUFFERPARAMETERIVPROC dolGetNamedBufferParameteriv;
PFNDOLGETNAMEDBUFFERPARAMETERI64VPROC dolGetNamedBufferParameteri64v;
PFNDOLGETNAMEDBUFFERPOINTERVPROC dolGetNamedBufferPointerv;
PFNDOLGETNAMEDBUFFERSUBDATAPROC dolGetNamedBufferSubData;
PFNDOLCREATEFRAMEBUFFERSPROC dolCreateFramebuffers;
PFNDOLNAMEDFRAMEBUFFERRENDERBUFFERPROC dolNamedFramebufferRenderbuffer;
PFNDOLNAMEDFRAMEBUFFERPARAMETERIPROC dolNamedFramebufferParameteri;
PFNDOLNAMEDFRAMEBUFFERTEXTUREPROC dolNamedFramebufferTexture;
PFNDOLNAMEDFRAMEBUFFERTEXTURELAYERPROC dolNamedFramebufferTextureLayer;
PFNDOLNAMEDFRAMEBUFFERDRAWBUFFERPROC dolNamedFramebufferDrawBuffer;
PFNDOLNAMEDFRAMEBUFFERDRAWBUFFERSPROC dolNamedFramebufferDrawBuffers;
PFNDOLNAMEDFRAMEBUFFERREADBUFFERPROC dolNamedFramebufferReadBuffer;
PFNDOLINVALIDATENAMEDFRAMEBUFFERDATAPROC dolInvalidateNamedFramebufferData;
PFNDOLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC dolInvalidateNamedFramebufferSubData;
PFNDOLCLEARNAMEDFRAMEBUFFERIVPROC dolClearNamedFramebufferiv;
PFNDOLCLEARNAMEDFRAMEBUFFERUIVPROC dolClearNamedFramebufferuiv;
PFNDOLCLEARNAMEDFRAMEBUFFERFVPROC dolClearNamedFramebufferfv;
PFNDOLCLEARNAMEDFRAMEBUFFERFIPROC dolClearNamedFramebufferfi;
PFNDOLBLITNAMEDFRAMEBUFFERPROC dolBlitNamedFramebuffer;
PFNDOLCHECKNAMEDFRAMEBUFFERSTATUSPROC dolCheckNamedFramebufferStatus;
PFNDOLGETNAMEDFRAMEBUFFERPARAMETERIVPROC dolGetNamedFramebufferParameteriv;
PFNDOLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC dolGetNamedFramebufferAttachmentParameteriv;
PFNDOLCREATERENDERBUFFERSPROC dolCreateRenderbuffers;
PFNDOLNAMEDRENDERBUFFERSTORAGEPROC dolNamedRenderbufferStorage;
PFNDOLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC dolNamedRenderbufferStorageMultisample;
PFNDOLGETNAMEDRENDERBUFFERPARAMETERIVPROC dolGetNamedRenderbufferParameteriv;
PFNDOLCREATETEXTURESPROC dolCreateTextures;
PFNDOLTEXTUREBUFFERPROC dolTextureBuffer;
PFNDOLTEXTUREBUFFERRANGEPROC dolTextureBufferRange;
PFNDOLTEXTURESTORAGE1DPROC dolTextureStorage1D;
PFNDOLTEXTURESTORAGE2DPROC dolTextureStorage2D;
PFNDOLTEXTURESTORAGE3DPROC dolTextureStorage3D;
PFNDOLTEXTURESTORAGE2DMULTISAMPLEPROC dolTextureStorage2DMultisample;
PFNDOLTEXTURESTORAGE3DMULTISAMPLEPROC dolTextureStorage3DMultisample;
PFNDOLTEXTURESUBIMAGE1DPROC dolTextureSubImage1D;
PFNDOLTEXTURESUBIMAGE2DPROC dolTextureSubImage2D;
PFNDOLTEXTURESUBIMAGE3DPROC dolTextureSubImage3D;
PFNDOLCOMPRESSEDTEXTURESUBIMAGE1DPROC dolCompressedTextureSubImage1D;
PFNDOLCOMPRESSEDTEXTURESUBIMAGE2DPROC dolCompressedTextureSubImage2D;
PFNDOLCOMPRESSEDTEXTURESUBIMAGE3DPROC dolCompressedTextureSubImage3D;
PFNDOLCOPYTEXTURESUBIMAGE1DPROC dolCopyTextureSubImage1D;
PFNDOLCOPYTEXTURESUBIMAGE2DPROC dolCopyTextureSubImage2D;
PFNDOLCOPYTEXTURESUBIMAGE3DPROC dolCopyTextureSubImage3D;
PFNDOLTEXTUREPARAMETERFPROC dolTextureParameterf;
PFNDOLTEXTUREPARAMETERFVPROC dolTextureParameterfv;
PFNDOLTEXTUREPARAMETERIPROC dolTextureParameteri;
PFNDOLTEXTUREPARAMETERIIVPROC dolTextureParameterIiv;
PFNDOLTEXTUREPARAMETERIUIVPROC dolTextureParameterIuiv;
PFNDOLTEXTUREPARAMETERIVPROC dolTextureParameteriv;
PFNDOLGENERATETEXTUREMIPMAPPROC dolGenerateTextureMipmap;
PFNDOLBINDTEXTUREUNITPROC dolBindTextureUnit;
PFNDOLGETTEXTUREIMAGEPROC dolGetTextureImage;
PFNDOLGETCOMPRESSEDTEXTUREIMAGEPROC dolGetCompressedTextureImage;
PFNDOLGETTEXTURELEVELPARAMETERFVPROC dolGetTextureLevelParameterfv;
PFNDOLGETTEXTURELEVELPARAMETERIVPROC dolGetTextureLevelParameteriv;
PFNDOLGETTEXTUREPARAMETERFVPROC dolGetTextureParameterfv;
PFNDOLGETTEXTUREPARAMETERIIVPROC dolGetTextureParameterIiv;
PFNDOLGETTEXTUREPARAMETERIUIVPROC dolGetTextureParameterIuiv;
PFNDOLGETTEXTUREPARAMETERIVPROC dolGetTextureParameteriv;
PFNDOLCREATEVERTEXARRAYSPROC dolCreateVertexArrays;
PFNDOLDISABLEVERTEXARRAYATTRIBPROC dolDisableVertexArrayAttrib;
PFNDOLENABLEVERTEXARRAYATTRIBPROC dolEnableVertexArrayAttrib;
PFNDOLVERTEXARRAYELEMENTBUFFERPROC dolVertexArrayElementBuffer;
PFNDOLVERTEXARRAYVERTEXBUFFERPROC dolVertexArrayVertexBuffer;
PFNDOLVERTEXARRAYVERTEXBUFFERSPROC dolVertexArrayVertexBuffers;
PFNDOLVERTEXARRAYATTRIBBINDINGPROC dolVertexArrayAttribBinding;
PFNDOLVERTEXARRAYATTRIBFORMATPROC dolVertexArrayAttribFormat;
PFNDOLVERTEXARRAYATTRIBIFORMATPROC dolVertexArrayAttribIFormat;
PFNDOLVERTEXARRAYATTRIBLFORMATPROC dolVertexArrayAttribLFormat;
PFNDOLVERTEXARRAYBINDINGDIVISORPROC dolVertexArrayBindingDivisor;
PFNDOLGETVERTEXARRAYIVPROC dolGetVertexArrayiv;
PFNDOLGETVERTEXARRAYINDEXEDIVPROC dolGetVertexArrayIndexediv;
PFNDOLGETVERTEXARRAYINDEXED64IVPROC dolGetVertexArrayIndexed64iv;
PFNDOLCREATESAMPLERSPROC dolCreateSamplers;
PFNDOLCREATEPROGRAMPIPELINESPROC dolCreateProgramPipelines;
PFNDOLCREATEQUERIESPROC dolCreateQueries;
PFNDOLGETQUERYBUFFEROBJECTI64VPROC dolGetQueryBufferObjecti64v;
PFNDOLGETQUERYBUFFEROBJECTIVPROC dolGetQueryBufferObjectiv;
PFNDOLGETQUERYBUFFEROBJECTUI64VPROC dolGetQueryBufferObjectui64v;
PFNDOLGETQUERYBUFFEROBJECTUIVPROC dolGetQueryBufferObjectuiv;
PFNDOLMEMORYBARRIERBYREGIONPROC dolMemoryBarrierByRegion;
PFNDOLGETTEXTURESUBIMAGEPROC dolGetTextureSubImage;
PFNDOLGETCOMPRESSEDTEXTURESUBIMAGEPROC dolGetCompressedTextureSubImage;
PFNDOLGETGRAPHICSRESETSTATUSPROC dolGetGraphicsResetStatus;
PFNDOLGETNCOMPRESSEDTEXIMAGEPROC dolGetnCompressedTexImage;
PFNDOLGETNTEXIMAGEPROC dolGetnTexImage;
PFNDOLGETNUNIFORMDVPROC dolGetnUniformdv;
PFNDOLGETNUNIFORMFVPROC dolGetnUniformfv;
PFNDOLGETNUNIFORMIVPROC dolGetnUniformiv;
PFNDOLGETNUNIFORMUIVPROC dolGetnUniformuiv;
PFNDOLREADNPIXELSPROC dolReadnPixels;
PFNDOLGETNMAPDVPROC dolGetnMapdv;
PFNDOLGETNMAPFVPROC dolGetnMapfv;
PFNDOLGETNMAPIVPROC dolGetnMapiv;
PFNDOLGETNPIXELMAPFVPROC dolGetnPixelMapfv;
PFNDOLGETNPIXELMAPUIVPROC dolGetnPixelMapuiv;
PFNDOLGETNPIXELMAPUSVPROC dolGetnPixelMapusv;
PFNDOLGETNPOLYGONSTIPPLEPROC dolGetnPolygonStipple;
PFNDOLGETNCOLORTABLEPROC dolGetnColorTable;
PFNDOLGETNCONVOLUTIONFILTERPROC dolGetnConvolutionFilter;
PFNDOLGETNSEPARABLEFILTERPROC dolGetnSeparableFilter;
PFNDOLGETNHISTOGRAMPROC dolGetnHistogram;
PFNDOLGETNMINMAXPROC dolGetnMinmax;
PFNDOLTEXTUREBARRIERPROC dolTextureBarrier;

// ARB_uniform_buffer_object
PFNDOLBINDBUFFERBASEPROC dolBindBufferBase;
PFNDOLBINDBUFFERRANGEPROC dolBindBufferRange;
PFNDOLGETACTIVEUNIFORMBLOCKNAMEPROC dolGetActiveUniformBlockName;
PFNDOLGETACTIVEUNIFORMBLOCKIVPROC dolGetActiveUniformBlockiv;
PFNDOLGETACTIVEUNIFORMNAMEPROC dolGetActiveUniformName;
PFNDOLGETACTIVEUNIFORMSIVPROC dolGetActiveUniformsiv;
PFNDOLGETINTEGERI_VPROC dolGetIntegeri_v;
PFNDOLGETUNIFORMBLOCKINDEXPROC dolGetUniformBlockIndex;
PFNDOLGETUNIFORMINDICESPROC dolGetUniformIndices;
PFNDOLUNIFORMBLOCKBINDINGPROC dolUniformBlockBinding;

// ARB_sampler_objects
PFNDOLBINDSAMPLERPROC dolBindSampler;
PFNDOLDELETESAMPLERSPROC dolDeleteSamplers;
PFNDOLGENSAMPLERSPROC dolGenSamplers;
PFNDOLGETSAMPLERPARAMETERIIVPROC dolGetSamplerParameterIiv;
PFNDOLGETSAMPLERPARAMETERIUIVPROC dolGetSamplerParameterIuiv;
PFNDOLGETSAMPLERPARAMETERFVPROC dolGetSamplerParameterfv;
PFNDOLGETSAMPLERPARAMETERIVPROC dolGetSamplerParameteriv;
PFNDOLISSAMPLERPROC dolIsSampler;
PFNDOLSAMPLERPARAMETERIIVPROC dolSamplerParameterIiv;
PFNDOLSAMPLERPARAMETERIUIVPROC dolSamplerParameterIuiv;
PFNDOLSAMPLERPARAMETERFPROC dolSamplerParameterf;
PFNDOLSAMPLERPARAMETERFVPROC dolSamplerParameterfv;
PFNDOLSAMPLERPARAMETERIPROC dolSamplerParameteri;
PFNDOLSAMPLERPARAMETERIVPROC dolSamplerParameteriv;

// ARB_map_buffer_range
PFNDOLFLUSHMAPPEDBUFFERRANGEPROC dolFlushMappedBufferRange;
PFNDOLMAPBUFFERRANGEPROC dolMapBufferRange;

// ARB_vertex_array_object
PFNDOLBINDVERTEXARRAYPROC dolBindVertexArray;
PFNDOLDELETEVERTEXARRAYSPROC dolDeleteVertexArrays;
PFNDOLGENVERTEXARRAYSPROC dolGenVertexArrays;
PFNDOLISVERTEXARRAYPROC dolIsVertexArray;

// ARB_framebuffer_object
PFNDOLBINDFRAMEBUFFERPROC dolBindFramebuffer;
PFNDOLBINDRENDERBUFFERPROC dolBindRenderbuffer;
PFNDOLBLITFRAMEBUFFERPROC dolBlitFramebuffer;
PFNDOLCHECKFRAMEBUFFERSTATUSPROC dolCheckFramebufferStatus;
PFNDOLDELETEFRAMEBUFFERSPROC dolDeleteFramebuffers;
PFNDOLDELETERENDERBUFFERSPROC dolDeleteRenderbuffers;
PFNDOLFRAMEBUFFERRENDERBUFFERPROC dolFramebufferRenderbuffer;
PFNDOLFRAMEBUFFERTEXTURE1DPROC dolFramebufferTexture1D;
PFNDOLFRAMEBUFFERTEXTURE2DPROC dolFramebufferTexture2D;
PFNDOLFRAMEBUFFERTEXTURE3DPROC dolFramebufferTexture3D;
PFNDOLFRAMEBUFFERTEXTURELAYERPROC dolFramebufferTextureLayer;
PFNDOLGENFRAMEBUFFERSPROC dolGenFramebuffers;
PFNDOLGENRENDERBUFFERSPROC dolGenRenderbuffers;
PFNDOLGENERATEMIPMAPPROC dolGenerateMipmap;
PFNDOLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC dolGetFramebufferAttachmentParameteriv;
PFNDOLGETRENDERBUFFERPARAMETERIVPROC dolGetRenderbufferParameteriv;
PFNDOLISFRAMEBUFFERPROC dolIsFramebuffer;
PFNDOLISRENDERBUFFERPROC dolIsRenderbuffer;
PFNDOLRENDERBUFFERSTORAGEPROC dolRenderbufferStorage;
PFNDOLRENDERBUFFERSTORAGEMULTISAMPLEPROC dolRenderbufferStorageMultisample;

// ARB_get_program_binary
PFNDOLGETPROGRAMBINARYPROC dolGetProgramBinary;
PFNDOLPROGRAMBINARYPROC dolProgramBinary;
PFNDOLPROGRAMPARAMETERIPROC dolProgramParameteri;

// ARB_sync
PFNDOLCLIENTWAITSYNCPROC dolClientWaitSync;
PFNDOLDELETESYNCPROC dolDeleteSync;
PFNDOLFENCESYNCPROC dolFenceSync;
PFNDOLGETINTEGER64VPROC dolGetInteger64v;
PFNDOLGETSYNCIVPROC dolGetSynciv;
PFNDOLISSYNCPROC dolIsSync;
PFNDOLWAITSYNCPROC dolWaitSync;

// ARB_texture_multisample
PFNDOLTEXIMAGE2DMULTISAMPLEPROC dolTexImage2DMultisample;
PFNDOLTEXIMAGE3DMULTISAMPLEPROC dolTexImage3DMultisample;
PFNDOLGETMULTISAMPLEFVPROC dolGetMultisamplefv;
PFNDOLSAMPLEMASKIPROC dolSampleMaski;

// ARB_texture_storage
PFNDOLTEXSTORAGE1DPROC dolTexStorage1D;
PFNDOLTEXSTORAGE2DPROC dolTexStorage2D;
PFNDOLTEXSTORAGE3DPROC dolTexStorage3D;

// ARB_texture_storage_multisample
PFNDOLTEXSTORAGE2DMULTISAMPLEPROC dolTexStorage2DMultisample;
PFNDOLTEXSTORAGE3DMULTISAMPLEPROC dolTexStorage3DMultisample;

// ARB_ES2_compatibility
PFNDOLCLEARDEPTHFPROC dolClearDepthf;
PFNDOLDEPTHRANGEFPROC dolDepthRangef;
PFNDOLGETSHADERPRECISIONFORMATPROC dolGetShaderPrecisionFormat;
PFNDOLRELEASESHADERCOMPILERPROC dolReleaseShaderCompiler;
PFNDOLSHADERBINARYPROC dolShaderBinary;

// NV_primitive_restart
PFNDOLPRIMITIVERESTARTINDEXNVPROC dolPrimitiveRestartIndexNV;
PFNDOLPRIMITIVERESTARTNVPROC dolPrimitiveRestartNV;

// ARB_blend_func_extended
PFNDOLBINDFRAGDATALOCATIONINDEXEDPROC dolBindFragDataLocationIndexed;
PFNDOLGETFRAGDATAINDEXPROC dolGetFragDataIndex;

// ARB_viewport_array
PFNDOLDEPTHRANGEARRAYVPROC dolDepthRangeArrayv;
PFNDOLDEPTHRANGEINDEXEDPROC dolDepthRangeIndexed;
PFNDOLGETDOUBLEI_VPROC dolGetDoublei_v;
PFNDOLGETFLOATI_VPROC dolGetFloati_v;
PFNDOLSCISSORARRAYVPROC dolScissorArrayv;
PFNDOLSCISSORINDEXEDPROC dolScissorIndexed;
PFNDOLSCISSORINDEXEDVPROC dolScissorIndexedv;
PFNDOLVIEWPORTARRAYVPROC dolViewportArrayv;
PFNDOLVIEWPORTINDEXEDFPROC dolViewportIndexedf;
PFNDOLVIEWPORTINDEXEDFVPROC dolViewportIndexedfv;

// ARB_draw_elements_base_vertex
PFNDOLDRAWELEMENTSBASEVERTEXPROC dolDrawElementsBaseVertex;
PFNDOLDRAWELEMENTSINSTANCEDBASEVERTEXPROC dolDrawElementsInstancedBaseVertex;
PFNDOLDRAWRANGEELEMENTSBASEVERTEXPROC dolDrawRangeElementsBaseVertex;
PFNDOLMULTIDRAWELEMENTSBASEVERTEXPROC dolMultiDrawElementsBaseVertex;

// ARB_sample_shading
PFNDOLMINSAMPLESHADINGARBPROC dolMinSampleShading;

// ARB_debug_output
PFNDOLDEBUGMESSAGECALLBACKARBPROC dolDebugMessageCallbackARB;
PFNDOLDEBUGMESSAGECONTROLARBPROC dolDebugMessageControlARB;
PFNDOLDEBUGMESSAGEINSERTARBPROC dolDebugMessageInsertARB;
PFNDOLGETDEBUGMESSAGELOGARBPROC dolGetDebugMessageLogARB;

// KHR_debug
PFNDOLDEBUGMESSAGECALLBACKPROC dolDebugMessageCallback;
PFNDOLDEBUGMESSAGECONTROLPROC dolDebugMessageControl;
PFNDOLDEBUGMESSAGEINSERTPROC dolDebugMessageInsert;
PFNDOLGETDEBUGMESSAGELOGPROC dolGetDebugMessageLog;
PFNDOLGETOBJECTLABELPROC dolGetObjectLabel;
PFNDOLGETOBJECTPTRLABELPROC dolGetObjectPtrLabel;
PFNDOLOBJECTLABELPROC dolObjectLabel;
PFNDOLOBJECTPTRLABELPROC dolObjectPtrLabel;
PFNDOLPOPDEBUGGROUPPROC dolPopDebugGroup;
PFNDOLPUSHDEBUGGROUPPROC dolPushDebugGroup;

// ARB_buffer_storage
PFNDOLBUFFERSTORAGEPROC dolBufferStorage;

// GL_NV_occlusion_query_samples
PFNDOLGENOCCLUSIONQUERIESNVPROC dolGenOcclusionQueriesNV;
PFNDOLDELETEOCCLUSIONQUERIESNVPROC dolDeleteOcclusionQueriesNV;
PFNDOLISOCCLUSIONQUERYNVPROC dolIsOcclusionQueryNV;
PFNDOLBEGINOCCLUSIONQUERYNVPROC dolBeginOcclusionQueryNV;
PFNDOLENDOCCLUSIONQUERYNVPROC dolEndOcclusionQueryNV;
PFNDOLGETOCCLUSIONQUERYIVNVPROC dolGetOcclusionQueryivNV;
PFNDOLGETOCCLUSIONQUERYUIVNVPROC dolGetOcclusionQueryuivNV;

// ARB_clip_control
PFNDOLCLIPCONTROLPROC dolClipControl;

// ARB_copy_image
PFNDOLCOPYIMAGESUBDATAPROC dolCopyImageSubData;

// ARB_shader_storage_buffer_object
PFNDOLSHADERSTORAGEBLOCKBINDINGPROC dolShaderStorageBlockBinding;

// NV_depth_buffer_float
PFNDOLDEPTHRANGEDNVPROC dolDepthRangedNV;
PFNDOLCLEARDEPTHDNVPROC dolClearDepthdNV;
PFNDOLDEPTHBOUNDSDNVPROC dolDepthBoundsdNV;

// ARB_shader_image_load_store
PFNDOLBINDIMAGETEXTUREPROC dolBindImageTexture;
PFNDOLMEMORYBARRIERPROC dolMemoryBarrier;

// ARB_compute_shader
PFNDOLDISPATCHCOMPUTEPROC dolDispatchCompute;
PFNDOLDISPATCHCOMPUTEINDIRECTPROC dolDispatchComputeIndirect;

// Creates a GLFunc object that requires a feature
#define GLFUNC_REQUIRES(x, y)                                                                      \
  {                                                                                                \
    (void**)&x, #x, y                                                                              \
  }
// Creates a GLFunc object with a different function suffix
// For when we want to use the same function pointer, but different function name
#define GLFUNC_SUFFIX(x, y, z)                                                                     \
  {                                                                                                \
    (void**)&x, #x #y, z                                                                           \
  }
// Creates a GLFunc object that should always be able to get grabbed
// Used for Desktop OpenGL functions that should /always/ be provided.
// aka GL 1.1/1.2/1.3/1.4
#define GLFUNC_ALWAYS_REQUIRED(x)                                                                  \
  {                                                                                                \
    (void**)&x, #x, "VERSION_GL"                                                                   \
  }
// Creates a GLFunc object that should be able to get grabbed
// on both GL and ES
#define GL_ES_FUNC_ALWAYS_REQUIRED(x)                                                              \
  {                                                                                                \
    (void**)&x, #x, "VERSION_GL |VERSION_GLES_2"                                                   \
  }
// Creates a GLFunc object that should be able to get grabbed
// on both GL and ES 3.0
#define GL_ES3_FUNC_ALWAYS_REQUIRED(x)                                                             \
  {                                                                                                \
    (void**)&x, #x, "VERSION_GL |VERSION_GLES_3"                                                   \
  }
// Creates a GLFunc object that should be able to get grabbed
// on both GL and ES 3.2
#define GL_ES32_FUNC_ALWAYS_REQUIRED(x)                                                            \
  {                                                                                                \
    (void**)&x, #x, "VERSION_GL |VERSION_GLES_3_2"                                                 \
  }

struct GLFunc
{
  void** function_ptr;
  const std::string function_name;
  const std::string requirements;
};

const GLFunc gl_function_array[] = {
    // gl_1_1
    GLFUNC_ALWAYS_REQUIRED(glClearIndex),
    GLFUNC_ALWAYS_REQUIRED(glIndexMask),
    GLFUNC_ALWAYS_REQUIRED(glAlphaFunc),
    GLFUNC_ALWAYS_REQUIRED(glLogicOp),
    GLFUNC_ALWAYS_REQUIRED(glPointSize),
    GLFUNC_ALWAYS_REQUIRED(glLineStipple),
    GLFUNC_ALWAYS_REQUIRED(glPolygonMode),
    GLFUNC_ALWAYS_REQUIRED(glPolygonStipple),
    GLFUNC_ALWAYS_REQUIRED(glGetPolygonStipple),
    GLFUNC_ALWAYS_REQUIRED(glEdgeFlag),
    GLFUNC_ALWAYS_REQUIRED(glEdgeFlagv),
    GLFUNC_ALWAYS_REQUIRED(glClipPlane),
    GLFUNC_ALWAYS_REQUIRED(glGetClipPlane),
    GLFUNC_ALWAYS_REQUIRED(glDrawBuffer),
    GLFUNC_ALWAYS_REQUIRED(glEnableClientState),
    GLFUNC_ALWAYS_REQUIRED(glDisableClientState),
    GLFUNC_ALWAYS_REQUIRED(glGetDoublev),
    GLFUNC_ALWAYS_REQUIRED(glPushAttrib),
    GLFUNC_ALWAYS_REQUIRED(glPopAttrib),
    GLFUNC_ALWAYS_REQUIRED(glPushClientAttrib),
    GLFUNC_ALWAYS_REQUIRED(glPopClientAttrib),
    GLFUNC_ALWAYS_REQUIRED(glRenderMode),
    GLFUNC_ALWAYS_REQUIRED(glClearDepth),
    GLFUNC_ALWAYS_REQUIRED(glDepthRange),
    GLFUNC_ALWAYS_REQUIRED(glClearAccum),
    GLFUNC_ALWAYS_REQUIRED(glAccum),
    GLFUNC_ALWAYS_REQUIRED(glMatrixMode),
    GLFUNC_ALWAYS_REQUIRED(glOrtho),
    GLFUNC_ALWAYS_REQUIRED(glFrustum),
    GLFUNC_ALWAYS_REQUIRED(glPushMatrix),
    GLFUNC_ALWAYS_REQUIRED(glPopMatrix),
    GLFUNC_ALWAYS_REQUIRED(glLoadIdentity),
    GLFUNC_ALWAYS_REQUIRED(glLoadMatrixd),
    GLFUNC_ALWAYS_REQUIRED(glLoadMatrixf),
    GLFUNC_ALWAYS_REQUIRED(glMultMatrixd),
    GLFUNC_ALWAYS_REQUIRED(glMultMatrixf),
    GLFUNC_ALWAYS_REQUIRED(glRotated),
    GLFUNC_ALWAYS_REQUIRED(glRotatef),
    GLFUNC_ALWAYS_REQUIRED(glScaled),
    GLFUNC_ALWAYS_REQUIRED(glScalef),
    GLFUNC_ALWAYS_REQUIRED(glTranslated),
    GLFUNC_ALWAYS_REQUIRED(glTranslatef),
    GLFUNC_ALWAYS_REQUIRED(glIsList),
    GLFUNC_ALWAYS_REQUIRED(glDeleteLists),
    GLFUNC_ALWAYS_REQUIRED(glGenLists),
    GLFUNC_ALWAYS_REQUIRED(glNewList),
    GLFUNC_ALWAYS_REQUIRED(glEndList),
    GLFUNC_ALWAYS_REQUIRED(glCallList),
    GLFUNC_ALWAYS_REQUIRED(glCallLists),
    GLFUNC_ALWAYS_REQUIRED(glListBase),
    GLFUNC_ALWAYS_REQUIRED(glBegin),
    GLFUNC_ALWAYS_REQUIRED(glEnd),
    GLFUNC_ALWAYS_REQUIRED(glVertex2d),
    GLFUNC_ALWAYS_REQUIRED(glVertex2f),
    GLFUNC_ALWAYS_REQUIRED(glVertex2i),
    GLFUNC_ALWAYS_REQUIRED(glVertex2s),
    GLFUNC_ALWAYS_REQUIRED(glVertex3d),
    GLFUNC_ALWAYS_REQUIRED(glVertex3f),
    GLFUNC_ALWAYS_REQUIRED(glVertex3i),
    GLFUNC_ALWAYS_REQUIRED(glVertex3s),
    GLFUNC_ALWAYS_REQUIRED(glVertex4d),
    GLFUNC_ALWAYS_REQUIRED(glVertex4f),
    GLFUNC_ALWAYS_REQUIRED(glVertex4i),
    GLFUNC_ALWAYS_REQUIRED(glVertex4s),
    GLFUNC_ALWAYS_REQUIRED(glVertex2dv),
    GLFUNC_ALWAYS_REQUIRED(glVertex2fv),
    GLFUNC_ALWAYS_REQUIRED(glVertex2iv),
    GLFUNC_ALWAYS_REQUIRED(glVertex2sv),
    GLFUNC_ALWAYS_REQUIRED(glVertex3dv),
    GLFUNC_ALWAYS_REQUIRED(glVertex3fv),
    GLFUNC_ALWAYS_REQUIRED(glVertex3iv),
    GLFUNC_ALWAYS_REQUIRED(glVertex3sv),
    GLFUNC_ALWAYS_REQUIRED(glVertex4dv),
    GLFUNC_ALWAYS_REQUIRED(glVertex4fv),
    GLFUNC_ALWAYS_REQUIRED(glVertex4iv),
    GLFUNC_ALWAYS_REQUIRED(glVertex4sv),
    GLFUNC_ALWAYS_REQUIRED(glNormal3b),
    GLFUNC_ALWAYS_REQUIRED(glNormal3d),
    GLFUNC_ALWAYS_REQUIRED(glNormal3f),
    GLFUNC_ALWAYS_REQUIRED(glNormal3i),
    GLFUNC_ALWAYS_REQUIRED(glNormal3s),
    GLFUNC_ALWAYS_REQUIRED(glNormal3bv),
    GLFUNC_ALWAYS_REQUIRED(glNormal3dv),
    GLFUNC_ALWAYS_REQUIRED(glNormal3fv),
    GLFUNC_ALWAYS_REQUIRED(glNormal3iv),
    GLFUNC_ALWAYS_REQUIRED(glNormal3sv),
    GLFUNC_ALWAYS_REQUIRED(glIndexd),
    GLFUNC_ALWAYS_REQUIRED(glIndexf),
    GLFUNC_ALWAYS_REQUIRED(glIndexi),
    GLFUNC_ALWAYS_REQUIRED(glIndexs),
    GLFUNC_ALWAYS_REQUIRED(glIndexub),
    GLFUNC_ALWAYS_REQUIRED(glIndexdv),
    GLFUNC_ALWAYS_REQUIRED(glIndexfv),
    GLFUNC_ALWAYS_REQUIRED(glIndexiv),
    GLFUNC_ALWAYS_REQUIRED(glIndexsv),
    GLFUNC_ALWAYS_REQUIRED(glIndexubv),
    GLFUNC_ALWAYS_REQUIRED(glColor3b),
    GLFUNC_ALWAYS_REQUIRED(glColor3d),
    GLFUNC_ALWAYS_REQUIRED(glColor3f),
    GLFUNC_ALWAYS_REQUIRED(glColor3i),
    GLFUNC_ALWAYS_REQUIRED(glColor3s),
    GLFUNC_ALWAYS_REQUIRED(glColor3ub),
    GLFUNC_ALWAYS_REQUIRED(glColor3ui),
    GLFUNC_ALWAYS_REQUIRED(glColor3us),
    GLFUNC_ALWAYS_REQUIRED(glColor4b),
    GLFUNC_ALWAYS_REQUIRED(glColor4d),
    GLFUNC_ALWAYS_REQUIRED(glColor4f),
    GLFUNC_ALWAYS_REQUIRED(glColor4i),
    GLFUNC_ALWAYS_REQUIRED(glColor4s),
    GLFUNC_ALWAYS_REQUIRED(glColor4ub),
    GLFUNC_ALWAYS_REQUIRED(glColor4ui),
    GLFUNC_ALWAYS_REQUIRED(glColor4us),
    GLFUNC_ALWAYS_REQUIRED(glColor3bv),
    GLFUNC_ALWAYS_REQUIRED(glColor3dv),
    GLFUNC_ALWAYS_REQUIRED(glColor3fv),
    GLFUNC_ALWAYS_REQUIRED(glColor3iv),
    GLFUNC_ALWAYS_REQUIRED(glColor3sv),
    GLFUNC_ALWAYS_REQUIRED(glColor3ubv),
    GLFUNC_ALWAYS_REQUIRED(glColor3uiv),
    GLFUNC_ALWAYS_REQUIRED(glColor3usv),
    GLFUNC_ALWAYS_REQUIRED(glColor4bv),
    GLFUNC_ALWAYS_REQUIRED(glColor4dv),
    GLFUNC_ALWAYS_REQUIRED(glColor4fv),
    GLFUNC_ALWAYS_REQUIRED(glColor4iv),
    GLFUNC_ALWAYS_REQUIRED(glColor4sv),
    GLFUNC_ALWAYS_REQUIRED(glColor4ubv),
    GLFUNC_ALWAYS_REQUIRED(glColor4uiv),
    GLFUNC_ALWAYS_REQUIRED(glColor4usv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1d),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1f),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1i),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1s),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2d),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2f),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2i),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2s),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3d),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3f),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3i),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3s),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4d),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4f),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4i),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4s),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1dv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1fv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1iv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord1sv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2dv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2fv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2iv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord2sv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3dv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3fv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3iv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord3sv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4dv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4fv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4iv),
    GLFUNC_ALWAYS_REQUIRED(glTexCoord4sv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2d),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2f),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2i),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2s),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3d),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3f),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3i),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3s),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4d),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4f),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4i),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4s),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2dv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2fv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2iv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos2sv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3dv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3fv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3iv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos3sv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4dv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4fv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4iv),
    GLFUNC_ALWAYS_REQUIRED(glRasterPos4sv),
    GLFUNC_ALWAYS_REQUIRED(glRectd),
    GLFUNC_ALWAYS_REQUIRED(glRectf),
    GLFUNC_ALWAYS_REQUIRED(glRecti),
    GLFUNC_ALWAYS_REQUIRED(glRects),
    GLFUNC_ALWAYS_REQUIRED(glRectdv),
    GLFUNC_ALWAYS_REQUIRED(glRectfv),
    GLFUNC_ALWAYS_REQUIRED(glRectiv),
    GLFUNC_ALWAYS_REQUIRED(glRectsv),
    GLFUNC_ALWAYS_REQUIRED(glVertexPointer),
    GLFUNC_ALWAYS_REQUIRED(glNormalPointer),
    GLFUNC_ALWAYS_REQUIRED(glColorPointer),
    GLFUNC_ALWAYS_REQUIRED(glIndexPointer),
    GLFUNC_ALWAYS_REQUIRED(glTexCoordPointer),
    GLFUNC_ALWAYS_REQUIRED(glEdgeFlagPointer),
    GLFUNC_ALWAYS_REQUIRED(glArrayElement),
    GLFUNC_ALWAYS_REQUIRED(glInterleavedArrays),
    GLFUNC_ALWAYS_REQUIRED(glShadeModel),
    GLFUNC_ALWAYS_REQUIRED(glLightf),
    GLFUNC_ALWAYS_REQUIRED(glLighti),
    GLFUNC_ALWAYS_REQUIRED(glLightfv),
    GLFUNC_ALWAYS_REQUIRED(glLightiv),
    GLFUNC_ALWAYS_REQUIRED(glGetLightfv),
    GLFUNC_ALWAYS_REQUIRED(glGetLightiv),
    GLFUNC_ALWAYS_REQUIRED(glLightModelf),
    GLFUNC_ALWAYS_REQUIRED(glLightModeli),
    GLFUNC_ALWAYS_REQUIRED(glLightModelfv),
    GLFUNC_ALWAYS_REQUIRED(glLightModeliv),
    GLFUNC_ALWAYS_REQUIRED(glMaterialf),
    GLFUNC_ALWAYS_REQUIRED(glMateriali),
    GLFUNC_ALWAYS_REQUIRED(glMaterialfv),
    GLFUNC_ALWAYS_REQUIRED(glMaterialiv),
    GLFUNC_ALWAYS_REQUIRED(glGetMaterialfv),
    GLFUNC_ALWAYS_REQUIRED(glGetMaterialiv),
    GLFUNC_ALWAYS_REQUIRED(glColorMaterial),
    GLFUNC_ALWAYS_REQUIRED(glPixelZoom),
    GLFUNC_ALWAYS_REQUIRED(glPixelStoref),
    GLFUNC_ALWAYS_REQUIRED(glPixelTransferf),
    GLFUNC_ALWAYS_REQUIRED(glPixelTransferi),
    GLFUNC_ALWAYS_REQUIRED(glPixelMapfv),
    GLFUNC_ALWAYS_REQUIRED(glPixelMapuiv),
    GLFUNC_ALWAYS_REQUIRED(glPixelMapusv),
    GLFUNC_ALWAYS_REQUIRED(glGetPixelMapfv),
    GLFUNC_ALWAYS_REQUIRED(glGetPixelMapuiv),
    GLFUNC_ALWAYS_REQUIRED(glGetPixelMapusv),
    GLFUNC_ALWAYS_REQUIRED(glBitmap),
    GLFUNC_ALWAYS_REQUIRED(glDrawPixels),
    GLFUNC_ALWAYS_REQUIRED(glCopyPixels),
    GLFUNC_ALWAYS_REQUIRED(glTexGend),
    GLFUNC_ALWAYS_REQUIRED(glTexGenf),
    GLFUNC_ALWAYS_REQUIRED(glTexGeni),
    GLFUNC_ALWAYS_REQUIRED(glTexGendv),
    GLFUNC_ALWAYS_REQUIRED(glTexGenfv),
    GLFUNC_ALWAYS_REQUIRED(glTexGeniv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexGendv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexGenfv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexGeniv),
    GLFUNC_ALWAYS_REQUIRED(glTexEnvf),
    GLFUNC_ALWAYS_REQUIRED(glTexEnvi),
    GLFUNC_ALWAYS_REQUIRED(glTexEnvfv),
    GLFUNC_ALWAYS_REQUIRED(glTexEnviv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexEnvfv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexEnviv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexLevelParameterfv),
    GLFUNC_ALWAYS_REQUIRED(glGetTexLevelParameteriv),
    GLFUNC_ALWAYS_REQUIRED(glTexImage1D),
    GLFUNC_ALWAYS_REQUIRED(glGetTexImage),
    GLFUNC_ALWAYS_REQUIRED(glPrioritizeTextures),
    GLFUNC_ALWAYS_REQUIRED(glAreTexturesResident),
    GLFUNC_ALWAYS_REQUIRED(glTexSubImage1D),
    GLFUNC_ALWAYS_REQUIRED(glCopyTexImage1D),
    GLFUNC_ALWAYS_REQUIRED(glCopyTexSubImage1D),
    GLFUNC_ALWAYS_REQUIRED(glMap1d),
    GLFUNC_ALWAYS_REQUIRED(glMap1f),
    GLFUNC_ALWAYS_REQUIRED(glMap2d),
    GLFUNC_ALWAYS_REQUIRED(glMap2f),
    GLFUNC_ALWAYS_REQUIRED(glGetMapdv),
    GLFUNC_ALWAYS_REQUIRED(glGetMapfv),
    GLFUNC_ALWAYS_REQUIRED(glGetMapiv),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord1d),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord1f),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord1dv),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord1fv),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord2d),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord2f),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord2dv),
    GLFUNC_ALWAYS_REQUIRED(glEvalCoord2fv),
    GLFUNC_ALWAYS_REQUIRED(glMapGrid1d),
    GLFUNC_ALWAYS_REQUIRED(glMapGrid1f),
    GLFUNC_ALWAYS_REQUIRED(glMapGrid2d),
    GLFUNC_ALWAYS_REQUIRED(glMapGrid2f),
    GLFUNC_ALWAYS_REQUIRED(glEvalPoint1),
    GLFUNC_ALWAYS_REQUIRED(glEvalPoint2),
    GLFUNC_ALWAYS_REQUIRED(glEvalMesh1),
    GLFUNC_ALWAYS_REQUIRED(glEvalMesh2),
    GLFUNC_ALWAYS_REQUIRED(glFogf),
    GLFUNC_ALWAYS_REQUIRED(glFogi),
    GLFUNC_ALWAYS_REQUIRED(glFogfv),
    GLFUNC_ALWAYS_REQUIRED(glFogiv),
    GLFUNC_ALWAYS_REQUIRED(glFeedbackBuffer),
    GLFUNC_ALWAYS_REQUIRED(glPassThrough),
    GLFUNC_ALWAYS_REQUIRED(glSelectBuffer),
    GLFUNC_ALWAYS_REQUIRED(glInitNames),
    GLFUNC_ALWAYS_REQUIRED(glLoadName),
    GLFUNC_ALWAYS_REQUIRED(glPushName),
    GLFUNC_ALWAYS_REQUIRED(glPopName),
    GL_ES_FUNC_ALWAYS_REQUIRED(glTexImage2D),
    GL_ES_FUNC_ALWAYS_REQUIRED(glClearColor),
    GL_ES_FUNC_ALWAYS_REQUIRED(glClear),
    GL_ES_FUNC_ALWAYS_REQUIRED(glColorMask),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBlendFunc),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCullFace),
    GL_ES_FUNC_ALWAYS_REQUIRED(glFrontFace),
    GL_ES_FUNC_ALWAYS_REQUIRED(glLineWidth),
    GL_ES_FUNC_ALWAYS_REQUIRED(glPolygonOffset),
    GL_ES_FUNC_ALWAYS_REQUIRED(glScissor),
    GL_ES_FUNC_ALWAYS_REQUIRED(glEnable),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDisable),
    GL_ES_FUNC_ALWAYS_REQUIRED(glIsEnabled),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetBooleanv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetFloatv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glFinish),
    GL_ES_FUNC_ALWAYS_REQUIRED(glFlush),
    GL_ES_FUNC_ALWAYS_REQUIRED(glHint),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDepthFunc),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDepthMask),
    GL_ES_FUNC_ALWAYS_REQUIRED(glViewport),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDrawArrays),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDrawElements),
    GL_ES_FUNC_ALWAYS_REQUIRED(glPixelStorei),
    GL_ES_FUNC_ALWAYS_REQUIRED(glReadPixels),
    GL_ES_FUNC_ALWAYS_REQUIRED(glStencilFunc),
    GL_ES_FUNC_ALWAYS_REQUIRED(glStencilMask),
    GL_ES_FUNC_ALWAYS_REQUIRED(glStencilOp),
    GL_ES_FUNC_ALWAYS_REQUIRED(glClearStencil),
    GL_ES_FUNC_ALWAYS_REQUIRED(glTexParameterf),
    GL_ES_FUNC_ALWAYS_REQUIRED(glTexParameteri),
    GL_ES_FUNC_ALWAYS_REQUIRED(glTexParameterfv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glTexParameteriv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetTexParameterfv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetTexParameteriv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGenTextures),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDeleteTextures),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBindTexture),
    GL_ES_FUNC_ALWAYS_REQUIRED(glIsTexture),
    GL_ES_FUNC_ALWAYS_REQUIRED(glTexSubImage2D),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCopyTexImage2D),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCopyTexSubImage2D),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glReadBuffer),
    GL_ES32_FUNC_ALWAYS_REQUIRED(glGetPointerv),

    // gl_1_2
    GL_ES3_FUNC_ALWAYS_REQUIRED(glCopyTexSubImage3D),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glDrawRangeElements),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glTexImage3D),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glTexSubImage3D),

    // gl_1_3
    GLFUNC_ALWAYS_REQUIRED(glClientActiveTexture),
    GLFUNC_ALWAYS_REQUIRED(glCompressedTexImage1D),
    GLFUNC_ALWAYS_REQUIRED(glCompressedTexSubImage1D),
    GLFUNC_ALWAYS_REQUIRED(glGetCompressedTexImage),
    GLFUNC_ALWAYS_REQUIRED(glLoadTransposeMatrixd),
    GLFUNC_ALWAYS_REQUIRED(glLoadTransposeMatrixf),
    GLFUNC_ALWAYS_REQUIRED(glMultTransposeMatrixd),
    GLFUNC_ALWAYS_REQUIRED(glMultTransposeMatrixf),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1d),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1dv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1f),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1fv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1i),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1iv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1s),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord1sv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2d),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2dv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2f),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2fv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2i),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2iv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2s),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord2sv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3d),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3dv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3f),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3fv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3i),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3iv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3s),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord3sv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4d),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4dv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4f),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4fv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4i),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4iv),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4s),
    GLFUNC_ALWAYS_REQUIRED(glMultiTexCoord4sv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glSampleCoverage),
    GL_ES_FUNC_ALWAYS_REQUIRED(glActiveTexture),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCompressedTexImage2D),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCompressedTexSubImage2D),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glCompressedTexImage3D),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glCompressedTexSubImage3D),

    // gl_1_4
    GLFUNC_ALWAYS_REQUIRED(glFogCoordPointer),
    GLFUNC_ALWAYS_REQUIRED(glFogCoordd),
    GLFUNC_ALWAYS_REQUIRED(glFogCoorddv),
    GLFUNC_ALWAYS_REQUIRED(glFogCoordf),
    GLFUNC_ALWAYS_REQUIRED(glFogCoordfv),
    GLFUNC_ALWAYS_REQUIRED(glMultiDrawArrays),
    GLFUNC_ALWAYS_REQUIRED(glMultiDrawElements),
    GLFUNC_ALWAYS_REQUIRED(glPointParameterf),
    GLFUNC_ALWAYS_REQUIRED(glPointParameterfv),
    GLFUNC_ALWAYS_REQUIRED(glPointParameteri),
    GLFUNC_ALWAYS_REQUIRED(glPointParameteriv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3b),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3bv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3d),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3dv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3f),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3fv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3i),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3iv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3s),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3sv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3ub),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3ubv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3ui),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3uiv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3us),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColor3usv),
    GLFUNC_ALWAYS_REQUIRED(glSecondaryColorPointer),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2d),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2dv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2f),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2fv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2i),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2iv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2s),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos2sv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3d),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3dv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3f),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3fv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3i),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3iv),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3s),
    GLFUNC_ALWAYS_REQUIRED(glWindowPos3sv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBlendColor),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBlendEquation),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBlendFuncSeparate),

    // gl_1_5
    GLFUNC_ALWAYS_REQUIRED(glGetBufferSubData),
    GLFUNC_ALWAYS_REQUIRED(glGetQueryObjectiv),
    GLFUNC_ALWAYS_REQUIRED(glMapBuffer),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBindBuffer),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBufferData),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBufferSubData),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDeleteBuffers),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGenBuffers),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetBufferParameteriv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glIsBuffer),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glBeginQuery),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glDeleteQueries),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glEndQuery),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glGenQueries),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glIsQuery),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glGetQueryiv),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glGetQueryObjectuiv),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glGetBufferPointerv),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glUnmapBuffer),

    // gl_2_0
    GLFUNC_ALWAYS_REQUIRED(glGetVertexAttribdv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib1d),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib1dv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib1s),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib1sv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib2d),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib2dv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib2s),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib2sv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib3d),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib3dv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib3s),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib3sv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Nbv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Niv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Nsv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Nub),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Nubv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Nuiv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4Nusv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4bv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4d),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4dv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4iv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4s),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4sv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4ubv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4uiv),
    GLFUNC_ALWAYS_REQUIRED(glVertexAttrib4usv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glAttachShader),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBindAttribLocation),
    GL_ES_FUNC_ALWAYS_REQUIRED(glBlendEquationSeparate),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCompileShader),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCreateProgram),
    GL_ES_FUNC_ALWAYS_REQUIRED(glCreateShader),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDeleteProgram),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDeleteShader),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDetachShader),
    GL_ES_FUNC_ALWAYS_REQUIRED(glDisableVertexAttribArray),
    GL_ES_FUNC_ALWAYS_REQUIRED(glEnableVertexAttribArray),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetActiveAttrib),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetActiveUniform),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetAttachedShaders),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetAttribLocation),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetProgramInfoLog),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetProgramiv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetShaderInfoLog),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetShaderSource),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetShaderiv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetUniformLocation),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetUniformfv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetUniformiv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetVertexAttribPointerv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetVertexAttribfv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glGetVertexAttribiv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glIsProgram),
    GL_ES_FUNC_ALWAYS_REQUIRED(glIsShader),
    GL_ES_FUNC_ALWAYS_REQUIRED(glLinkProgram),
    GL_ES_FUNC_ALWAYS_REQUIRED(glShaderSource),
    GL_ES_FUNC_ALWAYS_REQUIRED(glStencilFuncSeparate),
    GL_ES_FUNC_ALWAYS_REQUIRED(glStencilMaskSeparate),
    GL_ES_FUNC_ALWAYS_REQUIRED(glStencilOpSeparate),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform1f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform1fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform1i),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform1iv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform2f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform2fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform2i),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform2iv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform3f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform3fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform3i),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform3iv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform4f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform4fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform4i),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniform4iv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniformMatrix2fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniformMatrix3fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUniformMatrix4fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glUseProgram),
    GL_ES_FUNC_ALWAYS_REQUIRED(glValidateProgram),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib1f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib1fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib2f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib2fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib3f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib3fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib4f),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttrib4fv),
    GL_ES_FUNC_ALWAYS_REQUIRED(glVertexAttribPointer),
    GL_ES3_FUNC_ALWAYS_REQUIRED(glDrawBuffers),

    // gl_2_1
    GLFUNC_ALWAYS_REQUIRED(glUniformMatrix2x3fv),
    GLFUNC_ALWAYS_REQUIRED(glUniformMatrix2x4fv),
    GLFUNC_ALWAYS_REQUIRED(glUniformMatrix3x2fv),
    GLFUNC_ALWAYS_REQUIRED(glUniformMatrix3x4fv),
    GLFUNC_ALWAYS_REQUIRED(glUniformMatrix4x2fv),
    GLFUNC_ALWAYS_REQUIRED(glUniformMatrix4x3fv),

    // gl_3_0
    GLFUNC_REQUIRES(glBeginConditionalRender, "VERSION_3_0"),
    GLFUNC_REQUIRES(glBindFragDataLocation, "VERSION_3_0"),
    GLFUNC_REQUIRES(glClampColor, "VERSION_3_0"),
    GLFUNC_REQUIRES(glEndConditionalRender, "VERSION_3_0"),
    GLFUNC_REQUIRES(glGetBooleani_v, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI1i, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI1iv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI1ui, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI1uiv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI2i, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI2iv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI2ui, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI2uiv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI3i, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI3iv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI3ui, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI3uiv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI4bv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI4sv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI4ubv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glVertexAttribI4usv, "VERSION_3_0"),
    GLFUNC_REQUIRES(glBeginTransformFeedback, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glClearBufferfi, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glClearBufferfv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glClearBufferiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glClearBufferuiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glEndTransformFeedback, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetFragDataLocation, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetStringi, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetTransformFeedbackVarying, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetUniformuiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetVertexAttribIiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetVertexAttribIuiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glTransformFeedbackVaryings, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform1ui, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform1uiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform2ui, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform2uiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform3ui, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform3uiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform4ui, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniform4uiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glVertexAttribI4i, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glVertexAttribI4iv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glVertexAttribI4ui, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glVertexAttribI4uiv, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glVertexAttribIPointer, "VERSION_3_0 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glColorMaski, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glDisablei, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glEnablei, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glGetTexParameterIiv, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glGetTexParameterIuiv, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glIsEnabledi, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glTexParameterIiv, "VERSION_3_0 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glTexParameterIuiv, "VERSION_3_0 |VERSION_GLES_3_2"),

    // gl_3_1
    GLFUNC_REQUIRES(glPrimitiveRestartIndex, "VERSION_3_1"),
    GLFUNC_REQUIRES(glDrawArraysInstanced, "VERSION_3_1 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glDrawElementsInstanced, "VERSION_3_1 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glTexBuffer, "VERSION_3_1 |VERSION_GLES_3_2"),

    // gl_3_2
    GLFUNC_REQUIRES(glGetBufferParameteri64v, "VERSION_3_2 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetInteger64i_v, "VERSION_3_2 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glFramebufferTexture, "VERSION_3_2 |VERSION_GLES_3_2"),

    // gl_4_2
    GLFUNC_REQUIRES(glDrawArraysInstancedBaseInstance, "VERSION_4_2"),
    GLFUNC_REQUIRES(glDrawElementsInstancedBaseInstance, "VERSION_4_2"),
    GLFUNC_REQUIRES(glDrawElementsInstancedBaseVertexBaseInstance, "VERSION_4_2"),
    GLFUNC_REQUIRES(glGetInternalformativ, "VERSION_4_2"),
    GLFUNC_REQUIRES(glGetActiveAtomicCounterBufferiv, "VERSION_4_2"),
    GLFUNC_REQUIRES(glBindImageTexture, "VERSION_4_2"),
    GLFUNC_REQUIRES(glMemoryBarrier, "VERSION_4_2"),
    GLFUNC_REQUIRES(glTexStorage1D, "VERSION_4_2"),
    GLFUNC_REQUIRES(glTexStorage2D, "VERSION_4_2"),
    GLFUNC_REQUIRES(glTexStorage3D, "VERSION_4_2"),
    GLFUNC_REQUIRES(glDrawTransformFeedbackInstanced, "VERSION_4_2"),
    GLFUNC_REQUIRES(glDrawTransformFeedbackStreamInstanced, "VERSION_4_2"),

    // gl_4_3
    GLFUNC_REQUIRES(glClearBufferData, "VERSION_4_3"),
    GLFUNC_REQUIRES(glClearBufferSubData, "VERSION_4_3"),
    GLFUNC_REQUIRES(glDispatchCompute, "VERSION_4_3"),
    GLFUNC_REQUIRES(glDispatchComputeIndirect, "VERSION_4_3"),
    GLFUNC_REQUIRES(glCopyImageSubData, "VERSION_4_3"),
    GLFUNC_REQUIRES(glFramebufferParameteri, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetFramebufferParameteriv, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetInternalformati64v, "VERSION_4_3"),
    GLFUNC_REQUIRES(glInvalidateTexSubImage, "VERSION_4_3"),
    GLFUNC_REQUIRES(glInvalidateTexImage, "VERSION_4_3"),
    GLFUNC_REQUIRES(glInvalidateBufferSubData, "VERSION_4_3"),
    GLFUNC_REQUIRES(glInvalidateBufferData, "VERSION_4_3"),
    GLFUNC_REQUIRES(glInvalidateFramebuffer, "VERSION_4_3"),
    GLFUNC_REQUIRES(glInvalidateSubFramebuffer, "VERSION_4_3"),
    GLFUNC_REQUIRES(glMultiDrawArraysIndirect, "VERSION_4_3"),
    GLFUNC_REQUIRES(glMultiDrawElementsIndirect, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetProgramInterfaceiv, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetProgramResourceIndex, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetProgramResourceName, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetProgramResourceiv, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetProgramResourceLocation, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetProgramResourceLocationIndex, "VERSION_4_3"),
    GLFUNC_REQUIRES(glShaderStorageBlockBinding, "VERSION_4_3"),
    GLFUNC_REQUIRES(glTexBufferRange, "VERSION_4_3"),
    GLFUNC_REQUIRES(glTexStorage2DMultisample, "VERSION_4_3"),
    GLFUNC_REQUIRES(glTexStorage3DMultisample, "VERSION_4_3"),
    GLFUNC_REQUIRES(glTextureView, "VERSION_4_3"),
    GLFUNC_REQUIRES(glBindVertexBuffer, "VERSION_4_3"),
    GLFUNC_REQUIRES(glVertexAttribFormat, "VERSION_4_3"),
    GLFUNC_REQUIRES(glVertexAttribIFormat, "VERSION_4_3"),
    GLFUNC_REQUIRES(glVertexAttribLFormat, "VERSION_4_3"),
    GLFUNC_REQUIRES(glVertexAttribBinding, "VERSION_4_3"),
    GLFUNC_REQUIRES(glVertexBindingDivisor, "VERSION_4_3"),
    GLFUNC_REQUIRES(glDebugMessageControl, "VERSION_4_3"),
    GLFUNC_REQUIRES(glDebugMessageInsert, "VERSION_4_3"),
    GLFUNC_REQUIRES(glDebugMessageCallback, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetDebugMessageLog, "VERSION_4_3"),
    GLFUNC_REQUIRES(glPushDebugGroup, "VERSION_4_3"),
    GLFUNC_REQUIRES(glPopDebugGroup, "VERSION_4_3"),
    GLFUNC_REQUIRES(glObjectLabel, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetObjectLabel, "VERSION_4_3"),
    GLFUNC_REQUIRES(glObjectPtrLabel, "VERSION_4_3"),
    GLFUNC_REQUIRES(glGetObjectPtrLabel, "VERSION_4_3"),

    // gl_4_4
    GLFUNC_REQUIRES(glBufferStorage, "VERSION_4_4"),
    GLFUNC_REQUIRES(glClearTexImage, "VERSION_4_4"),
    GLFUNC_REQUIRES(glClearTexSubImage, "VERSION_4_4"),
    GLFUNC_REQUIRES(glBindBuffersBase, "VERSION_4_4"),
    GLFUNC_REQUIRES(glBindBuffersRange, "VERSION_4_4"),
    GLFUNC_REQUIRES(glBindTextures, "VERSION_4_4"),
    GLFUNC_REQUIRES(glBindSamplers, "VERSION_4_4"),
    GLFUNC_REQUIRES(glBindImageTextures, "VERSION_4_4"),
    GLFUNC_REQUIRES(glBindVertexBuffers, "VERSION_4_4"),

    // gl_4_5
    GLFUNC_REQUIRES(glClipControl, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateTransformFeedbacks, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTransformFeedbackBufferBase, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTransformFeedbackBufferRange, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTransformFeedbackiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTransformFeedbacki_v, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTransformFeedbacki64_v, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateBuffers, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedBufferStorage, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedBufferData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedBufferSubData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCopyNamedBufferSubData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glClearNamedBufferData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glClearNamedBufferSubData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glMapNamedBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glMapNamedBufferRange, "VERSION_4_5"),
    GLFUNC_REQUIRES(glUnmapNamedBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glFlushMappedNamedBufferRange, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedBufferParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedBufferParameteri64v, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedBufferPointerv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedBufferSubData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateFramebuffers, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferRenderbuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferParameteri, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferTexture, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferTextureLayer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferDrawBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferDrawBuffers, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedFramebufferReadBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glInvalidateNamedFramebufferData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glInvalidateNamedFramebufferSubData, "VERSION_4_5"),
    GLFUNC_REQUIRES(glClearNamedFramebufferiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glClearNamedFramebufferuiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glClearNamedFramebufferfv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glClearNamedFramebufferfi, "VERSION_4_5"),
    GLFUNC_REQUIRES(glBlitNamedFramebuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCheckNamedFramebufferStatus, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedFramebufferParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedFramebufferAttachmentParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateRenderbuffers, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedRenderbufferStorage, "VERSION_4_5"),
    GLFUNC_REQUIRES(glNamedRenderbufferStorageMultisample, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetNamedRenderbufferParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateTextures, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureBufferRange, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureStorage1D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureStorage2D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureStorage3D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureStorage2DMultisample, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureStorage3DMultisample, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureSubImage1D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureSubImage2D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureSubImage3D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCompressedTextureSubImage1D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCompressedTextureSubImage2D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCompressedTextureSubImage3D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCopyTextureSubImage1D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCopyTextureSubImage2D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCopyTextureSubImage3D, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureParameterf, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureParameterfv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureParameteri, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureParameterIiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureParameterIuiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGenerateTextureMipmap, "VERSION_4_5"),
    GLFUNC_REQUIRES(glBindTextureUnit, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureImage, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetCompressedTextureImage, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureLevelParameterfv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureLevelParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureParameterfv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureParameterIiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureParameterIuiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureParameteriv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateVertexArrays, "VERSION_4_5"),
    GLFUNC_REQUIRES(glDisableVertexArrayAttrib, "VERSION_4_5"),
    GLFUNC_REQUIRES(glEnableVertexArrayAttrib, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayElementBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayVertexBuffer, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayVertexBuffers, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayAttribBinding, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayAttribFormat, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayAttribIFormat, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayAttribLFormat, "VERSION_4_5"),
    GLFUNC_REQUIRES(glVertexArrayBindingDivisor, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetVertexArrayiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetVertexArrayIndexediv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetVertexArrayIndexed64iv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateSamplers, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateProgramPipelines, "VERSION_4_5"),
    GLFUNC_REQUIRES(glCreateQueries, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetQueryBufferObjecti64v, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetQueryBufferObjectiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetQueryBufferObjectui64v, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetQueryBufferObjectuiv, "VERSION_4_5"),
    GLFUNC_REQUIRES(glMemoryBarrierByRegion, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetTextureSubImage, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetCompressedTextureSubImage, "VERSION_4_5"),
    GLFUNC_REQUIRES(glGetGraphicsResetStatus, "VERSION_4_5"),
    GLFUNC_REQUIRES(glReadnPixels, "VERSION_4_5"),
    GLFUNC_REQUIRES(glTextureBarrier, "VERSION_4_5"),
    // AMD's video driver is trash and doesn't expose these function pointers
    // Remove them for now until they learn how to implement the spec properly.
    // GLFUNC_REQUIRES(glGetnCompressedTexImage,                   "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnTexImage,                             "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnUniformdv,                            "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnUniformfv,                            "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnUniformiv,                            "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnUniformuiv,                           "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnMapdv,                                "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnMapfv,                                "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnMapiv,                                "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnPixelMapfv,                           "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnPixelMapuiv,                          "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnPixelMapusv,                          "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnPolygonStipple,                       "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnColorTable,                           "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnConvolutionFilter,                    "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnSeparableFilter,                      "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnHistogram,                            "VERSION_4_5"),
    // GLFUNC_REQUIRES(glGetnMinmax,                               "VERSION_4_5"),

    // ARB_uniform_buffer_object
    GLFUNC_REQUIRES(glGetActiveUniformName, "GL_ARB_uniform_buffer_object"),
    GLFUNC_REQUIRES(glBindBufferBase, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glBindBufferRange, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetActiveUniformBlockName, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetActiveUniformBlockiv, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetActiveUniformsiv, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetIntegeri_v, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetUniformBlockIndex, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetUniformIndices, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glUniformBlockBinding, "GL_ARB_uniform_buffer_object |VERSION_GLES_3"),

    // ARB_sampler_objects
    GLFUNC_REQUIRES(glBindSampler, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glDeleteSamplers, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGenSamplers, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetSamplerParameterfv, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetSamplerParameteriv, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glIsSampler, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glSamplerParameterf, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glSamplerParameterfv, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glSamplerParameteri, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glSamplerParameteriv, "GL_ARB_sampler_objects |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetSamplerParameterIiv, "GL_ARB_sampler_objects |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glGetSamplerParameterIuiv, "GL_ARB_sampler_objects |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glSamplerParameterIiv, "GL_ARB_sampler_objects |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glSamplerParameterIuiv, "GL_ARB_sampler_objects |VERSION_GLES_3_2"),

    // ARB_map_buffer_range
    GLFUNC_REQUIRES(glFlushMappedBufferRange, "GL_ARB_map_buffer_range |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glMapBufferRange, "GL_ARB_map_buffer_range |VERSION_GLES_3"),

    // ARB_vertex_array_object
    GLFUNC_REQUIRES(glBindVertexArray, "GL_ARB_vertex_array_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glDeleteVertexArrays, "GL_ARB_vertex_array_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGenVertexArrays, "GL_ARB_vertex_array_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glIsVertexArray, "GL_ARB_vertex_array_object |VERSION_GLES_3"),

    // APPLE_vertex_array_object
    GLFUNC_SUFFIX(glBindVertexArray, APPLE,
                  "GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
    GLFUNC_SUFFIX(glDeleteVertexArrays, APPLE,
                  "GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
    GLFUNC_SUFFIX(glGenVertexArrays, APPLE,
                  "GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
    GLFUNC_SUFFIX(glIsVertexArray, APPLE,
                  "GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),

    // ARB_framebuffer_object
    GLFUNC_REQUIRES(glFramebufferTexture1D, "GL_ARB_framebuffer_object"),
    GLFUNC_REQUIRES(glFramebufferTexture3D, "GL_ARB_framebuffer_object"),
    GLFUNC_REQUIRES(glBindFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glBindRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glBlitFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glCheckFramebufferStatus, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glDeleteFramebuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glDeleteRenderbuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glFramebufferRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glFramebufferTexture2D, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glFramebufferTextureLayer, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGenFramebuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glGenRenderbuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glGenerateMipmap, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glGetFramebufferAttachmentParameteriv,
                    "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glGetRenderbufferParameteriv, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glIsFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glIsRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glRenderbufferStorage, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glRenderbufferStorageMultisample, "GL_ARB_framebuffer_object |VERSION_GLES_3"),

    // ARB_get_program_binary
    GLFUNC_REQUIRES(glGetProgramBinary, "GL_ARB_get_program_binary |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glProgramBinary, "GL_ARB_get_program_binary |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glProgramParameteri, "GL_ARB_get_program_binary |VERSION_GLES_3"),

    // ARB_sync
    GLFUNC_REQUIRES(glClientWaitSync, "GL_ARB_sync |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glDeleteSync, "GL_ARB_sync |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glFenceSync, "GL_ARB_sync |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetInteger64v, "GL_ARB_sync |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glGetSynciv, "GL_ARB_sync |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glIsSync, "GL_ARB_sync |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glWaitSync, "GL_ARB_sync |VERSION_GLES_3"),

    // ARB_texture_multisample
    GLFUNC_REQUIRES(glTexImage2DMultisample, "GL_ARB_texture_multisample"),
    GLFUNC_REQUIRES(glTexImage3DMultisample, "GL_ARB_texture_multisample"),
    GLFUNC_REQUIRES(glGetMultisamplefv, "GL_ARB_texture_multisample"),
    GLFUNC_REQUIRES(glSampleMaski, "GL_ARB_texture_multisample"),

    // ARB_texture_storage
    GLFUNC_REQUIRES(glTexStorage1D, "GL_ARB_texture_storage !VERSION_4_2"),
    GLFUNC_REQUIRES(glTexStorage2D, "GL_ARB_texture_storage !VERSION_4_2 |VERSION_GLES_3"),
    GLFUNC_REQUIRES(glTexStorage3D, "GL_ARB_texture_storage !VERSION_4_2 |VERSION_GLES_3"),

    // ARB_texture_storage_multisample
    GLFUNC_REQUIRES(glTexStorage2DMultisample,
                    "GL_ARB_texture_storage_multisample !VERSION_4_3 |VERSION_GLES_3_1"),
    GLFUNC_REQUIRES(glTexStorage3DMultisample,
                    "GL_ARB_texture_storage_multisample !VERSION_4_3 |VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glTexStorage3DMultisample, OES,
                  "GL_OES_texture_storage_multisample_2d_array !VERSION_GLES_3_2"),

    // ARB_ES2_compatibility
    GLFUNC_REQUIRES(glClearDepthf, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glDepthRangef, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glGetShaderPrecisionFormat, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glReleaseShaderCompiler, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
    GLFUNC_REQUIRES(glShaderBinary, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),

    // NV_primitive_restart
    GLFUNC_REQUIRES(glPrimitiveRestartIndexNV, "GL_NV_primitive_restart"),
    GLFUNC_REQUIRES(glPrimitiveRestartNV, "GL_NV_primitive_restart"),

    // ARB_blend_func_extended
    GLFUNC_REQUIRES(glBindFragDataLocationIndexed, "GL_ARB_blend_func_extended"),
    GLFUNC_REQUIRES(glGetFragDataIndex, "GL_ARB_blend_func_extended"),

    // ARB_viewport_array
    GLFUNC_REQUIRES(glDepthRangeArrayv, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glDepthRangeIndexed, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glGetDoublei_v, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glGetFloati_v, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glScissorArrayv, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glScissorIndexed, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glScissorIndexedv, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glViewportArrayv, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glViewportIndexedf, "GL_ARB_viewport_array"),
    GLFUNC_REQUIRES(glViewportIndexedfv, "GL_ARB_viewport_array"),

    // ARB_draw_elements_base_vertex
    GLFUNC_REQUIRES(glDrawElementsBaseVertex, "GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glDrawElementsInstancedBaseVertex,
                    "GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glDrawRangeElementsBaseVertex,
                    "GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glMultiDrawElementsBaseVertex, "GL_ARB_draw_elements_base_vertex"),

    // OES_draw_elements_base_vertex
    GLFUNC_SUFFIX(glDrawElementsBaseVertex, OES,
                  "GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glDrawElementsInstancedBaseVertex, OES,
                  "GL_OES_draw_elements_base_vertex VERSION_GLES_3 !VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glDrawRangeElementsBaseVertex, OES,
                  "GL_OES_draw_elements_base_vertex VERSION_GLES_3 !VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glMultiDrawElementsBaseVertex, EXT,
                  "GL_OES_draw_elements_base_vertex GL_EXT_multi_draw_arrays"),

    // EXT_draw_elements_base_vertex
    GLFUNC_SUFFIX(
        glDrawElementsBaseVertex, EXT,
        "GL_EXT_draw_elements_base_vertex !GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glDrawElementsInstancedBaseVertex, EXT,
                  "GL_EXT_draw_elements_base_vertex VERSION_GLES_3 "
                  "!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glDrawRangeElementsBaseVertex, EXT,
                  "GL_EXT_draw_elements_base_vertex VERSION_GLES_3 "
                  "!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
    GLFUNC_SUFFIX(glMultiDrawElementsBaseVertex, EXT,
                  "GL_EXT_draw_elements_base_vertex GL_EXT_multi_draw_arrays "
                  "!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),

    // ARB_sample_shading
    GLFUNC_SUFFIX(glMinSampleShading, ARB, "GL_ARB_sample_shading"),

    // OES_sample_shading
    GLFUNC_SUFFIX(glMinSampleShading, OES, "GL_OES_sample_shading !VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glMinSampleShading, "VERSION_GLES_3_2"),

    // ARB_debug_output
    GLFUNC_REQUIRES(glDebugMessageCallbackARB, "GL_ARB_debug_output"),
    GLFUNC_REQUIRES(glDebugMessageControlARB, "GL_ARB_debug_output"),
    GLFUNC_REQUIRES(glDebugMessageInsertARB, "GL_ARB_debug_output"),
    GLFUNC_REQUIRES(glGetDebugMessageLogARB, "GL_ARB_debug_output"),

    // KHR_debug
    GLFUNC_SUFFIX(glDebugMessageCallback, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glDebugMessageControl, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glDebugMessageInsert, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glGetDebugMessageLog, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glGetObjectLabel, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glGetObjectPtrLabel, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glObjectLabel, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glObjectPtrLabel, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glPopDebugGroup, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_SUFFIX(glPushDebugGroup, KHR, "GL_KHR_debug VERSION_GLES_3"),
    GLFUNC_REQUIRES(glDebugMessageCallback,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glDebugMessageControl,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glDebugMessageInsert,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glGetDebugMessageLog,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glGetObjectLabel,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glGetObjectPtrLabel,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glObjectLabel,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glObjectPtrLabel,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glPopDebugGroup,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
    GLFUNC_REQUIRES(glPushDebugGroup,
                    "GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),

    // ARB_buffer_storage
    GLFUNC_REQUIRES(glBufferStorage, "GL_ARB_buffer_storage !VERSION_4_4"),
    GLFUNC_SUFFIX(glNamedBufferStorage, EXT,
                  "GL_ARB_buffer_storage GL_EXT_direct_state_access !VERSION_4_5"),

    // EXT_buffer_storage
    GLFUNC_SUFFIX(glBufferStorage, EXT,
                  "GL_EXT_buffer_storage !GL_ARB_buffer_storage !VERSION_4_4"),

    // EXT_geometry_shader
    GLFUNC_SUFFIX(glFramebufferTexture, EXT, "GL_EXT_geometry_shader !VERSION_3_2"),

    // NV_occlusion_query_samples
    GLFUNC_REQUIRES(glGenOcclusionQueriesNV, "GL_NV_occlusion_query_samples"),
    GLFUNC_REQUIRES(glDeleteOcclusionQueriesNV, "GL_NV_occlusion_query_samples"),
    GLFUNC_REQUIRES(glIsOcclusionQueryNV, "GL_NV_occlusion_query_samples"),
    GLFUNC_REQUIRES(glBeginOcclusionQueryNV, "GL_NV_occlusion_query_samples"),
    GLFUNC_REQUIRES(glEndOcclusionQueryNV, "GL_NV_occlusion_query_samples"),
    GLFUNC_REQUIRES(glGetOcclusionQueryivNV, "GL_NV_occlusion_query_samples"),
    GLFUNC_REQUIRES(glGetOcclusionQueryuivNV, "GL_NV_occlusion_query_samples"),

    // ARB_clip_control
    GLFUNC_REQUIRES(glClipControl, "GL_ARB_clip_control !VERSION_4_5"),

    // ARB_copy_image
    GLFUNC_REQUIRES(glCopyImageSubData, "GL_ARB_copy_image !VERSION_4_3 |VERSION_GLES_3_2"),

    // NV_copy_image
    GLFUNC_SUFFIX(glCopyImageSubData, NV, "GL_NV_copy_image !GL_ARB_copy_image !VERSION_GLES_3_2"),

    // OES_copy_image
    GLFUNC_SUFFIX(glCopyImageSubData, OES, "GL_OES_copy_image !VERSION_GLES_3_2"),

    // EXT_copy_image
    GLFUNC_SUFFIX(glCopyImageSubData, EXT,
                  "GL_EXT_copy_image !GL_OES_copy_image !VERSION_GLES_3_2"),

    // EXT_texture_buffer
    GLFUNC_SUFFIX(glTexBuffer, OES, "GL_OES_texture_buffer !VERSION_GLES_3_2"),

    // EXT_texture_buffer
    GLFUNC_SUFFIX(glTexBuffer, EXT,
                  "GL_EXT_texture_buffer !GL_OES_texture_buffer !VERSION_GLES_3_2"),

    // EXT_blend_func_extended
    GLFUNC_SUFFIX(glBindFragDataLocationIndexed, EXT, "GL_EXT_blend_func_extended"),
    GLFUNC_SUFFIX(glGetFragDataIndex, EXT, "GL_EXT_blend_func_extended"),

    // ARB_shader_storage_buffer_object
    GLFUNC_REQUIRES(glShaderStorageBlockBinding, "ARB_shader_storage_buffer_object !VERSION_4_3"),

    // NV_depth_buffer_float
    GLFUNC_REQUIRES(glDepthRangedNV, "GL_NV_depth_buffer_float"),
    GLFUNC_REQUIRES(glClearDepthdNV, "GL_NV_depth_buffer_float"),
    GLFUNC_REQUIRES(glDepthBoundsdNV, "GL_NV_depth_buffer_float"),

    // ARB_shader_image_load_store
    GLFUNC_REQUIRES(glBindImageTexture,
                    "GL_ARB_shader_image_load_store !VERSION_4_2 |VERSION_GLES_3_1"),
    GLFUNC_REQUIRES(glMemoryBarrier,
                    "GL_ARB_shader_image_load_store !VERSION_4_2 |VERSION_GLES_3_1"),

    // ARB_compute_shader
    GLFUNC_REQUIRES(glDispatchCompute, "GL_ARB_compute_shader !VERSION_4_3 |VERSION_GLES_3_1"),
    GLFUNC_REQUIRES(glDispatchComputeIndirect,
                    "GL_ARB_compute_shader !VERSION_4_3 |VERSION_GLES_3_1"),

    // ARB_get_texture_sub_image
    GLFUNC_REQUIRES(glGetTextureSubImage, "GL_ARB_get_texture_sub_image !VERSION_4_5"),
};

namespace GLExtensions
{
// Private members and functions
static u32 s_gl_version;
static std::unordered_map<std::string, bool> s_extension_list;

// Private initialization functions
bool InitFunctionPointers(GLContext* context);

// Initializes the extension list the old way
static void InitExtensionList21()
{
  const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
  std::string tmp(extensions);
  std::istringstream buffer(tmp);

  while (buffer >> tmp)
    s_extension_list[tmp] = true;
}

static void InitExtensionList(GLContext* context)
{
  s_extension_list.clear();
  if (context->IsGLES())
  {
    switch (s_gl_version)
    {
    default:
    case 320:
      s_extension_list["VERSION_GLES_3_2"] = true;
    case 310:
      s_extension_list["VERSION_GLES_3_1"] = true;
    case 300:
      s_extension_list["VERSION_GLES_3"] = true;
      break;
    }

    // We always have ES 2.0
    s_extension_list["VERSION_GLES_2"] = true;
  }
  else
  {
    // Some OpenGL implementations chose to not expose core extensions as extensions
    // Let's add them to the list manually depending on which version of OpenGL we have
    // We need to be slightly careful here
    // When an extension got merged in to core, the naming may have changed

    // This has intentional fall through
    switch (s_gl_version)
    {
    default:
    case 450:
    {
      static const char* const gl450exts[] = {
          "GL_ARB_ES3_1_compatibility",
          "GL_ARB_clip_control",
          "GL_ARB_conditional_render_inverted",
          "GL_ARB_cull_distance",
          "GL_ARB_derivative_control",
          "GL_ARB_direct_state_access",
          "GL_ARB_get_texture_sub_image",
          "GL_ARB_robustness",
          "GL_ARB_shader_texture_image_samples",
          "GL_ARB_texture_barrier",
          "VERSION_4_5",
      };
      for (auto it : gl450exts)
        s_extension_list[it] = true;
    }
    case 440:
    {
      static const char* const gl440exts[] = {
          "GL_ARB_buffer_storage",
          "GL_ARB_clear_texture",
          "GL_ARB_enhanced_layouts",
          "GL_ARB_multi_bind",
          "GL_ARB_query_buffer_object",
          "GL_ARB_texture_mirror_clamp_to_edge",
          "GL_ARB_texture_stencil8",
          "GL_ARB_vertex_type_10f_11f_11f_rev",
          "VERSION_4_4",
      };
      for (auto it : gl440exts)
        s_extension_list[it] = true;
    }
    case 430:
    {
      static const char* const gl430exts[] = {
          "GL_ARB_ES3_compatibility",
          "GL_ARB_arrays_of_arrays",
          "GL_ARB_clear_buffer_object",
          "GL_ARB_compute_shader",
          "GL_ARB_copy_image",
          "GL_ARB_explicit_uniform_location",
          "GL_ARB_fragment_layer_viewport",
          "GL_ARB_framebuffer_no_attachments",
          "GL_ARB_internalformat_query2",
          "GL_ARB_invalidate_subdata",
          "GL_ARB_multi_draw_indirect",
          "GL_ARB_program_interface_query",
          "GL_ARB_shader_image_size",
          "GL_ARB_shader_storage_buffer_object",
          "GL_ARB_stencil_texturing",
          "GL_ARB_texture_buffer_range",
          "GL_ARB_texture_query_levels",
          "GL_ARB_texture_storage_multisample",
          "GL_ARB_texture_view",
          "GL_ARB_vertex_attrib_binding",
          "VERSION_4_3",
      };
      for (auto it : gl430exts)
        s_extension_list[it] = true;
    }
    case 420:
    {
      static const char* const gl420exts[] = {
          "GL_ARB_base_instance",
          "GL_ARB_compressed_texture_pixel_storage",
          "GL_ARB_conservative_depth",
          "GL_ARB_internalformat_query",
          "GL_ARB_map_buffer_alignment",
          "GL_ARB_shader_atomic_counters",
          "GL_ARB_shader_image_load_store",
          "GL_ARB_shading_language_420pack",
          "GL_ARB_shading_language_packing",
          "GL_ARB_texture_compression_BPTC",
          "GL_ARB_texture_storage",
          "GL_ARB_transform_feedback_instanced",
          "VERSION_4_2",
      };
      for (auto it : gl420exts)
        s_extension_list[it] = true;
    }
    case 410:
    {
      static const char* const gl410exts[] = {
          "GL_ARB_ES2_compatibility",
          "GL_ARB_get_program_binary",
          "GL_ARB_separate_shader_objects",
          "GL_ARB_shader_precision",
          "GL_ARB_vertex_attrib_64_bit",
          "GL_ARB_viewport_array",
          "VERSION_4_1",
      };
      for (auto it : gl410exts)
        s_extension_list[it] = true;
    }
    case 400:
    {
      static const char* const gl400exts[] = {
          "GL_ARB_draw_indirect",
          "GL_ARB_gpu_shader5",
          "GL_ARB_gpu_shader_fp64",
          "GL_ARB_sample_shading",
          "GL_ARB_shader_subroutine",
          "GL_ARB_tessellation_shader",
          "GL_ARB_texture_buffer_object_rgb32",
          "GL_ARB_texture_cube_map_array",
          "GL_ARB_texture_gather",
          "GL_ARB_texture_query_lod",
          "GL_ARB_transform_feedback2",
          "GL_ARB_transform_feedback3",
          "VERSION_4_0",
      };
      for (auto it : gl400exts)
        s_extension_list[it] = true;
    }
    case 330:
    {
      static const char* const gl330exts[] = {
          "GL_ARB_shader_bit_encoding",
          "GL_ARB_blend_func_extended",
          "GL_ARB_explicit_attrib_location",
          "GL_ARB_occlusion_query2",
          "GL_ARB_sampler_objects",
          "GL_ARB_texture_swizzle",
          "GL_ARB_timer_query",
          "GL_ARB_instanced_arrays",
          "GL_ARB_texture_rgb10_a2ui",
          "GL_ARB_vertex_type_2_10_10_10_rev",
          "VERSION_3_3",
      };
      for (auto it : gl330exts)
        s_extension_list[it] = true;
    }
    case 320:
    {
      static const char* const gl320exts[] = {
          "GL_ARB_geometry_shader4",
          "GL_ARB_sync",
          "GL_ARB_vertex_array_bgra",
          "GL_ARB_draw_elements_base_vertex",
          "GL_ARB_seamless_cube_map",
          "GL_ARB_texture_multisample",
          "GL_ARB_fragment_coord_conventions",
          "GL_ARB_provoking_vertex",
          "GL_ARB_depth_clamp",
          "VERSION_3_2",
      };
      for (auto it : gl320exts)
        s_extension_list[it] = true;
    }
    case 310:
    {
      // Can't add NV_primitive_restart since function name changed
      static const char* const gl310exts[] = {
          "GL_ARB_draw_instanced",
          "GL_ARB_copy_buffer",
          "GL_ARB_texture_buffer_object",
          "GL_ARB_texture_rectangle",
          "GL_ARB_uniform_buffer_object",
          //"GL_NV_primitive_restart",
          "VERSION_3_1",
      };
      for (auto it : gl310exts)
        s_extension_list[it] = true;
    }
    case 300:
    {
      // Quite a lot of these had their names changed when merged in to core
      // Disable the ones that have
      static const char* const gl300exts[] = {
          "GL_ARB_map_buffer_range",
          "GL_ARB_color_buffer_float",
          "GL_ARB_texture_float",
          "GL_ARB_half_float_pixel",
          "GL_ARB_framebuffer_object",
          "GL_ARB_texture_float",
          "GL_ARB_vertex_array_object",
          "GL_ARB_depth_buffer_float",
          //"GL_EXT_texture_integer",
          //"GL_EXT_gpu_shader4",
          //"GL_APPLE_flush_buffer_range",
          //"GL_EXT_packed_float",
          //"GL_EXT_texture_shared_exponent",
          //"GL_NV_half_float",
          //"GL_EXT_framebuffer_sRGB",
          //"GL_EXT_draw_buffers2",
          //"GL_EXT_texture_integer",
          //"GL_EXT_texture_array",
          //"GL_EXT_texture_compression_rgtc",
          //"GL_EXT_transform_feedback",
          //"GL_NV_conditional_render",
          "VERSION_3_0",
      };
      for (auto it : gl300exts)
        s_extension_list[it] = true;
    }
    case 210:
    case 200:
    case 150:
    case 140:
    case 130:
    case 121:
    case 120:
    case 110:
    case 100:
      break;
    }
    // So we can easily determine if we are running dekstop GL
    s_extension_list["VERSION_GL"] = true;
  }

  if (s_gl_version < 300)
  {
    InitExtensionList21();
    return;
  }
  GLint NumExtension = 0;
  glGetIntegerv(GL_NUM_EXTENSIONS, &NumExtension);
  for (GLint i = 0; i < NumExtension; ++i)
    s_extension_list[std::string((const char*)glGetStringi(GL_EXTENSIONS, i))] = true;
}
static void InitVersion()
{
  GLint major, minor;
  glGetIntegerv(GL_MAJOR_VERSION, &major);
  glGetIntegerv(GL_MINOR_VERSION, &minor);
  if (glGetError() == GL_NO_ERROR)
    s_gl_version = major * 100 + minor * 10;
  else
    s_gl_version = 210;
}

static void* GetFuncAddress(GLContext* context, const std::string& name, void** func)
{
  *func = context->GetFuncAddress(name);
  if (*func == nullptr)
  {
#if defined(__linux__) || defined(__APPLE__)
    // Give it a second try with dlsym
    *func = dlsym(RTLD_NEXT, name.c_str());
#endif
    if (*func == nullptr)
      ERROR_LOG_FMT(VIDEO, "Couldn't load function {}", name);
  }
  return *func;
}

// Public members
u32 Version()
{
  return s_gl_version;
}
bool Supports(const std::string& name)
{
  return s_extension_list[name];
}

bool Init(GLContext* context)
{
  // Grab a few functions for initial checking
  // We need them to grab the extension list
  // Also to check if there is an error grabbing the version
  if (GetFuncAddress(context, "glGetIntegerv", (void**)&glGetIntegerv) == nullptr)
    return false;
  if (GetFuncAddress(context, "glGetString", (void**)&glGetString) == nullptr)
    return false;
  if (GetFuncAddress(context, "glGetError", (void**)&glGetError) == nullptr)
    return false;

  InitVersion();

  // We need to use glGetStringi to get the extension list
  // if we are using GLES3 or a GL version greater than 2.1
  if (s_gl_version > 210 &&
      GetFuncAddress(context, "glGetStringi", (void**)&glGetStringi) == nullptr)
    return false;

  InitExtensionList(context);

  return InitFunctionPointers(context);
}

// Private initialization functions
static bool HasFeatures(const std::string& extensions)
{
  bool result = true;
  std::string tmp;
  std::istringstream buffer(extensions);

  while (buffer >> tmp)
  {
    if (tmp[0] == '!')
      result &= !s_extension_list[tmp.erase(0, 1)];
    else if (tmp[0] == '|')
      result |= s_extension_list[tmp.erase(0, 1)];
    else
      result &= s_extension_list[tmp];
  }
  return result;
}
bool InitFunctionPointers(GLContext* context)
{
  bool result = true;
  for (const auto& it : gl_function_array)
    if (HasFeatures(it.requirements))
      result &= !!GetFuncAddress(context, it.function_name, it.function_ptr);
  return result;
}
}  // namespace GLExtensions
