]> git.sesse.net Git - casparcg/commitdiff
[text_producer] Don't upload texture atlas to GPU every time the text or tracking...
authorHelge Norberg <helge.norberg@svt.se>
Wed, 15 Mar 2017 18:30:12 +0000 (19:30 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 15 Mar 2017 18:30:12 +0000 (19:30 +0100)
core/frame/frame.cpp
core/frame/frame.h
core/producer/text/text_producer.cpp
core/producer/text/utils/texture_atlas.cpp
core/producer/text/utils/texture_atlas.h
core/producer/text/utils/texture_font.cpp
core/producer/text/utils/texture_font.h

index f2c5fa01a4b0108794895f0a02ec7de1ebae1ed4..2feb67ec4dcb2eeaef4091219bf18cdcdb10286f 100644 (file)
@@ -129,6 +129,20 @@ struct const_frame::impl : boost::noncopyable
                recorded_age_ = 0;
        }
 
+       impl(const impl& other)
+               : future_buffers_(other.future_buffers_)
+               , audio_data_(other.audio_data_)
+               , desc_(other.desc_)
+               , channel_layout_(other.channel_layout_)
+               , tag_(other.tag_)
+               , geometry_(other.geometry_)
+               , since_created_timer_(other.since_created_timer_)
+               , should_record_age_(other.should_record_age_)
+               , key_only_on_demand_(other.key_only_on_demand_)
+       {
+               recorded_age_ = other.recorded_age_;
+       }
+
        impl(
                        std::shared_future<array<const std::uint8_t>> image,
                        audio_buffer audio_data,
@@ -237,6 +251,7 @@ const_frame& const_frame::operator=(const_frame&& other)
        return *this;
 }
 const_frame::const_frame(const const_frame& other) : impl_(other.impl_){}
