diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 5ca65fb13c..c16ec1d5ca 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -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(new AndroidOGLContextFactory(env, jSurface)); AndroidOGLContextFactory const * factory = m_contextFactory->CastFactory(); 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 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(); 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(); 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 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(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(enabled); frm()->SaveAutoZoom(autoZoomEnabled); - g_framework->PostDrapeTask([autoZoomEnabled]() - { - frm()->AllowAutoZoom(autoZoomEnabled); - }); + frm()->AllowAutoZoom(autoZoomEnabled); } JNIEXPORT jboolean JNICALL diff --git a/android/jni/com/mapswithme/maps/Framework.hpp b/android/jni/com/mapswithme/maps/Framework.hpp index a832382ba4..2937dbb7bc 100644 --- a/android/jni/com/mapswithme/maps/Framework.hpp +++ b/android/jni/com/mapswithme/maps/Framework.hpp @@ -45,6 +45,8 @@ namespace android string m_searchQuery; + bool m_isContextDestroyed; + map 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; - // 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 const & callback); @@ -167,13 +164,6 @@ namespace android bool IsAutoRetryDownloadFailed(); bool IsDownloadOn3gEnabled(); void EnableDownloadOn3g(); - - private: - vector m_drapeTasksQueue; - mutex m_drapeQueueMutex; - - // This method must be executed under mutex m_drapeQueueMutex. - void ExecuteDrapeTasks(); }; } diff --git a/android/jni/com/mapswithme/maps/MapFragment.cpp b/android/jni/com/mapswithme/maps/MapFragment.cpp index 54c057c639..b06ff33247 100644 --- a/android/jni/com/mapswithme/maps/MapFragment.cpp +++ b/android/jni/com/mapswithme/maps/MapFragment.cpp @@ -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 diff --git a/android/jni/com/mapswithme/maps/SearchEngine.cpp b/android/jni/com/mapswithme/maps/SearchEngine.cpp index 0c04e4e2bb..a96bf29375 100644 --- a/android/jni/com/mapswithme/maps/SearchEngine.cpp +++ b/android/jni/com/mapswithme/maps/SearchEngine.cpp @@ -238,23 +238,21 @@ extern "C" JNIEXPORT void JNICALL Java_com_mapswithme_maps_search_SearchEngine_nativeShowResult(JNIEnv * env, jclass clazz, jint index) { - lock_guard guard(g_resultsMutex); - Result const & result = g_results.GetResult(index); - g_framework->PostDrapeTask([result]() - { - g_framework->NativeFramework()->ShowSearchResult(result); - }); + unique_lock 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 guard(g_resultsMutex); - auto const & results = g_results; - g_framework->PostDrapeTask([results]() + Results results; { - g_framework->NativeFramework()->ShowSearchResults(results); - }); + lock_guard guard(g_resultsMutex); + results = g_results; + } + g_framework->NativeFramework()->ShowSearchResults(results); } JNIEXPORT void JNICALL diff --git a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp index ec87921647..a31f86cae2 100644 --- a/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp +++ b/android/jni/com/mapswithme/maps/bookmarks/data/BookmarkManager.cpp @@ -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 diff --git a/android/src/com/mapswithme/maps/MapFragment.java b/android/src/com/mapswithme/maps/MapFragment.java index 2e55d28230..778d625189 100644 --- a/android/src/com/mapswithme/maps/MapFragment.java +++ b/android/src/com/mapswithme/maps/MapFragment.java @@ -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); diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index 19cdd0c125..84489a0994 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -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(); } diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index d7a7af41f5..b26819750b 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -176,6 +176,11 @@ void BackendRenderer::AcceptMessage(ref_ptr message) } break; } + case Message::MapShapesRecache: + { + RecacheMapShapes(); + break; + } case Message::MapShapeReaded: { ref_ptr 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() diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 8222f674a7..ca34b14e4a 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -58,6 +58,9 @@ public: protected: unique_ptr CreateRoutine() override; + void OnContextCreate() override; + void OnContextDestroy() override; + private: void RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool needResetOldGui); void RecacheChoosePositionMark(); diff --git a/drape_frontend/base_renderer.cpp b/drape_frontend/base_renderer.cpp index 8cc083b2ca..265d28ed96 100644 --- a/drape_frontend/base_renderer.cpp +++ b/drape_frontend/base_renderer.cpp @@ -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 contextFactory) { - // here we have to wait for completion of internal SetRenderingEnabled - mutex completionMutex; - condition_variable completionCondition; - bool notified = false; - auto completionHandler = [&]() - { - lock_guard lock(completionMutex); - notified = true; - completionCondition.notify_one(); - }; + if (m_wasContextReset && contextFactory != nullptr) + m_contextFactory = contextFactory; + SetRenderingEnabled(true); +} - SetRenderingEnabled(isEnabled, completionHandler); - - unique_lock lock(completionMutex); - completionCondition.wait(lock, [¬ified] { 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 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 lock(completionMutex); + completionCondition.wait(lock, [¬ified] { return notified; }); +} + +bool BaseRenderer::FilterGLContextDependentMessage(ref_ptr 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(); } diff --git a/drape_frontend/base_renderer.hpp b/drape_frontend/base_renderer.hpp index 14d4da18b4..6171f4929a 100644 --- a/drape_frontend/base_renderer.hpp +++ b/drape_frontend/base_renderer.hpp @@ -40,7 +40,9 @@ public: bool CanReceiveMessages(); - void SetRenderingEnabled(bool const isEnabled); + void SetRenderingEnabled(ref_ptr contextFactory); + void SetRenderingDisabled(bool const destroyContext); + bool IsRenderingEnabled() const; protected: @@ -55,6 +57,9 @@ protected: virtual unique_ptr CreateRoutine() = 0; + virtual void OnContextCreate() = 0; + virtual void OnContextDestroy() = 0; + private: using TCompletionHandler = function; @@ -66,8 +71,10 @@ private: atomic m_isEnabled; TCompletionHandler m_renderingEnablingCompletionHandler; bool m_wasNotified; + atomic m_wasContextReset; - void SetRenderingEnabled(bool const isEnabled, TCompletionHandler completionHandler); + bool FilterGLContextDependentMessage(ref_ptr msg); + void SetRenderingEnabled(bool const isEnabled); void Notify(); void WakeUp(); }; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 9b2698c9b8..e406525800 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -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(), + MessagePriority::High); + + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(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 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(), + MessagePriority::Normal); +} + void DrapeEngine::RecacheGui(bool needResetOldGui) { m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 12c86481cc..63f38e616f 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -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 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 m_frontend; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 38d71b5e2e..19e8b5db04 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -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) break; } + case Message::RecoverGLResources: + { + UpdateGLResources(); + break; + } + case Message::UpdateMapStyle: { // Clear all graphics. @@ -575,46 +582,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr 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(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(position, false /* isStart */, - true /* isValid */), - MessagePriority::High); - } - - auto const & routeData = m_routeRenderer->GetRouteData(); - if (routeData != nullptr) - { - auto recacheRouteMsg = make_unique_dp(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(), - MessagePriority::UberHighSingleton); - - m_gpsTrackRenderer->Update(); - + UpdateGLResources(); break; } @@ -752,6 +720,50 @@ unique_ptr FrontendRenderer::CreateRoutine() return make_unique(*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(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(position, false /* isStart */, + true /* isValid */), + MessagePriority::High); + } + + auto const & routeData = m_routeRenderer->GetRouteData(); + if (routeData != nullptr) + { + auto recacheRouteMsg = make_unique_dp(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(), + 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(&m_renderer)); - m_renderer.m_userEventStream.SetListener(ref_ptr(&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(); + 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(&m_renderer)); + m_renderer.m_userEventStream.SetListener(ref_ptr(&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); diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 2bb43a25be..6152e408f1 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -151,6 +151,8 @@ public: protected: void AcceptMessage(ref_ptr message) override; unique_ptr 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); @@ -325,6 +328,8 @@ private: drape_ptr m_selectObjectMessage; + bool m_needRestoreSize; + #ifdef DEBUG bool m_isTeardowned; #endif diff --git a/drape_frontend/gps_track_renderer.cpp b/drape_frontend/gps_track_renderer.cpp index d3c82e404e..b5137402be 100644 --- a/drape_frontend/gps_track_renderer.cpp +++ b/drape_frontend/gps_track_renderer.cpp @@ -90,6 +90,12 @@ void GpsTrackRenderer::AddRenderData(ref_ptr mng, m_waitForRenderData = false; } +void GpsTrackRenderer::ClearRenderData() +{ + m_renderData.clear(); + m_waitForRenderData = false; +} + void GpsTrackRenderer::UpdatePoints(vector const & toAdd, vector const & toRemove) { bool wasChanged = false; diff --git a/drape_frontend/gps_track_renderer.hpp b/drape_frontend/gps_track_renderer.hpp index 0ddd6063d3..cb40cb34e8 100644 --- a/drape_frontend/gps_track_renderer.hpp +++ b/drape_frontend/gps_track_renderer.hpp @@ -34,6 +34,7 @@ public: void Update(); void Clear(); + void ClearRenderData(); private: float CalculateRadius(ScreenBase const & screen) const; diff --git a/drape_frontend/map_shape.hpp b/drape_frontend/map_shape.hpp index 49b1e8d9f5..cdde3a35f4 100644 --- a/drape_frontend/map_shape.hpp +++ b/drape_frontend/map_shape.hpp @@ -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: diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 7319c255b6..bdc97bc437 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -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 diff --git a/drape_frontend/message_acceptor.cpp b/drape_frontend/message_acceptor.cpp index 322b6158c4..4f05bcdb06 100644 --- a/drape_frontend/message_acceptor.cpp +++ b/drape_frontend/message_acceptor.cpp @@ -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, MessagePriority priority) { + if (m_needFilterMessageFn != nullptr && m_needFilterMessageFn(make_ref(message))) + return; + m_messageQueue.PushMessage(move(message), priority); } diff --git a/drape_frontend/message_acceptor.hpp b/drape_frontend/message_acceptor.hpp index 24ab837497..d2e2f14e86 100644 --- a/drape_frontend/message_acceptor.hpp +++ b/drape_frontend/message_acceptor.hpp @@ -33,6 +33,10 @@ protected: size_t GetQueueSize() const; #endif + using TFilterMessageFn = function)>; + void EnableMessageFiltering(TFilterMessageFn needFilterMessageFn); + void DisableMessageFiltering(); + private: friend class ThreadsCommutator; @@ -40,6 +44,7 @@ private: MessageQueue m_messageQueue; atomic m_infinityWaiting; + TFilterMessageFn m_needFilterMessageFn; }; } // namespace df diff --git a/drape_frontend/message_queue.cpp b/drape_frontend/message_queue.cpp index 69f9edbdc3..fce3e04e30 100644 --- a/drape_frontend/message_queue.cpp +++ b/drape_frontend/message_queue.cpp @@ -80,6 +80,20 @@ void MessageQueue::PushMessage(drape_ptr && message, MessagePriority pr CancelWaitImpl(); } +void MessageQueue::FilterMessages(TFilterMessageFn needFilterMessageFn) +{ + ASSERT(needFilterMessageFn != nullptr, ()); + + lock_guard 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 diff --git a/drape_frontend/message_queue.hpp b/drape_frontend/message_queue.hpp index 2562d4954c..dc2147191b 100644 --- a/drape_frontend/message_queue.hpp +++ b/drape_frontend/message_queue.hpp @@ -27,6 +27,9 @@ public: void CancelWait(); void ClearQuery(); + using TFilterMessageFn = function)>; + void FilterMessages(TFilterMessageFn needFilterMessageFn); + #ifdef DEBUG_MESSAGE_QUEUE bool IsEmpty() const; size_t GetSize() const; diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index a8bfb5b336..5fc9412856 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -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 && 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 && 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 && AcceptShape() { return move(m_shape); } drape_ptr 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 && 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 && 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 && AcceptRenderData() { return move(m_renderData); } private: diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 3d868a8efd..e51f72c1ce 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -285,6 +285,11 @@ void MyPositionController::SetRenderShape(drape_ptr && shape) m_shape = move(shape); } +void MyPositionController::ResetRenderShape() +{ + m_shape.reset(); +} + void MyPositionController::NextMode(ScreenBase const & screen) { string const kAlohalyticsClickEvent = "$onClick"; diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 00bd0be3bc..9d555fc880 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -69,6 +69,7 @@ public: void CorrectGlobalScalePoint(m2::PointD & pt) const; void SetRenderShape(drape_ptr && shape); + void ResetRenderShape(); void ActivateRouting(int zoomLevel, bool enableAutoZoom); void DeactivateRouting(); diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp index 4a7b115980..3f041b3ce7 100644 --- a/drape_frontend/route_renderer.cpp +++ b/drape_frontend/route_renderer.cpp @@ -229,7 +229,7 @@ void RouteRenderer::UpdateRoute(ScreenBase const & screen, TCacheRouteArrowsCall void RouteRenderer::RenderRoute(ScreenBase const & screen, ref_ptr 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 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 const & sign, Scree ref_ptr 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 const & sign, Scree void RouteRenderer::SetRouteData(drape_ptr && routeData, ref_ptr mng) { + m_invalidGLResources = false; + m_routeData = move(routeData); m_arrowBorders.clear(); @@ -331,6 +339,8 @@ void RouteRenderer::SetRouteData(drape_ptr && routeData, ref_ptr && routeSignData, ref_ptr mng) { + m_invalidGLResources = false; + if (routeSignData->m_isStart) { if (!routeSignData->m_isValid) @@ -373,6 +383,8 @@ drape_ptr const & RouteRenderer::GetRouteData() const void RouteRenderer::SetRouteArrows(drape_ptr && routeArrowsData, ref_ptr 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; diff --git a/drape_frontend/route_renderer.hpp b/drape_frontend/route_renderer.hpp index a9f530704c..f98b9858f5 100644 --- a/drape_frontend/route_renderer.hpp +++ b/drape_frontend/route_renderer.hpp @@ -35,6 +35,7 @@ public: void SetRouteArrows(drape_ptr && routeArrowsData, ref_ptr 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 diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index c51a63338f..e97e74a7e5 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -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 = 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(); diff --git a/geometry/screenbase.hpp b/geometry/screenbase.hpp index 2346f1dd0b..5094eabc8f 100644 --- a/geometry/screenbase.hpp +++ b/geometry/screenbase.hpp @@ -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; } diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index e50177fd84..5ed97acc02 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -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]; } diff --git a/map/framework.cpp b/map/framework.cpp index e171afa140..c8ac3f2907 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -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 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 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 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 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 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() diff --git a/map/framework.hpp b/map/framework.hpp index d27aa94390..5bb11fdd33 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -333,10 +333,6 @@ public: private: unique_ptr m_lastTapEvent; -#ifdef OMIM_OS_ANDROID - unique_ptr m_lastCompassInfo; - unique_ptr 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 contextFactory = nullptr); + void SetRenderingDisabled(bool destroyContext); + + void UpdateDrapeEngine(int width, int height); + private: /// Depends on initialized Drape engine. void SaveViewport();