summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/renderer_opengl.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp64
1 files changed, 54 insertions, 10 deletions
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 90b68943d..235732d86 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -19,9 +19,9 @@
#include "core/settings.h"
#include "core/telemetry_session.h"
#include "core/tracer/recorder.h"
+#include "video_core/morton.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
-#include "video_core/utils.h"
namespace OpenGL {
@@ -115,7 +115,8 @@ RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window)
RendererOpenGL::~RendererOpenGL() = default;
/// Swap buffers (render frame)
-void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) {
+void RendererOpenGL::SwapBuffers(
+ std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) {
ScopeAcquireGLContext acquire_context{render_window};
Core::System::GetInstance().GetPerfStats().EndSystemFrame();
@@ -124,11 +125,11 @@ void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&
OpenGLState prev_state = OpenGLState::GetCurState();
state.Apply();
- if (framebuffer != boost::none) {
+ if (framebuffer) {
// If framebuffer is provided, reload it from memory to a texture
- if (screen_info.texture.width != (GLsizei)framebuffer->width ||
- screen_info.texture.height != (GLsizei)framebuffer->height ||
- screen_info.texture.pixel_format != framebuffer->pixel_format) {
+ if (screen_info.texture.width != (GLsizei)framebuffer->get().width ||
+ screen_info.texture.height != (GLsizei)framebuffer->get().height ||
+ screen_info.texture.pixel_format != framebuffer->get().pixel_format) {
// Reallocate texture if the framebuffer size has changed.
// This is expected to not happen very often and hence should not be a
// performance problem.
@@ -137,7 +138,12 @@ void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&
// 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();
}
@@ -303,6 +309,12 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
gl_framebuffer_data.resize(texture.width * texture.height * 4);
break;
default:
+ internal_format = GL_RGBA;
+ texture.gl_format = GL_RGBA;
+ texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ gl_framebuffer_data.resize(texture.width * texture.height * 4);
+ LOG_CRITICAL(Render_OpenGL, "Unknown framebuffer pixel format: {}",
+ static_cast<u32>(framebuffer.pixel_format));
UNREACHABLE();
}
@@ -376,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);
@@ -407,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: \
@@ -420,6 +462,7 @@ static const char* GetSource(GLenum source) {
RET(OTHER);
default:
UNREACHABLE();
+ return "Unknown source";
}
#undef RET
}
@@ -438,6 +481,7 @@ static const char* GetType(GLenum type) {
RET(MARKER);
default:
UNREACHABLE();
+ return "Unknown type";
}
#undef RET
}
@@ -483,7 +527,7 @@ bool RendererOpenGL::Init() {
Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Model", gpu_model);
Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_OpenGL_Version", gl_version);
- if (!GLAD_GL_VERSION_3_3) {
+ if (!GLAD_GL_VERSION_4_3) {
return false;
}