]> git.sesse.net Git - casparcg/commitdiff
[image_mixer] #486 Fixed bug where glReadPixels() was done from the last drawn to...
authorHelge Norberg <helge.norberg@svt.se>
Fri, 27 Jan 2017 16:26:36 +0000 (17:26 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Fri, 27 Jan 2017 16:26:36 +0000 (17:26 +0100)
CHANGELOG
accelerator/ogl/image/image_mixer.cpp

index 607345334a9ce78b4017fd3c56ed0b75e76600f7..630a12148748762f10ba7f39d376d5be3e8a3b87 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -60,6 +60,10 @@ Mixer
   o Rewrote the chroma key code to support variable hue, instead of fixed green\r
     or blue. Threshold setting was removed in favour of separate hue width,\r
     minimum saturation and minimum brightness constraints.\r
+  o Fixed bug where glReadPixels() was done from the last drawn to texture\r
+    instead of always from the target texture. This means that for example a\r
+    MIXER KEYER layer without a layer above to key, as well as a separate alpha\r
+    file with MIXER OPACITY 0 now works as expected.\r
 \r
 AMCP\r
 ----\r
index 19d0191e5fef9a23f5a70e542d24a02806f2d776..5a7f157332d85ca0299f3b5b7b890cb424612098 100644 (file)
@@ -50,7 +50,7 @@
 #include <vector>
 
 namespace caspar { namespace accelerator { namespace ogl {
-               
+
 typedef std::shared_future<std::shared_ptr<texture>> future_texture;
 
 struct item
@@ -91,9 +91,9 @@ public:
                , kernel_(ogl_, blend_modes_wanted, straight_alpha_wanted)
        {
        }
-       
+
        std::future<array<const std::uint8_t>> operator()(std::vector<layer> layers, const core::video_format_desc& format_desc, bool straighten_alpha)
-       {       
+       {
                if(layers.empty())
                { // Bypass GPU with empty frame.
                        static const cache_aligned_vector<uint8_t> buffer(get_max_video_format_size(), 0);
@@ -133,14 +133,16 @@ public:
 
                        kernel_.post_process(target_texture, straighten_alpha);
 
+                       target_texture->attach();
+
                        return ogl_->copy_async(target_texture);
                }));
        }
 
-private:       
-       
-       void draw(spl::shared_ptr<texture>&                     target_texture, 
-                         std::vector<layer>                            layers, 
+private:
+
+       void draw(spl::shared_ptr<texture>&                     target_texture,
+                         std::vector<layer>                            layers,
                          const core::video_format_desc&        format_desc,
                          core::field_mode                                      field_mode)
        {
@@ -154,25 +156,25 @@ private:
        }
 
        void draw(spl::shared_ptr<texture>&                     target_texture,
-                         layer                                                         layer, 
+                         layer                                                         layer,
                          std::shared_ptr<texture>&                     layer_key_texture,
                          const core::video_format_desc&        format_desc,
                          core::field_mode                                      field_mode)
-       {                       
-               // REMOVED: This is done in frame_muxer. 
+       {
+               // REMOVED: This is done in frame_muxer.
                // Fix frames
-               //BOOST_FOREACH(auto& item, layer.items)                
+               //BOOST_FOREACH(auto& item, layer.items)
                //{
                        //if(std::abs(item.transform.fill_scale[1]-1.0) > 1.0/target_texture->height() ||
-                       //   std::abs(item.transform.fill_translation[1]) > 1.0/target_texture->height())               
-                       //      CASPAR_LOG(warning) << L"[image_mixer] Frame should be deinterlaced. Send FILTER DEINTERLACE_BOB when creating producer.";      
+                       //   std::abs(item.transform.fill_translation[1]) > 1.0/target_texture->height())
+                       //      CASPAR_LOG(warning) << L"[image_mixer] Frame should be deinterlaced. Send FILTER DEINTERLACE_BOB when creating producer.";
 
                        //if(item.pix_desc.planes.at(0).height == 480) // NTSC DV
                        //{
                        //      item.transform.fill_translation[1] += 2.0/static_cast<double>(format_desc.height);
                        //      item.transform.fill_scale[1] *= 1.0 - 6.0*1.0/static_cast<double>(format_desc.height);
                        //}
-       
+
                        //// Fix field-order if needed
                        //if(item.field_mode == core::field_mode::lower && format_desc.field_mode == core::field_mode::upper)
                        //      item.transform.fill_translation[1] += 1.0/static_cast<double>(format_desc.height);
@@ -181,49 +183,49 @@ private:
                //}
 
                // Mask out fields
-               for (auto& item : layer.items)                          
+               for (auto& item : layer.items)
                        item.transform.field_mode &= field_mode;
-               
+
                // Remove empty items.
                boost::range::remove_erase_if(layer.items, [&](const item& item)
                {
                        return item.transform.field_mode == core::field_mode::empty;
                });
-               
+
                if(layer.items.empty())
                        return;
 
                std::shared_ptr<texture> local_key_texture;
                std::shared_ptr<texture> local_mix_texture;
-                               
+
                if(layer.blend_mode != core::blend_mode::normal)
                {
                        auto layer_texture = ogl_->create_texture(target_texture->width(), target_texture->height(), 4, false);
 
                        for (auto& item : layer.items)
                                draw(layer_texture, std::move(item), layer_key_texture, local_key_texture, local_mix_texture, format_desc);
-               
-                       draw(layer_texture, std::move(local_mix_texture), core::blend_mode::normal);                                                    
+
+                       draw(layer_texture, std::move(local_mix_texture), core::blend_mode::normal);
                        draw(target_texture, std::move(layer_texture), layer.blend_mode);
                }
                else // fast path
                {
-                       for (auto& item : layer.items)          
+                       for (auto& item : layer.items)
                                draw(target_texture, std::move(item), layer_key_texture, local_key_texture, local_mix_texture, format_desc);
-                                       
+
                        draw(target_texture, std::move(local_mix_texture), core::blend_mode::normal);
-               }                                       
+               }
 
                layer_key_texture = std::move(local_key_texture);
        }
 
-       void draw(spl::shared_ptr<texture>& target_texture, 
-                         item item, 
-                     std::shared_ptr<texture>& layer_key_texture, 
-                         std::shared_ptr<texture>& local_key_texture, 
+       void draw(spl::shared_ptr<texture>& target_texture,
+                         item item,
+                     std::shared_ptr<texture>& layer_key_texture,
+                         std::shared_ptr<texture>& local_key_texture,
                          std::shared_ptr<texture>& local_mix_texture,
                          const core::video_format_desc& format_desc)
-       {                       
+       {
                draw_params draw_params;
                draw_params.pix_desc            = std::move(item.pix_desc);
                draw_params.transform           = std::move(item.transform);
@@ -258,17 +260,17 @@ private:
                else
                {
                        draw(target_texture, std::move(local_mix_texture), core::blend_mode::normal);
-                       
+
                        draw_params.background  = target_texture;
                        draw_params.local_key   = std::move(local_key_texture);
                        draw_params.layer_key   = layer_key_texture;
 
                        kernel_.draw(std::move(draw_params));
-               }       
+               }
        }
 
-       void draw(spl::shared_ptr<texture>&      target_texture, 
-                         std::shared_ptr<texture>&& source_buffer, 
+       void draw(spl::shared_ptr<texture>&      target_texture,
+                         std::shared_ptr<texture>&& source_buffer,
                          core::blend_mode                       blend_mode = core::blend_mode::normal)
        {
                if(!source_buffer)
@@ -286,9 +288,9 @@ private:
                kernel_.draw(std::move(draw_params));
        }
 };
-               
+
 struct image_mixer::impl : public core::frame_factory
-{      
+{
        spl::shared_ptr<device>                         ogl_;
        image_renderer                                          renderer_;
        std::vector<core::image_transform>      transform_stack_;
@@ -298,11 +300,11 @@ public:
        impl(const spl::shared_ptr<device>& ogl, bool blend_modes_wanted, bool straight_alpha_wanted, int channel_id)
                : ogl_(ogl)
                , renderer_(ogl, blend_modes_wanted, straight_alpha_wanted)
-               , transform_stack_(1)   
+               , transform_stack_(1)
        {
                CASPAR_LOG(info) << L"Initialized OpenGL Accelerated GPU Image Mixer for channel " << channel_id;
        }
-               
+
        void push(const core::frame_transform& transform)
        {
                auto previous_layer_depth = transform_stack_.back().layer_depth;
@@ -326,9 +328,9 @@ public:
                }
 
        }
-               
+
        void visit(const core::const_frame& frame)
-       {                       
+       {
                if(frame.pixel_format_desc().format == core::pixel_format::invalid)
                        return;
 
@@ -342,11 +344,11 @@ public:
                item.pix_desc   = frame.pixel_format_desc();
                item.transform  = transform_stack_.back();
                item.geometry   = frame.geometry();
-               
+
                // NOTE: Once we have copied the arrays they are no longer valid for reading!!! Check for alternative solution e.g. transfer with AMD_pinned_memory.
                for(int n = 0; n < static_cast<int>(item.pix_desc.planes.size()); ++n)
                        item.textures.push_back(ogl_->copy_async(frame.image_data(n), item.pix_desc.planes[n].width, item.pix_desc.planes[n].height, item.pix_desc.planes[n].stride, item.transform.use_mipmap));
-               
+
                layer_stack_.back()->items.push_back(item);
        }
 
@@ -355,17 +357,17 @@ public:
                transform_stack_.pop_back();
                layer_stack_.resize(transform_stack_.back().layer_depth);
        }
-       
+
        std::future<array<const std::uint8_t>> render(const core::video_format_desc& format_desc, bool straighten_alpha)
        {
                return renderer_(std::move(layers_), format_desc, straighten_alpha);
        }
-       
+
        core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc, const core::audio_channel_layout& channel_layout) override
        {
                std::vector<array<std::uint8_t>> buffers;
-               for (auto& plane : desc.planes)         
-                       buffers.push_back(ogl_->create_array(plane.size));              
+               for (auto& plane : desc.planes)
+                       buffers.push_back(ogl_->create_array(plane.size));
 
                return core::mutable_frame(std::move(buffers), core::mutable_audio_buffer(), tag, desc, channel_layout);
        }