agg renderer: recycle internal buffers

This commit is contained in:
Jiri Drbalek 2016-08-02 12:46:39 +00:00
parent 03929b5c76
commit d7ba7dc0db
2 changed files with 74 additions and 11 deletions

View file

@ -35,6 +35,7 @@
#include <mapnik/request.hpp>
#include <mapnik/symbolizer_enumerations.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/image_util.hpp>
// stl
#include <memory>
#include <stack>
@ -59,6 +60,53 @@ namespace mapnik {
namespace mapnik {
template <typename T>
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<T> buffers_;
typename std::deque<T>::iterator position_;
};
template <typename T0, typename T1=label_collision_detector4>
class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T0> >,
private util::noncopyable
@ -162,7 +210,8 @@ protected:
private:
std::stack<std::reference_wrapper<buffer_type>> buffers_;
std::stack<buffer_type> internal_buffers_;
buffer_stack<buffer_type> internal_buffers_;
std::unique_ptr<buffer_type> inflated_buffer_;
const std::unique_ptr<rasterizer> ras_ptr;
gamma_method_enum gamma_method_;
double gamma_;

View file

@ -41,8 +41,8 @@
#include <mapnik/pixel_position.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/image_filter.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/image_any.hpp>
#include <mapnik/make_unique.hpp>
#pragma GCC diagnostic push
#include <mapnik/warning_ignore_agg.hpp>
@ -72,7 +72,8 @@ template <typename T0, typename T1>
agg_renderer<T0,T1>::agg_renderer(Map const& m, T0 & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(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 <typename T0, typename T1>
agg_renderer<T0,T1>::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<agg_renderer>(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<T0,T1>::agg_renderer(Map const& m, T0 & pixmap, std::shared_ptr<T1>
double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<agg_renderer>(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<T0,T1>::start_layer_processing(layer const& lay, box2d<double>
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<T0,T1>::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<buffer_type>(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<T0,T1>::end_style_processing(feature_type_style const& st)
-common_.t_.offset(),
-common_.t_.offset());
}
internal_buffers_.pop();
if (&current_buffer == &internal_buffers_.top())
{
internal_buffers_.pop();
}
}
if (st.direct_image_filters().size() > 0)
{