From 64f9c546cb7e7c12bbaffab5993547e213a4f17d Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 14 May 2025 19:44:58 +0300 Subject: [PATCH] gl: update - more error checking - add a workaround for mesa compiled without OpenGL ES1.x (but with egl) - don't leave half-initialized state (and just a black screen) on error - clear texture memory, otherwise edges sometimes pick up noise from filtering taking garbage texels behind the edges - allow to pass vertices to flip - new clear function --- gl.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++----------- gl.h | 9 +++-- 2 files changed, 94 insertions(+), 22 deletions(-) diff --git a/gl.c b/gl.c index c5c5050..975520e 100644 --- a/gl.c +++ b/gl.c @@ -1,14 +1,16 @@ #include #include +#include +#include #include #include #include "gl_platform.h" #include "gl.h" -static EGLDisplay edpy; -static EGLSurface esfc; -static EGLContext ectxt; +static EGLDisplay edpy = EGL_NO_DISPLAY; +static EGLSurface esfc = EGL_NO_SURFACE; +static EGLContext ectxt = EGL_NO_CONTEXT; static GLuint texture_name; @@ -46,7 +48,7 @@ int gl_init(void *display, void *window, int *quirks, int w, int h) EGLint num_config; int retval = -1; int ret; - EGLint attr[] = + EGLint config_attr[] = { EGL_NONE }; @@ -67,6 +69,7 @@ int gl_init(void *display, void *window, int *quirks, int w, int h) fprintf(stderr, "OOM\n"); goto out; } + memset(tex_mem, 0, tex_w * tex_h * 2); edpy = eglGetDisplay((EGLNativeDisplayType)display); if (edpy == EGL_NO_DISPLAY) { @@ -79,7 +82,7 @@ int gl_init(void *display, void *window, int *quirks, int w, int h) goto out; } - if (!eglChooseConfig(edpy, attr, &ecfg, 1, &num_config)) { + if (!eglChooseConfig(edpy, config_attr, &ecfg, 1, &num_config)) { fprintf(stderr, "Failed to choose config (%x)\n", eglGetError()); goto out; } @@ -101,19 +104,39 @@ int gl_init(void *display, void *window, int *quirks, int w, int h) if (ectxt == EGL_NO_CONTEXT) { fprintf(stderr, "Unable to create EGL context (%x)\n", eglGetError()); - goto out; + // on mesa, some distros disable ES1.x but compat GL still works + ret = eglBindAPI(EGL_OPENGL_API); + if (!ret) { + fprintf(stderr, "eglBindAPI: %x\n", eglGetError()); + goto out; + } + ectxt = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, NULL); + if (ectxt == EGL_NO_CONTEXT) { + fprintf(stderr, "giving up on EGL context (%x)\n", + eglGetError()); + goto out; + } } - eglMakeCurrent(edpy, esfc, esfc, ectxt); + ret = eglMakeCurrent(edpy, esfc, esfc, ectxt); + if (!ret) { + fprintf(stderr, "eglMakeCurrent: %x\n", eglGetError()); + goto out; + } + // 1.x (fixed-function) only glEnable(GL_TEXTURE_2D); + glGetError(); - if (texture_name) - glDeleteTextures(1, &texture_name); + assert(!texture_name); glGenTextures(1, &texture_name); + if (gl_have_error("glGenTextures")) + goto out; glBindTexture(GL_TEXTURE_2D, texture_name); + if (gl_have_error("glBindTexture")) + goto out; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, tex_mem); @@ -139,15 +162,18 @@ int gl_init(void *display, void *window, int *quirks, int w, int h) gl_es_surface = (void *)esfc; retval = 0; out: + if (retval && edpy != EGL_NO_DISPLAY) + gl_finish(); return retval; } void gl_announce(void) { printf("GL_RENDERER: %s\n", (char *)glGetString(GL_RENDERER)); + printf("GL_VERSION: %s\n", (char *)glGetString(GL_VERSION)); } -static float vertices[] = { +static const float default_vertices[] = { -1.0f, 1.0f, 0.0f, // 0 0 1 1.0f, 1.0f, 0.0f, // 1 ^ -1.0f, -1.0f, 0.0f, // 2 | 2 3 @@ -161,8 +187,14 @@ static float texture[] = { 1.0f, 1.0f, // +--> }; -int gl_flip(const void *fb, int w, int h) +int gl_flip_v(const void *fb, int w, int h, const float *vertices) { + gl_have_error("pre-flip unknown"); + + glBindTexture(GL_TEXTURE_2D, texture_name); + if (gl_have_error("glBindTexture")) + return -1; + if (fb != NULL) { if (w != flip_old_w || h != flip_old_h) { float f_w = (float)w / tex_w; @@ -177,14 +209,15 @@ int gl_flip(const void *fb, int w, int h) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, fb); - if (gl_have_error("glTexSubImage2D")) + if (gl_have_error("glTexSubImage2D")) { + fprintf(stderr, " %dx%d t: %dx%d %p\n", w, h, tex_w, tex_h, fb); return -1; + } } - glVertexPointer(3, GL_FLOAT, 0, vertices); + glVertexPointer(3, GL_FLOAT, 0, vertices ? vertices : default_vertices); glTexCoordPointer(2, GL_FLOAT, 0, texture); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - if (gl_have_error("glDrawArrays")) return -1; @@ -195,15 +228,49 @@ int gl_flip(const void *fb, int w, int h) return 0; } +int gl_flip(const void *fb, int w, int h) +{ + return gl_flip_v(fb, w, h, NULL); +} + +// to be used once after exiting menu, etc +void gl_clear(void) +{ + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(edpy, esfc); + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(edpy, esfc); + glClear(GL_COLOR_BUFFER_BIT); + gl_have_error("glClear"); +} + void gl_finish(void) { + // sometimes there is an error... from somewhere? + //gl_have_error("finish"); + glGetError(); + + if (texture_name) + { + glDeleteTextures(1, &texture_name); + gl_have_error("glDeleteTextures"); + texture_name = 0; + } + eglMakeCurrent(edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(edpy, ectxt); - ectxt = EGL_NO_CONTEXT; - eglDestroySurface(edpy, esfc); - esfc = EGL_NO_SURFACE; - eglTerminate(edpy); - edpy = EGL_NO_DISPLAY; + if (ectxt != EGL_NO_CONTEXT) { + eglDestroyContext(edpy, ectxt); + ectxt = EGL_NO_CONTEXT; + } + if (esfc != EGL_NO_SURFACE) { + eglDestroySurface(edpy, esfc); + esfc = EGL_NO_SURFACE; + } + if (edpy != EGL_NO_DISPLAY) { + eglTerminate(edpy); + edpy = EGL_NO_DISPLAY; + } gl_es_display = (void *)edpy; gl_es_surface = (void *)esfc; diff --git a/gl.h b/gl.h index bddacdc..760960d 100644 --- a/gl.h +++ b/gl.h @@ -5,7 +5,9 @@ int gl_init(void *display, void *window, int *quirks, int w, int h); void gl_announce(void); +int gl_flip_v(const void *fb, int w, int h, const float *vertices); int gl_flip(const void *fb, int w, int h); +void gl_clear(void); void gl_finish(void); /* for external flips */ @@ -21,13 +23,16 @@ static __inline int gl_init(void *display, void *window, int *quirks, int w, int static __inline void gl_announce(void) { } -static __inline int gl_flip(const void *fb, int w, int h) +static __inline int gl_flip_v(const void *fb, int w, int h, const float *vertices) { return -1; } -static __inline void gl_finish(void) +static __inline int gl_flip(const void *fb, int w, int h) { + return -1; } +static __inline void gl_clear(void) {} +static __inline void gl_finish(void) {} #define gl_es_display (void *)0 #define gl_es_surface (void *)0 -- 2.39.5