summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/Render.cpp
diff options
context:
space:
mode:
authordegasus <wickmarkus@web.de>2016-10-08 02:11:24 +0200
committerdegasus <wickmarkus@web.de>2016-11-07 22:17:32 +0100
commitf6a6cc9c6743c1f9e9262775a6da7afbd153b19c (patch)
tree58d74d7b4d3b651ddddc43a331912490c0d8cc95 /Source/Core/VideoBackends/OGL/Render.cpp
parent136a10482f099aec67cebd8673388f54b78458b6 (diff)
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.cpp66
1 files changed, 54 insertions, 12 deletions
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp
index e3d3bea2d5..f0ab819815 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,55 @@ 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 * m_last_frame_height * 4, GL_MAP_READ_BIT);
+ DumpFrameData(reinterpret_cast<u8*>(data), m_last_frame_width, m_last_frame_height,
+ m_last_frame_width * 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]);
+ 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;
+ }
+
+ m_last_frame_width = flipped_trc.GetWidth();
+ m_last_frame_height = flipped_trc.GetHeight();
+ m_last_frame_state = AVIDump::FetchState(ticks);
+ m_last_frame_exported = true;
+
+ glBufferData(GL_PIXEL_PACK_BUFFER, m_last_frame_width * m_last_frame_height * 4, nullptr,
+ GL_STREAM_READ);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ glReadPixels(flipped_trc.left, flipped_trc.bottom, m_last_frame_width, m_last_frame_height,
+ 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()
{