]> git.sesse.net Git - casparcg/blob - accelerator/ogl/util/buffer.cpp
2.1.0: -cii: Merged changes from trunk.
[casparcg] / accelerator / ogl / util / buffer.cpp
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Robert Nagy, ronag89@gmail.com\r
20 */\r
21 \r
22 #include "../../stdafx.h"\r
23 \r
24 #include "buffer.h"\r
25 \r
26 #include "texture.h"\r
27 #include "device.h"\r
28 \r
29 #include <common/except.h>\r
30 #include <common/gl/gl_check.h>\r
31 \r
32 #include <gl/glew.h>\r
33 \r
34 #include <tbb/atomic.h>\r
35 \r
36 namespace caspar { namespace accelerator { namespace ogl {\r
37 \r
38 static tbb::atomic<int> g_w_total_count;\r
39 static tbb::atomic<int> g_r_total_count;\r
40                                                                                                                                                                                                                                                                                                                                 \r
41 struct buffer::impl : boost::noncopyable\r
42 {       \r
43         GLuint                                          pbo_;\r
44         const std::size_t                       size_;\r
45         tbb::atomic<uint8_t*>           data_;\r
46         GLenum                                          usage_;\r
47         GLenum                                          target_;\r
48 \r
49 public:\r
50         impl(std::size_t size, buffer::usage usage) \r
51                 : size_(size)\r
52                 , target_(usage == buffer::usage::write_only ? GL_PIXEL_UNPACK_BUFFER : GL_PIXEL_PACK_BUFFER)\r
53                 , usage_(usage == buffer::usage::write_only ? GL_STREAM_DRAW : GL_STREAM_READ)\r
54         {\r
55                 data_ = nullptr;\r
56                 GL(glGenBuffers(1, &pbo_));\r
57                 bind(); \r
58                 GL(glBufferData(target_, size_, NULL, usage_));         \r
59                 if(usage_ == GL_STREAM_DRAW)    \r
60                         data_ = (uint8_t*)GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));  \r
61                 unbind();\r
62 \r
63                 if(!pbo_)\r
64                         BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
65 \r
66                 //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
67         }       \r
68 \r
69         ~impl()\r
70         {\r
71                 glDeleteBuffers(1, &pbo_);\r
72         }\r
73 \r
74         void* map()\r
75         {\r
76                 if(data_ != nullptr)\r
77                         return data_;\r
78 \r
79                 GL(glBindBuffer(target_, pbo_));\r
80                 if(usage_ == GL_STREAM_DRAW)                    \r
81                         GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
82                 \r
83                 data_ = (uint8_t*)GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));  \r
84                 GL(glBindBuffer(target_, 0));\r
85                 if(!data_)\r
86                         BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target OpenGL Pixel Buffer Object."));\r
87 \r
88                 return data_;\r
89         }\r
90         \r
91         void unmap()\r
92         {\r
93                 if(data_ == nullptr)\r
94                         return;\r
95                 \r
96                 GL(glBindBuffer(target_, pbo_));\r
97                 GL(glUnmapBuffer(target_));     \r
98                 if(usage_ == GL_STREAM_READ)                    \r
99                         GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
100                 data_ = nullptr;        \r
101                 GL(glBindBuffer(target_, 0));\r
102         }\r
103 \r
104         void bind()\r
105         {\r
106                 GL(glBindBuffer(target_, pbo_));\r
107         }\r
108 \r
109         void unbind()\r
110         {\r
111                 GL(glBindBuffer(target_, 0));\r
112         }\r
113 };\r
114 \r
115 buffer::buffer(std::size_t size, usage usage) : impl_(new impl(size, usage)){}\r
116 buffer::~buffer(){}\r
117 uint8_t* buffer::data(){return impl_->data_;}\r
118 void buffer::map(){impl_->map();}\r
119 void buffer::unmap(){impl_->unmap();}\r
120 void buffer::bind() const{impl_->bind();}\r
121 void buffer::unbind() const{impl_->unbind();}\r
122 std::size_t buffer::size() const { return impl_->size_; }\r
123 \r
124 }}}