]> git.sesse.net Git - casparcg/blobdiff - core/mixer/gpu/host_buffer.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / mixer / gpu / host_buffer.cpp
index 17b5c7e35e835ed6b9b5d6ea560badd3c62712af..ec65338668de59c759c75fa973ce3ce19ee1a036 100644 (file)
@@ -1,20 +1,50 @@
-#include "../../StdAfx.h"\r
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+*  This file is part of CasparCG.\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
-#include "../gpu/host_buffer.h"\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
+*/\r
+#include "../../stdafx.h"\r
 \r
+#include "host_buffer.h"\r
+\r
+#include "fence.h"\r
+#include "device_buffer.h"\r
+#include "ogl_device.h"\r
+\r
+#include <common/exception/exceptions.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 core {\r
-                                                                                                                                                                                                                                                                                                                       \r
+\r
+static tbb::atomic<int> g_w_total_count;\r
+static tbb::atomic<int> g_r_total_count;\r
+                                                                                                                                                                                                                                                                                                                               \r
 struct host_buffer::implementation : boost::noncopyable\r
 {      \r
-       GLuint pbo_;\r
-\r
-       const size_t size_;\r
-\r
-       void* data_;\r
-       GLenum usage_;\r
-       GLenum target_;\r
+       GLuint                  pbo_;\r
+       const size_t    size_;\r
+       void*                   data_;\r
+       GLenum                  usage_;\r
+       GLenum                  target_;\r
+       fence                   fence_;\r
 \r
 public:\r
        implementation(size_t size, usage_t usage) \r
@@ -26,31 +56,49 @@ public:
        {\r
                GL(glGenBuffers(1, &pbo_));\r
                GL(glBindBuffer(target_, pbo_));\r
-               GL(glBufferData(target_, size_, NULL, usage_)); \r
+               if(usage_ != write_only)        \r
+                       GL(glBufferData(target_, size_, NULL, usage_)); \r
                GL(glBindBuffer(target_, 0));\r
 \r
                if(!pbo_)\r
                        BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
-               CASPAR_LOG(trace) << "[host_buffer] Allocated.";\r
+\r
+               CASPAR_LOG(trace) << "[host_buffer] [" << ++(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] allocated size:" << size_ << " usage: " << (usage == write_only ? "write_only" : "read_only");\r
        }       \r
 \r
        ~implementation()\r
        {\r
-               GL(glDeleteBuffers(1, &pbo_));\r
+               try\r
+               {\r
+                       GL(glDeleteBuffers(1, &pbo_));\r
+                       //CASPAR_LOG(trace) << "[host_buffer] [" << --(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] deallocated size:" << size_ << " usage: " << (usage_ == write_only ? "write_only" : "read_only");\r
+               }\r
+               catch(...)\r
+               {\r
+                       CASPAR_LOG_CURRENT_EXCEPTION();\r
+               }\r
        }\r
 \r
        void map()\r
        {\r
                if(data_)\r
                        return;\r
+\r
+               if(usage_ == write_only)                        \r
+                       GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
                \r
                GL(glBindBuffer(target_, pbo_));\r
-               data_ = glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY);  \r
+               data_ = GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));  \r
                GL(glBindBuffer(target_, 0)); \r
                if(!data_)\r
                        BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target_ OpenGL Pixel Buffer Object."));\r
        }\r
 \r
+       void wait(ogl_device& ogl)\r
+       {\r
+               fence_.wait(ogl);\r
+       }\r
+\r
        void unmap()\r
        {\r
                if(!data_)\r
@@ -71,6 +119,20 @@ public:
        {\r
                GL(glBindBuffer(target_, 0));\r
        }\r
+\r
+       void begin_read(size_t width, size_t height, GLuint format)\r
+       {\r
+               unmap();\r
+               bind();\r
+               GL(glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, NULL));\r
+               unbind();\r
+               fence_.set();\r
+       }\r
+\r
+       bool ready() const\r
+       {\r
+               return fence_.ready();\r
+       }\r
 };\r
 \r
 host_buffer::host_buffer(size_t size, usage_t usage) : impl_(new implementation(size, usage)){}\r
@@ -80,7 +142,9 @@ void host_buffer::map(){impl_->map();}
 void host_buffer::unmap(){impl_->unmap();}\r
 void host_buffer::bind(){impl_->bind();}\r
 void host_buffer::unbind(){impl_->unbind();}\r
-\r
+void host_buffer::begin_read(size_t width, size_t height, GLuint format){impl_->begin_read(width, height, format);}\r
 size_t host_buffer::size() const { return impl_->size_; }\r
+bool host_buffer::ready() const{return impl_->ready();}\r
+void host_buffer::wait(ogl_device& ogl){impl_->wait(ogl);}\r
 \r
 }}
\ No newline at end of file