diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvnflinger/buffer_transform_flags.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.cpp | 101 |
2 files changed, 57 insertions, 46 deletions
diff --git a/src/core/hle/service/nvnflinger/buffer_transform_flags.h b/src/core/hle/service/nvnflinger/buffer_transform_flags.h index 67aa5dad6..ffe579718 100644 --- a/src/core/hle/service/nvnflinger/buffer_transform_flags.h +++ b/src/core/hle/service/nvnflinger/buffer_transform_flags.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/common_funcs.h" | ||
| 6 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 7 | 8 | ||
| 8 | namespace Service::android { | 9 | namespace Service::android { |
| @@ -21,5 +22,6 @@ enum class BufferTransformFlags : u32 { | |||
| 21 | /// Rotate source image 270 degrees clockwise | 22 | /// Rotate source image 270 degrees clockwise |
| 22 | Rotate270 = 0x07, | 23 | Rotate270 = 0x07, |
| 23 | }; | 24 | }; |
| 25 | DECLARE_ENUM_FLAG_OPERATORS(BufferTransformFlags); | ||
| 24 | 26 | ||
| 25 | } // namespace Service::android | 27 | } // namespace Service::android |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 52fc142d1..459ab32c2 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -1395,63 +1395,72 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou | |||
| 1395 | MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height)); | 1395 | MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height)); |
| 1396 | } | 1396 | } |
| 1397 | 1397 | ||
| 1398 | void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, | 1398 | static Common::Rectangle<f32> NormalizeCrop(Common::Rectangle<int> crop, |
| 1399 | const Layout::FramebufferLayout layout) const { | 1399 | const Tegra::FramebufferConfig& framebuffer) { |
| 1400 | const auto& framebuffer_transform_flags = framebuffer.transform_flags; | 1400 | f32 left, top, right, bottom; |
| 1401 | const auto& framebuffer_crop_rect = framebuffer.crop_rect; | 1401 | |
| 1402 | 1402 | if (!crop.IsEmpty()) { | |
| 1403 | static constexpr Common::Rectangle<f32> texcoords{0.f, 0.f, 1.f, 1.f}; | 1403 | // If crop rectangle is not empty, apply properties from rectangle. |
| 1404 | auto left = texcoords.left; | 1404 | left = static_cast<f32>(crop.left); |
| 1405 | auto right = texcoords.right; | 1405 | top = static_cast<f32>(crop.top); |
| 1406 | 1406 | right = static_cast<f32>(crop.right); | |
| 1407 | switch (framebuffer_transform_flags) { | 1407 | bottom = static_cast<f32>(crop.bottom); |
| 1408 | case Service::android::BufferTransformFlags::Unset: | 1408 | } else { |
| 1409 | break; | 1409 | // Otherwise, fall back to framebuffer dimensions. |
| 1410 | case Service::android::BufferTransformFlags::FlipV: | 1410 | left = 0; |
| 1411 | // Flip the framebuffer vertically | 1411 | top = 0; |
| 1412 | left = texcoords.right; | 1412 | right = static_cast<f32>(framebuffer.width); |
| 1413 | right = texcoords.left; | 1413 | bottom = static_cast<f32>(framebuffer.height); |
| 1414 | break; | ||
| 1415 | default: | ||
| 1416 | UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}", | ||
| 1417 | static_cast<u32>(framebuffer_transform_flags)); | ||
| 1418 | break; | ||
| 1419 | } | 1414 | } |
| 1420 | 1415 | ||
| 1421 | UNIMPLEMENTED_IF(framebuffer_crop_rect.left != 0); | 1416 | // Apply transformation flags. |
| 1417 | auto framebuffer_transform_flags = framebuffer.transform_flags; | ||
| 1422 | 1418 | ||
| 1423 | f32 left_start{}; | 1419 | if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) { |
| 1424 | if (framebuffer_crop_rect.Top() > 0) { | 1420 | // Switch left and right. |
| 1425 | left_start = static_cast<f32>(framebuffer_crop_rect.Top()) / | 1421 | std::swap(left, right); |
| 1426 | static_cast<f32>(framebuffer_crop_rect.Bottom()); | ||
| 1427 | } | 1422 | } |
| 1428 | f32 scale_u = static_cast<f32>(framebuffer.width) / static_cast<f32>(screen_info.width); | 1423 | if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) { |
| 1429 | f32 scale_v = static_cast<f32>(framebuffer.height) / static_cast<f32>(screen_info.height); | 1424 | // Switch top and bottom. |
| 1430 | // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering | 1425 | std::swap(top, bottom); |
| 1431 | // (e.g. handheld mode) on a 1920x1080 framebuffer. | 1426 | } |
| 1432 | if (!fsr) { | 1427 | |
| 1433 | if (framebuffer_crop_rect.GetWidth() > 0) { | 1428 | framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH; |
| 1434 | scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) / | 1429 | framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV; |
| 1435 | static_cast<f32>(screen_info.width); | 1430 | if (True(framebuffer_transform_flags)) { |
| 1436 | } | 1431 | UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}", |
| 1437 | if (framebuffer_crop_rect.GetHeight() > 0) { | 1432 | static_cast<u32>(framebuffer_transform_flags)); |
| 1438 | scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) / | ||
| 1439 | static_cast<f32>(screen_info.height); | ||
| 1440 | } | ||
| 1441 | } | 1433 | } |
| 1442 | 1434 | ||
| 1435 | return Common::Rectangle<f32>(left, top, right, bottom); | ||
| 1436 | } | ||
| 1437 | |||
| 1438 | void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, | ||
| 1439 | const Layout::FramebufferLayout layout) const { | ||
| 1440 | // Get the normalized crop rectangle. | ||
| 1441 | const auto crop = NormalizeCrop(framebuffer.crop_rect, framebuffer); | ||
| 1442 | |||
| 1443 | // Get the screen properties. | ||
| 1444 | const f32 screen_width = static_cast<f32>(screen_info.width); | ||
| 1445 | const f32 screen_height = static_cast<f32>(screen_info.height); | ||
| 1446 | |||
| 1447 | // Apply the crop. | ||
| 1448 | const f32 left = crop.left / screen_width; | ||
| 1449 | const f32 top = crop.top / screen_height; | ||
| 1450 | const f32 right = crop.right / screen_width; | ||
| 1451 | const f32 bottom = crop.bottom / screen_height; | ||
| 1452 | |||
| 1453 | // Map the coordinates to the screen. | ||
| 1443 | const auto& screen = layout.screen; | 1454 | const auto& screen = layout.screen; |
| 1444 | const auto x = static_cast<f32>(screen.left); | 1455 | const auto x = static_cast<f32>(screen.left); |
| 1445 | const auto y = static_cast<f32>(screen.top); | 1456 | const auto y = static_cast<f32>(screen.top); |
| 1446 | const auto w = static_cast<f32>(screen.GetWidth()); | 1457 | const auto w = static_cast<f32>(screen.GetWidth()); |
| 1447 | const auto h = static_cast<f32>(screen.GetHeight()); | 1458 | const auto h = static_cast<f32>(screen.GetHeight()); |
| 1448 | data.vertices[0] = ScreenRectVertex(x, y, texcoords.top * scale_u, left_start + left * scale_v); | 1459 | |
| 1449 | data.vertices[1] = | 1460 | data.vertices[0] = ScreenRectVertex(x, y, left, top); |
| 1450 | ScreenRectVertex(x + w, y, texcoords.bottom * scale_u, left_start + left * scale_v); | 1461 | data.vertices[1] = ScreenRectVertex(x + w, y, right, top); |
| 1451 | data.vertices[2] = | 1462 | data.vertices[2] = ScreenRectVertex(x, y + h, left, bottom); |
| 1452 | ScreenRectVertex(x, y + h, texcoords.top * scale_u, left_start + right * scale_v); | 1463 | data.vertices[3] = ScreenRectVertex(x + w, y + h, right, bottom); |
| 1453 | data.vertices[3] = | ||
| 1454 | ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, left_start + right * scale_v); | ||
| 1455 | } | 1464 | } |
| 1456 | 1465 | ||
| 1457 | void BlitScreen::CreateSMAA(VkExtent2D smaa_size) { | 1466 | void BlitScreen::CreateSMAA(VkExtent2D smaa_size) { |