diff --git a/data/benchmark.txt b/data/benchmark.txt new file mode 100644 index 0000000000..1f16ca664b --- /dev/null +++ b/data/benchmark.txt @@ -0,0 +1,2 @@ +Belarus.mwm 10 +Minsk 27.3271 64.1124 27.7853 64.3744 17 diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index ad4434316e..cb946deb4b 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -12,7 +12,7 @@ #include "../../map/drawer_yg.hpp" #include "../../storage/storage.hpp" -typedef FrameWork framework_t; +typedef FrameWork framework_t; @implementation MapViewController diff --git a/map/benchmark_provider.cpp b/map/benchmark_provider.cpp new file mode 100644 index 0000000000..0791c34dc2 --- /dev/null +++ b/map/benchmark_provider.cpp @@ -0,0 +1,33 @@ +#include "../base/SRC_FIRST.hpp" +#include "benchmark_provider.hpp" +#include "../indexer/mercator.hpp" + +BenchmarkRectProvider::BenchmarkRectProvider(int startLevel, m2::RectD const & startRect, int endLevel) + : m_endLevel(endLevel) +{ + m_rects.push_back(make_pair(startRect, startLevel)); +} + +bool BenchmarkRectProvider::hasRect() const +{ + return !m_rects.empty(); +} + +m2::RectD const BenchmarkRectProvider::nextRect() +{ + pair const & f = m_rects.front(); + m2::RectD r = f.first; + + if (f.second < m_endLevel) + { + int nextLevel = f.second + 1; + + m_rects.push_back(make_pair(m2::RectD(r.minX(), r.minY(), r.minX() + r.SizeX() / 2, r.minY() + r.SizeY() / 2), nextLevel)); + m_rects.push_back(make_pair(m2::RectD(r.minX() + r.SizeX() / 2, r.minY(), r.maxX(), r.minY() + r.SizeY() / 2), nextLevel)); + m_rects.push_back(make_pair(m2::RectD(r.minX(), r.minY() + r.SizeY() / 2, r.minX() + r.SizeX() / 2, r.maxY()), nextLevel)); + m_rects.push_back(make_pair(m2::RectD(r.minX() + r.SizeX() / 2, r.minY() + r.SizeY() / 2, r.maxX(), r.maxY()), nextLevel)); + } + + m_rects.pop_front(); + return r; +} diff --git a/map/benchmark_provider.hpp b/map/benchmark_provider.hpp new file mode 100644 index 0000000000..754c5c1801 --- /dev/null +++ b/map/benchmark_provider.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "../geometry/rect2d.hpp" +#include "../std/list.hpp" + +struct BenchmarkRectProvider +{ + int m_endLevel; + list > m_rects; + BenchmarkRectProvider(int startLevel, m2::RectD const & startRect, int endLevel); + + bool hasRect() const; + m2::RectD const nextRect(); +}; + diff --git a/map/framework.cpp b/map/framework.cpp index 786d3dcc55..c676ffa777 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -3,6 +3,8 @@ #include "framework.hpp" #include "draw_processor.hpp" #include "drawer_yg.hpp" +#include "feature_vec_model.hpp" +#include "benchmark_provider.hpp" #include "../indexer/feature_visibility.hpp" #include "../indexer/feature.hpp" @@ -12,6 +14,7 @@ #include "../base/math.hpp" #include "../std/algorithm.hpp" +#include "../version/version.hpp" #include "../base/start_mem_debug.hpp" @@ -181,4 +184,787 @@ namespace fwork return true; } + } + +template +void FrameWork::AddRedrawCommandSure() +{ + m_renderQueue.AddCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), m_navigator.Screen()); +} + + template + void FrameWork::AddRedrawCommand() + { + yg::gl::RenderState const state = m_renderQueue.CopyState(); + if ((state.m_currentScreen != m_navigator.Screen()) && (m_isRedrawEnabled)) + AddRedrawCommandSure(); + } + + template + void FrameWork::AddMap(string const & datFile) + { + // update rect for Show All button + feature::DataHeader header; + header.Load(FilesContainerR(datFile).GetReader(HEADER_FILE_TAG)); + + m2::RectD bounds = header.GetBounds(); + + m_model.AddWorldRect(bounds); + { + threads::MutexGuard lock(m_modelSyn); + m_model.AddMap(datFile); + } + } + + template + void FrameWork::RemoveMap(string const & datFile) + { + threads::MutexGuard lock(m_modelSyn); + m_model.RemoveMap(datFile); + } + + template + void FrameWork::OnGpsUpdate(location::GpsInfo const & info) + { + if (info.m_timestamp < location::POSITION_TIMEOUT_SECONDS) + { + // notify GUI that we received gps position + if (!(m_locationState & location::State::EGps) && m_locationObserver) + m_locationObserver(); + + m_locationState.UpdateGps(info); + if (m_centeringMode == ECenterAndScale) + { + CenterAndScaleViewport(); + m_centeringMode = ECenterOnly; + } + else if (m_centeringMode == ECenterOnly) + CenterViewport(m_locationState.Position()); + UpdateNow(); + } + } + + template + void FrameWork::OnCompassUpdate(location::CompassInfo const & info) + { + if (info.m_timestamp < location::POSITION_TIMEOUT_SECONDS) + { + m_locationState.UpdateCompass(info); + UpdateNow(); + } + } + + template + FrameWork::FrameWork(shared_ptr windowHandle, + size_t bottomShift) + : m_windowHandle(windowHandle), + m_isBenchmarking(GetPlatform().IsBenchmarking()), + m_isBenchmarkInitialized(false), + m_bgColor(0xEE, 0xEE, 0xDD, 0xFF), + m_renderQueue(GetPlatform().SkinName(), + GetPlatform().IsMultiSampled(), + GetPlatform().DoPeriodicalUpdate(), + GetPlatform().PeriodicalUpdateInterval(), + GetPlatform().IsBenchmarking(), + GetPlatform().ScaleEtalonSize(), + m_bgColor), + m_isRedrawEnabled(true), + m_metresMinWidth(20), + m_minRulerWidth(97), + m_centeringMode(EDoNothing), + m_maxDuration(0) + { + m_informationDisplay.setBottomShift(bottomShift); +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.enableDebugPoints(true); +#endif + +#ifdef DEBUG + m_informationDisplay.enableGlobalRect(!m_isBenchmarking); +#endif + + m_informationDisplay.enableCenter(true); + + m_informationDisplay.enableRuler(true); + m_informationDisplay.setRulerParams(m_minRulerWidth, m_metresMinWidth); + m_navigator.SetMinScreenParams(m_minRulerWidth, m_metresMinWidth); + +#ifdef DEBUG + m_informationDisplay.enableDebugInfo(true); +#endif + + m_informationDisplay.enableLog(GetPlatform().IsVisualLog(), m_windowHandle.get()); + + m_informationDisplay.enableBenchmarkInfo(m_isBenchmarking); + + m_informationDisplay.setVisualScale(GetPlatform().VisualScale()); + m_renderQueue.AddWindowHandle(m_windowHandle); + + // initialize gps and compass subsystem + GetLocationService().SetGpsObserver( + boost::bind(&this_type::OnGpsUpdate, this, _1)); + GetLocationService().SetCompassObserver( + boost::bind(&this_type::OnCompassUpdate, this, _1)); + } + + template + void FrameWork::BenchmarkCommandFinished() + { + double duration = m_renderQueue.renderState().m_duration; + if (duration > m_maxDuration) + { + m_maxDuration = duration; + m_maxDurationRect = m_curBenchmarkRect; + m_informationDisplay.addBenchmarkInfo("maxDurationRect: ", m_maxDurationRect, m_maxDuration); + } + + BenchmarkResult res; + res.m_name = m_benchmarks[m_curBenchmark].m_name; + res.m_rect = m_curBenchmarkRect; + res.m_time = duration; + m_benchmarkResults.push_back(res); + + if (m_benchmarkResults.size() > 100) + SaveBenchmarkResults(); + + NextBenchmarkCommand(); + } + + template + void FrameWork::SaveBenchmarkResults() + { + string deviceID = GetPlatform().DeviceID(); + transform(deviceID.begin(), deviceID.end(), deviceID.begin(), ::tolower); + + ofstream fout(GetPlatform().WritablePathForFile(deviceID + "_benchmark_results.txt").c_str(), ios::app); + + for (int i = 0; i < m_benchmarkResults.size(); ++i) + { + fout << GetPlatform().DeviceID() << " " + << VERSION_STRING << " " + << m_benchmarkResults[i].m_name << " " + << m_benchmarkResults[i].m_rect.minX() << " " + << m_benchmarkResults[i].m_rect.minY() << " " + << m_benchmarkResults[i].m_rect.maxX() << " " + << m_benchmarkResults[i].m_rect.maxY() << " " + << m_benchmarkResults[i].m_time << endl; + } + + m_benchmarkResults.clear(); + } + + template + void FrameWork::NextBenchmarkCommand() + { + if ((m_benchmarks[m_curBenchmark].m_provider->hasRect()) || (++m_curBenchmark < m_benchmarks.size())) + { + m_curBenchmarkRect = m_benchmarks[m_curBenchmark].m_provider->nextRect(); + m_navigator.SetFromRect(m_curBenchmarkRect); + m_renderQueue.AddBenchmarkCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), m_navigator.Screen()); + } + else + { + SaveBenchmarkResults(); + LOG(LINFO, ("Bechmarks took ", m_benchmarksTimer.ElapsedSeconds(), " seconds to complete")); + } + } + + template + void FrameWork::EnumLocalMaps(Platform::FilesList & filesList) + { + // activate all downloaded maps + Platform & p = GetPlatform(); + string const dataPath = p.WritableDir(); + filesList.clear(); + p.GetFilesInDir(dataPath, "*" DATA_FILE_EXTENSION, filesList); + } + + template + void FrameWork::EnumBenchmarkMaps(Platform::FilesList & filesList) + { + filesList.clear(); + filesList.push_back("Belarus.mwm"); + } + + template + void FrameWork::InitBenchmark() + { +// m2::RectD wr(MercatorBounds::minX, MercatorBounds::minY, MercatorBounds::maxX, MercatorBounds::maxY); +// m2::RectD r(wr.Center().x, wr.Center().y + wr.SizeY() / 8, wr.Center().x + wr.SizeX() / 8, wr.Center().y + wr.SizeY() / 4); + + ifstream fin(GetPlatform().WritablePathForFile("benchmark.txt").c_str()); + while (true) + { + string name; + m2::RectD r; + + fin >> name; + + if (!fin) + break; + + if (GetPlatform().IsFileExists(GetPlatform().WritablePathForFile(name))) + { + try + { + feature::DataHeader header; + header.Load(FilesContainerR(GetPlatform().WritablePathForFile(name)).GetReader(HEADER_FILE_TAG)); + + r = header.GetBounds(); + } + catch (std::exception const & e) + { + double x0, y0, x1, y1; + fin >> x0 >> y0 >> x1 >> y1; + r = m2::RectD(x0, y0, x1, y1); + } + } + else + { + double x0, y0, x1, y1; + fin >> x0 >> y0 >> x1 >> y1; + r = m2::RectD(x0, y0, x1, y1); + } + + if (!fin) + break; + + int lastScale; + fin >> lastScale; + + Benchmark b; + b.m_name = name; + b.m_provider.reset(new BenchmarkRectProvider(scales::GetScaleLevel(r), r, lastScale)); + m_benchmarks.push_back(b); + } + + m_curBenchmark = 0; + + m_renderQueue.addRenderCommandFinishedFn(bind(&this_type::BenchmarkCommandFinished, this)); + m_benchmarksTimer.Reset(); + NextBenchmarkCommand(); + + Invalidate(); + } + + template + void FrameWork::initializeGL(shared_ptr const & primaryContext, + shared_ptr const & resourceManager) + { + m_resourceManager = resourceManager; + m_renderQueue.initializeGL(primaryContext, m_resourceManager, GetPlatform().VisualScale()); + } + + template + TModel & FrameWork::get_model() + { + return m_model; + } + + template + void FrameWork::StartLocationService(LocationRetrievedCallbackT observer) + { + m_locationObserver = observer; + m_centeringMode = ECenterAndScale; + // by default, we always start in accurate mode + GetLocationService().StartUpdate(true); + } + + template + void FrameWork::StopLocationService() + { + // reset callback + m_locationObserver.clear(); + m_centeringMode = EDoNothing; + GetLocationService().StopUpdate(); + m_locationState.TurnOff(); + Invalidate(); + } + + template + bool FrameWork::IsEmptyModel() + { + return m_model.GetWorldRect() == m2::RectD::GetEmptyRect(); + } + + // Cleanup. + template + void FrameWork::Clean() + { + m_model.Clean(); + } + + template + void FrameWork::SetMaxWorldRect() + { + m_navigator.SetFromRect(m_model.GetWorldRect()); + } + + template + void FrameWork::UpdateNow() + { + AddRedrawCommand(); + Invalidate(); + } + + template + void FrameWork::Invalidate() + { + m_windowHandle->invalidate(); + } + + template + void FrameWork::SaveState() + { + m_navigator.SaveState(); + } + + template + bool FrameWork::LoadState() + { + if (!m_navigator.LoadState()) + return false; + + return true; + } + //@} + + /// Resize event from window. + template + void FrameWork::OnSize(int w, int h) + { + if (w < 2) w = 2; + if (h < 2) h = 2; + + m_renderQueue.OnSize(w, h); + + m2::PointU ptShift = m_renderQueue.renderState().coordSystemShift(true); + + m_informationDisplay.setDisplayRect(m2::RectI(ptShift, ptShift + m2::PointU(w, h))); + + m_navigator.OnSize(ptShift.x, ptShift.y, w, h); + + if ((m_isBenchmarking) && (!m_isBenchmarkInitialized)) + { + m_isBenchmarkInitialized = true; + InitBenchmark(); + } + } + + template + bool FrameWork::SetUpdatesEnabled(bool doEnable) + { + return m_windowHandle->setUpdatesEnabled(doEnable); + } + + /// enabling/disabling AddRedrawCommand + template + void FrameWork::SetRedrawEnabled(bool isRedrawEnabled) + { + m_isRedrawEnabled = isRedrawEnabled; + AddRedrawCommand(); + } + + /// respond to device orientation changes + template + void FrameWork::SetOrientation(EOrientation orientation) + { + m_navigator.SetOrientation(orientation); + m_locationState.SetOrientation(orientation); + UpdateNow(); + } + + template + int FrameWork::GetCurrentScale() const + { + m2::PointD textureCenter(m_renderQueue.renderState().m_textureWidth / 2, + m_renderQueue.renderState().m_textureHeight / 2); + m2::RectD glbRect; + + unsigned scaleEtalonSize = GetPlatform().ScaleEtalonSize(); + m_navigator.Screen().PtoG(m2::RectD(textureCenter - m2::PointD(scaleEtalonSize / 2, scaleEtalonSize / 2), + textureCenter + m2::PointD(scaleEtalonSize / 2, scaleEtalonSize / 2)), + glbRect); + return scales::GetScaleLevel(glbRect); + } + + /// Actual rendering function. + /// Called, as the renderQueue processes RenderCommand + /// Usually it happens in the separate thread. + template + void FrameWork::PaintImpl(shared_ptr e, + ScreenBase const & screen, + m2::RectD const & selectRect, + int scaleLevel + ) + { + fwork::DrawProcessor doDraw(selectRect, screen, e, scaleLevel, m_renderQueue.renderStatePtr()); + m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = true; + + try + { + threads::MutexGuard lock(m_modelSyn); + +#ifdef PROFILER_DRAWING + using namespace prof; + + start(); + reset(); +#endif + + m_model.ForEachFeatureWithScale(selectRect, bind(ref(doDraw), _1), scaleLevel); + +#ifdef PROFILER_DRAWING + end(); + LOG(LPROF, ("ForEachFeature=", metric(), + "FeatureCount=", metric(), + "TextureUpload= ", metric())); +#endif + } + catch (redraw_operation_cancelled const &) + { + m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = false; + m_renderQueue.renderStatePtr()->m_isEmptyModelActual = false; + } + + if (m_navigator.Update(GetPlatform().TimeInSec())) + Invalidate(); + } + + /// Function for calling from platform dependent-paint function. + template + void FrameWork::Paint(shared_ptr e) + { + /// Making a copy of actualFrameInfo to compare without synchronizing. +// typename yg::gl::RenderState state = m_renderQueue.CopyState(); + + DrawerYG * pDrawer = e->drawer().get(); + + m_informationDisplay.setScreen(m_navigator.Screen()); + + m_informationDisplay.setDebugInfo(m_renderQueue.renderState().m_duration, GetCurrentScale()); + + m_informationDisplay.enableRuler(!IsEmptyModel()); + + m2::PointD const center = m_navigator.Screen().ClipRect().Center(); + + m_informationDisplay.setGlobalRect(m_navigator.Screen().GlobalRect()); + m_informationDisplay.setCenter(m2::PointD(MercatorBounds::XToLon(center.x), MercatorBounds::YToLat(center.y))); + + { + threads::MutexGuard guard(*m_renderQueue.renderState().m_mutex.get()); + + if (m_isBenchmarking) + { + m2::PointD const center = m_renderQueue.renderState().m_actualScreen.ClipRect().Center(); + m_informationDisplay.setScreen(m_renderQueue.renderState().m_actualScreen); + m_informationDisplay.setCenter(m2::PointD(MercatorBounds::XToLon(center.x), MercatorBounds::YToLat(center.y))); + + if (!m_isBenchmarkInitialized) + { + e->drawer()->screen()->beginFrame(); + e->drawer()->screen()->clear(m_bgColor); + m_informationDisplay.setDisplayRect(m2::RectI(0, 0, 100, 100)); + m_informationDisplay.enableRuler(false); + m_informationDisplay.doDraw(e->drawer().get()); + e->drawer()->screen()->endFrame(); + } + } + + if (m_renderQueue.renderState().m_actualTarget.get() != 0) + { + e->drawer()->screen()->beginFrame(); + e->drawer()->screen()->clear(m_bgColor); + + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(false); + + OGLCHECK(glMatrixMode(GL_MODELVIEW)); + OGLCHECK(glPushMatrix()); + OGLCHECK(glTranslatef(-ptShift.x, -ptShift.y, 0)); + + ScreenBase currentScreen = m_navigator.Screen(); + + m_informationDisplay.enableEmptyModelMessage(m_renderQueue.renderStatePtr()->m_isEmptyModelActual); + + if (m_isBenchmarking) + currentScreen = m_renderQueue.renderState().m_actualScreen; + + pDrawer->screen()->blit(m_renderQueue.renderState().m_actualTarget, + m_renderQueue.renderState().m_actualScreen, + currentScreen); + + m_informationDisplay.doDraw(pDrawer); + + InformationDisplay::DrawMyPosition(*pDrawer, m_navigator.Screen(), m_locationState); + + e->drawer()->screen()->endFrame(); + + OGLCHECK(glPopMatrix()); + } + } + } + + template + void FrameWork::CenterViewport(m2::PointD const & pt) + { + m_navigator.CenterViewport(pt); + UpdateNow(); + } + + template + void FrameWork::ShowRect(m2::RectD const & rect) + { + m_navigator.SetFromRect(rect); + UpdateNow(); + } + + template + void FrameWork::MemoryWarning() + { + // clearing caches on memory warning. + m_model.ClearCaches(); + LOG(LINFO, ("MemoryWarning")); + } + + template + void FrameWork::EnterBackground() + { + // clearing caches on entering background. + m_model.ClearCaches(); + } + + template + void FrameWork::EnterForeground() + { + } + + /// @TODO refactor to accept point and min visible length + template + void FrameWork::CenterAndScaleViewport() + { + m2::PointD const pt = m_locationState.Position(); + m_navigator.CenterViewport(pt); + + m2::RectD clipRect = m_navigator.Screen().ClipRect(); + + double const xMinSize = 6 * max(m_locationState.ErrorRadius(), + MercatorBounds::ConvertMetresToX(pt.x, m_metresMinWidth)); + double const yMinSize = 6 * max(m_locationState.ErrorRadius(), + MercatorBounds::ConvertMetresToY(pt.y, m_metresMinWidth)); + + bool needToScale = false; + + if (clipRect.SizeX() < clipRect.SizeY()) + needToScale = clipRect.SizeX() > xMinSize * 3; + else + needToScale = clipRect.SizeY() > yMinSize * 3; + +/* if ((ClipRect.SizeX() < 3 * errorRadius) || (ClipRect.SizeY() < 3 * errorRadius)) + needToScale = true;*/ + + if (needToScale) + { + double const k = max(xMinSize / clipRect.SizeX(), + yMinSize / clipRect.SizeY()); + + clipRect.Scale(k); + m_navigator.SetFromRect(clipRect); + } + + UpdateNow(); + } + + /// Show all model by it's world rect. + template + void FrameWork::ShowAll() + { + SetMaxWorldRect(); + UpdateNow(); + } + + template + void FrameWork::Repaint() + { + m_renderQueue.SetRedrawAll(); + AddRedrawCommandSure(); + Invalidate(); + } + + template + void FrameWork::RepaintRect(m2::RectD const & rect) + { + threads::MutexGuard lock(*m_renderQueue.renderState().m_mutex.get()); + m2::RectD pxRect(0, 0, m_renderQueue.renderState().m_surfaceWidth, m_renderQueue.renderState().m_surfaceHeight); + m2::RectD glbRect; + m_navigator.Screen().PtoG(pxRect, glbRect); + if (glbRect.Intersect(rect)) + Repaint(); + } + + /// @name Drag implementation. + //@{ + template + void FrameWork::StartDrag(DragEvent const & e) + { + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); + m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; + m_navigator.StartDrag(pos, + GetPlatform().TimeInSec()); + +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.setDebugPoint(0, pos); +#endif + + Invalidate(); + } + + template + void FrameWork::DoDrag(DragEvent const & e) + { + m_centeringMode = EDoNothing; + + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); + + m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; + m_navigator.DoDrag(pos, GetPlatform().TimeInSec()); + +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.setDebugPoint(0, pos); +#endif + + Invalidate(); + } + + template + void FrameWork::StopDrag(DragEvent const & e) + { + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); + + m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; + + m_navigator.StopDrag(pos, + GetPlatform().TimeInSec(), + true); + +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.setDebugPoint(0, m2::PointD(0, 0)); +#endif + + UpdateNow(); + } + + template + void FrameWork::Move(double azDir, double factor) + { + m_navigator.Move(azDir, factor); + UpdateNow(); + } + //@} + + /// @name Scaling. + //@{ + template + void FrameWork::ScaleToPoint(ScaleToPointEvent const & e) + { + m2::PointD const pt = (m_centeringMode == EDoNothing) + ? m_navigator.OrientPoint(e.Pt()) + m_renderQueue.renderState().coordSystemShift(true) + : m_navigator.Screen().PixelRect().Center(); + + m_navigator.ScaleToPoint(pt, e.ScaleFactor(), GetPlatform().TimeInSec()); + + UpdateNow(); + } + + template + void FrameWork::ScaleDefault(bool enlarge) + { + Scale(enlarge ? 1.5 : 2.0/3.0); + } + + template + void FrameWork::Scale(double scale) + { + m_navigator.Scale(scale); + UpdateNow(); + } + + template + void FrameWork::StartScale(ScaleEvent const & e) + { + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); + + m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()) + ptShift; + m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()) + ptShift; + + if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) + { + m2::PointD ptC = (pt1 + pt2) / 2; + m2::PointD ptDiff = m_navigator.Screen().PixelRect().Center() - ptC; + pt1 += ptDiff; + pt2 += ptDiff; + } + + m_navigator.StartScale(pt1, pt2, GetPlatform().TimeInSec()); + +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.setDebugPoint(0, pt1); + m_informationDisplay.setDebugPoint(1, pt2); +#endif + + Invalidate(); + } + + template + void FrameWork::DoScale(ScaleEvent const & e) + { + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); + + m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()) + ptShift; + m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()) + ptShift; + + if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) + { + m2::PointD ptC = (pt1 + pt2) / 2; + m2::PointD ptDiff = m_navigator.Screen().PixelRect().Center() - ptC; + pt1 += ptDiff; + pt2 += ptDiff; + } + + m_navigator.DoScale(pt1, pt2, GetPlatform().TimeInSec()); + +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.setDebugPoint(0, pt1); + m_informationDisplay.setDebugPoint(1, pt2); +#endif + + Invalidate(); + } + + template + void FrameWork::StopScale(ScaleEvent const & e) + { + m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); + + m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()) + ptShift; + m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()) + ptShift; + + if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) + { + m2::PointD ptC = (pt1 + pt2) / 2; + m2::PointD ptDiff = m_navigator.Screen().PixelRect().Center() - ptC; + pt1 += ptDiff; + pt2 += ptDiff; + } + + m_navigator.StopScale(pt1, pt2, GetPlatform().TimeInSec()); + +#ifdef DRAW_TOUCH_POINTS + m_informationDisplay.setDebugPoint(0, m2::PointD(0, 0)); + m_informationDisplay.setDebugPoint(0, m2::PointD(0, 0)); +#endif + + UpdateNow(); + } + +template class FrameWork; diff --git a/map/framework.hpp b/map/framework.hpp index b8c1872b23..223daa42a7 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -6,6 +6,7 @@ #include "information_display.hpp" #include "window_handle.hpp" #include "location_state.hpp" +#include "navigator.hpp" #include "../defines.hpp" @@ -48,6 +49,8 @@ namespace drule { class BaseRule; } class redraw_operation_cancelled {}; +struct BenchmarkRectProvider; + namespace fwork { class DrawProcessor @@ -89,24 +92,20 @@ typedef boost::function LocationRetrievedCallbackT; template < - class TModel, - class TNavigator + class TModel > class FrameWork { typedef TModel model_t; - typedef TNavigator navigator_t; - typedef FrameWork this_type; + typedef FrameWork this_type; model_t m_model; - navigator_t m_navigator; + Navigator m_navigator; shared_ptr m_windowHandle; bool m_isBenchmarking; bool m_isBenchmarkInitialized; - vector > m_benchmarks; - unsigned m_currentBenchmark; yg::Color m_bgColor; @@ -126,152 +125,63 @@ class FrameWork ECenterAndScale, ECenterOnly }; + TGpsCenteringMode m_centeringMode; LocationRetrievedCallbackT m_locationObserver; location::State m_locationState; - void AddRedrawCommandSure() - { - m_renderQueue.AddCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), m_navigator.Screen()); - } - - void AddRedrawCommand() - { - yg::gl::RenderState const state = m_renderQueue.CopyState(); - if ((state.m_currentScreen != m_navigator.Screen()) && (m_isRedrawEnabled)) - AddRedrawCommandSure(); - } - threads::Mutex m_modelSyn; - void AddMap(string const & datFile) + void AddRedrawCommandSure(); + void AddRedrawCommand(); + + double m_maxDuration; + m2::RectD m_maxDurationRect; + m2::RectD m_curBenchmarkRect; + + struct BenchmarkResult { - // update rect for Show All button - feature::DataHeader header; - header.Load(FilesContainerR(datFile).GetReader(HEADER_FILE_TAG)); + string m_name; + m2::RectD m_rect; + double m_time; + }; - m2::RectD bounds = header.GetBounds(); + vector m_benchmarkResults; + my::Timer m_benchmarksTimer; - m_model.AddWorldRect(bounds); - { - threads::MutexGuard lock(m_modelSyn); - m_model.AddMap(datFile); - } - } - - void RemoveMap(string const & datFile) + struct Benchmark { - threads::MutexGuard lock(m_modelSyn); - m_model.RemoveMap(datFile); - } + shared_ptr m_provider; + string m_name; + }; - void OnGpsUpdate(location::GpsInfo const & info) - { - if (info.m_timestamp < location::POSITION_TIMEOUT_SECONDS) - { - // notify GUI that we received gps position - if (!(m_locationState & location::State::EGps) && m_locationObserver) - m_locationObserver(); + vector m_benchmarks; + int m_curBenchmark; - m_locationState.UpdateGps(info); - if (m_centeringMode == ECenterAndScale) - { - CenterAndScaleViewport(); - m_centeringMode = ECenterOnly; - } - else if (m_centeringMode == ECenterOnly) - CenterViewport(m_locationState.Position()); - UpdateNow(); - } - } + void BenchmarkCommandFinished(); + void NextBenchmarkCommand(); + void SaveBenchmarkResults(); - void OnCompassUpdate(location::CompassInfo const & info) - { - if (info.m_timestamp < location::POSITION_TIMEOUT_SECONDS) - { - m_locationState.UpdateCompass(info); - UpdateNow(); - } - } + void AddMap(string const & datFile); + void RemoveMap(string const & datFile); + + void OnGpsUpdate(location::GpsInfo const & info); + + void OnCompassUpdate(location::CompassInfo const & info); public: FrameWork(shared_ptr windowHandle, - size_t bottomShift) - : m_windowHandle(windowHandle), - m_isBenchmarking(GetPlatform().IsBenchmarking()), - m_isBenchmarkInitialized(false), - m_currentBenchmark(0), - m_bgColor(0xEE, 0xEE, 0xDD, 0xFF), - m_renderQueue(GetPlatform().SkinName(), - GetPlatform().IsMultiSampled(), - GetPlatform().DoPeriodicalUpdate(), - GetPlatform().PeriodicalUpdateInterval(), - GetPlatform().IsBenchmarking(), - GetPlatform().ScaleEtalonSize(), - m_bgColor), - m_isRedrawEnabled(true), - m_metresMinWidth(20), - m_minRulerWidth(97), - m_centeringMode(EDoNothing) - { - m_informationDisplay.setBottomShift(bottomShift); -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.enableDebugPoints(true); -#endif + size_t bottomShift); -#ifdef DEBUG - m_informationDisplay.enableGlobalRect(!m_isBenchmarking); -#endif - - m_informationDisplay.enableCenter(true); - - m_informationDisplay.enableRuler(true); - m_informationDisplay.setRulerParams(m_minRulerWidth, m_metresMinWidth); - m_navigator.SetMinScreenParams(m_minRulerWidth, m_metresMinWidth); - -#ifdef DEBUG - m_informationDisplay.enableDebugInfo(true); -#endif - - m_informationDisplay.enableLog(GetPlatform().IsVisualLog(), m_windowHandle.get()); - - m_informationDisplay.enableBenchmarkInfo(m_isBenchmarking); - - m_informationDisplay.setVisualScale(GetPlatform().VisualScale()); - m_renderQueue.AddWindowHandle(m_windowHandle); - - // initialize gps and compass subsystem - GetLocationService().SetGpsObserver( - boost::bind(&this_type::OnGpsUpdate, this, _1)); - GetLocationService().SetCompassObserver( - boost::bind(&this_type::OnCompassUpdate, this, _1)); - } - - void InitBenchmark() - { - ifstream fin(GetPlatform().WritablePathForFile("benchmark.txt").c_str()); - while (true) - { - string name; - double x0, y0, x1, y1; - fin >> name >> x0 >> y0 >> x1 >> y1; - if (!fin) - break; - m_navigator.SetFromRect(m2::RectD(x0, y0, x1, y1)); - m_renderQueue.AddBenchmarkCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), m_navigator.Screen()); - m_benchmarks.push_back(make_pair(name, m2::RectD(x0, y0, x1, y1))); - } - Invalidate(); - } + void InitBenchmark(); void initializeGL(shared_ptr const & primaryContext, - shared_ptr const & resourceManager) - { - m_resourceManager = resourceManager; - m_renderQueue.initializeGL(primaryContext, m_resourceManager, GetPlatform().VisualScale()); - } + shared_ptr const & resourceManager); - model_t & get_model() { return m_model; } + model_t & get_model(); + + void EnumLocalMaps(Platform::FilesList & filesList); + void EnumBenchmarkMaps(Platform::FilesList & filesList); /// Initialization. template @@ -279,130 +189,49 @@ public: { m_model.InitClassificator(); + typename TStorage::TEnumMapsFunction enumMapsFn; + if (m_isBenchmarking) + enumMapsFn = bind(&FrameWork::EnumBenchmarkMaps, this, _1); + else + enumMapsFn = bind(&FrameWork::EnumLocalMaps, this, _1); + LOG(LINFO, ("Initializing storage")); // initializes model with locally downloaded maps storage.Init(bind(&FrameWork::AddMap, this, _1), bind(&FrameWork::RemoveMap, this, _1), - bind(&FrameWork::RepaintRect, this, _1)); + bind(&FrameWork::RepaintRect, this, _1), + enumMapsFn); LOG(LINFO, ("Storage initialized")); - } + }; - void StartLocationService(LocationRetrievedCallbackT observer) - { - m_locationObserver = observer; - m_centeringMode = ECenterAndScale; - // by default, we always start in accurate mode - GetLocationService().StartUpdate(true); - } + void StartLocationService(LocationRetrievedCallbackT observer); + void StopLocationService(); - void StopLocationService() - { - // reset callback - m_locationObserver.clear(); - m_centeringMode = EDoNothing; - GetLocationService().StopUpdate(); - m_locationState.TurnOff(); - Invalidate(); - } - - bool IsEmptyModel() - { - return m_model.GetWorldRect() == m2::RectD::GetEmptyRect(); - } + bool IsEmptyModel(); // Cleanup. - void Clean() - { - m_model.Clean(); - } + void Clean(); - /// Save and load framework state to ini file between sessions. - //@{ public: - void SetMaxWorldRect() - { - m_navigator.SetFromRect(m_model.GetWorldRect()); - } - - void UpdateNow() - { - AddRedrawCommand(); - Invalidate(); - } - - void Invalidate() - { - m_windowHandle->invalidate(); - } - - void SaveState() - { - m_navigator.SaveState(); - } - - bool LoadState() - { - if (!m_navigator.LoadState()) - return false; - - return true; - } - //@} + void SetMaxWorldRect(); + void UpdateNow(); + void Invalidate(); + void SaveState(); + bool LoadState(); /// Resize event from window. - void OnSize(int w, int h) - { - if (w < 2) w = 2; - if (h < 2) h = 2; + void OnSize(int w, int h); - m_renderQueue.OnSize(w, h); - - m2::PointU ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m_informationDisplay.setDisplayRect(m2::RectI(ptShift, ptShift + m2::PointU(w, h))); - - m_navigator.OnSize(ptShift.x, ptShift.y, w, h); - - if ((m_isBenchmarking) && (!m_isBenchmarkInitialized)) - { - m_isBenchmarkInitialized = true; - InitBenchmark(); - } - } - - bool SetUpdatesEnabled(bool doEnable) - { - return m_windowHandle->setUpdatesEnabled(doEnable); - } + bool SetUpdatesEnabled(bool doEnable); /// enabling/disabling AddRedrawCommand - void SetRedrawEnabled(bool isRedrawEnabled) - { - m_isRedrawEnabled = isRedrawEnabled; - AddRedrawCommand(); - } + void SetRedrawEnabled(bool isRedrawEnabled); /// respond to device orientation changes - void SetOrientation(EOrientation orientation) - { - m_navigator.SetOrientation(orientation); - m_locationState.SetOrientation(orientation); - UpdateNow(); - } + void SetOrientation(EOrientation orientation); - int GetCurrentScale() const - { - m2::PointD textureCenter(m_renderQueue.renderState().m_textureWidth / 2, - m_renderQueue.renderState().m_textureHeight / 2); - m2::RectD glbRect; - - unsigned scaleEtalonSize = GetPlatform().ScaleEtalonSize(); - m_navigator.Screen().PtoG(m2::RectD(textureCenter - m2::PointD(scaleEtalonSize / 2, scaleEtalonSize / 2), - textureCenter + m2::PointD(scaleEtalonSize / 2, scaleEtalonSize / 2)), - glbRect); - return scales::GetScaleLevel(glbRect); - } + int GetCurrentScale() const; /// Actual rendering function. /// Called, as the renderQueue processes RenderCommand @@ -411,360 +240,54 @@ public: ScreenBase const & screen, m2::RectD const & selectRect, int scaleLevel - ) - { - fwork::DrawProcessor doDraw(selectRect, screen, e, scaleLevel, m_renderQueue.renderStatePtr()); - m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = true; - - try - { - threads::MutexGuard lock(m_modelSyn); - -#ifdef PROFILER_DRAWING - using namespace prof; - - start(); - reset(); -#endif - - m_model.ForEachFeatureWithScale(selectRect, bind(ref(doDraw), _1), scaleLevel); - -#ifdef PROFILER_DRAWING - end(); - LOG(LPROF, ("ForEachFeature=", metric(), - "FeatureCount=", metric(), - "TextureUpload= ", metric())); -#endif - } - catch (redraw_operation_cancelled const &) - { - m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = false; - m_renderQueue.renderStatePtr()->m_isEmptyModelActual = false; - } - - if (m_navigator.Update(GetPlatform().TimeInSec())) - Invalidate(); - } + ); /// Function for calling from platform dependent-paint function. - void Paint(shared_ptr e) - { - /// Making a copy of actualFrameInfo to compare without synchronizing. -// typename yg::gl::RenderState state = m_renderQueue.CopyState(); + void Paint(shared_ptr e); - DrawerYG * pDrawer = e->drawer().get(); + void CenterViewport(m2::PointD const & pt); - m_informationDisplay.setScreen(m_navigator.Screen()); + void ShowRect(m2::RectD const & rect); - m_informationDisplay.setDebugInfo(m_renderQueue.renderState().m_duration, GetCurrentScale()); + void MemoryWarning(); - m_informationDisplay.enableRuler(!IsEmptyModel()); + void EnterBackground(); - m2::PointD const center = m_navigator.Screen().ClipRect().Center(); + void CenterViewport(m2::PointD const & pt); - m_informationDisplay.setGlobalRect(m_navigator.Screen().GlobalRect()); - m_informationDisplay.setCenter(m2::PointD(MercatorBounds::XToLon(center.x), MercatorBounds::YToLat(center.y))); + void ShowRect(m2::RectD const & rect); - { - threads::MutexGuard guard(*m_renderQueue.renderState().m_mutex.get()); + void MemoryWarning(); - if (m_isBenchmarking) - { - m2::PointD const center = m_renderQueue.renderState().m_actualScreen.ClipRect().Center(); - m_informationDisplay.setScreen(m_renderQueue.renderState().m_actualScreen); - m_informationDisplay.setCenter(m2::PointD(MercatorBounds::XToLon(center.x), MercatorBounds::YToLat(center.y))); + void EnterBackground(); - if (m_benchmarks.empty()) - { - e->drawer()->screen()->beginFrame(); - e->drawer()->screen()->clear(m_bgColor); - m_informationDisplay.setDisplayRect(m2::RectI(0, 0, 100, 100)); - m_informationDisplay.enableRuler(false); - m_informationDisplay.doDraw(e->drawer().get()); - e->drawer()->screen()->endFrame(); - } - } - - if (m_renderQueue.renderState().m_actualTarget.get() != 0) - { - if (m_isBenchmarking - && !m_benchmarks.empty() - && m_informationDisplay.addBenchmarkInfo(m_benchmarks[m_currentBenchmark].first, - m_benchmarks[m_currentBenchmark].second, - m_renderQueue.renderState().m_duration)) - m_currentBenchmark++; - - e->drawer()->screen()->beginFrame(); - e->drawer()->screen()->clear(m_bgColor); - - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(false); - - OGLCHECK(glMatrixMode(GL_MODELVIEW)); - OGLCHECK(glPushMatrix()); - OGLCHECK(glTranslatef(-ptShift.x, -ptShift.y, 0)); - - ScreenBase currentScreen = m_navigator.Screen(); - - m_informationDisplay.enableEmptyModelMessage(m_renderQueue.renderStatePtr()->m_isEmptyModelActual); - - if (m_isBenchmarking) - currentScreen = m_renderQueue.renderState().m_actualScreen; - - pDrawer->screen()->blit(m_renderQueue.renderState().m_actualTarget, - m_renderQueue.renderState().m_actualScreen, - currentScreen); - - m_informationDisplay.doDraw(pDrawer); - - m_locationState.DrawMyPosition(*pDrawer, m_navigator.Screen()); - - e->drawer()->screen()->endFrame(); - - OGLCHECK(glPopMatrix()); - } - } - } - - void CenterViewport(m2::PointD const & pt) - { - m_navigator.CenterViewport(pt); - UpdateNow(); - } - - void ShowRect(m2::RectD const & rect) - { - m_navigator.SetFromRect(rect); - UpdateNow(); - } - - void MemoryWarning() - { - // clearing caches on memory warning. - m_model.ClearCaches(); - LOG(LINFO, ("MemoryWarning")); - } - - void EnterBackground() - { - // clearing caches on entering background. - m_model.ClearCaches(); - } - - void EnterForeground() - { - } + void EnterForeground(); /// @TODO refactor to accept point and min visible length - void CenterAndScaleViewport() - { - m2::PointD const pt = m_locationState.Position(); - m_navigator.CenterViewport(pt); - - m2::RectD clipRect = m_navigator.Screen().ClipRect(); - - double const xMinSize = 6 * max(m_locationState.ErrorRadius(), - MercatorBounds::ConvertMetresToX(pt.x, m_metresMinWidth)); - double const yMinSize = 6 * max(m_locationState.ErrorRadius(), - MercatorBounds::ConvertMetresToY(pt.y, m_metresMinWidth)); - - bool needToScale = false; - - if (clipRect.SizeX() < clipRect.SizeY()) - needToScale = clipRect.SizeX() > xMinSize * 3; - else - needToScale = clipRect.SizeY() > yMinSize * 3; - -/* if ((ClipRect.SizeX() < 3 * errorRadius) || (ClipRect.SizeY() < 3 * errorRadius)) - needToScale = true;*/ - - if (needToScale) - { - double const k = max(xMinSize / clipRect.SizeX(), - yMinSize / clipRect.SizeY()); - - clipRect.Scale(k); - m_navigator.SetFromRect(clipRect); - } - - UpdateNow(); - } + void CenterAndScaleViewport(); /// Show all model by it's world rect. - void ShowAll() - { - SetMaxWorldRect(); - UpdateNow(); - } + void ShowAll(); - void Repaint() - { - m_renderQueue.SetRedrawAll(); - AddRedrawCommandSure(); - Invalidate(); - } + void Repaint(); - void RepaintRect(m2::RectD const & rect) - { - threads::MutexGuard lock(*m_renderQueue.renderState().m_mutex.get()); - m2::RectD pxRect(0, 0, m_renderQueue.renderState().m_surfaceWidth, m_renderQueue.renderState().m_surfaceHeight); - m2::RectD glbRect; - m_navigator.Screen().PtoG(pxRect, glbRect); - if (glbRect.Intersect(rect)) - Repaint(); - } + void RepaintRect(m2::RectD const & rect); /// @name Drag implementation. //@{ - void StartDrag(DragEvent const & e) - { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; - m_navigator.StartDrag(pos, - GetPlatform().TimeInSec()); - -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.setDebugPoint(0, pos); -#endif - - Invalidate(); - } - void DoDrag(DragEvent const & e) - { - m_centeringMode = EDoNothing; - - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; - m_navigator.DoDrag(pos, GetPlatform().TimeInSec()); - -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.setDebugPoint(0, pos); -#endif - - Invalidate(); - } - - void StopDrag(DragEvent const & e) - { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; - - m_navigator.StopDrag(pos, - GetPlatform().TimeInSec(), - true); - -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.setDebugPoint(0, m2::PointD(0, 0)); -#endif - - UpdateNow(); - } - - void Move(double azDir, double factor) - { - m_navigator.Move(azDir, factor); - UpdateNow(); - } + void StartDrag(DragEvent const & e); + void DoDrag(DragEvent const & e); + void StopDrag(DragEvent const & e); + void Move(double azDir, double factor); //@} /// @name Scaling. //@{ - void ScaleToPoint(ScaleToPointEvent const & e) - { - m2::PointD const pt = (m_centeringMode == EDoNothing) - ? m_navigator.OrientPoint(e.Pt()) + m_renderQueue.renderState().coordSystemShift(true) - : m_navigator.Screen().PixelRect().Center(); - - m_navigator.ScaleToPoint(pt, e.ScaleFactor(), GetPlatform().TimeInSec()); - - UpdateNow(); - } - - void ScaleDefault(bool enlarge) - { - Scale(enlarge ? 1.5 : 2.0/3.0); - } - - void Scale(double scale) - { - m_navigator.Scale(scale); - UpdateNow(); - } - - void StartScale(ScaleEvent const & e) - { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()) + ptShift; - m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()) + ptShift; - - if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) - { - m2::PointD ptC = (pt1 + pt2) / 2; - m2::PointD ptDiff = m_navigator.Screen().PixelRect().Center() - ptC; - pt1 += ptDiff; - pt2 += ptDiff; - } - - m_navigator.StartScale(pt1, pt2, GetPlatform().TimeInSec()); - -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.setDebugPoint(0, pt1); - m_informationDisplay.setDebugPoint(1, pt2); -#endif - - Invalidate(); - } - - void DoScale(ScaleEvent const & e) - { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()) + ptShift; - m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()) + ptShift; - - if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) - { - m2::PointD ptC = (pt1 + pt2) / 2; - m2::PointD ptDiff = m_navigator.Screen().PixelRect().Center() - ptC; - pt1 += ptDiff; - pt2 += ptDiff; - } - - m_navigator.DoScale(pt1, pt2, GetPlatform().TimeInSec()); - -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.setDebugPoint(0, pt1); - m_informationDisplay.setDebugPoint(1, pt2); -#endif - - Invalidate(); - } - - void StopScale(ScaleEvent const & e) - { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()) + ptShift; - m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()) + ptShift; - - if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) - { - m2::PointD ptC = (pt1 + pt2) / 2; - m2::PointD ptDiff = m_navigator.Screen().PixelRect().Center() - ptC; - pt1 += ptDiff; - pt2 += ptDiff; - } - - m_navigator.StopScale(pt1, pt2, GetPlatform().TimeInSec()); - -#ifdef DRAW_TOUCH_POINTS - m_informationDisplay.setDebugPoint(0, m2::PointD(0, 0)); - m_informationDisplay.setDebugPoint(0, m2::PointD(0, 0)); -#endif - - UpdateNow(); - } + void ScaleToPoint(ScaleToPointEvent const & e); + void ScaleDefault(bool enlarge); + void Scale(double scale); + void StartScale(ScaleEvent const & e); + void DoScale(ScaleEvent const & e); + void StopScale(ScaleEvent const & e); //@} }; diff --git a/map/information_display.cpp b/map/information_display.cpp index 6d86a0ceed..b7f22232fd 100644 --- a/map/information_display.cpp +++ b/map/information_display.cpp @@ -459,33 +459,26 @@ void InformationDisplay::enableBenchmarkInfo(bool doEnable) bool InformationDisplay::addBenchmarkInfo(string const & name, m2::RectD const & globalRect, double frameDuration) { - if (frameDuration == 0) - return false; - if ((m_benchmarkInfo.empty()) - ||(m_benchmarkInfo.back().m_duration != frameDuration)) - { - BenchmarkInfo info; - info.m_name = name; - info.m_duration = frameDuration; - info.m_rect = globalRect; - m_benchmarkInfo.push_back(info); + BenchmarkInfo info; + info.m_name = name; + info.m_duration = frameDuration; + info.m_rect = globalRect; + m_benchmarkInfo.push_back(info); - string deviceID = GetPlatform().DeviceID(); - transform(deviceID.begin(), deviceID.end(), deviceID.begin(), ::tolower); +/* string deviceID = GetPlatform().DeviceID(); + transform(deviceID.begin(), deviceID.end(), deviceID.begin(), ::tolower); - ofstream fout(GetPlatform().WritablePathForFile(deviceID + "_benchmark_results.txt").c_str(), ios::app); - fout << GetPlatform().DeviceID() << " " - << VERSION_STRING << " " - << info.m_name << " " - << info.m_rect.minX() << " " - << info.m_rect.minY() << " " - << info.m_rect.maxX() << " " - << info.m_rect.maxY() << " " - << info.m_duration << endl; - - return true; - } - return false; + ofstream fout(GetPlatform().WritablePathForFile(deviceID + "_benchmark_results.txt").c_str(), ios::app); + fout << GetPlatform().DeviceID() << " " + << VERSION_STRING << " " + << info.m_name << " " + << info.m_rect.minX() << " " + << info.m_rect.minY() << " " + << info.m_rect.maxX() << " " + << info.m_rect.maxY() << " " + << info.m_duration << endl; +*/ + return true; } void InformationDisplay::drawBenchmarkInfo(DrawerYG * pDrawer) @@ -500,7 +493,7 @@ void InformationDisplay::drawBenchmarkInfo(DrawerYG * pDrawer) yg::maxDepth, false); - for (unsigned i = 0; i < m_benchmarkInfo.size(); ++i) + for (unsigned i = max(0, (int)m_benchmarkInfo.size() - 5); i < m_benchmarkInfo.size(); ++i) { ostringstream out; m2::RectD const & r = m_benchmarkInfo[i].m_rect; diff --git a/map/map.pro b/map/map.pro index 9fee22cc98..54881f20c7 100644 --- a/map/map.pro +++ b/map/map.pro @@ -23,6 +23,7 @@ HEADERS += \ information_display.hpp \ settings.hpp \ location_state.hpp \ + benchmark_provider.hpp SOURCES += \ feature_vec_model.cpp \ @@ -35,6 +36,7 @@ SOURCES += \ information_display.cpp \ settings.cpp \ location_state.cpp \ + benchmark_provider.cpp !iphone*:!bada* { HEADERS += qgl_render_context.hpp diff --git a/map/render_queue.cpp b/map/render_queue.cpp index e8cd2f2655..0b4f4865db 100644 --- a/map/render_queue.cpp +++ b/map/render_queue.cpp @@ -69,6 +69,11 @@ void RenderQueue::AddWindowHandle(shared_ptr const & windowHandle) m_routine->addWindowHandle(windowHandle); } +void RenderQueue::addRenderCommandFinishedFn(renderCommandFinishedFn fn) +{ + m_routine->addRenderCommandFinishedFn(fn); +} + void RenderQueue::OnSize(size_t w, size_t h) { m_renderState->onSize(w, h); diff --git a/map/render_queue.hpp b/map/render_queue.hpp index 179334a8fb..96a7254942 100644 --- a/map/render_queue.hpp +++ b/map/render_queue.hpp @@ -30,6 +30,9 @@ private: RenderQueueRoutine * m_routine; public: + + typedef RenderQueueRoutine::renderCommandFinishedFn renderCommandFinishedFn; + /// constructor. RenderQueue(string const & skinName, bool isMultiSampled, @@ -54,6 +57,9 @@ public: /// add window handle to notify when rendering operation finishes void AddWindowHandle(shared_ptr const & windowHandle); + + void addRenderCommandFinishedFn(renderCommandFinishedFn fn); + /// process resize request void OnSize(size_t w, size_t h); /// copy primary render state diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 56cf302d76..fd10a54642 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -437,6 +437,9 @@ void RenderQueueRoutine::Do() } invalidate(); + + callRenderCommandFinishedFns(); + } } @@ -518,3 +521,15 @@ void RenderQueueRoutine::enterForeground() m_threadDrawer->screen()->enterForeground(); } +void RenderQueueRoutine::addRenderCommandFinishedFn(renderCommandFinishedFn fn) +{ + m_renderCommandFinishedFns.push_back(fn); +} + +void RenderQueueRoutine::callRenderCommandFinishedFns() +{ + if (!m_renderCommandFinishedFns.empty()) + for (list::const_iterator it = m_renderCommandFinishedFns.begin(); it != m_renderCommandFinishedFns.end(); ++it) + (*it)(); +} + diff --git a/map/render_queue_routine.hpp b/map/render_queue_routine.hpp index 0ae777bde9..1691e466b7 100644 --- a/map/render_queue_routine.hpp +++ b/map/render_queue_routine.hpp @@ -41,6 +41,7 @@ class RenderQueueRoutine : public threads::IRoutine public: typedef function, ScreenBase const &, m2::RectD const &, int)> render_fn_t; + typedef function renderCommandFinishedFn; private: @@ -85,6 +86,10 @@ private: void waitForRenderCommand(list > & cmdList, threads::ConditionGuard & guard); + list m_renderCommandFinishedFns; + + void callRenderCommandFinishedFns(); + public: RenderQueueRoutine(shared_ptr const & renderState, string const & skinName, @@ -124,4 +129,6 @@ public: void enterBackground(); /// recreate all necessary opengl resources and prepare to run in foreground. void enterForeground(); + /// add render-command-finished callback + void addRenderCommandFinishedFn(renderCommandFinishedFn fn); }; diff --git a/qt/draw_widget.hpp b/qt/draw_widget.hpp index 3b21731e46..01ea57a50f 100644 --- a/qt/draw_widget.hpp +++ b/qt/draw_widget.hpp @@ -30,7 +30,7 @@ namespace qt typedef model::FeaturesFetcher model_t; - FrameWork m_framework; + FrameWork m_framework; bool m_isDrag; diff --git a/storage/storage.cpp b/storage/storage.cpp index e968f12a0f..63e7e6694c 100644 --- a/storage/storage.cpp +++ b/storage/storage.cpp @@ -48,7 +48,7 @@ namespace storage } //////////////////////////////////////////////////////////////////////////// - void Storage::Init(TAddMapFunction addFunc, TRemoveMapFunction removeFunc, TUpdateRectFunction updateRectFunc) + void Storage::Init(TAddMapFunction addFunc, TRemoveMapFunction removeFunc, TUpdateRectFunction updateRectFunc, TEnumMapsFunction enumMapsFunc) { m_currentVersion = static_cast(Version::BUILD); @@ -56,18 +56,16 @@ namespace storage m_removeMap = removeFunc; m_updateRect = updateRectFunc; - // activate all downloaded maps - Platform & p = GetPlatform(); Platform::FilesList filesList; - string const dataPath = p.WritableDir(); - p.GetFilesInDir(dataPath, "*" DATA_FILE_EXTENSION, filesList); + enumMapsFunc(filesList); + for (Platform::FilesList::iterator it = filesList.begin(); it != filesList.end(); ++it) { // simple way to avoid continuous crashes with invalid data files try { - m_addMap(dataPath + *it); + m_addMap(GetPlatform().WritableDir() + *it); } catch (std::exception const & e) { - FileWriter::DeleteFileX(dataPath + *it); + FileWriter::DeleteFileX(GetPlatform().WritableDir() + *it); LOG(LWARNING, (e.what(), "while adding file", *it, "so this file is deleted")); } } @@ -78,7 +76,7 @@ namespace storage if (found == filesList.end()) { try { - m_addMap(p.ReadPathForFile(WORLD_FILE_NAME DATA_FILE_EXTENSION)); + m_addMap(GetPlatform().ReadPathForFile(WORLD_FILE_NAME DATA_FILE_EXTENSION)); } catch (std::exception const & e) { LOG(LWARNING, (e.what(), "while adding world data file")); diff --git a/storage/storage.hpp b/storage/storage.hpp index fa626fe358..a4ab27f8f8 100644 --- a/storage/storage.hpp +++ b/storage/storage.hpp @@ -89,9 +89,13 @@ namespace storage /// @name Communicate with Framework //@{ + public: typedef boost::function TAddMapFunction; typedef boost::function TRemoveMapFunction; typedef boost::function TUpdateRectFunction; + typedef boost::function TEnumMapsFunction; + private: + TAddMapFunction m_addMap; TRemoveMapFunction m_removeMap; TUpdateRectFunction m_updateRect; @@ -106,7 +110,7 @@ namespace storage Storage() {} /// Adds all locally downloaded maps to the model - void Init(TAddMapFunction addFunc, TRemoveMapFunction removeFunc, TUpdateRectFunction updateRectFunc); + void Init(TAddMapFunction addFunc, TRemoveMapFunction removeFunc, TUpdateRectFunction updateRectFunc, TEnumMapsFunction enumMapFunction); /// @name Called from DownloadManager //@{