]> git.sesse.net Git - casparcg/commitdiff
Experimental support for switching output between premultiplied / straight alpha
authorHelge Norberg <helge.norberg@gmail.com>
Tue, 11 Jun 2013 14:31:55 +0000 (16:31 +0200)
committerHelge Norberg <helge.norberg@gmail.com>
Tue, 11 Jun 2013 14:31:55 +0000 (16:31 +0200)
Use
MIXER 1 STRAIGHT_ALPHA_OUTPUT 1
to turn on straight alpha output on channel 1 or configure it in casparcg.config under the <straight-alpha-output /> element for the channel

The default is to not use straight alpha output

#50

12 files changed:
CHANGES.txt
core/mixer/image/image_kernel.cpp
core/mixer/image/image_kernel.h
core/mixer/image/image_mixer.cpp
core/mixer/image/image_mixer.h
core/mixer/image/shader/blending_glsl.h
core/mixer/image/shader/image_shader.cpp
core/mixer/mixer.cpp
core/mixer/mixer.h
protocol/amcp/AMCPCommandsImpl.cpp
shell/casparcg.config
shell/server.cpp

index abffccb76a348817a89bdaf1003fb80a3c4b756a..9d290743c7d489a3274e0660e1c26d422fc53f6d 100644 (file)
@@ -34,6 +34,7 @@ Video mixer
 \r
   o Added support for chroma keying.\r
   o Fixed bug where MIXER CONTRAST set to < 1 can cause transparency issues.\r
+  o Experimental support for straight alpha output.\r
 \r
 Consumers\r
 ---------\r
@@ -82,6 +83,8 @@ AMCP
   o Fixed bug where MIXER FILL overrides any previous MIXER CLIP on the same\r
     layer. The bugfix also has the side effect of supporting negative scale on\r
     MIXER FILL, causing the image to be flipped.\r
+  o MIXER <ch> STRAIGHT_ALPHA_OUTPUT added to control whether to output straight\r
+    alpha or not.\r
 \r
 OSC\r
 ---\r
index 41d6a6ff8d3e031f137534e6da9723bd7520dbc0..7b36a6f8ed1901ad260d30b47edb4fb795356f37 100644 (file)
@@ -59,11 +59,15 @@ struct image_kernel::implementation : boost::noncopyable
        safe_ptr<ogl_device>    ogl_;\r
        safe_ptr<shader>                shader_;\r
        bool                                    blend_modes_;\r
+       bool                                    supports_texture_barrier_;\r
                                                        \r
        implementation(const safe_ptr<ogl_device>& ogl)\r
                : ogl_(ogl)\r
                , shader_(ogl_->invoke([&]{return get_image_shader(*ogl, blend_modes_);}))\r
+               , supports_texture_barrier_(glTextureBarrierNV != 0)\r
        {\r
+               if (!supports_texture_barrier_)\r
+                       CASPAR_LOG(warning) << L"[image_mixer] TextureBarrierNV not supported. Post processing will not be available";\r
        }\r
 \r
        void draw(draw_params&& params)\r
@@ -110,8 +114,9 @@ struct image_kernel::implementation : boost::noncopyable
                shader_->set("has_layer_key",   bool(params.layer_key));\r
                shader_->set("pixel_format",    params.pix_desc.pix_fmt);       \r
                shader_->set("opacity",                 params.transform.is_key ? 1.0 : params.transform.opacity);      \r
+               shader_->set("post_processing", false);\r
 \r
-        shader_->set("chroma_mode",    params.blend_mode.chroma.key == chroma::green ? 1 : (params.blend_mode.chroma.key == chroma::blue ? 2 : 0));\r
+               shader_->set("chroma_mode",    params.blend_mode.chroma.key == chroma::green ? 1 : (params.blend_mode.chroma.key == chroma::blue ? 2 : 0));\r
         shader_->set("chroma_blend",   params.blend_mode.chroma.threshold, params.blend_mode.chroma.softness);\r
         shader_->set("chroma_spill",   params.blend_mode.chroma.spill);\r
 //        shader_->set("chroma.key",      ((params.blend_mode.chroma.key >> 24) && 0xff)/255.0f,\r
