Merge pull request #4151 from darina/drape-engine-soft-recovering

Soft recovering of drape engine .
This commit is contained in:
ygorshenin 2016-08-26 17:14:18 +03:00 committed by GitHub
commit 9c2c2bc366
33 changed files with 502 additions and 244 deletions

View file

@ -63,6 +63,7 @@ enum MultiTouchAction
Framework::Framework()
: m_lastCompass(0.0)
, m_isContextDestroyed(false)
, m_currentMode(location::PendingPosition)
, m_isCurrentModeInitialized(false)
, m_isChoosePositionMode(false)
@ -124,7 +125,10 @@ bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi
m_contextFactory = make_unique_dp<dp::ThreadSafeFactory>(new AndroidOGLContextFactory(env, jSurface));
AndroidOGLContextFactory const * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
if (!factory->IsValid())
{
LOG(LWARNING, ("Invalid GL context."));
return false;
}
::Framework::DrapeCreationParams p;
p.m_surfaceWidth = factory->GetWidth();
@ -143,23 +147,9 @@ bool Framework::CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi
m_work.CreateDrapeEngine(make_ref(m_contextFactory), move(p));
m_work.EnterForeground();
// Execute drape tasks which set up custom state.
{
lock_guard<mutex> lock(m_drapeQueueMutex);
if (!m_drapeTasksQueue.empty())
ExecuteDrapeTasks();
}
return true;
}
void Framework::DeleteDrapeEngine()
{
m_work.EnterBackground();
m_work.DestroyDrapeEngine();
}
bool Framework::IsDrapeEngineCreated()
{
return m_work.IsDrapeEngineCreated();
@ -171,22 +161,50 @@ void Framework::Resize(int w, int h)
m_work.OnSize(w, h);
}
void Framework::DetachSurface()
void Framework::DetachSurface(bool destroyContext)
{
m_work.SetRenderingEnabled(false);
LOG(LINFO, ("Detach surface."));
if (destroyContext)
{
LOG(LINFO, ("Destroy context."));
m_isContextDestroyed = true;
m_work.EnterBackground();
}
m_work.SetRenderingDisabled(destroyContext);
ASSERT(m_contextFactory != nullptr, ());
AndroidOGLContextFactory * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
factory->ResetSurface();
}
void Framework::AttachSurface(JNIEnv * env, jobject jSurface)
bool Framework::AttachSurface(JNIEnv * env, jobject jSurface)
{
LOG(LINFO, ("Attach surface."));
ASSERT(m_contextFactory != nullptr, ());
AndroidOGLContextFactory * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
factory->SetSurface(env, jSurface);
m_work.SetRenderingEnabled(true);
if (!factory->IsValid())
{
LOG(LWARNING, ("Invalid GL context."));
return false;
}
ASSERT(!m_guiPositions.empty(), ("GUI elements must be set-up before engine is created"));
m_work.SetRenderingEnabled(factory);
if (m_isContextDestroyed)
{
LOG(LINFO, ("Recover GL resources, viewport size:", factory->GetWidth(), factory->GetHeight()));
m_work.UpdateDrapeEngine(factory->GetWidth(), factory->GetHeight());
m_isContextDestroyed = false;
m_work.EnterForeground();
}
return true;
}
void Framework::SetMapStyle(MapStyle mapStyle)
@ -437,23 +455,6 @@ void Framework::SetupMeasurementSystem()
m_work.SetupMeasurementSystem();
}
void Framework::PostDrapeTask(TDrapeTask && task)
{
ASSERT(task != nullptr, ());
lock_guard<mutex> lock(m_drapeQueueMutex);
if (IsDrapeEngineCreated())
task();
else
m_drapeTasksQueue.push_back(move(task));
}
void Framework::ExecuteDrapeTasks()
{
for (auto & task : m_drapeTasksQueue)
task();
m_drapeTasksQueue.clear();
}
void Framework::SetPlacePageInfo(place_page::Info const & info)
{
m_info = info;
@ -803,20 +804,15 @@ Java_com_mapswithme_maps_Framework_nativeBuildRoute(JNIEnv * env, jclass,
jdouble startLat, jdouble startLon,
jdouble finishLat, jdouble finishLon)
{
g_framework->PostDrapeTask([startLat, startLon, finishLat, finishLon]()
{
frm()->BuildRoute(MercatorBounds::FromLatLon(startLat, startLon),
MercatorBounds::FromLatLon(finishLat, finishLon), 0 /* timeoutSec */);
});
frm()->BuildRoute(MercatorBounds::FromLatLon(startLat, startLon),
MercatorBounds::FromLatLon(finishLat, finishLon), 0 /* timeoutSec */);
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_Framework_nativeFollowRoute(JNIEnv * env, jclass)
{
g_framework->PostDrapeTask([]()
{
frm()->FollowRoute();
});
frm()->FollowRoute();
}
JNIEXPORT void JNICALL
@ -1013,10 +1009,7 @@ Java_com_mapswithme_maps_Framework_nativeSet3dMode(JNIEnv * env, jclass, jboolea
bool const allow3dBuildings = static_cast<bool>(allowBuildings);
g_framework->Save3dMode(allow3d, allow3dBuildings);
g_framework->PostDrapeTask([allow3d, allow3dBuildings]()
{
g_framework->Set3dMode(allow3d, allow3dBuildings);
});
g_framework->Set3dMode(allow3d, allow3dBuildings);
}
JNIEXPORT void JNICALL
@ -1040,10 +1033,7 @@ Java_com_mapswithme_maps_Framework_nativeSetAutoZoomEnabled(JNIEnv * env, jclass
{
bool const autoZoomEnabled = static_cast<bool>(enabled);
frm()->SaveAutoZoom(autoZoomEnabled);
g_framework->PostDrapeTask([autoZoomEnabled]()
{
frm()->AllowAutoZoom(autoZoomEnabled);
});
frm()->AllowAutoZoom(autoZoomEnabled);
}
JNIEXPORT jboolean JNICALL

View file

@ -45,6 +45,8 @@ namespace android
string m_searchQuery;
bool m_isContextDestroyed;
map<gui::EWidget, gui::Position> m_guiPositions;
void MyPositionModeChanged(location::EMyPositionMode mode, bool routingActive);
@ -73,11 +75,10 @@ namespace android
void Invalidate();
bool CreateDrapeEngine(JNIEnv * env, jobject jSurface, int densityDpi, bool firstLaunch);
void DeleteDrapeEngine();
bool IsDrapeEngineCreated();
void DetachSurface();
void AttachSurface(JNIEnv * env, jobject jSurface);
void DetachSurface(bool destroyContext);
bool AttachSurface(JNIEnv * env, jobject jSurface);
void SetMapStyle(MapStyle mapStyle);
void MarkMapStyle(MapStyle mapStyle);
@ -151,10 +152,6 @@ namespace android
void ApplyWidgets();
void CleanWidgets();
using TDrapeTask = function<void()>;
// Posts a task which must be executed when Drape Engine is alive.
void PostDrapeTask(TDrapeTask && task);
void SetPlacePageInfo(place_page::Info const & info);
place_page::Info & GetPlacePageInfo();
void RequestBookingMinPrice(string const & hotelId, string const & currency, function<void(string const &, string const &)> const & callback);
@ -167,13 +164,6 @@ namespace android
bool IsAutoRetryDownloadFailed();
bool IsDownloadOn3gEnabled();
void EnableDownloadOn3g();
private:
vector<TDrapeTask> m_drapeTasksQueue;
mutex m_drapeQueueMutex;
// This method must be executed under mutex m_drapeQueueMutex.
void ExecuteDrapeTasks();
};
}

View file

@ -69,28 +69,22 @@ Java_com_mapswithme_maps_MapFragment_nativeCreateEngine(JNIEnv * env, jclass cla
return g_framework->CreateDrapeEngine(env, surface, density, firstLaunch);
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_MapFragment_nativeDestroyEngine(JNIEnv * env, jclass clazz)
{
g_framework->DeleteDrapeEngine();
}
JNIEXPORT jboolean JNICALL
Java_com_mapswithme_maps_MapFragment_nativeIsEngineCreated(JNIEnv * env, jclass clazz)
{
return g_framework->IsDrapeEngineCreated();
}
JNIEXPORT void JNICALL
JNIEXPORT jboolean JNICALL
Java_com_mapswithme_maps_MapFragment_nativeAttachSurface(JNIEnv * env, jclass clazz, jobject surface)
{
g_framework->AttachSurface(env, surface);
return g_framework->AttachSurface(env, surface);
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_MapFragment_nativeDetachSurface(JNIEnv * env, jclass clazz)
Java_com_mapswithme_maps_MapFragment_nativeDetachSurface(JNIEnv * env, jclass clazz, jboolean destroyContext)
{
g_framework->DetachSurface();
g_framework->DetachSurface(destroyContext);
}
JNIEXPORT void JNICALL

View file

@ -238,23 +238,21 @@ extern "C"
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_search_SearchEngine_nativeShowResult(JNIEnv * env, jclass clazz, jint index)
{
lock_guard<mutex> guard(g_resultsMutex);
Result const & result = g_results.GetResult(index);
g_framework->PostDrapeTask([result]()
{
g_framework->NativeFramework()->ShowSearchResult(result);
});
unique_lock<mutex> guard(g_resultsMutex);
Result const result = g_results.GetResult(index);
guard.unlock();
g_framework->NativeFramework()->ShowSearchResult(result);
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_search_SearchEngine_nativeShowAllResults(JNIEnv * env, jclass clazz)
{
lock_guard<mutex> guard(g_resultsMutex);
auto const & results = g_results;
g_framework->PostDrapeTask([results]()
Results results;
{
g_framework->NativeFramework()->ShowSearchResults(results);
});
lock_guard<mutex> guard(g_resultsMutex);
results = g_results;
}
g_framework->NativeFramework()->ShowSearchResults(results);
}
JNIEXPORT void JNICALL

View file

@ -37,10 +37,7 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkManager_nativeShowBookmarkOnMap(
JNIEnv * env, jobject thiz, jint c, jint b)
{
BookmarkAndCategory bnc = BookmarkAndCategory(c,b);
g_framework->PostDrapeTask([bnc]()
{
frm()->ShowBookmark(bnc);
});
frm()->ShowBookmark(bnc);
}
JNIEXPORT void JNICALL

View file

@ -52,7 +52,7 @@ public class MapFragment extends BaseMwmFragment
private int mHeight;
private int mWidth;
private boolean mRequireResize;
private boolean mEngineCreated;
private boolean mContextCreated;
private boolean mFirstStart;
private static boolean sWasCopyrightDisplayed;
@ -98,7 +98,7 @@ public class MapFragment extends BaseMwmFragment
UiUtils.dimen(R.dimen.margin_compass_left) + offsetX,
mHeight - UiUtils.dimen(R.dimen.margin_compass_bottom) + offsetY,
ANCHOR_CENTER);
if (forceRedraw && mEngineCreated)
if (forceRedraw && mContextCreated)
nativeApplyWidgets();
}
@ -108,7 +108,7 @@ public class MapFragment extends BaseMwmFragment
mWidth - UiUtils.dimen(R.dimen.margin_ruler_right) + offsetX,
mHeight - UiUtils.dimen(R.dimen.margin_ruler_bottom) + offsetY,
ANCHOR_RIGHT_BOTTOM);
if (forceRedraw && mEngineCreated)
if (forceRedraw && mContextCreated)
nativeApplyWidgets();
}
@ -140,7 +140,12 @@ public class MapFragment extends BaseMwmFragment
final Surface surface = surfaceHolder.getSurface();
if (nativeIsEngineCreated())
{
nativeAttachSurface(surface);
if (!nativeAttachSurface(surface))
{
reportUnsupported();
return;
}
mContextCreated = true;
mRequireResize = true;
return;
}
@ -154,20 +159,20 @@ public class MapFragment extends BaseMwmFragment
final float exactDensityDpi = metrics.densityDpi;
mFirstStart = ((MwmActivity) getMwmActivity()).isFirstStart();
mEngineCreated = nativeCreateEngine(surface, (int) exactDensityDpi, mFirstStart);
if (!mEngineCreated)
if (!nativeCreateEngine(surface, (int) exactDensityDpi, mFirstStart))
{
reportUnsupported();
return;
}
mContextCreated = true;
onRenderingInitialized();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height)
{
if (!mEngineCreated ||
if (!mContextCreated ||
(!mRequireResize && surfaceHolder.isCreating()))
return;
@ -181,22 +186,22 @@ public class MapFragment extends BaseMwmFragment
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder)
{
if (!mEngineCreated)
if (!mContextCreated)
return;
if (getActivity() == null || !getActivity().isChangingConfigurations())
destroyEngine();
destroyContext();
else
nativeDetachSurface();
nativeDetachSurface(false);
}
void destroyEngine()
void destroyContext()
{
if (!mEngineCreated)
if (!mContextCreated)
return;
nativeDestroyEngine();
mEngineCreated = false;
nativeDetachSurface(true);
mContextCreated = false;
}
@Override
@ -281,9 +286,8 @@ public class MapFragment extends BaseMwmFragment
static native boolean nativeShowMapForUrl(String url);
static native boolean nativeIsEngineCreated();
private static native boolean nativeCreateEngine(Surface surface, int density, boolean firstLaunch);
private static native void nativeDestroyEngine();
private static native void nativeAttachSurface(Surface surface);
private static native void nativeDetachSurface();
private static native boolean nativeAttachSurface(Surface surface);
private static native void nativeDetachSurface(boolean destroyContext);
private static native void nativeSurfaceChanged(int w, int h);
private static native void nativeOnTouch(int actionType, int id1, float x1, float y1, int id2, float x2, float y2, int maskedPointer);
private static native void nativeSetupWidget(int widget, float x, float y, int anchor);

View file

@ -751,8 +751,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public void recreate()
{
// Explicitly destroy engine before activity recreation.
mMapFragment.destroyEngine();
// Explicitly destroy context before activity recreation.
mMapFragment.destroyContext();
super.recreate();
}

View file

@ -176,6 +176,11 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
}
break;
}
case Message::MapShapesRecache:
{
RecacheMapShapes();
break;
}
case Message::MapShapeReaded:
{
ref_ptr<MapShapeReadedMessage> msg = message;
@ -314,21 +319,40 @@ void BackendRenderer::ReleaseResources()
m_readManager.reset();
m_batchersPool.reset();
m_routeBuilder.reset();
m_overlays.clear();
m_texMng->Release();
m_contextFactory->getResourcesUploadContext()->doneCurrent();
}
void BackendRenderer::OnContextCreate()
{
LOG(LINFO, ("On context create."));
m_contextFactory->waitForInitialization();
m_contextFactory->getResourcesUploadContext()->makeCurrent();
GLFunctions::Init();
InitGLDependentResource();
}
void BackendRenderer::OnContextDestroy()
{
LOG(LINFO, ("On context destroy."));
m_readManager->InvalidateAll();
m_batchersPool.reset();
m_texMng->Release();
m_overlays.clear();
m_contextFactory->getResourcesUploadContext()->doneCurrent();
}
BackendRenderer::Routine::Routine(BackendRenderer & renderer) : m_renderer(renderer) {}
void BackendRenderer::Routine::Do()
{
m_renderer.m_contextFactory->waitForInitialization();
m_renderer.m_contextFactory->getResourcesUploadContext()->makeCurrent();
GLFunctions::Init();
m_renderer.InitGLDependentResource();
LOG(LINFO, ("Start routine."));
m_renderer.OnContextCreate();
while (!IsCancelled())
{
@ -356,8 +380,6 @@ void BackendRenderer::InitGLDependentResource()
GetPlatform().GetFontNames(params.m_glyphMngParams.m_fonts);
m_texMng->Init(params);
RecacheMapShapes();
}
void BackendRenderer::RecacheMapShapes()

View file

@ -58,6 +58,9 @@ public:
protected:
unique_ptr<threads::IRoutine> CreateRoutine() override;
void OnContextCreate() override;
void OnContextDestroy() override;
private:
void RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool needResetOldGui);
void RecacheChoosePositionMark();