+const_frame::const_frame(const const_frame::impl& other) : impl_(new impl(other)) {}
 const_frame& const_frame::operator=(const const_frame& other)
 {
        impl_ = other.impl_;
@@ -255,7 +270,14 @@ std::size_t const_frame::height()const{return impl_->height();}
 std::size_t const_frame::size()const{return impl_->size();}
 const void* const_frame::stream_tag()const{return impl_->tag_;}
 const frame_geometry& const_frame::geometry() const { return impl_->geometry_; }
-void const_frame::set_geometry(const frame_geometry& g) { impl_->geometry_ = g; }
+const_frame const_frame::with_geometry(const frame_geometry& g) const
+{
+       const_frame copy(*impl_);
+
+       copy.impl_->geometry_ = g;
+
+       return copy;
+}
 int64_t const_frame::get_age_millis() const { return impl_->get_age_millis(); }
 const_frame const_frame::key_only() const
 {
index fff5382c845a715e34cecb93380e2dd107852be5..640a6589e3027cea195813d7da3f95e792816026 100644 (file)
@@ -75,6 +75,7 @@ private:
 
 class const_frame final
 {
+       struct impl;
 public:
 
        // Static Members
@@ -97,6 +98,7 @@ public:
        const_frame(const_frame&& other);
        const_frame& operator=(const_frame&& other);
        const_frame(const const_frame&);
+       const_frame(const const_frame::impl&);
        const_frame& operator=(const const_frame& other);
 
        const_frame key_only() const;
@@ -116,7 +118,7 @@ public:
        const void* stream_tag() const;
 
        const core::frame_geometry& geometry() const;
-       void set_geometry(const frame_geometry& g);
+       const_frame with_geometry(const frame_geometry& g) const;
        int64_t get_age_millis() const;
 
        bool operator==(const const_frame& other);
@@ -125,7 +127,6 @@ public:
        bool operator>(const const_frame& other);
 
 private:
-       struct impl;
        spl::shared_ptr<impl> impl_;
 };
 
index 4bcf08519a69a4419c26c8ef73f95a14184ac971..4a00b460892822a6b69f9fcf83a93fb7f68d89e3 100644 (file)
@@ -145,6 +145,7 @@ struct text_producer::impl
        draw_frame                                                              frame_;
        text::texture_atlas                                             atlas_                                          { 1024, 512, 4 };
        text::texture_font                                              font_;
+       const_frame                                                             atlas_frame_;
 
 public:
        explicit impl(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, text::text_info& text_info, long parent_width, long parent_height, bool standalone)
@@ -159,6 +160,8 @@ public:
                font_.load_glyphs(text::unicode_block::Latin_1_Supplement, text_info.color);
                font_.load_glyphs(text::unicode_block::Latin_Extended_A, text_info.color);
 
+               atlas_frame_ = create_atlas_frame();
+
                tracking_.value().set(text_info.tracking);
                scale_x_.value().set(text_info.scale_x);
                scale_y_.value().set(text_info.scale_y);
@@ -183,18 +186,22 @@ public:
                CASPAR_LOG(info) << print() << L" Initialized";
        }
 
-       void generate_frame()
+       core::const_frame create_atlas_frame() const
        {
                core::pixel_format_desc pfd(core::pixel_format::bgra);
                pfd.planes.push_back(core::pixel_format_desc::plane(static_cast<int>(atlas_.width()), static_cast<int>(atlas_.height()), static_cast<int>(atlas_.depth())));
+               auto frame = frame_factory_->create_frame(this, pfd, core::audio_channel_layout::invalid());
+               memcpy(frame.image_data().data(), atlas_.data(), frame.image_data().size());
+               return frame;
+       }
 
+       void generate_frame()
+       {
                text::string_metrics metrics;
-               font_.set_tracking(static_cast<int>(tracking_.value().get()));
+               font_.set_tracking(tracking_.value().get());
 
                auto vertex_stream = font_.create_vertex_stream(text_.value().get(), x_, y_, parent_width_, parent_height_, &metrics, shear_.value().get());
-               auto frame = frame_factory_->create_frame(vertex_stream.data(), pfd, core::audio_channel_layout::invalid());
-               memcpy(frame.image_data().data(), atlas_.data(), frame.image_data().size());
-               frame.set_geometry(frame_geometry(frame_geometry::geometry_type::quad_list, std::move(vertex_stream)));
+               auto frame = atlas_frame_.with_geometry(frame_geometry(frame_geometry::geometry_type::quad_list, std::move(vertex_stream)));
 
                this->constraints_.width.set(metrics.width * this->scale_x_.value().get());
                this->constraints_.height.set(metrics.height * this->scale_y_.value().get());
index 0622d58581a81ffd615f4b1e1d77061c106b2900..8213f16f5ddee107a81d81fd3dbe049b2aad27b6 100644 (file)
@@ -57,14 +57,12 @@ private:
        size_t width_;
        size_t height_;
        size_t depth_;
-       const unsigned char* dataptr_;
-       std::vector<unsigned char> data_;
+       std::vector<uint8_t> data_;
        size_t used_                                            = 0;
 
 public:
        impl(const size_t width, const size_t height, const size_t depth) : width_(width), height_(height), depth_(depth), data_(width*height*depth, 0)
        {
-               dataptr_ = data_.data();
                // We want a one pixel border around the whole atlas to avoid any artefact when sampling texture
                node n = {1, 1, static_cast<int>(width_) - 2};
                nodes_.push_back(n);
@@ -94,7 +92,7 @@ public:
                                }
                        }
                }
-   
+
                if(best_it == nodes_.end())
                {
                        region.x = -1;
@@ -165,10 +163,10 @@ public:
                data_.assign(width_*height_*depth_, 0);
        }
 
-       size_t depth() { return depth_; }
-       size_t width() { return width_; }
-       size_t height() { return height_; }
-       unsigned char* data() { return data_.data(); }
+       size_t depth() const { return depth_; }
+       size_t width() const { return width_; }
+       size_t height() const { return height_; }
+       const uint8_t* data() const { return data_.data(); }
 
 private:
        int fit(node_iterator it, const size_t width, const size_t height)
@@ -215,15 +213,15 @@ private:
 };
 
 texture_atlas::texture_atlas(const size_t w, const size_t h, const size_t d) : impl_(new impl(w, h, d)) {}
