summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorGravatar zhupengfei2018-08-31 14:16:16 +0800
committerGravatar fearlessTobi2018-12-18 22:54:41 +0100
commita2be49305d8c5c66cfa2ec2060688013cf3729b9 (patch)
tree2a2e38805ae8af0718628682d7e911ccb253fc16 /src/video_core
parentMerge pull request #1868 from lioncash/config (diff)
downloadyuzu-a2be49305d8c5c66cfa2ec2060688013cf3729b9.tar.gz
yuzu-a2be49305d8c5c66cfa2ec2060688013cf3729b9.tar.xz
yuzu-a2be49305d8c5c66cfa2ec2060688013cf3729b9.zip
yuzu, video_core: Screenshot functionality
Allows capturing screenshot at the current internal resolution (native for software renderer), but a setting is available to capture it in other resolutions. The screenshot is saved to a single PNG in the current layout.
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/renderer_base.cpp12
-rw-r--r--src/video_core/renderer_base.h27
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp41
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h9
-rw-r--r--src/video_core/video_core.cpp8
-rw-r--r--src/video_core/video_core.h2
6 files changed, 95 insertions, 4 deletions
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index 1482cdb40..94223f45f 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -27,4 +27,16 @@ void RendererBase::UpdateCurrentFramebufferLayout() {
27 render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height); 27 render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
28} 28}
29 29
30void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
31 const Layout::FramebufferLayout& layout) {
32 if (renderer_settings.screenshot_requested) {
33 LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
34 return;
35 }
36 renderer_settings.screenshot_bits = data;
37 renderer_settings.screenshot_complete_callback = std::move(callback);
38 renderer_settings.screenshot_framebuffer_layout = layout;
39 renderer_settings.screenshot_requested = true;
40}
41
30} // namespace VideoCore 42} // namespace VideoCore
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 669e26e15..1d54c3723 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -9,6 +9,7 @@
9#include <optional> 9#include <optional>
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/frontend/emu_window.h"
12#include "video_core/gpu.h" 13#include "video_core/gpu.h"
13#include "video_core/rasterizer_interface.h" 14#include "video_core/rasterizer_interface.h"
14 15
@@ -21,6 +22,12 @@ namespace VideoCore {
21struct RendererSettings { 22struct RendererSettings {
22 std::atomic_bool use_framelimiter{false}; 23 std::atomic_bool use_framelimiter{false};
23 std::atomic_bool set_background_color{false}; 24 std::atomic_bool set_background_color{false};
25
26 // Screenshot
27 std::atomic<bool> screenshot_requested{false};
28 void* screenshot_bits;
29 std::function<void()> screenshot_complete_callback;
30 Layout::FramebufferLayout screenshot_framebuffer_layout;
24}; 31};
25 32
26class RendererBase : NonCopyable { 33class RendererBase : NonCopyable {
@@ -57,9 +64,29 @@ public:
57 return *rasterizer; 64 return *rasterizer;
58 } 65 }
59 66
67 Core::Frontend::EmuWindow& GetRenderWindow() {
68 return render_window;
69 }
70
71 const Core::Frontend::EmuWindow& GetRenderWindow() const {
72 return render_window;
73 }
74
75 RendererSettings& Settings() {
76 return renderer_settings;
77 }
78
79 const RendererSettings& Settings() const {
80 return renderer_settings;
81 }
82
60 /// Refreshes the settings common to all renderers 83 /// Refreshes the settings common to all renderers
61 void RefreshBaseSettings(); 84 void RefreshBaseSettings();
62 85
86 /// Request a screenshot of the next frame
87 void RequestScreenshot(void* data, std::function<void()> callback,
88 const Layout::FramebufferLayout& layout);
89
63protected: 90protected:
64 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. 91 Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
65 std::unique_ptr<RasterizerInterface> rasterizer; 92 std::unique_ptr<RasterizerInterface> rasterizer;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 4fd0d66c5..49a1989e4 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -138,7 +138,12 @@ void RendererOpenGL::SwapBuffers(
138 138
139 // Load the framebuffer from memory, draw it to the screen, and swap buffers 139 // Load the framebuffer from memory, draw it to the screen, and swap buffers
140 LoadFBToScreenInfo(*framebuffer); 140 LoadFBToScreenInfo(*framebuffer);
141 DrawScreen(); 141
142 if (renderer_settings.screenshot_requested)
143 CaptureScreenshot();
144
145 DrawScreen(render_window.GetFramebufferLayout());
146
142 render_window.SwapBuffers(); 147 render_window.SwapBuffers();
143 } 148 }
144 149
@@ -383,14 +388,13 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
383/** 388/**
384 * Draws the emulated screens to the emulator window. 389 * Draws the emulated screens to the emulator window.
385 */ 390 */
386void RendererOpenGL::DrawScreen() { 391void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
387 if (renderer_settings.set_background_color) { 392 if (renderer_settings.set_background_color) {
388 // Update background color before drawing 393 // Update background color before drawing
389 glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, 394 glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
390 0.0f); 395 0.0f);
391 } 396 }
392 397
393 const auto& layout = render_window.GetFramebufferLayout();
394 const auto& screen = layout.screen; 398 const auto& screen = layout.screen;
395 399
396 glViewport(0, 0, layout.width, layout.height); 400 glViewport(0, 0, layout.width, layout.height);
@@ -414,6 +418,37 @@ void RendererOpenGL::DrawScreen() {
414/// Updates the framerate 418/// Updates the framerate
415void RendererOpenGL::UpdateFramerate() {} 419void RendererOpenGL::UpdateFramerate() {}
416 420
421void RendererOpenGL::CaptureScreenshot() {
422 // Draw the current frame to the screenshot framebuffer
423 screenshot_framebuffer.Create();
424 GLuint old_read_fb = state.draw.read_framebuffer;
425 GLuint old_draw_fb = state.draw.draw_framebuffer;
426 state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
427 state.Apply();
428
429 Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
430
431 GLuint renderbuffer;
432 glGenRenderbuffers(1, &renderbuffer);
433 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
434 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, layout.width, layout.height);
435 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
436
437 DrawScreen(layout);
438
439 glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
440 renderer_settings.screenshot_bits);
441
442 screenshot_framebuffer.Release();
443 state.draw.read_framebuffer = old_read_fb;
444 state.draw.draw_framebuffer = old_draw_fb;
445 state.Apply();
446 glDeleteRenderbuffers(1, &renderbuffer);
447
448 renderer_settings.screenshot_complete_callback();
449 renderer_settings.screenshot_requested = false;
450}
451
417static const char* GetSource(GLenum source) { 452static const char* GetSource(GLenum source) {
418#define RET(s) \ 453#define RET(s) \
419 case GL_DEBUG_SOURCE_##s: \ 454 case GL_DEBUG_SOURCE_##s: \
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index c0868c0e4..067fad81b 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -16,6 +16,10 @@ namespace Core::Frontend {
16class EmuWindow; 16class EmuWindow;
17} 17}
18 18
19namespace Layout {
20class FramebufferLayout;
21}
22
19namespace OpenGL { 23namespace OpenGL {
20 24
21/// Structure used for storing information about the textures for the Switch screen 25/// Structure used for storing information about the textures for the Switch screen
@@ -66,10 +70,12 @@ private:
66 70
67 void ConfigureFramebufferTexture(TextureInfo& texture, 71 void ConfigureFramebufferTexture(TextureInfo& texture,
68 const Tegra::FramebufferConfig& framebuffer); 72 const Tegra::FramebufferConfig& framebuffer);
69 void DrawScreen(); 73 void DrawScreen(const Layout::FramebufferLayout& layout);
70 void DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, float h); 74 void DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, float h);
71 void UpdateFramerate(); 75 void UpdateFramerate();
72 76
77 void CaptureScreenshot();
78
73 // Loads framebuffer from emulated memory into the display information structure 79 // Loads framebuffer from emulated memory into the display information structure
74 void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); 80 void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
75 // Fills active OpenGL texture with the given RGBA color. 81 // Fills active OpenGL texture with the given RGBA color.
@@ -82,6 +88,7 @@ private:
82 OGLVertexArray vertex_array; 88 OGLVertexArray vertex_array;
83 OGLBuffer vertex_buffer; 89 OGLBuffer vertex_buffer;
84 OGLProgram shader; 90 OGLProgram shader;
91 OGLFramebuffer screenshot_framebuffer;
85 92
86 /// Display information for Switch screen 93 /// Display information for Switch screen
87 ScreenInfo screen_info; 94 ScreenInfo screen_info;
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 07e3a7d24..f7de3471b 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -3,6 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6#include "core/core.h"
7#include "core/settings.h"
6#include "video_core/renderer_base.h" 8#include "video_core/renderer_base.h"
7#include "video_core/renderer_opengl/renderer_opengl.h" 9#include "video_core/renderer_opengl/renderer_opengl.h"
8#include "video_core/video_core.h" 10#include "video_core/video_core.h"
@@ -13,4 +15,10 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind
13 return std::make_unique<OpenGL::RendererOpenGL>(emu_window); 15 return std::make_unique<OpenGL::RendererOpenGL>(emu_window);
14} 16}
15 17
18u16 GetResolutionScaleFactor(const RendererBase& renderer) {
19 return !Settings::values.resolution_factor
20 ? renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio()
21 : Settings::values.resolution_factor;
22}
23
16} // namespace VideoCore 24} // namespace VideoCore
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h
index f79f85dfe..5b373bcb1 100644
--- a/src/video_core/video_core.h
+++ b/src/video_core/video_core.h
@@ -22,4 +22,6 @@ class RendererBase;
22 */ 22 */
23std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window); 23std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window);
24 24
25u16 GetResolutionScaleFactor(const RendererBase& renderer);
26
25} // namespace VideoCore 27} // namespace VideoCore