@@ -132,7 +137,7 @@ struct image_kernel::implementation : boost::noncopyable
 \r
                if(blend_modes_)\r
                {\r
-                       params.background->bind(6);\r
+                       params.background->bind(texture_id::background);\r
 \r
                        shader_->set("background",      texture_id::background);\r
                        shader_->set("blend_mode",      params.blend_mode.mode);\r
@@ -249,6 +254,44 @@ struct image_kernel::implementation : boost::noncopyable
                        glTextureBarrierNV(); \r
                }\r
        }\r
+\r
+       void post_process(\r
+                       const safe_ptr<device_buffer>& background, bool straighten_alpha)\r
+       {\r
+               bool should_post_process = \r
+                               supports_texture_barrier_ && straighten_alpha;\r
+\r
+               if (!should_post_process)\r
+                       return;\r
+\r
+               if (!blend_modes_)\r
+                       ogl_->disable(GL_BLEND);\r
+\r
+               ogl_->disable(GL_POLYGON_STIPPLE);\r
+\r
+               ogl_->attach(*background);\r
+\r
+               background->bind(texture_id::background);\r
+\r
+               ogl_->use(*shader_);\r
+               shader_->set("background", texture_id::background);\r
+               shader_->set("post_processing", should_post_process);\r
+               shader_->set("straighten_alpha", straighten_alpha);\r
+\r
+               ogl_->viewport(0, 0, background->width(), background->height());\r
+\r
+               glBegin(GL_QUADS);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 0.0, 0.0); glVertex2d(-1.0, -1.0);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 1.0, 0.0); glVertex2d( 1.0, -1.0);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 1.0, 1.0); glVertex2d( 1.0,  1.0);\r
+                       glMultiTexCoord2d(GL_TEXTURE0, 0.0, 1.0); glVertex2d(-1.0,  1.0);\r
+               glEnd();\r
+\r
+               glTextureBarrierNV();\r
+\r
+               if (!blend_modes_)\r
+                       ogl_->enable(GL_BLEND);\r
+       }\r
 };\r
 \r
 image_kernel::image_kernel(const safe_ptr<ogl_device>& ogl) : impl_(new implementation(ogl)){}\r
@@ -257,4 +300,10 @@ void image_kernel::draw(draw_params&& params)
        impl_->draw(std::move(params));\r
 }\r
 \r
+void image_kernel::post_process(\r
+               const safe_ptr<device_buffer>& background, bool straighten_alpha)\r
+{\r
+       impl_->post_process(background, straighten_alpha);\r
+}\r
+\r
 }}\r
index 10a8622e9884336f3f025b80dcfede6963069f8c..975577bf8a77d7b29af59665025b369bc4b21bdd 100644 (file)
@@ -67,6 +67,8 @@ class image_kernel : boost::noncopyable
 public:\r
        image_kernel(const safe_ptr<ogl_device>& ogl);\r
        void draw(draw_params&& params);\r
+       void post_process(\r
+                       const safe_ptr<device_buffer>& background, bool straighten_alpha);\r
 private:\r
        struct implementation;\r
        safe_ptr<implementation> impl_;\r
index a51073e82ba6659c4ec813f47339677976b53018..1ad020d26eac7ab48d7ecbb2fa75b8821fbcccaa 100644 (file)
@@ -70,17 +70,21 @@ public:
        {\r
        }\r
        \r
-       boost::unique_future<safe_ptr<host_buffer>> operator()(std::vector<layer>&& layers, const video_format_desc& format_desc)\r
+       boost::unique_future<safe_ptr<host_buffer>> operator()(\r
+                       std::vector<layer>&& layers,\r
+                       const video_format_desc& format_desc,\r
+                       bool straighten_alpha)\r
        {               \r
                auto layers2 = make_move_on_copy(std::move(layers));\r
                return ogl_->begin_invoke([=]\r
                {\r
-                       return do_render(std::move(layers2.value), format_desc);\r
+                       return do_render(\r
+                                       std::move(layers2.value), format_desc, straighten_alpha);\r
                });\r
        }\r
 \r
 private:\r
