integer res_scale and cleanup

This commit is contained in:
Phantom 2017-10-06 17:33:00 +02:00
parent 96861c6347
commit 926abc6ddb
11 changed files with 99 additions and 200 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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 =

View File

@ -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

View File

@ -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;
};
/**

View File

@ -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;

View File

@ -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);

View File

@ -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");

View File

@ -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) {

View File

@ -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;
};

View File

@ -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;