]> git.sesse.net Git - casparcg/commitdiff
2.0. image_mixer: Refactored.
authorRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 21 Aug 2011 11:29:47 +0000 (11:29 +0000)
committerRonag <Ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sun, 21 Aug 2011 11:29:47 +0000 (11:29 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1244 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

core/mixer/image/image_kernel.cpp
core/mixer/image/image_kernel.h
core/mixer/image/image_mixer.cpp
modules/decklink/interop/DeckLinkAPI_h.h
modules/decklink/interop/DeckLinkAPI_i.c

index b4505d06510c49225bb9dcba647166d7b6676607..2765f09b955b8f3d2c508e0e208d63ce8ebbb7f3 100644 (file)
@@ -249,7 +249,7 @@ void image_kernel::draw(ogl_device& ogl,
 \r
 bool operator==(const render_item& lhs, const render_item& rhs)\r
 {\r
-       return lhs.textures == rhs.textures && lhs.transform == rhs.transform && lhs.tag == rhs.tag;\r
+       return lhs.textures == rhs.textures && lhs.transform == rhs.transform;\r
 }\r
 \r
 }}
\ No newline at end of file
index 6b0fd32ef7355d5bd8385579a3fa8c825173a483..ea81f75a8d0b3fd9ef3353109c14b526ad6ee3cc 100644 (file)
@@ -38,7 +38,6 @@ struct render_item
        pixel_format_desc                                               pix_desc;\r
        std::vector<safe_ptr<device_buffer>>    textures;\r
        image_transform                                                 transform;\r
-       const void*                                                             tag;\r
        blend_mode::type                                                blend_mode;\r
 };\r
 \r
index 906ceea5a9fc84cda7d5fdbbb60debee5e8b96ca..0877430de64c03618018cc3b8ca1824e1b3a8ace 100644 (file)
 #include <deque>\r
 #include <unordered_map>\r
 \r
