From 2cfe40e47c46a652eed324a73cd68bc23bbcf4b7 Mon Sep 17 00:00:00 2001 From: ronag Date: Thu, 25 Aug 2011 07:48:36 +0000 Subject: [PATCH] 2.0. image_mixer: Refactored, draw fields in separate draw calls. This way we don't need to worry about fields in the drawing code. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1280 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- core/mixer/image/image_mixer.cpp | 120 ++++++++++++++++--------------- core/mixer/mixer.cpp | 4 +- core/producer/frame_producer.cpp | 8 +-- shell/casparcg.config | 38 ++++------ 4 files changed, 81 insertions(+), 89 deletions(-) diff --git a/core/mixer/image/image_mixer.cpp b/core/mixer/image/image_mixer.cpp index 941e28d6c..ec167ce39 100644 --- a/core/mixer/image/image_mixer.cpp +++ b/core/mixer/image/image_mixer.cpp @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -80,13 +81,35 @@ public: private: safe_ptr do_render(std::vector&& layers) { - std::shared_ptr layer_key_buffer; - auto draw_buffer = create_device_buffer(4); - - BOOST_FOREACH(auto& layer, layers) - draw_layer(std::move(layer), draw_buffer, layer_key_buffer); - + + if(channel_.get_format_desc().field_mode != field_mode::progressive) + { + auto upper = layers; + auto lower = std::move(layers); + + BOOST_FOREACH(auto& layer, upper) + { + boost::remove_erase_if(layer.items, [](const render_item& item){return !(item.transform.field_mode & field_mode::upper);}); + BOOST_FOREACH(auto& item, layer.items) + item.transform.field_mode = field_mode::upper; + } + + BOOST_FOREACH(auto& layer, lower) + { + boost::remove_erase_if(layer.items, [](const render_item& item){return !(item.transform.field_mode & field_mode::lower);}); + BOOST_FOREACH(auto& item, layer.items) + item.transform.field_mode = field_mode::lower; + } + + draw(std::move(upper), *draw_buffer); + draw(std::move(lower), *draw_buffer); + } + else + { + draw(std::move(layers), *draw_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())); @@ -98,16 +121,27 @@ private: return host_buffer; } - void draw_layer(layer&& layer, const safe_ptr& draw_buffer, std::shared_ptr& layer_key_buffer) + void draw(std::vector&& layers, + device_buffer& draw_buffer) + { + std::shared_ptr layer_key_buffer; + + BOOST_FOREACH(auto& layer, layers) + draw_layer(std::move(layer), draw_buffer, layer_key_buffer); + } + + void draw_layer(layer&& layer, + device_buffer& draw_buffer, + std::shared_ptr& layer_key_buffer) { if(layer.items.empty()) return; - std::pair> local_key_buffer = std::make_pair(0, nullptr); // int is fields flag + std::shared_ptr local_key_buffer; - if(layer.blend_mode != blend_mode::normal && has_overlapping_items(layer)) + if(layer.blend_mode != blend_mode::normal && layer.items.size() > 1) { - auto layer_draw_buffer = create_device_buffer(4); // int is fields flag + auto layer_draw_buffer = create_device_buffer(4); BOOST_FOREACH(auto& item, layer.items) draw_item(std::move(item), *layer_draw_buffer, local_key_buffer, layer_key_buffer); @@ -119,63 +153,34 @@ private: item.transform = frame_transform(); item.blend_mode = layer.blend_mode; - kernel_.draw(channel_.ogl(), std::move(item), *draw_buffer, nullptr, nullptr); + kernel_.draw(channel_.ogl(), std::move(item), draw_buffer, nullptr, nullptr); } else // fast path { BOOST_FOREACH(auto& item, layer.items) - draw_item(std::move(item), *draw_buffer, local_key_buffer, layer_key_buffer); + draw_item(std::move(item), draw_buffer, local_key_buffer, layer_key_buffer); } - - CASPAR_ASSERT(local_key_buffer.first == 0 || local_key_buffer.first == core::field_mode::progressive); - - std::swap(local_key_buffer.second, layer_key_buffer); + + std::swap(local_key_buffer, layer_key_buffer); } - void draw_item(render_item&& item, - device_buffer& draw_buffer, - std::pair>& local_key_buffer, - std::shared_ptr& layer_key_buffer) - { + void draw_item(render_item&& item, + device_buffer& draw_buffer, + std::shared_ptr& local_key_buffer, + std::shared_ptr& layer_key_buffer) + { if(item.transform.is_key) { - if(!local_key_buffer.second) - { - local_key_buffer.first = 0; - local_key_buffer.second = create_device_buffer(1); - } - - local_key_buffer.first |= item.transform.field_mode; // Add field to flag. - kernel_.draw(channel_.ogl(), std::move(item), *local_key_buffer.second, nullptr, nullptr); + local_key_buffer = local_key_buffer ? local_key_buffer : create_device_buffer(1); + kernel_.draw(channel_.ogl(), std::move(item), *local_key_buffer, nullptr, nullptr); } else { - kernel_.draw(channel_.ogl(), std::move(item), draw_buffer, local_key_buffer.second, layer_key_buffer); - local_key_buffer.first ^= item.transform.field_mode; // Remove field from flag. - - if(local_key_buffer.first == 0) // If all fields from key has been used, reset it - { - local_key_buffer.first = 0; - local_key_buffer.second.reset(); - } - } + kernel_.draw(channel_.ogl(), std::move(item), draw_buffer, local_key_buffer, layer_key_buffer); + local_key_buffer = nullptr; + } } - - bool has_overlapping_items(const layer& layer) - { - auto upper_count = boost::range::count_if(layer.items, [&](const render_item& item) - { - return !item.transform.is_key && (item.transform.field_mode & field_mode::upper); - }); - - auto lower_count = boost::range::count_if(layer.items, [&](const render_item& item) - { - return !item.transform.is_key && (item.transform.field_mode & field_mode::lower); - }); - - return upper_count > 1 || lower_count > 1; - } - + safe_ptr create_device_buffer(size_t stride) { auto buffer = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, stride); @@ -183,7 +188,6 @@ private: return buffer; } }; - struct image_mixer::implementation : boost::noncopyable { @@ -210,10 +214,10 @@ public: } void visit(core::write_frame& frame) - { - if(transform_stack_.back().field_mode == field_mode::empty) + { + if(frame.get_frame_transform().field_mode == field_mode::empty) return; - + core::render_item item; item.pix_desc = frame.get_pixel_format_desc(); item.textures = frame.get_textures(); diff --git a/core/mixer/mixer.cpp b/core/mixer/mixer.cpp index f539fba1d..4fbf8d8a5 100644 --- a/core/mixer/mixer.cpp +++ b/core/mixer/mixer.cpp @@ -126,9 +126,7 @@ public: { auto frame2 = make_safe(frame.second); frame2->get_frame_transform() = transforms_[frame.first].fetch_and_tick(1); - - if(frame1->get_frame_transform() != frame2->get_frame_transform()) - frame1 = core::basic_frame::interlace(frame1, frame2, channel_.get_format_desc().field_mode); + frame1 = core::basic_frame::interlace(frame1, frame2, channel_.get_format_desc().field_mode); } frame1->accept(audio_mixer_); diff --git a/core/producer/frame_producer.cpp b/core/producer/frame_producer.cpp index a17fa10ba..cae3c0bcf 100644 --- a/core/producer/frame_producer.cpp +++ b/core/producer/frame_producer.cpp @@ -55,10 +55,10 @@ public: auto empty_producer = frame_producer::empty(); destroy_context_.begin_invoke([=] { - if(!mov_producer.value.unique()) - CASPAR_LOG(debug) << mov_producer.value->print() << L" Not destroyed on safe asynchronous destruction thread."; - else - CASPAR_LOG(debug) << mov_producer.value->print() << L" Destroying on safe asynchronous destruction thread."; + //if(!mov_producer.value.unique()) + // CASPAR_LOG(debug) << mov_producer.value->print() << L" Not destroyed on safe asynchronous destruction thread."; + //else + // CASPAR_LOG(debug) << mov_producer.value->print() << L" Destroying on safe asynchronous destruction thread."; mov_producer.value = empty_producer; }); diff --git a/shell/casparcg.config b/shell/casparcg.config index ed235ac3c..36a38ca7a 100644 --- a/shell/casparcg.config +++ b/shell/casparcg.config @@ -1,7 +1,7 @@ - C:\Lokala Filer\server\branches\2.0.0.2\bin\_media\ + L:\casparcg\_media\ L:\casparcg\_log\ L:\casparcg\_data\ L:\casparcg\_templates\ @@ -13,45 +13,35 @@ 3 - true + false 1 true - 1080p5000 - cg.fth.18 - 1280 - 720 - - - 720p5000 - cg.fth.18 - 1280 - 720 + 1080i5994 + cg.fth.18.6000 - 1080i5000 + 1080p5000 cg.fth.18 1280 720 - - PAL - cg.fth.18 - - - NTSC - cg.fth.18 - - - + + - PAL + 1080i5000 + + 1 + true + true + + 1 -- 2.39.2