summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/AsyncRequests.cpp
diff options
context:
space:
mode:
authorJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
committerJules Blok <jules.blok@gmail.com>2015-06-10 00:00:12 +0200
commit7dfced21a2e5aac7195e0e1ad76468e30306766b (patch)
treebd671b639d3d911460b767caabad8fc8a759a6bf /Source/Core/VideoCommon/AsyncRequests.cpp
parentc25be031fc1031d795157d8344b87b7841145197 (diff)
parent7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff)
Merge branch 'master' into stable
Diffstat (limited to 'Source/Core/VideoCommon/AsyncRequests.cpp')
-rw-r--r--Source/Core/VideoCommon/AsyncRequests.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/AsyncRequests.cpp b/Source/Core/VideoCommon/AsyncRequests.cpp
new file mode 100644
index 0000000000..993b6bce2c
--- /dev/null
+++ b/Source/Core/VideoCommon/AsyncRequests.cpp
@@ -0,0 +1,147 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "VideoCommon/AsyncRequests.h"
+#include "VideoCommon/Fifo.h"
+#include "VideoCommon/RenderBase.h"
+
+AsyncRequests AsyncRequests::s_singleton;
+
+AsyncRequests::AsyncRequests()
+: m_enable(false), m_passthrough(true)
+{
+}
+
+void AsyncRequests::PullEventsInternal()
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_empty.store(true);
+
+ while (!m_queue.empty())
+ {
+ Event e = m_queue.front();
+
+ // try to merge as many efb pokes as possible
+ // it's a bit hacky, but some games render a complete frame in this way
+ if ((e.type == Event::EFB_POKE_COLOR || e.type == Event::EFB_POKE_Z))
+ {
+ m_merged_efb_pokes.clear();
+ Event first_event = m_queue.front();
+ EFBAccessType t = first_event.type == Event::EFB_POKE_COLOR ? POKE_COLOR : POKE_Z;
+
+ do
+ {
+ e = m_queue.front();
+
+ EfbPokeData d;
+ d.data = e.efb_poke.data;
+ d.x = e.efb_poke.x;
+ d.y = e.efb_poke.y;
+ m_merged_efb_pokes.push_back(d);
+
+ m_queue.pop();
+ } while(!m_queue.empty() && m_queue.front().type == first_event.type);
+
+ lock.unlock();
+ g_renderer->PokeEFB(t, m_merged_efb_pokes);
+ lock.lock();
+ continue;
+ }
+
+ lock.unlock();
+ HandleEvent(e);
+ lock.lock();
+
+ m_queue.pop();
+ }
+
+ if (m_wake_me_up_again)
+ {
+ m_wake_me_up_again = false;
+ m_cond.notify_all();
+ }
+}
+
+void AsyncRequests::PushEvent(const AsyncRequests::Event& event, bool blocking)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+
+ if (m_passthrough)
+ {
+ HandleEvent(event);
+ return;
+ }
+
+ m_empty.store(false);
+ m_wake_me_up_again |= blocking;
+
+ if (!m_enable)
+ return;
+
+ m_queue.push(event);
+
+ RunGpu();
+ if (blocking)
+ {
+ m_cond.wait(lock, [this]{return m_queue.empty();});
+ }
+}
+
+void AsyncRequests::SetEnable(bool enable)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_enable = enable;
+
+ if (!enable)
+ {
+ // flush the queue on disabling
+ while (!m_queue.empty())
+ m_queue.pop();
+ if (m_wake_me_up_again)
+ m_cond.notify_all();
+ }
+}
+
+void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
+{
+ EFBRectangle rc;
+ switch (e.type)
+ {
+ case Event::EFB_POKE_COLOR:
+ g_renderer->AccessEFB(POKE_COLOR, e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
+ break;
+
+ case Event::EFB_POKE_Z:
+ g_renderer->AccessEFB(POKE_Z, e.efb_poke.x, e.efb_poke.y, e.efb_poke.data);
+ break;
+
+ case Event::EFB_PEEK_COLOR:
+ *e.efb_peek.data = g_renderer->AccessEFB(PEEK_COLOR, e.efb_peek.x, e.efb_peek.y, 0);
+ break;
+
+ case Event::EFB_PEEK_Z:
+ *e.efb_peek.data = g_renderer->AccessEFB(PEEK_Z, e.efb_peek.x, e.efb_peek.y, 0);
+ break;
+
+ case Event::SWAP_EVENT:
+ Renderer::Swap(e.swap_event.xfbAddr, e.swap_event.fbWidth, e.swap_event.fbStride, e.swap_event.fbHeight, rc);
+ break;
+
+ case Event::BBOX_READ:
+ *e.bbox.data = g_renderer->BBoxRead(e.bbox.index);
+ break;
+
+ case Event::PERF_QUERY:
+ g_perf_query->FlushResults();
+ break;
+
+ }
+}
+
+void AsyncRequests::SetPassthrough(bool enable)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_passthrough = enable;
+}
+