1 #include "../StdAfx.h"
\r
3 #include "pixel_buffer_object.h"
\r
5 #include "../../common/exception/exceptions.h"
\r
6 #include "../../common/gl/utility.h"
\r
7 #include "../../common/utility/memory.h"
\r
9 namespace caspar { namespace common { namespace gl {
\r
11 struct pixel_buffer_object::implementation : boost::noncopyable
\r
13 implementation(size_t width, size_t height, GLenum format)
\r
14 : width_(width), height_(height), pbo_(0), format_(format), data_(nullptr),
\r
15 texture_(0), writing_(false), reading_(false), mapped_(false)
\r
21 internal_ = GL_RGBA8;
\r
22 size_ = width*height*4;
\r
25 internal_ = GL_RGB8;
\r
26 size_ = width*height*3;
\r
28 case GL_LUMINANCE_ALPHA:
\r
29 internal_ = GL_LUMINANCE_ALPHA;
\r
30 size_ = width*height*2;
\r
34 internal_ = GL_LUMINANCE;
\r
35 size_ = width*height*1;
\r
38 BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Unsupported format.") << arg_name_info("format"));
\r
40 if(width < 2 || height < 2)
\r
41 BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Invalid dimensions.") << arg_name_info("width/height"));
\r
47 glDeleteBuffers(1, &pbo_);
\r
49 glDeleteTextures(1, &texture_);
\r
52 void bind_pbo(GLenum mode)
\r
55 GL(glGenBuffers(1, &pbo_));
\r
56 GL(glBindBuffer(mode, pbo_));
\r
59 void unbind_pbo(GLenum mode)
\r
61 GL(glBindBuffer(mode, 0));
\r
68 GL(glGenTextures(1, &texture_));
\r
70 GL(glBindTexture(GL_TEXTURE_2D, texture_));
\r
72 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
\r
73 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
\r
74 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
\r
75 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
\r
77 GL(glTexImage2D(GL_TEXTURE_2D, 0, internal_, width_, height_, 0, format_, GL_UNSIGNED_BYTE, NULL));
\r
79 GL(glBindTexture(GL_TEXTURE_2D, texture_));
\r
84 bind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
86 GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));
\r
89 GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, format_, GL_UNSIGNED_BYTE, NULL));
\r
90 unbind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
101 BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Buffer is already mapped."));
\r
104 bind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
105 GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW));
\r
106 data_= glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
\r
107 unbind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
109 BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("glMapBuffer failed"));
\r
117 bind_pbo(GL_PIXEL_PACK_BUFFER);
\r
119 GL(glUnmapBuffer(GL_PIXEL_PACK_BUFFER));
\r
121 GL(glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ));
\r
122 GL(glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
\r
123 unbind_pbo(GL_PIXEL_PACK_BUFFER);
\r
134 BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Buffer is already mapped."));
\r
137 bind_pbo(GL_PIXEL_PACK_BUFFER);
\r
138 data_ = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
\r
139 unbind_pbo(GL_PIXEL_PACK_BUFFER);
\r
141 BOOST_THROW_EXCEPTION(std::bad_alloc());
\r
147 void is_smooth(bool smooth)
\r
151 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
\r
152 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
\r
156 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
\r
157 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
\r
176 pixel_buffer_object::pixel_buffer_object(){}
\r
177 pixel_buffer_object::pixel_buffer_object(size_t width, size_t height, GLenum format)
\r
178 : impl_(new implementation(width, height, format)){}
\r
179 void pixel_buffer_object::create(size_t width, size_t height, GLenum format)
\r
181 impl_.reset(new implementation(width, height, format));
\r
183 void pixel_buffer_object::begin_write() { impl_->begin_write();}
\r
184 void* pixel_buffer_object::end_write() {return impl_->end_write();}
\r
185 void pixel_buffer_object::begin_read() { impl_->begin_read();}
\r
186 void* pixel_buffer_object::end_read(){return impl_->end_read();}
\r
187 void pixel_buffer_object::bind_texture() {impl_->bind_texture();}
\r
188 size_t pixel_buffer_object::width() const {return impl_->width_;}
\r
189 size_t pixel_buffer_object::height() const {return impl_->height_;}
\r
190 size_t pixel_buffer_object::size() const {return impl_->size_;}
\r
191 bool pixel_buffer_object::is_reading() const { return impl_->reading_;}
\r
192 bool pixel_buffer_object::is_writing() const { return impl_->writing_;}
\r
193 void pixel_buffer_object::is_smooth(bool smooth){impl_->is_smooth(smooth);}
\r