summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/egl_retry.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag/egl_retry.c')
-rw-r--r--tools/guest-diag/egl_retry.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/tools/guest-diag/egl_retry.c b/tools/guest-diag/egl_retry.c
new file mode 100644
index 0000000..ce45d45
--- /dev/null
+++ b/tools/guest-diag/egl_retry.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * egl_retry.c - EGL/GLES2 offscreen probe with an explicit eglMakeCurrent
+ * retry loop. The r581-era trace showed the glsi engine-init returning
+ * 0xee00001 ("busy") exactly once and setting the device state bit 0x20;
+ * eglcore does not retry. This probe retries the make-current (and the whole
+ * display/context creation) up to N times, printing the precise EGL error of
+ * every attempt, so we can tell "one-shot busy, retry succeeds" from
+ * "permanent failure".
+ *
+ * Build (guest): gcc -O2 -o egl_retry egl_retry.c -lEGL -lGLESv2
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+
+static EGLDisplay get_device_display(void)
+{
+ PFNEGLGETPLATFORMDISPLAYEXTPROC gp =
+ (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress(
+ "eglGetPlatformDisplayEXT");
+ PFNEGLQUERYDEVICESEXTPROC qd =
+ (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress(
+ "eglQueryDevicesEXT");
+ EGLDeviceEXT devs[8];
+ EGLint n = 0;
+
+ if (!gp || !qd || !qd(8, devs, &n) || n <= 0)
+ return EGL_NO_DISPLAY;
+ printf("EGL_DEVICES n=%d\n", n);
+ return gp(EGL_PLATFORM_DEVICE_EXT, devs[0], NULL);
+}
+
+int main(int argc, char **argv)
+{
+ int tries = argc > 1 ? atoi(argv[1]) : 10;
+ EGLDisplay dpy;
+ EGLint major = 0, minor = 0;
+ EGLConfig cfg;
+ EGLint ncfg = 0;
+ EGLSurface surf;
+ EGLContext ctx = EGL_NO_CONTEXT;
+ EGLint attrs[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8, EGL_NONE
+ };
+ EGLint pb[] = { EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE };
+ EGLint cattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ int i;
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ dpy = get_device_display();
+ if (dpy == EGL_NO_DISPLAY) {
+ printf("NO_DEVICE_DISPLAY\n");
+ return 1;
+ }
+ if (!eglInitialize(dpy, &major, &minor)) {
+ printf("EGL_INIT_FAIL 0x%x\n", eglGetError());
+ return 1;
+ }
+ printf("EGL_INIT ok %d.%d vendor=%s\n", major, minor,
+ eglQueryString(dpy, EGL_VENDOR));
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ printf("BIND_API_FAIL 0x%x\n", eglGetError());
+ return 1;
+ }
+ if (!eglChooseConfig(dpy, attrs, &cfg, 1, &ncfg) || ncfg < 1) {
+ printf("CHOOSE_CONFIG_FAIL 0x%x n=%d\n", eglGetError(), ncfg);
+ return 1;
+ }
+ for (i = 0; i < tries; i++) {
+ surf = eglCreatePbufferSurface(dpy, cfg, pb);
+ if (surf == EGL_NO_SURFACE) {
+ printf("TRY %d CREATE_SURFACE_FAIL 0x%x\n", i + 1,
+ eglGetError());
+ usleep(200000);
+ continue;
+ }
+ if (ctx == EGL_NO_CONTEXT) {
+ ctx = eglCreateContext(dpy, cfg, EGL_NO_CONTEXT,
+ cattr);
+ if (ctx == EGL_NO_CONTEXT) {
+ printf("TRY %d CREATE_CTX_FAIL 0x%x\n", i + 1,
+ eglGetError());
+ eglDestroySurface(dpy, surf);
+ usleep(200000);
+ continue;
+ }
+ }
+ if (eglMakeCurrent(dpy, surf, surf, ctx)) {
+ const char *rend = (const char *)glGetString(
+ GL_RENDERER);
+ const char *ver = (const char *)glGetString(
+ GL_VERSION);
+ printf("TRY %d CURRENT OK renderer=%s version=%s\n",
+ i + 1, rend ? rend : "?", ver ? ver : "?");
+ /* draw one clear + readback so the pipeline runs */
+ glClearColor(0.1f, 0.4f, 0.9f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ {
+ unsigned char px[4];
+ glReadPixels(0, 0, 1, 1, GL_RGBA,
+ GL_UNSIGNED_BYTE, px);
+ printf("PIXEL %02x%02x%02x%02x\n", px[0],
+ px[1], px[2], px[3]);
+ }
+ printf("EGL_RETRY_OK on try %d\n", i + 1);
+ return 0;
+ }
+ printf("TRY %d MAKE_CURRENT_FAIL 0x%x\n", i + 1,
+ eglGetError());
+ eglDestroySurface(dpy, surf);
+ usleep(200000);
+ }
+ printf("EGL_RETRY_EXHAUSTED tries=%d\n", tries);
+ return 1;
+} \ No newline at end of file