blob: 0f5e734fb5c78f94e878402b62712aa35373745a [file] [log] [blame]
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <iostream>
#include "SDL.h"
#include "graphics/surface.hpp"
#include "Renderer.hpp"
#include "System.hpp"
Renderer::Renderer(SDL_Window *window, int width, int height) : sys_width(width), sys_height(height) {
//SDL_SetHint(SDL_HINT_RENDER_DRIVER, "openGL");
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer == nullptr) {
std::cerr << "could not create renderer: " << SDL_GetError() << std::endl;
}
current = fb_texture;
int w, h;
SDL_GetWindowSize(window, &w, &h);
resize(w, h);
set_mode(mode);
// Clear the window.
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
fb_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, sys_width, sys_height);
fb_565_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_BGR565, SDL_TEXTUREACCESS_STREAMING, sys_width, sys_height);
}
Renderer::~Renderer() {
SDL_DestroyTexture(fb_texture);
SDL_DestroyTexture(fb_565_texture);
SDL_DestroyRenderer(renderer);
}
void Renderer::set_mode(Mode new_mode) {
mode = new_mode;
int w = is_lores ? sys_width / 2 : sys_width;
int h = is_lores ? sys_height / 2 : sys_height;
SDL_RenderSetLogicalSize(renderer, w, h);
SDL_RenderSetIntegerScale(renderer, (mode == KeepPixels) ? SDL_TRUE : SDL_FALSE);
if (mode == Stretch) {
// override the automatic scaling to not preserve the ratio
SDL_RenderSetViewport(renderer, nullptr);
SDL_RenderSetScale(renderer, (float)win_width / w, (float)win_height / h);
}
}
void Renderer::resize(int width, int height) {
win_width = width;
win_height = height;
if (mode == Stretch)
set_mode(mode);
}
void Renderer::update(System *sys) {
auto format = blit::PixelFormat(sys->format());
current = format == blit::PixelFormat::RGB565 ? fb_565_texture : fb_texture;
if(is_lores != (sys->mode() == 0)) {
is_lores = sys->mode() == 0;
set_mode(mode);
}
sys->update_texture(current);
}
void Renderer::_render(SDL_Texture *target, SDL_Rect *destination) {
SDL_SetRenderTarget(renderer, target);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, current, nullptr, destination);
}
void Renderer::present() {
SDL_Rect dest;
dest.x = 0;
dest.y = 0;
dest.w = sys_width;
dest.h = sys_height;
_render(nullptr, &dest);
SDL_RenderPresent(renderer);
}
void Renderer::read_pixels(int width, int height, Uint32 format, Uint8 *buffer) {
SDL_Texture *record_target = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, width, height);
_render(record_target, nullptr);
SDL_RenderReadPixels(renderer, nullptr, format, buffer, width*SDL_BYTESPERPIXEL(format));
SDL_DestroyTexture(record_target);
}