summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/test_tri.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag/test_tri.c')
-rw-r--r--tools/guest-diag/test_tri.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/tools/guest-diag/test_tri.c b/tools/guest-diag/test_tri.c
new file mode 100644
index 0000000..dc42876
--- /dev/null
+++ b/tools/guest-diag/test_tri.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: BSD-3-Clause
+// Copyright (c) 2026 Open-IOV contributors
+// test_tri.c - minimal SDL2 + OpenGL triangle for the offscreen pbuffer
+// harness. Intended to be run with SDL_VIDEODRIVER=offscreen and the
+// gz_pbuf.so shim preloaded (plus sdl_cap.so to capture the swaps):
+//
+// SDL_VIDEODRIVER=offscreen DISPLAY=:0 \
+// LD_PRELOAD="/tmp/sdl_cap.so /tmp/gz_pbuf.so" GZCAP=/tmp/testframes.bin \
+// ./test_tri 20 640 480
+//
+// It creates an SDL2 GL window/context (the shim turns the context into a
+// GLX pbuffer), clears to a colour, draws a rotating triangle, reads the
+// centre pixel back (non-black proof), and calls SDL_GL_SwapWindow each
+// frame. The sdl_cap.so hook captures the swap; the gz_pbuf.so hook turns
+// the swap into glFinish. Build:
+// gcc -O2 -o test_tri test_tri.c $(pkg-config --cflags --libs sdl2) -lGL
+#include <SDL2/SDL.h>
+#include <GL/gl.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+ int frames = argc > 1 ? atoi(argv[1]) : 20;
+ int w = argc > 2 ? atoi(argv[2]) : 640;
+ int h = argc > 3 ? atoi(argv[3]) : 480;
+ SDL_Window *win;
+ SDL_GLContext ctx;
+ int i;
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ fprintf(stderr, "test_tri: SDL_Init: %s\n", SDL_GetError());
+ return 1;
+ }
+ printf("test_tri: videodriver=%s\n",
+ SDL_GetCurrentVideoDriver() ? SDL_GetCurrentVideoDriver() : "?");
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ win = SDL_CreateWindow("test_tri", SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED, w, h,
+ SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
+ if (!win) {
+ fprintf(stderr, "test_tri: SDL_CreateWindow: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 2;
+ }
+
+ ctx = SDL_GL_CreateContext(win);
+ if (!ctx) {
+ fprintf(stderr, "test_tri: SDL_GL_CreateContext: %s\n",
+ SDL_GetError());
+ SDL_DestroyWindow(win);
+ SDL_Quit();
+ return 3;
+ }
+ if (SDL_GL_MakeCurrent(win, ctx) != 0)
+ fprintf(stderr, "test_tri: SDL_GL_MakeCurrent: %s\n",
+ SDL_GetError());
+ SDL_GL_SetSwapInterval(0);
+
+ printf("test_tri: GL %s | %s | %s\n",
+ (const char *)glGetString(GL_VENDOR),
+ (const char *)glGetString(GL_RENDERER),
+ (const char *)glGetString(GL_VERSION));
+
+ for (i = 0; i < frames; i++) {
+ float a = (float)i * 0.10f;
+ unsigned char px[4] = { 0, 0, 0, 0 };
+
+ glViewport(0, 0, w, h);
+ glClearColor(0.05f, 0.05f, 0.10f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glRotatef(a * 57.29578f, 0.0f, 0.0f, 1.0f);
+
+ glBegin(GL_TRIANGLES);
+ glColor3f(1.0f, 0.2f, 0.1f);
+ glVertex2f(0.0f, 0.8f);
+ glColor3f(0.1f, 1.0f, 0.3f);
+ glVertex2f(-0.8f, -0.6f);
+ glColor3f(0.2f, 0.3f, 1.0f);
+ glVertex2f(0.8f, -0.6f);
+ glEnd();
+ glFinish();
+
+ glReadPixels(w / 2, h / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, px);
+ printf("test_tri: frame=%d centre=%02x%02x%02x%02x err=0x%x\n",
+ i, px[0], px[1], px[2], px[3], glGetError());
+
+ SDL_GL_SwapWindow(win);
+ SDL_Delay(20);
+ }
+
+ printf("test_tri: done frames=%d %dx%d\n", frames, w, h);
+ SDL_GL_DeleteContext(ctx);
+ SDL_DestroyWindow(win);
+ SDL_Quit();
+ return 0;
+}