Soft processing of android context destruction.

This commit is contained in:
Daria Volvenkova 2016-08-18 15:34:39 +03:00
parent 362211cf7e
commit 0f11b6d630
24 changed files with 316 additions and 164 deletions

View file

@ -63,6 +63,7 @@ enum MultiTouchAction
Framework::Framework()
: m_lastCompass(0.0)
, m_isContextDestroyed(false)
, m_currentMode(location::PendingPosition)
, m_isCurrentModeInitialized(false)
, m_isChoosePositionMode(false)
@ -143,23 +144,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,9 +158,16 @@ 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(LWARNING, ("Detach surface"));
if (destroyContext)
{
LOG(LWARNING, ("Destroy context"));
m_isContextDestroyed = true;
m_work.EnterBackground();
}
m_work.SetRenderingDisabled(destroyContext);
ASSERT(m_contextFactory != nullptr, ());
AndroidOGLContextFactory * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
@ -182,11 +176,24 @@ void Framework::DetachSurface()
void Framework::AttachSurface(JNIEnv * env, jobject jSurface)
{
LOG(LWARNING, ("Attach surface"));
ASSERT(m_contextFactory != nullptr, ());
AndroidOGLContextFactory * factory = m_contextFactory->CastFactory<AndroidOGLContextFactory>();
factory->SetSurface(env, jSurface);
m_work.SetRenderingEnabled(true);
ASSERT(!m_guiPositions.empty(), ("GUI elements must be set-up before engine is created"));
m_work.SetRenderingEnabled(factory);
if (m_isContextDestroyed)
{
LOG(LWARNING, ("Recover resources, size:", factory->GetWidth(), factory->GetHeight()));
m_work.UpdateDrapeEngine(factory->GetWidth(), factory->GetHeight());
m_isContextDestroyed = false;
m_work.EnterForeground();
}
}
void Framework::SetMapStyle(MapStyle mapStyle)
@ -196,6 +203,7 @@ void Framework::SetMapStyle(MapStyle mapStyle)
void Framework::MarkMapStyle(MapStyle mapStyle)
{
LOG(LWARNING, ("MarkMapStyle"));
m_work.MarkMapStyle(mapStyle);
}
@ -437,23 +445,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 +794,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 +999,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 +1023,7 @@ Java_com_mapswithme_maps_Framework_nativeSetAutoZoomEnabled(JNIEnv * env, jclass
{
bool const autoZoomEnabled = static_cast<bool>(enabled);
frm()->SaveAutoZoom(autoZoomEnabled);
g_framework->PostDrapeTask([autoZoomEnabled]()
{
frm()->AllowAutoZoom(autoZoomEnabled);
});
frm()->AllowAutoZoom(autoZoomEnabled);
}
JNIEXPORT jboolean JNICALL

View file

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

View file

@ -69,12 +69,6 @@ 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)
{
@ -88,9 +82,9 @@ Java_com_mapswithme_maps_MapFragment_nativeAttachSurface(JNIEnv * env, jclass cl
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_MapFragment_nativeDetachSurface(JNIEnv * env, jclass clazz)
Java_com_mapswithme_maps_MapFragment_nativeDetachSurface(JNIEnv * env, jclass clazz, jboolean destroyContext)
{
g_framework->DetachSurface();
g_framework->DetachSurface(destroyContext);
}
JNIEXPORT void JNICALL

View file

@ -240,21 +240,14 @@ extern "C"
{
lock_guard<mutex> guard(g_resultsMutex);
Result const & result = g_results.GetResult(index);
g_framework->PostDrapeTask([result]()
{
g_framework->NativeFramework()->ShowSearchResult(result);
});
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]()
{
g_framework->NativeFramework()->ShowSearchResults(results);
});
g_framework->NativeFramework()->ShowSearchResults(g_results);
}
JNIEXPORT void JNICALL

View file

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

View file

@ -52,7 +52,7 @@ public class MapFragment extends BaseMwmFragment
private int mHeight;
private int mWidth;
private boolean mRequireResize;
private boolean mEngineCreated;
private boolean mContextCreated;
private boolean mFirstStart;
private static boolean sWasCopyrightDisplayed;
@ -98,7 +98,7 @@ public class MapFragment extends BaseMwmFragment
UiUtils.dimen(R.dimen.margin_compass_left) + offsetX,
mHeight - UiUtils.dimen(R.dimen.margin_compass_bottom) + offsetY,
ANCHOR_CENTER);
if (forceRedraw && mEngineCreated)
if (forceRedraw && mContextCreated)
nativeApplyWidgets();
}
@ -108,7 +108,7 @@ public class MapFragment extends BaseMwmFragment
mWidth - UiUtils.dimen(R.dimen.margin_ruler_right) + offsetX,
mHeight - UiUtils.dimen(R.dimen.margin_ruler_bottom) + offsetY,
ANCHOR_RIGHT_BOTTOM);
if (forceRedraw && mEngineCreated)
if (forceRedraw && mContextCreated)
nativeApplyWidgets();
}
@ -141,6 +141,7 @@ public class MapFragment extends BaseMwmFragment
if (nativeIsEngineCreated())
{
nativeAttachSurface(surface);
mContextCreated = true;
mRequireResize = true;
return;
}
@ -154,20 +155,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 +182,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 +282,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 void nativeDetachSurface(boolean destroyContext);
private static native void nativeSurfaceChanged(int w, int h);
private static native void nativeOnTouch(int actionType, int id1, float x1, float y1, int id2, float x2, float y2, int maskedPointer);
private static native void nativeSetupWidget(int widget, float x, float y, int anchor);

View file

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

View file

