]> git.sesse.net Git - casparcg/blobdiff - modules/ogl/consumer/ogl_consumer.cpp
2.0. Optimized key-only.
[casparcg] / modules / ogl / consumer / ogl_consumer.cpp
index 76c06055c46b9847f3f6e908c845260b33beb6da..4cdfa93fe036083e9bb6d388769dac9bea4faf78 100644 (file)
@@ -28,6 +28,7 @@
 #include <common/log/log.h>\r
 #include <common/memory/safe_ptr.h>\r
 #include <common/memory/memcpy.h>\r
+#include <common/memory/memshfl.h>\r
 #include <common/utility/timer.h>\r
 #include <common/utility/string.h>\r
 \r
@@ -44,7 +45,7 @@
 #include <tbb/concurrent_queue.h>\r
 \r
 #include <algorithm>\r
-#include <array>\r
+#include <vector>\r
 \r
 namespace caspar {\r
                \r
@@ -61,6 +62,7 @@ struct ogl_consumer : boost::noncopyable
        core::video_format_desc format_desc_;\r
        \r
        GLuint                                  texture_;\r
+       std::vector<GLuint>             pbos_;\r
        \r
        float                                   width_;\r
        float                                   height_;\r
@@ -87,10 +89,13 @@ struct ogl_consumer : boost::noncopyable
 \r
        boost::thread                   thread_;\r
        tbb::atomic<bool>               is_running_;\r
+\r
+       const bool key_only_;\r
 public:\r
-       ogl_consumer(unsigned int screen_index, stretch stretch, bool windowed, const core::video_format_desc& format_desc) \r
+       ogl_consumer(unsigned int screen_index, stretch stretch, bool windowed, const core::video_format_desc& format_desc, bool key_only\r
                : format_desc_(format_desc)\r
                , texture_(0)\r
+               , pbos_(2, 0)\r
                , stretch_(stretch)\r
                , windowed_(windowed)\r
                , screen_index_(screen_index)           \r
@@ -100,6 +105,7 @@ public:
                , square_height_(format_desc.height)\r
                , graph_(diagnostics::create_graph(narrow(print())))\r
                , input_buffer_(core::consumer_buffer_depth()-1)\r
+               , key_only_(key_only)\r
        {               \r
                frame_buffer_.set_capacity(2);\r
 \r
@@ -181,7 +187,15 @@ public:
                GL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP));\r
                GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, format_desc_.width, format_desc_.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0));\r
                GL(glBindTexture(GL_TEXTURE_2D, 0));\r
+                                       \r
+               GL(glGenBuffers(2, pbos_.data()));\r
                        \r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[0]);\r
+               glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW_ARB);\r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbos_[1]);\r
+               glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, format_desc_.size, 0, GL_STREAM_DRAW_ARB);\r
+               glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);\r
+\r
                CASPAR_LOG(info) << print() << " Sucessfully Initialized.";\r
        }\r
 \r
@@ -190,6 +204,12 @@ public:
                if(texture_)\r
                        glDeleteTextures(1, &texture_);\r
 \r
+               BOOST_FOREACH(auto& pbo, pbos_)\r
+               {\r
+                       if(pbo)\r
+                               glDeleteBuffers(1, &pbo);\r
+               }\r
+\r
                CASPAR_LOG(info) << print() << " Sucessfully Uninitialized.";\r
        }\r
 \r
@@ -245,10 +265,27 @@ public:
                if(frame->image_data().empty())\r
                        return;\r
 \r
-               GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
+               glBindTexture(GL_TEXTURE_2D, texture_);\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[0]);\r
+               glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);\r
 \r
-               GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, format_desc_.width, format_desc_.height, GL_BGRA, GL_UNSIGNED_BYTE, frame->image_data().begin()));\r
-                                               \r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbos_[1]);\r
+               glBufferData(GL_PIXEL_UNPACK_BUFFER, format_desc_.size, 0, GL_STREAM_DRAW);\r
+\r
+               auto ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
+               if(ptr)\r
+               {\r
+                       if(key_only_)\r
+                               fast_memshfl(reinterpret_cast<char*>(ptr), frame->image_data().begin(), frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                       else\r
+                               fast_memcpy(reinterpret_cast<char*>(ptr), frame->image_data().begin(), frame->image_data().size());\r
+\r
+                       glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer\r
+               }\r
+\r
+               glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);\r
+                               \r
                GL(glClear(GL_COLOR_BUFFER_BIT));                       \r
                glBegin(GL_QUADS);\r
                                glTexCoord2f(0.0f,        1.0f);        glVertex2f(-width_, -height_);\r
@@ -258,6 +295,8 @@ public:
                glEnd();\r
                \r
                glBindTexture(GL_TEXTURE_2D, 0);\r
+\r
+               std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
        }\r
 \r
        void send(const safe_ptr<core::read_frame>& frame)\r
@@ -353,7 +392,7 @@ public:
        \r
        virtual void initialize(const core::video_format_desc& format_desc)\r
        {\r
-               consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc));\r
+               consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc, key_only_));\r
        }\r
        \r
        virtual bool send(const safe_ptr<core::read_frame>& frame)\r
@@ -367,11 +406,6 @@ public:
                return consumer_->print();\r
        }\r
 \r
-       virtual bool key_only() const\r
-       {\r
-               return key_only_;\r
-       }\r
-\r
        virtual bool has_synchronization_clock() const \r
        {\r
                return false;\r