From 9d8640a1c6a6d7e8ceb9fa47c0f17f6535601007 Mon Sep 17 00:00:00 2001 From: Eggert Jung Date: Sun, 7 Dec 2025 11:23:27 +0100 Subject: [PATCH] initial --- test.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 test.c diff --git a/test.c b/test.c new file mode 100644 index 0000000..add4f44 --- /dev/null +++ b/test.c @@ -0,0 +1,177 @@ +/* ------------------------------------------------------------- + * framebuffer_demo.c + * ------------------------------------------------------------- + * A tiny example that: + * * allocates a 600×400 RGB‑888 framebuffer in RAM, + * * fills it with a demo pattern, + * * opens an SDL2 window, + * * streams the framebuffer to the window each frame. + * + * Build (Linux/macOS): + * gcc -Wall -O2 -std=c11 framebuffer_demo.c -lSDL2 -o framebuffer_demo + * + * Run: + * ./framebuffer_demo + * + * ------------------------------------------------------------- */ +#include +#include +#include +#include + +/* ------------------------------------------------------------- + * Configuration + * ------------------------------------------------------------- */ +#define WIDTH 600 +#define HEIGHT 400 + +/* ------------------------------------------------------------- + * Simple pixel format helpers + * ------------------------------------------------------------- */ +/* The framebuffer will be stored as 32‑bit ARGB (0xAARRGGBB). */ +typedef Uint32 pixel_t; + +/* Build a pixel from separate components (no gamma correction). */ +static inline pixel_t make_pixel(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { + /* SDL uses little‑endian, so the order in memory is BGRA. + * Our 0xAARRGGBB layout works fine with SDL_UpdateTexture. */ + return (pixel_t)( (a << 24) | (r << 16) | (g << 8) | b ); +} + +/* ------------------------------------------------------------- + * Global framebuffer + * ------------------------------------------------------------- */ +static pixel_t framebuffer[HEIGHT][WIDTH]; + +/* ------------------------------------------------------------- + * Fill the framebuffer with a demo pattern + * ------------------------------------------------------------- */ +static void init_framebuffer(void) +{ + for (int y = 0; y < HEIGHT; ++y) { + for (int x = 0; x < WIDTH; ++x) { + /* Example: a smooth red‑to‑green gradient */ + Uint8 r = (Uint8)((x * 255) / (WIDTH - 1)); /* left → right */ + Uint8 g = (Uint8)((y * 255) / (HEIGHT - 1)); /* top → bottom */ + Uint8 b = 0x80; /* constant bluish */ + framebuffer[y][x] = make_pixel(r, g, b, 255); + } + } +} + +/* ------------------------------------------------------------- + * Main entry point + * ------------------------------------------------------------- */ +int main(void) +{ + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + fprintf(stderr, "SDL_Init error: %s\n", SDL_GetError()); + return EXIT_FAILURE; + } + + /* --------------------------------------------------------- + * Create a window and a renderer (software accelerated is fine) + * --------------------------------------------------------- */ + SDL_Window *window = SDL_CreateWindow( + "Framebuffer Demo", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + WIDTH, + HEIGHT, + SDL_WINDOW_SHOWN + ); + if (!window) { + fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError()); + SDL_Quit(); + return EXIT_FAILURE; + } + + SDL_Renderer *renderer = SDL_CreateRenderer( + window, + -1, + SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC + ); + if (!renderer) { + fprintf(stderr, "SDL_CreateRenderer error: %s\n", SDL_GetError()); + SDL_DestroyWindow(window); + SDL_Quit(); + return EXIT_FAILURE; + } + + /* --------------------------------------------------------- + * Create a texture that will hold the framebuffer. + * SDL_PIXELFORMAT_ARGB8888 matches our pixel_t layout. + * --------------------------------------------------------- */ + SDL_Texture *texture = SDL_CreateTexture( + renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + WIDTH, + HEIGHT + ); + if (!texture) { + fprintf(stderr, "SDL_CreateTexture error: %s\n", SDL_GetError()); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + return EXIT_FAILURE; + } + + /* --------------------------------------------------------- + * Initialise the framebuffer with example data. + * --------------------------------------------------------- */ + init_framebuffer(); + + /* --------------------------------------------------------- + * Main loop + * --------------------------------------------------------- */ + bool quit = false; + SDL_Event ev; + + while (!quit) { + /* ----- Event handling --------------------------------- */ + while (SDL_PollEvent(&ev)) { + if (ev.type == SDL_QUIT) { + quit = true; + } else if (ev.type == SDL_KEYDOWN) { + /* Press Escape to quit */ + if (ev.key.keysym.sym == SDLK_ESCAPE) + quit = true; + } + } + + /* ----- Update texture from the framebuffer ------------ */ + void *tex_pixels; + int tex_pitch; // bytes per row + if (SDL_LockTexture(texture, NULL, &tex_pixels, &tex_pitch) != 0) { + fprintf(stderr, "SDL_LockTexture error: %s\n", SDL_GetError()); + break; + } + + /* Copy line‑by‑line because the pitch may differ from WIDTH*4 */ + for (int y = 0; y < HEIGHT; ++y) { + memcpy( + (Uint8 *)tex_pixels + y * tex_pitch, + framebuffer[y], + WIDTH * sizeof(pixel_t) + ); + } + SDL_UnlockTexture(texture); + + /* ----- Render ------------------------------------------ */ + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + /* The loop runs at the monitor refresh rate thanks to VSYNC. */ + } + + /* --------------------------------------------------------- + * Cleanup + * --------------------------------------------------------- */ + SDL_DestroyTexture(texture); + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); + + return EXIT_SUCCESS; +}