-rect texture_atlas::get_region(int width, int height) { return impl_->get_region(width, height); }
+rect texture_atlas::get_region(int width, int height) const { return impl_->get_region(width, height); }
 void texture_atlas::set_region(const size_t x, const size_t y, const size_t width, const size_t height, const unsigned char *src, const size_t stride, const color<double>& col)
        { impl_->set_region(x, y, width, height, src, stride, col); }
 
 void texture_atlas::clear() { impl_->clear(); }
 
-size_t texture_atlas::width() { return impl_->width(); }
-size_t texture_atlas::height() { return impl_->height(); }
-size_t texture_atlas::depth() { return impl_->depth(); }
-unsigned char* texture_atlas::data() { return impl_->data(); }
+size_t texture_atlas::width() const { return impl_->width(); }
+size_t texture_atlas::height() const { return impl_->height(); }
+size_t texture_atlas::depth() const { return impl_->depth(); }
+const uint8_t* texture_atlas::data() const { return impl_->data(); }
 
-}}}
\ No newline at end of file
+}}}
index 4831158dfa9cd6c2bdf92023b0ddbad6ef51943f..e3ad0462d4ee24836d9be112ef6fd6f454a14d79 100644 (file)
@@ -80,15 +80,15 @@ class texture_atlas
 public:
        texture_atlas(const size_t w, const size_t h, const size_t d);
 
-       rect get_region(int width, int height);
+       rect get_region(int width, int height) const;
        void set_region(const size_t x, const size_t y, const size_t width, const size_t height, const unsigned char *data, const size_t stride, const color<double>& col);
        void clear();
 
-       size_t depth();
-       size_t width();
-       size_t height();
+       size_t depth() const;
+       size_t width() const;
+       size_t height() const;
 
-       unsigned char* data();
+       const uint8_t* data() const;
 
 private:
        struct impl;
index ae38582131d756eefd6aef00f84dcab52ebe51a4..5a0421701e9078f797a1fd1ed827f4f4b49a58dc 100644 (file)
@@ -57,7 +57,7 @@ public:
                        CASPAR_THROW_EXCEPTION(expected_freetype_exception() << msg_info("Failed to set font size"));
        }
 
-       void set_tracking(int tracking)
+       void set_tracking(double tracking)
        {
                tracking_ = size_ * tracking / 1000.0;
        }
@@ -285,7 +285,7 @@ public:
 
 texture_font::texture_font(texture_atlas& atlas, const text_info& info, bool normalize_coordinates) : impl_(new impl(atlas, info, normalize_coordinates)) {}
 void texture_font::load_glyphs(unicode_block range, const color<double>& col) { impl_->load_glyphs(range, col); }
-void texture_font::set_tracking(int tracking) { impl_->set_tracking(tracking); }
+void texture_font::set_tracking(double tracking) { impl_->set_tracking(tracking); }
 std::vector<frame_geometry::coord> texture_font::create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height, string_metrics* metrics, double shear) { return impl_->create_vertex_stream(str, x, y, parent_width, parent_height, metrics, shear); }
 string_metrics texture_font::measure_string(const std::wstring& str) { return impl_->measure_string(str); }
 std::wstring texture_font::get_name() const { return impl_->get_name(); }
index 89662c134845e640b440d7e3cfd3aab4b26ec54f..11855adfaee4c14957a94795a8a0388af44607cd 100644 (file)
@@ -22,7 +22,7 @@ class texture_font
 public:
        texture_font(texture_atlas&, const text_info&, bool normalize_coordinates);
        void load_glyphs(unicode_block block, const color<double>& col);
-       void set_tracking(int tracking);
+       void set_tracking(double tracking);
        std::vector<frame_geometry::coord> create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height, string_metrics* metrics, double shear = 0.0);
        string_metrics measure_string(const std::wstring& str);
        std::wstring get_name() const;
@@ -257,4 +257,4 @@ enum class unicode_block
        Supplementary_Private_Use_Area_B
 };
 
-}}}
\ No newline at end of file
+}}}