Merge pull request #822 from DanielGibson/gles3-rb

OpenGL ES 3.0 support
This commit is contained in:
Yamagi 2022-05-07 09:45:30 +02:00 committed by GitHub
commit e294fc94e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 3032 additions and 107 deletions

View file

@ -264,7 +264,7 @@ endif()
# With all of those libraries and user defined paths
# added, lets give them to the compiler and linker.
include_directories(${yquake2IncludeDirectories} ${CMAKE_SOURCE_DIR}/src/client/refresh/gl3/glad/include)
include_directories(${yquake2IncludeDirectories})
link_directories(${yquake2LinkerDirectories})
# If we're building with gcc for i386 let's define -ffloat-store.
@ -606,7 +606,6 @@ set(GL3-Source
${REF_SRC_DIR}/gl3/gl3_shaders.c
${REF_SRC_DIR}/gl3/gl3_md2.c
${REF_SRC_DIR}/gl3/gl3_sp2.c
${REF_SRC_DIR}/gl3/glad/src/glad.c
${REF_SRC_DIR}/files/pcx.c
${REF_SRC_DIR}/files/stb.c
${REF_SRC_DIR}/files/wal.c
@ -615,14 +614,15 @@ set(GL3-Source
${COMMON_SRC_DIR}/md4.c
)
set(Glad-GL3-Source ${REF_SRC_DIR}/gl3/glad/src/glad.c)
set(Glad-GLES3-Source ${REF_SRC_DIR}/gl3/glad-gles3/src/glad.c)
set(GL3-Header
${REF_SRC_DIR}/ref_shared.h
${REF_SRC_DIR}/constants/anorms.h
${REF_SRC_DIR}/constants/anormtab.h
${REF_SRC_DIR}/constants/warpsin.h
${REF_SRC_DIR}/files/stb_image.h
${REF_SRC_DIR}/gl3/glad/include/glad/glad.h
${REF_SRC_DIR}/gl3/glad/include/KHR/khrplatform.h
${REF_SRC_DIR}/gl3/header/DG_dynarr.h
${REF_SRC_DIR}/gl3/header/HandmadeMath.h
${REF_SRC_DIR}/gl3/header/local.h
@ -630,6 +630,16 @@ set(GL3-Header
${COMMON_SRC_DIR}/header/shared.h
)
set(Glad-GL3-Header
${REF_SRC_DIR}/gl3/glad/include/glad/glad.h
${REF_SRC_DIR}/gl3/glad/include/KHR/khrplatform.h
)
set(Glad-GLES3-Header
${REF_SRC_DIR}/gl3/glad-gles3/include/glad/glad.h
${REF_SRC_DIR}/gl3/glad-gles3/include/KHR/khrplatform.h
)
set(SOFT-Source
${REF_SRC_DIR}/soft/sw_aclip.c
${REF_SRC_DIR}/soft/sw_alias.c
@ -750,7 +760,7 @@ set_target_properties(ref_gl1 PROPERTIES
target_link_libraries(ref_gl1 ${yquake2LinkerFlags} ${yquake2OpenGLLinkerFlags} ${yquake2SDLLinkerFlags})
# Build the GL3 dynamic library
add_library(ref_gl3 MODULE ${GL3-Source} ${GL3-Header} ${REF-Platform-Specific-Source})
add_library(ref_gl3 MODULE ${GL3-Source} ${Glad-GL3-Source} ${GL3-Header} ${Glad-GL3-Header} ${REF-Platform-Specific-Source})
set_target_properties(ref_gl3 PROPERTIES
PREFIX ""
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
@ -758,8 +768,23 @@ set_target_properties(ref_gl3 PROPERTIES
SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}
C_STANDARD 11
)
target_include_directories(ref_gl3 PRIVATE ${CMAKE_SOURCE_DIR}/src/client/refresh/gl3/glad/include)
target_link_libraries(ref_gl3 ${yquake2LinkerFlags} ${yquake2SDLLinkerFlags})
# Build the GLES3 dynamic library
add_library(ref_gles3 MODULE ${GL3-Source} ${Glad-GLES3-Source} ${GL3-Header} ${Glad-GLES3-Header} ${REF-Platform-Specific-Source})
set_target_properties(ref_gles3 PROPERTIES
PREFIX ""
#COMPILE_DEFINITIONS "YQ2_GL3_GLES3=1;YQ2_GL3_GLES=1"
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/release
SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}
C_STANDARD 11
)
target_include_directories(ref_gles3 PRIVATE ${CMAKE_SOURCE_DIR}/src/client/refresh/gl3/glad-gles3/include)
target_compile_definitions(ref_gles3 PRIVATE YQ2_GL3_GLES3=1 YQ2_GL3_GLES=1)
target_link_libraries(ref_gles3 ${yquake2LinkerFlags} ${yquake2SDLLinkerFlags})
# Build the soft renderer dynamic library
add_library(ref_soft MODULE ${SOFT-Source} ${SOFT-Header} ${REF-Platform-Specific-Source})
set_target_properties(ref_soft PROPERTIES

View file

@ -300,11 +300,6 @@ endif
# ----------
# Local includes for GLAD.
GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad/include
# ----------
# Base LDFLAGS. This is just the library path.
ifeq ($(YQ2_OSTYPE),Linux)
LDFLAGS ?= -L/usr/lib
@ -387,12 +382,12 @@ endif
# ----------
# Phony targets
.PHONY : all client game icon server ref_gl1 ref_gl3 ref_soft
.PHONY : all client game icon server ref_gl1 ref_gl3 ref_gles3 ref_soft
# ----------
# Builds everything
all: config client server game ref_gl1 ref_gl3 ref_soft
all: config client server game ref_gl1 ref_gl3 ref_gles3 ref_soft
# ----------
@ -618,6 +613,7 @@ ref_gl3:
@echo "===> Building ref_gl3.dll"
$(MAKE) release/ref_gl3.dll
release/ref_gl3.dll : GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad/include
release/ref_gl3.dll : LDFLAGS += -shared
else ifeq ($(YQ2_OSTYPE), Darwin)
@ -626,7 +622,7 @@ ref_gl3:
@echo "===> Building ref_gl3.dylib"
$(MAKE) release/ref_gl3.dylib
release/ref_gl3.dylib : GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad/include
release/ref_gl3.dylib : LDFLAGS += -shared
else # not Windows or Darwin
@ -635,7 +631,7 @@ ref_gl3:
@echo "===> Building ref_gl3.so"
$(MAKE) release/ref_gl3.so
release/ref_gl3.so : GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad/include
release/ref_gl3.so : CFLAGS += -fPIC
release/ref_gl3.so : LDFLAGS += -shared
@ -648,6 +644,61 @@ build/ref_gl3/%.o: %.c
# ----------
# The OpenGL ES 3.0 renderer lib
ifeq ($(YQ2_OSTYPE), Windows)
ref_gles3:
@echo "===> Building ref_gles3.dll"
$(MAKE) release/ref_gles3.dll
release/ref_gles3.dll : GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad-gles3/include
# YQ2_GL3_GLES3 is for GLES3, DYQ2_GL3_GLES is for things that are identical
# in both GLES3 and GLES2 (in case we ever support that)
release/ref_gles3.dll : CFLAGS += -DYQ2_GL3_GLES3 -DYQ2_GL3_GLES
release/ref_gles3.dll : LDFLAGS += -shared
else ifeq ($(YQ2_OSTYPE), Darwin)
ref_gles3:
@echo "===> Building ref_gles3.dylib"
$(MAKE) release/ref_gles3.dylib
release/ref_gles3.dylib : GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad-gles3/include
# YQ2_GL3_GLES3 is for GLES3, DYQ2_GL3_GLES is for things that are identical
# in both GLES3 and GLES2 (in case we ever support that)
release/ref_gles3.dylib : CFLAGS += -DYQ2_GL3_GLES3 -DYQ2_GL3_GLES
release/ref_gles3.dylib : LDFLAGS += -shared
else # not Windows or Darwin
ref_gles3:
@echo "===> Building ref_gles3.so"
$(MAKE) release/ref_gles3.so
release/ref_gles3.so : GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad-gles3/include
# YQ2_GL3_GLES3 is for GLES3, DYQ2_GL3_GLES is for things that are identical
# in both GLES3 and GLES2 (in case we ever support that)
release/ref_gles3.so : CFLAGS += -DYQ2_GL3_GLES3 -DYQ2_GL3_GLES -fPIC
release/ref_gles3.so : LDFLAGS += -shared
GLAD_INCLUDE = -Isrc/client/refresh/gl3/glad-gles3/include
endif # OS specific ref_gl3 stuff
build/ref_gles3/%.o: %.c
@echo "===> CC $<"
${Q}mkdir -p $(@D)
${Q}$(CC) -c $(CFLAGS) $(SDLCFLAGS) $(INCLUDE) $(GLAD_INCLUDE) -o $@ $<
# ----------
# The soft renderer lib
ifeq ($(YQ2_OSTYPE), Windows)
@ -680,7 +731,7 @@ endif # OS specific ref_soft stuff
build/ref_soft/%.o: %.c
@echo "===> CC $<"
${Q}mkdir -p $(@D)
${Q}$(CC) -c $(CFLAGS) $(SDLCFLAGS) $(INCLUDE) $(GLAD_INCLUDE) -o $@ $<
${Q}$(CC) -c $(CFLAGS) $(SDLCFLAGS) $(INCLUDE) -o $@ $<
# ----------
@ -915,7 +966,6 @@ REFGL3_OBJS_ := \
src/client/refresh/gl3/gl3_shaders.o \
src/client/refresh/gl3/gl3_md2.o \
src/client/refresh/gl3/gl3_sp2.o \
src/client/refresh/gl3/glad/src/glad.o \
src/client/refresh/files/pcx.o \
src/client/refresh/files/stb.o \
src/client/refresh/files/wal.o \
@ -923,6 +973,12 @@ REFGL3_OBJS_ := \
src/common/shared/shared.o \
src/common/md4.o
REFGL3_OBJS_GLADE_ := \
src/client/refresh/gl3/glad/src/glad.o
REFGL3_OBJS_GLADEES_ := \
src/client/refresh/gl3/glad-gles3/src/glad.o
ifeq ($(YQ2_OSTYPE), Windows)
REFGL3_OBJS_ += \
src/backends/windows/shared/hunk.o
@ -1023,6 +1079,9 @@ endif
CLIENT_OBJS = $(patsubst %,build/client/%,$(CLIENT_OBJS_))
REFGL1_OBJS = $(patsubst %,build/ref_gl1/%,$(REFGL1_OBJS_))
REFGL3_OBJS = $(patsubst %,build/ref_gl3/%,$(REFGL3_OBJS_))
REFGL3_OBJS += $(patsubst %,build/ref_gl3/%,$(REFGL3_OBJS_GLADE_))
REFGLES3_OBJS = $(patsubst %,build/ref_gles3/%,$(REFGL3_OBJS_))
REFGLES3_OBJS += $(patsubst %,build/ref_gles3/%,$(REFGL3_OBJS_GLADEES_))
REFSOFT_OBJS = $(patsubst %,build/ref_soft/%,$(REFSOFT_OBJS_))
SERVER_OBJS = $(patsubst %,build/server/%,$(SERVER_OBJS_))
GAME_OBJS = $(patsubst %,build/baseq2/%,$(GAME_OBJS_))
@ -1034,6 +1093,7 @@ CLIENT_DEPS= $(CLIENT_OBJS:.o=.d)
GAME_DEPS= $(GAME_OBJS:.o=.d)
REFGL1_DEPS= $(REFGL1_OBJS:.o=.d)
REFGL3_DEPS= $(REFGL3_OBJS:.o=.d)
REFGLES3_DEPS= $(REFGLES3_OBJS:.o=.d)
REFSOFT_DEPS= $(REFSOFT_OBJS:.o=.d)
SERVER_DEPS= $(SERVER_OBJS:.o=.d)
@ -1042,6 +1102,7 @@ SERVER_DEPS= $(SERVER_OBJS:.o=.d)
-include $(GAME_DEPS)
-include $(REFGL1_DEPS)
-include $(REFGL3_DEPS)
-include $(REFGLES3_DEPS)
-include $(SERVER_DEPS)
# ----------
@ -1105,6 +1166,22 @@ release/ref_gl3.so : $(REFGL3_OBJS)
${Q}$(CC) $(LDFLAGS) $(REFGL3_OBJS) $(LDLIBS) $(SDLLDFLAGS) -o $@
endif
# release/ref_gles3.so
ifeq ($(YQ2_OSTYPE), Windows)
release/ref_gles3.dll : $(REFGLES3_OBJS)
@echo "===> LD $@"
${Q}$(CC) $(LDFLAGS) $(REFGLES3_OBJS) $(LDLIBS) $(DLL_SDLLDFLAGS) -o $@
$(Q)strip $@
else ifeq ($(YQ2_OSTYPE), Darwin)
release/ref_gles3.dylib : $(REFGLES3_OBJS)
@echo "===> LD $@"
${Q}$(CC) $(LDFLAGS) $(REFGLES3_OBJS) $(LDLIBS) $(SDLLDFLAGS) -o $@
else
release/ref_gles3.so : $(REFGLES3_OBJS)
@echo "===> LD $@"
${Q}$(CC) $(LDFLAGS) $(REFGLES3_OBJS) $(LDLIBS) $(SDLLDFLAGS) -o $@
endif
# release/ref_soft.so
ifeq ($(YQ2_OSTYPE), Windows)
release/ref_soft.dll : $(REFSOFT_OBJS)

View file

@ -8,7 +8,7 @@ with the defaults and the options that can be set through the menu.
## Choosing a Renderer
Yamagi Quake II ships with 3 renderers:
Yamagi Quake II ships with 4 renderers:
* The **OpenGL 3.2** renderer: This renderer was developed for the needs
of modern graphics hardware and is usually the best choice for OpenGL
@ -17,6 +17,11 @@ Yamagi Quake II ships with 3 renderers:
rendering looks mostly the same on all GPU drivers. Depending on the
display, the default lighting may be too bright or too dark, it can be
adjusted through the menu or through the *vid_gamma* cvar.
* The **OpenGL ES3** renderer: This is pretty much the same as the
OpenGL 3.2 renderer (and uses the same cvars for configuration), but
uses OpenGL ES 3.0 instead of "desktop" OpenGL, so it also works on
the Raspberry Pi 4, for example. Reportedly it also has slightly
better performance on Wayland, at least with the open source AMD drivers.
* The **OpenGL 1.4** renderer: This is a slightly enhanced version of
the original OpenGL renderer shipped in 1997 with the retail release.
It's provided for older graphics cards, not able to run the OpenGL 3.2

View file

@ -9,7 +9,7 @@ have been renamed. The prefixes are:
* `cl_`: Client.
* `gl_`: Common to all OpenGL renderers.
* `gl1_`: OpenGL 1.4 renderer.
* `gl3_`: OpenGL 3.2 renderer.
* `gl3_`: OpenGL 3.2 and OpenGL ES3 renderers.
* `ogg_`: Ogg/Vorbis music playback.
* `r_`: Common to all renderers.
* `s_`: Sound system.
@ -349,7 +349,8 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
* **vid_renderer**: Selects the renderer library. Possible options are
`gl1` (the default) for the old OpenGL 1.4 renderer, `gl3` for the
OpenGL 3.2 renderer and `soft` for the software renderer.
OpenGL 3.2 renderer, `gles3` for the OpenGL ES3 renderer
and `soft` for the software renderer.
## Graphics (GL renderers only)
@ -388,7 +389,7 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
look a bit better (no flickering) by using the stencil buffer.
## Graphics (OpenGL 3.2 only)
## Graphics (OpenGL 3.2 and OpenGL ES3 only)
* **gl3_debugcontext**: Enables the OpenGL 3.2 renderers debug context,
e.g. prints warnings and errors emitted by the GPU driver. Not
@ -423,6 +424,11 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
colorless (greyscale-only), like in the original soft renderer.
Default is `1`.
* **gl3_usefbo**: When set to `1` (the default), an OpenGL Framebuffer
Object is used to implement a warping underwater-effect (like the
software renderer has). Set to `0` to disable this, in case you don't
like the effect or it's too slow on your machine.
## Graphics (Software only)

View file

@ -34,6 +34,7 @@ level.
# Renderer libraries:
/ref_gl1.dll
/ref_gl3.dll
/ref_gles3.dll
/ref_soft.dll
# The Executables:

View file

@ -63,8 +63,8 @@ static menuaction_s s_apply_action;
// --------
// gl1, gl3, vk, soft
#define MAXRENDERERS 4
// gl1, gl3, gles3, vk, soft
#define MAXRENDERERS 5
typedef struct
{
@ -94,6 +94,13 @@ Renderer_FillRenderdef(void)
rendererlist[numrenderer].cvarstr = "gl3";
}
if (VID_HasRenderer("gles3"))
{
numrenderer++;
rendererlist[numrenderer].boxstr = "[OpenGL ES3]";
rendererlist[numrenderer].cvarstr = "gles3";
}
if (VID_HasRenderer("vk"))
{
numrenderer++;

View file

@ -191,15 +191,11 @@ GL3_Upload32(unsigned *data, int width, int height, qboolean mipmap)
{
qboolean res;
int samples;
int i, c;
byte *scan;
int comp;
c = width * height;
scan = ((byte *)data) + 3;
samples = gl3_solid_format;
comp = gl3_tex_solid_format;
int i;
int c = width * height;
byte *scan = ((byte *)data) + 3;
int comp = gl3_tex_solid_format;
int samples = gl3_solid_format;
for (i = 0; i < c; i++, scan += 4)
{

View file

@ -35,8 +35,11 @@
#define DG_DYNARR_IMPLEMENTATION
#include "header/DG_dynarr.h"
#define REF_VERSION "Yamagi Quake II OpenGL3 Refresher"
#ifdef YQ2_GL3_GLES3
#define REF_VERSION "Yamagi Quake II OpenGL ES3 Refresher"
#else
#define REF_VERSION "Yamagi Quake II OpenGL3 Refresher"
#endif
refimport_t ri;
@ -961,7 +964,16 @@ GL3_DrawParticles(void)
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
#ifdef YQ2_GL3_GLES
// the RPi4 GLES3 implementation doesn't draw particles if culling is
// enabled (at least with GL_FRONT which seems to be default in q2?)
glDisable(GL_CULL_FACE);
#else
// GLES doesn't have this, maybe it's always enabled? (https://gamedev.stackexchange.com/a/15528 says it works)
// luckily we don't use glPointSize() but set gl_PointSize in shader anyway
glEnable(GL_PROGRAM_POINT_SIZE);
#endif
GL3_UseProgram(gl3state.siParticle.shaderProgram);
@ -976,7 +988,7 @@ GL3_DrawParticles(void)
cur->size = pointSize;
cur->dist = VectorLength(offset);
for(int j=0; j<3; ++j) cur->color[j] = color[j]/255.0f;
for(int j=0; j<3; ++j) cur->color[j] = color[j]*(1.0f/255.0f);
cur->color[3] = p->alpha;
}
@ -986,10 +998,14 @@ GL3_DrawParticles(void)
glBufferData(GL_ARRAY_BUFFER, sizeof(part_vtx)*numParticles, buf, GL_STREAM_DRAW);
glDrawArrays(GL_POINTS, 0, numParticles);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
#ifdef YQ2_GL3_GLES
if(gl_cull->value != 0.0f)
glEnable(GL_CULL_FACE);
#else
glDisable(GL_PROGRAM_POINT_SIZE);
#endif
YQ2_VLAFREE(buf);
}
@ -1306,6 +1322,7 @@ GL3_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zF
// the following emulates glFrustum(left, right, bottom, top, zNear, zFar)
// see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml
// or http://docs.gl/gl2/glFrustum#description (looks better in non-Firefox browsers)
A = (right+left)/(right-left);
B = (top+bottom)/(top-bottom);
C = -(zFar+zNear)/(zFar-zNear);
@ -1353,8 +1370,6 @@ SetupGL(void)
}
#endif // 0
// set up the FBO accordingly, but only if actually rendering the world
// (=> don't use FBO when rendering the playermodel in the player menu)
// also, only do this when under water, because this has a noticeable overhead on some systems
@ -1421,7 +1436,7 @@ SetupGL(void)
{
float screenaspect = (float)gl3_newrefdef.width / gl3_newrefdef.height;
float dist = (r_farsee->value == 0) ? 4096.0f : 8192.0f;
gl3state.uni3DData.transProjMat4 = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist);
gl3state.projMat3D = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist);
}
glCullFace(GL_FRONT);
@ -1430,7 +1445,7 @@ SetupGL(void)
{
// first put Z axis going up
hmm_mat4 viewMat = {{
{ 0, 0, -1, 0 }, // first *column* (the matrix is colum-major)
{ 0, 0, -1, 0 }, // first *column* (the matrix is column-major)
{ -1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 1 }
@ -1445,9 +1460,13 @@ SetupGL(void)
hmm_vec3 trans = HMM_Vec3(-gl3_newrefdef.vieworg[0], -gl3_newrefdef.vieworg[1], -gl3_newrefdef.vieworg[2]);
viewMat = HMM_MultiplyMat4( viewMat, HMM_Translate(trans) );
gl3state.uni3DData.transViewMat4 = viewMat;
gl3state.viewMat3D = viewMat;
}
// just use one projection-view-matrix (premultiplied here)
// so we have one less mat4 multiplication in the 3D shaders
gl3state.uni3DData.transProjViewMat4 = HMM_MultiplyMat4(gl3state.projMat3D, gl3state.viewMat3D);
gl3state.uni3DData.transModelMat4 = gl3_identityMat4;
gl3state.uni3DData.time = gl3_newrefdef.time;
@ -1859,18 +1878,23 @@ GL3_BeginFrame(float camera_separation)
{
gl_drawbuffer->modified = false;
#ifdef YQ2_GL3_GLES
// OpenGL ES3 only supports GL_NONE, GL_BACK and GL_COLOR_ATTACHMENT*
// so this doesn't make sense here, see https://docs.gl/es3/glDrawBuffers
R_Printf(PRINT_ALL, "NOTE: gl_drawbuffer not supported by OpenGL ES!\n");
#else // Desktop GL
// TODO: stereo stuff
//if ((gl3state.camera_separation == 0) || gl3state.stereo_mode != STEREO_MODE_OPENGL)
{
GLenum drawBuffer = GL_BACK;
if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
{
glDrawBuffer(GL_FRONT);
}
else
{
glDrawBuffer(GL_BACK);
drawBuffer = GL_FRONT;
}
glDrawBuffer(drawBuffer);
}
#endif
}
/* texturemode stuff */

View file

@ -650,7 +650,7 @@ GL3_DrawAliasModel(entity_t *entity)
vec3_t shadelight;
vec3_t shadevector;
gl3image_t *skin;
hmm_mat4 origProjMat = {0}; // use for left-handed rendering
hmm_mat4 origProjViewMat = {0}; // use for left-handed rendering
// used to restore ModelView matrix after changing it for this entities position/rotation
hmm_mat4 origModelMat = {0};
@ -817,19 +817,20 @@ GL3_DrawAliasModel(entity_t *entity)
{
extern hmm_mat4 GL3_MYgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
origProjMat = gl3state.uni3DData.transProjMat4;
origProjViewMat = gl3state.uni3DData.transProjViewMat4;
// render weapon with a different FOV (r_gunfov) so it's not distorted at high view FOV
float screenaspect = (float)gl3_newrefdef.width / gl3_newrefdef.height;
float dist = (r_farsee->value == 0) ? 4096.0f : 8192.0f;
hmm_mat4 projMat;
if (r_gunfov->value < 0)
{
gl3state.uni3DData.transProjMat4 = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist);
projMat = GL3_MYgluPerspective(gl3_newrefdef.fov_y, screenaspect, 4, dist);
}
else
{
gl3state.uni3DData.transProjMat4 = GL3_MYgluPerspective(r_gunfov->value, screenaspect, 4, dist);
projMat = GL3_MYgluPerspective(r_gunfov->value, screenaspect, 4, dist);
}
if(gl_lefthand->value == 1.0F)
@ -838,12 +839,13 @@ GL3_DrawAliasModel(entity_t *entity)
// of projection matrix
for(int i=0; i<4; ++i)
{
gl3state.uni3DData.transProjMat4.Elements[0][i] = -gl3state.uni3DData.transProjMat4.Elements[0][i];
projMat.Elements[0][i] = - projMat.Elements[0][i];
}
//GL3_UpdateUBO3D(); Note: GL3_RotateForEntity() will call this,no need to do it twice before drawing
glCullFace(GL_BACK);
}
gl3state.uni3DData.transProjViewMat4 = HMM_MultiplyMat4(projMat, gl3state.viewMat3D);
}
@ -916,7 +918,7 @@ GL3_DrawAliasModel(entity_t *entity)
if (entity->flags & RF_WEAPONMODEL)
{
gl3state.uni3DData.transProjMat4 = origProjMat;
gl3state.uni3DData.transProjViewMat4 = origProjViewMat;
GL3_UpdateUBO3D();
if(gl_lefthand->value == 1.0F)
glCullFace(GL_FRONT);

View file

@ -34,14 +34,22 @@ void
GL3_SetDefaultState(void)
{
glClearColor(1, 0, 0.5, 0.5);
#ifndef YQ2_GL3_GLES
// in GLES this is only supported with an extension:
// https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_multisample_compatibility.txt
// but apparently it's just enabled by default if set in the context?
glDisable(GL_MULTISAMPLE);
#endif
glCullFace(GL_FRONT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
#ifndef YQ2_GL3_GLES
// in GLES GL_FILL is the only supported mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// TODO: gl1_texturealphamode?
GL3_TextureMode(gl_texturemode->string);
@ -56,11 +64,13 @@ GL3_SetDefaultState(void)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifndef YQ2_GL3_GLES // see above
if (gl_msaa_samples->value)
{
glEnable(GL_MULTISAMPLE);
// glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); TODO what is this for?
}
#endif
}
static byte dottexture[8][8] = {
@ -115,7 +125,16 @@ void
GL3_ScreenShot(void)
{
int w=vid.width, h=vid.height;
byte *buffer = malloc(w*h*3);
#ifdef YQ2_GL3_GLES
// My RPi4's GLES3 doesn't like GL_RGB, so use GL_RGBA with GLES
// TODO: we could convert the screenshot to RGB before writing
// so the resulting file is smaller
static const int comps = 4;
#else // Desktop GL
static const int comps = 3;
#endif
byte *buffer = malloc(w*h*comps);
if (!buffer)
{
@ -124,13 +143,13 @@ GL3_ScreenShot(void)
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glReadPixels(0, 0, w, h, (comps == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, buffer);
// the pixels are now row-wise left to right, bottom to top,
// but we need them row-wise left to right, top to bottom.
// so swap bottom rows with top rows
{
size_t bytesPerRow = 3*w;
size_t bytesPerRow = comps*w;
YQ2_VLA(byte, rowBuffer, bytesPerRow);
byte *curRowL = buffer; // first byte of first row
byte *curRowH = buffer + bytesPerRow*(h-1); // first byte of last row
@ -146,7 +165,7 @@ GL3_ScreenShot(void)
YQ2_VLAFREE(rowBuffer);
}
ri.Vid_WriteScreenshot(w, h, 3, buffer);
ri.Vid_WriteScreenshot(w, h, comps, buffer);
free(buffer);
}

View file

@ -39,6 +39,7 @@ static qboolean vsyncActive = false;
enum {
// Not all GL.h header know about GL_DEBUG_SEVERITY_NOTIFICATION_*.
// DG: yes, it's the same value in GLES3.2
QGL_DEBUG_SEVERITY_NOTIFICATION = 0x826B
};
@ -55,17 +56,26 @@ DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei le
switch (severity)
{
case QGL_DEBUG_SEVERITY_NOTIFICATION:
return;
#ifdef YQ2_GL3_GLES
#define SVRCASE(X, STR) case GL_DEBUG_SEVERITY_ ## X ## _KHR : severityStr = STR; break;
#else // Desktop GL
#define SVRCASE(X, STR) case GL_DEBUG_SEVERITY_ ## X ## _ARB : severityStr = STR; break;
#endif
case GL_DEBUG_SEVERITY_HIGH_ARB: severityStr = "Severity: High"; break;
case GL_DEBUG_SEVERITY_MEDIUM_ARB: severityStr = "Severity: Medium"; break;
case GL_DEBUG_SEVERITY_LOW_ARB: severityStr = "Severity: Low"; break;
case QGL_DEBUG_SEVERITY_NOTIFICATION: return;
SVRCASE(HIGH, "Severity: High")
SVRCASE(MEDIUM, "Severity: Medium")
SVRCASE(LOW, "Severity: Low")
#undef SVRCASE
}
switch (source)
{
#define SRCCASE(X) case GL_DEBUG_SOURCE_ ## X ## _ARB: sourceStr = "Source: " #X; break;
#ifdef YQ2_GL3_GLES
#define SRCCASE(X) case GL_DEBUG_SOURCE_ ## X ## _KHR: sourceStr = "Source: " #X; break;
#else
#define SRCCASE(X) case GL_DEBUG_SOURCE_ ## X ## _ARB: sourceStr = "Source: " #X; break;
#endif
SRCCASE(API);
SRCCASE(WINDOW_SYSTEM);
SRCCASE(SHADER_COMPILER);
@ -77,7 +87,11 @@ DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei le
switch(type)
{
#define TYPECASE(X) case GL_DEBUG_TYPE_ ## X ## _ARB: typeStr = "Type: " #X; break;
#ifdef YQ2_GL3_GLES
#define TYPECASE(X) case GL_DEBUG_TYPE_ ## X ## _KHR: typeStr = "Type: " #X; break;
#else
#define TYPECASE(X) case GL_DEBUG_TYPE_ ## X ## _ARB: typeStr = "Type: " #X; break;
#endif
TYPECASE(ERROR);
TYPECASE(DEPRECATED_BEHAVIOR);
TYPECASE(UNDEFINED_BEHAVIOR);
@ -211,12 +225,22 @@ int GL3_PrepareForWindow(void)
gl3config.stencil = false;
}
#ifdef YQ2_GL3_GLES3
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#else // Desktop GL
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#endif
// Set GL context flags.
int contextFlags = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
int contextFlags = 0;
#ifndef YQ2_GL3_GLES // Desktop GL (at least RPi4 doesn't like this for GLES3)
contextFlags |= SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
#endif
if (gl3_debugcontext && gl3_debugcontext->value)
{
@ -317,13 +341,21 @@ int GL3_InitContext(void* win)
GL3_SetVsync();
// Load GL pointrs through GLAD and check context.
#ifdef YQ2_GL3_GLES
if( !gladLoadGLES2Loader(SDL_GL_GetProcAddress))
#else // Desktop GL
if( !gladLoadGLLoader(SDL_GL_GetProcAddress))
#endif
{
R_Printf(PRINT_ALL, "GL3_InitContext(): ERROR: loading OpenGL function pointers failed!\n");
return false;
}
#ifdef YQ2_GL3_GLES3
else if (GLVersion.major < 3)
#else // Desktop GL
else if (GLVersion.major < 3 || (GLVersion.major == 3 && GLVersion.minor < 2))
#endif
{
R_Printf(PRINT_ALL, "GL3_InitContext(): ERROR: glad only got GL version %d.%d!\n", GLVersion.major, GLVersion.minor);
@ -334,7 +366,11 @@ int GL3_InitContext(void* win)
R_Printf(PRINT_ALL, "Successfully loaded OpenGL function pointers using glad, got version %d.%d!\n", GLVersion.major, GLVersion.minor);
}
#ifdef YQ2_GL3_GLES
gl3config.debug_output = GLAD_GL_KHR_debug != 0;
#else // Desktop GL
gl3config.debug_output = GLAD_GL_ARB_debug_output != 0;
#endif
gl3config.anisotropic = GLAD_GL_EXT_texture_filter_anisotropic != 0;
gl3config.major_version = GLVersion.major;
@ -343,17 +379,25 @@ int GL3_InitContext(void* win)
// Debug context setup.
if (gl3_debugcontext && gl3_debugcontext->value && gl3config.debug_output)
{
glDebugMessageCallbackARB(DebugCallback, NULL);
#ifdef YQ2_GL3_GLES
glDebugMessageCallbackKHR(DebugCallback, NULL);
// Call GL3_DebugCallback() synchronously, i.e. directly when and
// where the error happens (so we can get the cause in a backtrace)
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
#else // Desktop GL
glDebugMessageCallbackARB(DebugCallback, NULL);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
#endif
}
// Window title - set here so we can display renderer name in it.
char title[40] = {0};
#ifdef YQ2_GL3_GLES3
snprintf(title, sizeof(title), "Yamagi Quake II %s - OpenGL ES 3.0", YQ2VERSION);
#else
snprintf(title, sizeof(title), "Yamagi Quake II %s - OpenGL 3.2", YQ2VERSION);
#endif
SDL_SetWindowTitle(window, title);
return true;

View file

@ -36,8 +36,13 @@ CompileShader(GLenum shaderType, const char* shaderSrc, const char* shaderSrc2)
{
GLuint shader = glCreateShader(shaderType);
const char* sources[2] = { shaderSrc, shaderSrc2 };
int numSources = shaderSrc2 != NULL ? 2 : 1;
#ifdef YQ2_GL3_GLES3
const char* version = "#version 300 es\nprecision mediump float;\n";
#else // Desktop GL
const char* version = "#version 150\n";
#endif
const char* sources[3] = { version, shaderSrc, shaderSrc2 };
int numSources = shaderSrc2 != NULL ? 3 : 2;
glShaderSource(shader, numSources, sources, NULL);
glCompileShader(shader);
@ -69,7 +74,8 @@ CompileShader(GLenum shaderType, const char* shaderSrc, const char* shaderSrc2)
{
case GL_VERTEX_SHADER: shaderTypeStr = "Vertex"; break;
case GL_FRAGMENT_SHADER: shaderTypeStr = "Fragment"; break;
case GL_GEOMETRY_SHADER: shaderTypeStr = "Geometry"; break;
// we don't use geometry shaders and GLES3.0 doesn't support them
// case GL_GEOMETRY_SHADER: shaderTypeStr = "Geometry"; break;
/* not supported in OpenGL3.2 and we're unlikely to need/use them anyway
case GL_COMPUTE_SHADER: shaderTypeStr = "Compute"; break;
case GL_TESS_CONTROL_SHADER: shaderTypeStr = "TessControl"; break;
@ -163,7 +169,7 @@ CreateShaderProgram(int numShaders, const GLuint* shaders)
// ############## shaders for 2D rendering (HUD, menus, console, videos, ..) #####################
static const char* vertexSrc2D = MULTILINE_STRING(#version 150\n
static const char* vertexSrc2D = MULTILINE_STRING(
in vec2 position; // GL3_ATTRIB_POSITION
in vec2 texCoord; // GL3_ATTRIB_TEXCOORD
@ -183,7 +189,7 @@ static const char* vertexSrc2D = MULTILINE_STRING(#version 150\n
}
);
static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n
static const char* fragmentSrc2D = MULTILINE_STRING(
in vec2 passTexCoord;
@ -217,7 +223,7 @@ static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n
}
);
static const char* fragmentSrc2Dpostprocess = MULTILINE_STRING(#version 150\n
static const char* fragmentSrc2Dpostprocess = MULTILINE_STRING(
in vec2 passTexCoord;
// for UBO shared between all shaders (incl. 2D)
@ -248,7 +254,7 @@ static const char* fragmentSrc2Dpostprocess = MULTILINE_STRING(#version 150\n
}
);
static const char* fragmentSrc2DpostprocessWater = MULTILINE_STRING(#version 150\n
static const char* fragmentSrc2DpostprocessWater = MULTILINE_STRING(
in vec2 passTexCoord;
// for UBO shared between all shaders (incl. 2D)
@ -281,8 +287,8 @@ static const char* fragmentSrc2DpostprocessWater = MULTILINE_STRING(#version 150
//float sy = pc.scale - abs(pc.scrHeight / 2.0 - gl_FragCoord.y) * 2.0 / pc.scrHeight;
float sx = 1.0 - abs(0.5-uv.x)*2.0;
float sy = 1.0 - abs(0.5-uv.y)*2.0;
float xShift = 2.0 * time + uv.y * PI * 10;
float yShift = 2.0 * time + uv.x * PI * 10;
float xShift = 2.0 * time + uv.y * PI * 10.0;
float yShift = 2.0 * time + uv.x * PI * 10.0;
vec2 distortion = vec2(sin(xShift) * sx, sin(yShift) * sy) * 0.00666;
uv += distortion;
@ -299,7 +305,7 @@ static const char* fragmentSrc2DpostprocessWater = MULTILINE_STRING(#version 150
);
// 2D color only rendering, GL3_Draw_Fill(), GL3_Draw_FadeScreen()
static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n
static const char* vertexSrc2Dcolor = MULTILINE_STRING(
in vec2 position; // GL3_ATTRIB_POSITION
@ -315,7 +321,7 @@ static const char* vertexSrc2Dcolor = MULTILINE_STRING(#version 150\n
}
);
static const char* fragmentSrc2Dcolor = MULTILINE_STRING(#version 150\n
static const char* fragmentSrc2Dcolor = MULTILINE_STRING(
// for UBO shared between all shaders (incl. 2D)
layout (std140) uniform uniCommon
@ -339,7 +345,7 @@ static const char* fragmentSrc2Dcolor = MULTILINE_STRING(#version 150\n
// ############## shaders for 3D rendering #####################
static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n
static const char* vertexCommon3D = MULTILINE_STRING(
in vec3 position; // GL3_ATTRIB_POSITION
in vec2 texCoord; // GL3_ATTRIB_TEXCOORD
@ -353,8 +359,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n
// for UBO shared between all 3D shaders
layout (std140) uniform uni3D
{
mat4 transProj;
mat4 transView;
mat4 transProjView;
mat4 transModel;
float scroll; // for SURF_FLOWING
@ -368,7 +373,7 @@ static const char* vertexCommon3D = MULTILINE_STRING(#version 150\n
};
);
static const char* fragmentCommon3D = MULTILINE_STRING(#version 150\n
static const char* fragmentCommon3D = MULTILINE_STRING(
in vec2 passTexCoord;
@ -382,13 +387,11 @@ static const char* fragmentCommon3D = MULTILINE_STRING(#version 150\n
float intensity2D; // for HUD, menus etc
vec4 color; // really?
};
// for UBO shared between all 3D shaders
layout (std140) uniform uni3D
{
mat4 transProj;
mat4 transView;
mat4 transProjView;
mat4 transModel;
float scroll; // for SURF_FLOWING
@ -409,7 +412,7 @@ static const char* vertexSrc3D = MULTILINE_STRING(
void main()
{
passTexCoord = texCoord;
gl_Position = transProj * transView * transModel * vec4(position, 1.0);
gl_Position = transProjView * transModel * vec4(position, 1.0);
}
);
@ -419,8 +422,8 @@ static const char* vertexSrc3Dflow = MULTILINE_STRING(
void main()
{
passTexCoord = texCoord + vec2(scroll, 0);
gl_Position = transProj * transView * transModel * vec4(position, 1.0);
passTexCoord = texCoord + vec2(scroll, 0.0);
gl_Position = transProjView * transModel * vec4(position, 1.0);
}
);
@ -443,7 +446,7 @@ static const char* vertexSrc3Dlm = MULTILINE_STRING(
passNormal = normalize(worldNormal.xyz);
passLightFlags = lightFlags;
gl_Position = transProj * transView * worldCoord;
gl_Position = transProjView * worldCoord;
}
);
@ -458,7 +461,7 @@ static const char* vertexSrc3DlmFlow = MULTILINE_STRING(
void main()
{
passTexCoord = texCoord + vec2(scroll, 0);
passTexCoord = texCoord + vec2(scroll, 0.0);
passLMcoord = lmTexCoord;
vec4 worldCoord = transModel * vec4(position, 1.0);
passWorldCoord = worldCoord.xyz;
@ -466,7 +469,7 @@ static const char* vertexSrc3DlmFlow = MULTILINE_STRING(
passNormal = normalize(worldNormal.xyz);
passLightFlags = lightFlags;
gl_Position = transProj * transView * worldCoord;
gl_Position = transProjView * worldCoord;
}
);
@ -496,9 +499,9 @@ static const char* fragmentSrc3Dwater = MULTILINE_STRING(
void main()
{
vec2 tc = passTexCoord;
tc.s += sin( passTexCoord.t*0.125 + time ) * 4;
tc.s += sin( passTexCoord.t*0.125 + time ) * 4.0;
tc.s += scroll;
tc.t += sin( passTexCoord.s*0.125 + time ) * 4;
tc.t += sin( passTexCoord.s*0.125 + time ) * 4.0;
tc *= 1.0/64.0; // do this last
vec4 texel = texture(tex, tc);
@ -573,7 +576,7 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING(
vec3 lightToPos = dynLights[i].lightOrigin - passWorldCoord;
float distLightToPos = length(lightToPos);
float fact = max(0, intens - distLightToPos - 52);
float fact = max(0.0, intens - distLightToPos - 52.0);
// move the light source a bit further above the surface
// => helps if the lightsource is so close to the surface (e.g. grenades, rockets)
@ -582,7 +585,7 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING(
lightToPos += passNormal*32.0;
// also factor in angle between light and point on surface
fact *= max(0, dot(passNormal, normalize(lightToPos)));
fact *= max(0.0, dot(passNormal, normalize(lightToPos)));
lmTex.rgb += dynLights[i].lightColor.rgb * fact * (1.0/256.0);
@ -593,7 +596,7 @@ static const char* fragmentSrc3Dlm = MULTILINE_STRING(
outColor = lmTex*texel;
outColor.rgb = pow(outColor.rgb, vec3(gamma)); // apply gamma correction to result
outColor.a = 1; // lightmaps aren't used with translucent surfaces
outColor.a = 1.0; // lightmaps aren't used with translucent surfaces
}
);
@ -660,7 +663,7 @@ static const char* fragmentSrc3DlmNoColor = MULTILINE_STRING(
vec3 lightToPos = dynLights[i].lightOrigin - passWorldCoord;
float distLightToPos = length(lightToPos);
float fact = max(0, intens - distLightToPos - 52);
float fact = max(0.0, intens - distLightToPos - 52.0);
// move the light source a bit further above the surface
// => helps if the lightsource is so close to the surface (e.g. grenades, rockets)
@ -669,7 +672,7 @@ static const char* fragmentSrc3DlmNoColor = MULTILINE_STRING(
lightToPos += passNormal*32.0;
// also factor in angle between light and point on surface
fact *= max(0, dot(passNormal, normalize(lightToPos)));
fact *= max(0.0, dot(passNormal, normalize(lightToPos)));
lmTex.rgb += dynLights[i].lightColor.rgb * fact * (1.0/256.0);
@ -765,7 +768,7 @@ static const char* vertexSrc3Dwater = MULTILINE_STRING(
{
passTexCoord = texCoord;
gl_Position = transProj * transView * transModel * vec4(position, 1.0);
gl_Position = transProjView * transModel * vec4(position, 1.0);
}
);
@ -779,7 +782,7 @@ static const char* vertexSrcAlias = MULTILINE_STRING(
{
passColor = vertColor*overbrightbits;
passTexCoord = texCoord;
gl_Position = transProj * transView * transModel * vec4(position, 1.0);
gl_Position = transProjView* transModel * vec4(position, 1.0);
}
);
@ -832,7 +835,7 @@ static const char* vertexSrcParticles = MULTILINE_STRING(
void main()
{
passColor = vertColor;
gl_Position = transProj * transView * transModel * vec4(position, 1.0);
gl_Position = transProjView * transModel * vec4(position, 1.0);
// abusing texCoord for pointSize, pointDist for particles
float pointDist = texCoord.y*0.1; // with factor 0.1 it looks good.
@ -1161,8 +1164,7 @@ static void initUBOs(void)
glBufferData(GL_UNIFORM_BUFFER, sizeof(gl3state.uni2DData), &gl3state.uni2DData, GL_DYNAMIC_DRAW);
// the matrices will be set to something more useful later, before being used
gl3state.uni3DData.transProjMat4 = HMM_Mat4();
gl3state.uni3DData.transViewMat4 = HMM_Mat4();
gl3state.uni3DData.transProjViewMat4 = HMM_Mat4();
gl3state.uni3DData.transModelMat4 = gl3_identityMat4;
gl3state.uni3DData.scroll = 0.0f;
gl3state.uni3DData.time = 0.0f;

View file

@ -26,6 +26,7 @@
*/
#include <assert.h>
#include <stddef.h> // ofsetof()
#include "header/local.h"

View file

@ -0,0 +1,290 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(KHRONOS_STATIC)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef _WIN64
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,741 @@
/*
OpenGL ES loader generated by glad 0.1.33 on Sun Feb 23 03:46:49 2020.
Language/Generator: C/C++
Specification: gl
APIs: gles2=3.0
Profile: core
Extensions:
GL_EXT_texture_filter_anisotropic,
GL_KHR_debug
Loader: False
Local files: False
Omit khrplatform: False
Reproducible: False
Commandline:
--profile="core" --api="gles2=3.0" --generator="c" --spec="gl" --no-loader --extensions="GL_EXT_texture_filter_anisotropic,GL_KHR_debug"
Online:
https://glad.dav1d.de/#profile=core&language=c&specification=gl&api=gles2%3D3.0&extensions=GL_EXT_texture_filter_anisotropic&extensions=GL_KHR_debug
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glad/glad.h>
struct gladGLversionStruct GLVersion = { 0, 0 };
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
#define _GLAD_IS_SOME_NEW_VERSION 1
#endif
static int max_loaded_major;
static int max_loaded_minor;
static const char *exts = NULL;
static int num_exts_i = 0;
static char **exts_i = NULL;
static int get_exts(void) {
#ifdef _GLAD_IS_SOME_NEW_VERSION
if(max_loaded_major < 3) {
#endif
exts = (const char *)glGetString(GL_EXTENSIONS);
#ifdef _GLAD_IS_SOME_NEW_VERSION
} else {
unsigned int index;
num_exts_i = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
if (num_exts_i > 0) {
exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i));
}
if (exts_i == NULL) {
return 0;
}
for(index = 0; index < (unsigned)num_exts_i; index++) {
const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index);
size_t len = strlen(gl_str_tmp);
char *local_str = (char*)malloc((len+1) * sizeof(char));
if(local_str != NULL) {
memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char));
}
exts_i[index] = local_str;
}
}
#endif
return 1;
}
static void free_exts(void) {
if (exts_i != NULL) {
int index;
for(index = 0; index < num_exts_i; index++) {
free((char *)exts_i[index]);
}
free((void *)exts_i);
exts_i = NULL;
}
}
static int has_ext(const char *ext) {
#ifdef _GLAD_IS_SOME_NEW_VERSION
if(max_loaded_major < 3) {
#endif
const char *extensions;
const char *loc;
const char *terminator;
extensions = exts;
if(extensions == NULL || ext == NULL) {
return 0;
}
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL) {
return 0;
}
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\0')) {
return 1;
}
extensions = terminator;
}
#ifdef _GLAD_IS_SOME_NEW_VERSION
} else {
int index;
if(exts_i == NULL) return 0;
for(index = 0; index < num_exts_i; index++) {
const char *e = exts_i[index];
if(exts_i[index] != NULL && strcmp(e, ext) == 0) {
return 1;
}
}
}
#endif
return 0;
}
int GLAD_GL_ES_VERSION_2_0 = 0;
int GLAD_GL_ES_VERSION_3_0 = 0;
PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL;
PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
PFNGLCLEARPROC glad_glClear = NULL;
PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
PFNGLCOLORMASKPROC glad_glColorMask = NULL;
PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
PFNGLCULLFACEPROC glad_glCullFace = NULL;
PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks = NULL;
PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
PFNGLDISABLEPROC glad_glDisable = NULL;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
PFNGLENABLEPROC glad_glEnable = NULL;
PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
PFNGLENDQUERYPROC glad_glEndQuery = NULL;
PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
PFNGLFINISHPROC glad_glFinish = NULL;
PFNGLFLUSHPROC glad_glFlush = NULL;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL;
PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
PFNGLGETERRORPROC glad_glGetError = NULL;
PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL;
PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary = NULL;
PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL;
PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
PFNGLGETSTRINGPROC glad_glGetString = NULL;
PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
PFNGLHINTPROC glad_glHint = NULL;
PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL;
PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL;
PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
PFNGLISQUERYPROC glad_glIsQuery = NULL;
PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
PFNGLISSHADERPROC glad_glIsShader = NULL;
PFNGLISSYNCPROC glad_glIsSync = NULL;
PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback = NULL;
PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback = NULL;
PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
PFNGLPROGRAMBINARYPROC glad_glProgramBinary = NULL;
PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri = NULL;
PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL;
PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback = NULL;
PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
PFNGLSCISSORPROC glad_glScissor = NULL;
PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D = NULL;
PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D = NULL;
PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
PFNGLVIEWPORTPROC glad_glViewport = NULL;
PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
int GLAD_GL_EXT_texture_filter_anisotropic = 0;
int GLAD_GL_KHR_debug = 0;
PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL;
PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL;
PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL;
PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR = NULL;
PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR = NULL;
PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR = NULL;
PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR = NULL;
PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR = NULL;
PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR = NULL;
PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR = NULL;
PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR = NULL;
PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR = NULL;
PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR = NULL;
PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR = NULL;
static void load_GL_ES_VERSION_2_0(GLADloadproc load) {
if(!GLAD_GL_ES_VERSION_2_0) return;
glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC)load("glActiveTexture");
glad_glAttachShader = (PFNGLATTACHSHADERPROC)load("glAttachShader");
glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)load("glBindAttribLocation");
glad_glBindBuffer = (PFNGLBINDBUFFERPROC)load("glBindBuffer");
glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer");
glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer");
glad_glBindTexture = (PFNGLBINDTEXTUREPROC)load("glBindTexture");
glad_glBlendColor = (PFNGLBLENDCOLORPROC)load("glBlendColor");
glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC)load("glBlendEquation");
glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)load("glBlendEquationSeparate");
glad_glBlendFunc = (PFNGLBLENDFUNCPROC)load("glBlendFunc");
glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)load("glBlendFuncSeparate");
glad_glBufferData = (PFNGLBUFFERDATAPROC)load("glBufferData");
glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC)load("glBufferSubData");
glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus");
glad_glClear = (PFNGLCLEARPROC)load("glClear");
glad_glClearColor = (PFNGLCLEARCOLORPROC)load("glClearColor");
glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC)load("glClearDepthf");
glad_glClearStencil = (PFNGLCLEARSTENCILPROC)load("glClearStencil");
glad_glColorMask = (PFNGLCOLORMASKPROC)load("glColorMask");
glad_glCompileShader = (PFNGLCOMPILESHADERPROC)load("glCompileShader");
glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)load("glCompressedTexImage2D");
glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)load("glCompressedTexSubImage2D");
glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)load("glCopyTexImage2D");
glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)load("glCopyTexSubImage2D");
glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC)load("glCreateProgram");
glad_glCreateShader = (PFNGLCREATESHADERPROC)load("glCreateShader");
glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)load("glDeleteBuffers");
glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers");
glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC)load("glDeleteProgram");
glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers");
glad_glDeleteShader = (PFNGLDELETESHADERPROC)load("glDeleteShader");
glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC)load("glDeleteTextures");
glad_glDepthFunc = (PFNGLDEPTHFUNCPROC)load("glDepthFunc");
glad_glDepthMask = (PFNGLDEPTHMASKPROC)load("glDepthMask");
glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC)load("glDepthRangef");
glad_glDetachShader = (PFNGLDETACHSHADERPROC)load("glDetachShader");
glad_glDisable = (PFNGLDISABLEPROC)load("glDisable");
glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)load("glDisableVertexAttribArray");
glad_glDrawArrays = (PFNGLDRAWARRAYSPROC)load("glDrawArrays");
glad_glDrawElements = (PFNGLDRAWELEMENTSPROC)load("glDrawElements");
glad_glEnable = (PFNGLENABLEPROC)load("glEnable");
glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)load("glEnableVertexAttribArray");
glad_glFinish = (PFNGLFINISHPROC)load("glFinish");
glad_glFlush = (PFNGLFLUSHPROC)load("glFlush");
glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer");
glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D");
glad_glFrontFace = (PFNGLFRONTFACEPROC)load("glFrontFace");
glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers");
glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap");
glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers");
glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers");
glad_glGenTextures = (PFNGLGENTEXTURESPROC)load("glGenTextures");
glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)load("glGetActiveAttrib");
glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)load("glGetActiveUniform");
glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)load("glGetAttachedShaders");
glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)load("glGetAttribLocation");
glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC)load("glGetBooleanv");
glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv");
glad_glGetError = (PFNGLGETERRORPROC)load("glGetError");
glad_glGetFloatv = (PFNGLGETFLOATVPROC)load("glGetFloatv");
glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv");
glad_glGetIntegerv = (PFNGLGETINTEGERVPROC)load("glGetIntegerv");
glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)load("glGetProgramiv");
glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)load("glGetProgramInfoLog");
glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv");
glad_glGetShaderiv = (PFNGLGETSHADERIVPROC)load("glGetShaderiv");
glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)load("glGetShaderInfoLog");
glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)load("glGetShaderPrecisionFormat");
glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)load("glGetShaderSource");
glad_glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)load("glGetTexParameterfv");
glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)load("glGetTexParameteriv");
glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC)load("glGetUniformfv");
glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC)load("glGetUniformiv");
glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)load("glGetUniformLocation");
glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)load("glGetVertexAttribfv");
glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)load("glGetVertexAttribiv");
glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)load("glGetVertexAttribPointerv");
glad_glHint = (PFNGLHINTPROC)load("glHint");
glad_glIsBuffer = (PFNGLISBUFFERPROC)load("glIsBuffer");
glad_glIsEnabled = (PFNGLISENABLEDPROC)load("glIsEnabled");
glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer");
glad_glIsProgram = (PFNGLISPROGRAMPROC)load("glIsProgram");
glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
glad_glIsShader = (PFNGLISSHADERPROC)load("glIsShader");
glad_glIsTexture = (PFNGLISTEXTUREPROC)load("glIsTexture");
glad_glLineWidth = (PFNGLLINEWIDTHPROC)load("glLineWidth");
glad_glLinkProgram = (PFNGLLINKPROGRAMPROC)load("glLinkProgram");
glad_glPixelStorei = (PFNGLPIXELSTOREIPROC)load("glPixelStorei");
glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC)load("glPolygonOffset");
glad_glReadPixels = (PFNGLREADPIXELSPROC)load("glReadPixels");
glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)load("glReleaseShaderCompiler");
glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage");
glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)load("glSampleCoverage");
glad_glScissor = (PFNGLSCISSORPROC)load("glScissor");
glad_glShaderBinary = (PFNGLSHADERBINARYPROC)load("glShaderBinary");
glad_glShaderSource = (PFNGLSHADERSOURCEPROC)load("glShaderSource");
glad_glStencilFunc = (PFNGLSTENCILFUNCPROC)load("glStencilFunc");
glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)load("glStencilFuncSeparate");
glad_glStencilMask = (PFNGLSTENCILMASKPROC)load("glStencilMask");
glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)load("glStencilMaskSeparate");
glad_glStencilOp = (PFNGLSTENCILOPPROC)load("glStencilOp");
glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)load("glStencilOpSeparate");
glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC)load("glTexImage2D");
glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC)load("glTexParameterf");
glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)load("glTexParameterfv");
glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC)load("glTexParameteri");
glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)load("glTexParameteriv");
glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)load("glTexSubImage2D");
glad_glUniform1f = (PFNGLUNIFORM1FPROC)load("glUniform1f");
glad_glUniform1fv = (PFNGLUNIFORM1FVPROC)load("glUniform1fv");
glad_glUniform1i = (PFNGLUNIFORM1IPROC)load("glUniform1i");
glad_glUniform1iv = (PFNGLUNIFORM1IVPROC)load("glUniform1iv");
glad_glUniform2f = (PFNGLUNIFORM2FPROC)load("glUniform2f");
glad_glUniform2fv = (PFNGLUNIFORM2FVPROC)load("glUniform2fv");
glad_glUniform2i = (PFNGLUNIFORM2IPROC)load("glUniform2i");
glad_glUniform2iv = (PFNGLUNIFORM2IVPROC)load("glUniform2iv");
glad_glUniform3f = (PFNGLUNIFORM3FPROC)load("glUniform3f");
glad_glUniform3fv = (PFNGLUNIFORM3FVPROC)load("glUniform3fv");
glad_glUniform3i = (PFNGLUNIFORM3IPROC)load("glUniform3i");
glad_glUniform3iv = (PFNGLUNIFORM3IVPROC)load("glUniform3iv");
glad_glUniform4f = (PFNGLUNIFORM4FPROC)load("glUniform4f");
glad_glUniform4fv = (PFNGLUNIFORM4FVPROC)load("glUniform4fv");
glad_glUniform4i = (PFNGLUNIFORM4IPROC)load("glUniform4i");
glad_glUniform4iv = (PFNGLUNIFORM4IVPROC)load("glUniform4iv");
glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)load("glUniformMatrix2fv");
glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)load("glUniformMatrix3fv");
glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)load("glUniformMatrix4fv");
glad_glUseProgram = (PFNGLUSEPROGRAMPROC)load("glUseProgram");
glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)load("glValidateProgram");
glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)load("glVertexAttrib1f");
glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)load("glVertexAttrib1fv");
glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)load("glVertexAttrib2f");
glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)load("glVertexAttrib2fv");
glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)load("glVertexAttrib3f");
glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)load("glVertexAttrib3fv");
glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)load("glVertexAttrib4f");
glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)load("glVertexAttrib4fv");
glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)load("glVertexAttribPointer");
glad_glViewport = (PFNGLVIEWPORTPROC)load("glViewport");
}
static void load_GL_ES_VERSION_3_0(GLADloadproc load) {
if(!GLAD_GL_ES_VERSION_3_0) return;
glad_glReadBuffer = (PFNGLREADBUFFERPROC)load("glReadBuffer");
glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)load("glDrawRangeElements");
glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC)load("glTexImage3D");
glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)load("glTexSubImage3D");
glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)load("glCopyTexSubImage3D");
glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)load("glCompressedTexImage3D");
glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)load("glCompressedTexSubImage3D");
glad_glGenQueries = (PFNGLGENQUERIESPROC)load("glGenQueries");
glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC)load("glDeleteQueries");
glad_glIsQuery = (PFNGLISQUERYPROC)load("glIsQuery");
glad_glBeginQuery = (PFNGLBEGINQUERYPROC)load("glBeginQuery");
glad_glEndQuery = (PFNGLENDQUERYPROC)load("glEndQuery");
glad_glGetQueryiv = (PFNGLGETQUERYIVPROC)load("glGetQueryiv");
glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)load("glGetQueryObjectuiv");
glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)load("glUnmapBuffer");
glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv");
glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)load("glDrawBuffers");
glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)load("glUniformMatrix2x3fv");
glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)load("glUniformMatrix3x2fv");
glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)load("glUniformMatrix2x4fv");
glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)load("glUniformMatrix4x2fv");
glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)load("glUniformMatrix3x4fv");
glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)load("glUniformMatrix4x3fv");
glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer");
glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)load("glMapBufferRange");
glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)load("glFlushMappedBufferRange");
glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)load("glBindVertexArray");
glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)load("glDeleteVertexArrays");
glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)load("glGenVertexArrays");
glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC)load("glIsVertexArray");
glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)load("glBeginTransformFeedback");
glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)load("glEndTransformFeedback");
glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)load("glTransformFeedbackVaryings");
glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)load("glGetTransformFeedbackVarying");
glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)load("glVertexAttribIPointer");
glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)load("glGetVertexAttribIiv");
glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)load("glGetVertexAttribIuiv");
glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)load("glVertexAttribI4i");
glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)load("glVertexAttribI4ui");
glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)load("glVertexAttribI4iv");
glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)load("glVertexAttribI4uiv");
glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)load("glGetUniformuiv");
glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)load("glGetFragDataLocation");
glad_glUniform1ui = (PFNGLUNIFORM1UIPROC)load("glUniform1ui");
glad_glUniform2ui = (PFNGLUNIFORM2UIPROC)load("glUniform2ui");
glad_glUniform3ui = (PFNGLUNIFORM3UIPROC)load("glUniform3ui");
glad_glUniform4ui = (PFNGLUNIFORM4UIPROC)load("glUniform4ui");
glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC)load("glUniform1uiv");
glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC)load("glUniform2uiv");
glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC)load("glUniform3uiv");
glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC)load("glUniform4uiv");
glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)load("glClearBufferiv");
glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)load("glClearBufferuiv");
glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)load("glClearBufferfv");
glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)load("glClearBufferfi");
glad_glGetStringi = (PFNGLGETSTRINGIPROC)load("glGetStringi");
glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)load("glCopyBufferSubData");
glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)load("glGetUniformIndices");
glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)load("glGetActiveUniformsiv");
glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)load("glGetUniformBlockIndex");
glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)load("glGetActiveUniformBlockiv");
glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)load("glGetActiveUniformBlockName");
glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)load("glUniformBlockBinding");
glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)load("glDrawArraysInstanced");
glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)load("glDrawElementsInstanced");
glad_glFenceSync = (PFNGLFENCESYNCPROC)load("glFenceSync");
glad_glIsSync = (PFNGLISSYNCPROC)load("glIsSync");
glad_glDeleteSync = (PFNGLDELETESYNCPROC)load("glDeleteSync");
glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)load("glClientWaitSync");
glad_glWaitSync = (PFNGLWAITSYNCPROC)load("glWaitSync");
glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC)load("glGetInteger64v");
glad_glGetSynciv = (PFNGLGETSYNCIVPROC)load("glGetSynciv");
glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)load("glGetInteger64i_v");
glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)load("glGetBufferParameteri64v");
glad_glGenSamplers = (PFNGLGENSAMPLERSPROC)load("glGenSamplers");
glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)load("glDeleteSamplers");
glad_glIsSampler = (PFNGLISSAMPLERPROC)load("glIsSampler");
glad_glBindSampler = (PFNGLBINDSAMPLERPROC)load("glBindSampler");
glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)load("glSamplerParameteri");
glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)load("glSamplerParameteriv");
glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)load("glSamplerParameterf");
glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)load("glSamplerParameterfv");
glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)load("glGetSamplerParameteriv");
glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)load("glGetSamplerParameterfv");
glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)load("glVertexAttribDivisor");
glad_glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC)load("glBindTransformFeedback");
glad_glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC)load("glDeleteTransformFeedbacks");
glad_glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC)load("glGenTransformFeedbacks");
glad_glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC)load("glIsTransformFeedback");
glad_glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC)load("glPauseTransformFeedback");
glad_glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC)load("glResumeTransformFeedback");
glad_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC)load("glGetProgramBinary");
glad_glProgramBinary = (PFNGLPROGRAMBINARYPROC)load("glProgramBinary");
glad_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC)load("glProgramParameteri");
glad_glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)load("glInvalidateFramebuffer");
glad_glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC)load("glInvalidateSubFramebuffer");
glad_glTexStorage2D = (PFNGLTEXSTORAGE2DPROC)load("glTexStorage2D");
glad_glTexStorage3D = (PFNGLTEXSTORAGE3DPROC)load("glTexStorage3D");
glad_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC)load("glGetInternalformativ");
}
static void load_GL_KHR_debug(GLADloadproc load) {
if(!GLAD_GL_KHR_debug) return;
glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)load("glDebugMessageControl");
glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)load("glDebugMessageInsert");
glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)load("glDebugMessageCallback");
glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)load("glGetDebugMessageLog");
glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)load("glPushDebugGroup");
glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)load("glPopDebugGroup");
glad_glObjectLabel = (PFNGLOBJECTLABELPROC)load("glObjectLabel");
glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)load("glGetObjectLabel");
glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)load("glObjectPtrLabel");
glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)load("glGetObjectPtrLabel");
glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
glad_glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC)load("glDebugMessageControlKHR");
glad_glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC)load("glDebugMessageInsertKHR");
glad_glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC)load("glDebugMessageCallbackKHR");
glad_glGetDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC)load("glGetDebugMessageLogKHR");
glad_glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC)load("glPushDebugGroupKHR");
glad_glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC)load("glPopDebugGroupKHR");
glad_glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC)load("glObjectLabelKHR");
glad_glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC)load("glGetObjectLabelKHR");
glad_glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC)load("glObjectPtrLabelKHR");
glad_glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC)load("glGetObjectPtrLabelKHR");
glad_glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC)load("glGetPointervKHR");
}
static int find_extensionsGLES2(void) {
if (!get_exts()) return 0;
GLAD_GL_EXT_texture_filter_anisotropic = has_ext("GL_EXT_texture_filter_anisotropic");
GLAD_GL_KHR_debug = has_ext("GL_KHR_debug");
free_exts();
return 1;
}
static void find_coreGLES2(void) {
/* Thank you @elmindreda
* https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
* https://github.com/glfw/glfw/blob/master/src/context.c#L36
*/
int i, major, minor;
const char* version;
const char* prefixes[] = {
"OpenGL ES-CM ",
"OpenGL ES-CL ",
"OpenGL ES ",
NULL
};
version = (const char*) glGetString(GL_VERSION);
if (!version) return;
for (i = 0; prefixes[i]; i++) {
const size_t length = strlen(prefixes[i]);
if (strncmp(version, prefixes[i], length) == 0) {
version += length;
break;
}
}
/* PR #18 */
#ifdef _MSC_VER
sscanf_s(version, "%d.%d", &major, &minor);
#else
sscanf(version, "%d.%d", &major, &minor);
#endif
GLVersion.major = major; GLVersion.minor = minor;
max_loaded_major = major; max_loaded_minor = minor;
GLAD_GL_ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
GLAD_GL_ES_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 0)) {
max_loaded_major = 3;
max_loaded_minor = 0;
}
}
int gladLoadGLES2Loader(GLADloadproc load) {
GLVersion.major = 0; GLVersion.minor = 0;
glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
if(glGetString == NULL) return 0;
if(glGetString(GL_VERSION) == NULL) return 0;
find_coreGLES2();
load_GL_ES_VERSION_2_0(load);
load_GL_ES_VERSION_3_0(load);
if (!find_extensionsGLES2()) return 0;
load_GL_KHR_debug(load);
return GLVersion.major != 0 || GLVersion.minor != 0;
}

View file

@ -34,13 +34,26 @@
// using system headers for their parsers/indexers but glad for real build
// (in glad glFoo is just a #define to glad_glFoo or sth, which screws up autocompletion)
// (you may have to configure your IDE to #define IN_IDE_PARSER, but not for building!)
#ifdef YQ2_GL3_GLES3
#include <GLES3/gl32.h>
#else // desktop GL3
#define GL_GLEXT_PROTOTYPES 1
#include <GL/gl.h>
#include <GL/glext.h>
#endif
#else
#ifdef YQ2_GL3_GLES3
#include "../glad-gles3/include/glad/glad.h"
// yes, this is a bit hacky, but it works :-P
#define glDepthRange glDepthRangef
#else // desktop GL3
#include "../glad/include/glad/glad.h"
#endif
#endif
#include "../../ref_shared.h"
#include "HandmadeMath.h"
@ -81,10 +94,11 @@ enum {
GL3_ATTRIB_LIGHTFLAGS = 5 // uint, each set bit means "dyn light i affects this surface"
};
// TODO: do we need the following configurable?
static const int gl3_solid_format = GL_RGB;
// always using RGBA now, GLES3 on RPi4 doesn't work otherwise
// and I think all modern GPUs prefer 4byte pixels over 3bytes
static const int gl3_solid_format = GL_RGBA;
static const int gl3_alpha_format = GL_RGBA;
static const int gl3_tex_solid_format = GL_RGB;
static const int gl3_tex_solid_format = GL_RGBA;
static const int gl3_tex_alpha_format = GL_RGBA;
extern unsigned gl3_rawpalette[256];
@ -141,8 +155,7 @@ typedef struct
typedef struct
{
hmm_mat4 transProjMat4;
hmm_mat4 transViewMat4;
hmm_mat4 transProjViewMat4; // gl3state.projMat3D * gl3state.viewMat3D - so we don't have to do this in the shader
hmm_mat4 transModelMat4;
GLfloat scroll; // for SURF_FLOWING
@ -255,6 +268,8 @@ typedef struct
GLuint uni3DUBO;
GLuint uniLightsUBO;
hmm_mat4 projMat3D;
hmm_mat4 viewMat3D;
} gl3state_t;
extern gl3config_t gl3config;

View file

@ -217,6 +217,7 @@ CreateSDLWindow(int flags, int w, int h)
}
else
{
Com_Printf("Creating window failed: %s\n", SDL_GetError());
return false;
}
@ -594,7 +595,7 @@ GLimp_InitGraphics(int fullscreen, int *pwidth, int *pheight)
/* Now that we've got a working window print it's mode. */
int curdisplay = SDL_GetWindowDisplayIndex(window);
if (curdisplay < 0) {
if (curdisplay < 0) {
curdisplay = 0;
}