#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
#include <tbb/concurrent_queue.h>\r
\r
#include <algorithm>\r
-#include <array>\r
+#include <vector>\r
\r
namespace caspar {\r
\r
core::video_format_desc format_desc_;\r
\r
GLuint texture_;\r
+ std::vector<GLuint> pbos_;\r
\r
float width_;\r
float height_;\r
\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
, 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
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
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
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
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
\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
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