X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fmixer%2Fimage%2Fimage_mixer.cpp;h=7d1d595e0e60313cbf1fcd25f5276461a0e8147f;hb=0b7bab6c3bcaef9971d2d2d05fba0dc822dd9b29;hp=f7e403dd35e1167f35510562261af1cf193cb229;hpb=17a8853f08f9744a5cd0ac34053d1138824260ba;p=casparcg diff --git a/core/mixer/image/image_mixer.cpp b/core/mixer/image/image_mixer.cpp index f7e403dd3..7d1d595e0 100644 --- a/core/mixer/image/image_mixer.cpp +++ b/core/mixer/image/image_mixer.cpp @@ -37,59 +37,46 @@ #include #include +#include + #include #include +#include #include #include +#include #include namespace caspar { namespace core { struct image_mixer::implementation : boost::noncopyable { - typedef std::deque layer; + typedef std::deque layer; - video_channel_context& channel_; + video_channel_context& channel_; - std::vector transform_stack_; - std::vector mode_stack_; + std::vector transform_stack_; + std::vector mode_stack_; - std::queue> layers_; // layer/stream/items + std::deque> layers_; // layer/stream/items - image_kernel kernel_; + image_kernel kernel_; - std::array,2> draw_buffer_; - std::shared_ptr write_buffer_; - - std::array,2> stream_key_buffer_; - std::shared_ptr layer_key_buffer_; - + std::shared_ptr draw_buffer_; public: implementation(video_channel_context& video_channel) : channel_(video_channel) , transform_stack_(1) , mode_stack_(1, video_mode::progressive) { - initialize_buffers(); } ~implementation() { channel_.ogl().gc(); } - - void initialize_buffers() - { - write_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4); - layer_key_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1); - draw_buffer_[0] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4); - draw_buffer_[1] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4); - stream_key_buffer_[0] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1); - stream_key_buffer_[1] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1); - channel_.ogl().gc(); - } - + void begin(core::basic_frame& frame) { transform_stack_.push_back(transform_stack_.back()*frame.get_image_transform()); @@ -104,12 +91,11 @@ public: if(boost::range::find(mode_stack_, video_mode::upper) != mode_stack_.end() && boost::range::find(mode_stack_, video_mode::lower) != mode_stack_.end()) return; - core::render_item item = {frame.get_pixel_format_desc(), frame.get_textures(), transform_stack_.back(), mode_stack_.back(), frame.tag()}; + core::render_item item(frame.get_pixel_format_desc(), frame.get_textures(), transform_stack_.back(), mode_stack_.back(), frame.tag()); auto& layer = layers_.back(); - auto it = boost::range::find(layer, item); - if(it == layer.end()) + if(boost::range::find(layer, item) == layer.end()) layer.push_back(item); } @@ -121,7 +107,7 @@ public: void begin_layer() { - layers_.push(layer()); + layers_.push_back(layer()); } void end_layer() @@ -131,69 +117,61 @@ public: boost::unique_future> render() { auto layers = std::move(layers_); - - return channel_.ogl().begin_invoke([=]() mutable -> safe_ptr - { - if(channel_.get_format_desc().width != write_buffer_->width() || channel_.get_format_desc().height != write_buffer_->height()) - initialize_buffers(); - - return do_render(std::move(layers)); + return channel_.ogl().begin_invoke([=]()mutable + { + return render(std::move(layers)); }); } - safe_ptr do_render(std::queue&& layers) + safe_ptr render(std::deque&& layers) { - auto read_buffer = channel_.ogl().create_host_buffer(channel_.get_format_desc().size, host_buffer::read_only); + std::shared_ptr layer_key_buffer; - layer_key_buffer_->clear(); - draw_buffer_[0]->clear(); - draw_buffer_[1]->clear(); - stream_key_buffer_[0]->clear(); - stream_key_buffer_[1]->clear(); + draw_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4); + channel_.ogl().clear(*draw_buffer_); + + BOOST_FOREACH(auto& layer, layers) + draw(std::move(layer), layer_key_buffer); + + auto host_buffer = channel_.ogl().create_host_buffer(channel_.get_format_desc().size, host_buffer::read_only); + channel_.ogl().attach(*draw_buffer_); + host_buffer->begin_read(draw_buffer_->width(), draw_buffer_->height(), format(draw_buffer_->stride())); + + GL(glFlush()); + + return host_buffer; + } - bool local_key = false; - bool layer_key = false; + void draw(layer&& layer, std::shared_ptr& layer_key_buffer) + { + std::shared_ptr local_key_buffer; - while(!layers.empty()) - { - stream_key_buffer_[0]->clear(); + BOOST_FOREACH(auto& item, layer) + draw(std::move(item), local_key_buffer, layer_key_buffer); + + std::swap(local_key_buffer, layer_key_buffer); + } - auto layer = std::move(layers.front()); - layers.pop(); - - while(!layer.empty()) + void draw(render_item&& item, std::shared_ptr& local_key_buffer, std::shared_ptr& layer_key_buffer) + { + if(item.transform.get_is_key()) + { + if(!local_key_buffer) { - auto item = std::move(layer.front()); - layer.pop_front(); - - if(item.transform.get_is_key()) - { - render_item(stream_key_buffer_, std::move(item), nullptr, nullptr); - local_key = true; - } - else - { - render_item(draw_buffer_, std::move(item), local_key ? stream_key_buffer_[0] : nullptr, layer_key ? layer_key_buffer_ : nullptr); - stream_key_buffer_[0]->clear(); - local_key = false; - } - channel_.ogl().yield(); // Return resources to pool as early as possible. + local_key_buffer = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1); + channel_.ogl().clear(*local_key_buffer); } - layer_key = local_key; - local_key = false; - std::swap(stream_key_buffer_[0], layer_key_buffer_); + draw(std::move(item), local_key_buffer, nullptr, nullptr); + } + else + { + draw(std::move(item), draw_buffer_, local_key_buffer, layer_key_buffer); + local_key_buffer.reset(); } - - std::swap(draw_buffer_[0], write_buffer_); - - // device -> host. - read_buffer->begin_read(*write_buffer_); - - return read_buffer; } - void render_item(std::array,2>& targets, render_item&& item, const std::shared_ptr& local_key, const std::shared_ptr& layer_key) + void draw(render_item&& item, std::shared_ptr& draw_buffer, const std::shared_ptr& local_key, const std::shared_ptr& layer_key) { if(!std::all_of(item.textures.begin(), item.textures.end(), std::mem_fn(&device_buffer::ready))) { @@ -201,15 +179,7 @@ public: channel_.ogl().yield(); // Try to give it some more time. } - targets[1]->attach(); - - kernel_.draw(item, make_safe(targets[0]), local_key, layer_key); - - targets[0]->bind(); - - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, targets[0]->width(), targets[0]->height()); - - std::swap(targets[0], targets[1]); + kernel_.draw(channel_.ogl(), std::move(item), make_safe(draw_buffer), local_key, layer_key); } safe_ptr create_frame(const void* tag, const core::pixel_format_desc& desc)