-       safe_ptr<host_buffer> do_render(std::vector<layer>&& layers, const video_format_desc& format_desc)\r
+       safe_ptr<host_buffer> do_render(std::vector<layer>&& layers, const video_format_desc& format_desc, bool straighten_alpha)\r
        {\r
                auto draw_buffer = create_mixer_buffer(4, format_desc);\r
 \r
@@ -109,6 +113,8 @@ private:
                        draw(std::move(layers), draw_buffer, format_desc);\r
                }\r
 \r
+               kernel_.post_process(draw_buffer, straighten_alpha);\r
+\r
                auto host_buffer = ogl_->create_host_buffer(format_desc.size, host_buffer::read_only);\r
                ogl_->attach(*draw_buffer);\r
                ogl_->read_buffer(*draw_buffer);\r
@@ -280,9 +286,9 @@ public:
        {               \r
        }\r
        \r
-       boost::unique_future<safe_ptr<host_buffer>> render(const video_format_desc& format_desc)\r
+       boost::unique_future<safe_ptr<host_buffer>> render(const video_format_desc& format_desc, bool straighten_alpha)\r
        {\r
-               return renderer_(std::move(layers_), format_desc);\r
+               return renderer_(std::move(layers_), format_desc, straighten_alpha);\r
        }\r
 };\r
 \r
