\r
return flatten(ogl_->begin_invoke([=]() mutable -> boost::shared_future<array<const std::uint8_t>>\r
{\r
- auto draw_buffer = create_mixer_buffer(format_desc.width, format_desc.height, 4);\r
+ auto target_texture = ogl_->create_texture(format_desc.width, format_desc.height, 4);\r
\r
if(format_desc.field_mode != core::field_mode::progressive)\r
{\r
- draw(layers, draw_buffer, format_desc, core::field_mode::upper);\r
- draw(std::move(layers), draw_buffer, format_desc, core::field_mode::lower);\r
+ draw(target_texture, layers, format_desc, core::field_mode::upper);\r
+ draw(target_texture, std::move(layers), format_desc, core::field_mode::lower);\r
}\r
else \r
- draw(std::move(layers), draw_buffer, format_desc, core::field_mode::progressive);\r
+ draw(target_texture, std::move(layers), format_desc, core::field_mode::progressive);\r
\r
- return make_shared(ogl_->copy_async(draw_buffer));\r
+ return make_shared(ogl_->copy_async(target_texture));\r
}));\r
}\r
\r
private: \r
\r
- void draw(std::vector<layer> layers, \r
- spl::shared_ptr<texture>& draw_buffer, \r
+ void draw(spl::shared_ptr<texture>& target_texture, \r
+ std::vector<layer> layers, \r
const core::video_format_desc& format_desc,\r
core::field_mode field_mode)\r
{\r
- std::shared_ptr<texture> layer_key_buffer;\r
+ std::shared_ptr<texture> layer_key_texture;\r
\r
BOOST_FOREACH(auto& layer, layers)\r
- draw_layer(std::move(layer), draw_buffer, layer_key_buffer, format_desc, field_mode);\r
+ draw(target_texture, std::move(layer), layer_key_texture, format_desc, field_mode);\r
}\r
\r
- void draw_layer(layer layer, \r
- spl::shared_ptr<texture>& draw_buffer,\r
- std::shared_ptr<texture>& layer_key_buffer,\r
- const core::video_format_desc& format_desc,\r
- core::field_mode field_mode)\r
+ void draw(spl::shared_ptr<texture>& target_texture,\r
+ layer layer, \r
+ std::shared_ptr<texture>& layer_key_texture,\r
+ const core::video_format_desc& format_desc,\r
+ core::field_mode field_mode)\r
{ \r
// Fix frames \r
BOOST_FOREACH(auto& item, layer.items) \r
if(layer.items.empty())\r
return;\r
\r
- std::shared_ptr<texture> local_key_buffer;\r
- std::shared_ptr<texture> local_mix_buffer;\r
+ std::shared_ptr<texture> local_key_texture;\r
+ std::shared_ptr<texture> local_mix_texture;\r
\r
if(layer.blend_mode != core::blend_mode::normal)\r
{\r
- auto layer_draw_buffer = create_mixer_buffer(draw_buffer->width(), draw_buffer->height(), 4);\r
+ auto layer_texture = ogl_->create_texture(target_texture->width(), target_texture->height(), 4);\r
\r
BOOST_FOREACH(auto& item, layer.items)\r
- draw_item(std::move(item), layer_draw_buffer, layer_key_buffer, local_key_buffer, local_mix_buffer); \r
+ draw(layer_texture, std::move(item), layer_key_texture, local_key_texture, local_mix_texture); \r
\r
- draw_mixer_buffer(layer_draw_buffer, std::move(local_mix_buffer), core::blend_mode::normal); \r
- draw_mixer_buffer(draw_buffer, std::move(layer_draw_buffer), layer.blend_mode);\r
+ draw(layer_texture, std::move(local_mix_texture), core::blend_mode::normal); \r
+ draw(target_texture, std::move(layer_texture), layer.blend_mode);\r
}\r
else // fast path\r
{\r
BOOST_FOREACH(auto& item, layer.items) \r
- draw_item(std::move(item), draw_buffer, layer_key_buffer, local_key_buffer, local_mix_buffer); \r
+ draw(target_texture, std::move(item), layer_key_texture, local_key_texture, local_mix_texture); \r
\r
- draw_mixer_buffer(draw_buffer, std::move(local_mix_buffer), core::blend_mode::normal);\r
+ draw(target_texture, std::move(local_mix_texture), core::blend_mode::normal);\r
} \r
\r
- layer_key_buffer = std::move(local_key_buffer);\r
+ layer_key_texture = std::move(local_key_texture);\r
}\r
\r
- void draw_item(item item, \r
- spl::shared_ptr<texture>& draw_buffer, \r
- std::shared_ptr<texture>& layer_key_buffer, \r
- std::shared_ptr<texture>& local_key_buffer, \r
- std::shared_ptr<texture>& local_mix_buffer)\r
+ void draw(spl::shared_ptr<texture>& target_texture, \r
+ item item, \r
+ std::shared_ptr<texture>& layer_key_texture, \r
+ std::shared_ptr<texture>& local_key_texture, \r
+ std::shared_ptr<texture>& local_mix_texture)\r
{ \r
draw_params draw_params;\r
draw_params.pix_desc = std::move(item.pix_desc);\r
\r
if(item.transform.is_key)\r
{\r
- local_key_buffer = local_key_buffer ? local_key_buffer : create_mixer_buffer(draw_buffer->width(), draw_buffer->height(), 1);\r
+ local_key_texture = local_key_texture ? local_key_texture : ogl_->create_texture(target_texture->width(), target_texture->height(), 1);\r
\r
- draw_params.background = local_key_buffer;\r
+ draw_params.background = local_key_texture;\r
draw_params.local_key = nullptr;\r
draw_params.layer_key = nullptr;\r
\r
}\r
else if(item.transform.is_mix)\r
{\r
- local_mix_buffer = local_mix_buffer ? local_mix_buffer : create_mixer_buffer(draw_buffer->width(), draw_buffer->height(), 4);\r
+ local_mix_texture = local_mix_texture ? local_mix_texture : ogl_->create_texture(target_texture->width(), target_texture->height(), 4);\r
\r
- draw_params.background = local_mix_buffer;\r
- draw_params.local_key = std::move(local_key_buffer);\r
- draw_params.layer_key = layer_key_buffer;\r
+ draw_params.background = local_mix_texture;\r
+ draw_params.local_key = std::move(local_key_texture);\r
+ draw_params.layer_key = layer_key_texture;\r
\r
draw_params.keyer = keyer::additive;\r
\r
}\r
else\r
{\r
- draw_mixer_buffer(draw_buffer, std::move(local_mix_buffer), core::blend_mode::normal);\r
+ draw(target_texture, std::move(local_mix_texture), core::blend_mode::normal);\r
\r
- draw_params.background = draw_buffer;\r
- draw_params.local_key = std::move(local_key_buffer);\r
- draw_params.layer_key = layer_key_buffer;\r
+ draw_params.background = target_texture;\r
+ draw_params.local_key = std::move(local_key_texture);\r
+ draw_params.layer_key = layer_key_texture;\r
\r
kernel_.draw(std::move(draw_params));\r
} \r
}\r
\r
- void draw_mixer_buffer(spl::shared_ptr<texture>& draw_buffer, \r
- std::shared_ptr<texture>&& source_buffer, \r
- core::blend_mode blend_mode = core::blend_mode::normal)\r
+ void draw(spl::shared_ptr<texture>& target_texture, \r
+ std::shared_ptr<texture>&& source_buffer, \r
+ core::blend_mode blend_mode = core::blend_mode::normal)\r
{\r
if(!source_buffer)\r
return;\r
draw_params.textures = list_of(source_buffer);\r
draw_params.transform = core::image_transform();\r
draw_params.blend_mode = blend_mode;\r
- draw_params.background = draw_buffer;\r
+ draw_params.background = target_texture;\r
\r
kernel_.draw(std::move(draw_params));\r
}\r
- \r
- spl::shared_ptr<texture> create_mixer_buffer(int width, int height, int stride)\r
- {\r
- auto buffer = ogl_->create_texture(width, height, stride);\r
- buffer->clear();\r
- return buffer;\r
- }\r
};\r
\r
struct image_mixer::impl : boost::noncopyable\r
}\r
}\r
\r
- spl::shared_ptr<texture> create_texture(int width, int height, int stride)\r
+ spl::shared_ptr<texture> create_texture(int width, int height, int stride, bool clear = false)\r
{\r
- CASPAR_VERIFY(stride > 0 && stride < 5);\r
- CASPAR_VERIFY(width > 0 && height > 0);\r
+ return render_executor_.invoke([=]() -> spl::shared_ptr<texture>\r
+ {\r
+ CASPAR_VERIFY(stride > 0 && stride < 5);\r
+ CASPAR_VERIFY(width > 0 && height > 0);\r
\r
- auto pool = &device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
+ auto pool = &device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
\r
- std::shared_ptr<texture> buffer;\r
- if(!pool->try_pop(buffer)) \r
- buffer = spl::make_shared<texture>(width, height, stride);\r
+ std::shared_ptr<texture> buffer;\r
+ if(!pool->try_pop(buffer)) \r
+ buffer = spl::make_shared<texture>(width, height, stride);\r
\r
- return spl::shared_ptr<texture>(buffer.get(), [buffer, pool](texture*) mutable\r
- { \r
- pool->push(buffer); \r
+ if(clear)\r
+ buffer->clear();\r
+\r
+ return spl::shared_ptr<texture>(buffer.get(), [buffer, pool](texture*) mutable\r
+ { \r
+ pool->push(buffer); \r
+ });\r
});\r
}\r
\r
texture_cache_.insert(std::make_pair(buf.get(), texture));\r
\r
return texture;\r
-\r
}, task_priority::high_priority);\r
}\r
\r
\r
return render_executor_.begin_invoke([=]() -> spl::shared_ptr<texture>\r
{\r
- auto texture = create_texture(width, height, stride);\r
+ auto texture = create_texture(width, height, stride, false);\r
texture->copy_from(*buf); \r
return texture;\r
}, task_priority::high_priority);\r
: executor_(L"OpenGL Rendering Context.")\r
, impl_(new impl(executor_)){}\r
device::~device(){}\r
-spl::shared_ptr<texture> device::create_texture(int width, int height, int stride){return impl_->create_texture(width, height, stride);}\r
+spl::shared_ptr<texture> device::create_texture(int width, int height, int stride){return impl_->create_texture(width, height, stride, true);}\r
array<std::uint8_t> device::create_array(int size){return impl_->create_array(size);}\r
boost::unique_future<spl::shared_ptr<texture>> device::copy_async(const array<const std::uint8_t>& source, int width, int height, int stride){return impl_->copy_async(source, width, height, stride);}\r
boost::unique_future<spl::shared_ptr<texture>> device::copy_async(const array<std::uint8_t>& source, int width, int height, int stride){return impl_->copy_async(source, width, height, stride);}\r