//================================================================
// E3D library
//
// OpenGL basics
//
// AUTHOR:  Gabor Nagy
// DATE:    2025-May-07 18:00:49
//
// Copyright (C) 2014-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _Image_EpGL_h
#define _Image_EpGL_h


#ifdef __APPLE__
#include <OpenGL/gl.h>
#else

#ifndef sgi
	#define E3dGLHAS_COLORINDEX_TEXTURE  1
	#define GL_GLEXT_PROTOTYPES          1
#endif

#include <GL/gl.h>
#endif	// __APPLE__


#ifndef sgi
	#define EpGL_HAS_FBO                1
#endif


#ifdef sgi
#include <GL/glx.h>
#define GLXPbuffer  GLXPbufferSGIX
#else

#ifdef __APPLE__
#include <OpenGL/glext.h>
#else
 #include <GL/glext.h>
#endif  // __APPLE__

#endif  // sgi


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


// To force stenciled solid+wire, comment this out:
//
#if defined(GL_EXT_polygon_offset) || defined(GL_VERSION_1_1)
	#define E3dGL_POLYGON_OFFSET_SUPPORTED
#endif

#if defined(GL_EXT_polygon_offset) && !defined(GL_VERSION_1_1)
	#define glPolygonOffset(A, B)     glPolygonOffsetEXT(A, B)

// OpenGL 1.1's polygon offset can be different for each
// polygon mode primitive type.
// The EXT extension has only one offset.
//
	#define GL_POLYGON_OFFSET_FILL   GL_POLYGON_OFFSET_EXT
#endif

#ifndef sgi
	#define E3dGL_MULTITEXTURING  1
#endif

#if defined(GL_EXT_polygon_offset) || defined(GL_VERSION_1_1)
// To force stenciled solid+wire, comment this out:
//
	#define E3dGL_POLYGON_OFFSET_SUPPORTED
#endif



#ifndef GL_TEXTURE_RECTANGLE
	#ifdef GL_TEXTURE_RECTANGLE_ARB
		#define GL_TEXTURE_RECTANGLE  GL_TEXTURE_RECTANGLE_ARB
	#endif
#endif

#ifndef GL_TEXTURE_BINDING_RECTANGLE
	#ifdef GL_TEXTURE_BINDING_RECTANGLE_ARB
		#define GL_TEXTURE_BINDING_RECTANGLE  GL_TEXTURE_BINDING_RECTANGLE_ARB
	#endif
#endif


#if ERELEASE_BUILD
#define EpGLDEBUG  0
#else
#define EpGLDEBUG  1
#endif

