1 #include "../StdAfx.h"
\r
3 #include "pixel_buffer_object.h"
\r
5 #include "../../common/exception/exceptions.h"
\r
6 #include "../../common/gl/gl_check.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),
\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("format"));
\r
45 glDeleteBuffers(1, &pbo_);
\r
48 void bind_pbo(GLenum mode)
\r
51 GL(glGenBuffers(1, &pbo_));
\r
52 GL(glBindBuffer(mode, pbo_));
\r
55 void unbind_pbo(GLenum mode)
\r
57 GL(glBindBuffer(mode, 0));
\r
64 GL(glGenTextures(1, &texture_));
\r
66 GL(glBindTexture(GL_TEXTURE_2D, texture_));
\r
68 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
\r
69 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
\r
70 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
\r
71 GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
\r
73 GL(glTexImage2D(GL_TEXTURE_2D, 0, internal_, width_, height_, 0, format_,
\r
74 GL_UNSIGNED_BYTE, NULL));
\r
76 GL(glBindTexture(GL_TEXTURE_2D, texture_));
\r
81 bind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
83 GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));
\r
86 GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, format_,
\r
87 GL_UNSIGNED_BYTE, NULL));
\r
88 unbind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
95 BOOST_THROW_EXCEPTION(invalid_operation());
\r
97 bind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
98 GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW));
\r
99 auto data = static_cast<unsigned char*>(glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
\r
100 unbind_pbo(GL_PIXEL_UNPACK_BUFFER);
\r
102 BOOST_THROW_EXCEPTION(invalid_operation()
\r
103 << msg_info("glMapBuffer failed"));
\r
111 bind_pbo(GL_PIXEL_PACK_BUFFER);
\r
113 GL(glUnmapBuffer(GL_PIXEL_PACK_BUFFER));
\r
115 GL(glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ));
\r
116 GL(glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
\r
117 unbind_pbo(GL_PIXEL_PACK_BUFFER);
\r
124 BOOST_THROW_EXCEPTION(invalid_operation());
\r
126 bind_pbo(GL_PIXEL_PACK_BUFFER);
\r
127 auto data = static_cast<unsigned char*>(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY));
\r
128 unbind_pbo(GL_PIXEL_PACK_BUFFER);
\r
130 BOOST_THROW_EXCEPTION(std::bad_alloc());
\r
151 pixel_buffer_object::pixel_buffer_object(){}
\r
152 pixel_buffer_object::pixel_buffer_object(size_t width, size_t height, GLenum format)
\r
153 : impl_(new implementation(width, height, format)){}
\r
154 void pixel_buffer_object::create(size_t width, size_t height, GLenum format)
\r
156 impl_.reset(new implementation(width, height, format));
\r
158 void pixel_buffer_object::begin_write() { impl_->begin_write();}
\r
159 void* pixel_buffer_object::end_write() {return impl_->end_write();}
\r
160 void pixel_buffer_object::begin_read() { impl_->begin_read();}
\r
161 void* pixel_buffer_object::end_read(){return impl_->end_read();}
\r
162 void pixel_buffer_object::bind_texture() {impl_->bind_texture();}
\r
163 size_t pixel_buffer_object::width() const {return impl_->width_;}
\r
164 size_t pixel_buffer_object::height() const {return impl_->height_;}
\r
165 size_t pixel_buffer_object::size() const {return impl_->size_;}
\r
166 bool pixel_buffer_object::is_reading() const { return impl_->reading_;}
\r
167 bool pixel_buffer_object::is_writing() const { return impl_->writing_;}
\r