From 202ff7325368bae41b51f484c907d29973568b88 Mon Sep 17 00:00:00 2001 From: rachytski Date: Sun, 3 Jul 2011 14:22:20 +0300 Subject: [PATCH] Initial implementation of tile rendering. --- base/base.pro | 7 +- base/base_tests/base_tests.pro | 3 +- base/base_tests/mru_cache_test.cpp | 31 ++ ...t_pool_test.cpp => threaded_list_test.cpp} | 25 +- base/mru_cache.hpp | 124 +++++ base/object_pool.hpp | 91 ---- base/threaded_container.cpp | 22 + base/threaded_container.hpp | 24 + base/threaded_list.hpp | 101 ++++ map/framework.cpp | 238 ++++----- map/framework.hpp | 4 +- map/render_queue.cpp | 120 ++--- map/render_queue.hpp | 61 ++- map/render_queue_routine.cpp | 455 +++--------------- map/render_queue_routine.hpp | 59 +-- qt/widgets.cpp | 1 - qt_tstfrm/tstwidgets.cpp | 1 - std/functional.hpp | 1 + yg/blitter.cpp | 18 +- yg/blitter.hpp | 4 +- yg/geometry_batcher.cpp | 6 +- yg/overlay_renderer.cpp | 15 +- yg/overlay_renderer.hpp | 4 + yg/render_state_updater.cpp | 47 +- yg/resource_manager.cpp | 68 ++- yg/resource_manager.hpp | 37 +- yg/skin_page.cpp | 8 +- yg/texture.hpp | 14 + yg/tile.hpp | 20 +- yg/tile_cache.cpp | 26 +- yg/tile_cache.hpp | 29 +- yg/tiler.cpp | 39 +- yg/tiler.hpp | 9 +- yg/yg_tests/skin_loader_test.cpp | 2 +- yg/yg_tests/skin_test.cpp | 2 +- 35 files changed, 809 insertions(+), 907 deletions(-) create mode 100644 base/base_tests/mru_cache_test.cpp rename base/base_tests/{object_pool_test.cpp => threaded_list_test.cpp} (73%) create mode 100644 base/mru_cache.hpp delete mode 100644 base/object_pool.hpp create mode 100644 base/threaded_container.cpp create mode 100644 base/threaded_container.hpp create mode 100644 base/threaded_list.hpp diff --git a/base/base.pro b/base/base.pro index 355dc248cd..ce2cfd284f 100644 --- a/base/base.pro +++ b/base/base.pro @@ -24,7 +24,8 @@ SOURCES += \ runner.cpp \ timer.cpp \ internal/message.cpp \ - exception.cpp + exception.cpp \ + threaded_container.cpp HEADERS += \ SRC_FIRST.hpp \ @@ -66,4 +67,6 @@ HEADERS += \ buffer_vector.hpp \ array_adapters.hpp \ runner.hpp \ - object_pool.hpp + mru_cache.hpp \ + threaded_container.hpp \ + threaded_list.hpp diff --git a/base/base_tests/base_tests.pro b/base/base_tests/base_tests.pro index 2987046bc6..b1c74d7eca 100644 --- a/base/base_tests/base_tests.pro +++ b/base/base_tests/base_tests.pro @@ -31,6 +31,7 @@ SOURCES += \ buffer_vector_test.cpp \ assert_test.cpp \ timer_test.cpp \ - object_pool_test.cpp\ + mru_cache_test.cpp \ + threaded_list_test.cpp HEADERS += diff --git a/base/base_tests/mru_cache_test.cpp b/base/base_tests/mru_cache_test.cpp new file mode 100644 index 0000000000..323b0438d1 --- /dev/null +++ b/base/base_tests/mru_cache_test.cpp @@ -0,0 +1,31 @@ +#include "../../base/SRC_FIRST.hpp" +#include "../../testing/testing.hpp" + +#include "../mru_cache.hpp" + +UNIT_TEST(MRUCache_Test) +{ + my::MRUCache m(4); + + CHECK(m.HasElem(1) == false, ()); + + m.Add(1, 2, 1); + + CHECK(m.HasElem(1) == true, ()); + CHECK(m.Find(1, false) == 2, ()); + + m.Add(2, 4, 2); + + CHECK(m.HasElem(2) == true, ()); + CHECK(m.Find(2, false) == 4, ()); + + m.Touch(1); + + m.Add(3, 9, 2); + + CHECK(m.HasElem(3) == true, ()); + CHECK(m.Find(3, false) == 9, ()); + + CHECK(m.HasElem(2) == false, ()); + CHECK(m.HasElem(1) == true, ()); +} diff --git a/base/base_tests/object_pool_test.cpp b/base/base_tests/threaded_list_test.cpp similarity index 73% rename from base/base_tests/object_pool_test.cpp rename to base/base_tests/threaded_list_test.cpp index ff559f999f..3d6944ba86 100644 --- a/base/base_tests/object_pool_test.cpp +++ b/base/base_tests/threaded_list_test.cpp @@ -1,7 +1,7 @@ #include "../../base/SRC_FIRST.hpp" #include "../../testing/testing.hpp" -#include "../object_pool.hpp" +#include "../threaded_list.hpp" #include "../thread.hpp" #include "../../base/logging.hpp" @@ -9,19 +9,19 @@ struct ProcessorThread : public threads::IRoutine { - ObjectPool * m_p; + ThreadedList * m_p; int m_data; list * m_res; int m_id; - ProcessorThread(ObjectPool * p, list * res, int id) : m_p(p), m_res(res), m_id(id) + ProcessorThread(ThreadedList * p, list * res, int id) : m_p(p), m_res(res), m_id(id) {} virtual void Do() { while (!m_p->IsCancelled()) { - int res = m_p->Reserve(); + int res = m_p->Front(true); m_res->push_back(res); LOG(LINFO, (m_id, " thread got ", res)); threads::Sleep(10); @@ -30,13 +30,12 @@ struct ProcessorThread : public threads::IRoutine } }; -UNIT_TEST(ObjectPool) +UNIT_TEST(ThreadedList) { list l; list res; - ObjectPool p; - p.Add(l); + ThreadedList p; threads::Thread t0; t0.Create(new ProcessorThread(&p, &res, 0)); @@ -47,14 +46,14 @@ UNIT_TEST(ObjectPool) threads::Thread t2; t2.Create(new ProcessorThread(&p, &res, 2)); - p.Free(0); - threads::Sleep(200); + p.PushBack(0); + my::sleep(200); - p.Free(1); - threads::Sleep(200); + p.PushBack(1); + my::sleep(200); - p.Free(2); - threads::Sleep(200); + p.PushBack(2); + my::sleep(200); TEST_EQUAL(res.front(), 0, ()); res.pop_front(); diff --git a/base/mru_cache.hpp b/base/mru_cache.hpp new file mode 100644 index 0000000000..c6cb03f934 --- /dev/null +++ b/base/mru_cache.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include "../std/unordered_map.hpp" +#include "assert.hpp" + +namespace my +{ + template + struct MRUCacheValueTraits + { + static void Evict(TValue & val){} + }; + + template > + class MRUCache + { + public: + typedef MRUCache this_type; + private: + MRUCache(this_type const & c); + this_type & operator= (this_type const &); + + typedef list list_t; + + struct MapEntry + { + ValueT m_value; + size_t m_weight; + typename list_t::iterator m_it; + }; + + typedef unordered_map map_t; + + map_t m_map; + list_t m_list; + int m_curWeight; + int m_maxWeight; + + public: + explicit MRUCache(size_t maxWeight) + : m_curWeight(0), m_maxWeight(maxWeight) + {} + + bool HasElem(KeyT const & key) + { + return m_map.find(key) != m_map.end(); + } + + ValueT const & Find(KeyT const & key, bool DoTouch = true) + { + typename map_t::iterator it = m_map.find(key); + CHECK(it != m_map.end(), ()); + if (DoTouch) + { + typename list_t::iterator listIt = it->second.m_it; + KeyT k = *listIt; + m_list.erase(listIt); + m_list.push_front(k); + it->second.m_it = m_list.begin(); + } + return it->second.m_value; + } + + void Touch(KeyT const & key) + { + if (!HasElem(key)) + return; + typename map_t::iterator it = m_map.find(key); + CHECK(it != m_map.end(), ()); + + typename list_t::iterator listIt = it->second.m_it; + KeyT k = *listIt; + m_list.erase(listIt); + m_list.push_front(k); + it->second.m_it = m_list.begin(); + } + + void Remove(KeyT const & key) + { + typename map_t::iterator it = m_map.find(key); + + if (it != m_map.end()) + { + m_curWeight -= it->second.m_weight; + m_list.erase(it->second.m_it); + ValueTraitsT::Evict(it->second.m_value); + m_map.erase(it); + } + } + + void Add(KeyT const & key, ValueT const & val, size_t weight) + { + if (HasElem(key)) + Remove(key); + + while (m_curWeight + weight > m_maxWeight) + { + if (m_list.empty()) + return; + KeyT k = m_list.back(); + m_list.pop_back(); + m_curWeight -= m_map[k].m_weight; + ValueTraitsT::Evict(m_map[k].m_value); + m_map.erase(k); + } + + m_list.push_front(key); + m_map[key].m_weight = weight; + m_map[key].m_value = val; + m_map[key].m_it = m_list.begin(); + m_curWeight += weight; + } + + void Clear() + { + for (typename map_t::iterator it = m_map.begin(); it != m_map.end(); ++it) + ValueTraitsT::Evict(it->second); + + m_map.clear(); + m_list.clear(); + m_curWeight = 0; + } + }; +} diff --git a/base/object_pool.hpp b/base/object_pool.hpp deleted file mode 100644 index 1434d2f814..0000000000 --- a/base/object_pool.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include "condition.hpp" -#include "../std/list.hpp" - -/// multithreaded object pool. -/// implements condition waiting scheme, to save the CPU cycles. -template -class ObjectPool -{ -private: - - list m_List; - - threads::Condition m_Cond; - - bool m_IsCancelled; - -public: - - ObjectPool() : m_IsCancelled(false) - {} - - void Add(list const & l) - { - for (typename list::const_iterator it = l.begin(); it != l.end(); ++it) - Free(*it); - } - - size_t Size() - { - threads::ConditionGuard Guard(m_Cond); - return m_List.size(); - } - - void Add(T const & t) - { - Free(t); - } - - void Clear() - { - threads::ConditionGuard Guard(m_Cond); - m_List.clear(); - } - - T const Reserve() - { - threads::ConditionGuard Guard(m_Cond); - - while (m_List.empty()) - { - if (m_IsCancelled) - break; - m_Cond.Wait(); - } - - if (m_IsCancelled) - return T(); - - T res = m_List.front(); - m_List.pop_front(); - return res; - } - - /// cancel all waiting requests - void Cancel() - { - m_IsCancelled = true; - m_Cond.Signal(true); - } - - bool IsCancelled() const - { - return m_IsCancelled; - } - - void Free(T const & t) - { - threads::ConditionGuard Guard(m_Cond); - - bool DoSignal = m_List.empty(); - - m_List.push_back(t); - - if (DoSignal) - m_Cond.Signal(); //< this doesn't release the mutex associated with m_cond, - - /// we should return as quickly as possible to minimize "waked threads" waiting time - } -}; diff --git a/base/threaded_container.cpp b/base/threaded_container.cpp new file mode 100644 index 0000000000..0f3b371312 --- /dev/null +++ b/base/threaded_container.cpp @@ -0,0 +1,22 @@ +#include "threaded_container.hpp" + +ThreadedContainer::ThreadedContainer() + : m_WaitTime(0), m_IsCancelled(false) +{ +} + +void ThreadedContainer::Cancel() +{ + m_IsCancelled = true; + m_Cond.Signal(true); +} + +bool ThreadedContainer::IsCancelled() const +{ + return m_IsCancelled; +} + +double ThreadedContainer::WaitTime() const +{ + return m_WaitTime; +} diff --git a/base/threaded_container.hpp b/base/threaded_container.hpp new file mode 100644 index 0000000000..dd611b7965 --- /dev/null +++ b/base/threaded_container.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "condition.hpp" +#include "timer.hpp" + +struct ThreadedContainer +{ +protected: + + my::Timer m_Timer; + double m_WaitTime; + + threads::Condition m_Cond; + bool m_IsCancelled; + +public: + + ThreadedContainer(); + + void Cancel(); + bool IsCancelled() const; + + double WaitTime() const; +}; diff --git a/base/threaded_list.hpp b/base/threaded_list.hpp new file mode 100644 index 0000000000..7ec0c828f9 --- /dev/null +++ b/base/threaded_list.hpp @@ -0,0 +1,101 @@ +#pragma once + +#include "condition.hpp" +#include "../std/list.hpp" + +#include "threaded_container.hpp" + +template +class ThreadedList : public ThreadedContainer +{ +private: + + list m_list; + +public: + + void PushBack(T const & t) + { + threads::ConditionGuard g(m_Cond); + + bool doSignal = m_list.empty(); + + m_list.push_back(t); + + if (doSignal) + m_Cond.Signal(); + } + + void PushFront(T const & t) + { + threads::ConditionGuard g(m_Cond); + + bool doSignal = m_list.empty(); + + m_list.push_front(t); + + if (doSignal) + m_Cond.Signal(); + } + + bool WaitNonEmpty() + { + double StartWaitTime = m_Timer.ElapsedSeconds(); + + while (m_list.empty()) + { + if (IsCancelled()) + break; + m_Cond.Wait(); + } + + m_WaitTime += m_Timer.ElapsedSeconds() - StartWaitTime; + + if (IsCancelled()) + return true; + + return false; + } + + T const Front(bool doPop) + { + threads::ConditionGuard g(m_Cond); + + if (WaitNonEmpty()) + return T(); + + T res = m_list.front(); + + if (doPop) + m_list.pop_front(); + + return res; + } + + T const Back(bool doPop) + { + threads::ConditionGuard g(m_Cond); + + if (WaitNonEmpty()) + return T(); + + T res = m_list.back(); + + if (doPop) + m_list.pop_back(); + + return res; + } + + size_t Size() + { + threads::ConditionGuard g(m_Cond); + return m_list.size(); + } + + void Clear() + { + threads::ConditionGuard g(m_Cond); + m_list.clear(); + } +}; diff --git a/map/framework.cpp b/map/framework.cpp index 6da642ab46..e717796955 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -56,13 +56,11 @@ namespace fwork ScreenBase const & convertor, shared_ptr const & paintEvent, int scaleLevel, - shared_ptr const & renderState, yg::GlyphCache * glyphCache) : m_rect(r), m_convertor(convertor), m_paintEvent(paintEvent), m_zoom(scaleLevel), - m_renderState(renderState), m_glyphCache(glyphCache) #ifdef PROFILER_DRAWING , m_drawCount(0) @@ -175,8 +173,6 @@ namespace fwork sort(rules.begin(), rules.end(), less_depth()); - m_renderState->m_isEmptyModelCurrent = false; - shared_ptr ptr(new di::DrawInfo( f.GetPreferredDrawableName(languages::GetCurrentPriorities()), f.GetRoadNumber(), @@ -271,19 +267,19 @@ namespace fwork } } -template +/*template void FrameWork::AddRedrawCommandSure() { - m_renderQueue.AddCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), m_navigator.Screen()); -} - template +}*/ + +/* 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 & file) @@ -340,9 +336,6 @@ void FrameWork::AddRedrawCommandSure() m_isBenchmarkInitialized(false), m_bgColor(0xEE, 0xEE, 0xDD, 0xFF), m_renderQueue(GetPlatform().SkinName(), - GetPlatform().IsMultiSampled() && yg::gl::g_isMultisamplingSupported, - GetPlatform().DoPeriodicalUpdate(), - GetPlatform().PeriodicalUpdateInterval(), GetPlatform().IsBenchmarking(), GetPlatform().ScaleEtalonSize(), m_bgColor), @@ -401,7 +394,7 @@ void FrameWork::AddRedrawCommandSure() template void FrameWork::BenchmarkCommandFinished() { - double duration = m_renderQueue.renderState().m_duration; +/* double duration = m_renderQueue.renderState().m_duration; if (duration > m_maxDuration) { m_maxDuration = duration; @@ -418,13 +411,13 @@ void FrameWork::AddRedrawCommandSure() if (m_benchmarkResults.size() > 100) SaveBenchmarkResults(); - NextBenchmarkCommand(); +// NextBenchmarkCommand();*/ } template void FrameWork::SaveBenchmarkResults() { - string resultsPath; +/* string resultsPath; Settings::Get("BenchmarkResults", resultsPath); LOG(LINFO, (resultsPath)); ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); @@ -442,16 +435,17 @@ void FrameWork::AddRedrawCommandSure() << m_benchmarkResults[i].m_time << endl; } - m_benchmarkResults.clear(); + m_benchmarkResults.clear();*/ } template void FrameWork::SendBenchmarkResults() { - //ofstream fout(GetPlatform().WritablePathForFile("benchmarks/results.txt").c_str(), ios::app); - //fout << "[COMPLETED]"; - //fout.close(); - /// @todo send to server for adding to statistics graphics and delete results file +// ofstream fout(GetPlatform().WritablePathForFile("benchmarks/results.txt").c_str(), ios::app); +// fout << "[COMPLETED]"; +// fout.close(); + /// send to server for adding to statistics graphics + /// and delete results file } template @@ -474,7 +468,7 @@ void FrameWork::AddRedrawCommandSure() fout << "START " << m_startTime << endl; } - template +/* template void FrameWork::NextBenchmarkCommand() { if ((m_benchmarks[m_curBenchmark].m_provider->hasRect()) || (++m_curBenchmark < m_benchmarks.size())) @@ -491,7 +485,7 @@ void FrameWork::AddRedrawCommandSure() LOG(LINFO, ("Bechmarks took ", m_benchmarksTimer.ElapsedSeconds(), " seconds to complete")); } } - +*/ struct PathAppender { string const & m_path; @@ -676,11 +670,11 @@ void FrameWork::AddRedrawCommandSure() m_curBenchmark = 0; - m_renderQueue.addRenderCommandFinishedFn(bind(&this_type::BenchmarkCommandFinished, this)); + m_renderQueue.AddRenderCommandFinishedFn(bind(&this_type::BenchmarkCommandFinished, this)); m_benchmarksTimer.Reset(); MarkBenchmarkResultsStart(); - NextBenchmarkCommand(); +// NextBenchmarkCommand(); Invalidate(); } @@ -691,7 +685,7 @@ void FrameWork::AddRedrawCommandSure() shared_ptr const & resourceManager) { m_resourceManager = resourceManager; - m_renderQueue.initializeGL(primaryContext, m_resourceManager, GetPlatform().VisualScale()); + m_renderQueue.InitializeGL(primaryContext, m_resourceManager, GetPlatform().VisualScale()); } template @@ -749,7 +743,7 @@ void FrameWork::AddRedrawCommandSure() template void FrameWork::UpdateNow() { - AddRedrawCommand(); +// AddRedrawCommand(); Invalidate(); } @@ -782,13 +776,9 @@ void FrameWork::AddRedrawCommandSure() if (w < 2) w = 2; if (h < 2) h = 2; - m_renderQueue.OnSize(w, h); + m_informationDisplay.setDisplayRect(m2::RectI(m2::PointI(0, 0), m2::PointU(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); + m_navigator.OnSize(0, 0, w, h); if ((m_isBenchmarking) && (!m_isBenchmarkInitialized)) { @@ -808,7 +798,8 @@ void FrameWork::AddRedrawCommandSure() void FrameWork::SetRedrawEnabled(bool isRedrawEnabled) { m_isRedrawEnabled = isRedrawEnabled; - AddRedrawCommand(); + Invalidate(); +// AddRedrawCommand(); } /// respond to device orientation changes @@ -823,8 +814,7 @@ void FrameWork::AddRedrawCommandSure() template double FrameWork::GetCurrentScale() const { - m2::PointD textureCenter(m_renderQueue.renderState().m_textureWidth / 2, - m_renderQueue.renderState().m_textureHeight / 2); + m2::PointD textureCenter(m_navigator.Screen().PixelRect().Center()); m2::RectD glbRect; unsigned scaleEtalonSize = GetPlatform().ScaleEtalonSize(); @@ -843,8 +833,7 @@ void FrameWork::AddRedrawCommandSure() m2::RectD const & selectRect, int scaleLevel) { - fwork::DrawProcessor doDraw(selectRect, screen, e, scaleLevel, m_renderQueue.renderStatePtr(), e->drawer()->screen()->glyphCache()); - m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = true; + fwork::DrawProcessor doDraw(selectRect, screen, e, scaleLevel, e->drawer()->screen()->glyphCache()); try { @@ -868,8 +857,8 @@ void FrameWork::AddRedrawCommandSure() } catch (redraw_operation_cancelled const &) { - m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = false; - m_renderQueue.renderStatePtr()->m_isEmptyModelActual = false; +// m_renderQueue.renderStatePtr()->m_isEmptyModelCurrent = false; +// m_renderQueue.renderStatePtr()->m_isEmptyModelActual = false; } if (m_navigator.Update(m_timer.ElapsedSeconds())) @@ -887,7 +876,7 @@ void FrameWork::AddRedrawCommandSure() m_informationDisplay.setScreen(m_navigator.Screen()); - m_informationDisplay.setDebugInfo(m_renderQueue.renderState().m_duration, my::rounds(GetCurrentScale())); +// m_informationDisplay.setDebugInfo(m_renderQueue.renderState().m_duration, my::rounds(GetCurrentScale())); m_informationDisplay.enableRuler(!IsEmptyModel()); @@ -896,96 +885,69 @@ void FrameWork::AddRedrawCommandSure() m_informationDisplay.setGlobalRect(m_navigator.Screen().GlobalRect()); m_informationDisplay.setCenter(m2::PointD(MercatorBounds::XToLon(center.x), MercatorBounds::YToLat(center.y))); +/* if (m_isBenchmarking) { - threads::MutexGuard guard(*m_renderQueue.renderState().m_mutex.get()); + 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_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) + if (!m_isBenchmarkInitialized) { 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_tiler.seed(currentScreen, m_tileSize); - - while (m_tiler.hasTile()) - { - yg::Tiler::RectInfo ri = m_tiler.nextTile(); - - m_renderQueue.tileCache().lock(); - if (m_renderQueue.tileCache().hasTile(ri)) - { - yg::Tile tile = m_renderQueue.tileCache().getTile(ri); - m2::RectD pxRect; - currentScreen.GtoP(ri.m_rect, pxRect); - - pDrawer->screen()->drawRectangle(pxRect, yg::Color(255, 0, 0, 64), yg::maxDepth - 1); - - m_renderQueue.tileCache().unlock(); -// pDrawer->screen()->blit(tile.m_renderTarget, tile.m_tileScreen, currentScreen); - } - else - { - m_renderQueue.tileCache().unlock(); -// m_renderQueue.addTileRenderCmd(); - m2::RectD pxRect; - currentScreen.GtoP(ri.m_rect, pxRect); - pDrawer->screen()->drawRectangle(pxRect, yg::Color(0, 0, 255, 192 - (ri.m_distance * 3 > 255 ? 255 : ri.m_distance * 3) / (255.0 / 192)), yg::maxDepth - 2); - } - } -*/ - - m_informationDisplay.doDraw(pDrawer); - -/* m_renderQueue.renderState().m_actualInfoLayer->draw( - pDrawer->screen().get(), - m_renderQueue.renderState().m_actualScreen.PtoGMatrix() * currentScreen.GtoPMatrix());*/ - - m_locationState.DrawMyPosition(*pDrawer, m_navigator.Screen()); - + m_informationDisplay.setDisplayRect(m2::RectI(0, 0, 100, 100)); + m_informationDisplay.enableRuler(false); + m_informationDisplay.doDraw(e->drawer().get()); e->drawer()->screen()->endFrame(); + } + }*/ - OGLCHECK(glPopMatrix()); + e->drawer()->screen()->beginFrame(); + e->drawer()->screen()->clear(m_bgColor); + + 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_tiler.seed(currentScreen, m_tileSize); + + while (m_tiler.hasTile()) + { + yg::Tiler::RectInfo ri = m_tiler.nextTile(); + + m_renderQueue.TileCache().lock(); + + LOG(LINFO, ("Checking TileRect:", ri.m_rect)); + + if (m_renderQueue.TileCache().hasTile(ri)) + { + yg::Tile tile = m_renderQueue.TileCache().getTile(ri); + m_renderQueue.TileCache().unlock(); + pDrawer->screen()->blit(tile.m_renderTarget, tile.m_tileScreen, currentScreen, true); } else { - e->drawer()->screen()->beginFrame(); - e->drawer()->screen()->clear(m_bgColor); - e->drawer()->screen()->endFrame(); + m_renderQueue.TileCache().unlock(); + m_renderQueue.AddCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), ri, m_tiler.seqNum()); } } + + m_informationDisplay.doDraw(pDrawer); + +/* m_renderQueue.renderState().m_actualInfoLayer->draw( + pDrawer->screen().get(), + m_renderQueue.renderState().m_actualScreen.PtoGMatrix() * currentScreen.GtoPMatrix());*/ + + m_locationState.DrawMyPosition(*pDrawer, m_navigator.Screen()); + + e->drawer()->screen()->endFrame(); } template @@ -1076,19 +1038,14 @@ void FrameWork::AddRedrawCommandSure() template void FrameWork::Repaint() { - m_renderQueue.SetRedrawAll(); - AddRedrawCommandSure(); +// 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)) + if (m_navigator.Screen().GlobalRect().IsIntersect(rect)) Repaint(); } @@ -1097,8 +1054,7 @@ void FrameWork::AddRedrawCommandSure() template void FrameWork::StartDrag(DragEvent const & e) { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; + m2::PointD pos = m_navigator.OrientPoint(e.Pos()); m_navigator.StartDrag(pos, m_timer.ElapsedSeconds()); #ifdef DRAW_TOUCH_POINTS @@ -1113,9 +1069,7 @@ void FrameWork::AddRedrawCommandSure() { m_centeringMode = EDoNothing; - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; + m2::PointD pos = m_navigator.OrientPoint(e.Pos()); m_navigator.DoDrag(pos, m_timer.ElapsedSeconds()); #ifdef DRAW_TOUCH_POINTS @@ -1128,9 +1082,7 @@ void FrameWork::AddRedrawCommandSure() template void FrameWork::StopDrag(DragEvent const & e) { - m2::PointD ptShift = m_renderQueue.renderState().coordSystemShift(true); - - m2::PointD pos = m_navigator.OrientPoint(e.Pos()) + ptShift; + m2::PointD pos = m_navigator.OrientPoint(e.Pos()); m_navigator.StopDrag(pos, m_timer.ElapsedSeconds(), true); @@ -1156,7 +1108,7 @@ void FrameWork::AddRedrawCommandSure() 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.OrientPoint(e.Pt()) : m_navigator.Screen().PixelRect().Center(); m_navigator.ScaleToPoint(pt, e.ScaleFactor(), m_timer.ElapsedSeconds()); @@ -1181,10 +1133,8 @@ void FrameWork::AddRedrawCommandSure() 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; + m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()); + m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()); if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) { @@ -1207,10 +1157,8 @@ void FrameWork::AddRedrawCommandSure() 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; + m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()); + m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()); if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) { @@ -1233,10 +1181,8 @@ void FrameWork::AddRedrawCommandSure() 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; + m2::PointD pt1 = m_navigator.OrientPoint(e.Pt1()); + m2::PointD pt2 = m_navigator.OrientPoint(e.Pt2()); if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly)) { diff --git a/map/framework.hpp b/map/framework.hpp index f63af9cd74..fa88fb1694 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -70,7 +70,6 @@ namespace fwork vector m_keys; int m_zoom; - shared_ptr m_renderState; yg::GlyphCache * m_glyphCache; #ifdef PROFILER_DRAWING @@ -89,7 +88,6 @@ namespace fwork ScreenBase const & convertor, shared_ptr const & paintEvent, int scaleLevel, - shared_ptr const & renderState, yg::GlyphCache * glyphCache); bool operator() (FeatureType const & f); @@ -174,7 +172,7 @@ class FrameWork yg::Tiler m_tiler; void BenchmarkCommandFinished(); - void NextBenchmarkCommand(); +// void NextBenchmarkCommand(); void SaveBenchmarkResults(); void SendBenchmarkResults(); diff --git a/map/render_queue.cpp b/map/render_queue.cpp index 8c69dc200a..db13f0d060 100644 --- a/map/render_queue.cpp +++ b/map/render_queue.cpp @@ -7,114 +7,92 @@ RenderQueue::RenderQueue( string const & skinName, - bool isMultiSampled, - bool doPeriodicalUpdate, - double updateInterval, bool isBenchmarking, unsigned scaleEtalonSize, yg::Color const & bgColor - ) - : m_renderState(new yg::gl::RenderState()), - m_tileCache(256 * 256 * 2, 10 * 1024 * 1024) + ) : m_sequence(0), m_tileCache(39) { - m_renderState->m_surfaceWidth = 100; - m_renderState->m_surfaceHeight = 100; - m_renderState->m_textureWidth = 256; - m_renderState->m_textureHeight = 256; - m_renderState->m_duration = 0; - - m_routine = new RenderQueueRoutine( - m_renderState, - skinName, - isMultiSampled, - doPeriodicalUpdate, - updateInterval, - isBenchmarking, - scaleEtalonSize, - bgColor); + m_tasksCount = 1; //< calculate from the CPU Cores Number + m_tasks = new Task[m_tasksCount]; + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_routine = new RenderQueueRoutine( + skinName, + isBenchmarking, + scaleEtalonSize, + bgColor, + i, + this); } -void RenderQueue::initializeGL(shared_ptr const & primaryContext, +void RenderQueue::InitializeGL(shared_ptr const & primaryContext, shared_ptr const & resourceManager, double visualScale) { m_resourceManager = resourceManager; - m_routine->initializeGL(primaryContext->createShared(), - m_resourceManager); - m_routine->setVisualScale(visualScale); - m_renderQueueThread.Create(m_routine); + for (unsigned i = 0; i < m_tasksCount; ++i) + { + m_tasks[i].m_routine->initializeGL(primaryContext->createShared(), + m_resourceManager); + m_tasks[i].m_routine->setVisualScale(visualScale); + m_tasks[i].m_thread.Create(m_tasks[i].m_routine); + } } RenderQueue::~RenderQueue() { - m_renderQueueThread.Cancel(); + m_renderCommands.Cancel(); + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_thread.Cancel(); } -void RenderQueue::AddCommand(RenderQueueRoutine::render_fn_t const & fn, ScreenBase const & frameScreen) +void RenderQueue::AddCommand(RenderQueueRoutine::render_fn_t const & fn, yg::Tiler::RectInfo const & rectInfo, size_t seqNum) { - m_routine->addCommand(fn, frameScreen); -} - -void RenderQueue::AddBenchmarkCommand(RenderQueueRoutine::render_fn_t const & fn, ScreenBase const & frameScreen) -{ - m_routine->addBenchmarkCommand(fn, frameScreen); -} - -void RenderQueue::SetRedrawAll() -{ - m_renderState->m_doRepaintAll = true; + m_sequence = seqNum; + m_renderCommands.PushBack(make_shared_ptr(new RenderQueueRoutine::Command(rectInfo, fn, seqNum))); } void RenderQueue::AddWindowHandle(shared_ptr const & windowHandle) { - m_routine->addWindowHandle(windowHandle); + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_routine->addWindowHandle(windowHandle); } -void RenderQueue::addRenderCommandFinishedFn(renderCommandFinishedFn fn) +void RenderQueue::AddRenderCommandFinishedFn(renderCommandFinishedFn fn) { - m_routine->addRenderCommandFinishedFn(fn); + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_routine->addRenderCommandFinishedFn(fn); } -void RenderQueue::OnSize(size_t w, size_t h) +void RenderQueue::MemoryWarning() { - m_renderState->onSize(w, h); + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_routine->memoryWarning(); } -yg::gl::RenderState const RenderQueue::CopyState() const +void RenderQueue::EnterBackground() { - yg::gl::RenderState state; - m_renderState->copyTo(state); - return state; + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_routine->enterBackground(); } -yg::gl::RenderState const & RenderQueue::renderState() const +void RenderQueue::EnterForeground() { - return *m_renderState.get(); + for (unsigned i = 0; i < m_tasksCount; ++i) + m_tasks[i].m_routine->enterForeground(); } -shared_ptr const & RenderQueue::renderStatePtr() const -{ - return m_renderState; -} - -void RenderQueue::memoryWarning() -{ - m_routine->memoryWarning(); -} - -void RenderQueue::enterBackground() -{ - m_routine->enterBackground(); -} - -void RenderQueue::enterForeground() -{ - m_routine->enterForeground(); -} - -yg::TileCache & RenderQueue::tileCache() +yg::TileCache & RenderQueue::TileCache() { return m_tileCache; } +size_t RenderQueue::CurrentSequence() const +{ + return m_sequence; +} + +ThreadedList > & RenderQueue::RenderCommands() +{ + return m_renderCommands; +} diff --git a/map/render_queue.hpp b/map/render_queue.hpp index d3dbe2d0e1..120d9ad529 100644 --- a/map/render_queue.hpp +++ b/map/render_queue.hpp @@ -6,6 +6,7 @@ #include "render_queue_routine.hpp" #include "../yg/tile_cache.hpp" #include "../yg/tiler.hpp" +#include "../base/threaded_list.hpp" namespace yg { @@ -23,13 +24,23 @@ class RenderQueue { private: + /// single rendering task + struct Task + { + threads::Thread m_thread; + RenderQueueRoutine * m_routine; + }; + + Task * m_tasks; + size_t m_tasksCount; + + size_t m_sequence; + friend class RenderQueueRoutine; - threads::Thread m_renderQueueThread; - - shared_ptr m_renderState; shared_ptr m_resourceManager; - RenderQueueRoutine * m_routine; + + ThreadedList > m_renderCommands; yg::TileCache m_tileCache; @@ -39,50 +50,34 @@ public: /// constructor. RenderQueue(string const & skinName, - bool isMultiSampled, - bool doPeriodicalUpdate, - double updateInterval, bool isBenchmarking, unsigned scaleEtalonSize, yg::Color const & bgColor); /// destructor. ~RenderQueue(); /// set the primary context. it starts the rendering thread. - void initializeGL(shared_ptr const & primaryContext, + void InitializeGL(shared_ptr const & primaryContext, shared_ptr const & resourceManager, double ppmScale); /// add command to the commands queue. - void AddCommand(RenderQueueRoutine::render_fn_t const & fn, ScreenBase const & frameScreen); - void AddBenchmarkCommand(RenderQueueRoutine::render_fn_t const & fn, ScreenBase const & frameScreen); - - void SetRedrawAll(); - + void AddCommand(RenderQueueRoutine::render_fn_t const & fn, yg::Tiler::RectInfo const & rectInfo, size_t seqNum); + /// set visual scale void SetVisualScale(double visualScale); - /// 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 - yg::gl::RenderState const CopyState() const; - - shared_ptr const & renderStatePtr() const; - - yg::gl::RenderState const & renderState() const; - + /// add function, that will be called upon render command completion. + void AddRenderCommandFinishedFn(renderCommandFinishedFn fn); /// free all possible memory caches. - void memoryWarning(); + void MemoryWarning(); /// free all possible memory caches, opengl resources, /// and make sure no opengl call will be made in background - void enterBackground(); + void EnterBackground(); /// load all necessary memory caches and opengl resources. - void enterForeground(); - + void EnterForeground(); /// get tile cache. - yg::TileCache & tileCache(); - /// add tiler rendering command. - void addTileRenderCmd(yg::Tiler::RectInfo const & ri); + yg::TileCache & TileCache(); + /// number of the current tiler sequence to skip the old commands upon rendering. + size_t CurrentSequence() const; + /// common render commands queue for all rendering threads. + ThreadedList > & RenderCommands(); }; diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index c42725b95f..afea7118ab 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -15,6 +15,7 @@ #include "../yg/skin.hpp" #include "../yg/base_texture.hpp" #include "../yg/info_layer.hpp" +#include "../yg/tile.hpp" #include "../indexer/scales.hpp" @@ -22,29 +23,27 @@ #include "drawer_yg.hpp" #include "window_handle.hpp" #include "render_queue_routine.hpp" +#include "render_queue.hpp" -RenderQueueRoutine::RenderModelCommand::RenderModelCommand(ScreenBase const & frameScreen, - render_fn_t renderFn) - : m_frameScreen(frameScreen), - m_renderFn(renderFn) +RenderQueueRoutine::Command::Command(yg::Tiler::RectInfo const & rectInfo, + render_fn_t renderFn, + size_t seqNum) + : m_rectInfo(rectInfo), + m_renderFn(renderFn), + m_seqNum(seqNum) {} -RenderQueueRoutine::RenderQueueRoutine(shared_ptr const & renderState, - string const & skinName, - bool isMultiSampled, - bool doPeriodicalUpdate, - double updateInterval, +RenderQueueRoutine::RenderQueueRoutine(string const & skinName, bool isBenchmarking, unsigned scaleEtalonSize, - yg::Color const & bgColor) + yg::Color const & bgColor, + size_t threadNum, + RenderQueue * renderQueue) + : m_threadNum(threadNum), + m_renderQueue(renderQueue) { m_skinName = skinName; m_visualScale = 0; - m_renderState = renderState; - m_renderState->addInvalidateFn(bind(&RenderQueueRoutine::invalidate, this)); - m_isMultiSampled = isMultiSampled; - m_doPeriodicalUpdate = doPeriodicalUpdate; - m_updateInterval = updateInterval; m_isBenchmarking = isBenchmarking; m_scaleEtalonSize = scaleEtalonSize; m_bgColor = bgColor; @@ -53,160 +52,9 @@ RenderQueueRoutine::RenderQueueRoutine(shared_ptr const & r void RenderQueueRoutine::Cancel() { IRoutine::Cancel(); - /// Waking up the sleeping thread... - m_hasRenderCommands.Signal(); /// ...Or cancelling the current rendering command in progress. - if (m_currentRenderCommand != 0) - m_currentRenderCommand->m_paintEvent->setIsCancelled(true); -} - -void RenderQueueRoutine::processResize(ScreenBase const & frameScreen) -{ - if (m_renderState->m_isResized) - { - size_t texW = m_renderState->m_textureWidth; - size_t texH = m_renderState->m_textureHeight; - - m_renderState->m_depthBuffer.reset(); - - if (!m_isMultiSampled) - { - m_renderState->m_depthBuffer = make_shared_ptr(new yg::gl::RenderBuffer(texW, texH, true)); - m_threadDrawer->screen()->frameBuffer()->setDepthBuffer(m_renderState->m_depthBuffer); - } - - m_threadDrawer->onSize(texW, texH); - m_threadDrawer->screen()->frameBuffer()->onSize(texW, texH); - - shared_ptr oldActualTarget = m_renderState->m_actualTarget; - - m_renderState->m_actualTarget.reset(); - m_renderState->m_actualTarget = m_resourceManager->createRenderTarget(texW, texH); - - m_auxScreen->onSize(texW, texH); - m_auxScreen->setRenderTarget(m_renderState->m_actualTarget); - m_auxScreen->beginFrame(); - m_auxScreen->clear(m_bgColor); - - if (oldActualTarget != 0) - { - m_auxScreen->blit(oldActualTarget, - m_renderState->m_actualScreen, - frameScreen); - oldActualTarget.reset(); - } - m_auxScreen->endFrame(); - - for (size_t i = 0; i < m_renderState->m_backBufferLayers.size(); ++i) - { - shared_ptr oldBackBuffer = m_renderState->m_backBufferLayers[i]; - m_renderState->m_backBufferLayers[i].reset(); - m_renderState->m_backBufferLayers[i] = m_resourceManager->createRenderTarget(texW, texH); - m_auxScreen->setRenderTarget(m_renderState->m_backBufferLayers[i]); - m_auxScreen->beginFrame(); - m_auxScreen->clear(m_bgColor); - - if (oldBackBuffer != 0) - { - m_auxScreen->blit(oldBackBuffer, - m_renderState->m_actualScreen, - frameScreen); - oldBackBuffer.reset(); - } - m_auxScreen->endFrame(); - - m_renderState->m_actualScreen = frameScreen; - } - - m_renderState->m_isResized = false; - } -} - -void RenderQueueRoutine::getUpdateAreas( - ScreenBase const & oldScreen, - m2::RectI const & oldRect, - ScreenBase const & newScreen, - m2::RectI const & newRect, - vector & areas) -{ - areas.clear(); - - if (IsPanning(oldScreen, newScreen)) - { - m2::RectD o(newScreen.GtoP(oldScreen.PtoG(m2::PointD(oldRect.minX(), oldRect.minY()))), - newScreen.GtoP(oldScreen.PtoG(m2::PointD(oldRect.maxX(), oldRect.maxY())))); - m2::RectD n(newRect); - - /// checking two corner cases - if (o.IsRectInside(n)) - return; - if (!o.IsIntersect(n)) - { - areas.push_back(m2::RectI(n)); - return; - } - - double leftBarMinX = 0; - double leftBarMaxX = 0; - double rightBarMinX = n.maxX(); - double rightBarMaxX = n.maxX(); - double topBarMinY = 0; - double topBarMaxY = 0; - double bottomBarMinY = n.maxY(); - double bottomBarMaxY = n.maxY(); - - if (o.minX() > n.minX()) - leftBarMaxX = ceil(o.minX()); - if (o.maxX() < n.maxX()) - rightBarMinX = floor(o.maxX()); - if (o.minY() > n.minY()) - topBarMaxY = ceil(o.minY()); - if (o.maxY() < n.maxY()) - bottomBarMinY = floor(o.maxY()); - - if (leftBarMinX != leftBarMaxX) - areas.push_back(m2::RectI(leftBarMinX, topBarMinY, leftBarMaxX, bottomBarMinY)); - if (topBarMinY != topBarMaxY) - areas.push_back(m2::RectI(leftBarMaxX, topBarMinY, rightBarMaxX, topBarMaxY)); - if (rightBarMinX != rightBarMaxX) - areas.push_back(m2::RectI(rightBarMinX, topBarMaxY, rightBarMaxX, bottomBarMaxY)); - if (bottomBarMinY != bottomBarMaxY) - areas.push_back(m2::RectI(leftBarMinX, bottomBarMinY, rightBarMinX, bottomBarMaxY)); - } - else - { - areas.push_back(newRect); - -/* int rectW = (newRect.SizeX() + 9) / 5; - int rectH = (newRect.SizeY() + 9) / 5; - m2::RectI r( 2 * rectW, 2 * rectH, 3 * rectW, 3 * rectH); - areas.push_back(r); - areas.push_back(m2::Offset(r, -rectW, 0)); - areas.push_back(m2::Offset(r, -rectW, -rectH)); - areas.push_back(m2::Offset(r, 0, -rectH)); - areas.push_back(m2::Offset(r, rectW, -rectH)); - areas.push_back(m2::Offset(r, rectW, 0)); - areas.push_back(m2::Offset(r, rectW, rectH)); - areas.push_back(m2::Offset(r, 0, rectH)); - areas.push_back(m2::Offset(r, -rectW, rectH)); - areas.push_back(m2::Offset(r, -2 * rectW, rectH)); - areas.push_back(m2::Offset(r, -2 * rectW, 0)); - areas.push_back(m2::Offset(r, -2 * rectW, -rectH)); - areas.push_back(m2::Offset(r, -2 * rectW, -2*rectH)); - areas.push_back(m2::Offset(r, -rectW, -2*rectH)); - areas.push_back(m2::Offset(r, 0, -2*rectH)); - areas.push_back(m2::Offset(r, rectW, -2*rectH)); - areas.push_back(m2::Offset(r, 2 * rectW, -2*rectH)); - areas.push_back(m2::Offset(r, 2 * rectW, -rectH)); - areas.push_back(m2::Offset(r, 2 * rectW, 0)); - areas.push_back(m2::Offset(r, 2 * rectW, rectH)); - areas.push_back(m2::Offset(r, 2 * rectW, 2*rectH)); - areas.push_back(m2::Offset(r, rectW, 2*rectH)); - areas.push_back(m2::Offset(r, 0, 2*rectH)); - areas.push_back(m2::Offset(r, -rectW, 2*rectH)); - areas.push_back(m2::Offset(r, -2*rectW, 2*rectH)); -*/ - } + if (m_currentCommand != 0) + m_currentCommand->m_paintEvent->setIsCancelled(true); } void RenderQueueRoutine::setVisualScale(double visualScale) @@ -214,32 +62,26 @@ void RenderQueueRoutine::setVisualScale(double visualScale) m_visualScale = visualScale; } -void RenderQueueRoutine::waitForRenderCommand(list > & cmdList, - threads::ConditionGuard & guard) -{ - while (cmdList.empty()) - { - guard.Wait(); - if (IsCancelled()) - break; - } -} - void RenderQueueRoutine::Do() { m_renderContext->makeCurrent(); m_frameBuffer = make_shared_ptr(new yg::gl::FrameBuffer()); + unsigned tileWidth = m_resourceManager->tileTextureWidth(); + unsigned tileHeight = m_resourceManager->tileTextureHeight(); + + shared_ptr depthBuffer(new yg::gl::RenderBuffer(tileWidth, tileHeight, true)); + m_frameBuffer->setDepthBuffer(depthBuffer); + DrawerYG::params_t params; + shared_ptr infoLayer(new yg::InfoLayer()); + params.m_resourceManager = m_resourceManager; - params.m_isMultiSampled = m_isMultiSampled; params.m_frameBuffer = m_frameBuffer; - params.m_renderState = m_renderState; - params.m_doPeriodicalUpdate = m_doPeriodicalUpdate; - params.m_updateInterval = m_updateInterval; - params.m_glyphCacheID = m_resourceManager->renderThreadGlyphCacheID(); + params.m_infoLayer = infoLayer; + params.m_glyphCacheID = m_resourceManager->renderThreadGlyphCacheID(m_threadNum); params.m_useOverlay = true; /* params.m_isDebugging = true; params.m_drawPathes = false; @@ -247,187 +89,69 @@ void RenderQueueRoutine::Do() params.m_drawTexts = false; */ m_threadDrawer = make_shared_ptr(new DrawerYG(m_skinName, params)); + m_threadDrawer->onSize(tileWidth, tileHeight); - yg::gl::Screen::Params auxParams; - auxParams.m_frameBuffer = make_shared_ptr(new yg::gl::FrameBuffer()); - auxParams.m_resourceManager = m_resourceManager; - - m_auxScreen = make_shared_ptr(new yg::gl::Screen(auxParams)); - - CHECK(m_visualScale != 0, ("Set the VisualScale first!")); + CHECK(m_visualScale != 0, ("VisualScale is not set")); m_threadDrawer->SetVisualScale(m_visualScale); - bool isPanning = false; - bool doRedrawAll = false; - bool fullRectRepaint = false; - /// update areas in pixel coordinates. - vector areas; - - m2::RectI surfaceRect; - m2::RectI textureRect; + ScreenBase frameScreen; + frameScreen.OnSize(0, 0, tileWidth, tileHeight); while (!IsCancelled()) { { - threads::ConditionGuard guard(m_hasRenderCommands); - - if (m_isBenchmarking) - waitForRenderCommand(m_benchmarkRenderCommands, guard); - else - waitForRenderCommand(m_renderCommands, guard); + threads::MutexGuard guard(m_mutex); + m_currentCommand = m_renderQueue->RenderCommands().Front(true); if (IsCancelled()) break; + m_currentCommand->m_paintEvent = make_shared_ptr(new PaintEvent(m_threadDrawer)); - /// Preparing render command for execution. - if (m_isBenchmarking) - { - m_currentRenderCommand = m_benchmarkRenderCommands.front(); - m_benchmarkRenderCommands.erase(m_benchmarkRenderCommands.begin()); - } - else - { - m_currentRenderCommand = m_renderCommands.front(); - m_renderCommands.erase(m_renderCommands.begin()); - } + /// commands from the previous sequence are ignored + if (m_currentCommand->m_seqNum < m_renderQueue->CurrentSequence()) + continue; - m_currentRenderCommand->m_paintEvent = make_shared_ptr(new PaintEvent(m_threadDrawer)); + bool hasTile = false; - /// this prevents the framework from flooding us with a bunch of RenderCommands with the same screen. - { - threads::MutexGuard guard(*m_renderState->m_mutex.get()); + m_renderQueue->TileCache().lock(); + hasTile = m_renderQueue->TileCache().hasTile(m_currentCommand->m_rectInfo); + m_renderQueue->TileCache().unlock(); - m_renderState->m_currentScreen = m_currentRenderCommand->m_frameScreen; - - m2::RectI prevRect(0, 0, 0, 0); - ScreenBase prevScreen = m_renderState->m_actualScreen; - - if (m_renderState->m_actualTarget != 0) - prevRect = m2::RectI(0, 0, - m_renderState->m_actualTarget->width(), - m_renderState->m_actualTarget->height()); - - processResize(m_currentRenderCommand->m_frameScreen); - - /// saving parameters, which might be changed from the GUI thread for later use. - surfaceRect = m2::RectI(0, 0, m_renderState->m_surfaceWidth, m_renderState->m_surfaceHeight); - textureRect = m2::RectI(0, 0, m_renderState->m_textureWidth, m_renderState->m_textureHeight); - - m2::RectI curRect = textureRect; - - doRedrawAll = m_renderState->m_doRepaintAll; - - fullRectRepaint = false; - - if (m_renderState->m_doRepaintAll) - { - areas.clear(); - areas.push_back(curRect); - fullRectRepaint = true; - m_renderState->m_currentInfoLayer->clear(); -// m_renderState->m_actualInfoLayer->clear(); - m_renderState->m_doRepaintAll = false; - } - else - { - getUpdateAreas(prevScreen, - prevRect, - m_currentRenderCommand->m_frameScreen, - curRect, - areas); - if ((areas.size() == 1) && (areas[0] == curRect)) - fullRectRepaint = true; - } - - isPanning = IsPanning(prevScreen, m_renderState->m_currentScreen); - - if (isPanning) - { - m2::RectD oldRect = m2::RectD(m_renderState->m_currentScreen.GtoP(prevScreen.PtoG(m2::PointD(prevRect.minX(), prevRect.minY()))), - m_renderState->m_currentScreen.GtoP(prevScreen.PtoG(m2::PointD(prevRect.maxX(), prevRect.maxY())))); - m2::RectD redrawTextRect(curRect); - - if (!redrawTextRect.Intersect(oldRect)) - redrawTextRect = m2::RectD(0, 0, 0, 0); - - m2::PointD offs(m_renderState->m_currentScreen.GtoP(prevScreen.PtoG(m2::PointD(0, 0)))); - - m_renderState->m_currentInfoLayer->offset( - offs, - redrawTextRect); - } - else - { - m_renderState->m_currentInfoLayer->clear(); -// m_renderState->m_actualInfoLayer->clear(); - } - } + if (hasTile) + continue; } + if (IsCancelled()) + break; + my::Timer timer; - /// At this point renderQueue->mutex is released to allow - /// main thread to add new rendering tasks and blit already - /// rendered model while the current command is actually rendering. + shared_ptr tileTarget; - if (m_currentRenderCommand != 0) - { - /// this fixes some strange issue with multisampled framebuffer. - /// setRenderTarget should be made here. - m_threadDrawer->screen()->setRenderTarget(m_renderState->m_backBufferLayers.front()); + tileTarget = m_resourceManager->renderTargets().Front(true); + if (IsCancelled()) + break; - m_threadDrawer->beginFrame(); + m_threadDrawer->screen()->setRenderTarget(tileTarget); - m_threadDrawer->screen()->enableClipRect(true); - m_threadDrawer->screen()->setClipRect(textureRect); - m_threadDrawer->clear(m_bgColor); + m_threadDrawer->beginFrame(); - if ((isPanning) && (!doRedrawAll)) - { - m_threadDrawer->screen()->blit( - m_renderState->m_actualTarget, - m_renderState->m_actualScreen, - m_renderState->m_currentScreen); - } + m_threadDrawer->clear(m_bgColor); - ScreenBase const & frameScreen = m_currentRenderCommand->m_frameScreen; - m2::RectD glbRect; - frameScreen.PtoG(m2::RectD(textureRect.Center() - m2::PointD(m_scaleEtalonSize / 2, m_scaleEtalonSize / 2), - textureRect.Center() + m2::PointD(m_scaleEtalonSize / 2, m_scaleEtalonSize / 2)), - glbRect); -// frameScreen.PtoG(m2::RectD(surfaceRect), glbRect); - int scaleLevel = scales::GetScaleLevel(glbRect); + frameScreen.SetFromRect(m_currentCommand->m_rectInfo.m_rect); - for (size_t i = 0; i < areas.size(); ++i) - { - if ((areas[i].SizeX() != 0) && (areas[i].SizeY() != 0)) - { - frameScreen.PtoG(m2::Inflate(m2::RectD(areas[i]), 30 * m_visualScale, 30 * m_visualScale), glbRect); - if ((glbRect.SizeX() == 0) || (glbRect.SizeY() == 0)) - continue; + int scaleLevel = scales::GetScaleLevel(m_currentCommand->m_rectInfo.m_rect); - m_threadDrawer->screen()->setClipRect(areas[i]); + m_currentCommand->m_renderFn( + m_currentCommand->m_paintEvent, + frameScreen, + m_currentCommand->m_rectInfo.m_rect, + scaleLevel); - m_currentRenderCommand->m_renderFn( - m_currentRenderCommand->m_paintEvent, - m_currentRenderCommand->m_frameScreen, - glbRect, - scaleLevel); - } - } + /// rendering all collected texts +// m_infoLayer->draw(m_threadDrawer->screen().get(), math::Identity()); - /// if something were actually drawn, or (exclusive or) we are repainting the whole rect - if ((!m_renderState->m_isEmptyModelCurrent) || (fullRectRepaint)) - m_renderState->m_isEmptyModelActual = m_renderState->m_isEmptyModelCurrent; - - /// setting the "whole texture" clip rect to render texts opened by panning. - m_threadDrawer->screen()->setClipRect(textureRect); - - /// rendering all collected texts - m_renderState->m_currentInfoLayer->draw(m_threadDrawer->screen().get(), math::Identity()); - - m_threadDrawer->endFrame(); - } + m_threadDrawer->endFrame(); double duration = timer.ElapsedSeconds(); @@ -437,17 +161,23 @@ void RenderQueueRoutine::Do() /// in the endFrame function /// updateActualTarget(); - m_currentRenderCommand.reset(); - { - threads::MutexGuard guard(*m_renderState->m_mutex.get()); - m_renderState->m_duration = duration; + threads::MutexGuard guard(m_mutex); + + if (!m_currentCommand->m_paintEvent->isCancelled()) + { + yg::Tile tile(tileTarget, frameScreen, m_currentCommand->m_rectInfo, duration); + m_renderQueue->TileCache().lock(); + m_renderQueue->TileCache().addTile(m_currentCommand->m_rectInfo, yg::TileCache::Entry(tile, m_resourceManager)); + m_renderQueue->TileCache().unlock(); + } + + m_currentCommand.reset(); } invalidate(); callRenderCommandFinishedFns(); - } } @@ -469,49 +199,11 @@ void RenderQueueRoutine::invalidate() bind(&WindowHandle::invalidate, _1)); } -void RenderQueueRoutine::addCommand(render_fn_t const & fn, ScreenBase const & frameScreen) -{ - /// Command queue modification is syncronized by mutex - threads::ConditionGuard guard(m_hasRenderCommands); - - bool needToSignal = m_renderCommands.empty(); - - /// Clearing a list of commands. - m_renderCommands.clear(); - - /// pushing back new RenderCommand. - m_renderCommands.push_back(make_shared_ptr(new RenderModelCommand(frameScreen, fn))); - - /// if we are in benchmarking mode, we shouldn't cancel any render command - /// else, if we are not panning, we should cancel the render command in progress to start a new one - if ((!m_isBenchmarking) - && (m_currentRenderCommand != 0) - && (!IsPanning(m_currentRenderCommand->m_frameScreen, frameScreen))) - m_currentRenderCommand->m_paintEvent->setIsCancelled(true); - - if (needToSignal) - guard.Signal(); -} - -void RenderQueueRoutine::addBenchmarkCommand(render_fn_t const & fn, ScreenBase const & frameScreen) -{ - /// Command queue modification is syncronized by mutex - threads::ConditionGuard guard(m_hasRenderCommands); - - bool needToSignal = m_renderCommands.empty(); - - m_benchmarkRenderCommands.push_back(make_shared_ptr(new RenderModelCommand(frameScreen, fn))); - - if (needToSignal) - guard.Signal(); -} - void RenderQueueRoutine::initializeGL(shared_ptr const & renderContext, shared_ptr const & resourceManager) { m_renderContext = renderContext; m_resourceManager = resourceManager; - m_threadRenderer.init(renderContext->createShared(), m_renderState); } void RenderQueueRoutine::memoryWarning() @@ -540,4 +232,3 @@ void RenderQueueRoutine::callRenderCommandFinishedFns() 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 1691e466b7..fb6f2605aa 100644 --- a/map/render_queue_routine.hpp +++ b/map/render_queue_routine.hpp @@ -9,6 +9,8 @@ #include "../std/function.hpp" #include "../yg/thread_renderer.hpp" #include "../yg/color.hpp" +#include "../yg/tile_cache.hpp" +#include "../yg/tiler.hpp" class DrawerYG; @@ -19,11 +21,13 @@ namespace threads class PaintEvent; class WindowHandle; +class RenderQueue; namespace yg { class ResourceManager; + namespace gl { class RenderContext; @@ -43,74 +47,59 @@ public: typedef function, ScreenBase const &, m2::RectD const &, int)> render_fn_t; typedef function renderCommandFinishedFn; -private: - - threads::CommandsQueue m_threadRendererQueue; - yg::gl::ThreadRenderer m_threadRenderer; - - struct RenderModelCommand + /// Single tile rendering command + struct Command { - ScreenBase m_frameScreen; + yg::Tiler::RectInfo m_rectInfo; shared_ptr m_paintEvent; render_fn_t m_renderFn; - RenderModelCommand(ScreenBase const & frameScreen, - render_fn_t renderFn); + size_t m_seqNum; + Command(yg::Tiler::RectInfo const & rectInfo, + render_fn_t renderFn, + size_t seqNum); //< paintEvent is set later after construction }; +private: + shared_ptr m_renderContext; shared_ptr m_frameBuffer; shared_ptr m_threadDrawer; - shared_ptr m_auxScreen; - threads::Condition m_hasRenderCommands; - shared_ptr m_currentRenderCommand; - list > m_renderCommands; - list > m_benchmarkRenderCommands; - - shared_ptr m_renderState; + threads::Mutex m_mutex; + shared_ptr m_currentCommand; shared_ptr m_resourceManager; /// A list of window handles to notify about ending rendering operations. list > m_windowHandles; - bool m_isMultiSampled; - bool m_doPeriodicalUpdate; - double m_updateInterval; double m_visualScale; string m_skinName; bool m_isBenchmarking; unsigned m_scaleEtalonSize; yg::Color m_bgColor; - void waitForRenderCommand(list > & cmdList, - threads::ConditionGuard & guard); + size_t m_threadNum; list m_renderCommandFinishedFns; + RenderQueue * m_renderQueue; + void callRenderCommandFinishedFns(); public: - RenderQueueRoutine(shared_ptr const & renderState, - string const & skinName, - bool isMultiSampled, - bool doPeriodicalUpdate, - double updateInterval, + RenderQueueRoutine(string const & skinName, bool isBenchmarking, unsigned scaleEtalonSize, - yg::Color const & bgColor); + yg::Color const & bgColor, + size_t threadNum, + RenderQueue * renderQueue); /// initialize GL rendering /// this function is called just before the thread starts. void initializeGL(shared_ptr const & renderContext, shared_ptr const & resourceManager); /// This function should always be called from the main thread. void Cancel(); - /// Check, whether the resize command is queued, and resize accordingly. - void processResize(ScreenBase const & frameScreen); - /// Get update areas for the current render state - void getUpdateAreas(ScreenBase const & oldScreen, m2::RectI const & oldRect, - ScreenBase const & newScreen, m2::RectI const & newRect, - vector & areas); /// Thread procedure void Do(); /// invalidate all connected window handles @@ -118,9 +107,9 @@ public: /// add monitoring window void addWindowHandle(shared_ptr window); /// add model rendering command to rendering queue - void addCommand(render_fn_t const & fn, ScreenBase const & frameScreen); + void addCommand(render_fn_t const & fn, yg::Tiler::RectInfo const & rectInfo, size_t seqNumber); /// add benchmark rendering command - void addBenchmarkCommand(render_fn_t const & fn, ScreenBase const & frameScreen); +// void addBenchmarkCommand(render_fn_t const & fn, m2::RectD const & globalRect); /// set the resolution scale factor to the main thread drawer; void setVisualScale(double visualScale); /// free all available memory diff --git a/qt/widgets.cpp b/qt/widgets.cpp index 7a4bc2da69..788cd1e1df 100644 --- a/qt/widgets.cpp +++ b/qt/widgets.cpp @@ -56,7 +56,6 @@ namespace qt "fonts_whitelist.txt", "fonts_blacklist.txt", 2 * 1024 * 1024, - 500 * 1024, yg::Rt8Bpp, !yg::gl::g_isBufferObjectsSupported, !pl.IsMultiSampled())); diff --git a/qt_tstfrm/tstwidgets.cpp b/qt_tstfrm/tstwidgets.cpp index b7debe696a..effcaf2018 100644 --- a/qt_tstfrm/tstwidgets.cpp +++ b/qt_tstfrm/tstwidgets.cpp @@ -60,7 +60,6 @@ void GLDrawWidget::initializeGL() "fonts_whitelist.txt", "fonts_blacklist.txt", 2 * 1024 * 1024, - 500 * 1024, yg::Rt8Bpp, !yg::gl::g_isBufferObjectsSupported, !GetPlatform().IsMultiSampled())); diff --git a/std/functional.hpp b/std/functional.hpp index aa6f8cba10..87c636e221 100644 --- a/std/functional.hpp +++ b/std/functional.hpp @@ -8,6 +8,7 @@ #include using std::greater; using std::less; +using std::greater; using std::equal_to; #ifdef DEBUG_NEW diff --git a/yg/blitter.cpp b/yg/blitter.cpp index af239319e5..e8feb589e3 100644 --- a/yg/blitter.cpp +++ b/yg/blitter.cpp @@ -40,14 +40,20 @@ namespace yg void Blitter::blit(shared_ptr const & srcSurface, ScreenBase const & from, ScreenBase const & to, + bool isSubPixel, yg::Color const & color, m2::RectI const & srcRect, m2::RectU const & texRect) { m2::PointF pt = to.GtoP(from.PtoG(m2::PointF(srcRect.minX(), srcRect.minY()))); - pt.x = pt.x - my::rounds(pt.x); - pt.y = pt.y - my::rounds(pt.y); + if (!isSubPixel) + { + pt.x = pt.x - my::rounds(pt.x); + pt.y = pt.y - my::rounds(pt.y); + } + else + pt = m2::PointF(0, 0); m2::PointF pts[4] = { @@ -70,11 +76,13 @@ namespace yg void Blitter::blit(shared_ptr const & srcSurface, ScreenBase const & from, - ScreenBase const & to) + ScreenBase const & to, + bool isSubPixel) { blit(srcSurface, from, to, + isSubPixel, yg::Color(), m2::RectI(0, 0, srcSurface->width(), srcSurface->height()), m2::RectU(0, 0, srcSurface->width(), srcSurface->height())); @@ -168,7 +176,7 @@ namespace yg yg::Color const & color, bool hasColor) { - m_blitStorage = resourceManager()->blitStorages().Reserve(); + m_blitStorage = resourceManager()->blitStorages().Front(true); AuxVertex * pointsData = (AuxVertex*)m_blitStorage.m_vertices->lock(); @@ -203,7 +211,7 @@ namespace yg /// This call is necessary to avoid parasite blitting in updateActualTarget() on IPhone. OGLCHECK(glFinish()); - resourceManager()->blitStorages().Free(m_blitStorage); + resourceManager()->blitStorages().PushBack(m_blitStorage); m_blitStorage = yg::gl::Storage(); } } diff --git a/yg/blitter.hpp b/yg/blitter.hpp index 9dc26bb230..06f39aba7f 100644 --- a/yg/blitter.hpp +++ b/yg/blitter.hpp @@ -45,13 +45,15 @@ namespace yg void blit(shared_ptr const & srcSurface, ScreenBase const & from, ScreenBase const & to, + bool isSubPixel, yg::Color const & color, m2::RectI const & srcRect, m2::RectU const & texRect); void blit(shared_ptr const & srcSurface, ScreenBase const & from, - ScreenBase const & to); + ScreenBase const & to, + bool isSubPixel = false); void immDrawSolidRect(m2::RectF const & rect, yg::Color const & color); diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index 7f98f9662f..ad9c8dae70 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -76,7 +76,7 @@ namespace yg { if (!m_hasStorage) { - m_storage = usage != SkinPage::EStaticUsage ? resourceManager->storages().Reserve() : resourceManager->smallStorages().Reserve(); + m_storage = usage != SkinPage::EStaticUsage ? resourceManager->storages().Front(true) : resourceManager->smallStorages().Front(true); m_maxVertices = m_storage.m_vertices->size() / sizeof(Vertex); m_maxIndices = m_storage.m_indices->size() / sizeof(unsigned short); @@ -220,9 +220,9 @@ namespace yg renderedData = true; if (skinPage->usage() != SkinPage::EStaticUsage) - resourceManager()->storages().Free(pipeline.m_storage); + resourceManager()->storages().PushBack(pipeline.m_storage); else - resourceManager()->smallStorages().Free(pipeline.m_storage); + resourceManager()->smallStorages().PushBack(pipeline.m_storage); pipeline.m_hasStorage = false; pipeline.m_storage = Storage(); diff --git a/yg/overlay_renderer.cpp b/yg/overlay_renderer.cpp index 3c8013e3a2..a126249f1a 100644 --- a/yg/overlay_renderer.cpp +++ b/yg/overlay_renderer.cpp @@ -23,7 +23,8 @@ namespace yg : TextRenderer(p), m_useOverlay(p.m_useOverlay), m_drawTexts(p.m_drawTexts), - m_drawSymbols(p.m_drawSymbols) + m_drawSymbols(p.m_drawSymbols), + m_infoLayer(p.m_infoLayer) { } @@ -45,10 +46,10 @@ namespace yg SymbolElement se(params); - if (!renderState().get() || !m_useOverlay) + if (!m_infoLayer.get() || !m_useOverlay) se.draw(this, math::Identity()); else - renderState()->m_currentInfoLayer->addSymbol(se); + m_infoLayer->addSymbol(se); } void OverlayRenderer::drawCircle(m2::PointD const & pt, @@ -88,10 +89,10 @@ namespace yg StraightTextElement ste(params); - if (!renderState().get() || !m_useOverlay) + if (!m_infoLayer.get() || !m_useOverlay) ste.draw(this, math::Identity()); else - renderState()->m_currentInfoLayer->addStraightText(ste); + m_infoLayer->addStraightText(ste); } bool OverlayRenderer::drawPathText( @@ -117,10 +118,10 @@ namespace yg PathTextElement pte(params); - if (!renderState().get() || !m_useOverlay) + if (!m_infoLayer.get() || !m_useOverlay) pte.draw(this, math::Identity()); else - renderState()->m_currentInfoLayer->addPathText(pte); + m_infoLayer->addPathText(pte); return true; } diff --git a/yg/overlay_renderer.hpp b/yg/overlay_renderer.hpp index 5d3f48a4ef..2e27da9cf7 100644 --- a/yg/overlay_renderer.hpp +++ b/yg/overlay_renderer.hpp @@ -1,6 +1,8 @@ #pragma once #include "text_renderer.hpp" +#include "../std/shared_ptr.hpp" +#include "info_layer.hpp" namespace yg { @@ -13,6 +15,7 @@ namespace yg bool m_useOverlay; bool m_drawTexts; bool m_drawSymbols; + shared_ptr m_infoLayer; public: @@ -21,6 +24,7 @@ namespace yg bool m_useOverlay; bool m_drawTexts; bool m_drawSymbols; + shared_ptr m_infoLayer; Params(); }; diff --git a/yg/render_state_updater.cpp b/yg/render_state_updater.cpp index 22e4a1d7d0..a28ec66f29 100644 --- a/yg/render_state_updater.cpp +++ b/yg/render_state_updater.cpp @@ -47,52 +47,7 @@ namespace yg } void RenderStateUpdater::updateActualTarget() - { - /// Carefully synchronizing the access to the m_renderState to minimize wait time. - OGLCHECK(glFinish()); - updateFrameBuffer(); - - { - threads::MutexGuard guard(*m_renderState->m_mutex.get()); - swap(m_renderState->m_actualTarget, m_renderState->m_backBufferLayers.front()); -// swap(m_renderState->m_actualInfoLayer, m_renderState->m_currentInfoLayer); - m_renderState->m_actualScreen = m_renderState->m_currentScreen; - } - - /// copying info layer -// *m_renderState->m_currentInfoLayer.get() = *m_renderState->m_actualInfoLayer.get(); - - /// blitting will be performed through - /// non-multisampled framebuffer for the sake of speed - - frameBuffer()->setRenderTarget(m_renderState->m_backBufferLayers.front()); - frameBuffer()->makeCurrent(); - - OGLCHECK(glFinish()); - - OGLCHECK(glDisable(GL_SCISSOR_TEST)); - - OGLCHECK(glClearColor(192 / 255.0, 192 / 255.0, 192 / 255.0, 1.0)); - OGLCHECK(glClear(GL_COLOR_BUFFER_BIT)); - - shared_ptr actualTarget = m_renderState->m_actualTarget; - - immDrawTexturedRect( - m2::RectF(0, 0, actualTarget->width(), actualTarget->height()), - m2::RectF(0, 0, 1, 1), - actualTarget - ); - - if (clipRectEnabled()) - OGLCHECK(glEnable(GL_SCISSOR_TEST)); - - OGLCHECK(glFinish()); - - if (isMultiSampled()) - multiSampledFrameBuffer()->makeCurrent(); - - m_renderState->invalidate(); - } + {} void RenderStateUpdater::beginFrame() { diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index 3e6f1e5abc..6c6d4a05fc 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -24,14 +24,15 @@ namespace yg size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t dynamicTexWidth, size_t dynamicTexHeight, size_t dynamicTexCount, size_t fontTexWidth, size_t fontTexHeight, size_t fontTexCount, + size_t tileTexWidth, size_t tileTexHeight, size_t tileTexCount, char const * blocksFile, char const * whiteListFile, char const * blackListFile, - size_t primaryGlyphCacheSize, - size_t secondaryGlyphCacheSize, + size_t glyphCacheSize, RtFormat fmt, bool useVA, bool fillSkinAlpha) : m_dynamicTextureWidth(dynamicTexWidth), m_dynamicTextureHeight(dynamicTexHeight), m_fontTextureWidth(fontTexWidth), m_fontTextureHeight(fontTexHeight), + m_tileTextureWidth(tileTexWidth), m_tileTextureHeight(tileTexHeight), m_vbSize(vbSize), m_ibSize(ibSize), m_smallVBSize(smallVBSize), m_smallIBSize(smallIBSize), m_blitVBSize(blitVBSize), m_blitIBSize(blitIBSize), @@ -40,9 +41,9 @@ namespace yg m_fillSkinAlpha(fillSkinAlpha) { /// primary cache is for rendering, so it's big - m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, primaryGlyphCacheSize))); - /// secondary caches is for glyph metrics only, so they are small - m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, secondaryGlyphCacheSize))); + m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, glyphCacheSize / 3))); + m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, glyphCacheSize / 3))); + m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(blocksFile, whiteListFile, blackListFile, glyphCacheSize / 3))); if (useVA) { @@ -50,24 +51,24 @@ namespace yg } for (size_t i = 0; i < storagesCount; ++i) - m_storages.Add(gl::Storage(vbSize, ibSize, m_useVA)); + m_storages.PushBack(gl::Storage(vbSize, ibSize, m_useVA)); LOG(LINFO, ("allocating ", (vbSize + ibSize) * storagesCount, " bytes for main storage")); for (size_t i = 0; i < smallStoragesCount; ++i) - m_smallStorages.Add(gl::Storage(smallVBSize, smallIBSize, m_useVA)); + m_smallStorages.PushBack(gl::Storage(smallVBSize, smallIBSize, m_useVA)); LOG(LINFO, ("allocating ", (smallVBSize + smallIBSize) * smallStoragesCount, " bytes for small storage")); for (size_t i = 0; i < blitStoragesCount; ++i) - m_blitStorages.Add(gl::Storage(blitVBSize, blitIBSize, m_useVA)); + m_blitStorages.PushBack(gl::Storage(blitVBSize, blitIBSize, m_useVA)); LOG(LINFO, ("allocating ", (blitVBSize + blitIBSize) * blitStoragesCount, " bytes for blit storage")); for (size_t i = 0; i < dynamicTexCount; ++i) { shared_ptr t(new TDynamicTexture(dynamicTexWidth, dynamicTexHeight)); - m_dynamicTextures.Add(t); + m_dynamicTextures.PushBack(t); #ifdef DEBUG static_cast(t.get())->randomize(); #endif @@ -78,13 +79,21 @@ namespace yg for (size_t i = 0; i < fontTexCount; ++i) { shared_ptr t(new TDynamicTexture(fontTexWidth, fontTexHeight)); - m_fontTextures.Add(t); + m_fontTextures.PushBack(t); #ifdef DEBUG static_cast(t.get())->randomize(); #endif } LOG(LINFO, ("allocating ", fontTexWidth * fontTexHeight * sizeof(TDynamicTexture::pixel_t), " bytes for font textures")); + + for (size_t i = 0; i < tileTexCount; ++i) + { + shared_ptr t(new TStaticTexture(tileTexWidth, tileTexHeight)); + m_renderTargets.PushBack(t); + } + + LOG(LINFO, ("allocating ", tileTexWidth * tileTexHeight * sizeof(TStaticTexture::pixel_t), " bytes for tiles")); } shared_ptr const & ResourceManager::getTexture(string const & fileName) @@ -144,6 +153,15 @@ namespace yg return m_fontTextureHeight; } + size_t ResourceManager::tileTextureWidth() const + { + return m_tileTextureWidth; + } + + size_t ResourceManager::tileTextureHeight() const + { + return m_tileTextureHeight; + } GlyphCache * ResourceManager::glyphCache(int glyphCacheID) { @@ -184,16 +202,16 @@ namespace yg threads::MutexGuard guard(m_mutex); for (size_t i = 0; i < m_storagesCount; ++i) - m_storages.Add(gl::Storage(m_vbSize, m_ibSize, m_useVA)); + m_storages.PushBack(gl::Storage(m_vbSize, m_ibSize, m_useVA)); for (size_t i = 0; i < m_smallStoragesCount; ++i) - m_smallStorages.Add(gl::Storage(m_smallVBSize, m_smallIBSize, m_useVA)); + m_smallStorages.PushBack(gl::Storage(m_smallVBSize, m_smallIBSize, m_useVA)); for (size_t i = 0; i < m_blitStoragesCount; ++i) - m_blitStorages.Add(gl::Storage(m_blitVBSize, m_blitIBSize, m_useVA)); + m_blitStorages.PushBack(gl::Storage(m_blitVBSize, m_blitIBSize, m_useVA)); for (size_t i = 0; i < m_dynamicTexturesCount; ++i) - m_dynamicTextures.Add(shared_ptr(new TDynamicTexture(m_dynamicTextureWidth, m_dynamicTextureHeight))); + m_dynamicTextures.PushBack(shared_ptr(new TDynamicTexture(m_dynamicTextureWidth, m_dynamicTextureHeight))); for (size_t i = 0; i < m_fontTexturesCount; ++i) - m_fontTextures.Add(shared_ptr(new TDynamicTexture(m_fontTextureWidth, m_fontTextureHeight))); + m_fontTextures.PushBack(shared_ptr(new TDynamicTexture(m_fontTextureWidth, m_fontTextureHeight))); } shared_ptr ResourceManager::createRenderTarget(unsigned w, unsigned h) @@ -214,39 +232,43 @@ namespace yg return m_fillSkinAlpha; } - int ResourceManager::renderThreadGlyphCacheID() const + int ResourceManager::renderThreadGlyphCacheID(int threadNum) const { - return 0; + return 1 + threadNum; } int ResourceManager::guiThreadGlyphCacheID() const { - return 1; + return 0; } - ObjectPool & ResourceManager::storages() + ThreadedList & ResourceManager::storages() { return m_storages; } - ObjectPool & ResourceManager::smallStorages() + ThreadedList & ResourceManager::smallStorages() { return m_smallStorages; } - ObjectPool & ResourceManager::blitStorages() + ThreadedList & ResourceManager::blitStorages() { return m_blitStorages; } - ObjectPool > & ResourceManager::dynamicTextures() + ThreadedList > & ResourceManager::dynamicTextures() { return m_dynamicTextures; } - ObjectPool > & ResourceManager::fontTextures() + ThreadedList > & ResourceManager::fontTextures() { return m_fontTextures; } + ThreadedList > & ResourceManager::renderTargets() + { + return m_renderTargets; + } } diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index 65282f993c..1d47e0f3f1 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -6,7 +6,7 @@ #include "../std/list.hpp" #include "../base/mutex.hpp" -#include "../base/object_pool.hpp" +#include "../base/threaded_list.hpp" #include "storage.hpp" #include "glyph_cache.hpp" @@ -42,12 +42,17 @@ namespace yg size_t m_dynamicTextureWidth; size_t m_dynamicTextureHeight; - ObjectPool > m_dynamicTextures; + ThreadedList > m_dynamicTextures; size_t m_fontTextureWidth; size_t m_fontTextureHeight; - ObjectPool > m_fontTextures; + ThreadedList > m_fontTextures; + + size_t m_tileTextureWidth; + size_t m_tileTextureHeight; + + ThreadedList > m_renderTargets; size_t m_vbSize; size_t m_ibSize; @@ -58,9 +63,9 @@ namespace yg size_t m_blitVBSize; size_t m_blitIBSize; - ObjectPool m_storages; - ObjectPool m_smallStorages; - ObjectPool m_blitStorages; + ThreadedList m_storages; + ThreadedList m_smallStorages; + ThreadedList m_blitStorages; vector m_glyphCaches; @@ -82,20 +87,21 @@ namespace yg size_t blitVBSize, size_t blitIBSize, size_t blitStoragesCount, size_t texWidth, size_t texHeight, size_t texCount, size_t fontTexWidth, size_t fontTexHeight, size_t fontTexCount, + size_t tileTexWidth, size_t tileTexHeight, size_t tileTexCount, char const * blocksFile, char const * whileListFile, char const * blackListFile, - size_t primaryGlyphCacheSize, - size_t secondaryGlyphCacheSize, + size_t glyphCacheSize, RtFormat fmt, bool useVA, bool fillSkinAlpha); shared_ptr const & getTexture(string const & fileName); - ObjectPool & storages(); - ObjectPool & smallStorages(); - ObjectPool & blitStorages(); - ObjectPool > & dynamicTextures(); - ObjectPool > & fontTextures(); + ThreadedList & storages(); + ThreadedList & smallStorages(); + ThreadedList & blitStorages(); + ThreadedList > & dynamicTextures(); + ThreadedList > & fontTextures(); + ThreadedList > & renderTargets(); size_t dynamicTextureWidth() const; size_t dynamicTextureHeight() const; @@ -103,11 +109,14 @@ namespace yg size_t fontTextureWidth() const; size_t fontTextureHeight() const; + size_t tileTextureWidth() const; + size_t tileTextureHeight() const; + shared_ptr const getGlyphInfo(GlyphKey const & key); GlyphMetrics const getGlyphMetrics(GlyphKey const & key); GlyphCache * glyphCache(int glyphCacheID = 0); - int renderThreadGlyphCacheID() const; + int renderThreadGlyphCacheID(int threadNum) const; int guiThreadGlyphCacheID() const; void addFonts(vector const & fontNames); diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index aa62391406..ebd8607ed7 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -750,10 +750,10 @@ namespace yg switch (m_usage) { case EDynamicUsage: - m_resourceManager->dynamicTextures().Free(m_texture); + m_resourceManager->dynamicTextures().PushBack(m_texture); break; case EFontsUsage: - m_resourceManager->fontTextures().Free(m_texture); + m_resourceManager->fontTextures().PushBack(m_texture); break; default: LOG(LINFO, ("freeTexture call for with invalid usage param")); @@ -768,10 +768,10 @@ namespace yg switch (m_usage) { case EDynamicUsage: - m_texture = m_resourceManager->dynamicTextures().Reserve(); + m_texture = m_resourceManager->dynamicTextures().Front(true); break; case EFontsUsage: - m_texture = m_resourceManager->fontTextures().Reserve(); + m_texture = m_resourceManager->fontTextures().Front(true); break; default: LOG(LINFO, ("freeTexture call for with invalid usage param")); diff --git a/yg/texture.hpp b/yg/texture.hpp index 4c9bed7df2..bac7570abd 100644 --- a/yg/texture.hpp +++ b/yg/texture.hpp @@ -28,6 +28,20 @@ namespace yg template class Texture : public BaseTexture { + public: + + typedef Traits traits_t; + typedef typename Traits::pixel_t pixel_t; + typedef typename Traits::const_pixel_t const_pixel_t; + typedef typename Traits::view_t view_t; + typedef typename Traits::const_view_t const_view_t; + typedef typename Traits::image_t image_t; + + static const int maxChannelVal = Traits::maxChannelVal; + static const int channelScaleFactor = Traits::channelScaleFactor; + static const int gl_pixel_data_type = Traits::gl_pixel_data_type; + static const int gl_pixel_format_type = Traits::gl_pixel_format_type; + private: void upload(void * data) diff --git a/yg/tile.hpp b/yg/tile.hpp index e5a81d8cdc..1a7bfc53a6 100644 --- a/yg/tile.hpp +++ b/yg/tile.hpp @@ -3,16 +3,30 @@ #include "../geometry/screenbase.hpp" #include "../std/shared_ptr.hpp" #include "base_texture.hpp" -#include "renderbuffer.hpp" +#include "resource_manager.hpp" #include "tiler.hpp" namespace yg { struct Tile { - shared_ptr m_depthBuffer; //< taken from resource manager shared_ptr m_renderTarget; //< taken from resource manager - ScreenBase m_tileScreen; + ScreenBase m_tileScreen; //< cached to calculate it once, cause tile blitting + //< is performed on GUI thread. Tiler::RectInfo m_rectInfo; //< taken from tiler + double m_duration; + + Tile() + {} + + Tile(shared_ptr const & renderTarget, + ScreenBase const & tileScreen, + Tiler::RectInfo const & rectInfo, + double duration) + : m_renderTarget(renderTarget), + m_tileScreen(tileScreen), + m_rectInfo(rectInfo), + m_duration(duration) + {} }; } diff --git a/yg/tile_cache.cpp b/yg/tile_cache.cpp index 51040cc82f..b7b8efd4af 100644 --- a/yg/tile_cache.cpp +++ b/yg/tile_cache.cpp @@ -1,20 +1,23 @@ #include "tile_cache.hpp" -#include "../std/cmath.hpp" - - namespace yg { - TileCache::TileCache(size_t tileMemSize, size_t memSize) - : m_cache(log(memSize / static_cast(tileMemSize)) / log(2.0)) + TileCache::Entry::Entry() + {} + + TileCache::Entry::Entry(Tile const & tile, shared_ptr const & rm) + : m_tile(tile), m_rm(rm) + {} + + + TileCache::TileCache(size_t maxCacheSize) + : m_cache(maxCacheSize) { } - void TileCache::addTile(Tiler::RectInfo const & key, Tile const & value) + void TileCache::addTile(Tiler::RectInfo const & key, Entry const & entry) { - bool found; - Tile & cachedVal = m_cache.Find(key.toUInt64Cell(), found); - cachedVal = value; + m_cache.Add(key.toUInt64Cell(), entry, 1); } void TileCache::lock() @@ -29,12 +32,11 @@ namespace yg bool TileCache::hasTile(Tiler::RectInfo const & key) { - return m_cache.HasKey(key.toUInt64Cell()); + return m_cache.HasElem(key.toUInt64Cell()); } Tile const & TileCache::getTile(Tiler::RectInfo const & key) { - bool found; - return m_cache.Find(key.toUInt64Cell(), found); + return m_cache.Find(key.toUInt64Cell()).m_tile; } } diff --git a/yg/tile_cache.hpp b/yg/tile_cache.hpp index a6c8570c4f..64e24d545d 100644 --- a/yg/tile_cache.hpp +++ b/yg/tile_cache.hpp @@ -2,27 +2,48 @@ #include "tile.hpp" #include "tiler.hpp" -#include "../base/cache.hpp" +#include "../base/mru_cache.hpp" #include "../base/mutex.hpp" namespace yg { + class ResourceManager; + class TileCache { + public: + + struct Entry + { + Tile m_tile; + shared_ptr m_rm; + Entry(); + Entry(Tile const & tile, shared_ptr const & rm); + }; + + struct EntryValueTraits + { + static void Evict(Entry & val) + { + if (val.m_rm) + val.m_rm->renderTargets().PushBack(val.m_tile.m_renderTarget); + } + }; + private: - my::Cache m_cache; + my::MRUCache m_cache; threads::Mutex m_mutex; public: - TileCache(size_t tileMemSize, size_t memSize); + TileCache(size_t maxCacheSize); /// lock for multithreaded access void lock(); /// unlock for multithreaded access void unlock(); /// add tile to cache - void addTile(Tiler::RectInfo const & key, Tile const & value); + void addTile(Tiler::RectInfo const & key, Entry const & entry); /// check, whether we have some tile in the cache bool hasTile(Tiler::RectInfo const & key); /// get tile from the cache diff --git a/yg/tiler.cpp b/yg/tiler.cpp index 45c2e473e3..7fe87e2dfe 100644 --- a/yg/tiler.cpp +++ b/yg/tiler.cpp @@ -2,6 +2,7 @@ #include "tiler.hpp" #include "../indexer/mercator.hpp" #include "../indexer/scales.hpp" +#include "../base/logging.hpp" namespace yg { @@ -22,7 +23,7 @@ namespace yg } Tiler::RectInfo::RectInfo() - : m_scale(0), m_x(0), m_y(0), m_coverage(0), m_distance(0) + : m_scale(0), m_x(0), m_y(0), m_distance(0), m_coverage(0) {} Tiler::RectInfo::RectInfo(int scale, int x, int y, m2::RectD const & globRect) @@ -55,18 +56,30 @@ namespace yg bool operator<(Tiler::RectInfo const & l, Tiler::RectInfo const & r) { if (l.m_coverage != r.m_coverage) - return l.m_coverage < r.m_coverage; + return l.m_coverage > r.m_coverage; return l.m_distance < r.m_distance; } + bool operator>(Tiler::RectInfo const & l, Tiler::RectInfo const & r) + { + if (l.m_coverage != r.m_coverage) + return l.m_coverage < r.m_coverage; + + return l.m_distance > r.m_distance; + } + void Tiler::seed(ScreenBase const & screen, int scaleEtalonSize) { + if (screen != m_screen) + ++m_seqNum; + m2::RectD glbRect; m2::PointD pxCenter = screen.PixelRect().Center(); screen.PtoG(m2::RectD(pxCenter - m2::PointD(scaleEtalonSize / 2, scaleEtalonSize / 2), pxCenter + m2::PointD(scaleEtalonSize / 2, scaleEtalonSize / 2)), - glbRect); + glbRect); + m_scale = scales::GetScaleLevel(glbRect); m_screen = screen; @@ -80,11 +93,26 @@ namespace yg int minTileY = floor(screenRect.minY() / rectSizeY); int maxTileY = ceil(screenRect.maxY() / rectSizeY); + unsigned rectCount = 0; + + /// clearing previous coverage + + while (!m_coverage.empty()) + m_coverage.pop(); + for (int tileY = minTileY; tileY < maxTileY; ++tileY) for (int tileX = minTileX; tileX < maxTileX; ++tileX) + { m_coverage.push(RectInfo(m_scale, tileX, tileY, screenRect)); + ++rectCount; + } + + LOG(LINFO, ("Tiler coverage contains ", rectCount, " rectangles")); } + Tiler::Tiler() : m_seqNum(0) + {} + bool Tiler::hasTile() { return !m_coverage.empty(); @@ -96,4 +124,9 @@ namespace yg m_coverage.pop(); return r; } + + size_t Tiler::seqNum() const + { + return m_seqNum; + } } diff --git a/yg/tiler.hpp b/yg/tiler.hpp index b0611c7079..3bb479be25 100644 --- a/yg/tiler.hpp +++ b/yg/tiler.hpp @@ -3,6 +3,7 @@ #include "../geometry/screenbase.hpp" #include "../geometry/rect2d.hpp" #include "../std/queue.hpp" +#include "../std/functional.hpp" namespace yg { @@ -35,11 +36,14 @@ namespace yg ScreenBase m_screen; int m_scale; + size_t m_seqNum; - priority_queue m_coverage; + priority_queue, greater > m_coverage; public: + Tiler(); + /// seed tiler with new screenBase. /// if there are an existing tile sequence it is /// reorganized to reflect screen changes. @@ -49,7 +53,10 @@ namespace yg bool hasTile(); /// pop tile from the sequence and return it RectInfo const nextTile(); + + size_t seqNum() const; }; bool operator <(Tiler::RectInfo const & l, Tiler::RectInfo const & r); + bool operator >(Tiler::RectInfo const & l, Tiler::RectInfo const & r); } diff --git a/yg/yg_tests/skin_loader_test.cpp b/yg/yg_tests/skin_loader_test.cpp index 4120359936..d9db87914f 100644 --- a/yg/yg_tests/skin_loader_test.cpp +++ b/yg/yg_tests/skin_loader_test.cpp @@ -8,6 +8,6 @@ UNIT_TEST(SkinLoaderTest_Main) { GL_TEST_START; - shared_ptr rm(new yg::ResourceManager(1000, 1000, 2, 1000, 1000, 2, 1000, 1000, 2, 128, 128, 15, 256, 256, 5, "", "", "", 2 * 1024 * 1024, 500 * 1024, yg::Rt8Bpp, false, false)); + shared_ptr rm(new yg::ResourceManager(1000, 1000, 2, 1000, 1000, 2, 1000, 1000, 2, 128, 128, 15, 256, 256, 5, 256, 256, 40, "", "", "", 2 * 1024 * 1024, yg::Rt8Bpp, false, false)); /*yg::Skin * skin = */loadSkin(rm, "basic.skn", 2, 2); }; diff --git a/yg/yg_tests/skin_test.cpp b/yg/yg_tests/skin_test.cpp index 85e8cb852c..7137fcb1fb 100644 --- a/yg/yg_tests/skin_test.cpp +++ b/yg/yg_tests/skin_test.cpp @@ -10,7 +10,7 @@ UNIT_TEST(SkinTest_Main) { GL_TEST_START; - shared_ptr rm(new yg::ResourceManager(100, 100, 1, 100, 100, 1, 100, 100, 1, 128, 128, 15, 256, 256, 5, "", "", "", 2 * 1024 * 1024, 500 * 1024, yg::Rt8Bpp, false, false)); + shared_ptr rm(new yg::ResourceManager(100, 100, 1, 100, 100, 1, 100, 100, 1, 128, 128, 15, 256, 256, 5, 256, 256, 40, "", "", "", 2 * 1024 * 1024, yg::Rt8Bpp, false, false)); yg::Skin * skin = loadSkin(rm, "test.skn", 2, 2); double p0 [] = {1, 1};