View file

@ -14,6 +14,7 @@ BaseRenderer::BaseRenderer(ThreadsCommutator::ThreadName name, Params const & pa
, m_isEnabled(true)
, m_renderingEnablingCompletionHandler(nullptr)
, m_wasNotified(false)
, m_wasContextReset(false)
{
m_commutator->RegisterThread(m_threadName, this);
}
@ -39,23 +40,18 @@ void BaseRenderer::StopThread()
m_selfThread.Join();
}
void BaseRenderer::SetRenderingEnabled(bool const isEnabled)
void BaseRenderer::SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory)
{
// here we have to wait for completion of internal SetRenderingEnabled
mutex completionMutex;
condition_variable completionCondition;
bool notified = false;
auto completionHandler = [&]()
{
lock_guard<mutex> lock(completionMutex);
notified = true;
completionCondition.notify_one();
};
if (m_wasContextReset && contextFactory != nullptr)
m_contextFactory = contextFactory;
SetRenderingEnabled(true);
}
SetRenderingEnabled(isEnabled, completionHandler);
unique_lock<mutex> lock(completionMutex);
completionCondition.wait(lock, [&notified] { return notified; });
void BaseRenderer::SetRenderingDisabled(bool const destroyContext)
{
if (destroyContext)
m_wasContextReset = true;
SetRenderingEnabled(false);
}
bool BaseRenderer::IsRenderingEnabled() const
@ -63,17 +59,22 @@ bool BaseRenderer::IsRenderingEnabled() const
return m_isEnabled;
}
void BaseRenderer::SetRenderingEnabled(bool const isEnabled, TCompletionHandler completionHandler)
void BaseRenderer::SetRenderingEnabled(bool const isEnabled)
{
if (isEnabled == m_isEnabled)
{
if (completionHandler != nullptr)
completionHandler();
return;
}
m_renderingEnablingCompletionHandler = move(completionHandler);
// here we have to wait for completion of internal SetRenderingEnabled
mutex completionMutex;
condition_variable completionCondition;
bool notified = false;
m_renderingEnablingCompletionHandler = [&]()
{
lock_guard<mutex> lock(completionMutex);
notified = true;
completionCondition.notify_one();
};
if (isEnabled)
{
// wake up rendering thread
@ -87,19 +88,36 @@ void BaseRenderer::SetRenderingEnabled(bool const isEnabled, TCompletionHandler
// if renderer thread is waiting for message let it go
CancelMessageWaiting();
}
unique_lock<mutex> lock(completionMutex);
completionCondition.wait(lock, [&notified] { return notified; });
}
bool BaseRenderer::FilterGLContextDependentMessage(ref_ptr<Message> msg)
{
return msg->IsGLContextDependent();
}
void BaseRenderer::CheckRenderingEnabled()
{
if (!m_isEnabled)
{
bool const isDrawContext = m_threadName == ThreadsCommutator::RenderThread;
dp::OGLContext * context = isDrawContext ? m_contextFactory->getDrawContext() :
m_contextFactory->getResourcesUploadContext();
dp::OGLContext * context = nullptr;
context->setRenderingEnabled(false);
if (m_wasContextReset)
{
EnableMessageFiltering(bind(&BaseRenderer::FilterGLContextDependentMessage, this, _1));
OnContextDestroy();
}
else
{
bool const isDrawContext = m_threadName == ThreadsCommutator::RenderThread;
context = isDrawContext ? m_contextFactory->getDrawContext() :
m_contextFactory->getResourcesUploadContext();
context->setRenderingEnabled(false);
}
// nofity initiator-thread about rendering disabling
// notify initiator-thread about rendering disabling
Notify();
// wait for signal
@ -110,9 +128,18 @@ void BaseRenderer::CheckRenderingEnabled()
m_wasNotified = false;
m_isEnabled = true;
context->setRenderingEnabled(true);
if (m_wasContextReset)
{
m_wasContextReset = false;
DisableMessageFiltering();
OnContextCreate();
}
else
{
context->setRenderingEnabled(true);
}
// nofity initiator-thread about rendering enabling
// notify initiator-thread about rendering enabling
// m_renderingEnablingCompletionHandler will be setup before awakening of this thread
Notify();
}

View file

@ -40,7 +40,9 @@ public:
bool CanReceiveMessages();
void SetRenderingEnabled(bool const isEnabled);
void SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory);
void SetRenderingDisabled(bool const destroyContext);
bool IsRenderingEnabled() const;
protected:
@ -55,6 +57,9 @@ protected:
virtual unique_ptr<threads::IRoutine> CreateRoutine() = 0;
virtual void OnContextCreate() = 0;
virtual void OnContextDestroy() = 0;
private:
using TCompletionHandler = function<void()>;
@ -66,8 +71,10 @@ private:
atomic<bool> m_isEnabled;
TCompletionHandler m_renderingEnablingCompletionHandler;
bool m_wasNotified;
atomic<bool> m_wasContextReset;
void SetRenderingEnabled(bool const isEnabled, TCompletionHandler completionHandler);
bool FilterGLContextDependentMessage(ref_ptr<Message> msg);
void SetRenderingEnabled(bool const isEnabled);
void Notify();
void WakeUp();
};

View file

@ -68,6 +68,7 @@ DrapeEngine::DrapeEngine(Params && params)
m_widgetsInfo = move(params.m_info);
RecacheGui(false);
RecacheMapShapes();
if (params.m_showChoosePositionMark)
EnableChoosePositionMode(true, move(params.m_boundAreaTriangles), false, m2::PointD());
@ -92,6 +93,23 @@ DrapeEngine::~DrapeEngine()
m_textureManager->Release();
}
void DrapeEngine::Update(int w, int h)
{
RecacheGui(false);
RecacheMapShapes();
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<RecoverGLResourcesMessage>(),
MessagePriority::High);
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<GuiLayerLayoutMessage>(m_widgetsLayout),
MessagePriority::Normal);
ResizeImpl(w, h);
}
void DrapeEngine::Resize(int w, int h)
{
if (m_viewport.GetHeight() != h || m_viewport.GetWidth() != w)
@ -151,12 +169,20 @@ void DrapeEngine::UpdateUserMarksLayer(TileKey const & tileKey, UserMarksProvide
MessagePriority::Normal);
}
void DrapeEngine::SetRenderingEnabled(bool const isEnabled)
void DrapeEngine::SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory)
{
m_frontend->SetRenderingEnabled(isEnabled);
m_backend->SetRenderingEnabled(isEnabled);
m_backend->SetRenderingEnabled(contextFactory);
m_frontend->SetRenderingEnabled(contextFactory);
LOG(LDEBUG, (isEnabled ? "Rendering enabled" : "Rendering disabled"));
LOG(LDEBUG, ("Rendering enabled"));
}
void DrapeEngine::SetRenderingDisabled(bool const destroyContext)
{
m_frontend->SetRenderingDisabled(destroyContext);
m_backend->SetRenderingDisabled(destroyContext);
LOG(LDEBUG, ("Rendering disabled"));
}
void DrapeEngine::InvalidateRect(m2::RectD const & rect)
@ -187,6 +213,13 @@ void DrapeEngine::UpdateMapStyle()
}
}
void DrapeEngine::RecacheMapShapes()
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<MapShapesRecacheMessage>(),
MessagePriority::Normal);
}
void DrapeEngine::RecacheGui(bool needResetOldGui)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,