@@ -290,7 +296,7 @@ image_mixer::image_mixer(const safe_ptr<ogl_device>& ogl) : impl_(new implementa
 void image_mixer::begin(basic_frame& frame){impl_->begin(frame);}\r
 void image_mixer::visit(write_frame& frame){impl_->visit(frame);}\r
 void image_mixer::end(){impl_->end();}\r
-boost::unique_future<safe_ptr<host_buffer>> image_mixer::operator()(const video_format_desc& format_desc){return impl_->render(format_desc);}\r
+boost::unique_future<safe_ptr<host_buffer>> image_mixer::operator()(const video_format_desc& format_desc, bool straighten_alpha){return impl_->render(format_desc, straighten_alpha);}\r
 void image_mixer::begin_layer(blend_mode blend_mode){impl_->begin_layer(blend_mode);}\r
 void image_mixer::end_layer(){impl_->end_layer();}\r
 \r
index d4db0c8919dcfe0aab03ad240e11e9290d6b98f6..ea739488de922f5eb5c1d79d948b5f8e4c35235f 100644 (file)
@@ -51,7 +51,8 @@ public:
        void begin_layer(blend_mode blend_mode);\r
        void end_layer();\r
                \r
-       boost::unique_future<safe_ptr<host_buffer>> operator()(const video_format_desc& format_desc);\r
+       boost::unique_future<safe_ptr<host_buffer>> operator()(\r
+                       const video_format_desc& format_desc, bool straighten_alpha);\r
                \r
 private:\r
        struct implementation;\r
index 18aeffa7358b14beb9ad3305e5160b5bd0eee2de..bda7fbf55e71bdba890dc340377410df8cb25c7d 100644 (file)
@@ -37,7 +37,7 @@ static std::string get_adjustement_glsl()
                "\n             const float AvgLumB = 0.5;                                                                                                                                                                                                                                                                                                                                                                         "\r
                "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
                "\n             const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);                                                                                                                                                                                                                                                                                                                        "\r
-               "\n             bool demultiply_remultiply = con < 1.0;                                                                                                                                                                                                                                                                                                                                                                                                            "\r
+               "\n             bool demultiply_remultiply = con < 1.0 && color.a != 1.0;                                                                                                                                                                                                                                                                                                                                                                                                                  "\r
                "\n                                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
                "\n             if (demultiply_remultiply && color.a > 0.0)                                                                                                                                                                                                                                                                                                                                                                                                                        "\r
                "\n                     color.rgb /= color.a;                                                                                                                                                                                                                                                                                                                                                                                                              "\r
index 5c0254258d9396c8eb0ca456fe71823a7a6d8736..0ccadd5e937a1f03f0c5800dbe4ca3b447df8e9b 100644 (file)
@@ -175,6 +175,9 @@ std::string get_fragment(bool blend_modes)
        "uniform float          sat;                                                                                                                    \n"\r
        "uniform float          con;                                                                                                                    \n"\r
        "                                                                                                                                                                       \n"     \r
+       "uniform bool           post_processing;                                                                                                \n"\r
+       "uniform bool           straighten_alpha;                                                                                               \n"\r
+       "                                                                                                                                                                       \n"     \r
     "uniform int        chroma_mode;                                                    \n"\r
     "uniform vec2       chroma_blend;                                                   \n"\r
     "uniform float      chroma_spill;                                                   \n"\r
@@ -257,8 +260,24 @@ std::string get_fragment(bool blend_modes)
        "       return vec4(0.0, 0.0, 0.0, 0.0);                                                                                                \n"\r
        "}                                                                                                                                                                      \n"\r
        "                                                                                                                                                                       \n"\r
+       "vec4 post_process()                                                                                                                            \n"\r
+       "{                                                                                                                                                                      \n"\r
+       "       vec4 color = texture2D(background, gl_TexCoord[0].st).bgra;                                             \n"\r
+       "                                                                                                                                                                       \n"\r
+       "       if (straighten_alpha && color.a > 0.0 && color.a != 1.0)                                                \n"\r
+       "               color.rgb /= color.a;                                                                                                           \n"\r
+       "                                                                                                                                                                       \n"\r
+       "       return color;                                                                                                                                   \n"\r
+       "}                                                                                                                                                                      \n"\r
+       "                                                                                                                                                                       \n"\r
        "void main()                                                                                                                                            \n"\r
        "{                                                                                                                                                                      \n"\r
+       "       if (post_processing)                                                                                                                    \n"\r
+       "       {                                                                                                                                                               \n"\r
+       "               gl_FragColor = post_process().bgra;                                                                                     \n"\r
+       "               return;                                                                                                                                         \n"\r
+       "       }                                                                                                                                                               \n"\r
+       "                                                                                                                                                                       \n"\r
        "       vec4 color = get_rgba_color();                                                                                                  \n"\r
        "   color = chroma_key(color);                                                      \n"\r
        "   if(levels)                                                                                                                                          \n"\r
index 4b286418f02fd5360fd2aa18acc77cd44a107018..04904d4df5e3c166507ed1a3b2da79b76d16051b 100644 (file)
@@ -66,6 +66,7 @@ struct mixer::implementation : boost::noncopyable
        video_format_desc                               format_desc_;\r
        safe_ptr<ogl_device>                    ogl_;\r
        channel_layout                                  audio_channel_layout_;\r
+       bool                                                    straighten_alpha_;\r
        \r
        audio_mixer     audio_mixer_;\r
        image_mixer image_mixer_;\r
@@ -81,8 +82,9 @@ public:
                , format_desc_(format_desc)\r
                , ogl_(ogl)\r
                , audio_channel_layout_(audio_channel_layout)\r
-               , image_mixer_(ogl)\r
+               , straighten_alpha_(false)\r
                , audio_mixer_(graph_)\r
+               , image_mixer_(ogl)\r
                , executor_(L"mixer")\r
        {                       \r
                graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8));\r
@@ -109,7 +111,7 @@ public:
                                        image_mixer_.end_layer();\r
                                }\r
 \r
-                               auto image = image_mixer_(format_desc_);\r
+                               auto image = image_mixer_(format_desc_, straighten_alpha_);\r
                                auto audio = audio_mixer_(format_desc_, audio_channel_layout_);\r
                                image.wait();\r
 \r
@@ -180,6 +182,22 @@ public:
         }, high_priority);\r
     }\r
 \r
