X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=libpicofe.git;a=blobdiff_plain;f=gl.c;h=2ebb87c7077187561119db2069c90c74c6b1fed2;hp=44e0dd50e9001c4043a918b62493c183f4f16cc6;hb=HEAD;hpb=0d645bc539fdc073f20c4dea9f4a4e218cebec0e diff --git a/gl.c b/gl.c index 44e0dd5..3b201db 100644 --- a/gl.c +++ b/gl.c @@ -1,14 +1,27 @@ #include #include +#include +#include #include #include +#include "gl_loader.h" #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; + +/* for external flips */ +void *gl_es_display; +void *gl_es_surface; + +static int tex_w, tex_h; +static void *tex_mem; +static int flip_old_w, flip_old_h; static int gl_have_error(const char *name) { @@ -30,29 +43,15 @@ static int gles_have_error(const char *name) return 0; } -int gl_init(void *display, void *window, int *quirks) +int gl_init(void *display, int *quirks) { - EGLConfig ecfg = NULL; - GLuint texture_name = 0; - void *tmp_texture_mem = NULL; - EGLint num_config; int retval = -1; int ret; - EGLint attr[] = - { - EGL_NONE - }; - ret = gl_platform_init(&display, &window, quirks); + ret = gl_platform_init(&display, quirks); if (ret != 0) { fprintf(stderr, "gl_platform_init failed with %d\n", ret); - goto out; - } - - tmp_texture_mem = calloc(1, 1024 * 512 * 2); - if (tmp_texture_mem == NULL) { - fprintf(stderr, "OOM\n"); - goto out; + return retval; } edpy = eglGetDisplay((EGLNativeDisplayType)display); @@ -65,8 +64,44 @@ int gl_init(void *display, void *window, int *quirks) fprintf(stderr, "Failed to initialize EGL\n"); goto out; } + retval = 0; + +out: + if (retval && edpy != EGL_NO_DISPLAY) + gl_shutdown(); + return retval; +} - if (!eglChooseConfig(edpy, attr, &ecfg, 1, &num_config)) { +int gl_create(void *window, int *quirks, int w, int h) +{ + EGLConfig ecfg = NULL; + EGLint num_config; + int retval = -1; + int ret; + EGLint config_attr[] = + { + EGL_NONE + }; + + ret = gl_platform_create(&window, quirks); + if (ret != 0) { + fprintf(stderr, "gl_platform_init failed with %d\n", ret); + return retval; + } + + flip_old_w = flip_old_h = 0; + for (tex_w = 1; tex_w < w; tex_w *= 2) + ; + for (tex_h = 1; tex_h < h; tex_h *= 2) + ; + tex_mem = realloc(tex_mem, tex_w * tex_h * 2); + if (tex_mem == NULL) { + fprintf(stderr, "OOM\n"); + goto out; + } + memset(tex_mem, 0, tex_w * tex_h * 2); + + if (!eglChooseConfig(edpy, config_attr, &ecfg, 1, &num_config)) { fprintf(stderr, "Failed to choose config (%x)\n", eglGetError()); goto out; } @@ -88,25 +123,52 @@ int gl_init(void *display, void *window, int *quirks) 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; + } + + ret = *quirks & GL_QUIRK_VSYNC_ON ? 1 : 0; + eglSwapInterval(edpy, ret); + // 1.x (fixed-function) only glEnable(GL_TEXTURE_2D); + glGetError(); + + 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, 1024, 512, 0, GL_RGB, - GL_UNSIGNED_SHORT_5_6_5, tmp_texture_mem); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h, 0, GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, tex_mem); if (gl_have_error("glTexImage2D")) goto out; // no mipmaps - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ret = *quirks & GL_QUIRK_SCALING_NEAREST ? GL_NEAREST : GL_LINEAR; + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ret); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ret); //glViewport(0, 0, 512, 512); glLoadIdentity(); @@ -119,13 +181,22 @@ int gl_init(void *display, void *window, int *quirks) if (gl_have_error("init")) goto out; + gl_es_display = (void *)edpy; + gl_es_surface = (void *)esfc; retval = 0; out: - free(tmp_texture_mem); + if (retval && edpy != EGL_NO_DISPLAY) + gl_destroy(); return retval; } -static float vertices[] = { +void gl_announce(void) +{ + printf("GL_RENDERER: %s\n", (char *)glGetString(GL_RENDERER)); + printf("GL_VERSION: %s\n", (char *)glGetString(GL_VERSION)); +} + +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 @@ -139,32 +210,37 @@ 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) { - static int old_w, old_h; + gl_have_error("pre-flip unknown"); + + glBindTexture(GL_TEXTURE_2D, texture_name); + if (gl_have_error("glBindTexture")) + return -1; if (fb != NULL) { - if (w != old_w || h != old_h) { - float f_w = (float)w / 1024.0f; - float f_h = (float)h / 512.0f; + if (w != flip_old_w || h != flip_old_h) { + float f_w = (float)w / tex_w; + float f_h = (float)h / tex_h; texture[1*2 + 0] = f_w; texture[2*2 + 1] = f_h; texture[3*2 + 0] = f_w; texture[3*2 + 1] = f_h; - old_w = w; - old_h = h; + flip_old_w = w; + flip_old_h = 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; @@ -175,15 +251,65 @@ int gl_flip(const void *fb, int w, int h) return 0; } -void gl_finish(void) +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_destroy(void) { + if (edpy == EGL_NO_DISPLAY) + return; // nothing to do + + // 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; - - gl_platform_finish(); + if (ectxt != EGL_NO_CONTEXT) { + eglDestroyContext(edpy, ectxt); + ectxt = EGL_NO_CONTEXT; + } + if (esfc != EGL_NO_SURFACE) { + eglDestroySurface(edpy, esfc); + esfc = EGL_NO_SURFACE; + } + + gl_es_surface = (void *)esfc; + + if (tex_mem) free(tex_mem); + tex_mem = NULL; + + gl_platform_destroy(); +} + +void gl_shutdown(void) +{ + if (edpy != EGL_NO_DISPLAY) { + eglTerminate(edpy); + edpy = EGL_NO_DISPLAY; + } + + gl_es_display = (void *)edpy; + + gl_platform_shutdown(); }