Files
waveform-draw/test.c
2025-12-07 11:23:27 +01:00

178 lines
6.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* -------------------------------------------------------------
* framebuffer_demo.c
* -------------------------------------------------------------
* A tiny example that:
* * allocates a 600×400 RGB888 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 <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/* -------------------------------------------------------------
* Configuration
* ------------------------------------------------------------- */
#define WIDTH 600
#define HEIGHT 400
/* -------------------------------------------------------------
* Simple pixel format helpers
* ------------------------------------------------------------- */
/* The framebuffer will be stored as 32bit 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 littleendian, 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 redtogreen 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 linebyline 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;
}