optimitzat textureToRenderer()

This commit is contained in:
2026-03-27 20:34:45 +01:00
parent deb0a8677f
commit c063488e8e
2 changed files with 53 additions and 21 deletions

View File

@@ -89,6 +89,10 @@ Screen::Screen()
border_surface_->setPalette(initial_palette);
border_surface_->clear(border_color_);
// Cachear el color ARGB inicial del borde (borde sólido por defecto)
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
border_argb_color_ = border_pixel_buffer_[0];
// Establece la surface que actuará como renderer para recibir las llamadas a render()
renderer_surface_ = std::make_shared<std::shared_ptr<Surface>>(game_surface_);
@@ -192,6 +196,11 @@ auto Screen::incWindowZoom() -> bool {
void Screen::setBorderColor(Uint8 color) {
border_color_ = color;
border_surface_->clear(border_color_);
// Actualizar caché ARGB del borde sólido (ocurre una vez por habitación, no cada frame)
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
border_argb_color_ = border_pixel_buffer_[0];
border_is_solid_ = true;
}
// Cambia entre borde visible y no visible
@@ -317,6 +326,12 @@ void Screen::setPalete() { // NOLINT(readability-convert-member-functions-to-st
// Convertir a mayúsculas
std::ranges::transform(Options::video.palette, Options::video.palette.begin(), ::toupper);
// Actualizar caché si el borde es sólido (la paleta cambia el valor ARGB del color)
if (border_is_solid_) {
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
border_argb_color_ = border_pixel_buffer_[0];
}
}
// Extrae los nombres de las paletas
@@ -343,30 +358,41 @@ void Screen::textureToRenderer() {
const int GAME_H = Options::game.height;
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 BORDER_H = window_height_;
const int OFF_X = static_cast<int>(game_surface_dstrect_.x);
const int OFF_Y = static_cast<int>(game_surface_dstrect_.y);
for (int y = 0; y < GAME_H; ++y) {
// 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];
if (border_is_solid_) {
// Path A: borde sólido (gameplay normal)
// Rellena solo el marco con el color cacheado — sin lookups de paleta.
// El área central (juego) se deja sin tocar; el overlay la sobreescribe igualmente.
// Copia de bloque de memoria (muy eficiente)
// Franjas superior e inferior (ancho completo)
std::fill_n(border_pixel_buffer_.data(), OFF_Y * BORDER_W, border_argb_color_);
std::fill_n(&border_pixel_buffer_[(OFF_Y + GAME_H) * BORDER_W],
(BORDER_H - OFF_Y - GAME_H) * BORDER_W, border_argb_color_);
// Columnas laterales en las filas del área de juego
for (int y = OFF_Y; y < OFF_Y + GAME_H; ++y) {
std::fill_n(&border_pixel_buffer_[y * BORDER_W], OFF_X, border_argb_color_);
std::fill_n(&border_pixel_buffer_[y * BORDER_W + OFF_X + GAME_W],
BORDER_W - OFF_X - GAME_W, border_argb_color_);
}
} else {
// Path B: borde dinámico (escena de carga — bandas de colores animadas)
// Conversión completa: la escena modifica border_surface_ cada frame
border_surface_->toARGBBuffer(border_pixel_buffer_.data());
}
// Overlay del juego sobre el centro del buffer (ambos paths)
game_surface_->toARGBBuffer(game_pixel_buffer_.data());
for (int y = 0; y < GAME_H; ++y) {
const Uint32* src = &game_pixel_buffer_[y * GAME_W];
Uint32* dst = &border_pixel_buffer_[(OFF_Y + y) * BORDER_W + OFF_X];
std::memcpy(dst, src, GAME_W * sizeof(Uint32));
}
// 4. Subida final de un único buffer completo
shader_backend_->uploadPixels(border_pixel_buffer_.data(), BORDER_W, window_height_);
shader_backend_->uploadPixels(border_pixel_buffer_.data(), BORDER_W, BORDER_H);
} else {
// Caso sin borde: subida directa simplificada
game_surface_->toARGBBuffer(game_pixel_buffer_.data());
@@ -492,7 +518,10 @@ void Screen::toggleVSync() {
// Getters
auto Screen::getRenderer() -> SDL_Renderer* { return renderer_; }
auto Screen::getRendererSurface() -> std::shared_ptr<Surface> { return (*renderer_surface_); }
auto Screen::getBorderSurface() -> std::shared_ptr<Surface> { return border_surface_; }
auto Screen::getBorderSurface() -> std::shared_ptr<Surface> {
border_is_solid_ = false; // Modificación externa → modo borde dinámico
return border_surface_;
}
auto loadData(const std::string& filepath) -> std::vector<uint8_t> {
// Load using ResourceHelper (supports both filesystem and pack)

View File

@@ -141,7 +141,11 @@ class Screen {
// Buffers persistentes para evitar .resize() cada frame
std::vector<Uint32> game_pixel_buffer_; // Textura de juego
std::vector<Uint32> border_pixel_buffer_; // Textura de borde
std::vector<Uint32> border_pixel_buffer_; // Textura de borde (composición final borde+juego)
// Caché del borde sólido (gameplay normal)
bool border_is_solid_{true}; // true = borde de color sólido; false = borde dinámico (carga)
Uint32 border_argb_color_{0}; // Color ARGB pre-convertido del borde sólido
// Configuración de ventana y pantalla
int window_width_{0}; // Ancho de la pantalla o ventana
@@ -159,9 +163,8 @@ class Screen {
DisplayMonitor display_monitor_; // Información de la pantalla
// Shaders
std::string info_resolution_; // Texto con la información de la pantalla
std::string gpu_driver_; // Nombre del driver GPU (SDL3GPU), capturado en initShaders()
std::vector<Uint32> pixel_buffer_; // Buffer intermedio para SDL3GPU path (surface → ARGB)
std::string info_resolution_; // Texto con la información de la pantalla
std::string gpu_driver_; // Nombre del driver GPU (SDL3GPU), capturado en initShaders()
#ifdef _DEBUG
bool show_fps_{true}; // Indica si ha de mostrar el contador de FPS