+       void set_straight_alpha_output(bool value)\r
+       {\r
+        executor_.begin_invoke([=]\r
+        {\r
+                       straighten_alpha_ = value;\r
+        }, high_priority);\r
+       }\r
+\r
+       bool get_straight_alpha_output()\r
+       {\r
+               return executor_.invoke([=]\r
+               {\r
+                       return straighten_alpha_;\r
+               });\r
+       }\r
+\r
        float get_master_volume()\r
        {\r
                return executor_.invoke([=]\r
@@ -230,6 +248,8 @@ chroma mixer::get_chroma(int index) { return impl_->get_chroma(index); }
 void mixer::set_chroma(int index, const chroma & value){impl_->set_chroma(index, value);}\r
 void mixer::clear_blend_mode(int index) { impl_->clear_blend_mode(index); }\r
 void mixer::clear_blend_modes() { impl_->clear_blend_modes(); }\r
+void mixer::set_straight_alpha_output(bool value) { impl_->set_straight_alpha_output(value); }\r
+bool mixer::get_straight_alpha_output() { return impl_->get_straight_alpha_output(); }\r
 float mixer::get_master_volume() { return impl_->get_master_volume(); }\r
 void mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }\r
 void mixer::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
index d854f7b1ded5023feb59c333e1a96013edb84f2b..3c59f5cb21bbca3038bf8b92e3ee4f51f10481ee 100644 (file)
@@ -73,6 +73,8 @@ public:
     void set_chroma(int index, const chroma& value);\r
        void clear_blend_mode(int index);\r
        void clear_blend_modes();\r
+       void set_straight_alpha_output(bool value);\r
+       bool get_straight_alpha_output();\r
 \r
        float get_master_volume();\r
        void set_master_volume(float volume);\r
index 09562ea07a968063a15d2fa8419dd6d2c1f06591..0ffd85cdd771461945bd466c067dda0113d976f0 100644 (file)
@@ -698,6 +698,20 @@ bool MixerCommand::DoExecute()
                                return transform;\r
                        }, duration, tween));\r
                }\r
+               else if(_parameters[0] == L"STRAIGHT_ALPHA_OUTPUT")\r
+               {\r
+                       if (_parameters.size() == 1)\r
+                       {\r
+                               SetReplyString(L"201 MIXER OK\r\n"\r
+                                       + lexical_cast<std::wstring>(\r
+                                                       GetChannel()->mixer()->get_straight_alpha_output())\r
+                                       + L"\r\n");\r
+                               return true;\r
+                       }\r
+\r
+                       bool value = boost::lexical_cast<bool>(_parameters[1]);\r
+                       GetChannel()->mixer()->set_straight_alpha_output(value);\r
+               }\r
                else if(_parameters[0] == L"VOLUME")\r
                {\r
                        if (_parameters.size() == 1)\r
index 4b607187348ecda6f482dbf821fbf40c3e86f2d3..221bc63934c6e036741a3b43fc5dc332fbf2303c 100644 (file)
@@ -63,6 +63,7 @@
     <channel>\r
         <video-mode> PAL [PAL|NTSC|576p2500|720p2398|720p2400|720p2500|720p5000|720p2997|720p5994|720p3000|720p6000|1080p2398|1080p2400|1080i5000|1080i5994|1080i6000|1080p2500|1080p2997|1080p3000|1080p5000|1080p5994|1080p6000|2k2398|2k2400|2k2500|4k2398|4k2400|4k2500|4k2997|4k3000] </video-mode>\r
         <channel-layout>stereo [mono|stereo|dts|dolbye|dolbydigital|smpte|passthru]</channel-layout>\r
+        <straight-alpha-output>false [true|false]</straight-alpha-output>\r
         <consumers>\r
             <decklink>\r
                 <device>[1..]</device>\r
index d03c39f77715996f2c7dd86eff24c21cbcee77b6..0fa59241848031f6e36557ed816c08e17ab4280b 100644 (file)
@@ -31,6 +31,7 @@
 \r
 #include <core/mixer/gpu/ogl_device.h>\r
 #include <core/mixer/audio/audio_util.h>\r
+#include <core/mixer/mixer.h>\r
 #include <core/video_channel.h>\r
 #include <core/producer/stage.h>\r
 #include <core/consumer/output.h>\r
@@ -167,6 +168,8 @@ struct server::implementation : boost::noncopyable
                        channels_.push_back(make_safe<video_channel>(channels_.size()+1, format_desc, ogl_, audio_channel_layout));\r
                        \r
                        channels_.back()->monitor_output().link_target(&monitor_subject_);\r
+                       channels_.back()->mixer()->set_straight_alpha_output(\r
+                                       xml_channel.second.get(L"straight-alpha-output", false));\r
 \r
                        create_consumers(\r
                                xml_channel.second.get_child(L"consumers"),\r