summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
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() {
render_window.UpdateCurrentFramebufferLayout(layout.width, layout.height);
}
+void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
+ const Layout::FramebufferLayout& layout) {
+ if (renderer_settings.screenshot_requested) {
+ LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
+ return;
+ }
+ renderer_settings.screenshot_bits = data;
+ renderer_settings.screenshot_complete_callback = std::move(callback);
+ renderer_settings.screenshot_framebuffer_layout = layout;
+ renderer_settings.screenshot_requested = true;
+}
+
} // 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 @@
#include <optional>
#include "common/common_types.h"
+#include "core/frontend/emu_window.h"
#include "video_core/gpu.h"
#include "video_core/rasterizer_interface.h"
@@ -21,6 +22,12 @@ namespace VideoCore {
struct RendererSettings {
std::atomic_bool use_framelimiter{false};
std::atomic_bool set_background_color{false};
+
+ // Screenshot
+ std::atomic<bool> screenshot_requested{false};
+ void* screenshot_bits;
+ std::function<void()> screenshot_complete_callback;
+ Layout::FramebufferLayout screenshot_framebuffer_layout;
};
class RendererBase : NonCopyable {
@@ -57,9 +64,29 @@ public:
return *rasterizer;
}
+ Core::Frontend::EmuWindow& GetRenderWindow() {
+ return render_window;
+ }
+
+ const Core::Frontend::EmuWindow& GetRenderWindow() const {
+ return render_window;
+ }
+
+ RendererSettings& Settings() {
+ return renderer_settings;
+ }
+
+ const RendererSettings& Settings() const {
+ return renderer_settings;
+ }
+
/// Refreshes the settings common to all renderers
void RefreshBaseSettings();
+ /// Request a screenshot of the next frame
+ void RequestScreenshot(void* data, std::function<void()> callback,
+ const Layout::FramebufferLayout& layout);
+
protected:
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
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(
// Load the framebuffer from memory, draw it to the screen, and swap buffers
LoadFBToScreenInfo(*framebuffer);
- DrawScreen();
+
+ if (renderer_settings.screenshot_requested)
+ CaptureScreenshot();
+
+ DrawScreen(render_window.GetFramebufferLayout());
+
render_window.SwapBuffers();
}
@@ -383,14 +388,13 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
/**
* Draws the emulated screens to the emulator window.
*/
-void RendererOpenGL::DrawScreen() {
+void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
if (renderer_settings.set_background_color) {
// Update background color before drawing
glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
0.0f);
}
- const auto& layout = render_window.GetFramebufferLayout();
const auto& screen = layout.screen;
glViewport(0, 0, layout.width, layout.height);
@@ -414,6 +418,37 @@ void RendererOpenGL::DrawScreen() {
/// Updates the framerate
void RendererOpenGL::UpdateFramerate() {}
+void RendererOpenGL::CaptureScreenshot() {
+ // Draw the current frame to the screenshot framebuffer
+ screenshot_framebuffer.Create();
+ GLuint old_read_fb = state.draw.read_framebuffer;
+ GLuint old_draw_fb = state.draw.draw_framebuffer;
+ state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
+ state.Apply();
+
+ Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
+
+ GLuint renderbuffer;
+ glGenRenderbuffers(1, &renderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, layout.width, layout.height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
+
+ DrawScreen(layout);
+
+ glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ renderer_settings.screenshot_bits);
+
+ screenshot_framebuffer.Release();
+ state.draw.read_framebuffer = old_read_fb;
+ state.draw.draw_framebuffer = old_draw_fb;
+ state.Apply();
+ glDeleteRenderbuffers(1, &renderbuffer);
+
+ renderer_settings.screenshot_complete_callback();
+ renderer_settings.screenshot_requested = false;
+}
+
static const char* GetSource(GLenum source) {
#define RET(s) \
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 {
class EmuWindow;
}
+namespace Layout {
+class FramebufferLayout;
+}
+
namespace OpenGL {
/// Structure used for storing information about the textures for the Switch screen
@@ -66,10 +70,12 @@ private:
void ConfigureFramebufferTexture(TextureInfo& texture,
const Tegra::FramebufferConfig& framebuffer);
- void DrawScreen();
+ void DrawScreen(const Layout::FramebufferLayout& layout);
void DrawScreenTriangles(const ScreenInfo& screen_info, float x, float y, float w, float h);
void UpdateFramerate();
+ void CaptureScreenshot();
+
// Loads framebuffer from emulated memory into the display information structure
void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
// Fills active OpenGL texture with the given RGBA color.
@@ -82,6 +88,7 @@ private:
OGLVertexArray vertex_array;
OGLBuffer vertex_buffer;
OGLProgram shader;
+ OGLFramebuffer screenshot_framebuffer;
/// Display information for Switch screen
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 @@
// Refer to the license.txt file included.
#include <memory>
+#include "core/core.h"
+#include "core/settings.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
#include "video_core/video_core.h"
@@ -13,4 +15,10 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind
return std::make_unique<OpenGL::RendererOpenGL>(emu_window);
}
+u16 GetResolutionScaleFactor(const RendererBase& renderer) {
+ return !Settings::values.resolution_factor
+ ? renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio()
+ : Settings::values.resolution_factor;
+}
+
} // 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;
*/
std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window);
+u16 GetResolutionScaleFactor(const RendererBase& renderer);
+
} // namespace VideoCore