View file

@ -84,6 +84,8 @@ public:
DrapeEngine(Params && params);
~DrapeEngine();
void Update(int w, int h);
void Resize(int w, int h);
void Invalidate();
@ -102,7 +104,8 @@ public:
void ChangeVisibilityUserMarksLayer(TileKey const & tileKey, bool isVisible);
void UpdateUserMarksLayer(TileKey const & tileKey, UserMarksProvider * provider);
void SetRenderingEnabled(bool const isEnabled);
void SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory = nullptr);
void SetRenderingDisabled(bool const destroyContext);
void InvalidateRect(m2::RectD const & rect);
void UpdateMapStyle();
@ -166,6 +169,7 @@ private:
void ResizeImpl(int w, int h);
void RecacheGui(bool needResetOldGui);
void RecacheMapShapes();
private:
drape_ptr<FrontendRenderer> m_frontend;

View file

@ -129,6 +129,7 @@ FrontendRenderer::FrontendRenderer(Params const & params)
, m_userPositionChangedFn(params.m_positionChangedFn)
, m_requestedTiles(params.m_requestedTiles)
, m_maxGeneration(0)
, m_needRestoreSize(false)
{
#ifdef DRAW_INFO
m_tpf = 0.0;
@ -548,6 +549,12 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
case Message::RecoverGLResources:
{
UpdateGLResources();
break;
}
case Message::UpdateMapStyle:
{
// Clear all graphics.
@ -575,46 +582,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
blocker.Wait();
}
// Invalidate route.
if (m_routeRenderer->GetStartPoint())
{
m2::PointD const & position = m_routeRenderer->GetStartPoint()->m_position;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<CacheRouteSignMessage>(position, true /* isStart */,
true /* isValid */),
MessagePriority::High);
}
if (m_routeRenderer->GetFinishPoint())
{
m2::PointD const & position = m_routeRenderer->GetFinishPoint()->m_position;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<CacheRouteSignMessage>(position, false /* isStart */,
true /* isValid */),
MessagePriority::High);
}
auto const & routeData = m_routeRenderer->GetRouteData();
if (routeData != nullptr)
{
auto recacheRouteMsg = make_unique_dp<AddRouteMessage>(routeData->m_sourcePolyline,
routeData->m_sourceTurns,
routeData->m_color,
routeData->m_pattern);
m_routeRenderer->Clear(true /* keepDistanceFromBegin */);
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, move(recacheRouteMsg),
MessagePriority::Normal);
}
// Request new tiles.
ScreenBase screen = m_userEventStream.GetCurrentScreen();
m_lastReadedModelView = screen;
m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), ResolveTileKeys(screen));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<UpdateReadManagerMessage>(),
MessagePriority::UberHighSingleton);
m_gpsTrackRenderer->Update();
UpdateGLResources();
break;
}
@ -752,6 +720,50 @@ unique_ptr<threads::IRoutine> FrontendRenderer::CreateRoutine()
return make_unique<Routine>(*this);
}
void FrontendRenderer::UpdateGLResources()
{
// Invalidate route.
if (m_routeRenderer->GetStartPoint())
{
m2::PointD const & position = m_routeRenderer->GetStartPoint()->m_position;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<CacheRouteSignMessage>(position, true /* isStart */,
true /* isValid */),
MessagePriority::High);
}
if (m_routeRenderer->GetFinishPoint())
{
m2::PointD const & position = m_routeRenderer->GetFinishPoint()->m_position;
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<CacheRouteSignMessage>(position, false /* isStart */,
true /* isValid */),
MessagePriority::High);
}
auto const & routeData = m_routeRenderer->GetRouteData();
if (routeData != nullptr)
{
auto recacheRouteMsg = make_unique_dp<AddRouteMessage>(routeData->m_sourcePolyline,
routeData->m_sourceTurns,
routeData->m_color,
routeData->m_pattern);
m_routeRenderer->Clear(true /* keepDistanceFromBegin */);
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, move(recacheRouteMsg),
MessagePriority::Normal);
}
// Request new tiles.
ScreenBase screen = m_userEventStream.GetCurrentScreen();
m_lastReadedModelView = screen;
m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), ResolveTileKeys(screen));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<UpdateReadManagerMessage>(),
MessagePriority::UberHighSingleton);
m_gpsTrackRenderer->Update();
}
void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom)
{
@ -819,8 +831,13 @@ void FrontendRenderer::OnResize(ScreenBase const & screen)
{
m_myPositionController->OnNewViewportRect();
m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY());
}
if (viewportChanged || m_needRestoreSize)
{
m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY());
m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
m_needRestoreSize = false;
}
RefreshProjection(screen);
@ -1451,24 +1468,49 @@ TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen)
return tiles;
}
FrontendRenderer::Routine::Routine(FrontendRenderer & renderer) : m_renderer(renderer) {}
void FrontendRenderer::Routine::Do()
void FrontendRenderer::OnContextDestroy()
{
m_renderer.m_contextFactory->waitForInitialization();
LOG(LINFO, ("On context destroy."));
gui::DrapeGui::Instance().ConnectOnCompassTappedHandler(bind(&FrontendRenderer::OnCompassTapped, &m_renderer));
m_renderer.m_myPositionController->SetListener(ref_ptr<MyPositionController::Listener>(&m_renderer));
m_renderer.m_userEventStream.SetListener(ref_ptr<UserEventStream::Listener>(&m_renderer));
// Clear all graphics.
for (RenderLayer & layer : m_layers)
{
layer.m_renderGroups.clear();
layer.m_isDirty = false;
}
dp::OGLContext * context = m_renderer.m_contextFactory->getDrawContext();
m_userMarkRenderGroups.clear();
m_guiRenderer.reset();
m_selectionShape.release();
m_framebuffer.reset();
m_transparentLayer.reset();
m_myPositionController->ResetRenderShape();
m_routeRenderer->ClearGLDependentResources();
m_gpsTrackRenderer->ClearRenderData();
#ifdef RENDER_DEBUG_RECTS
dp::DebugRectRenderer::Instance().Destroy();
#endif
m_gpuProgramManager.reset();
m_contextFactory->getDrawContext()->doneCurrent();
m_needRestoreSize = true;
}
void FrontendRenderer::OnContextCreate()
{
LOG(LINFO, ("On context create."));
m_contextFactory->waitForInitialization();
dp::OGLContext * context = m_contextFactory->getDrawContext();
context->makeCurrent();
m_renderer.m_framebuffer->SetDefaultContext(context);
GLFunctions::Init();
GLFunctions::AttachCache(this_thread::get_id());
dp::SupportManager::Instance().Init();
GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1);
GLFunctions::glEnable(gl_const::GLDepthTest);
@ -1481,7 +1523,10 @@ void FrontendRenderer::Routine::Do()
GLFunctions::glEnable(gl_const::GLCullFace);
GLFunctions::glEnable(gl_const::GLScissorTest);
m_renderer.m_gpuProgramManager->Init();
dp::SupportManager::Instance().Init();
m_gpuProgramManager = make_unique_dp<dp::GpuProgramManager>();
m_gpuProgramManager->Init();
dp::BlendingParams blendingParams;
blendingParams.Apply();
@ -1490,6 +1535,25 @@ void FrontendRenderer::Routine::Do()
dp::DebugRectRenderer::Instance().Init(make_ref(m_renderer.m_gpuProgramManager));
#endif
// resources recovering
m_framebuffer.reset(new Framebuffer());
m_framebuffer->SetDefaultContext(context);
m_transparentLayer.reset(new TransparentLayer());
}
FrontendRenderer::Routine::Routine(FrontendRenderer & renderer) : m_renderer(renderer) {}
void FrontendRenderer::Routine::Do()
{
LOG(LINFO, ("Start routine."));
gui::DrapeGui::Instance().ConnectOnCompassTappedHandler(bind(&FrontendRenderer::OnCompassTapped, &m_renderer));
m_renderer.m_myPositionController->SetListener(ref_ptr<MyPositionController::Listener>(&m_renderer));
m_renderer.m_userEventStream.SetListener(ref_ptr<UserEventStream::Listener>(&m_renderer));
m_renderer.OnContextCreate();
double const kMaxInactiveSeconds = 2.0;
my::Timer timer;
@ -1499,6 +1563,8 @@ void FrontendRenderer::Routine::Do()
bool modelViewChanged = true;
bool viewportChanged = true;
dp::OGLContext * context = m_renderer.m_contextFactory->getDrawContext();
while (!IsCancelled())
{
ScreenBase modelView = m_renderer.ProcessEvents(modelViewChanged, viewportChanged);

View file

@ -151,6 +151,8 @@ public:
protected:
void AcceptMessage(ref_ptr<Message> message) override;
unique_ptr<threads::IRoutine> CreateRoutine() override;
void OnContextCreate() override;
void OnContextDestroy() override;
private:
void OnResize(ScreenBase const & screen);
@ -213,6 +215,7 @@ private:
};
void ReleaseResources();
void UpdateGLResources();
void BeginUpdateOverlayTree(ScreenBase const & modelView);
void UpdateOverlayTree(ScreenBase const & modelView, drape_ptr<RenderGroup> & renderGroup);
@ -325,6 +328,8 @@ private:
drape_ptr<SelectObjectMessage> m_selectObjectMessage;
bool m_needRestoreSize;
#ifdef DEBUG
bool m_isTeardowned;
#endif

View file

@ -90,6 +90,12 @@ void GpsTrackRenderer::AddRenderData(ref_ptr<dp::GpuProgramManager> mng,
m_waitForRenderData = false;
}
void GpsTrackRenderer::ClearRenderData()
{
m_renderData.clear();
m_waitForRenderData = false;
}
void GpsTrackRenderer::UpdatePoints(vector<GpsTrackPoint> const & toAdd, vector<uint32_t> const & toRemove)
{
bool wasChanged = false;

View file

@ -34,6 +34,7 @@ public:
void Update();
void Clear();
void ClearRenderData();
private:
float CalculateRadius(ScreenBase const & screen) const;

View file

@ -74,6 +74,7 @@ public:
{}
Type GetType() const override { return Message::MapShapeReaded; }
bool IsGLContextDependent() const override { return true; }
TMapShapes const & GetShapes() { return m_shapes; }
private:

View file

@ -26,6 +26,7 @@ public:
GuiLayerRecached,
GuiRecache,
GuiLayerLayout,
MapShapesRecache,
MapShapes,
ChangeMyPostitionMode,
CompassInfo,
@ -60,11 +61,13 @@ public:
SetAddNewPlaceMode,
SetDisplacementMode,
AllowAutoZoom,
RequestSymbolsSize
RequestSymbolsSize,
RecoverGLResources
};
virtual ~Message() {}
virtual Type GetType() const { return Unknown; }
virtual bool IsGLContextDependent() const { return false; }
};
enum class MessagePriority

