forked from organicmaps/organicmaps
Merge pull request #4151 from darina/drape-engine-soft-recovering
Soft recovering of drape engine .
This commit is contained in:
commit
9c2c2bc366
33 changed files with 502 additions and 244 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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, [¬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<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, [¬ified] { 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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
|
||||
void Update();
|
||||
void Clear();
|
||||
void ClearRenderData();
|
||||
|
||||
private:
|
||||
float CalculateRadius(ScreenBase const & screen) const;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue