From d7ba7dc0db62514aa50bbe3869dba3aaf1aedabd Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Tue, 2 Aug 2016 12:46:39 +0000 Subject: [PATCH] agg renderer: recycle internal buffers --- include/mapnik/agg_renderer.hpp | 51 ++++++++++++++++++++++++++++++++- src/agg/agg_renderer.cpp | 34 +++++++++++++++------- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index c237cf4f4..27a22b74a 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -35,6 +35,7 @@ #include #include #include +#include // stl #include #include @@ -59,6 +60,53 @@ namespace mapnik { namespace mapnik { +template +class buffer_stack +{ +public: + buffer_stack(std::size_t width, std::size_t height) + : width_(width), + height_(height), + buffers_(), + position_(buffers_.begin()) + { + } + + T & push() + { + if (position_ == buffers_.begin()) + { + buffers_.emplace_front(width_, height_); + position_ = buffers_.begin(); + } + else + { + position_--; + mapnik::fill(*position_, 0); // fill with transparent colour + } + return *position_; + } + + void pop() + { + if (position_ != buffers_.end()) + { + position_++; + } + } + + T & top() const + { + return *position_; + } + +private: + const std::size_t width_; + const std::size_t height_; + std::deque buffers_; + typename std::deque::iterator position_; +}; + template class MAPNIK_DECL agg_renderer : public feature_style_processor >, private util::noncopyable @@ -162,7 +210,8 @@ protected: private: std::stack> buffers_; - std::stack internal_buffers_; + buffer_stack internal_buffers_; + std::unique_ptr inflated_buffer_; const std::unique_ptr ras_ptr; gamma_method_enum gamma_method_; double gamma_; diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index de2430dad..ed28335ef 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -41,8 +41,8 @@ #include #include #include -#include #include +#include #pragma GCC diagnostic push #include @@ -72,7 +72,8 @@ template agg_renderer::agg_renderer(Map const& m, T0 & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), buffers_(), - internal_buffers_(), + internal_buffers_(m.width(), m.height()), + inflated_buffer_(), ras_ptr(new rasterizer), gamma_method_(GAMMA_POWER), gamma_(1.0), @@ -85,7 +86,8 @@ template agg_renderer::agg_renderer(Map const& m, request const& req, attributes const& vars, T0 & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), buffers_(), - internal_buffers_(), + internal_buffers_(req.width(), req.height()), + inflated_buffer_(), ras_ptr(new rasterizer), gamma_method_(GAMMA_POWER), gamma_(1.0), @@ -99,7 +101,8 @@ agg_renderer::agg_renderer(Map const& m, T0 & pixmap, std::shared_ptr double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), buffers_(), - internal_buffers_(), + internal_buffers_(m.width(), m.height()), + inflated_buffer_(), ras_ptr(new rasterizer), gamma_method_(GAMMA_POWER), gamma_(1.0), @@ -225,8 +228,7 @@ void agg_renderer::start_layer_processing(layer const& lay, box2d if (lay.comp_op() || lay.get_opacity() < 1.0) { - internal_buffers_.emplace(common_.width_, common_.height_); - buffers_.emplace(internal_buffers_.top()); + buffers_.emplace(internal_buffers_.push()); set_premultiplied_alpha(buffers_.top().get(), true); } else @@ -279,15 +281,24 @@ void agg_renderer::start_style_processing(feature_type_style const& st) unsigned target_width = common_.width_ + (offset * 2); unsigned target_height = common_.height_ + (offset * 2); ras_ptr->clip_box(-int(offset*2),-int(offset*2),target_width,target_height); - internal_buffers_.emplace(target_width, target_height); + if (!inflated_buffer_ || + (inflated_buffer_->width() < target_width || + inflated_buffer_->height() < target_height)) + { + inflated_buffer_ = std::make_unique(target_width, target_height); + } + else + { + mapnik::fill(*inflated_buffer_, 0); // fill with transparent colour + } + buffers_.emplace(*inflated_buffer_); } else { - internal_buffers_.emplace(common_.width_, common_.height_); + buffers_.emplace(internal_buffers_.push()); common_.t_.set_offset(0); ras_ptr->clip_box(0,0,common_.width_,common_.height_); } - buffers_.emplace(internal_buffers_.top()); set_premultiplied_alpha(buffers_.top().get(), true); } else @@ -331,7 +342,10 @@ void agg_renderer::end_style_processing(feature_type_style const& st) -common_.t_.offset(), -common_.t_.offset()); } - internal_buffers_.pop(); + if (¤t_buffer == &internal_buffers_.top()) + { + internal_buffers_.pop(); + } } if (st.direct_image_filters().size() > 0) {