#if EpGLDEBUG
#define EpglActiveTexture(p)                          do { glActiveTexture(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglAttachShader(p0, p1)                      do { glAttachShader(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBegin(p)                                  glBegin(p)      // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglBindBuffer(p0, p1)                        do { glBindBuffer(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBindTexture(p0, p1)                       do { glBindTexture(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBindFramebuffer(p0, p1)                   do { glBindFramebuffer(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBindRenderbuffer(p0, p1)                  do { glBindRenderbuffer(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBitmap(p0, p1, p2, p3, p4, p5, p6)        do { glBitmap(p0, p1, p2, p3, p4, p5, p6);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBlendFunc(p0, p1)                         do { glBlendFunc(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBlendColor(p0, p1, p2, p3)                do { glBlendColor(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglBufferData(p0, p1, p2, p3)                do { glBufferData(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglCallList(p)                               do { glCallList(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglCallLists(p0, p1, p2)                     do { glCallLists(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglClear(p)                                  do { glClear(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglClearColor(p0, p1, p2, p3)                do { glClearColor(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglClearDepth(p)                             do { glClearDepth(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglClearStencil(p)                           do { glClearStencil(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglClientActiveTexture(p)                    do { glClientActiveTexture(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColor3d(p0, p1, p2)                       do { glColor3d(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColor3f(p0, p1, p2)                       do { glColor3f(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColor4ub(p0, p1, p2, p3)                  do { glColor4ub(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColor4ubv(p)                              do { glColor4ubv(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColor4f(p0, p1, p2, p3)                   do { glColor4f(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColor4fv(p)                               do { glColor4fv(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColorMask(p0, p1, p2, p3)                 do { glColorMask(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColorTable(p0, p1, p2, p3, p4, p5)        do { glColorTable(p0, p1, p2, p3, p4, p5);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglCompileShader(p)                          do { glCompileShader(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglCullFace(p)                               do { glCullFace(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDeleteLists(p0, p1)                       do { glDeleteLists(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDeleteProgram(p)                          do { glDeleteProgram(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDeleteTextures(p0, p1)                    do { glDeleteTextures(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDepthMask(p)                              do { glDepthMask(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDepthFunc(p)                              do { glDepthFunc(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDisable(p)                                do { glDisable(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDisableClientState(p)                     do { glDisableClientState(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDisableVertexAttribArray(p)               do { glDisableVertexAttribArray(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDrawBuffer(p)                             do { glDrawBuffer(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDrawArrays(p0, p1, p2)                    do { glDrawArrays(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDrawElements(p0, p1, p2, p3)              do { glDrawElements(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDrawRangeElements(p0, p1, p2, p3, p4, p6) do { glDrawRangeElements(p0, p1, p2, p3, p4, p5);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglDrawPixels(p0, p1, p2, p3, p4)            do { glDrawPixels(p0, p1, p2, p3, p4);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglEnable(p)                                 do { glEnable(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglEnableClientState(p)                      do { glEnableClientState(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglEnableVertexAttribArray(p)                do { glEnableVertexAttribArray(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglEnd()                                     do { glEnd();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglEndList()                                 do { glEndList();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglFinish()                                  do { glFinish();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglFlush()                                   do { glFlush();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglFramebufferTexture2D(p0, p1, p2, p3, p4)  do { glFramebufferTexture2D(p0, p1, p2, p3, p4);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglFramebufferRenderbuffer(p0, p1, p2, p3)   do { glFramebufferRenderbuffer(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglFrontFace(p)                              do { glFrontFace(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglFrustum(p0, p1, p2, p3, p4, p5)           do { glFrustum(p0, p1, p2, p3, p4, p5);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGenBuffers(p0, p1)                        do { glGenBuffers(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGenRenderbuffers(p0, p1)                  do { glGenRenderbuffers(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGenTextures(p0, p1)                       do { glGenTextures(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGetBooleanv(p0, p1)                       do { glGetBooleanv(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGetDoublev(p0, p1)                        do { glGetDoublev(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGetFloatv(p0, p1)                         do { glGetFloatv(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGetIntegerv(p0, p1)                       do { glGetIntegerv(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGetPointerv(p0, p1)                       do { glGetPointerv(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglGetProgramiv(p0, p1, p2)                  do { glGetProgramiv(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglHint(p0, p1)                              do { glHint(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglIndexi(p)                                 do { glIndexi(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglInitNames()                               do { glInitNames();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLightf(p0, p1, p2)                        do { glLightf(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLightfv(p0, p1, p2)                       do { glLightfv(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLightModeli(p0, p1)                       do { glLightModeli(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLightModelfv(p0, p1)                      do { glLightModelfv(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLineStipple(p0, p1)                       do { glLineStipple(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLineWidth(p)                              do { glLineWidth(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLinkProgram(p)                            do { glLinkProgram(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglListBase(p)                               do { glListBase(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLoadIdentity()                            do { glLoadIdentity();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLoadMatrixf(p)                            do { glLoadMatrixf(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglLoadName(p)                               do { glLoadName(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglMaterialf(p0, p1, p2)                     do { glMaterialf(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglMaterialfv(p0, p1, p2)                    do { glMaterialfv(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglMatrixMode(p)                             do { glMatrixMode(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglMultiTexCoord2fv(p0, p1)                  glMultiTexCoord2fv(p0, p1)  // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglMultMatrixf(p)                            do { glMultMatrixf(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglNewList(p0, p1)                           do { glNewList(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglNormal3f                                  glNormal3f                  // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglNormal3fv(p)                              glNormal3fv(p)              // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglNormalPointer(p0, p1, p2)                 do { glNormalPointer(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglOrtho(p0, p1, p2, p3, p4, p5)             do { glOrtho(p0, p1, p2, p3, p4, p5);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPixelMapusv(p0, p1, p2)                   do { glPixelMapusv(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPixelStorei(p0, p1)                       do { glPixelStorei(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPixelZoom(p0, p1)                         do { glPixelZoom(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPointSize(p)                              do { glPointSize(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPopMatrix()                               do { glPopMatrix();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPopName()                                 do { glPopName();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPolygonMode(p0, p1)                       do { glPolygonMode(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPolygonOffset(p0, p1)                     do { glPolygonOffset(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPushMatrix()                              do { glPushMatrix();XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglPushName(p)                               do { glPushName(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglRasterPos2f(p0, p1)                       do { glRasterPos2f(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglRasterPos2i(p0, p1)                       do { glRasterPos2i(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglRasterPos2fv(p)                           do { glRasterPos2fv(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglRasterPos3f(p0, p1, p2)                   do { glRasterPos3f(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglRasterPos3fv(p)                           do { glRasterPos3fv(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglReadBuffer(p)                             do { glReadBuffer(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglReadPixels(p0, p1, p2, p3, p4, p5, p6)    do { glReadPixels(p0, p1, p2, p3, p4, p5, p6);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglRenderbufferStorage(p0, p1, p2, p3)       do { glRenderbufferStorage(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
static inline GLint EpglRenderMode(GLenum PMode) { const GLint  LResult = glRenderMode(PMode);XeGLM_CheckStatusNL(FALSE);return(LResult); }
#define EpglScalef(p0, p1, p2)                        do { glScalef(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglSelectBuffer(p0, p1)                      do { glSelectBuffer(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglShadeModel(p)                             do { glShadeModel(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglShaderSource(p0, p1, p2, p3)              do { glShaderSource(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexCoord2f(p0, p1)                        glTexCoord2f(p0, p1)        // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglTexCoord2fv(p)                            glTexCoord2fv(p)            // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglTexCoordPointer(p0, p1, p2, p3)           do { glTexCoordPointer(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexEnvf(p0, p1, p2)                       do { glTexEnvf(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexGenfv(p0, p1, p2)                      do { glTexGenfv(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexGeni(p0, p1, p2)                       do { glTexGeni(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexImage1D(p0, p1, p2, p3, p4, p5, p6, p7)  do { glTexImage1D(p0, p1, p2, p3, p4, p5, p6, p7);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8)  do { glTexImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexImage3D(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)  do { glTexImage3D(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexParameterf(p0, p1, p2)                 do { glTexParameterf(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexParameterfv(p0, p1, p2)                do { glTexParameterfv(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexParameteri(p0, p1, p2)                 do { glTexParameteri(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexSubImage1D(p0, p1, p2, p3, p4, p5, p6) do { glTexSubImage1D(p0, p1, p2, p3, p4, p5, p6);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTexSubImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8)  do { glTexSubImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglTranslatef(p0, p1, p2)                    do { glTranslatef(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglUniform1i(p0, p1)                         do { glUniform1i(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglUseProgram(p)                             do { glUseProgram(p);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglVertex2i(p0, p1)                          glVertex2i(p0, p1)        // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglVertex2fv(p)                              glVertex2fv(p)            // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglVertex3f(p0, p1, p2)                      glVertex3f(p0, p1, p2)    // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglVertex3fv(p)                              glVertex3fv(p)            // Can't have any GL calls between glBegin and glEnd. That includes XeGLM_CheckStatusNL.
#define EpglVertexAttribPointer(p0, p1, p2, p3, p4, p5)   do { glVertexAttribPointer(p0, p1, p2, p3, p4, p5);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglVertexPointer(p0, p1, p2, p3)             do { glVertexPointer(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglColorPointer(p0, p1, p2, p3)              do { glColorPointer(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
#define EpglViewport(p0, p1, p2, p3)                  do { glViewport(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
//#define Epgl(p)                              do { gl(p);XeGLM_CheckStatusNL(FALSE); } while(0)
//#define Epgl(p0, p1)                         do { gl(p0, p1);XeGLM_CheckStatusNL(FALSE); } while(0)
//#define Epgl(p0, p1, p2)                     do { gl(p0, p1, p2);XeGLM_CheckStatusNL(FALSE); } while(0)
//#define Epgl(p0, p1, p2, p3)                 do { gl(p0, p1, p2, p3);XeGLM_CheckStatusNL(FALSE); } while(0)
//#define Epgl(p0, p1, p2, p3, p4)             do { gl(p0, p1, p2, p3, p4);XeGLM_CheckStatusNL(FALSE); } while(0)
//#define Epgl(p0, p1, p2, p3, p4, p5)         do { gl(p0, p1, p2, p3, p4, p5);XeGLM_CheckStatusNL(FALSE); } while(0)
#else
#define EpglActiveTexture(p)                          glActiveTexture(p)
#define EpglAttachShader(p0, p1)                      glAttachShader(p0, p1)
#define EpglBegin(p)                                  glBegin(p)
#define EpglBindBuffer(p0, p1)                        glBindBuffer(p0, p1)
#define EpglBindTexture(p0, p1)                       glBindTexture(p0, p1)
#define EpglBindFramebuffer(p0, p1)                   glBindFramebuffer(p0, p1)
#define EpglBindRenderbuffer(p0, p1)                  glBindRenderbuffer(p0, p1)
#define EpglBitmap(p0, p1, p2, p3, p4, p5, p6)        glBitmap(p0, p1, p2, p3, p4, p5, p6)
#define EpglBlendFunc(p0, p1)                         glBlendFunc(p0, p1)
#define EpglBlendColor(p0, p1, p2, p3)                glBlendColor(p0, p1, p2, p3)
#define EpglBufferData(p0, p1, p2, p3)                glBufferData(p0, p1, p2, p3)
#define EpglCallList(p)                               glCallList(p)
#define EpglCallLists(p0, p1, p2)                     glCallLists(p0, p1, p2)
#define EpglClear(p)                                  glClear(p)
#define EpglClearColor(p0, p1, p2, p3)                glClearColor(p0, p1, p2, p3)
#define EpglClearDepth(p)                             glClearDepth(p)
#define EpglClearStencil(p)                           glClearStencil(p)
#define EpglClientActiveTexture(p)                    glClientActiveTexture(p)
#define EpglColor3d(p0, p1, p2)                       glColor3d(p0, p1, p2)
#define EpglColor3f(p0, p1, p2)                       glColor3f(p0, p1, p2)
#define EpglColor4ub(p0, p1, p2, p3)                  glColor4ub(p0, p1, p2, p3)
#define EpglColor4ubv(p)                              glColor4ubv(p)
#define EpglColor4f(p0, p1, p2, p3)                   glColor4f(p0, p1, p2, p3)
#define EpglColor4fv(p)                               glColor4fv(p)
#define EpglColorMask(p0, p1, p2, p3)                 glColorMask(p0, p1, p2, p3)
#define EpglColorTable(p0, p1, p2, p3, p4, p5)        glColorTable(p0, p1, p2, p3, p4, p5)
#define EpglCompileShader(p)                          glCompileShader(p)
#define EpglCullFace(p)                               glCullFace(p)
#define EpglDeleteLists(p0, p1)                       glDeleteLists(p0, p1)
#define EpglDeleteProgram(p)                          glDeleteProgram(p)
#define EpglDeleteTextures(p0, p1)                    glDeleteTextures(p0, p1)
#define EpglDepthMask(p0)                             glDepthMask(p0)
#define EpglDepthFunc(p)                              glDepthFunc(p)
#define EpglDisable(p)                                glDisable(p)
#define EpglDisableClientState(p)                     glDisableClientState(p)
#define EpglDisableVertexAttribArray(p)               glDisableVertexAttribArray(p)
#define EpglDrawBuffer(p)                             glDrawBuffer(p)
#define EpglDrawArrays(p0, p1, p2)                    glDrawArrays(p0, p1, p2)
#define EpglDrawElements(p0, p1, p2, p3)              glDrawElements(p0, p1, p2, p3)
#define EpglDrawRangeElements(p0, p1, p2, p3, p4, p5) glDrawRangeElements(p0, p1, p2, p3, p4, p5)
#define EpglDrawPixels(p0, p1, p2, p3, p4)            glDrawPixels(p0, p1, p2, p3, p4)
#define EpglEnable(p)                                 glEnable(p)
#define EpglEnableClientState(p)                      glEnableClientState(p)
#define EpglEnableVertexAttribArray(p)                glEnableVertexAttribArray(p)
#define EpglEnd()                                     glEnd()
#define EpglEndList()                                 glEndList()
#define EpglFinish()                                  glFinish()
#define EpglFlush()                                   glFlush()
#define EpglFramebufferTexture2D(p0, p1, p2, p3, p4)  glFramebufferTexture2D(p0, p1, p2, p3, p4)
#define EpglFramebufferRenderbuffer(p0, p1, p2, p3)   glFramebufferRenderbuffer(p0, p1, p2, p3)
#define EpglFrontFace(p)                              glFrontFace(p)
#define EpglFrustum(p0, p1, p2, p3, p4, p5)           glFrustum(p0, p1, p2, p3, p4, p5)
#define EpglGenBuffers(p0, p1)                        glGenBuffers(p0, p1)
#define EpglGenRenderbuffers(p0, p1)                  glGenRenderbuffers(p0, p1)
#define EpglGenTextures(p0, p1)                       glGenTextures(p0, p1)
#define EpglGetBooleanv(p0, p1)                       glGetBooleanv(p0, p1)
#define EpglGetDoublev(p0, p1)                        glGetDoublev(p0, p1);
#define EpglGetFloatv(p0, p1)                         glGetFloatv(p0, p1)
#define EpglGetIntegerv(p0, p1)                       glGetIntegerv(p0, p1)
#define EpglGetPointerv(p0, p1)                       glGetPointerv(p0, p1)
#define EpglGetProgramiv(p0, p1, p2)                  glGetProgramiv(p0, p1, p2)
#define EpglHint(p0, p1)                              glHint(p0, p1)
#define EpglIndexi(p)                                 glIndexi(p)
#define EpglInitNames()                               glInitNames()
#define EpglLightf(p0, p1, p2)                        glLightf(p0, p1, p2)
#define EpglLightfv(p0, p1, p2)                       glLightfv(p0, p1, p2)
#define EpglLightModeli(p0, p1)                       glLightModeli(p0, p1)
#define EpglLightModelfv(p0, p1)                      glLightModelfv(p0, p1)
#define EpglLineStipple(p0, p1)                       glLineStipple(p0, p1)
#define EpglLineWidth(p)                              glLineWidth(p)
#define EpglLinkProgram(p)                            glLinkProgram(p)
#define EpglListBase(p)                               glListBase(p)
#define EpglLoadIdentity()                            glLoadIdentity()
#define EpglLoadMatrixf(p)                            glLoadMatrixf(p)
#define EpglLoadName(p)                               glLoadName(p)
#define EpglMaterialf(p0, p1, p2)                     glMaterialf(p0, p1, p2)
#define EpglMaterialfv(p0, p1, p2)                    glMaterialfv(p0, p1, p2)
#define EpglMatrixMode(p)                             glMatrixMode(p)
#define EpglMultiTexCoord2fv(p0, p1)                  glMultiTexCoord2fv(p0, p1)
#define EpglMultMatrixf(p)                            glMultMatrixf(p)
#define EpglNewList(p0, p1)                           glNewList(p0, p1)
#define EpglNormal3f                                  glNormal3f
#define EpglNormal3fv(p)                              glNormal3fv(p)
#define EpglNormalPointer(p0, p1, p2)                 glNormalPointer(p0, p1, p2)
#define EpglOrtho(p0, p1, p2, p3, p4, p5)             glOrtho(p0, p1, p2, p3, p4, p5)
#define EpglPixelMapusv(p0, p1, p2)                   glPixelMapusv(p0, p1, p2)
#define EpglPixelStorei(p0, p1)                       glPixelStorei(p0, p1)
#define EpglPixelZoom(p0, p1)                         glPixelZoom(p0, p1)
#define EpglPointSize(p)                              glPointSize(p)
#define EpglPolygonMode(p0, p1)                       glPolygonMode(p0, p1)
#define EpglPolygonOffset(p0, p1)                     glPolygonOffset(p0, p1)
#define EpglPopMatrix()                               glPopMatrix()
#define EpglPopName()                                 glPopName()
#define EpglPushMatrix()                              glPushMatrix()
#define EpglPushName(p)                               glPushName(p)
#define EpglRasterPos2f(p0, p1)                       glRasterPos2f(p0, p1)
#define EpglRasterPos2i(p0, p1)                       glRasterPos2i(p0, p1)
#define EpglRasterPos2fv(p)                           glRasterPos2fv(p)
#define EpglRasterPos3f(p0, p1, p2)                   glRasterPos3f(p0, p1, p2)
#define EpglRasterPos3fv(p)                           glRasterPos3fv(p)
#define EpglReadBuffer(p)                             glReadBuffer(p)
#define EpglReadPixels(p0, p1, p2, p3, p4, p5, p6)    glReadPixels(p0, p1, p2, p3, p4, p5, p6)
#define EpglRenderbufferStorage(p0, p1, p2, p3)       glRenderbufferStorage(p0, p1, p2, p3)
#define EpglRenderMode(p)                             glRenderMode(p)
#define EpglScalef(p0, p1, p2)                        glScalef(p0, p1, p2)
#define EpglSelectBuffer(p0, p1)                      glSelectBuffer(p0, p1)
#define EpglShadeModel(p)                             glShadeModel(p)
#define EpglShaderSource(p0, p1, p2, p3)              glShaderSource(p0, p1, p2, p3)
#define EpglTexCoord2f(p0, p1)                        glTexCoord2f(p0, p1)
#define EpglTexCoord2fv(p)                            glTexCoord2fv(p)
#define EpglTexCoordPointer(p0, p1, p2, p3)           glTexCoordPointer(p0, p1, p2, p3)
#define EpglTexEnvf(p0, p1, p2)                       glTexEnvf(p0, p1, p2)
#define EpglTexGenfv(p0, p1, p2)                      glTexGenfv(p0, p1, p2)
#define EpglTexGeni(p0, p1, p2)                       glTexGeni(p0, p1, p2)
#define EpglTexImage1D(p0, p1, p2, p3, p4, p5, p6, p7)    glTexImage1D(p0, p1, p2, p3, p4, p5, p6, p7)
#define EpglTexImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8)  glTexImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8)
#define EpglTexImage3D(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)  glTexImage3D(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)
#define EpglTexParameterf(p0, p1, p2)                 glTexParameterf(p0, p1, p2)
#define EpglTexParameterfv(p0, p1, p2)                glTexParameterfv(p0, p1, p2)
#define EpglTexParameteri(p0, p1, p2)                 glTexParameteri(p0, p1, p2)
#define EpglTexSubImage1D(p0, p1, p2, p3, p4, p5, p6) glTexSubImage1D(p0, p1, p2, p3, p4, p5, p6)
#define EpglTexSubImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8)  glTexSubImage2D(p0, p1, p2, p3, p4, p5, p6, p7, p8)
#define EpglTranslatef(p0, p1, p2)                    glTranslatef(p0, p1, p2)
#define EpglUniform1i(p0, p1)                         glUniform1i(p0, p1)
#define EpglUseProgram(p)                             glUseProgram(p)
#define EpglVertex2i(p0, p1)                          glVertex2i(p0, p1)
#define EpglVertex2fv(p)                              glVertex2fv(p)
#define EpglVertex3f(p0, p1, p2)                      glVertex3f(p0, p1, p2)
#define EpglVertex3fv(p)                              glVertex3fv(p)
#define EpglVertexAttribPointer(p0, p1, p2, p3, p4, p5)   glVertexAttribPointer(p0, p1, p2, p3, p4, p5)
#define EpglVertexPointer(p0, p1, p2, p3)             glVertexPointer(p0, p1, p2, p3)
#define EpglColorPointer(p0, p1, p2, p3)              glColorPointer(p0, p1, p2, p3)
#define EpglViewport(p0, p1, p2, p3)                  glViewport(p0, p1, p2, p3)
#endif

