#include "render.h" #include "program.h" #include "debug.h" #include #include 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(); }