tbb::concurrent_hash_map<buffer*, std::shared_ptr<texture>> texture_cache_;\r
\r
std::unique_ptr<sf::Context> device_;\r
- std::unique_ptr<sf::Context> host_alloc_device_;\r
\r
std::array<tbb::concurrent_unordered_map<std::size_t, tbb::concurrent_bounded_queue<std::shared_ptr<texture>>>, 4> device_pools_;\r
std::array<tbb::concurrent_unordered_map<std::size_t, tbb::concurrent_bounded_queue<std::shared_ptr<buffer>>>, 2> host_pools_;\r
\r
GLuint fbo_;\r
\r
- executor& render_executor_;\r
- executor alloc_executor_;\r
+ executor& executor_;\r
\r
impl(executor& executor) \r
- : render_executor_(executor)\r
- , alloc_executor_(L"OpenGL allocation context")\r
+ : executor_(executor)\r
{\r
- render_executor_.set_capacity(128);\r
- alloc_executor_.set_capacity(256);\r
+ executor_.set_capacity(256);\r
\r
CASPAR_LOG(info) << L"Initializing OpenGL Device.";\r
\r
- auto ctx1 = render_executor_.invoke([=]() -> HGLRC \r
+ executor_.invoke([=]\r
{\r
device_.reset(new sf::Context());\r
device_->SetActive(true); \r
\r
glGenFramebuffers(1, &fbo_); \r
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);\r
- \r
- auto ctx1 = wglGetCurrentContext();\r
- \r
- device_->SetActive(false);\r
-\r
- return ctx1;\r
- });\r
-\r
- alloc_executor_.invoke([=]\r
- {\r
- host_alloc_device_.reset(new sf::Context());\r
- host_alloc_device_->SetActive(true); \r
- auto ctx2 = wglGetCurrentContext();\r
-\r
- if(!wglShareLists(ctx1, ctx2))\r
- CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to share OpenGL devices."));\r
- });\r
-\r
- render_executor_.invoke([=]\r
- { \r
- device_->SetActive(true);\r
});\r
\r
CASPAR_LOG(info) << L"Successfully initialized OpenGL " << version();\r
\r
~impl()\r
{\r
- alloc_executor_.invoke([=]\r
- {\r
- host_alloc_device_.reset();\r
- BOOST_FOREACH(auto& pool, host_pools_)\r
- pool.clear();\r
- });\r
-\r
- render_executor_.invoke([=]\r
+ executor_.invoke([=]\r
{\r
BOOST_FOREACH(auto& pool, device_pools_)\r
pool.clear();\r
{ \r
try\r
{\r
- return alloc_executor_.invoke([]\r
+ return executor_.invoke([]\r
{\r
return u16(reinterpret_cast<const char*>(GL2(glGetString(GL_VERSION)))) + L" " + u16(reinterpret_cast<const char*>(GL2(glGetString(GL_VENDOR))));\r
}); \r
CASPAR_VERIFY(stride > 0 && stride < 5);\r
CASPAR_VERIFY(width > 0 && height > 0);\r
\r
- if(!render_executor_.is_current())\r
+ if(!executor_.is_current())\r
CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info("Operation only valid in an OpenGL Context."));\r
\r
auto pool = &device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
std::shared_ptr<buffer> buf;\r
if(!pool->try_pop(buf)) \r
{\r
- buf = alloc_executor_.invoke([&]\r
+ buf = executor_.invoke([&]\r
{\r
return spl::make_shared<buffer>(size, usage);\r
}, task_priority::high_priority);\r
{\r
std::shared_ptr<buffer> buf = copy_to_buf(source);\r
\r
- return render_executor_.begin_invoke([=]() -> spl::shared_ptr<texture>\r
+ return executor_.begin_invoke([=]() -> spl::shared_ptr<texture>\r
{\r
tbb::concurrent_hash_map<buffer*, std::shared_ptr<texture>>::const_accessor a;\r
if(texture_cache_.find(a, buf.get()))\r
{\r
std::shared_ptr<buffer> buf = copy_to_buf(source);\r
\r
- return render_executor_.begin_invoke([=]() -> spl::shared_ptr<texture>\r
+ return executor_.begin_invoke([=]() -> spl::shared_ptr<texture>\r
{\r
auto texture = create_texture(width, height, stride, false);\r
texture->copy_from(*buf); \r
\r
boost::unique_future<array<const std::uint8_t>> copy_async(const spl::shared_ptr<texture>& source)\r
{\r
- if(!render_executor_.is_current())\r
+ if(!executor_.is_current())\r
CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info("Operation only valid in an OpenGL Context."));\r
\r
auto buffer = create_buffer(source->size(), buffer::usage::read_only); \r
auto self = shared_from_this();\r
return async(launch::deferred, [self, buffer]() mutable -> array<const std::uint8_t>\r
{\r
- self->alloc_executor_.invoke(std::bind(&buffer::map, std::ref(buffer))); // Defer blocking "map" call until data is needed.\r
+ self->executor_.invoke(std::bind(&buffer::map, std::ref(buffer))); // Defer blocking "map" call until data is needed.\r
return array<const std::uint8_t>(buffer->data(), buffer->size(), true, buffer);\r
});\r
}\r
\r
const_frame operator()(std::map<int, draw_frame> frames, const video_format_desc& format_desc)\r
{ \r
- return executor_.invoke([=]() mutable -> const_frame\r
+ boost::timer frame_timer;\r
+\r
+ auto frame = executor_.invoke([=]() mutable -> const_frame\r
{ \r
try\r
{ \r
- boost::timer frame_timer;\r
-\r
BOOST_FOREACH(auto& frame, frames)\r
{\r
auto blend_it = blend_modes_.find(frame.first);\r
\r
auto image = (*image_mixer_)(format_desc);\r
auto audio = audio_mixer_(format_desc);\r
- \r
- graph_->set_value("mix-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
\r
auto desc = core::pixel_format_desc(core::pixel_format::bgra);\r
desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
return const_frame::empty();\r
} \r
}); \r
+ \r
+ graph_->set_value("mix-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
+\r
+ return frame;\r
}\r
\r
void set_blend_mode(int index, blend_mode value)\r
{\r
try\r
{\r
- auto format_desc = video_format_desc();\r
+ boost::timer t;\r
\r
+ auto format_desc = video_format_desc();\r
+ \r
boost::timer frame_timer;\r
\r
// Produce\r
\r
auto stage_frames = stage_(format_desc);\r
\r
+ if(t.elapsed() > 1.0/format_desc.fps*0.9)\r
+ CASPAR_LOG(trace) << print() << L" Stage is slowing down channel: " << t.elapsed();\r
+\r
+ t.restart();\r
// Mix\r
\r
auto mixed_frame = mixer_(std::move(stage_frames), format_desc);\r
+ \r
+ if(t.elapsed() > 1.0/format_desc.fps*0.9)\r
+ CASPAR_LOG(trace) << print() << L"Mixer is slowing down channel: " << t.elapsed();\r
\r
+ t.restart();\r
// Consume\r
\r
output_(std::move(mixed_frame), format_desc);\r
\r
+ t.restart();\r
+\r
graph_->set_value("tick-time", frame_timer.elapsed()*format_desc.fps*0.5);\r
\r
event_subject_ << monitor::event("profiler/time") % frame_timer.elapsed() % (1.0/format_desc_.fps)\r
<< monitor::event("format") % format_desc.name;\r
+ \r
+ if(t.elapsed() > 0.001)\r
+ CASPAR_LOG(trace) << L"4## " << t.elapsed();\r
+\r
+ t.restart();\r
}\r
catch(...)\r
{\r