View file

@ -23,8 +23,24 @@ bool MessageAcceptor::ProcessSingleMessage(bool waitForMessage)
return true;
}
void MessageAcceptor::EnableMessageFiltering(TFilterMessageFn needFilterMessageFn)
{
ASSERT(needFilterMessageFn != nullptr, ());
m_needFilterMessageFn = needFilterMessageFn;
m_messageQueue.FilterMessages(needFilterMessageFn);
}
void MessageAcceptor::DisableMessageFiltering()
{
m_needFilterMessageFn = nullptr;
}
void MessageAcceptor::PostMessage(drape_ptr<Message> && message, MessagePriority priority)
{
if (m_needFilterMessageFn != nullptr && m_needFilterMessageFn(make_ref(message)))
return;
m_messageQueue.PushMessage(move(message), priority);
}

View file

@ -33,6 +33,10 @@ protected:
size_t GetQueueSize() const;
#endif
using TFilterMessageFn = function<bool (ref_ptr<Message>)>;
void EnableMessageFiltering(TFilterMessageFn needFilterMessageFn);
void DisableMessageFiltering();
private:
friend class ThreadsCommutator;
@ -40,6 +44,7 @@ private:
MessageQueue m_messageQueue;
atomic<bool> m_infinityWaiting;
TFilterMessageFn m_needFilterMessageFn;
};
} // namespace df

