\r
#include <gl/glew.h>\r
\r
+#include <windows.h>\r
+\r
#include <SFML/Window/Context.hpp>\r
\r
#include <array>\r
#include <tbb/concurrent_queue.h>\r
\r
namespace caspar { namespace accelerator { namespace ogl {\r
- \r
+ \r
struct context::impl : public std::enable_shared_from_this<impl>\r
{\r
std::unique_ptr<sf::Context> context_;\r
+ std::unique_ptr<sf::Context> secondary_context_;\r
\r
std::array<tbb::concurrent_unordered_map<int, tbb::concurrent_bounded_queue<std::shared_ptr<device_buffer>>>, 4> device_pools_;\r
std::array<tbb::concurrent_unordered_map<int, tbb::concurrent_bounded_queue<std::shared_ptr<host_buffer>>>, 2> host_pools_;\r
GLuint fbo_;\r
\r
executor& executor_;\r
+ executor secondary_executor_;\r
\r
impl(executor& executor) \r
: executor_(executor)\r
+ , secondary_executor_(L"OpenGL allocation context")\r
{\r
CASPAR_LOG(info) << L"Initializing OpenGL Device.";\r
\r
- executor_.invoke([=]\r
+ auto ctx1 = executor_.invoke([=]() -> HGLRC \r
{\r
context_.reset(new sf::Context());\r
- context_->SetActive(true);\r
- \r
+ context_->SetActive(true); \r
+ \r
if (glewInit() != GLEW_OK)\r
BOOST_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to initialize GLEW."));\r
- \r
- CASPAR_LOG(info) << L"OpenGL " << version();\r
-\r
+ \r
if(!GLEW_VERSION_3_0)\r
BOOST_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Your graphics card does not meet the minimum hardware requirements since it does not support OpenGL 3.0 or higher. CasparCG Server will not be able to continue."));\r
\r
glGenFramebuffers(1, &fbo_); \r
glBindFramebuffer(GL_FRAMEBUFFER, fbo_);\r
+ \r
+ auto ctx1 = wglGetCurrentContext();\r
+ \r
+ context_->SetActive(false);\r
+\r
+ return ctx1;\r
+ });\r
\r
- CASPAR_LOG(info) << L"Successfully initialized OpenGL Device.";\r
+ secondary_executor_.invoke([=]\r
+ {\r
+ secondary_context_.reset(new sf::Context());\r
+ secondary_context_->SetActive(true); \r
+ auto ctx2 = wglGetCurrentContext();\r
+\r
+ if(!wglShareLists(ctx1, ctx2))\r
+ BOOST_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to share OpenGL contexts."));\r
});\r
+\r
+ executor_.invoke([=]\r
+ { \r
+ context_->SetActive(true);\r
+ });\r
+ \r
+ CASPAR_LOG(info) << L"Successfully initialized OpenGL " << version();\r
}\r
\r
~impl()\r
{\r
+ secondary_executor_.invoke([=]\r
+ {\r
+ secondary_context_.reset();\r
+ });\r
+\r
executor_.invoke([=]\r
{\r
BOOST_FOREACH(auto& pool, device_pools_)\r
BOOST_FOREACH(auto& pool, host_pools_)\r
pool.clear();\r
glDeleteFramebuffers(1, &fbo_);\r
+\r
+ context_.reset();\r
});\r
}\r
\r
spl::shared_ptr<device_buffer> allocate_device_buffer(int width, int height, int stride)\r
{\r
- std::shared_ptr<device_buffer> buffer;\r
- try\r
+ return executor_.invoke([&]() -> spl::shared_ptr<device_buffer>\r
{\r
- buffer.reset(new device_buffer(width, height, stride));\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG(error) << L"ogl: create_device_buffer failed!";\r
- throw;\r
- }\r
- return spl::make_shared_ptr(buffer);\r
+ std::shared_ptr<device_buffer> buffer;\r
+ try\r
+ {\r
+ buffer.reset(new device_buffer(width, height, stride));\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG(error) << L"ogl: create_device_buffer failed!";\r
+ throw;\r
+ }\r
+ return spl::make_shared_ptr(buffer);\r
+ });\r
}\r
\r
spl::shared_ptr<device_buffer> create_device_buffer(int width, int height, int stride)\r
\r
std::shared_ptr<device_buffer> buffer;\r
if(!pool->try_pop(buffer)) \r
- buffer = executor_.invoke([&]{return allocate_device_buffer(width, height, stride);}, task_priority::high_priority); \r
+ buffer = allocate_device_buffer(width, height, stride); \r
\r
auto self = shared_from_this();\r
return spl::shared_ptr<device_buffer>(buffer.get(), [self, buffer, pool](device_buffer*) mutable\r
\r
spl::shared_ptr<host_buffer> allocate_host_buffer(int size, host_buffer::usage usage)\r
{\r
- std::shared_ptr<host_buffer> buffer;\r
-\r
- try\r
- {\r
- buffer.reset(new host_buffer(size, usage));\r
- if(usage == host_buffer::usage::write_only)\r
- buffer->map();\r
- else\r
- buffer->unmap(); \r
- }\r
- catch(...)\r
+ return secondary_executor_.invoke([=]() -> spl::shared_ptr<host_buffer>\r
{\r
- CASPAR_LOG(error) << L"ogl: create_host_buffer failed!";\r
- throw; \r
- }\r
+ std::shared_ptr<host_buffer> buffer;\r
\r
- return spl::make_shared_ptr(buffer);\r
+ try\r
+ {\r
+ buffer.reset(new host_buffer(size, usage));\r
+ if(usage == host_buffer::usage::write_only)\r
+ buffer->map();\r
+ else\r
+ buffer->unmap(); \r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG(error) << L"ogl: create_host_buffer failed!";\r
+ throw; \r
+ }\r
+\r
+ return spl::make_shared_ptr(buffer);\r
+ });\r
}\r
\r
spl::shared_ptr<host_buffer> create_host_buffer(int size, host_buffer::usage usage)\r
\r
std::shared_ptr<host_buffer> buffer;\r
if(!pool->try_pop(buffer)) \r
- buffer = executor_.invoke([=]{return allocate_host_buffer(size, usage);}, task_priority::high_priority); \r
+ buffer = allocate_host_buffer(size, usage); \r
\r
- auto self = shared_from_this();\r
- bool is_write = (usage == host_buffer::usage::write_only);\r
+ bool is_write = (usage == host_buffer::usage::write_only);\r
+\r
+ auto self = shared_from_this();\r
return spl::shared_ptr<host_buffer>(buffer.get(), [self, is_write, buffer, pool](host_buffer*) mutable\r
{\r
- self->executor_.begin_invoke([=]() mutable\r
+ self->secondary_executor_.begin_invoke([=]() mutable\r
{ \r
if(is_write)\r
buffer->map();\r
tbb::atomic<uint32_t> file_frame_number_;\r
\r
public:\r
- explicit impl(const spl::shared_ptr<AVFormatContext>& context, const spl::shared_ptr<core::frame_factory>& frame_factory) \r
+ explicit impl(const spl::shared_ptr<AVFormatContext>& context) \r
: codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_))\r
, nb_frames_(static_cast<uint32_t>(context->streams[index_]->nb_frames))\r
, width_(codec_context_->width)\r
, height_(codec_context_->height)\r
{\r
file_frame_number_ = 0;\r
-\r
- // Reserve some frames\r
- std::vector<spl::shared_ptr<core::write_frame>> frames;\r
- for(int n = 0; n < 3; ++n)\r
- frames.push_back(frame_factory->create_frame(this, get_pixel_format_desc(codec_context_->pix_fmt, codec_context_->width, codec_context_->height)));\r
}\r
\r
void push(const std::shared_ptr<AVPacket>& packet)\r
}\r
};\r
\r
-video_decoder::video_decoder(const spl::shared_ptr<AVFormatContext>& context, const spl::shared_ptr<core::frame_factory>& frame_factory) : impl_(new impl(context, frame_factory)){}\r
+video_decoder::video_decoder(const spl::shared_ptr<AVFormatContext>& context) : impl_(new impl(context)){}\r
void video_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}\r
std::shared_ptr<AVFrame> video_decoder::poll(){return impl_->poll();}\r
bool video_decoder::ready() const{return impl_->ready();}\r