[core] Throttle tiles to redo symbol placement at most once every 300ms.

Fixes issue #8435 and prepares for pitch-scaling changes in issue #8967.
This commit is contained in:
Chris Loer
2017-05-17 13:49:48 -07:00
committed by Chris Loer
parent e7154adac3
commit 77b24bc0d3
5 changed files with 74 additions and 2 deletions

View File

@@ -593,6 +593,8 @@ set(MBGL_CORE_FILES
src/mbgl/util/thread_context.cpp
src/mbgl/util/thread_context.hpp
src/mbgl/util/thread_local.hpp
src/mbgl/util/throttler.cpp
src/mbgl/util/throttler.hpp
src/mbgl/util/tile_coordinate.hpp
src/mbgl/util/tile_cover.cpp
src/mbgl/util/tile_cover.hpp

View File

@@ -18,6 +18,7 @@
#include <mbgl/map/query.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/logging.hpp>
#include <iostream>
@@ -41,7 +42,8 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_,
obsolete,
parameters.mode),
glyphAtlas(glyphAtlas_),
spriteAtlas(spriteAtlas_) {
spriteAtlas(spriteAtlas_),
placementThrottler(Milliseconds(300), [this] { invokePlacement(); }) {
}
GeometryTile::~GeometryTile() {
@@ -85,7 +87,13 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) {
++correlationID;
requestedConfig = desiredConfig;
worker.invoke(&GeometryTileWorker::setPlacementConfig, desiredConfig, correlationID);
placementThrottler.invoke();
}
void GeometryTile::invokePlacement() {
if (requestedConfig) {
worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID);
}
}
void GeometryTile::redoLayout() {

View File

@@ -6,6 +6,7 @@
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/text/placement_config.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/throttler.hpp>
#include <mbgl/actor/actor.hpp>
#include <atomic>
@@ -88,6 +89,7 @@ protected:
private:
void markObsolete();
void invokePlacement();
const std::string sourceID;
style::Style& style;
@@ -110,6 +112,8 @@ private:
std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
std::unique_ptr<CollisionTile> collisionTile;
util::Throttler placementThrottler;
};
} // namespace mbgl

View File

@@ -0,0 +1,36 @@
#include <mbgl/util/throttler.hpp>
namespace mbgl {
namespace util {
Throttler::Throttler(Duration frequency_, std::function<void()>&& function_)
: frequency(frequency_)
, function(std::move(function_))
, pendingInvocation(false)
, lastInvocation(TimePoint::min())
{}
void Throttler::invoke() {
if (pendingInvocation) {
return;
}
Duration timeToNextInvocation = lastInvocation == TimePoint::min()
? Duration::zero()
: (lastInvocation + frequency) - Clock::now();
if (timeToNextInvocation <= Duration::zero()) {
lastInvocation = Clock::now();
function();
} else {
pendingInvocation = true;
timer.start(timeToNextInvocation, Duration::zero(), [this]{
pendingInvocation = false;
lastInvocation = Clock::now();
function();
});
}
}
} // namespace util
} // namespace mbgl

View File

@@ -0,0 +1,22 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/timer.hpp>
namespace mbgl {
namespace util {
class Throttler {
public:
Throttler(Duration frequency, std::function<void()>&& function);
void invoke();
private:
Duration frequency;
std::function<void()> function;
Timer timer;
bool pendingInvocation;
TimePoint lastInvocation;
};
} // namespace util
} // namespace mbgl