@ -319,16 +319,33 @@ void BackendRenderer::ReleaseResources()
m_contextFactory->getResourcesUploadContext()->doneCurrent();
}
void BackendRenderer::OnContextCreate()
{
LOG(LWARNING, ("On context create."));
m_contextFactory->waitForInitialization();
m_contextFactory->getResourcesUploadContext()->makeCurrent();
GLFunctions::Init();
InitGLDependentResource();
}
void BackendRenderer::OnContextDestroy()
{
LOG(LWARNING, ("On context destroy."));
m_readManager->InvalidateAll();
m_batchersPool.reset();
m_texMng->Release();
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(LWARNING, ("Start routine."));
m_renderer.OnContextCreate();
while (!IsCancelled())
{

View file

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

View file

@ -39,23 +39,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)
m_contextFactory = contextFactory;
SetRenderingEnabled(true);
}
SetRenderingEnabled(isEnabled, completionHandler);
unique_lock<mutex> lock(completionMutex);
completionCondition.wait(lock, [&notified] { return notified; });
void BaseRenderer::SetRenderingDisabled(bool const destroyContext)
{
if (destroyContext)
m_wasContextReset = true;
SetRenderingEnabled(false);
}
bool BaseRenderer::IsRenderingEnabled() const
@ -63,17 +58,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 +87,30 @@ void BaseRenderer::SetRenderingEnabled(bool const isEnabled, TCompletionHandler
// if renderer thread is waiting for message let it go
CancelMessageWaiting();
}
unique_lock<mutex> lock(completionMutex);
completionCondition.wait(lock, [&notified] { return notified; });
}
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)
{
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 +121,17 @@ void BaseRenderer::CheckRenderingEnabled()
m_wasNotified = false;
m_isEnabled = true;
context->setRenderingEnabled(true);
if (m_wasContextReset)
{
m_wasContextReset = false;
OnContextCreate();
}
else
{
context->setRenderingEnabled(true);
}
// nofity initiator-thread about rendering enabling
// notify initiator-thread about rendering enabling
// m_renderingEnablingCompletionHandler will be setup before awakening of this thread
Notify();
}

View file

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

View file

@ -92,6 +92,24 @@ DrapeEngine::~DrapeEngine()
m_textureManager->Release();
}
void DrapeEngine::Update(int w, int h)
{
LOG(LWARNING, (w, h));
RecacheGui(false);
UpdateMapStyleMessage::Blocker blocker;
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<UpdateMapStyleMessage>(blocker),
MessagePriority::High);
blocker.Wait();
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)

View file

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

View file

@ -129,6 +129,7 @@ FrontendRenderer::FrontendRenderer(Params const & params)
, m_userPositionChangedFn(params.m_positionChangedFn)
, m_requestedTiles(params.m_requestedTiles)
, m_maxGeneration(0)
, m_needRestoreSize(false)
{
#ifdef DRAW_INFO
m_tpf = 0.0;
@ -819,8 +820,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 +1457,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(LWARNING, ("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(LWARNING, ("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 +1512,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 +1524,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(LWARNING, ("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 +1552,8 @@ void FrontendRenderer::Routine::Do()
bool modelViewChanged = true;
bool viewportChanged = true;
dp::OGLContext * context = m_renderer.m_contextFactory->getDrawContext();
while (!IsCancelled())
{
ScreenBase modelView = m_renderer.ProcessEvents(modelViewChanged, viewportChanged);

View file

@ -151,6 +151,8 @@ public:
protected:
void AcceptMessage(ref_ptr<Message> message) override;
unique_ptr<threads::IRoutine> CreateRoutine() override;
void OnContextCreate() override;
void OnContextDestroy() override;
private:
void OnResize(ScreenBase const & screen);
@ -325,6 +327,8 @@ private:
drape_ptr<SelectObjectMessage> m_selectObjectMessage;
bool m_needRestoreSize;
#ifdef DEBUG
bool m_isTeardowned;
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -290,7 +290,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(false);
m_selectedFeature = FeatureID();
m_searchEngine.reset();
m_infoGetter.reset();
@ -303,7 +303,7 @@ void Framework::Migrate(bool keepDownloaded)
InitSearchEngine();
RegisterAllMaps();
if (m_drapeEngine && m_isRenderingEnabled)
m_drapeEngine->SetRenderingEnabled(true);
m_drapeEngine->SetRenderingEnabled(nullptr);
InvalidateRect(MercatorBounds::FullRect());
}
@ -1659,6 +1659,15 @@ void Framework::CreateDrapeEngine(ref_ptr<dp::OGLContextFactory> contextFactory,
});
}
void Framework::UpdateDrapeEngine(int width, int height)
{
if (m_drapeEngine)
{
m_drapeEngine->Update(width, height);
InvalidateUserMarks();
}
}
ref_ptr<df::DrapeEngine> Framework::GetDrapeEngine()
{
return make_ref(m_drapeEngine);
@ -1670,11 +1679,18 @@ void Framework::DestroyDrapeEngine()
m_drapeEngine.reset();
}
void Framework::SetRenderingEnabled(bool enable)
void Framework::SetRenderingEnabled(ref_ptr<dp::OGLContextFactory> contextFactory)
{
m_isRenderingEnabled = enable;
m_isRenderingEnabled = true;
if (m_drapeEngine)
m_drapeEngine->SetRenderingEnabled(enable);
m_drapeEngine->SetRenderingEnabled(contextFactory);
}
void Framework::SetRenderingDisabled(bool destroyContext)
{
m_isRenderingEnabled = false;
if (m_drapeEngine)
m_drapeEngine->SetRenderingDisabled(destroyContext);
}
void Framework::ConnectToGpsTracker()

View file

@ -392,7 +392,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);
void SetRenderingDisabled(bool destroyContext);
void UpdateDrapeEngine(int width, int height);
private:
/// Depends on initialized Drape engine.
void SaveViewport();