1 /*
2 * This file is part of libplacebo.
3 *
4 * libplacebo is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * libplacebo is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "common.h"
19 #include "gpu.h"
20 #include "utils.h"
21
gl_err_str(GLenum err)22 const char *gl_err_str(GLenum err)
23 {
24 switch (err) {
25 #define CASE(name) case name: return #name
26 CASE(GL_NO_ERROR);
27 CASE(GL_INVALID_ENUM);
28 CASE(GL_INVALID_VALUE);
29 CASE(GL_INVALID_OPERATION);
30 CASE(GL_INVALID_FRAMEBUFFER_OPERATION);
31 CASE(GL_OUT_OF_MEMORY);
32 CASE(GL_STACK_UNDERFLOW);
33 CASE(GL_STACK_OVERFLOW);
34 #undef CASE
35
36 default: return "unknown error";
37 }
38 }
39
gl_poll_callbacks(pl_gpu gpu)40 void gl_poll_callbacks(pl_gpu gpu)
41 {
42 struct pl_gl *gl = PL_PRIV(gpu);
43 while (gl->callbacks.num) {
44 struct gl_cb cb = gl->callbacks.elem[0];
45 GLenum res = glClientWaitSync(cb.sync, 0, 0);
46 switch (res) {
47 case GL_ALREADY_SIGNALED:
48 case GL_CONDITION_SATISFIED:
49 PL_ARRAY_REMOVE_AT(gl->callbacks, 0);
50 cb.callback(cb.priv);
51 continue;
52
53 case GL_WAIT_FAILED:
54 PL_ARRAY_REMOVE_AT(gl->callbacks, 0);
55 glDeleteSync(cb.sync);
56 gl->failed = true;
57 gl_check_err(gpu, "gl_poll_callbacks"); // NOTE: will recurse!
58 return;
59
60 case GL_TIMEOUT_EXPIRED:
61 return;
62
63 default:
64 pl_unreachable();
65 }
66 }
67 }
68
gl_check_err(pl_gpu gpu,const char * fun)69 bool gl_check_err(pl_gpu gpu, const char *fun)
70 {
71 struct pl_gl *gl = PL_PRIV(gpu);
72 bool ret = true;
73
74 while (true) {
75 GLenum error = glGetError();
76 if (error == GL_NO_ERROR)
77 break;
78 PL_ERR(gpu, "%s: OpenGL error: %s", fun, gl_err_str(error));
79 ret = false;
80 gl->failed = true;
81 }
82
83 gl_poll_callbacks(gpu);
84 return ret;
85 }
86
gl_is_software(void)87 bool gl_is_software(void)
88 {
89 const char *renderer = glGetString(GL_RENDERER);
90 const char *vendor = glGetString(GL_VENDOR);
91 return !(renderer && vendor) ||
92 strcmp(renderer, "Software Rasterizer") == 0 ||
93 strstr(renderer, "llvmpipe") ||
94 strstr(renderer, "softpipe") ||
95 strcmp(vendor, "Microsoft Corporation") == 0 ||
96 strcmp(renderer, "Mesa X11") == 0 ||
97 strcmp(renderer, "Apple Software Renderer") == 0;
98 }
99
gl_test_ext(pl_gpu gpu,const char * ext,int gl_ver,int gles_ver)100 bool gl_test_ext(pl_gpu gpu, const char *ext, int gl_ver, int gles_ver)
101 {
102 struct pl_gl *p = PL_PRIV(gpu);
103 if (gl_ver && p->gl_ver >= gl_ver)
104 return true;
105 if (gles_ver && p->gles_ver >= gles_ver)
106 return true;
107
108 return ext ? epoxy_has_gl_extension(ext) : false;
109 }
110
111 #ifdef EPOXY_HAS_EGL
112
egl_err_str(EGLenum err)113 const char *egl_err_str(EGLenum err)
114 {
115 switch (err) {
116 #define CASE(name) case name: return #name
117 CASE(EGL_SUCCESS);
118 CASE(EGL_NOT_INITIALIZED);
119 CASE(EGL_BAD_ACCESS);
120 CASE(EGL_BAD_ALLOC);
121 CASE(EGL_BAD_ATTRIBUTE);
122 CASE(EGL_BAD_CONFIG);
123 CASE(EGL_BAD_CONTEXT);
124 CASE(EGL_BAD_CURRENT_SURFACE);
125 CASE(EGL_BAD_DISPLAY);
126 CASE(EGL_BAD_MATCH);
127 CASE(EGL_BAD_NATIVE_PIXMAP);
128 CASE(EGL_BAD_NATIVE_WINDOW);
129 CASE(EGL_BAD_PARAMETER);
130 CASE(EGL_BAD_SURFACE);
131 #undef CASE
132
133 default: return "unknown error";
134 }
135 }
136
egl_check_err(pl_gpu gpu,const char * fun)137 bool egl_check_err(pl_gpu gpu, const char *fun)
138 {
139 struct pl_gl *gl = PL_PRIV(gpu);
140 bool ret = true;
141
142 while (true) {
143 GLenum error = eglGetError();
144 if (error == EGL_SUCCESS)
145 return ret;
146 PL_ERR(gpu, "%s: EGL error: %s", fun, egl_err_str(error));
147 ret = false;
148 gl->failed = true;
149 }
150 }
151
152 #endif // EPOXY_HAS_EGL
153