#define E3dFBO_GROW_ONLY   0x0001
#define E3dFBO_CREATE_PBO  0x0002


#ifdef EGLES
#define EpGL_VertexPointer(pParam,  pSize, pType, pStride, pPtr) do\
{\
	if(pParam >= 0) { EpglVertexAttribPointer(pParam,  pSize,  pType,  FALSE,  pStride, pPtr);EpglEnableVertexAttribArray(pParam); }\
} while(0)

#define EpGL_ColorPointer(pParam,  pSize, pType, pStride, pPtr) do\
{\
	if(pParam >= 0) { EpglVertexAttribPointer(pParam,  pSize,  pType,  FALSE,  pStride, pPtr);EpglEnableVertexAttribArray(pParam); }\
} while(0)

#define EpGL_NormalPointer(pParam,  pType, pStride, pPtr) do\
{\
	if(pParam >= 0) { EpglVertexAttribPointer(pParam,  3,  pType,  FALSE,  pStride, pPtr);EpglEnableVertexAttribArray(pParam); }\
} while(0)

#define EpGL_TexCoordPointer(pParam,  pSize, pType, pStride, pPtr) do\
{\
	if(pParam >= 0) { EpglVertexAttribPointer(pParam,  pSize,  pType,  FALSE,  pStride, pPtr);EpglEnableVertexAttribArray(pParam); }\
} while(0)

