treballant en internal resolution
This commit is contained in:
@@ -37,6 +37,13 @@ Screen::Screen() {
|
||||
if (zoom_ < 1) zoom_ = 1;
|
||||
if (zoom_ > max_zoom_) zoom_ = max_zoom_;
|
||||
|
||||
// Clamp de la resolució interna a [1, max_zoom_]. Llegir del YAML i
|
||||
// ajustar aquí és l'únic moment en què es fa — el menú re-clampa cada
|
||||
// canvi. Si la pantalla és més petita que el valor desat (p.ex. canvi
|
||||
// de monitor), baixem al màxim suportat.
|
||||
if (Options::video.internal_resolution < 1) Options::video.internal_resolution = 1;
|
||||
if (Options::video.internal_resolution > max_zoom_) Options::video.internal_resolution = max_zoom_;
|
||||
|
||||
int w = GAME_WIDTH * zoom_;
|
||||
int h = Options::video.aspect_ratio_4_3 ? static_cast<int>(GAME_HEIGHT * 1.2F) * zoom_ : GAME_HEIGHT * zoom_;
|
||||
|
||||
@@ -66,6 +73,7 @@ Screen::~Screen() {
|
||||
shader_backend_.reset();
|
||||
}
|
||||
|
||||
if (internal_texture_sdl_) SDL_DestroyTexture(internal_texture_sdl_);
|
||||
if (texture_) SDL_DestroyTexture(texture_);
|
||||
if (renderer_) SDL_DestroyRenderer(renderer_);
|
||||
if (window_) SDL_DestroyWindow(window_);
|
||||
@@ -108,6 +116,8 @@ void Screen::initShaders() {
|
||||
shader_backend_->setOversample(3);
|
||||
}
|
||||
|
||||
shader_backend_->setInternalResolution(Options::video.internal_resolution);
|
||||
|
||||
// Resol el shader actiu des del config
|
||||
if (Options::video.current_shader == "crtpi") {
|
||||
shader_backend_->setActiveShader(Rendering::ShaderType::CRTPI);
|
||||
@@ -164,6 +174,33 @@ void Screen::present(Uint32* pixel_data) {
|
||||
} else {
|
||||
// Fallback SDL_Renderer
|
||||
SDL_UpdateTexture(texture_, nullptr, pixel_data, GAME_WIDTH * sizeof(Uint32));
|
||||
|
||||
const int mult = Options::video.internal_resolution;
|
||||
if (mult > 1) {
|
||||
// Resolució interna: còpia NN de texture_ → internal_texture_sdl_
|
||||
// (la fa SDL/GPU, no CPU). Tota la presentació downstream llegirà
|
||||
// d'aquesta textura més gran — el filtre LINEAR final parteix d'una
|
||||
// font més fina i l'estirament a finestra queda menys difús.
|
||||
ensureFallbackInternalTexture();
|
||||
if (internal_texture_sdl_ != nullptr) {
|
||||
SDL_SetTextureScaleMode(texture_, SDL_SCALEMODE_NEAREST);
|
||||
SDL_SetRenderTarget(renderer_, internal_texture_sdl_);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_RenderTexture(renderer_, texture_, nullptr, nullptr);
|
||||
SDL_SetRenderTarget(renderer_, nullptr);
|
||||
// El filtre global (LINEAR/NEAREST) s'aplica a l'estirament final
|
||||
// cap a la finestra; per això l'aplicam a la textura intermèdia.
|
||||
SDL_ScaleMode final_scale = (Options::video.texture_filter == Options::TextureFilter::LINEAR)
|
||||
? SDL_SCALEMODE_LINEAR
|
||||
: SDL_SCALEMODE_NEAREST;
|
||||
SDL_SetTextureScaleMode(internal_texture_sdl_, final_scale);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_RenderTexture(renderer_, internal_texture_sdl_, nullptr, nullptr);
|
||||
SDL_RenderPresent(renderer_);
|
||||
return;
|
||||
}
|
||||
// Si la creació de la textura ha fallat, caiem al path normal.
|
||||
}
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_RenderTexture(renderer_, texture_, nullptr, nullptr);
|
||||
SDL_RenderPresent(renderer_);
|
||||
@@ -261,6 +298,22 @@ void Screen::cycleTextureFilter(int dir) {
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::changeInternalResolution(int dir) {
|
||||
int next = Options::video.internal_resolution + (dir >= 0 ? 1 : -1);
|
||||
if (next < 1) next = 1;
|
||||
if (next > max_zoom_) next = max_zoom_;
|
||||
if (next == Options::video.internal_resolution) return;
|
||||
Options::video.internal_resolution = next;
|
||||
|
||||
// Propaga al backend actiu. Al fallback path, la textura es recrea al
|
||||
// pròxim present via ensureFallbackInternalTexture.
|
||||
if (shader_backend_) {
|
||||
shader_backend_->setInternalResolution(next);
|
||||
} else {
|
||||
applyFallbackPresentation();
|
||||
}
|
||||
}
|
||||
|
||||
auto Screen::nextShaderType() -> bool {
|
||||
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) return false;
|
||||
if (!Options::video.shader_enabled) return false;
|
||||
@@ -442,7 +495,41 @@ void Screen::applyFallbackPresentation() {
|
||||
case Options::ScalingMode::INTEGER: mode = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE; break;
|
||||
}
|
||||
}
|
||||
SDL_SetRenderLogicalPresentation(renderer_, GAME_WIDTH, GAME_HEIGHT, mode);
|
||||
// Amb resolució interna N > 1, la mida lògica creix proporcionalment
|
||||
// perquè SDL scale des de 320·N × 200·N a la finestra — menys aggressive linear.
|
||||
const int mult = Options::video.internal_resolution < 1 ? 1 : Options::video.internal_resolution;
|
||||
SDL_SetRenderLogicalPresentation(renderer_, GAME_WIDTH * mult, GAME_HEIGHT * mult, mode);
|
||||
}
|
||||
|
||||
void Screen::ensureFallbackInternalTexture() {
|
||||
const int mult = Options::video.internal_resolution;
|
||||
if (mult <= 1 || renderer_ == nullptr) {
|
||||
// No cal textura intermèdia. Si la teníem, la reciclem.
|
||||
if (internal_texture_sdl_ != nullptr) {
|
||||
SDL_DestroyTexture(internal_texture_sdl_);
|
||||
internal_texture_sdl_ = nullptr;
|
||||
internal_texture_mult_ = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (internal_texture_sdl_ != nullptr && internal_texture_mult_ == mult) return;
|
||||
|
||||
if (internal_texture_sdl_ != nullptr) {
|
||||
SDL_DestroyTexture(internal_texture_sdl_);
|
||||
internal_texture_sdl_ = nullptr;
|
||||
}
|
||||
internal_texture_sdl_ = SDL_CreateTexture(renderer_,
|
||||
SDL_PIXELFORMAT_ABGR8888,
|
||||
SDL_TEXTUREACCESS_TARGET,
|
||||
GAME_WIDTH * mult,
|
||||
GAME_HEIGHT * mult);
|
||||
if (internal_texture_sdl_ == nullptr) {
|
||||
std::cerr << "Screen: failed to create fallback internal texture (×" << mult << "): "
|
||||
<< SDL_GetError() << '\n';
|
||||
internal_texture_mult_ = 0;
|
||||
return;
|
||||
}
|
||||
internal_texture_mult_ = mult;
|
||||
}
|
||||
|
||||
void Screen::adjustWindowSize() {
|
||||
|
||||
Reference in New Issue
Block a user