forked from jaildesigner-jailgames/jaildoctors_dilemma
optimitzant textureToRenderer()
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <algorithm> // Para max, min, transform
|
||||
#include <cctype> // Para toupper
|
||||
#include <cstring> // Para memcpy
|
||||
#include <fstream> // Para basic_ostream, operator<<, endl, basic_...
|
||||
#include <iostream> // Para cerr
|
||||
#include <iterator> // Para istreambuf_iterator, operator==
|
||||
@@ -48,7 +49,6 @@ Screen::Screen()
|
||||
|
||||
// Ajusta los tamaños
|
||||
game_surface_dstrect_ = {.x = Options::video.border.width, .y = Options::video.border.height, .w = Options::game.width, .h = Options::game.height};
|
||||
// adjustWindowSize();
|
||||
current_palette_ = findPalette(Options::video.palette);
|
||||
|
||||
// Define el color del borde para el modo de pantalla completa
|
||||
@@ -244,21 +244,27 @@ void Screen::adjustWindowSize() {
|
||||
window_width_ = Options::game.width + (Options::video.border.enabled ? Options::video.border.width * 2 : 0);
|
||||
window_height_ = Options::game.height + (Options::video.border.enabled ? Options::video.border.height * 2 : 0);
|
||||
|
||||
// Establece el nuevo tamaño
|
||||
// Reservamos memoria una sola vez.
|
||||
// game_pixel_buffer_ contendrá solo los píxeles del área de juego.
|
||||
game_pixel_buffer_.resize(static_cast<size_t>(Options::game.width * Options::game.height));
|
||||
|
||||
// border_pixel_buffer_ es el buffer que se sube a la GPU (tamaño total ventana).
|
||||
if (Options::video.border.enabled) {
|
||||
border_pixel_buffer_.resize(static_cast<size_t>(window_width_ * window_height_));
|
||||
}
|
||||
|
||||
// Lógica de centrado y redimensionado de ventana SDL
|
||||
if (static_cast<int>(Options::video.fullscreen) == 0) {
|
||||
int old_width;
|
||||
int old_height;
|
||||
SDL_GetWindowSize(window_, &old_width, &old_height);
|
||||
int old_w, old_h;
|
||||
SDL_GetWindowSize(window_, &old_w, &old_h);
|
||||
int old_x, old_y;
|
||||
SDL_GetWindowPosition(window_, &old_x, &old_y);
|
||||
|
||||
int old_pos_x;
|
||||
int old_pos_y;
|
||||
SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y);
|
||||
|
||||
const int NEW_POS_X = old_pos_x + ((old_width - (window_width_ * Options::window.zoom)) / 2);
|
||||
const int NEW_POS_Y = old_pos_y + ((old_height - (window_height_ * Options::window.zoom)) / 2);
|
||||
const int NEW_X = old_x + ((old_w - (window_width_ * Options::window.zoom)) / 2);
|
||||
const int NEW_Y = old_y + ((old_h - (window_height_ * Options::window.zoom)) / 2);
|
||||
|
||||
SDL_SetWindowSize(window_, window_width_ * Options::window.zoom, window_height_ * Options::window.zoom);
|
||||
SDL_SetWindowPosition(window_, std::max(NEW_POS_X, WINDOWS_DECORATIONS), std::max(NEW_POS_Y, 0));
|
||||
SDL_SetWindowPosition(window_, std::max(NEW_X, WINDOWS_DECORATIONS), std::max(NEW_Y, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,42 +336,47 @@ void Screen::surfaceToTexture() { // NOLINT(readability-convert-member-function
|
||||
// Copia la textura al renderizador (o hace el present GPU)
|
||||
void Screen::textureToRenderer() {
|
||||
if (shader_backend_ && shader_backend_->isHardwareAccelerated()) {
|
||||
// ---- SDL3 GPU path: convertir Surface → ARGB → upload → PostFX/pass-through → present ----
|
||||
if (Options::video.border.enabled) {
|
||||
// El border_surface_ solo tiene el color de borde; hay que componer encima el game_surface_
|
||||
const int BORDER_W = static_cast<int>(border_surface_->getWidth());
|
||||
const int BORDER_H = static_cast<int>(border_surface_->getHeight());
|
||||
pixel_buffer_.resize(static_cast<size_t>(BORDER_W * BORDER_H));
|
||||
border_surface_->toARGBBuffer(pixel_buffer_.data());
|
||||
const int GAME_W = Options::game.width;
|
||||
const int GAME_H = Options::game.height;
|
||||
|
||||
// Compositar game_surface_ en la posición correcta dentro del buffer
|
||||
const int GAME_W = static_cast<int>(game_surface_->getWidth());
|
||||
const int GAME_H = static_cast<int>(game_surface_->getHeight());
|
||||
if (Options::video.border.enabled) {
|
||||
// 1. Volcamos la Surface del borde al buffer (aquí van las franjas de carga)
|
||||
// Esto es mucho más rápido que un bucle manual
|
||||
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
|
||||
|
||||
// 2. Extraemos los píxeles del juego
|
||||
game_surface_->toARGBBuffer(game_pixel_buffer_.data());
|
||||
|
||||
// 3. Superponemos el juego sobre el borde (Composición por filas)
|
||||
const int BORDER_W = window_width_;
|
||||
const int OFF_X = static_cast<int>(game_surface_dstrect_.x);
|
||||
const int OFF_Y = static_cast<int>(game_surface_dstrect_.y);
|
||||
std::vector<Uint32> game_pixels(static_cast<size_t>(GAME_W * GAME_H));
|
||||
game_surface_->toARGBBuffer(game_pixels.data());
|
||||
|
||||
for (int y = 0; y < GAME_H; ++y) {
|
||||
for (int x = 0; x < GAME_W; ++x) {
|
||||
pixel_buffer_[static_cast<size_t>(((OFF_Y + y) * BORDER_W) + (OFF_X + x))] = game_pixels[static_cast<size_t>((y * GAME_W) + x)];
|
||||
}
|
||||
// Puntero de origen (fila Y del juego)
|
||||
const Uint32* src = &game_pixel_buffer_[y * GAME_W];
|
||||
// Puntero de destino (fila Y + offset en el buffer global)
|
||||
Uint32* dst = &border_pixel_buffer_[(OFF_Y + y) * BORDER_W + OFF_X];
|
||||
|
||||
// Copia de bloque de memoria (muy eficiente)
|
||||
std::memcpy(dst, src, GAME_W * sizeof(Uint32));
|
||||
}
|
||||
shader_backend_->uploadPixels(pixel_buffer_.data(), BORDER_W, BORDER_H);
|
||||
|
||||
// 4. Subida final de un único buffer completo
|
||||
shader_backend_->uploadPixels(border_pixel_buffer_.data(), BORDER_W, window_height_);
|
||||
} else {
|
||||
const int GAME_W = static_cast<int>(game_surface_->getWidth());
|
||||
const int GAME_H = static_cast<int>(game_surface_->getHeight());
|
||||
pixel_buffer_.resize(static_cast<size_t>(GAME_W * GAME_H));
|
||||
game_surface_->toARGBBuffer(pixel_buffer_.data());
|
||||
shader_backend_->uploadPixels(pixel_buffer_.data(), GAME_W, GAME_H);
|
||||
// Caso sin borde: subida directa simplificada
|
||||
game_surface_->toARGBBuffer(game_pixel_buffer_.data());
|
||||
shader_backend_->uploadPixels(game_pixel_buffer_.data(), GAME_W, GAME_H);
|
||||
}
|
||||
|
||||
shader_backend_->render();
|
||||
} else {
|
||||
// ---- SDL_Renderer path (fallback / no-shader) ----
|
||||
SDL_Texture* texture_to_render = Options::video.border.enabled ? border_texture_ : game_texture_;
|
||||
// Fallback SDL_Renderer (mantiene tu lógica de texturas SDL)
|
||||
SDL_Texture* tex = Options::video.border.enabled ? border_texture_ : game_texture_;
|
||||
SDL_SetRenderTarget(renderer_, nullptr);
|
||||
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_RenderTexture(renderer_, texture_to_render, nullptr, nullptr);
|
||||
SDL_RenderTexture(renderer_, tex, nullptr, nullptr);
|
||||
SDL_RenderPresent(renderer_);
|
||||
}
|
||||
}
|
||||
@@ -634,7 +645,6 @@ auto Screen::initSDLVideo() -> bool {
|
||||
void Screen::createText() { // NOLINT(readability-convert-member-functions-to-static)
|
||||
// Carga la surface de la fuente directamente del archivo
|
||||
auto surface = std::make_shared<Surface>(Resource::List::get()->get("aseprite.gif"));
|
||||
//surface->setTransparentColor(static_cast<Uint8>(PaletteColor::BLACK));
|
||||
|
||||
// Crea el objeto de texto (el constructor de Text carga el archivo text_file internamente)
|
||||
text_ = std::make_shared<Text>(surface, Resource::List::get()->get("aseprite.fnt"));
|
||||
|
||||
Reference in New Issue
Block a user