\r
spl::shared_ptr<texture> create_texture(int width, int height, int stride, bool clear = false)\r
{\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
+ CASPAR_VERIFY(stride > 0 && stride < 5);\r
+ CASPAR_VERIFY(width > 0 && height > 0);\r
+\r
+ if(!render_executor_.is_current())\r
+ BOOST_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
\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
- if(clear)\r
- buffer->clear();\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
+ return spl::shared_ptr<texture>(buffer.get(), [buffer, pool](texture*) mutable\r
+ { \r
+ pool->push(buffer); \r
});\r
}\r
\r
return spl::make_shared<buffer>(size, usage);\r
});\r
}\r
- \r
- auto ptr = buf->data();\r
- auto self = shared_from_this(); // buffers can leave the device context, take a hold on life-time.\r
-\r
- auto on_release = [self, buf, ptr, usage, pool]() mutable\r
- { \r
- if(usage == buffer::usage::write_only) \r
- buf->map(); \r
- else\r
- buf->unmap();\r
-\r
- self->texture_cache_.erase(buf.get());\r
-\r
- pool->push(buf);\r
- };\r
\r
+ auto self = shared_from_this(); // buffers can leave the device context, take a hold on life-time.\r
return spl::shared_ptr<buffer>(buf.get(), [=](buffer*) mutable\r
- {\r
- self->alloc_executor_.begin_invoke(on_release); \r
+ { \r
+ texture_cache_.erase(buf.get());\r
+ pool->push(buf);\r
});\r
}\r
\r
\r
boost::unique_future<array<const std::uint8_t>> copy_async(const spl::shared_ptr<texture>& source)\r
{\r
- return flatten(render_executor_.begin_invoke([=]() -> boost::shared_future<array<const std::uint8_t>>\r
- {\r
- auto buffer = create_buffer(source->size(), buffer::usage::read_only); \r
- source->copy_to(*buffer); \r
+ if(!render_executor_.is_current())\r
+ BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Operation only valid in an OpenGL Context."));\r
\r
- auto self = shared_from_this();\r
- return async(launch::deferred, [self, buffer]() mutable -> array<const std::uint8_t>\r
- {\r
- const auto& buf = buffer.get();\r
- if(!buf->data())\r
- self->alloc_executor_.invoke(std::bind(&buffer::map, std::ref(buf))); // Defer blocking "map" call until data is needed.\r
+ auto buffer = create_buffer(source->size(), buffer::usage::read_only); \r
+ source->copy_to(*buffer); \r
\r
- return array<const std::uint8_t>(buf->data(), buf->size(), true, buffer);\r
- });\r
- }, task_priority::high_priority));\r
+ auto self = shared_from_this();\r
+ return async(launch::deferred, [self, buffer]() mutable -> array<const std::uint8_t>\r
+ {\r
+ const auto& buf = buffer.get();\r
+ if(!buf->data())\r
+ self->alloc_executor_.invoke(std::bind(&buffer::map, std::ref(buf))); // Defer blocking "map" call until data is needed.\r
+\r
+ return array<const std::uint8_t>(buf->data(), buf->size(), true, buffer);\r
+ });\r
}\r
};\r
\r
{\r
try\r
{\r
- if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.\r
+ if(is_current()) // Avoids potential deadlock.\r
my_task();\r
}\r
catch(boost::task_already_started&){}\r
template<typename Func>\r
auto invoke(Func&& func, task_priority prioriy = task_priority::normal_priority) -> decltype(func()) // noexcept\r
{\r
- if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.\r
+ if(is_current()) // Avoids potential deadlock.\r
return func();\r
\r
return begin_invoke(std::forward<Func>(func), prioriy).get();\r
\r
void yield() // noexcept\r
{\r
- if(boost::this_thread::get_id() != thread_.get_id())\r
+ if(!is_current())\r
BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Executor can only yield inside of thread context."));\r
\r
int dummy;\r
{\r
return is_running_; \r
} \r
+\r
+ bool is_current() const\r
+ {\r
+ return boost::this_thread::get_id() == thread_.get_id();\r
+ }\r
\r
private: \r
\r