From c836f3758fe52cff7abc822f104d0edc71167569 Mon Sep 17 00:00:00 2001 From: Abdelrahman Said Date: Mon, 18 Dec 2023 13:25:02 +0000 Subject: [PATCH] Implement basic window abstraction --- include/window/window.h | 31 +++++++++ src/window/window.c | 144 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 include/window/window.h create mode 100644 src/window/window.c diff --git a/include/window/window.h b/include/window/window.h new file mode 100644 index 0000000..bc99300 --- /dev/null +++ b/include/window/window.h @@ -0,0 +1,31 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include "c_cpp_aliases/aliases.h" +#include +#include + +typedef struct { + u8 r; + u8 g; + u8 b; + u8 a; +} colour_t; + +typedef struct { + u64 width; + u64 height; + const char *title; + SDL_Window *window; + SDL_Surface *front_buffer; + SDL_Surface *back_buffer; +} window_t; + +bool init_window(window_t *wnd, u64 width, u64 height, const char *title); +void close_window(window_t *wnd); + +void clear_window(window_t *wnd, colour_t colour); +void set_pixel(window_t *wnd, f32 x, f32 y, colour_t colour); +void swap_buffers(window_t *wnd); + +#endif // !WINDOW_H diff --git a/src/window/window.c b/src/window/window.c new file mode 100644 index 0000000..b3f299f --- /dev/null +++ b/src/window/window.c @@ -0,0 +1,144 @@ +#include "window/window.h" +#include "c_cpp_aliases/aliases.h" +#include +#include +#include +#include +#include +#include + +#define NORMALISED_MIN -1.0f +#define NORMALISED_MAX 1.0f + +u32 colour_to_u32(colour_t colour); +u32 index_from_coordinates(window_t *wnd, u32 x, u32 y); +i32 denormalise(f32 value, u32 max); +void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour); + +bool init_window(window_t *wnd, u64 width, u64 height, const char *title) { + if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { + printf("Failed to initialise SDL: %s\n", SDL_GetError()); + + return false; + } + + wnd->window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, width, height, 0); + if (!(wnd->window)) { + printf("Failed to create window: %s\n", SDL_GetError()); + + close_window(wnd); + + return false; + } + + wnd->front_buffer = SDL_GetWindowSurface(wnd->window); + if (!(wnd->front_buffer)) { + printf("Failed to get front buffer: %s\n", SDL_GetError()); + + close_window(wnd); + + return false; + } + + wnd->back_buffer = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, + SDL_PIXELFORMAT_ABGR32); + if (!(wnd->back_buffer)) { + printf("Failed to create back buffer: %s\n", SDL_GetError()); + + close_window(wnd); + + return false; + } + + wnd->width = width; + wnd->height = height; + wnd->title = title; + + return true; +} + +void close_window(window_t *wnd) { + if (wnd) { + wnd->width = 0; + wnd->height = 0; + wnd->title = ""; + + if (wnd->window) { + SDL_DestroyWindow(wnd->window); + + wnd->window = NULL; + } + + if (wnd->back_buffer) { + SDL_FreeSurface(wnd->back_buffer); + + wnd->back_buffer = NULL; + } + } + + SDL_Quit(); +} + +void clear_window(window_t *wnd, colour_t colour) { + SDL_LockSurface(wnd->back_buffer); + + u32 c = colour_to_u32(colour); + + u32 *pixels = (u32 *)(wnd->back_buffer->pixels); + u32 count = wnd->back_buffer->w * wnd->back_buffer->h; + + for (u32 i = 0; i < count; ++i) { + pixels[i] = c; + } + + SDL_UnlockSurface(wnd->back_buffer); +} + +void set_pixel(window_t *wnd, f32 x, f32 y, colour_t colour) { + i32 screen_x = denormalise(x, wnd->width); + i32 screen_y = denormalise(-y, wnd->height); + + if (screen_x < 0 || screen_y < 0) { + return; + } + + SDL_LockSurface(wnd->back_buffer); + + set_screen_pixel(wnd, screen_x, screen_y, colour); + + SDL_UnlockSurface(wnd->back_buffer); +} + +void swap_buffers(window_t *wnd) { + SDL_BlitSurface(wnd->back_buffer, NULL, wnd->front_buffer, NULL); + + SDL_UpdateWindowSurface(wnd->window); +} + +u32 colour_to_u32(colour_t colour) { + return ((u32)(colour.r) << 24) | ((u32)(colour.g) << 16) | + ((u32)(colour.b) << 8) | (u32)(colour.a); +} + +u32 index_from_coordinates(window_t *wnd, u32 x, u32 y) { + return y * wnd->width + x; +} + +i32 denormalise(f32 value, u32 max) { + if (max == 0 || value < NORMALISED_MIN || value >= NORMALISED_MAX) { + return -1; + } + + return (i32)(((value - NORMALISED_MIN) * max) / + (NORMALISED_MAX - NORMALISED_MIN)); +} + +void set_screen_pixel(window_t *wnd, u32 x, u32 y, colour_t colour) { + u32 index = index_from_coordinates(wnd, x, y); + u32 c = colour_to_u32(colour); + + u32 *pixels = (u32 *)(wnd->back_buffer->pixels); + + pixels[index] = c; +}