89 lines
3.2 KiB
C
89 lines
3.2 KiB
C
#include "render.h"
|
|
#include "program.h"
|
|
#include "debug.h"
|
|
#include <SDL2/SDL_pixels.h>
|
|
#include <SDL2/SDL_render.h>
|
|
|
|
SDL_Renderer* g_renderer;
|
|
SDL_Texture* g_render_target;
|
|
SDL_Rect g_render_area;
|
|
IVector g_render_resolution;
|
|
|
|
void render_init(SDL_Window* window, const struct ProgramSettings* settings) {
|
|
LOG_INFO("render_init");
|
|
// create renderer, needs to be able to target textures, preferably hardware accelerated
|
|
g_renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
|
|
// create render target texture
|
|
g_render_target = SDL_CreateTexture(
|
|
g_renderer,
|
|
SDL_PIXELFORMAT_ARGB32,
|
|
SDL_TEXTUREACCESS_TARGET,
|
|
settings->view_resolution.x, settings->view_resolution.y);
|
|
|
|
// store the desired view resolution
|
|
g_render_resolution = settings->view_resolution;
|
|
|
|
// get the destination area for rendering the target onto the window
|
|
render_calculate_render_area();
|
|
|
|
// clear target black
|
|
SDL_SetRenderTarget(g_renderer, g_render_target);
|
|
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(g_renderer);
|
|
}
|
|
|
|
void render_clean() {
|
|
// clear up allocated SDL objects
|
|
SDL_DestroyTexture(g_render_target);
|
|
SDL_DestroyRenderer(g_renderer);
|
|
}
|
|
|
|
void render_present() {
|
|
// clear window white
|
|
SDL_SetRenderTarget(g_renderer, NULL);
|
|
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(g_renderer);
|
|
// copy render target
|
|
SDL_Rect source_rect = {0, 0, g_render_resolution.x, g_render_resolution.y};
|
|
SDL_RenderCopy(g_renderer, g_render_target, &source_rect, &g_render_area);
|
|
SDL_RenderPresent(g_renderer);
|
|
// clear render target
|
|
SDL_SetRenderTarget(g_renderer, g_render_target);
|
|
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
|
|
SDL_RenderClear(g_renderer);
|
|
}
|
|
|
|
void render_calculate_render_area() {
|
|
// get aspect ratios of both the window and the rendertexture
|
|
IVector window_resolution = render_get_window_size();
|
|
float window_aspect = (float)window_resolution.x / (float)window_resolution.y;
|
|
float target_aspect = (float)g_render_resolution.x / (float)g_render_resolution.y;
|
|
|
|
// calculate the largest area that will fit the entire rendertexture into the window space
|
|
g_render_area = (SDL_Rect) {0, 0, window_resolution.x, window_resolution.y};
|
|
if(window_aspect <= target_aspect) {
|
|
g_render_area.h = window_resolution.x / target_aspect;
|
|
g_render_area.y = (window_resolution.y - g_render_area.h) / 2;
|
|
} else {
|
|
g_render_area.w = window_resolution.y * target_aspect;
|
|
g_render_area.x += (window_resolution.x - g_render_area.w) / 2;
|
|
}
|
|
}
|
|
|
|
IVector render_get_window_size() {
|
|
// select window as target (store target to reset)
|
|
SDL_Texture* target = SDL_GetRenderTarget(g_renderer);
|
|
SDL_SetRenderTarget(g_renderer, NULL);
|
|
// fetch output size (= window size) of renderer
|
|
int window_width, window_height;
|
|
SDL_GetRendererOutputSize(g_renderer, &window_width, &window_height);
|
|
// reset render target
|
|
SDL_SetRenderTarget(g_renderer, target);
|
|
// construct IVector from fetched output size
|
|
return (IVector){window_width, window_height};
|
|
}
|
|
|
|
void render_handle_resize() {
|
|
render_calculate_render_area();
|
|
}
|