mirror of
https://github.com/citra-emu/citra.git
synced 2025-02-17 05:01:04 +00:00
integer res_scale and cleanup
This commit is contained in:
parent
96861c6347
commit
926abc6ddb
@ -88,7 +88,7 @@ void Config::ReadValues() {
|
||||
Settings::values.use_hw_renderer = sdl2_config->GetBoolean("Renderer", "use_hw_renderer", true);
|
||||
Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true);
|
||||
Settings::values.resolution_factor =
|
||||
(float)sdl2_config->GetReal("Renderer", "resolution_factor", 1.0);
|
||||
static_cast<u16>(sdl2_config->GetInteger("Renderer", "resolution_factor", 1));
|
||||
Settings::values.use_vsync = sdl2_config->GetBoolean("Renderer", "use_vsync", false);
|
||||
Settings::values.toggle_framelimit =
|
||||
sdl2_config->GetBoolean("Renderer", "toggle_framelimit", true);
|
||||
|
@ -73,7 +73,8 @@ void Config::ReadValues() {
|
||||
qt_config->beginGroup("Renderer");
|
||||
Settings::values.use_hw_renderer = qt_config->value("use_hw_renderer", true).toBool();
|
||||
Settings::values.use_shader_jit = qt_config->value("use_shader_jit", true).toBool();
|
||||
Settings::values.resolution_factor = qt_config->value("resolution_factor", 1.0).toFloat();
|
||||
Settings::values.resolution_factor =
|
||||
static_cast<u16>(qt_config->value("resolution_factor", 1).toInt());
|
||||
Settings::values.use_vsync = qt_config->value("use_vsync", false).toBool();
|
||||
Settings::values.toggle_framelimit = qt_config->value("toggle_framelimit", true).toBool();
|
||||
|
||||
|
@ -20,81 +20,11 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
||||
|
||||
ConfigureGraphics::~ConfigureGraphics() {}
|
||||
|
||||
enum class Resolution : int {
|
||||
Auto,
|
||||
Scale1x,
|
||||
Scale2x,
|
||||
Scale3x,
|
||||
Scale4x,
|
||||
Scale5x,
|
||||
Scale6x,
|
||||
Scale7x,
|
||||
Scale8x,
|
||||
Scale9x,
|
||||
Scale10x,
|
||||
};
|
||||
|
||||
float ToResolutionFactor(Resolution option) {
|
||||
switch (option) {
|
||||
case Resolution::Auto:
|
||||
return 0.f;
|
||||
case Resolution::Scale1x:
|
||||
return 1.f;
|
||||
case Resolution::Scale2x:
|
||||
return 2.f;
|
||||
case Resolution::Scale3x:
|
||||
return 3.f;
|
||||
case Resolution::Scale4x:
|
||||
return 4.f;
|
||||
case Resolution::Scale5x:
|
||||
return 5.f;
|
||||
case Resolution::Scale6x:
|
||||
return 6.f;
|
||||
case Resolution::Scale7x:
|
||||
return 7.f;
|
||||
case Resolution::Scale8x:
|
||||
return 8.f;
|
||||
case Resolution::Scale9x:
|
||||
return 9.f;
|
||||
case Resolution::Scale10x:
|
||||
return 10.f;
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
Resolution FromResolutionFactor(float factor) {
|
||||
if (factor == 0.f) {
|
||||
return Resolution::Auto;
|
||||
} else if (factor == 1.f) {
|
||||
return Resolution::Scale1x;
|
||||
} else if (factor == 2.f) {
|
||||
return Resolution::Scale2x;
|
||||
} else if (factor == 3.f) {
|
||||
return Resolution::Scale3x;
|
||||
} else if (factor == 4.f) {
|
||||
return Resolution::Scale4x;
|
||||
} else if (factor == 5.f) {
|
||||
return Resolution::Scale5x;
|
||||
} else if (factor == 6.f) {
|
||||
return Resolution::Scale6x;
|
||||
} else if (factor == 7.f) {
|
||||
return Resolution::Scale7x;
|
||||
} else if (factor == 8.f) {
|
||||
return Resolution::Scale8x;
|
||||
} else if (factor == 9.f) {
|
||||
return Resolution::Scale9x;
|
||||
} else if (factor == 10.f) {
|
||||
return Resolution::Scale10x;
|
||||
}
|
||||
return Resolution::Auto;
|
||||
}
|
||||
|
||||
void ConfigureGraphics::setConfiguration() {
|
||||
ui->toggle_hw_renderer->setChecked(Settings::values.use_hw_renderer);
|
||||
ui->resolution_factor_combobox->setEnabled(Settings::values.use_hw_renderer);
|
||||
ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit);
|
||||
ui->resolution_factor_combobox->setCurrentIndex(
|
||||
static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor)));
|
||||
ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor);
|
||||
ui->toggle_vsync->setChecked(Settings::values.use_vsync);
|
||||
ui->toggle_framelimit->setChecked(Settings::values.toggle_framelimit);
|
||||
ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option));
|
||||
@ -105,7 +35,7 @@ void ConfigureGraphics::applyConfiguration() {
|
||||
Settings::values.use_hw_renderer = ui->toggle_hw_renderer->isChecked();
|
||||
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
||||
Settings::values.resolution_factor =
|
||||
ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex()));
|
||||
static_cast<u16>(ui->resolution_factor_combobox->currentIndex());
|
||||
Settings::values.use_vsync = ui->toggle_vsync->isChecked();
|
||||
Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked();
|
||||
Settings::values.layout_option =
|
||||
|
@ -16,8 +16,8 @@ static const float TOP_SCREEN_ASPECT_RATIO =
|
||||
static const float BOT_SCREEN_ASPECT_RATIO =
|
||||
static_cast<float>(Core::kScreenBottomHeight) / Core::kScreenBottomWidth;
|
||||
|
||||
float FramebufferLayout::GetScalingRatio() const {
|
||||
return static_cast<float>(top_screen.GetWidth()) / Core::kScreenTopWidth;
|
||||
u16 FramebufferLayout::GetScalingRatio() const {
|
||||
return static_cast<u16>(((top_screen.GetWidth() - 1) / Core::kScreenTopWidth) + 1);
|
||||
}
|
||||
|
||||
// Finds the largest size subrectangle contained in window area that is confined to the aspect ratio
|
||||
|
@ -21,7 +21,7 @@ struct FramebufferLayout {
|
||||
* Returns the ration of pixel size of the top screen, compared to the native size of the 3DS
|
||||
* screen.
|
||||
*/
|
||||
float GetScalingRatio() const;
|
||||
u16 GetScalingRatio() const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -95,7 +95,7 @@ struct Values {
|
||||
// Renderer
|
||||
bool use_hw_renderer;
|
||||
bool use_shader_jit;
|
||||
float resolution_factor;
|
||||
u16 resolution_factor;
|
||||
bool use_vsync;
|
||||
bool toggle_framelimit;
|
||||
|
||||
|
@ -245,7 +245,7 @@ void RasterizerOpenGL::DrawTriangles() {
|
||||
// Sync and bind the framebuffer surfaces
|
||||
Surface color_surface;
|
||||
Surface depth_surface;
|
||||
MathUtil::Rectangle<int> rect;
|
||||
MathUtil::Rectangle<u32> rect;
|
||||
std::tie(color_surface, depth_surface, rect) =
|
||||
res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb);
|
||||
|
||||
@ -279,37 +279,32 @@ void RasterizerOpenGL::DrawTriangles() {
|
||||
const GLsizei viewport_height =
|
||||
static_cast<GLsizei>(Pica::float24::FromRaw(regs.rasterizer.viewport_size_y).ToFloat32() * 2);
|
||||
|
||||
const float res_scale_width = color_surface != nullptr ? color_surface->res_scale_width :
|
||||
(depth_surface == nullptr ? 1.0f : depth_surface->res_scale_width);
|
||||
const float res_scale_height = color_surface != nullptr ? color_surface->res_scale_height :
|
||||
(depth_surface == nullptr ? 1.0f : depth_surface->res_scale_height);
|
||||
const u16 res_scale = color_surface != nullptr ? color_surface->res_scale :
|
||||
(depth_surface == nullptr ? 1u : depth_surface->res_scale);
|
||||
|
||||
glViewport(
|
||||
static_cast<GLint>(rect.left + regs.rasterizer.viewport_corner.x * res_scale_width),
|
||||
static_cast<GLint>(rect.bottom + regs.rasterizer.viewport_corner.y * res_scale_height),
|
||||
static_cast<GLsizei>(viewport_width * res_scale_width),
|
||||
static_cast<GLsizei>(viewport_height * res_scale_height));
|
||||
static_cast<GLint>(rect.left + regs.rasterizer.viewport_corner.x * res_scale),
|
||||
static_cast<GLint>(rect.bottom + regs.rasterizer.viewport_corner.y * res_scale),
|
||||
viewport_width * res_scale,
|
||||
viewport_height * res_scale);
|
||||
|
||||
if (uniform_block_data.data.framebuffer_scale[0] != res_scale_width ||
|
||||
uniform_block_data.data.framebuffer_scale[1] != res_scale_height) {
|
||||
|
||||
uniform_block_data.data.framebuffer_scale[0] = res_scale_width;
|
||||
uniform_block_data.data.framebuffer_scale[1] = res_scale_height;
|
||||
if (uniform_block_data.data.framebuffer_scale != res_scale) {
|
||||
uniform_block_data.data.framebuffer_scale = res_scale;
|
||||
uniform_block_data.dirty = true;
|
||||
}
|
||||
|
||||
// Scissor checks are window-, not viewport-relative, which means that if the cached texture
|
||||
// sub-rect changes, the scissor bounds also need to be updated.
|
||||
GLint scissor_x1 = static_cast<GLint>(
|
||||
rect.left + regs.rasterizer.scissor_test.x1 * res_scale_width);
|
||||
rect.left + regs.rasterizer.scissor_test.x1 * res_scale);
|
||||
GLint scissor_y1 = static_cast<GLint>(
|
||||
rect.bottom + regs.rasterizer.scissor_test.y1 * res_scale_height);
|
||||
rect.bottom + regs.rasterizer.scissor_test.y1 * res_scale);
|
||||
// x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when
|
||||
// scaling or doing multisampling.
|
||||
GLint scissor_x2 = static_cast<GLint>(
|
||||
rect.left + (regs.rasterizer.scissor_test.x2 + 1) * res_scale_width);
|
||||
rect.left + (regs.rasterizer.scissor_test.x2 + 1) * res_scale);
|
||||
GLint scissor_y2 = static_cast<GLint>(
|
||||
rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * res_scale_height);
|
||||
rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * res_scale);
|
||||
|
||||
if (uniform_block_data.data.scissor_x1 != scissor_x1 ||
|
||||
uniform_block_data.data.scissor_x2 != scissor_x2 ||
|
||||
@ -959,16 +954,15 @@ bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransfe
|
||||
dst_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.output_format);
|
||||
dst_params.UpdateParams();
|
||||
|
||||
MathUtil::Rectangle<int> src_rect;
|
||||
MathUtil::Rectangle<u32> src_rect;
|
||||
Surface src_surface;
|
||||
std::tie(src_surface, src_rect) = res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true);
|
||||
if (src_surface == nullptr)
|
||||
return false;
|
||||
|
||||
dst_params.res_scale_width = src_surface->res_scale_width;
|
||||
dst_params.res_scale_height = src_surface->res_scale_height;
|
||||
dst_params.res_scale = src_surface->res_scale;
|
||||
|
||||
MathUtil::Rectangle<int> dst_rect;
|
||||
MathUtil::Rectangle<u32> dst_rect;
|
||||
Surface dst_surface;
|
||||
std::tie(dst_surface, dst_rect) = res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, false);
|
||||
if (dst_surface == nullptr)
|
||||
@ -1004,7 +998,7 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon
|
||||
src_params.size = ((src_params.height - 1) * src_params.stride) + src_params.width;
|
||||
src_params.end = src_params.addr + src_params.size;
|
||||
|
||||
MathUtil::Rectangle<int> src_rect;
|
||||
MathUtil::Rectangle<u32> src_rect;
|
||||
Surface src_surface;
|
||||
std::tie(src_surface, src_rect) = res_cache.GetTexCopySurface(src_params);
|
||||
if (src_surface == nullptr)
|
||||
@ -1019,12 +1013,11 @@ bool RasterizerOpenGL::AccelerateTextureCopy(const GPU::Regs::DisplayTransferCon
|
||||
dst_params.stride = (output_width + output_gap) * src_surface->stride / src_params.stride;
|
||||
dst_params.width = output_width * src_surface->stride / src_params.stride;
|
||||
dst_params.height = src_surface->is_tiled ? src_params.height * 8 : src_params.height;
|
||||
dst_params.res_scale_width = src_surface->res_scale_width;
|
||||
dst_params.res_scale_height = src_surface->res_scale_height;
|
||||
dst_params.res_scale = src_surface->res_scale;
|
||||
dst_params.UpdateParams();
|
||||
|
||||
const bool load_gap = output_gap != 0; // Since we are going to invalidate the gap if there is one, we will have to load it first
|
||||
MathUtil::Rectangle<int> dst_rect;
|
||||
MathUtil::Rectangle<u32> dst_rect;
|
||||
Surface dst_surface;
|
||||
std::tie(dst_surface, dst_rect) = res_cache.GetSurfaceSubRect(dst_params, ScaleMatch::Upscale, load_gap);
|
||||
if (src_surface == nullptr)
|
||||
@ -1063,7 +1056,7 @@ bool RasterizerOpenGL::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
|
||||
src_params.pixel_format = SurfaceParams::PixelFormatFromGPUPixelFormat(config.color_format);
|
||||
src_params.UpdateParams();
|
||||
|
||||
MathUtil::Rectangle<int> src_rect;
|
||||
MathUtil::Rectangle<u32> src_rect;
|
||||
Surface src_surface;
|
||||
std::tie(src_surface, src_rect) = res_cache.GetSurfaceSubRect(src_params, ScaleMatch::Ignore, true);
|
||||
|
||||
|
@ -136,7 +136,7 @@ private:
|
||||
// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
|
||||
// Not following that rule will cause problems on some AMD drivers.
|
||||
struct UniformData {
|
||||
alignas(8) GLvec2 framebuffer_scale;
|
||||
GLint framebuffer_scale;
|
||||
GLint alphatest_ref;
|
||||
GLfloat depth_scale;
|
||||
GLfloat depth_offset;
|
||||
@ -156,7 +156,7 @@ private:
|
||||
};
|
||||
|
||||
static_assert(
|
||||
sizeof(UniformData) == 0x470,
|
||||
sizeof(UniformData) == 0x460,
|
||||
"The size of the UniformData structure has changed, update the structure in the shader");
|
||||
static_assert(sizeof(UniformData) < 16384,
|
||||
"UniformData structure must be less than 16kb as per the OpenGL spec");
|
||||
|
@ -179,8 +179,8 @@ static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tup
|
||||
cur_state.Apply();
|
||||
}
|
||||
|
||||
static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<int>& src_rect,
|
||||
GLuint dst_tex, const MathUtil::Rectangle<int>& dst_rect,
|
||||
static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect,
|
||||
GLuint dst_tex, const MathUtil::Rectangle<u32>& dst_rect,
|
||||
SurfaceType type) {
|
||||
OpenGLState cur_state = OpenGLState::GetCurState();
|
||||
|
||||
@ -312,35 +312,23 @@ static bool FillSurface(const Surface& surface, const u8* fill_data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SurfaceParams::SurfaceParams() {
|
||||
// todo: metroid needs that for now, "breaks" other stuff
|
||||
// Set the internal resolution, assume the same scaling factor for top and bottom screens
|
||||
float resolution_scale_factor = Settings::values.resolution_factor;
|
||||
if (resolution_scale_factor == 0.0f) {
|
||||
// Auto - scale resolution to the window size
|
||||
resolution_scale_factor = VideoCore::g_emu_window->GetFramebufferLayout().GetScalingRatio();
|
||||
}
|
||||
res_scale_width = resolution_scale_factor;
|
||||
res_scale_height = resolution_scale_factor;
|
||||
}
|
||||
|
||||
MathUtil::Rectangle<int> CachedSurface::GetSubRect(const SurfaceParams& sub_surface) const {
|
||||
MathUtil::Rectangle<u32> CachedSurface::GetSubRect(const SurfaceParams& sub_surface) const {
|
||||
const u32 begin_pixel_index = PixelsInBytes(sub_surface.addr - addr);
|
||||
const int x0 = begin_pixel_index % width;
|
||||
const int y0 = begin_pixel_index / width;
|
||||
|
||||
if (is_tiled)
|
||||
return MathUtil::Rectangle<int>(x0, height - y0 - sub_surface.height, x0 + sub_surface.width, height - y0); // Bottom to top
|
||||
return MathUtil::Rectangle<u32>(x0, height - y0 - sub_surface.height, x0 + sub_surface.width, height - y0); // Bottom to top
|
||||
|
||||
return MathUtil::Rectangle<int>(x0, y0, x0 + sub_surface.width, y0 + sub_surface.height); // Top to bottom
|
||||
return MathUtil::Rectangle<u32>(x0, y0, x0 + sub_surface.width, y0 + sub_surface.height); // Top to bottom
|
||||
}
|
||||
|
||||
MathUtil::Rectangle<int> CachedSurface::GetScaledSubRect(const SurfaceParams& sub_surface) const {
|
||||
MathUtil::Rectangle<u32> CachedSurface::GetScaledSubRect(const SurfaceParams& sub_surface) const {
|
||||
auto rect = GetSubRect(sub_surface);
|
||||
rect.left = static_cast<int>(rect.left * res_scale_width);
|
||||
rect.right = static_cast<int>(rect.right * res_scale_width);
|
||||
rect.top = static_cast<int>(rect.top * res_scale_height);
|
||||
rect.bottom = static_cast<int>(rect.bottom * res_scale_height);
|
||||
rect.left = rect.left * res_scale;
|
||||
rect.right = rect.right * res_scale;
|
||||
rect.top = rect.top * res_scale;
|
||||
rect.bottom = rect.bottom * res_scale;
|
||||
return rect;
|
||||
}
|
||||
|
||||
@ -577,7 +565,7 @@ void CachedSurface::UploadGLTexture() {
|
||||
cur_state.Apply();
|
||||
|
||||
// If not 1x scale, blit 1x texture to a new scaled texture and replace texture in surface
|
||||
if (res_scale_width != 1.f || res_scale_height != 1.f) {
|
||||
if (res_scale != 1) {
|
||||
OGLTexture scaled_texture;
|
||||
scaled_texture.Create();
|
||||
|
||||
@ -604,7 +592,7 @@ void CachedSurface::DownloadGLTexture() {
|
||||
|
||||
// If not 1x scale, blit scaled texture to a new 1x texture and use that to flush
|
||||
OGLTexture unscaled_tex;
|
||||
if (res_scale_width != 1.f || res_scale_height != 1.f) {
|
||||
if (res_scale != 1) {
|
||||
unscaled_tex.Create();
|
||||
|
||||
AllocateSurfaceTexture(unscaled_tex.handle, tuple, width, height);
|
||||
@ -626,65 +614,58 @@ void CachedSurface::DownloadGLTexture() {
|
||||
gl_buffer_dirty = false;
|
||||
}
|
||||
|
||||
enum MatchType : int {
|
||||
Exact = (1 << 0), // Surfaces perfectly match
|
||||
SubRect = (1 << 1), // Surface encompasses params
|
||||
Invalid = (1 << 2), // Flag that can be applied to other match types, invalid matches require validation before they can be used
|
||||
Copy = (1 << 3), // Surface we can copy from
|
||||
//PartialCopy = (1 << 4), // Surface we can partialy copy from
|
||||
TexCopy = (1 << 5), // Surface that will match a display transfer "texture copy" parameters
|
||||
All = (1 << 6) - 1,
|
||||
None = 0,
|
||||
enum MatchFlags {
|
||||
Invalid = 1, // Flag that can be applied to other match types, invalid matches require validation before they can be used
|
||||
Exact = 1 << 1, // Surfaces perfectly match
|
||||
SubRect = 1 << 2, // Surface encompasses params
|
||||
Copy = 1 << 3, // Surface we can copy from
|
||||
TexCopy = 1 << 4 // Surface that will match a display transfer "texture copy" parameters
|
||||
};
|
||||
|
||||
constexpr MatchType operator | (MatchType lhs, MatchType rhs) {
|
||||
return static_cast<MatchType>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
||||
constexpr MatchFlags operator | (MatchFlags lhs, MatchFlags rhs) {
|
||||
return static_cast<MatchFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
|
||||
}
|
||||
|
||||
/// Get the best surface match (and its match type) for the given flags, higher flag value meaning lower priority
|
||||
/// NEW:: no more match type priority, only region validity matters and then scaling comparison
|
||||
template <MatchType find_flags>
|
||||
Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, ScaleMatch match_res_scale) {
|
||||
constexpr float MATCH_GOODNESS_RESET = -1.f;
|
||||
|
||||
/// Get the best surface match (and its match type) for the given flags
|
||||
template <MatchFlags find_flags>
|
||||
Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, ScaleMatch match_scale_type) {
|
||||
Surface match_surface = nullptr;
|
||||
bool match_valid = false;
|
||||
float best_match_goodness = MATCH_GOODNESS_RESET;
|
||||
u32 match_scale = 0;
|
||||
|
||||
for (auto& pair : RangeFromInterval(surface_cache, params.GetInterval())) {
|
||||
for (auto& surface : pair.second) {
|
||||
const bool res_scale_match = match_res_scale == ScaleMatch::Exact ?
|
||||
(params.res_scale_width == surface->res_scale_width && params.res_scale_height == surface->res_scale_height) :
|
||||
(params.res_scale_width <= surface->res_scale_width && params.res_scale_height <= surface->res_scale_height);
|
||||
const float match_goodness = surface->res_scale_width * surface->res_scale_height;
|
||||
const bool res_scale_matched = match_scale_type == ScaleMatch::Exact ?
|
||||
(params.res_scale == surface->res_scale) :
|
||||
(params.res_scale <= surface->res_scale);
|
||||
const bool is_valid = surface->IsRegionValid(params.GetInterval());
|
||||
|
||||
if (!(find_flags & MatchType::Invalid) && !is_valid)
|
||||
if (!(find_flags & MatchFlags::Invalid) && !is_valid)
|
||||
continue;
|
||||
|
||||
const auto IsMatch_Helper = [&](MatchType check_type, auto match_fn) {
|
||||
const auto IsMatch_Helper = [&](MatchFlags check_type, auto match_fn) {
|
||||
if (!(find_flags & check_type))
|
||||
return false;
|
||||
|
||||
if (!match_fn())
|
||||
return false;
|
||||
|
||||
if (match_res_scale == ScaleMatch::Ignore || res_scale_match || surface->type == SurfaceType::Fill) { // Found a match
|
||||
if (match_scale_type == ScaleMatch::Ignore || res_scale_matched || surface->type == SurfaceType::Fill) { // Found a match
|
||||
if (is_valid && !match_valid) {
|
||||
best_match_goodness = MATCH_GOODNESS_RESET;
|
||||
match_scale = 0;
|
||||
match_valid = true;
|
||||
}
|
||||
if (match_goodness > best_match_goodness) {
|
||||
best_match_goodness = match_goodness;
|
||||
if (surface->res_scale > match_scale) {
|
||||
match_scale = surface->res_scale;
|
||||
match_surface = surface;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
IsMatch_Helper(MatchType::Exact, [&] { return surface->ExactMatch(params); });
|
||||
IsMatch_Helper(MatchType::SubRect, [&] { return surface->CanSubRect(params); });
|
||||
IsMatch_Helper(MatchType::Copy, [&] { return surface->CanCopy(params); });
|
||||
IsMatch_Helper(MatchType::TexCopy, [&] { return surface->CanTexCopy(params); });
|
||||
IsMatch_Helper(MatchFlags::Exact, [&] { return surface->ExactMatch(params); });
|
||||
IsMatch_Helper(MatchFlags::SubRect, [&] { return surface->CanSubRect(params); });
|
||||
IsMatch_Helper(MatchFlags::Copy, [&] { return surface->CanCopy(params); });
|
||||
IsMatch_Helper(MatchFlags::TexCopy, [&] { return surface->CanTexCopy(params); });
|
||||
}
|
||||
}
|
||||
return match_surface;
|
||||
@ -704,9 +685,9 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() {
|
||||
}
|
||||
|
||||
bool RasterizerCacheOpenGL::BlitSurfaces(const Surface& src_surface,
|
||||
const MathUtil::Rectangle<int>& src_rect,
|
||||
const MathUtil::Rectangle<u32>& src_rect,
|
||||
const Surface& dst_surface,
|
||||
const MathUtil::Rectangle<int>& dst_rect) {
|
||||
const MathUtil::Rectangle<u32>& dst_rect) {
|
||||
if (!SurfaceParams::CheckFormatsBlittable(src_surface->pixel_format,
|
||||
dst_surface->pixel_format))
|
||||
return false;
|
||||
@ -722,7 +703,7 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
|
||||
}
|
||||
|
||||
// Check for an exact or subrect match in existing surfaces
|
||||
Surface surface_match = FindMatch<MatchType::Exact | MatchType::Invalid>(surface_cache, params, match_res_scale);
|
||||
Surface surface_match = FindMatch<MatchFlags::Exact | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
||||
|
||||
if (surface_match != nullptr) {
|
||||
if (load_if_create) {
|
||||
@ -745,14 +726,14 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
|
||||
SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params,
|
||||
ScaleMatch match_res_scale,
|
||||
bool load_if_create) {
|
||||
MathUtil::Rectangle<int> out_rect{};
|
||||
MathUtil::Rectangle<u32> out_rect{};
|
||||
|
||||
if (params.addr == 0 || params.height * params.width == 0) {
|
||||
return std::make_tuple(nullptr, out_rect);
|
||||
}
|
||||
|
||||
// Attempt to find encompassing surface
|
||||
Surface subrect_match = FindMatch<MatchType::SubRect | MatchType::Invalid>(surface_cache, params, match_res_scale);
|
||||
Surface subrect_match = FindMatch<MatchFlags::SubRect | MatchFlags::Invalid>(surface_cache, params, match_res_scale);
|
||||
|
||||
// Return the best subrect surface if found
|
||||
if (subrect_match != nullptr) {
|
||||
@ -778,7 +759,7 @@ SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams&
|
||||
std::swap(out_rect.top, out_rect.bottom);
|
||||
|
||||
// If stride was bigger than width we need to adjust our output rect
|
||||
out_rect.right = static_cast<int>(params.width * new_params.res_scale_width);
|
||||
out_rect.right = static_cast<int>(params.width * new_params.res_scale);
|
||||
|
||||
Surface new_surface = CreateSurface(new_params);
|
||||
if (load_if_create)
|
||||
@ -802,8 +783,8 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Pica::TexturingRegs::Full
|
||||
return GetSurface(params, ScaleMatch::Ignore, true);
|
||||
}
|
||||
|
||||
constexpr float GetResolutionScaleFactor() {
|
||||
return Settings::values.resolution_factor == 0.0f ?
|
||||
constexpr u16 GetResolutionScaleFactor() {
|
||||
return !Settings::values.resolution_factor ?
|
||||
VideoCore::g_emu_window->GetFramebufferLayout().GetScalingRatio() :
|
||||
Settings::values.resolution_factor;
|
||||
}
|
||||
@ -834,7 +815,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool usin
|
||||
color_params.is_tiled = depth_params.is_tiled = true;
|
||||
|
||||
// update resolution_scale_factor and reset cache if changed
|
||||
static float resolution_scale_factor = GetResolutionScaleFactor();
|
||||
static u16 resolution_scale_factor = GetResolutionScaleFactor();
|
||||
if (resolution_scale_factor != GetResolutionScaleFactor()) {
|
||||
resolution_scale_factor = GetResolutionScaleFactor();
|
||||
FlushAll();
|
||||
@ -845,19 +826,17 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool usin
|
||||
color_params.width = depth_params.width = config.GetWidth();
|
||||
color_params.height = depth_params.height = config.GetHeight();
|
||||
color_params.pixel_format = SurfaceParams::PixelFormatFromColorFormat(config.color_format);
|
||||
color_params.res_scale_height = resolution_scale_factor;
|
||||
color_params.res_scale_width = resolution_scale_factor;
|
||||
color_params.res_scale = resolution_scale_factor;
|
||||
color_params.UpdateParams();
|
||||
|
||||
MathUtil::Rectangle<int> rect{};
|
||||
MathUtil::Rectangle<u32> rect{};
|
||||
Surface color_surface = nullptr;
|
||||
if (using_color_fb)
|
||||
std::tie(color_surface, rect) = GetSurfaceSubRect(color_params, ScaleMatch::Exact, true);
|
||||
|
||||
depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(config.depth_format);
|
||||
depth_params.addr = config.GetDepthBufferPhysicalAddress();
|
||||
depth_params.res_scale_height = resolution_scale_factor;
|
||||
depth_params.res_scale_width = resolution_scale_factor;
|
||||
depth_params.res_scale = resolution_scale_factor;
|
||||
depth_params.UpdateParams();
|
||||
|
||||
Surface depth_surface = nullptr;
|
||||
@ -900,9 +879,9 @@ Surface RasterizerCacheOpenGL::GetFillSurface(const GPU::Regs::MemoryFillConfig&
|
||||
}
|
||||
|
||||
SurfaceRect_Tuple RasterizerCacheOpenGL::GetTexCopySurface(const SurfaceParams& params) {
|
||||
MathUtil::Rectangle<int> rect{};
|
||||
MathUtil::Rectangle<u32> rect{};
|
||||
|
||||
Surface match_surface = FindMatch<MatchType::TexCopy | MatchType::Invalid>(surface_cache, params, ScaleMatch::Ignore);
|
||||
Surface match_surface = FindMatch<MatchFlags::TexCopy | MatchFlags::Invalid>(surface_cache, params, ScaleMatch::Ignore);
|
||||
|
||||
if (match_surface != nullptr) {
|
||||
ValidateSurface(match_surface, params.addr, params.size);
|
||||
@ -964,7 +943,7 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, PAddr addr,
|
||||
}
|
||||
params.UpdateParams();
|
||||
|
||||
Surface match_surface = FindMatch<MatchType::SubRect | MatchType::Copy>(surface_cache, params, ScaleMatch::Ignore);
|
||||
Surface match_surface = FindMatch<MatchFlags::SubRect | MatchFlags::Copy>(surface_cache, params, ScaleMatch::Ignore);
|
||||
|
||||
if (match_surface != nullptr) {
|
||||
if (!match_surface->CanSubRect(params)) {
|
||||
@ -1046,8 +1025,6 @@ void RasterizerCacheOpenGL::InvalidateRegion(PAddr addr, u32 size, const Surface
|
||||
region_owner->invalid_regions.erase(invalid_interval);
|
||||
}
|
||||
|
||||
SurfaceSet remove_surfaces;
|
||||
|
||||
for (auto& pair : RangeFromInterval(surface_cache, invalid_interval)) {
|
||||
for (auto& cached_surface : pair.second) {
|
||||
if (cached_surface == region_owner)
|
||||
@ -1085,6 +1062,7 @@ void RasterizerCacheOpenGL::InvalidateRegion(PAddr addr, u32 size, const Surface
|
||||
|
||||
for (auto& remove_surface : remove_surfaces)
|
||||
UnregisterSurface(remove_surface);
|
||||
remove_surfaces.clear();
|
||||
}
|
||||
|
||||
Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
|
||||
|
@ -39,8 +39,8 @@ using SurfaceInterval = SurfaceCache::interval_type;
|
||||
static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() &&
|
||||
std::is_same<SurfaceMap::interval_type, SurfaceCache::interval_type>(), "incorrect interval types");
|
||||
|
||||
using SurfaceRect_Tuple = std::tuple<Surface, MathUtil::Rectangle<int>>;
|
||||
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, MathUtil::Rectangle<int>>;
|
||||
using SurfaceRect_Tuple = std::tuple<Surface, MathUtil::Rectangle<u32>>;
|
||||
using SurfaceSurfaceRect_Tuple = std::tuple<Surface, Surface, MathUtil::Rectangle<u32>>;
|
||||
|
||||
using PageMap = boost::icl::interval_map<u32, int>;
|
||||
|
||||
@ -51,8 +51,6 @@ enum class ScaleMatch {
|
||||
};
|
||||
|
||||
struct SurfaceParams {
|
||||
explicit SurfaceParams();
|
||||
|
||||
enum class PixelFormat {
|
||||
// First 5 formats are shared between textures and color buffers
|
||||
RGBA8 = 0,
|
||||
@ -200,19 +198,19 @@ struct SurfaceParams {
|
||||
}
|
||||
|
||||
u32 GetScaledWidth() const {
|
||||
return static_cast<u32>(width * res_scale_width);
|
||||
return width * res_scale;
|
||||
}
|
||||
|
||||
u32 GetScaledHeight() const {
|
||||
return static_cast<u32>(height * res_scale_height);
|
||||
return height * res_scale;
|
||||
}
|
||||
|
||||
MathUtil::Rectangle<int> GetRect() const {
|
||||
return MathUtil::Rectangle<int>(0, 0, width, height);
|
||||
MathUtil::Rectangle<u32> GetRect() const {
|
||||
return { 0, 0, width, height };
|
||||
}
|
||||
|
||||
MathUtil::Rectangle<int> GetScaledRect() const {
|
||||
return MathUtil::Rectangle<int>(0, 0, GetScaledWidth(), GetScaledHeight());
|
||||
MathUtil::Rectangle<u32> GetScaledRect() const {
|
||||
return { 0, 0, GetScaledWidth(), GetScaledHeight() };
|
||||
}
|
||||
|
||||
u32 PixelsInBytes(u32 size) const {
|
||||
@ -226,8 +224,7 @@ struct SurfaceParams {
|
||||
u32 width = 0;
|
||||
u32 height = 0;
|
||||
u32 stride = 0;
|
||||
float res_scale_width = 1.f;
|
||||
float res_scale_height = 1.f;
|
||||
u16 res_scale = 1;
|
||||
|
||||
bool is_tiled = false;
|
||||
u32 bytes_per_pixel = 0;
|
||||
@ -239,11 +236,10 @@ struct CachedSurface : SurfaceParams {
|
||||
bool ExactMatch(const SurfaceParams& other_surface) const;
|
||||
bool CanSubRect(const SurfaceParams& sub_surface) const;
|
||||
bool CanCopy(const SurfaceParams& dest_surface) const;
|
||||
//bool CanPartialCopy(const SurfaceParams& dest_surface) const;
|
||||
bool CanTexCopy(const SurfaceParams& texcopy_params) const;
|
||||
|
||||
MathUtil::Rectangle<int> GetSubRect(const SurfaceParams& sub_surface) const;
|
||||
MathUtil::Rectangle<int> GetScaledSubRect(const SurfaceParams& sub_surface) const;
|
||||
MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const;
|
||||
MathUtil::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const;
|
||||
|
||||
bool IsRegionValid(const SurfaceInterval& interval) const {
|
||||
return (invalid_regions.find(interval) == invalid_regions.end());
|
||||
@ -283,8 +279,8 @@ public:
|
||||
~RasterizerCacheOpenGL();
|
||||
|
||||
/// Blit one surface's texture to another
|
||||
bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle<int>& src_rect,
|
||||
const Surface& dst_surface, const MathUtil::Rectangle<int>& dst_rect);
|
||||
bool BlitSurfaces(const Surface& src_surface, const MathUtil::Rectangle<u32>& src_rect,
|
||||
const Surface& dst_surface, const MathUtil::Rectangle<u32>& dst_rect);
|
||||
|
||||
/// Load a texture from 3DS memory to OpenGL and cache it (if not already cached)
|
||||
Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale, bool load_if_create);
|
||||
@ -334,4 +330,5 @@ private:
|
||||
SurfaceCache surface_cache;
|
||||
SurfaceMap dirty_regions;
|
||||
PageMap cached_pages;
|
||||
SurfaceSet remove_surfaces;
|
||||
};
|
||||
|
@ -41,7 +41,7 @@ struct LightSrc {
|
||||
};
|
||||
|
||||
layout (std140) uniform shader_data {
|
||||
vec2 framebuffer_scale;
|
||||
int framebuffer_scale;
|
||||
int alphatest_ref;
|
||||
float depth_scale;
|
||||
float depth_offset;
|
||||
|
Loading…
Reference in New Issue
Block a user