-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\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
-*\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
-#include "../../stdafx.h"\r
-\r
-#include "buffer.h"\r
-\r
-#include "texture.h"\r
-#include "device.h"\r
-\r
-#include <common/except.h>\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <gl/glew.h>\r
-\r
-#include <tbb/atomic.h>\r
-\r
-namespace caspar { namespace accelerator { namespace ogl {\r
-\r
-static tbb::atomic<int> g_w_total_count;\r
-static tbb::atomic<int> g_r_total_count;\r
- \r
-struct buffer::impl : boost::noncopyable\r
-{ \r
- GLuint pbo_;\r
- const std::size_t size_;\r
- tbb::atomic<uint8_t*> data_;\r
- GLenum usage_;\r
- GLenum target_;\r
-\r
-public:\r
- impl(std::size_t size, buffer::usage usage) \r
- : size_(size)\r
- , target_(usage == buffer::usage::write_only ? GL_PIXEL_UNPACK_BUFFER : GL_PIXEL_PACK_BUFFER)\r
- , usage_(usage == buffer::usage::write_only ? GL_STREAM_DRAW : GL_STREAM_READ)\r
- {\r
- boost::timer timer;\r
-\r
- data_ = nullptr;\r
- GL(glGenBuffers(1, &pbo_));\r
- bind(); \r
- GL(glBufferData(target_, size_, NULL, usage_)); \r
- if(usage_ == GL_STREAM_DRAW) \r
- data_ = (uint8_t*)GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY)); \r
- unbind();\r
-\r
- if(!pbo_)\r
- CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
- \r
- if(timer.elapsed() > 0.02)\r
- CASPAR_LOG(debug) << L"[buffer] Performance warning. Buffer allocation blocked: " << timer.elapsed();\r
- \r
- //CASPAR_LOG(trace) << "[buffer] [" << ++(usage_ == buffer::usage::write_only ? g_w_total_count : g_r_total_count) << L"] allocated size:" << size_ << " usage: " << (usage == buffer::usage::write_only ? "write_only" : "read_only");\r
- } \r
-\r
- ~impl()\r
- {\r
- glDeleteBuffers(1, &pbo_);\r
- }\r
-\r
- void* map()\r
- {\r
- if(data_ != nullptr)\r
- return data_;\r
- \r
- boost::timer timer;\r
-\r
- GL(glBindBuffer(target_, pbo_));\r
- if(usage_ == GL_STREAM_DRAW) \r
- GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
- \r
- data_ = (uint8_t*)GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY)); \r
-\r
- if(timer.elapsed() > 0.02)\r
- CASPAR_LOG(debug) << L"[buffer] Performance warning. Buffer mapping blocked: " << timer.elapsed();\r
-\r
- GL(glBindBuffer(target_, 0));\r
- if(!data_)\r
- CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target OpenGL Pixel Buffer Object."));\r
-\r
- return data_;\r
- }\r
- \r
- void unmap()\r
- {\r
- if(data_ == nullptr)\r
- return;\r
- \r
- GL(glBindBuffer(target_, pbo_));\r
- GL(glUnmapBuffer(target_)); \r
- if(usage_ == GL_STREAM_READ) \r
- GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
- data_ = nullptr; \r
- GL(glBindBuffer(target_, 0));\r
- }\r
-\r
- void bind()\r
- {\r
- GL(glBindBuffer(target_, pbo_));\r
- }\r
-\r
- void unbind()\r
- {\r
- GL(glBindBuffer(target_, 0));\r
- }\r
-};\r
-\r
-buffer::buffer(std::size_t size, usage usage) : impl_(new impl(size, usage)){}\r
-buffer::buffer(buffer&& other) : impl_(std::move(other.impl_)){}\r
-buffer::~buffer(){}\r
-buffer& buffer::operator=(buffer&& other){impl_ = std::move(other.impl_); return *this;}\r
-uint8_t* buffer::data(){return impl_->data_;}\r
-void buffer::map(){impl_->map();}\r
-void buffer::unmap(){impl_->unmap();}\r
-void buffer::bind() const{impl_->bind();}\r
-void buffer::unbind() const{impl_->unbind();}\r
-std::size_t buffer::size() const { return impl_->size_; }\r
-int buffer::id() const {return impl_->pbo_;}\r
-\r
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* 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 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 <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "../../stdafx.h"
+
+#include "buffer.h"
+
+#include "texture.h"
+#include "device.h"
+
+#include <common/except.h>
+#include <common/gl/gl_check.h>
+
+#include <gl/glew.h>
+
+#include <tbb/atomic.h>
+
+namespace caspar { namespace accelerator { namespace ogl {
+
+static tbb::atomic<int> g_w_total_count;
+static tbb::atomic<int> g_r_total_count;
+
+struct buffer::impl : boost::noncopyable
+{
+ GLuint pbo_;
+ const std::size_t size_;
+ tbb::atomic<uint8_t*> data_;
+ GLenum usage_;
+ GLenum target_;
+
+public:
+ impl(std::size_t size, buffer::usage usage)
+ : size_(size)
+ , target_(usage == buffer::usage::write_only ? GL_PIXEL_UNPACK_BUFFER : GL_PIXEL_PACK_BUFFER)
+ , usage_(usage == buffer::usage::write_only ? GL_STREAM_DRAW : GL_STREAM_READ)
+ {
+ boost::timer timer;
+
+ data_ = nullptr;
+ GL(glGenBuffers(1, &pbo_));
+ bind();
+ GL(glBufferData(target_, size_, NULL, usage_));
+ if(usage_ == GL_STREAM_DRAW)
+ data_ = (uint8_t*)GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));
+ unbind();
+
+ if(!pbo_)
+ CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));
+
+ if(timer.elapsed() > 0.02)
+ CASPAR_LOG(debug) << L"[buffer] Performance warning. Buffer allocation blocked: " << timer.elapsed();
+
+ //CASPAR_LOG(trace) << "[buffer] [" << ++(usage_ == buffer::usage::write_only ? g_w_total_count : g_r_total_count) << L"] allocated size:" << size_ << " usage: " << (usage == buffer::usage::write_only ? "write_only" : "read_only");
+ }
+
+ ~impl()
+ {
+ glDeleteBuffers(1, &pbo_);
+ }
+
+ void* map()
+ {
+ if(data_ != nullptr)
+ return data_;
+
+ boost::timer timer;
+
+ GL(glBindBuffer(target_, pbo_));
+ if(usage_ == GL_STREAM_DRAW)
+ GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.
+
+ data_ = (uint8_t*)GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));
+
+ if(timer.elapsed() > 0.02)
+ CASPAR_LOG(debug) << L"[buffer] Performance warning. Buffer mapping blocked: " << timer.elapsed();
+
+ GL(glBindBuffer(target_, 0));
+ if(!data_)
+ CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target OpenGL Pixel Buffer Object."));
+
+ return data_;
+ }
+
+ void unmap()
+ {
+ if(data_ == nullptr)
+ return;
+
+ GL(glBindBuffer(target_, pbo_));
+ GL(glUnmapBuffer(target_));
+ if(usage_ == GL_STREAM_READ)
+ GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.
+ data_ = nullptr;
+ GL(glBindBuffer(target_, 0));
+ }
+
+ void bind()
+ {
+ GL(glBindBuffer(target_, pbo_));
+ }
+
+ void unbind()
+ {
+ GL(glBindBuffer(target_, 0));
+ }
+};
+
+buffer::buffer(std::size_t size, usage usage) : impl_(new impl(size, usage)){}
+buffer::buffer(buffer&& other) : impl_(std::move(other.impl_)){}
+buffer::~buffer(){}
+buffer& buffer::operator=(buffer&& other){impl_ = std::move(other.impl_); return *this;}
+uint8_t* buffer::data(){return impl_->data_;}
+void buffer::map(){impl_->map();}
+void buffer::unmap(){impl_->unmap();}
+void buffer::bind() const{impl_->bind();}
+void buffer::unbind() const{impl_->unbind();}
+std::size_t buffer::size() const { return impl_->size_; }
+int buffer::id() const {return impl_->pbo_;}
+
}}}
\ No newline at end of file