diff options
Diffstat (limited to '')
-rw-r--r-- | src/opengl/utils.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/opengl/utils.c b/src/opengl/utils.c new file mode 100644 index 0000000..d96a3e7 --- /dev/null +++ b/src/opengl/utils.c @@ -0,0 +1,158 @@ +/* + * This file is part of libplacebo. + * + * libplacebo is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libplacebo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common.h" +#include "gpu.h" +#include "utils.h" + +const char *gl_err_str(GLenum err) +{ + switch (err) { +#define CASE(name) case name: return #name + CASE(GL_NO_ERROR); + CASE(GL_INVALID_ENUM); + CASE(GL_INVALID_VALUE); + CASE(GL_INVALID_OPERATION); + CASE(GL_INVALID_FRAMEBUFFER_OPERATION); + CASE(GL_OUT_OF_MEMORY); + CASE(GL_STACK_UNDERFLOW); + CASE(GL_STACK_OVERFLOW); +#undef CASE + + default: return "unknown error"; + } +} + +void gl_poll_callbacks(pl_gpu gpu) +{ + const gl_funcs *gl = gl_funcs_get(gpu); + struct pl_gl *p = PL_PRIV(gpu); + while (p->callbacks.num) { + struct gl_cb cb = p->callbacks.elem[0]; + GLenum res = gl->ClientWaitSync(cb.sync, 0, 0); + switch (res) { + case GL_ALREADY_SIGNALED: + case GL_CONDITION_SATISFIED: + PL_ARRAY_REMOVE_AT(p->callbacks, 0); + cb.callback(cb.priv); + continue; + + case GL_WAIT_FAILED: + PL_ARRAY_REMOVE_AT(p->callbacks, 0); + gl->DeleteSync(cb.sync); + p->failed = true; + gl_check_err(gpu, "gl_poll_callbacks"); // NOTE: will recurse! + return; + + case GL_TIMEOUT_EXPIRED: + return; + + default: + pl_unreachable(); + } + } +} + +bool gl_check_err(pl_gpu gpu, const char *fun) +{ + const gl_funcs *gl = gl_funcs_get(gpu); + struct pl_gl *p = PL_PRIV(gpu); + bool ret = true; + + while (true) { + GLenum error = gl->GetError(); + if (error == GL_NO_ERROR) + break; + PL_ERR(gpu, "%s: OpenGL error: %s", fun, gl_err_str(error)); + ret = false; + p->failed = true; + } + + gl_poll_callbacks(gpu); + return ret; +} + +bool gl_is_software(pl_opengl pl_gl) +{ + struct gl_ctx *glctx = PL_PRIV(pl_gl); + const gl_funcs *gl = &glctx->func; + const char *renderer = (char *) gl->GetString(GL_RENDERER); + return !renderer || + strcmp(renderer, "Software Rasterizer") == 0 || + strstr(renderer, "llvmpipe") || + strstr(renderer, "softpipe") || + strcmp(renderer, "Mesa X11") == 0 || + strcmp(renderer, "Apple Software Renderer") == 0; +} + +bool gl_is_gles(pl_opengl pl_gl) +{ + struct gl_ctx *glctx = PL_PRIV(pl_gl); + const gl_funcs *gl = &glctx->func; + const char *version = (char *) gl->GetString(GL_VERSION); + return pl_str_startswith0(pl_str0(version), "OpenGL ES"); +} + +bool gl_test_ext(pl_gpu gpu, const char *ext, int gl_ver, int gles_ver) +{ + struct pl_gl *p = PL_PRIV(gpu); + if (gl_ver && p->gl_ver >= gl_ver) + return true; + if (gles_ver && p->gles_ver >= gles_ver) + return true; + + return ext ? pl_opengl_has_ext(p->gl, ext) : false; +} + +const char *egl_err_str(EGLenum err) +{ + switch (err) { +#define CASE(name) case name: return #name + CASE(EGL_SUCCESS); + CASE(EGL_NOT_INITIALIZED); + CASE(EGL_BAD_ACCESS); + CASE(EGL_BAD_ALLOC); + CASE(EGL_BAD_ATTRIBUTE); + CASE(EGL_BAD_CONFIG); + CASE(EGL_BAD_CONTEXT); + CASE(EGL_BAD_CURRENT_SURFACE); + CASE(EGL_BAD_DISPLAY); + CASE(EGL_BAD_MATCH); + CASE(EGL_BAD_NATIVE_PIXMAP); + CASE(EGL_BAD_NATIVE_WINDOW); + CASE(EGL_BAD_PARAMETER); + CASE(EGL_BAD_SURFACE); +#undef CASE + + default: return "unknown error"; + } +} + +bool egl_check_err(pl_gpu gpu, const char *fun) +{ + struct pl_gl *p = PL_PRIV(gpu); + bool ret = true; + + while (true) { + GLenum error = eglGetError(); + if (error == EGL_SUCCESS) + return ret; + PL_ERR(gpu, "%s: EGL error: %s", fun, egl_err_str(error)); + ret = false; + p->failed = true; + } +} |