View file

@ -80,6 +80,20 @@ void MessageQueue::PushMessage(drape_ptr<Message> && message, MessagePriority pr
CancelWaitImpl();
}
void MessageQueue::FilterMessages(TFilterMessageFn needFilterMessageFn)
{
ASSERT(needFilterMessageFn != nullptr, ());
lock_guard<mutex> lock(m_mutex);
for (auto it = m_messages.begin(); it != m_messages.end(); )
{
if (needFilterMessageFn(make_ref(it->first)))
it = m_messages.erase(it);
else
++it;
}
}
#ifdef DEBUG_MESSAGE_QUEUE
bool MessageQueue::IsEmpty() const

View file

@ -27,6 +27,9 @@ public:
void CancelWait();
void ClearQuery();
using TFilterMessageFn = function<bool(ref_ptr<Message>)>;
void FilterMessages(TFilterMessageFn needFilterMessageFn);
#ifdef DEBUG_MESSAGE_QUEUE
bool IsEmpty() const;
size_t GetSize() const;

View file

@ -121,6 +121,7 @@ public:
{}
Type GetType() const override { return Message::FlushTile; }
bool IsGLContextDependent() const override { return true; }
dp::GLState const & GetState() const { return m_state; }
drape_ptr<dp::RenderBucket> && AcceptBuffer() { return move(m_buffer); }
@ -136,6 +137,8 @@ public:
FlushOverlaysMessage(TOverlaysRenderData && data) : m_data(move(data)) {}
Type GetType() const override { return Message::FlushOverlays; }
bool IsGLContextDependent() const override { return true; }
TOverlaysRenderData && AcceptRenderData() { return move(m_data); }
private:
@ -265,6 +268,7 @@ public:
{}
Type GetType() const override { return Message::GuiLayerRecached; }
bool IsGLContextDependent() const override { return true; }
drape_ptr<gui::LayerRenderer> && AcceptRenderer() { return move(m_renderer); }
bool NeedResetOldGui() const { return m_needResetOldGui; }
@ -292,6 +296,14 @@ private:
bool const m_needResetOldGui;
};
class MapShapesRecacheMessage : public Message
{
public:
MapShapesRecacheMessage() = default;
Type GetType() const override { return Message::MapShapesRecache; }
};
class GuiLayerLayoutMessage : public Message
{
public:
@ -380,6 +392,7 @@ public:
{}
Type GetType() const override { return Message::MapShapes; }
bool IsGLContextDependent() const override { return true; }
drape_ptr<MyPosition> && AcceptShape() { return move(m_shape); }
drape_ptr<SelectionShape> AcceptSelection() { return move(m_selection); }
@ -630,6 +643,8 @@ public:
{}
Type GetType() const override { return Message::FlushRoute; }
bool IsGLContextDependent() const override { return true; }
drape_ptr<RouteData> && AcceptRouteData() { return move(m_routeData); }
private:
@ -658,6 +673,8 @@ public:
{}
Type GetType() const override { return Message::FlushRouteSign; }
bool IsGLContextDependent() const override { return true; }
drape_ptr<RouteSignData> && AcceptRouteSignData() { return move(m_routeSignData); }
private:
@ -712,6 +729,14 @@ public:
Type GetType() const override { return Message::Invalidate; }
};
class RecoverGLResourcesMessage : public Message
{
public:
RecoverGLResourcesMessage(){}
Type GetType() const override { return Message::RecoverGLResources; }
};
class DeactivateRouteFollowingMessage : public Message
{
public:
@ -792,6 +817,8 @@ public:
{}
Type GetType() const override { return Message::FlushGpsTrackPoints; }
bool IsGLContextDependent() const override { return true; }
drape_ptr<GpsTrackRenderData> && AcceptRenderData() { return move(m_renderData); }
private:

View file

@ -285,6 +285,11 @@ void MyPositionController::SetRenderShape(drape_ptr<MyPosition> && shape)
m_shape = move(shape);
}
void MyPositionController::ResetRenderShape()
{
m_shape.reset();
}
void MyPositionController::NextMode(ScreenBase const & screen)
{
string const kAlohalyticsClickEvent = "$onClick";

View file

@ -69,6 +69,7 @@ public:
void CorrectGlobalScalePoint(m2::PointD & pt) const;
void SetRenderShape(drape_ptr<MyPosition> && shape);
void ResetRenderShape();
void ActivateRouting(int zoomLevel, bool enableAutoZoom);
void DeactivateRouting();

View file

@ -229,7 +229,7 @@ void RouteRenderer::UpdateRoute(ScreenBase const & screen, TCacheRouteArrowsCall
void RouteRenderer::RenderRoute(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
dp::UniformValuesStorage const & commonUniforms)
{
if (!m_routeData)
if (!m_routeData || m_invalidGLResources)
return;
// Render route.
@ -284,6 +284,9 @@ void RouteRenderer::RenderRoute(ScreenBase const & screen, ref_ptr<dp::GpuProgra
void RouteRenderer::RenderRouteSigns(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
dp::UniformValuesStorage const & commonUniforms)
{
if (m_invalidGLResources)
return;
if (m_startRouteSign)
{
ASSERT(m_startRouteSign->m_isValid, ());
@ -301,6 +304,9 @@ void RouteRenderer::RenderRouteSign(drape_ptr<RouteSignData> const & sign, Scree
ref_ptr<dp::GpuProgramManager> mng,
dp::UniformValuesStorage const & commonUniforms)
{
if (m_invalidGLResources)
return;
dp::GLState const & state = sign->m_sign.m_state;
dp::UniformValuesStorage uniforms = commonUniforms;
@ -322,6 +328,8 @@ void RouteRenderer::RenderRouteSign(drape_ptr<RouteSignData> const & sign, Scree
void RouteRenderer::SetRouteData(drape_ptr<RouteData> && routeData, ref_ptr<dp::GpuProgramManager> mng)
{
m_invalidGLResources = false;
m_routeData = move(routeData);
m_arrowBorders.clear();
@ -331,6 +339,8 @@ void RouteRenderer::SetRouteData(drape_ptr<RouteData> && routeData, ref_ptr<dp::
void RouteRenderer::SetRouteSign(drape_ptr<RouteSignData> && routeSignData, ref_ptr<dp::GpuProgramManager> mng)
{
m_invalidGLResources = false;
if (routeSignData->m_isStart)
{
if (!routeSignData->m_isValid)
@ -373,6 +383,8 @@ drape_ptr<RouteData> const & RouteRenderer::GetRouteData() const
void RouteRenderer::SetRouteArrows(drape_ptr<RouteArrowsData> && routeArrowsData,
ref_ptr<dp::GpuProgramManager> mng)
{
m_invalidGLResources = false;
m_routeArrows = move(routeArrowsData);
BuildBuckets(m_routeArrows->m_arrows, mng);
}
@ -389,6 +401,19 @@ void RouteRenderer::Clear(bool keepDistanceFromBegin)
m_distanceFromBegin = 0.0;
}
void RouteRenderer::ClearGLDependentResources()
{
m_invalidGLResources = true;
if (m_routeData != nullptr)
m_routeData->m_route.m_buckets.clear();
if (m_startRouteSign != nullptr)
m_startRouteSign->m_sign.m_buckets.clear();
if (m_finishRouteSign != nullptr)
m_finishRouteSign->m_sign.m_buckets.clear();
m_routeArrows.reset();
}
void RouteRenderer::UpdateDistanceFromBegin(double distanceFromBegin)
{
m_distanceFromBegin = distanceFromBegin;

View file

@ -35,6 +35,7 @@ public:
void SetRouteArrows(drape_ptr<RouteArrowsData> && routeArrowsData, ref_ptr<dp::GpuProgramManager> mng);
void Clear(bool keepDistanceFromBegin = false);
void ClearGLDependentResources();
void UpdateDistanceFromBegin(double distanceFromBegin);
@ -54,6 +55,8 @@ private:
float m_currentHalfWidth = 0.0f;
float m_currentAlpha = 0.0f;
bool m_invalidGLResources = false;
};
} // namespace df

View file

@ -160,7 +160,9 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
m2::RectD const prevPixelRect = GetCurrentScreen().PixelRect();
viewportChanged = false;
m_modelViewChanged = !events.empty() || m_state == STATE_SCALE || m_state == STATE_DRAG;
for (auto const & e : events)
{
bool breakAnim = false;
@ -178,6 +180,7 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
{
ref_ptr<ResizeEvent> resizeEvent = make_ref(e);
m_navigator.OnSize(resizeEvent->GetWidth(), resizeEvent->GetHeight());
viewportChanged = true;
breakAnim = true;
TouchCancel(m_touches);
if (m_state == STATE_DOUBLE_TAP_HOLD)
@ -258,7 +261,7 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool
modelViewChanged = m_modelViewChanged;
double const kEps = 1e-5;
viewportChanged = !m2::IsEqualSize(prevPixelRect, GetCurrentScreen().PixelRect(), kEps, kEps);
viewportChanged |= !m2::IsEqualSize(prevPixelRect, GetCurrentScreen().PixelRect(), kEps, kEps);
m_modelViewChanged = false;
return m_navigator.Screen();

View file

@ -156,7 +156,7 @@ public:
m2::PointD PtoP3d(m2::PointD const & pt) const;
m2::PointD PtoP3d(m2::PointD const & pt, double ptZ) const;
m2::RectD PixelRectIn3d() const
m2::RectD const & PixelRectIn3d() const
{
return m_ViewportRect;
}

View file

@ -633,7 +633,7 @@ using namespace osm_auth_ios;
[self.mapViewController onGetFocus:NO];
[self.mapViewController.appWallAd close];
[MWMRouterSavedState store];
GetFramework().SetRenderingEnabled(false);
GetFramework().SetRenderingDisabled(false);
[MWMLocationManager applicationWillResignActive];
}
@ -667,7 +667,7 @@ using namespace osm_auth_ios;
[self.mapViewController onGetFocus:YES];
[self handleURLs];
[[Statistics instance] applicationDidBecomeActive];
GetFramework().SetRenderingEnabled(true);
GetFramework().SetRenderingEnabled();
[MWMLocationManager applicationDidBecomeActive];
[MWMRouterSavedState restore];
}

View file

@ -191,9 +191,6 @@ void Framework::OnLocationUpdate(GpsInfo const & info)
GpsInfo rInfo(info);
#endif
#ifdef OMIM_OS_ANDROID
m_lastGPSInfo.reset(new GpsInfo(rInfo));
#endif
location::RouteMatchingInfo routeMatchingInfo;
CheckLocationForRouting(rInfo);
@ -212,9 +209,6 @@ void Framework::OnCompassUpdate(CompassInfo const & info)
CompassInfo const & rInfo = info;
#endif
#ifdef OMIM_OS_ANDROID
m_lastCompassInfo.reset(new CompassInfo(rInfo));
#endif
CallDrapeFunction(bind(&df::DrapeEngine::SetCompassInfo, _1, rInfo));
}
@ -292,7 +286,7 @@ void Framework::Migrate(bool keepDownloaded)
// If we do not suspend drape, it tries to access framework fields (i.e. m_infoGetter) which are null
// while migration is performed.
if (m_drapeEngine && m_isRenderingEnabled)
m_drapeEngine->SetRenderingEnabled(false);
m_drapeEngine->SetRenderingDisabled(true);
m_selectedFeature = FeatureID();
m_searchEngine.reset();
m_infoGetter.reset();
@ -305,7 +299,11 @@ void Framework::Migrate(bool keepDownloaded)
InitSearchEngine();
RegisterAllMaps();
if (m_drapeEngine && m_isRenderingEnabled)
m_drapeEngine->SetRenderingEnabled(true);
{
m_drapeEngine->SetRenderingEnabled();
UpdateDrapeEngine(m_currentModelView.PixelRectIn3d().SizeX(),
m_currentModelView.PixelRectIn3d().SizeY());
}
InvalidateRect(MercatorBounds::FullRect());
}
@ -1562,15 +1560,6 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> contextFactory,
InvalidateUserMarks();
#ifdef OMIM_OS_ANDROID
// In case of the engine reinitialization recover compass and location data
// for correct my position state.
if (m_lastCompassInfo != nullptr)
OnCompassUpdate(*m_lastCompassInfo.release());
if (m_lastGPSInfo != nullptr)
OnLocationUpdate(*m_lastGPSInfo.release());
#endif
Allow3dMode(allow3d, allow3dBuildings);
LoadViewport();
@ -1585,19 +1574,28 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> contextFactory,
if (m_connectToGpsTrack)
GpsTracker::Instance().Connect(bind(&Framework::OnUpdateGpsTrackPointsCallback, this, _1, _2));
// In case of the engine reinitialization simulate the last tap to show selection mark.
if (m_lastTapEvent)
{
place_page::Info info;
ActivateMapSelection(false, OnTapEventImpl(*m_lastTapEvent, info), info);
}
m_drapeEngine->RequestSymbolsSize(kSearchMarks, [this](vector<m2::PointU> const & sizes)
{
GetPlatform().RunOnGuiThread([this, sizes](){ m_searchMarksSizes = sizes; });
});
}
void Framework::UpdateDrapeEngine(int width, int height)
{
if (m_drapeEngine)
{
m_drapeEngine->Update(width, height);
InvalidateUserMarks();
if (m_lastTapEvent)
{
place_page::Info info;
ActivateMapSelection(false, OnTapEventImpl(*m_lastTapEvent, info), info);
}
}
}
ref_ptr<df::DrapeEngine> Framework::GetDrapeEngine()
{
return make_ref(m_drapeEngine);
@ -1609,11 +1607,18 @@ void Framework::DestroyDrapeEngine()
m_drapeEngine.reset();
}
void Framework::SetRenderingEnabled(bool enable)
void Framework::SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory)
{
m_isRenderingEnabled = enable;
m_isRenderingEnabled = true;
if (m_drapeEngine)
m_drapeEngine->SetRenderingEnabled(enable);
m_drapeEngine->SetRenderingEnabled(contextFactory);
}
void Framework::SetRenderingDisabled(bool destroyContext)
{
m_isRenderingEnabled = false;
if (m_drapeEngine)
m_drapeEngine->SetRenderingDisabled(destroyContext);
}
void Framework::ConnectToGpsTracker()

View file

@ -333,10 +333,6 @@ public:
private:
unique_ptr<df::TapInfo> m_lastTapEvent;
#ifdef OMIM_OS_ANDROID
unique_ptr<location::CompassInfo> m_lastCompassInfo;
unique_ptr<location::GpsInfo> m_lastGPSInfo;
#endif
void OnTapEvent(df::TapInfo const & tapInfo);
/// outInfo is valid only if return value is not df::SelectionShape::OBJECT_EMPTY.
@ -394,7 +390,11 @@ public:
bool IsDrapeEngineCreated() const { return m_drapeEngine != nullptr; }
void DestroyDrapeEngine();
/// Called when graphics engine should be temporarily paused and then resumed.
void SetRenderingEnabled(bool enable);
void SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory = nullptr);
void SetRenderingDisabled(bool destroyContext);
void UpdateDrapeEngine(int width, int height);
private:
/// Depends on initialized Drape engine.
void SaveViewport();