]> git.sesse.net Git - casparcg/blobdiff - core/mixer/gpu/ogl_device.cpp
- Increased consumer timeout to 10 seconds.
[casparcg] / core / mixer / gpu / ogl_device.cpp
index 760aaca4a55debd96e091f069de6a7f33f86831a..0ea77fbb4641b625975a0eeca14650045352f734 100644 (file)
@@ -1,22 +1,24 @@
 /*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+* Copyright 2013 Sveriges Television AB http://casparcg.com/\r
 *\r
-*  This file is part of CasparCG.\r
+* This file is part of CasparCG (www.casparcg.com).\r
 *\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
 *\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
 *\r
+* Author: Robert Nagy, ronag89@gmail.com\r
 */\r
+\r
 // TODO: Smart GC\r
 \r
 #include "../../stdafx.h"\r
@@ -30,6 +32,7 @@
 #include <common/gl/gl_check.h>\r
 \r
 #include <boost/foreach.hpp>\r
+#include <boost/property_tree/ptree.hpp>\r
 \r
 #include <gl/glew.h>\r
 \r
@@ -39,7 +42,9 @@ ogl_device::ogl_device()
        : executor_(L"ogl_device")\r
        , pattern_(nullptr)\r
        , attached_texture_(0)\r
+       , attached_fbo_(0)\r
        , active_shader_(0)\r
+       , read_buffer_(0)\r
 {\r
        CASPAR_LOG(info) << L"Initializing OpenGL Device.";\r
 \r
@@ -59,15 +64,10 @@ ogl_device::ogl_device()
                CASPAR_LOG(info) << L"OpenGL " << version();\r
 \r
                if(!GLEW_VERSION_3_0)\r
-                       CASPAR_LOG(warning) << "Missing OpenGL 3.0 support.";\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
-               CASPAR_LOG(info) << L"Successfully initialized GLEW.";\r
-\r
-               GL(glGenFramebuffers(1, &fbo_));                \r
-               GL(glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_));\r
-               GL(glReadBuffer(GL_COLOR_ATTACHMENT0_EXT));\r
-        //GL(glDisable(GL_MULTISAMPLE_ARB));\r
-\r
+               glGenFramebuffers(1, &fbo_);    \r
+               \r
                CASPAR_LOG(info) << L"Successfully initialized OpenGL Device.";\r
        });\r
 }\r
@@ -80,16 +80,16 @@ ogl_device::~ogl_device()
                        pool.clear();\r
                BOOST_FOREACH(auto& pool, host_pools_)\r
                        pool.clear();\r
-               glDeleteFramebuffersEXT(1, &fbo_);\r
+               glDeleteFramebuffers(1, &fbo_);\r
        });\r
 }\r
 \r
