summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar Narr the Reg2024-02-11 20:58:28 -0600
committerGravatar GitHub2024-02-11 20:58:28 -0600
commit2ff45cd0da941dce2564f5c18c580d0283da27bf (patch)
tree81fea8c23f9afa39c167288e03ff57eb25413ee4 /src/video_core/renderer_opengl
parentMerge pull request #12991 from german77/news2 (diff)
parentam: use applet program loading for tested versions (diff)
downloadyuzu-2ff45cd0da941dce2564f5c18c580d0283da27bf.tar.gz
yuzu-2ff45cd0da941dce2564f5c18c580d0283da27bf.tar.xz
yuzu-2ff45cd0da941dce2564f5c18c580d0283da27bf.zip
Merge pull request #12756 from liamwhite/applet-multiprocess-hwc
general: applet multiprocess
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_blit_screen.cpp15
-rw-r--r--src/video_core/renderer_opengl/gl_blit_screen.h7
-rw-r--r--src/video_core/renderer_opengl/present/layer.cpp35
-rw-r--r--src/video_core/renderer_opengl/present/layer.h8
-rw-r--r--src/video_core/renderer_opengl/present/window_adapt_pass.cpp19
-rw-r--r--src/video_core/renderer_opengl/present/window_adapt_pass.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp89
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h9
8 files changed, 145 insertions, 39 deletions
diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp
index 6ba8b214b..9260a4dc4 100644
--- a/src/video_core/renderer_opengl/gl_blit_screen.cpp
+++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/settings.h" 4#include "common/settings.h"
5#include "video_core/present.h"
5#include "video_core/renderer_opengl/gl_blit_screen.h" 6#include "video_core/renderer_opengl/gl_blit_screen.h"
6#include "video_core/renderer_opengl/gl_state_tracker.h" 7#include "video_core/renderer_opengl/gl_state_tracker.h"
7#include "video_core/renderer_opengl/present/filters.h" 8#include "video_core/renderer_opengl/present/filters.h"
@@ -13,14 +14,14 @@ namespace OpenGL {
13BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, 14BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_,
14 Tegra::MaxwellDeviceMemoryManager& device_memory_, 15 Tegra::MaxwellDeviceMemoryManager& device_memory_,
15 StateTracker& state_tracker_, ProgramManager& program_manager_, 16 StateTracker& state_tracker_, ProgramManager& program_manager_,
16 Device& device_) 17 Device& device_, const PresentFilters& filters_)
17 : rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_), 18 : rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_),
18 program_manager(program_manager_), device(device_) {} 19 program_manager(program_manager_), device(device_), filters(filters_) {}
19 20
20BlitScreen::~BlitScreen() = default; 21BlitScreen::~BlitScreen() = default;
21 22
22void BlitScreen::DrawScreen(std::span<const Tegra::FramebufferConfig> framebuffers, 23void BlitScreen::DrawScreen(std::span<const Tegra::FramebufferConfig> framebuffers,
23 const Layout::FramebufferLayout& layout) { 24 const Layout::FramebufferLayout& layout, bool invert_y) {
24 // TODO: Signal state tracker about these changes 25 // TODO: Signal state tracker about these changes
25 state_tracker.NotifyScreenDrawVertexArray(); 26 state_tracker.NotifyScreenDrawVertexArray();
26 state_tracker.NotifyPolygonModes(); 27 state_tracker.NotifyPolygonModes();
@@ -56,22 +57,22 @@ void BlitScreen::DrawScreen(std::span<const Tegra::FramebufferConfig> framebuffe
56 glDepthRangeIndexed(0, 0.0, 0.0); 57 glDepthRangeIndexed(0, 0.0, 0.0);
57 58
58 while (layers.size() < framebuffers.size()) { 59 while (layers.size() < framebuffers.size()) {
59 layers.emplace_back(rasterizer, device_memory); 60 layers.emplace_back(rasterizer, device_memory, filters);
60 } 61 }
61 62
62 CreateWindowAdapt(); 63 CreateWindowAdapt();
63 window_adapt->DrawToFramebuffer(program_manager, layers, framebuffers, layout); 64 window_adapt->DrawToFramebuffer(program_manager, layers, framebuffers, layout, invert_y);
64 65
65 // TODO 66 // TODO
66 // program_manager.RestoreGuestPipeline(); 67 // program_manager.RestoreGuestPipeline();
67} 68}
68 69
69void BlitScreen::CreateWindowAdapt() { 70void BlitScreen::CreateWindowAdapt() {
70 if (window_adapt && Settings::values.scaling_filter.GetValue() == current_window_adapt) { 71 if (window_adapt && filters.get_scaling_filter() == current_window_adapt) {
71 return; 72 return;
72 } 73 }
73 74
74 current_window_adapt = Settings::values.scaling_filter.GetValue(); 75 current_window_adapt = filters.get_scaling_filter();
75 switch (current_window_adapt) { 76 switch (current_window_adapt) {
76 case Settings::ScalingFilter::NearestNeighbor: 77 case Settings::ScalingFilter::NearestNeighbor:
77 window_adapt = MakeNearestNeighbor(device); 78 window_adapt = MakeNearestNeighbor(device);
diff --git a/src/video_core/renderer_opengl/gl_blit_screen.h b/src/video_core/renderer_opengl/gl_blit_screen.h
index 0c3d838f1..df2da9424 100644
--- a/src/video_core/renderer_opengl/gl_blit_screen.h
+++ b/src/video_core/renderer_opengl/gl_blit_screen.h
@@ -15,6 +15,8 @@ namespace Layout {
15struct FramebufferLayout; 15struct FramebufferLayout;
16} 16}
17 17
18struct PresentFilters;
19
18namespace Tegra { 20namespace Tegra {
19struct FramebufferConfig; 21struct FramebufferConfig;
20} 22}
@@ -46,12 +48,12 @@ public:
46 explicit BlitScreen(RasterizerOpenGL& rasterizer, 48 explicit BlitScreen(RasterizerOpenGL& rasterizer,
47 Tegra::MaxwellDeviceMemoryManager& device_memory, 49 Tegra::MaxwellDeviceMemoryManager& device_memory,
48 StateTracker& state_tracker, ProgramManager& program_manager, 50 StateTracker& state_tracker, ProgramManager& program_manager,
49 Device& device); 51 Device& device, const PresentFilters& filters);
50 ~BlitScreen(); 52 ~BlitScreen();
51 53
52 /// Draws the emulated screens to the emulator window. 54 /// Draws the emulated screens to the emulator window.
53 void DrawScreen(std::span<const Tegra::FramebufferConfig> framebuffers, 55 void DrawScreen(std::span<const Tegra::FramebufferConfig> framebuffers,
54 const Layout::FramebufferLayout& layout); 56 const Layout::FramebufferLayout& layout, bool invert_y);
55 57
56private: 58private:
57 void CreateWindowAdapt(); 59 void CreateWindowAdapt();
@@ -61,6 +63,7 @@ private:
61 StateTracker& state_tracker; 63 StateTracker& state_tracker;
62 ProgramManager& program_manager; 64 ProgramManager& program_manager;
63 Device& device; 65 Device& device;
66 const PresentFilters& filters;
64 67
65 Settings::ScalingFilter current_window_adapt{}; 68 Settings::ScalingFilter current_window_adapt{};
66 std::unique_ptr<WindowAdaptPass> window_adapt; 69 std::unique_ptr<WindowAdaptPass> window_adapt;
diff --git a/src/video_core/renderer_opengl/present/layer.cpp b/src/video_core/renderer_opengl/present/layer.cpp
index 8643e07c6..6c7092d22 100644
--- a/src/video_core/renderer_opengl/present/layer.cpp
+++ b/src/video_core/renderer_opengl/present/layer.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "video_core/framebuffer_config.h" 4#include "video_core/framebuffer_config.h"
5#include "video_core/present.h"
5#include "video_core/renderer_opengl/gl_blit_screen.h" 6#include "video_core/renderer_opengl/gl_blit_screen.h"
6#include "video_core/renderer_opengl/gl_rasterizer.h" 7#include "video_core/renderer_opengl/gl_rasterizer.h"
7#include "video_core/renderer_opengl/present/fsr.h" 8#include "video_core/renderer_opengl/present/fsr.h"
@@ -14,8 +15,9 @@
14 15
15namespace OpenGL { 16namespace OpenGL {
16 17
17Layer::Layer(RasterizerOpenGL& rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_) 18Layer::Layer(RasterizerOpenGL& rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_,
18 : rasterizer(rasterizer_), device_memory(device_memory_) { 19 const PresentFilters& filters_)
20 : rasterizer(rasterizer_), device_memory(device_memory_), filters(filters_) {
19 // Allocate textures for the screen 21 // Allocate textures for the screen
20 framebuffer_texture.resource.Create(GL_TEXTURE_2D); 22 framebuffer_texture.resource.Create(GL_TEXTURE_2D);
21 23
@@ -34,12 +36,12 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
34 std::array<ScreenRectVertex, 4>& out_vertices, 36 std::array<ScreenRectVertex, 4>& out_vertices,
35 ProgramManager& program_manager, 37 ProgramManager& program_manager,
36 const Tegra::FramebufferConfig& framebuffer, 38 const Tegra::FramebufferConfig& framebuffer,
37 const Layout::FramebufferLayout& layout) { 39 const Layout::FramebufferLayout& layout, bool invert_y) {
38 FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); 40 FramebufferTextureInfo info = PrepareRenderTarget(framebuffer);
39 auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); 41 auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height);
40 GLuint texture = info.display_texture; 42 GLuint texture = info.display_texture;
41 43
42 auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); 44 auto anti_aliasing = filters.get_anti_aliasing();
43 if (anti_aliasing != Settings::AntiAliasing::None) { 45 if (anti_aliasing != Settings::AntiAliasing::None) {
44 glEnablei(GL_SCISSOR_TEST, 0); 46 glEnablei(GL_SCISSOR_TEST, 0);
45 auto viewport_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width); 47 auto viewport_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width);
@@ -64,7 +66,7 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
64 66
65 glDisablei(GL_SCISSOR_TEST, 0); 67 glDisablei(GL_SCISSOR_TEST, 0);
66 68
67 if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { 69 if (filters.get_scaling_filter() == Settings::ScalingFilter::Fsr) {
68 if (!fsr || fsr->NeedsRecreation(layout.screen)) { 70 if (!fsr || fsr->NeedsRecreation(layout.screen)) {
69 fsr = std::make_unique<FSR>(layout.screen.GetWidth(), layout.screen.GetHeight()); 71 fsr = std::make_unique<FSR>(layout.screen.GetWidth(), layout.screen.GetHeight());
70 } 72 }
@@ -83,10 +85,15 @@ GLuint Layer::ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
83 const auto w = screen.GetWidth(); 85 const auto w = screen.GetWidth();
84 const auto h = screen.GetHeight(); 86 const auto h = screen.GetHeight();
85 87
86 out_vertices[0] = ScreenRectVertex(x, y, crop.left, crop.top); 88 const auto left = crop.left;
87 out_vertices[1] = ScreenRectVertex(x + w, y, crop.right, crop.top); 89 const auto right = crop.right;
88 out_vertices[2] = ScreenRectVertex(x, y + h, crop.left, crop.bottom); 90 const auto top = invert_y ? crop.bottom : crop.top;
89 out_vertices[3] = ScreenRectVertex(x + w, y + h, crop.right, crop.bottom); 91 const auto bottom = invert_y ? crop.top : crop.bottom;
92
93 out_vertices[0] = ScreenRectVertex(x, y, left, top);
94 out_vertices[1] = ScreenRectVertex(x + w, y, right, top);
95 out_vertices[2] = ScreenRectVertex(x, y + h, left, bottom);
96 out_vertices[3] = ScreenRectVertex(x + w, y + h, right, bottom);
90 97
91 return texture; 98 return texture;
92} 99}
@@ -131,10 +138,12 @@ FramebufferTextureInfo Layer::LoadFBToScreenInfo(const Tegra::FramebufferConfig&
131 const u64 size_in_bytes{Tegra::Texture::CalculateSize( 138 const u64 size_in_bytes{Tegra::Texture::CalculateSize(
132 true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; 139 true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
133 const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)}; 140 const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
134 const std::span<const u8> input_data(host_ptr, size_in_bytes); 141 if (host_ptr) {
135 Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, 142 const std::span<const u8> input_data(host_ptr, size_in_bytes);
136 framebuffer.width, framebuffer.height, 1, block_height_log2, 143 Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
137 0); 144 framebuffer.width, framebuffer.height, 1,
145 block_height_log2, 0);
146 }
138 147
139 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 148 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
140 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); 149 glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
diff --git a/src/video_core/renderer_opengl/present/layer.h b/src/video_core/renderer_opengl/present/layer.h
index ef1055abf..5b15b730f 100644
--- a/src/video_core/renderer_opengl/present/layer.h
+++ b/src/video_core/renderer_opengl/present/layer.h
@@ -13,6 +13,8 @@ namespace Layout {
13struct FramebufferLayout; 13struct FramebufferLayout;
14} 14}
15 15
16struct PresentFilters;
17
16namespace Service::android { 18namespace Service::android {
17enum class PixelFormat : u32; 19enum class PixelFormat : u32;
18}; 20};
@@ -44,14 +46,15 @@ struct ScreenRectVertex;
44 46
45class Layer { 47class Layer {
46public: 48public:
47 explicit Layer(RasterizerOpenGL& rasterizer, Tegra::MaxwellDeviceMemoryManager& device_memory); 49 explicit Layer(RasterizerOpenGL& rasterizer, Tegra::MaxwellDeviceMemoryManager& device_memory,
50 const PresentFilters& filters);
48 ~Layer(); 51 ~Layer();
49 52
50 GLuint ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix, 53 GLuint ConfigureDraw(std::array<GLfloat, 3 * 2>& out_matrix,
51 std::array<ScreenRectVertex, 4>& out_vertices, 54 std::array<ScreenRectVertex, 4>& out_vertices,
52 ProgramManager& program_manager, 55 ProgramManager& program_manager,
53 const Tegra::FramebufferConfig& framebuffer, 56 const Tegra::FramebufferConfig& framebuffer,
54 const Layout::FramebufferLayout& layout); 57 const Layout::FramebufferLayout& layout, bool invert_y);
55 58
56private: 59private:
57 /// Loads framebuffer from emulated memory into the active OpenGL texture. 60 /// Loads framebuffer from emulated memory into the active OpenGL texture.
@@ -65,6 +68,7 @@ private:
65private: 68private:
66 RasterizerOpenGL& rasterizer; 69 RasterizerOpenGL& rasterizer;
67 Tegra::MaxwellDeviceMemoryManager& device_memory; 70 Tegra::MaxwellDeviceMemoryManager& device_memory;
71 const PresentFilters& filters;
68 72
69 /// OpenGL framebuffer data 73 /// OpenGL framebuffer data
70 std::vector<u8> gl_framebuffer_data; 74 std::vector<u8> gl_framebuffer_data;
diff --git a/src/video_core/renderer_opengl/present/window_adapt_pass.cpp b/src/video_core/renderer_opengl/present/window_adapt_pass.cpp
index 4d681606b..d8b6a11cb 100644
--- a/src/video_core/renderer_opengl/present/window_adapt_pass.cpp
+++ b/src/video_core/renderer_opengl/present/window_adapt_pass.cpp
@@ -37,7 +37,7 @@ WindowAdaptPass::~WindowAdaptPass() = default;
37 37
38void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, std::list<Layer>& layers, 38void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, std::list<Layer>& layers,
39 std::span<const Tegra::FramebufferConfig> framebuffers, 39 std::span<const Tegra::FramebufferConfig> framebuffers,
40 const Layout::FramebufferLayout& layout) { 40 const Layout::FramebufferLayout& layout, bool invert_y) {
41 GLint old_read_fb; 41 GLint old_read_fb;
42 GLint old_draw_fb; 42 GLint old_draw_fb;
43 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); 43 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
@@ -51,7 +51,7 @@ void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, std::li
51 auto layer_it = layers.begin(); 51 auto layer_it = layers.begin();
52 for (size_t i = 0; i < layer_count; i++) { 52 for (size_t i = 0; i < layer_count; i++) {
53 textures[i] = layer_it->ConfigureDraw(matrices[i], vertices[i], program_manager, 53 textures[i] = layer_it->ConfigureDraw(matrices[i], vertices[i], program_manager,
54 framebuffers[i], layout); 54 framebuffers[i], layout, invert_y);
55 layer_it++; 55 layer_it++;
56 } 56 }
57 57
@@ -92,6 +92,21 @@ void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, std::li
92 glClear(GL_COLOR_BUFFER_BIT); 92 glClear(GL_COLOR_BUFFER_BIT);
93 93
94 for (size_t i = 0; i < layer_count; i++) { 94 for (size_t i = 0; i < layer_count; i++) {
95 switch (framebuffers[i].blending) {
96 case Tegra::BlendMode::Opaque:
97 default:
98 glDisablei(GL_BLEND, 0);
99 break;
100 case Tegra::BlendMode::Premultiplied:
101 glEnablei(GL_BLEND, 0);
102 glBlendFuncSeparatei(0, GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
103 break;
104 case Tegra::BlendMode::Coverage:
105 glEnablei(GL_BLEND, 0);
106 glBlendFuncSeparatei(0, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
107 break;
108 }
109
95 glBindTextureUnit(0, textures[i]); 110 glBindTextureUnit(0, textures[i]);
96 glProgramUniformMatrix3x2fv(vert.handle, ModelViewMatrixLocation, 1, GL_FALSE, 111 glProgramUniformMatrix3x2fv(vert.handle, ModelViewMatrixLocation, 1, GL_FALSE,
97 matrices[i].data()); 112 matrices[i].data());
diff --git a/src/video_core/renderer_opengl/present/window_adapt_pass.h b/src/video_core/renderer_opengl/present/window_adapt_pass.h
index 00975a9c6..0a8bcef2f 100644
--- a/src/video_core/renderer_opengl/present/window_adapt_pass.h
+++ b/src/video_core/renderer_opengl/present/window_adapt_pass.h
@@ -31,7 +31,7 @@ public:
31 31
32 void DrawToFramebuffer(ProgramManager& program_manager, std::list<Layer>& layers, 32 void DrawToFramebuffer(ProgramManager& program_manager, std::list<Layer>& layers,
33 std::span<const Tegra::FramebufferConfig> framebuffers, 33 std::span<const Tegra::FramebufferConfig> framebuffers,
34 const Layout::FramebufferLayout& layout); 34 const Layout::FramebufferLayout& layout, bool invert_y);
35 35
36private: 36private:
37 const Device& device; 37 const Device& device;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index e33a32592..5fb54635d 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -16,6 +16,8 @@
16#include "core/core_timing.h" 16#include "core/core_timing.h"
17#include "core/frontend/emu_window.h" 17#include "core/frontend/emu_window.h"
18#include "core/telemetry_session.h" 18#include "core/telemetry_session.h"
19#include "video_core/capture.h"
20#include "video_core/present.h"
19#include "video_core/renderer_opengl/gl_blit_screen.h" 21#include "video_core/renderer_opengl/gl_blit_screen.h"
20#include "video_core/renderer_opengl/gl_rasterizer.h" 22#include "video_core/renderer_opengl/gl_rasterizer.h"
21#include "video_core/renderer_opengl/gl_shader_manager.h" 23#include "video_core/renderer_opengl/gl_shader_manager.h"
@@ -120,7 +122,15 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
120 glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV); 122 glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
121 } 123 }
122 blit_screen = std::make_unique<BlitScreen>(rasterizer, device_memory, state_tracker, 124 blit_screen = std::make_unique<BlitScreen>(rasterizer, device_memory, state_tracker,
123 program_manager, device); 125 program_manager, device, PresentFiltersForDisplay);
126 blit_applet =
127 std::make_unique<BlitScreen>(rasterizer, device_memory, state_tracker, program_manager,
128 device, PresentFiltersForAppletCapture);
129 capture_framebuffer.Create();
130 capture_renderbuffer.Create();
131 glBindRenderbuffer(GL_RENDERBUFFER, capture_renderbuffer.handle);
132 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, VideoCore::Capture::LinearWidth,
133 VideoCore::Capture::LinearHeight);
124} 134}
125 135
126RendererOpenGL::~RendererOpenGL() = default; 136RendererOpenGL::~RendererOpenGL() = default;
@@ -130,10 +140,11 @@ void RendererOpenGL::Composite(std::span<const Tegra::FramebufferConfig> framebu
130 return; 140 return;
131 } 141 }
132 142
143 RenderAppletCaptureLayer(framebuffers);
133 RenderScreenshot(framebuffers); 144 RenderScreenshot(framebuffers);
134 145
135 state_tracker.BindFramebuffer(0); 146 state_tracker.BindFramebuffer(0);
136 blit_screen->DrawScreen(framebuffers, emu_window.GetFramebufferLayout()); 147 blit_screen->DrawScreen(framebuffers, emu_window.GetFramebufferLayout(), false);
137 148
138 ++m_current_frame; 149 ++m_current_frame;
139 150
@@ -159,11 +170,8 @@ void RendererOpenGL::AddTelemetryFields() {
159 telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); 170 telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
160} 171}
161 172
162void RendererOpenGL::RenderScreenshot(std::span<const Tegra::FramebufferConfig> framebuffers) { 173void RendererOpenGL::RenderToBuffer(std::span<const Tegra::FramebufferConfig> framebuffers,
163 if (!renderer_settings.screenshot_requested) { 174 const Layout::FramebufferLayout& layout, void* dst) {
164 return;
165 }
166
167 GLint old_read_fb; 175 GLint old_read_fb;
168 GLint old_draw_fb; 176 GLint old_draw_fb;
169 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); 177 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
@@ -173,29 +181,86 @@ void RendererOpenGL::RenderScreenshot(std::span<const Tegra::FramebufferConfig>
173 screenshot_framebuffer.Create(); 181 screenshot_framebuffer.Create();
174 glBindFramebuffer(GL_FRAMEBUFFER, screenshot_framebuffer.handle); 182 glBindFramebuffer(GL_FRAMEBUFFER, screenshot_framebuffer.handle);
175 183
176 const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
177
178 GLuint renderbuffer; 184 GLuint renderbuffer;
179 glGenRenderbuffers(1, &renderbuffer); 185 glGenRenderbuffers(1, &renderbuffer);
180 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 186 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
181 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height); 187 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
182 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); 188 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
183 189
184 blit_screen->DrawScreen(framebuffers, layout); 190 blit_screen->DrawScreen(framebuffers, layout, false);
185 191
186 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 192 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
187 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 193 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
188 glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 194 glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dst);
189 renderer_settings.screenshot_bits);
190 195
191 screenshot_framebuffer.Release(); 196 screenshot_framebuffer.Release();
192 glDeleteRenderbuffers(1, &renderbuffer); 197 glDeleteRenderbuffers(1, &renderbuffer);
193 198
194 glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); 199 glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
195 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); 200 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
201}
202
203void RendererOpenGL::RenderScreenshot(std::span<const Tegra::FramebufferConfig> framebuffers) {
204 if (!renderer_settings.screenshot_requested) {
205 return;
206 }
207
208 RenderToBuffer(framebuffers, renderer_settings.screenshot_framebuffer_layout,
209 renderer_settings.screenshot_bits);
196 210
197 renderer_settings.screenshot_complete_callback(true); 211 renderer_settings.screenshot_complete_callback(true);
198 renderer_settings.screenshot_requested = false; 212 renderer_settings.screenshot_requested = false;
199} 213}
200 214
215void RendererOpenGL::RenderAppletCaptureLayer(
216 std::span<const Tegra::FramebufferConfig> framebuffers) {
217 GLint old_read_fb;
218 GLint old_draw_fb;
219 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
220 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
221
222 glBindFramebuffer(GL_FRAMEBUFFER, capture_framebuffer.handle);
223 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
224 capture_renderbuffer.handle);
225
226 blit_applet->DrawScreen(framebuffers, VideoCore::Capture::Layout, true);
227
228 glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
229 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
230}
231
232std::vector<u8> RendererOpenGL::GetAppletCaptureBuffer() {
233 using namespace VideoCore::Capture;
234
235 std::vector<u8> linear(TiledSize);
236 std::vector<u8> out(TiledSize);
237
238 GLint old_read_fb;
239 GLint old_draw_fb;
240 GLint old_pixel_pack_buffer;
241 GLint old_pack_row_length;
242 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb);
243 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb);
244 glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &old_pixel_pack_buffer);
245 glGetIntegerv(GL_PACK_ROW_LENGTH, &old_pack_row_length);
246
247 glBindFramebuffer(GL_FRAMEBUFFER, capture_framebuffer.handle);
248 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
249 capture_renderbuffer.handle);
250 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
251 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
252 glReadPixels(0, 0, LinearWidth, LinearHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
253 linear.data());
254
255 glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb);
256 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb);
257 glBindBuffer(GL_PIXEL_PACK_BUFFER, old_pixel_pack_buffer);
258 glPixelStorei(GL_PACK_ROW_LENGTH, old_pack_row_length);
259
260 Tegra::Texture::SwizzleTexture(out, linear, BytesPerPixel, LinearWidth, LinearHeight,
261 LinearDepth, BlockHeight, BlockDepth);
262
263 return out;
264}
265
201} // namespace OpenGL 266} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index c4625c96e..60d6a1477 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -42,6 +42,8 @@ public:
42 42
43 void Composite(std::span<const Tegra::FramebufferConfig> framebuffers) override; 43 void Composite(std::span<const Tegra::FramebufferConfig> framebuffers) override;
44 44
45 std::vector<u8> GetAppletCaptureBuffer() override;
46
45 VideoCore::RasterizerInterface* ReadRasterizer() override { 47 VideoCore::RasterizerInterface* ReadRasterizer() override {
46 return &rasterizer; 48 return &rasterizer;
47 } 49 }
@@ -52,7 +54,11 @@ public:
52 54
53private: 55private:
54 void AddTelemetryFields(); 56 void AddTelemetryFields();
57
58 void RenderToBuffer(std::span<const Tegra::FramebufferConfig> framebuffers,
59 const Layout::FramebufferLayout& layout, void* dst);
55 void RenderScreenshot(std::span<const Tegra::FramebufferConfig> framebuffers); 60 void RenderScreenshot(std::span<const Tegra::FramebufferConfig> framebuffers);
61 void RenderAppletCaptureLayer(std::span<const Tegra::FramebufferConfig> framebuffers);
56 62
57 Core::TelemetrySession& telemetry_session; 63 Core::TelemetrySession& telemetry_session;
58 Core::Frontend::EmuWindow& emu_window; 64 Core::Frontend::EmuWindow& emu_window;
@@ -64,8 +70,11 @@ private:
64 ProgramManager program_manager; 70 ProgramManager program_manager;
65 RasterizerOpenGL rasterizer; 71 RasterizerOpenGL rasterizer;
66 OGLFramebuffer screenshot_framebuffer; 72 OGLFramebuffer screenshot_framebuffer;
73 OGLFramebuffer capture_framebuffer;
74 OGLRenderbuffer capture_renderbuffer;
67 75
68 std::unique_ptr<BlitScreen> blit_screen; 76 std::unique_ptr<BlitScreen> blit_screen;
77 std::unique_ptr<BlitScreen> blit_applet;
69}; 78};
70 79
71} // namespace OpenGL 80} // namespace OpenGL