-namespace caspar { namespace core {\r
-               \r
-struct image_mixer::implementation : boost::noncopyable\r
-{              \r
-       typedef std::deque<render_item>                 layer;\r
-\r
-       video_channel_context&                                  channel_;\r
-\r
-       std::vector<image_transform>                    transform_stack_;\r
-       std::stack<blend_mode::type>                    blend_mode_stack_;\r
+using namespace boost::assign;\r
 \r
-       std::deque<std::deque<render_item>>             layers_; // layer/stream/items\r
+namespace caspar { namespace core {\r
        \r
-       image_kernel                                                    kernel_;                \r
+typedef std::deque<render_item>                                layer;\r
 \r
+class image_renderer\r
+{\r
+       video_channel_context&                                  channel_;       \r
+       image_kernel                                                    kernel_;        \r
        std::shared_ptr<device_buffer>                  active_buffer_;\r
 public:\r
-       implementation(video_channel_context& video_channel) \r
-               : channel_(video_channel)\r
-               , transform_stack_(1)\r
+       image_renderer(video_channel_context& channel)\r
+               : channel_(channel)\r
        {\r
        }\r
-\r
-       ~implementation()\r
-       {\r
-               channel_.ogl().gc();\r
-       }\r
        \r
-       void begin(core::basic_frame& frame)\r
-       {\r
-               transform_stack_.push_back(transform_stack_.back()*frame.get_image_transform());\r
-       }\r
-               \r
-       void visit(core::write_frame& frame)\r
-       {       \r
-               if(transform_stack_.back().get_field_mode() == field_mode::empty)\r
-                       return;\r
-               \r
-               core::render_item item;\r
-               item.pix_desc           = frame.get_pixel_format_desc();\r
-               item.textures           = frame.get_textures();\r
-               item.transform          = transform_stack_.back();\r
-               item.tag                        = frame.tag();\r
-               item.blend_mode         = blend_mode_stack_.top();      \r
-\r
-               auto& layer = layers_.back();\r
-               if(boost::range::find(layer, item) == layer.end())\r
-                       layer.push_back(item);\r
-       }\r
-\r
-       void end()\r
-       {\r
-               transform_stack_.pop_back();\r
-       }\r
-\r
-       void begin_layer(blend_mode::type blend_mode)\r
-       {\r
-               blend_mode_stack_.push(blend_mode);\r
-               layers_.push_back(layer());\r
-       }\r
-\r
-       void end_layer()\r
-       {\r
-               blend_mode_stack_.pop();\r
-       }\r
-       \r
-       boost::unique_future<safe_ptr<host_buffer>> render()\r
+       boost::unique_future<safe_ptr<host_buffer>> render(std::deque<layer>&& layers)\r
        {               \r
-               auto layers = std::move(layers_);\r
+               auto layers2 = std::move(layers);\r
                return channel_.ogl().begin_invoke([=]() mutable\r
                {\r
-                       return render(std::move(layers));\r
+                       return do_render(std::move(layers2));\r
                });\r
        }\r
        \r
-       safe_ptr<host_buffer> render(std::deque<layer>&& layers)\r
+private:\r
+       safe_ptr<host_buffer> do_render(std::deque<layer>&& layers)\r
        {\r
                std::shared_ptr<device_buffer> layer_key_buffer;\r
 \r
@@ -152,30 +104,31 @@ public:
 \r
                std::pair<int, std::shared_ptr<device_buffer>> local_key_buffer;\r
                                \r
-               if(has_overlapping_items(layer, layer.front().blend_mode))\r
+               if(layer.front().blend_mode != blend_mode::normal && has_overlapping_items(layer))\r
                {\r
-                       auto local_draw_buffer = create_device_buffer(4);       \r
-                       auto local_blend_mode = layer.front().blend_mode;\r
+                       auto layer_draw_buffer = create_device_buffer(4);       \r
+                       auto layer_blend_mode = layer.front().blend_mode;\r
 \r
                        int fields = 0;\r
                        BOOST_FOREACH(auto& item, layer)\r
                        {\r
                                if(fields & item.transform.get_field_mode())\r
-                                       item.blend_mode = blend_mode::normal; // Disable blending, it will be used when merging back into render stack.\r
+                                       item.blend_mode = blend_mode::normal; // Disable blending and just merge, it will be used when merging back into render stack.\r
                                else\r
                                {\r
                                        item.blend_mode = blend_mode::replace; // Target field is empty, no blending, just copy\r
                                        fields |= item.transform.get_field_mode();\r
                                }\r
 \r
-                               draw_item(std::move(item), *local_draw_buffer, local_key_buffer, layer_key_buffer);             \r
+                               draw_item(std::move(item), *layer_draw_buffer, local_key_buffer, layer_key_buffer);             \r
                        }\r
                        \r
                        render_item item;\r
-                       item.pix_desc.pix_fmt = pixel_format::bgra;\r
-                       item.pix_desc.planes.push_back(pixel_format_desc::plane(channel_.get_format_desc().width, channel_.get_format_desc().height, 4));\r
-                       item.textures.push_back(local_draw_buffer);\r
-                       item.blend_mode = local_blend_mode;\r
+                       item.pix_desc.pix_fmt   = pixel_format::bgra;\r
+                       item.pix_desc.planes    = list_of(pixel_format_desc::plane(channel_.get_format_desc().width, channel_.get_format_desc().height, 4));\r
+                       item.textures                   = list_of(layer_draw_buffer);\r
+                       item.transform                  = image_transform();\r
+                       item.blend_mode                 = layer_blend_mode;\r
 \r
                        kernel_.draw(channel_.ogl(), std::move(item), *draw_buffer, nullptr, nullptr);\r
                }\r
@@ -219,38 +172,25 @@ public:
                }\r
        }\r
 \r
-       //// TODO: Optimize\r
-       bool has_overlapping_items(const layer& layer, blend_mode::type blend_mode)\r
+       bool has_overlapping_items(const layer& layer)\r
        {\r
                if(layer.size() < 2)\r
                        return false;   \r
                \r
-               if(blend_mode == blend_mode::normal)\r
-                       return false;\r
-                               \r
-               return std::any_of(layer.begin(), layer.end(), [&](const render_item& item)\r
+               auto upper_count = boost::range::count_if(layer, [&](const render_item& item)\r
+               {\r
+                       return item.transform.get_field_mode() | field_mode::upper;\r
+               });\r
+\r
+               auto lower_count = boost::range::count_if(layer, [&](const render_item& item)\r
                {\r
-                       return item.tag != layer.front().tag;\r
+                       return item.transform.get_field_mode() | field_mode::lower;\r
                });\r
 \r
-               //std::copy_if(layer.begin(), layer.end(), std::back_inserter(fill), [&](const render_item& item)\r
-               //{\r
-               //      return !item.transform.get_is_key();\r
-               //});\r
-               //      \r
-               //if(blend_mode == blend_mode::normal) // only overlap if opacity\r
-               //{\r
-               //      return std::any_of(fill.begin(), fill.end(), [&](const render_item& item)\r
-               //      {\r
-               //              return item.transform.get_opacity() < 1.0 - 0.001;\r
-               //      });\r
-               //}\r
-\r
-               //// simple solution, just check if we have differnt video streams / tags.\r
-               //return std::any_of(fill.begin(), fill.end(), [&](const render_item& item)\r
-               //{\r
-               //      return item.tag != fill.front().tag;\r
-               //});\r
+               if(upper_count < 2 && lower_count < 2)\r
+                       return false;\r
+\r
+               return true;\r
        }                       \r
                \r
        safe_ptr<device_buffer> create_device_buffer(size_t stride)\r
@@ -259,10 +199,67 @@ public:
                channel_.ogl().clear(*buffer);\r
                return buffer;\r
        }\r
+};\r
+\r
+               \r
+struct image_mixer::implementation : boost::noncopyable\r
+{      \r
+       ogl_device&                                                             ogl_;\r
+       image_renderer                                                  renderer_;\r
+       std::vector<image_transform>                    transform_stack_;\r
+       blend_mode::type                                                active_blend_mode_;\r
+       std::deque<std::deque<render_item>>             layers_; // layer/stream/items\r
+public:\r
+       implementation(video_channel_context& video_channel) \r
+               : ogl_(video_channel.ogl())\r
+               , renderer_(video_channel)\r
+               , transform_stack_(1)\r
+               , active_blend_mode_(blend_mode::normal)                \r
+       {\r
+       }\r
+\r
+       void begin_layer(blend_mode::type blend_mode)\r
+       {\r
+               active_blend_mode_ = blend_mode;\r
+               layers_ += layer();\r
+       }\r
+               \r
+       void begin(core::basic_frame& frame)\r
+       {\r
+               transform_stack_.push_back(transform_stack_.back()*frame.get_image_transform());\r
+       }\r
+               \r
+       void visit(core::write_frame& frame)\r
+       {       \r
+               if(transform_stack_.back().get_field_mode() == field_mode::empty)\r
+                       return;\r
+               \r
+               core::render_item item;\r
+               item.pix_desc   = frame.get_pixel_format_desc();\r
+               item.textures   = frame.get_textures();\r
+               item.transform  = transform_stack_.back();\r
+               item.blend_mode = active_blend_mode_;   \r
+\r
+               layers_.back() += item;\r
+       }\r
+\r
+       void end()\r
+       {\r
+               transform_stack_.pop_back();\r
+       }\r
+\r
+       void end_layer()\r
+       {               \r
+       }\r
+       \r
+       boost::unique_future<safe_ptr<host_buffer>> render()\r
+       {\r
+               return renderer_.render(std::move(layers_));\r
+       }\r
 \r
        safe_ptr<write_frame> create_frame(const void* tag, const core::pixel_format_desc& desc)\r
        {\r
-               return make_safe<write_frame>(channel_.ogl(), tag, desc);\r
+               return make_safe<write_frame>(ogl_, tag, desc);\r
        }\r
 };\r
 \r
index 3939157dc39c5f1c1a16e4f5f3b8719a23180915..03b03d3b62b384645562ce487dde9c926a347845 100644 (file)
@@ -4,7 +4,7 @@
 \r
 \r
  /* File created by MIDL compiler version 7.00.0555 */\r
-/* at Thu Aug 18 20:53:57 2011\r
+/* at Fri Aug 19 23:43:33 2011\r
  */\r
 /* Compiler settings for interop\DeckLinkAPI.idl:\r
     Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
index 0d54c148d3425ff0ae2dbf0a9bad5a319513903f..d90511728ab8cabbf5bf8cde52e1f52a987cb745 100644 (file)
@@ -6,7 +6,7 @@
 \r
 \r
  /* File created by MIDL compiler version 7.00.0555 */\r
-/* at Thu Aug 18 20:53:57 2011\r
+/* at Fri Aug 19 23:43:33 2011\r
  */\r
 /* Compiler settings for interop\DeckLinkAPI.idl:\r
     Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r