-safe_ptr<device_buffer> ogl_device::allocate_device_buffer(size_t width, size_t height, size_t stride)\r
+safe_ptr<device_buffer> ogl_device::allocate_device_buffer(size_t width, size_t height, size_t stride, bool mipmapped)\r
 {\r
        std::shared_ptr<device_buffer> buffer;\r
        try\r
        {\r
-               buffer.reset(new device_buffer(width, height, stride));\r
+               buffer.reset(new device_buffer(width, height, stride, mipmapped));\r
        }\r
        catch(...)\r
        {\r
@@ -99,7 +99,7 @@ safe_ptr<device_buffer> ogl_device::allocate_device_buffer(size_t width, size_t
                        gc().wait();\r
                                        \r
                        // Try again\r
-                       buffer.reset(new device_buffer(width, height, stride));\r
+                       buffer.reset(new device_buffer(width, height, stride, mipmapped));\r
                }\r
                catch(...)\r
                {\r
@@ -110,14 +110,14 @@ safe_ptr<device_buffer> ogl_device::allocate_device_buffer(size_t width, size_t
        return make_safe_ptr(buffer);\r
 }\r
                                \r
-safe_ptr<device_buffer> ogl_device::create_device_buffer(size_t width, size_t height, size_t stride)\r
+safe_ptr<device_buffer> ogl_device::create_device_buffer(size_t width, size_t height, size_t stride, bool mipmapped)\r
 {\r
        CASPAR_VERIFY(stride > 0 && stride < 5);\r
        CASPAR_VERIFY(width > 0 && height > 0);\r
-       auto& pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
+       auto& pool = device_pools_[stride-1 + (mipmapped ? 4 : 0)][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)];\r
        std::shared_ptr<device_buffer> buffer;\r
        if(!pool->items.try_pop(buffer))                \r
-               buffer = executor_.invoke([&]{return allocate_device_buffer(width, height, stride);}, high_priority);                   \r
+               buffer = executor_.invoke([&]{return allocate_device_buffer(width, height, stride, mipmapped);}, high_priority);                        \r
        \r
        //++pool->usage_count;\r
 \r
@@ -238,6 +238,97 @@ void ogl_device::yield()
        executor_.yield();\r
 }\r
 \r
+boost::property_tree::wptree ogl_device::info() const\r
+{\r
+       boost::property_tree::wptree info;\r
+\r
+       boost::property_tree::wptree pooled_device_buffers;\r
+       size_t total_pooled_device_buffer_size = 0;\r
+       size_t total_pooled_device_buffer_count = 0;\r
+\r
+       for (size_t i = 0; i < device_pools_.size(); ++i)\r
+       {\r
+               auto& pools = device_pools_.at(i);\r
+               bool mipmapping = i > 3;\r
+               int stride = mipmapping ? i - 3 : i + 1;\r
+\r
+               BOOST_FOREACH(auto& pool, pools)\r
+               {\r
+                       auto width = pool.first >> 16;\r
+                       auto height = pool.first & 0x0000FFFF;\r
+                       auto size = width * height * stride;\r
+                       auto count = pool.second->items.size();\r
+\r
+                       if (count == 0)\r
+                               continue;\r
+\r
+                       boost::property_tree::wptree pool_info;\r
+\r
+                       pool_info.add(L"stride", stride);\r
+                       pool_info.add(L"mipmapping", mipmapping);\r
+                       pool_info.add(L"width", width);\r
+                       pool_info.add(L"height", height);\r
+                       pool_info.add(L"size", size);\r
+                       pool_info.add(L"count", count);\r
+\r
+                       total_pooled_device_buffer_size += size * count;\r
+                       total_pooled_device_buffer_count += count;\r
+\r
+                       pooled_device_buffers.add_child(L"device_buffer_pool", pool_info);\r
+               }\r
+       }\r
+\r
+       info.add_child(L"gl.details.pooled_device_buffers", pooled_device_buffers);\r
+\r
+       boost::property_tree::wptree pooled_host_buffers;\r
+       size_t total_read_size = 0;\r
+       size_t total_write_size = 0;\r
+       size_t total_read_count = 0;\r
+       size_t total_write_count = 0;\r
+\r
+       for (size_t i = 0; i < host_pools_.size(); ++i)\r
+       {\r
+               auto& pools = host_pools_.at(i);\r
+               host_buffer::usage_t usage = static_cast<host_buffer::usage_t>(i);\r
+\r
+               BOOST_FOREACH(auto& pool, pools)\r
+               {\r
+                       auto size = pool.first;\r
+                       auto count = pool.second->items.size();\r
+\r
+                       if (count == 0)\r
+                               continue;\r
+\r
+                       boost::property_tree::wptree pool_info;\r
+\r
+                       pool_info.add(L"usage", usage == host_buffer::read_only\r
+                               ? L"read_only" : L"write_only");\r
+                       pool_info.add(L"size", size);\r
+                       pool_info.add(L"count", count);\r
+\r
+                       pooled_host_buffers.add_child(L"host_buffer_pool", pool_info);\r
+\r
+                       (usage == host_buffer::read_only\r
+                                       ? total_read_count : total_write_count) += count;\r
+                       (usage == host_buffer::read_only\r
+                                       ? total_read_size : total_write_size) += size * count;\r
+               }\r
+       }\r
+\r
+       info.add_child(L"gl.details.pooled_host_buffers", pooled_host_buffers);\r
+\r
+       info.add(L"gl.summary.pooled_device_buffers.total_count", total_pooled_device_buffer_count);\r
+       info.add(L"gl.summary.pooled_device_buffers.total_size", total_pooled_device_buffer_size);\r
+       info.add_child(L"gl.summary.all_device_buffers", device_buffer::info());\r
+       info.add(L"gl.summary.pooled_host_buffers.total_read_count", total_read_count);\r
+       info.add(L"gl.summary.pooled_host_buffers.total_write_count", total_write_count);\r
+       info.add(L"gl.summary.pooled_host_buffers.total_read_size", total_read_size);\r
+       info.add(L"gl.summary.pooled_host_buffers.total_write_size", total_write_size);\r
+       info.add_child(L"gl.summary.all_host_buffers", host_buffer::info());\r
+\r
+       return info;\r
+}\r
+\r
 boost::unique_future<void> ogl_device::gc()\r
 {      \r
        return begin_invoke([=]\r
@@ -335,6 +426,12 @@ void ogl_device::attach(device_buffer& texture)
 {      \r
        if(attached_texture_ != texture.id())\r
        {\r
+               if(attached_fbo_ != fbo_)\r
+               {\r
+                       glBindFramebuffer(GL_FRAMEBUFFER, fbo_);\r
+                       attached_fbo_ = fbo_;\r
+               }\r
+\r
                GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, texture.id(), 0));\r
                attached_texture_ = texture.id();\r
        }\r
@@ -346,6 +443,15 @@ void ogl_device::clear(device_buffer& texture)
        GL(glClear(GL_COLOR_BUFFER_BIT));\r
 }\r
 \r
+void ogl_device::read_buffer(device_buffer&)\r
+{\r
+       if(read_buffer_ != GL_COLOR_ATTACHMENT0)\r
+       {\r
+               GL(glReadBuffer(GL_COLOR_ATTACHMENT0));\r
+               read_buffer_ = GL_COLOR_ATTACHMENT0;\r
+       }\r
+}\r
+\r
 void ogl_device::use(shader& shader)\r
 {\r
        if(active_shader_ != shader.id())\r