Branch data Line data Source code
1 : : #include "gpu_tests.h"
2 : : #include "opengl/utils.h"
3 : :
4 : : #include <libplacebo/opengl.h>
5 : : #include <libplacebo/renderer.h>
6 : :
7 : 4 : static void opengl_interop_tests(pl_gpu gpu)
8 : : {
9 : 4 : pl_fmt fmt = pl_find_fmt(gpu, PL_FMT_UNORM, 1, 0, 0,
10 : : PL_FMT_CAP_RENDERABLE | PL_FMT_CAP_LINEAR);
11 [ - + ]: 4 : if (!fmt)
12 : 0 : return;
13 : : printf("opengl_interop_tests:\n");
14 : :
15 : 4 : pl_tex export = pl_tex_create(gpu, pl_tex_params(
16 : : .w = 32,
17 : : .h = 32,
18 : : .format = fmt,
19 : : .sampleable = true,
20 : : .renderable = true,
21 : : .blit_dst = fmt->caps & PL_FMT_CAP_BLITTABLE,
22 : : ));
23 : :
24 [ - + ]: 4 : REQUIRE(export);
25 : :
26 : 4 : struct pl_opengl_wrap_params wrap = {
27 : 4 : .width = export->params.w,
28 : 4 : .height = export->params.h,
29 : 4 : .depth = export->params.d,
30 : : };
31 : :
32 : 4 : wrap.texture = pl_opengl_unwrap(gpu, export, &wrap.target, &wrap.iformat, NULL);
33 [ - + ]: 4 : REQUIRE(wrap.texture);
34 : :
35 : 4 : pl_tex import = pl_opengl_wrap(gpu, &wrap);
36 [ - + ]: 4 : REQUIRE(import);
37 [ - + ]: 4 : REQUIRE(import->params.renderable);
38 [ - + ]: 4 : REQUIRE_CMP(import->params.blit_dst, ==, export->params.blit_dst, "d");
39 : :
40 : 4 : pl_tex_destroy(gpu, &import);
41 : 4 : pl_tex_destroy(gpu, &export);
42 : : }
43 : :
44 : : #define PBUFFER_WIDTH 640
45 : : #define PBUFFER_HEIGHT 480
46 : :
47 : : struct swapchain_priv {
48 : : EGLDisplay display;
49 : : EGLSurface surface;
50 : : };
51 : :
52 : 40 : static void swap_buffers(void *priv)
53 : : {
54 : : struct swapchain_priv *p = priv;
55 : 40 : eglSwapBuffers(p->display, p->surface);
56 : 40 : }
57 : :
58 : 4 : static void opengl_swapchain_tests(pl_opengl gl,
59 : : EGLDisplay display, EGLSurface surface)
60 : : {
61 [ - + ]: 4 : if (surface == EGL_NO_SURFACE)
62 : 0 : return;
63 : :
64 : : printf("opengl_swapchain_tests:\n");
65 : 4 : pl_gpu gpu = gl->gpu;
66 : : pl_swapchain sw;
67 : 4 : sw = pl_opengl_create_swapchain(gl, pl_opengl_swapchain_params(
68 : : .swap_buffers = swap_buffers,
69 : : .priv = &(struct swapchain_priv) { display, surface },
70 : : ));
71 [ - + ]: 4 : REQUIRE(sw);
72 : :
73 : 4 : int w = PBUFFER_WIDTH, h = PBUFFER_HEIGHT;
74 [ - + ]: 4 : REQUIRE(pl_swapchain_resize(sw, &w, &h));
75 : :
76 [ + + ]: 44 : for (int i = 0; i < 10; i++) {
77 : : struct pl_swapchain_frame frame;
78 [ - + ]: 40 : REQUIRE(pl_swapchain_start_frame(sw, &frame));
79 [ + - ]: 40 : if (frame.fbo->params.blit_dst)
80 : 40 : pl_tex_clear(gpu, frame.fbo, (float[4]){0});
81 : :
82 : : // TODO: test this with an actual pl_renderer instance
83 : : struct pl_frame target;
84 : 40 : pl_frame_from_swapchain(&target, &frame);
85 : :
86 [ - + ]: 40 : REQUIRE(pl_swapchain_submit_frame(sw));
87 : 40 : pl_swapchain_swap_buffers(sw);
88 : : }
89 : :
90 : 4 : pl_swapchain_destroy(&sw);
91 : : }
92 : :
93 : 1 : int main()
94 : : {
95 [ + - ]: 1 : if (!gladLoaderLoadEGL(EGL_NO_DISPLAY))
96 : 0 : return SKIP;
97 : :
98 : 1 : const char *extstr = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
99 [ + - + - ]: 1 : if (!extstr || !strstr(extstr, "EGL_MESA_platform_surfaceless"))
100 : : return SKIP;
101 : :
102 : : // Create the OpenGL context
103 : 1 : EGLDisplay dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_SURFACELESS_MESA,
104 : : (void *) EGL_DEFAULT_DISPLAY, NULL);
105 [ + - ]: 1 : if (dpy == EGL_NO_DISPLAY)
106 : : return SKIP;
107 : :
108 : : EGLint major, minor;
109 [ + - ]: 1 : if (!eglInitialize(dpy, &major, &minor))
110 : : return SKIP;
111 : :
112 [ + - ]: 1 : if (!gladLoaderLoadEGL(dpy))
113 : : return SKIP;
114 : :
115 : 1 : printf("Initialized EGL v%d.%d\n", major, minor);
116 : 1 : int egl_ver = major * 10 + minor;
117 : :
118 : : struct {
119 : : EGLenum api;
120 : : EGLenum render;
121 : : int major, minor;
122 : : int glsl_ver;
123 : : EGLenum profile;
124 : 1 : } egl_vers[] = {
125 : : { EGL_OPENGL_API, EGL_OPENGL_BIT, 4, 6, 460, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT },
126 : : { EGL_OPENGL_API, EGL_OPENGL_BIT, 3, 3, 330, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT },
127 : : { EGL_OPENGL_API, EGL_OPENGL_BIT, 3, 0, 130, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT, },
128 : : { EGL_OPENGL_ES_API, EGL_OPENGL_ES3_BIT, 3, 0, 300, },
129 : : };
130 : :
131 : 1 : struct pl_glsl_version last_glsl = {0};
132 : 1 : struct pl_gpu_limits last_limits = {0};
133 : :
134 : 1 : pl_log log = pl_test_logger();
135 : :
136 [ + + ]: 5 : for (int i = 0; i < PL_ARRAY_SIZE(egl_vers); i++) {
137 : :
138 : 4 : const int cfg_attribs[] = {
139 : : EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
140 : 4 : EGL_RENDERABLE_TYPE, egl_vers[i].render,
141 : : EGL_NONE
142 : : };
143 : :
144 : 4 : EGLConfig config = 0;
145 : 4 : EGLint num_configs = 0;
146 : 4 : bool ok = eglChooseConfig(dpy, cfg_attribs, &config, 1, &num_configs);
147 [ + - - + ]: 4 : if (!ok || !num_configs)
148 : 0 : goto error;
149 : :
150 [ - + ]: 4 : if (!eglBindAPI(egl_vers[i].api))
151 : 0 : goto error;
152 : :
153 : : EGLContext egl;
154 [ + + ]: 4 : if (egl_vers[i].api == EGL_OPENGL_ES_API) {
155 : : // OpenGL ES
156 : 1 : const EGLint egl_attribs[] = {
157 : 1 : EGL_CONTEXT_CLIENT_VERSION, egl_vers[i].major,
158 [ - + ]: 1 : (egl_ver >= 15) ? EGL_CONTEXT_OPENGL_DEBUG : EGL_NONE, EGL_TRUE,
159 : : EGL_NONE
160 : : };
161 : :
162 : : printf("Attempting creation of OpenGL ES v%d context\n", egl_vers[i].major);
163 : 1 : egl = eglCreateContext(dpy, config, EGL_NO_CONTEXT, egl_attribs);
164 : : } else {
165 : : // Desktop OpenGL
166 : 3 : const int egl_attribs[] = {
167 : 3 : EGL_CONTEXT_MAJOR_VERSION, egl_vers[i].major,
168 : 3 : EGL_CONTEXT_MINOR_VERSION, egl_vers[i].minor,
169 : 3 : EGL_CONTEXT_OPENGL_PROFILE_MASK, egl_vers[i].profile,
170 [ - + ]: 3 : (egl_ver >= 15) ? EGL_CONTEXT_OPENGL_DEBUG : EGL_NONE, EGL_TRUE,
171 : : EGL_NONE
172 : : };
173 : :
174 : : printf("Attempting creation of Desktop OpenGL v%d.%d context\n",
175 : : egl_vers[i].major, egl_vers[i].minor);
176 : 3 : egl = eglCreateContext(dpy, config, EGL_NO_CONTEXT, egl_attribs);
177 : : }
178 : :
179 [ - + ]: 4 : if (!egl)
180 : 0 : goto error;
181 : :
182 : 4 : const EGLint pbuffer_attribs[] = {
183 : : EGL_WIDTH, PBUFFER_WIDTH,
184 : : EGL_HEIGHT, PBUFFER_HEIGHT,
185 : : EGL_NONE
186 : : };
187 : :
188 : 4 : EGLSurface surf = eglCreatePbufferSurface(dpy, config, pbuffer_attribs);
189 : :
190 [ - + ]: 4 : if (!eglMakeCurrent(dpy, surf, surf, egl))
191 : 0 : goto error;
192 : :
193 : 4 : pl_opengl gl = pl_opengl_create(log, pl_opengl_params(
194 : : .get_proc_addr = (pl_voidfunc_t (*)(const char *)) eglGetProcAddress,
195 : : .max_glsl_version = egl_vers[i].glsl_ver,
196 : : .debug = true,
197 : : .egl_display = dpy,
198 : : .egl_context = egl,
199 : : #ifdef CI_ALLOW_SW
200 : : .allow_software = true,
201 : : #endif
202 : : ));
203 [ - + ]: 4 : if (!gl)
204 : 0 : goto next;
205 : :
206 : : // Skip repeat tests
207 : 4 : pl_gpu gpu = gl->gpu;
208 [ - + ]: 4 : if (memcmp(&last_glsl, &gpu->glsl, sizeof(last_glsl)) == 0 &&
209 [ # # ]: 0 : memcmp(&last_limits, &gpu->limits, sizeof(last_limits)) == 0)
210 : : {
211 : : printf("Skipping tests due to duplicate capabilities/version\n");
212 : 0 : goto next;
213 : : }
214 : :
215 : : #ifdef CI_MAXGL
216 : : if (last_glsl.version && last_glsl.gles == gpu->glsl.gles)
217 : : goto next;
218 : : #endif
219 : :
220 : 4 : last_glsl = gpu->glsl;
221 : 4 : last_limits = gpu->limits;
222 : :
223 : 4 : gpu_shader_tests(gpu);
224 : 4 : gpu_interop_tests(gpu);
225 : 4 : opengl_interop_tests(gpu);
226 : 4 : opengl_swapchain_tests(gl, dpy, surf);
227 : :
228 : : // Reduce log spam after first successful test
229 : 4 : pl_log_level_update(log, PL_LOG_INFO);
230 : :
231 : 4 : next:
232 : 4 : pl_opengl_destroy(&gl);
233 : 4 : eglDestroySurface(dpy, surf);
234 : 4 : eglDestroyContext(dpy, egl);
235 : 4 : continue;
236 : :
237 : 0 : error: ;
238 : 0 : EGLint error = eglGetError();
239 [ # # ]: 0 : if (error != EGL_SUCCESS)
240 : 0 : fprintf(stderr, "EGL error: %s\n", egl_err_str(error));
241 : : }
242 : :
243 : 1 : eglTerminate(dpy);
244 : 1 : gladLoaderUnloadEGL();
245 : 1 : pl_log_destroy(&log);
246 : :
247 [ + - ]: 1 : if (!last_glsl.version)
248 : : return SKIP;
249 : : }
|