integer res_scale and cleanup
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phantom
					Phantom