summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/Render.cpp
diff options
context:
space:
mode:
authorMarkus Wick <degasus@users.noreply.github.com>2016-11-08 10:50:38 +0100
committerGitHub <noreply@github.com>2016-11-08 10:50:38 +0100
commit363dec7bc7161215f32b4a1a16141d5c3509149c (patch)
tree6b4519d96351c45f39b352d96c8b3b7929e490fd /Source/Core/VideoBackends/OGL/Render.cpp
parent136a10482f099aec67cebd8673388f54b78458b6 (diff)
parent741debe2291b0788ec2fb54ec24f49490704d609 (diff)
Merge pull request #4344 from degasus/framedump_ogl
OGL: Use PBO for framedump, with async readback.
Diffstat (limited to 'Source/Core/VideoBackends/OGL/Render.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/Render.cpp73
1 files changed, 61 insertions, 12 deletions
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index e3d3bea2d5..b1fae3b98c 100644
--- a/Source/Core/VideoBackends/OGL/Render.cpp
+++ b/Source/Core/VideoBackends/OGL/Render.cpp
@@ -767,6 +767,9 @@ Renderer::Renderer()
Renderer::~Renderer()
{
+ FlushFrameDump();
+ if (m_frame_dumping_pbo[0])
+ glDeleteBuffers(2, m_frame_dumping_pbo.data());
}
void Renderer::Shutdown()
@@ -1447,19 +1450,9 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
- if (IsFrameDumping())
- {
- std::vector<u8> image(flipped_trc.GetWidth() * flipped_trc.GetHeight() * 4);
-
- glPixelStorei(GL_PACK_ALIGNMENT, 1);
- glReadPixels(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(),
- flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data());
+ FlushFrameDump();
+ DumpFrame(flipped_trc, ticks);
- AVIDump::Frame state = AVIDump::FetchState(ticks);
- DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(),
- flipped_trc.GetWidth() * 4, state, true);
- FinishFrameData();
- }
// Finish up the current frame, print some stats
SetWindowSize(fbStride, fbHeight);
@@ -1588,6 +1581,62 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
ClearEFBCache();
}
+void Renderer::FlushFrameDump()
+{
+ if (!m_last_frame_exported)
+ return;
+
+ FinishFrameData();
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]);
+ m_frame_pbo_is_mapped[0] = true;
+ void* data = glMapBufferRange(
+ GL_PIXEL_PACK_BUFFER, 0, m_last_frame_width[0] * m_last_frame_height[0] * 4, GL_MAP_READ_BIT);
+ DumpFrameData(reinterpret_cast<u8*>(data), m_last_frame_width[0], m_last_frame_height[0],
+ m_last_frame_width[0] * 4, m_last_frame_state, true);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+ m_last_frame_exported = false;
+}
+
+void Renderer::DumpFrame(const TargetRectangle& flipped_trc, u64 ticks)
+{
+ if (!IsFrameDumping())
+ return;
+
+ if (!m_frame_dumping_pbo[0])
+ {
+ glGenBuffers(2, m_frame_dumping_pbo.data());
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]);
+ }
+ else
+ {
+ std::swap(m_frame_dumping_pbo[0], m_frame_dumping_pbo[1]);
+ std::swap(m_frame_pbo_is_mapped[0], m_frame_pbo_is_mapped[1]);
+ std::swap(m_last_frame_width[0], m_last_frame_width[1]);
+ std::swap(m_last_frame_height[0], m_last_frame_height[1]);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]);
+ if (m_frame_pbo_is_mapped[0])
+ glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+ m_frame_pbo_is_mapped[0] = false;
+ }
+
+ if (flipped_trc.GetWidth() != m_last_frame_width[0] ||
+ flipped_trc.GetHeight() != m_last_frame_height[0])
+ {
+ m_last_frame_width[0] = flipped_trc.GetWidth();
+ m_last_frame_height[0] = flipped_trc.GetHeight();
+ glBufferData(GL_PIXEL_PACK_BUFFER, m_last_frame_width[0] * m_last_frame_height[0] * 4, nullptr,
+ GL_STREAM_READ);
+ }
+
+ m_last_frame_state = AVIDump::FetchState(ticks);
+ m_last_frame_exported = true;
+
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glReadPixels(flipped_trc.left, flipped_trc.bottom, m_last_frame_width[0], m_last_frame_height[0],
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+}
+
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
void Renderer::ResetAPIState()
{