summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/test_tri.c
blob: dc42876ef7520e5da32a876c531f6a2c78edb412 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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;
}