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