Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
227
libs/drape_frontend/base_renderer.cpp
Normal file
227
libs/drape_frontend/base_renderer.cpp
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
#include "drape_frontend/base_renderer.hpp"
|
||||
#include "drape_frontend/message_subclasses.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#if defined(OMIM_METAL_AVAILABLE)
|
||||
namespace dp
|
||||
{
|
||||
extern void RenderFrameMediator(std::function<void()> && renderFrameFunction);
|
||||
} // namespace dp
|
||||
#define RENDER_FRAME_MEDIATOR(renderFunction) dp::RenderFrameMediator([this] { renderFunction; })
|
||||
#else
|
||||
#define RENDER_FRAME_MEDIATOR(renderFunction) renderFunction
|
||||
#endif
|
||||
|
||||
namespace df
|
||||
{
|
||||
// static
|
||||
std::atomic<uint8_t> BaseRenderer::m_contextCounter(0);
|
||||
|
||||
BaseRenderer::BaseRenderer(ThreadsCommutator::ThreadName name, Params const & params)
|
||||
: m_apiVersion(params.m_apiVersion)
|
||||
, m_commutator(params.m_commutator)
|
||||
, m_contextFactory(params.m_oglContextFactory)
|
||||
, m_texMng(params.m_texMng)
|
||||
, m_threadName(name)
|
||||
, m_isEnabled(true)
|
||||
, m_renderingEnablingCompletionHandler(nullptr)
|
||||
, m_wasNotified(false)
|
||||
, m_wasContextReset(false)
|
||||
, m_onGraphicsContextInitialized(params.m_onGraphicsContextInitialized)
|
||||
{
|
||||
m_commutator->RegisterThread(m_threadName, this);
|
||||
}
|
||||
|
||||
void BaseRenderer::StartThread()
|
||||
{
|
||||
m_selfThread.Create(CreateRoutine());
|
||||
}
|
||||
|
||||
void BaseRenderer::StopThread()
|
||||
{
|
||||
// stop rendering and close queue
|
||||
m_selfThread.GetRoutine()->Cancel();
|
||||
CloseQueue();
|
||||
|
||||
// wake up render thread if necessary
|
||||
if (!m_isEnabled)
|
||||
WakeUp();
|
||||
|
||||
// wait for render thread completion
|
||||
m_selfThread.Join();
|
||||
}
|
||||
|
||||
void BaseRenderer::IterateRenderLoop()
|
||||
{
|
||||
RENDER_FRAME_MEDIATOR(IterateRenderLoopImpl());
|
||||
}
|
||||
|
||||
void BaseRenderer::IterateRenderLoopImpl()
|
||||
{
|
||||
RenderFrame();
|
||||
CheckRenderingEnabled();
|
||||
}
|
||||
|
||||
void BaseRenderer::SetRenderingEnabled(ref_ptr<dp::GraphicsContextFactory> contextFactory)
|
||||
{
|
||||
if (m_wasContextReset && contextFactory != nullptr)
|
||||
m_contextFactory = contextFactory;
|
||||
SetRenderingEnabled(true);
|
||||
}
|
||||
|
||||
void BaseRenderer::SetRenderingDisabled(bool const destroySurface)
|
||||
{
|
||||
if (destroySurface)
|
||||
m_wasContextReset = true;
|
||||
SetRenderingEnabled(false);
|
||||
}
|
||||
|
||||
bool BaseRenderer::IsRenderingEnabled() const
|
||||
{
|
||||
return m_isEnabled;
|
||||
}
|
||||
|
||||
void BaseRenderer::SetRenderingEnabled(bool const isEnabled)
|
||||
{
|
||||
if (isEnabled == m_isEnabled)
|
||||
return;
|
||||
|
||||
// here we have to wait for completion of internal SetRenderingEnabled
|
||||
std::mutex completionMutex;
|
||||
std::condition_variable completionCondition;
|
||||
bool notified = false;
|
||||
auto handler = [&]()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(completionMutex);
|
||||
notified = true;
|
||||
completionCondition.notify_one();
|
||||
};
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_completionHandlerMutex);
|
||||
m_renderingEnablingCompletionHandler = std::move(handler);
|
||||
}
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
// wake up rendering thread
|
||||
WakeUp();
|
||||
}
|
||||
else
|
||||
{
|
||||
// here we set up value only if rendering disabled
|
||||
m_isEnabled = false;
|
||||
|
||||
// if renderer thread is waiting for message let it go
|
||||
CancelMessageWaiting();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(completionMutex);
|
||||
completionCondition.wait(lock, [¬ified] { return notified; });
|
||||
}
|
||||
|
||||
bool BaseRenderer::FilterContextDependentMessage(ref_ptr<Message> msg)
|
||||
{
|
||||
return msg->IsGraphicsContextDependent();
|
||||
}
|
||||
|
||||
void BaseRenderer::CreateContext()
|
||||
{
|
||||
OnContextCreate();
|
||||
|
||||
m_contextCounter++;
|
||||
uint8_t constexpr kContextCount = 2;
|
||||
if (m_contextCounter == kContextCount && m_onGraphicsContextInitialized)
|
||||
m_onGraphicsContextInitialized();
|
||||
}
|
||||
|
||||
void BaseRenderer::CheckRenderingEnabled()
|
||||
{
|
||||
if (!m_isEnabled)
|
||||
{
|
||||
dp::GraphicsContext * context = nullptr;
|
||||
|
||||
if (m_wasContextReset)
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
EnableMessageFiltering(std::bind(&BaseRenderer::FilterContextDependentMessage, this, _1));
|
||||
OnContextDestroy();
|
||||
CHECK(m_contextCounter > 0, ());
|
||||
m_contextCounter--;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool const isDrawContext = m_threadName == ThreadsCommutator::RenderThread;
|
||||
context = isDrawContext ? m_contextFactory->GetDrawContext() : m_contextFactory->GetResourcesUploadContext();
|
||||
context->SetRenderingEnabled(false);
|
||||
}
|
||||
|
||||
OnRenderingDisabled();
|
||||
|
||||
// notify initiator-thread about rendering disabling
|
||||
Notify();
|
||||
|
||||
// wait for signal
|
||||
std::unique_lock<std::mutex> lock(m_renderingEnablingMutex);
|
||||
m_renderingEnablingCondition.wait(lock, [this] { return m_wasNotified; });
|
||||
|
||||
m_wasNotified = false;
|
||||
|
||||
bool needCreateContext = false;
|
||||
if (!m_selfThread.GetRoutine()->IsCancelled())
|
||||
{
|
||||
// here rendering is enabled again
|
||||
m_isEnabled = true;
|
||||
|
||||
if (m_wasContextReset)
|
||||
{
|
||||
m_wasContextReset = false;
|
||||
needCreateContext = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->SetRenderingEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (needCreateContext)
|
||||
DisableMessageFiltering();
|
||||
|
||||
// notify initiator-thread about rendering enabling
|
||||
// m_renderingEnablingCompletionHandler will be setup before awakening of this thread
|
||||
Notify();
|
||||
|
||||
OnRenderingEnabled();
|
||||
|
||||
if (needCreateContext)
|
||||
CreateContext();
|
||||
}
|
||||
}
|
||||
|
||||
void BaseRenderer::Notify()
|
||||
{
|
||||
std::function<void()> handler;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_completionHandlerMutex);
|
||||
handler = std::move(m_renderingEnablingCompletionHandler);
|
||||
m_renderingEnablingCompletionHandler = nullptr;
|
||||
}
|
||||
|
||||
if (handler != nullptr)
|
||||
handler();
|
||||
}
|
||||
|
||||
void BaseRenderer::WakeUp()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_renderingEnablingMutex);
|
||||
m_wasNotified = true;
|
||||
m_renderingEnablingCondition.notify_one();
|
||||
}
|
||||
|
||||
bool BaseRenderer::CanReceiveMessages()
|
||||
{
|
||||
threads::IRoutine * routine = m_selfThread.GetRoutine();
|
||||
return routine != nullptr && !routine->IsCancelled();
|
||||
}
|
||||
} // namespace df
|
||||
Loading…
Add table
Add a link
Reference in a new issue