#else

#define EpGL_VertexPointer(pParam,  pSize, pType, pStride, pPtr)    do { EpglVertexPointer(pSize, pType, pStride, pPtr);EpglEnableClientState(GL_VERTEX_ARRAY); } while(0)
#define EpGL_ColorPointer(pParam,  pSize, pType, pStride, pPtr)     do { EpglColorPointer(pSize, pType, pStride, pPtr);EpglEnableClientState(GL_COLOR_ARRAY); } while(0)
#define EpGL_NormalPointer(pParam,  pType, pStride, pPtr)           do { EpglNormalPointer(pType, pStride, pPtr);EpglEnableClientState(GL_NORMAL_ARRAY); } while(0)
#define EpGL_TexCoordPointer(pParam,  pSize, pType, pStride, pPtr)  do { EpglTexCoordPointer(pSize, pType, pStride, pPtr);EpglEnableClientState(GL_TEXTURE_COORD_ARRAY); } while(0)
#endif  // EGLSL


typedef struct
{
	const char*  API;       // EpAPI_OpenGL, EpAPI_Vulkan etc.
	const char*  Vendor;
	const char*  Model;

// Rendering features supported by the hardware
//
	uint32_t     PixelType, PixelComponentType;
	uint8_t      VertexArrays,
	             Shadows,
	             Stereo,
	             VertexPrograms,
	             PixelPrograms;

	uint32_t     OpenGL12:1,
	             FrameBufferObject:1, Multisampling:1;

	float        Texture_MaximumAnisotropy;
	uint32_t     Texture_AnisotropicFiltering : 1,
	             Texture_Float : 1,
	             Texture_Rectangle : 1,
	             Texture_EdgeClamp : 1, Texture_BorderClamp : 1, Texture_Cubemap : 1,
	             Lighting_SeparateSpecularColor : 1;
} EpGPUInfo;

