diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-12 20:01:04 -0500 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-11-12 20:01:04 -0500 |
| commit | 725898e44666b4def396f7f3c5e50712fd37aa33 (patch) | |
| tree | 261bba910db49036624cc2cf89baac6554a6f58d /tools/guest-diag/test_tri.c | |
| parent | 800c108f9d2463066a221a0e4ff56867304551a6 (diff) | |
| download | open-iov-725898e44666b4def396f7f3c5e50712fd37aa33.tar.gz open-iov-725898e44666b4def396f7f3c5e50712fd37aa33.zip | |
vgsp: stop fabricating 0xFFFF into the nvPush error notifier; add r1780 GL ops tooling
The uncommitted keep-alive change wrote 0xFFFF into slot 0's status field
(u16 at notifier+0x0e) on the X DDX / GLX kick-idle channel families. Ground
truth (570.144 reference sources + stock nvidia_drv.so disassembly): slot 0
of an nvPush notifier block is the ERROR notifier; nvPushCheckChannelError
reads that status and 0xFFFF aborts every nvPushWaitForNotifier/idle wait as
a channel error. There is no pb_kickIfIdle in 570.144 - the DDX DMA-idle
test reads the progress-tracker semaphore word, not this slot. Leave slot 0
untouched; keep the 0x8000->0 completion ack for the remaining slots and the
r864 0xFFFF/0x8000 completion on the RC-watchdog/beef families. Correct the
CONT.408/409 comments accordingly.
New host/guest tooling: gpa.py (QMP gva2gpa), tick_gen.py (guest-RM timer
BO tick), guest_mode.sh (shared nvClip modeNum reader), gl_verify.sh
(X/GLX bring-up with ScreenInit-lottery retries), push_gl_tools.sh, the
gzdoom_pbuf_run.sh guest recipe and the test_tri SDL2 harness validation
program; ignore tools/guest-diag/build/.
Diffstat (limited to 'tools/guest-diag/test_tri.c')
| -rw-r--r-- | tools/guest-diag/test_tri.c | 112 |
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; +} |
