| #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); |
| } |
| |