extern EpGPUInfo  Ep_GPUInfo;


static inline GLint EResType_ToGL(const uint16_t PType)
{
	switch(PType)
	{
		case EResINT8:     return(GL_BYTE);
		case EResUINT8:    return(GL_UNSIGNED_BYTE);
		case EResINT16:    return(GL_SHORT);
		case EResUINT16:   return(GL_UNSIGNED_SHORT);
		case EResFLOAT32:  return(GL_FLOAT);
		case EResFLOAT64:  return(GL_DOUBLE);
		default:
{ char  s[256];printf("%s() %s:%d  %sIMPLEMENT ME%s  %s\n", __FUNCTION__, __FILE__, __LINE__, ECodeYellow, ECodeNormal, ERes_TypeToString(PType, s, 256));fflush(stdout); }
		return(0);
	}
}


extern EBool  EpGL_ExtensionsInitialized;
extern GLint  EpGL_MAX_LIGHTS, EpGL_MAX_TEXTURE_UNITS, EpGL_MAX_TEXTURE_IMAGE_UNITS;


//========================================================
// Disable all texturing in fixed-pipeline mode
//========================================================
static inline void EpGL_TexturesDisableAll(void)
{
#ifndef EGLES
	GLint  LActiveTexture;EpglGetIntegerv(GL_ACTIVE_TEXTURE, &LActiveTexture);

	EpGPUInfo*  LGPUInfo = &Ep_GPUInfo;
	int  LI = 0;for(;LI < EpGL_MAX_TEXTURE_UNITS;LI++)
	{
	#ifdef E3dGL_MULTITEXTURING
		EpglActiveTexture(GL_TEXTURE0 + LI);
	#endif
		EpglDisable(GL_TEXTURE_1D);
		EpglDisable(GL_TEXTURE_2D);
		EpglDisable(GL_TEXTURE_3D);
		if(LGPUInfo->Texture_Cubemap) EpglDisable(GL_TEXTURE_CUBE_MAP);
	#if defined(GL_TEXTURE_RECTANGLE_ARB) && !defined(EGLES)
		EpglDisable(GL_TEXTURE_RECTANGLE);
	#endif
	}
	#ifdef E3dGL_MULTITEXTURING
	EpglActiveTexture(LActiveTexture);
	#endif
#endif  // EGLES
}


extern EBool   EpGL_ExtensionSupported(const char* PName);
extern int     EpGL_InitExtensions(void);


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _Image_EpGL_h

