diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 58926b2..1daba98 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -43,9 +43,11 @@ Screen::Screen() : palettes_(Resource::List::get()->getListByType(Resource::List::Type::PALETTE)) { // Arranca SDL VIDEO, crea la ventana y el renderizador initSDLVideo(); - if (Options::video.fullscreen) { - SDL_HideCursor(); - } + if (Options::video.fullscreen) { SDL_HideCursor(); } + + // Calcular tamaños y hacer .resize() de los buffers de píxeles + adjustWindowSize(); + adjustRenderLogicalSize(); // 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}; @@ -245,7 +247,8 @@ void Screen::adjustWindowSize() { window_height_ = Options::game.height + (Options::video.border.enabled ? Options::video.border.height * 2 : 0); // Reservamos memoria una sola vez. - // game_pixel_buffer_ contendrá solo los píxeles del área de juego. + // Si el buffer es más pequeño que la superficie, crash asegurado. + border_pixel_buffer_.resize(static_cast(window_width_ * window_height_)); game_pixel_buffer_.resize(static_cast(Options::game.width * Options::game.height)); // border_pixel_buffer_ es el buffer que se sube a la GPU (tamaño total ventana). @@ -416,6 +419,10 @@ void Screen::renderInfo() const { text_->write(X, y, FPS_TEXT); y += LINE_HEIGHT; + // Driver GPU + text_->write(X, y, gpu_driver_.empty() ? "sdl" : gpu_driver_); + y += LINE_HEIGHT; + // Zoom de la ventana const std::string ZOOM_TEXT = "zoom x" + std::to_string(Options::window.zoom); text_->write(X, y, ZOOM_TEXT); @@ -523,6 +530,7 @@ void Screen::initShaders() { shader_backend_ = std::make_unique(); } shader_backend_->init(window_, tex, "", ""); + gpu_driver_ = shader_backend_->getDriverName(); // Propagar flags de vsync e integer scale al backend GPU shader_backend_->setVSync(Options::video.vertical_sync); diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index 79a81d3..8189fd4 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -160,6 +160,7 @@ class Screen { // 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 pixel_buffer_; // Buffer intermedio para SDL3GPU path (surface → ARGB) #ifdef _DEBUG diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp index dea06f4..015642d 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp @@ -239,7 +239,8 @@ namespace Rendering { SDL_Log("SDL3GPUShader: SDL_CreateGPUDevice failed: %s", SDL_GetError()); return false; } - SDL_Log("SDL3GPUShader: driver = %s", SDL_GetGPUDeviceDriver(device_)); + driver_name_ = SDL_GetGPUDeviceDriver(device_); + SDL_Log("SDL3GPUShader: driver = %s", driver_name_.c_str()); // ---------------------------------------------------------------- // 2. Claim window (una sola vez — no liberar hasta destroy()) diff --git a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp index e505f55..9b64cdd 100644 --- a/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp +++ b/source/core/rendering/sdl3gpu/sdl3gpu_shader.hpp @@ -47,6 +47,7 @@ namespace Rendering { void cleanup() final; // Libera pipeline/texturas pero mantiene el device vivo void destroy(); // Limpieza completa (device + swapchain); llamar solo al cerrar [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } + [[nodiscard]] auto getDriverName() const -> std::string override { return driver_name_; } // Sube píxeles ARGB8888 desde CPU; llamado antes de render() void uploadPixels(const Uint32* pixels, int width, int height) override; @@ -100,6 +101,7 @@ namespace Rendering { int game_height_ = 0; int ss_factor_ = 0; // Factor SS activo (3, 6, 9...) o 0 si SS desactivado int oversample_ = 1; // SS on/off (1 = off, >1 = on) + std::string driver_name_; bool is_initialized_ = false; bool vsync_ = true; bool integer_scale_ = false; diff --git a/source/core/rendering/shader_backend.hpp b/source/core/rendering/shader_backend.hpp index a040f4d..428b885 100644 --- a/source/core/rendering/shader_backend.hpp +++ b/source/core/rendering/shader_backend.hpp @@ -95,6 +95,12 @@ namespace Rendering { * @return true si usa aceleración (OpenGL/Metal/Vulkan) */ [[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0; + + /** + * @brief Nombre del driver GPU activo (p.ej. "vulkan", "metal", "direct3d12") + * @return Cadena vacía si no disponible + */ + [[nodiscard]] virtual auto getDriverName() const -> std::string { return {}; } }; } // namespace Rendering diff --git a/source/core/rendering/surface.cpp b/source/core/rendering/surface.cpp index ec1d79e..18f0479 100644 --- a/source/core/rendering/surface.cpp +++ b/source/core/rendering/surface.cpp @@ -524,14 +524,24 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height } // Vuelca los píxeles como ARGB8888 a un buffer externo (sin SDL_Texture ni SDL_Renderer) -void Surface::toARGBBuffer(Uint32* buffer) const { // NOLINT(readability-convert-member-functions-to-static) - if (!surface_data_ || (surface_data_->data == nullptr)) { return; } +void Surface::toARGBBuffer(Uint32* buffer) const { + if (!surface_data_ || !surface_data_->data || !buffer) { return; } + const int WIDTH = static_cast(surface_data_->width); const int HEIGHT = static_cast(surface_data_->height); const Uint8* src = surface_data_->data.get(); - for (int y = 0; y < HEIGHT; ++y) { - for (int x = 0; x < WIDTH; ++x) { - buffer[(y * WIDTH) + x] = palette_[src[(y * WIDTH) + x]]; + + // Obtenemos el tamaño de la paleta para evitar accesos fuera de rango + const size_t PAL_SIZE = palette_.size(); + + for (int i = 0; i < WIDTH * HEIGHT; ++i) { + Uint8 color_index = src[i]; + + // Verificación de seguridad: ¿El índice existe en la paleta? + if (color_index < PAL_SIZE) { + buffer[i] = palette_[color_index]; + } else { + buffer[i] = 0xFF000000; // Negro opaco si el índice es erróneo } } }