#include "gpu_frame.h"\r
#include "../../common/utility/memory.h"\r
#include "../../common/gl/gl_check.h"\r
+#include "../../common/gl/pixel_buffer_object.h"\r
\r
namespace caspar { namespace core {\r
\r
struct gpu_frame::implementation : boost::noncopyable\r
{\r
implementation(size_t width, size_t height) \r
- : pbo_(0), data_(nullptr), width_(width), height_(height), \r
- size_(width*height*4), reading_(false), texture_(0), alpha_(1.0f), \r
+ : pbo_(width, height), data_(nullptr), width_(width), height_(height), \r
+ size_(width*height*4), reading_(false), alpha_(1.0f), \r
x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
- texcoords_(0.0, 1.0, 1.0, 0.0)\r
+ texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false)\r
{ \r
+ if(width > 0 && height > 0)\r
+ end_write();\r
}\r
-\r
- ~implementation()\r
+ \r
+ void begin_write()\r
{\r
- if(pbo_ != 0)\r
- glDeleteBuffers(1, &pbo_);\r
- if(texture_ != 0)\r
- glDeleteTextures(1, &texture_);\r
- }\r
-\r
- GLuint pbo()\r
- { \r
- if(pbo_ == 0)\r
- GL(glGenBuffers(1, &pbo_));\r
- return pbo_;\r
+ data_ = nullptr;\r
+ pbo_.begin_write(); \r
}\r
\r
- void write_lock()\r
+ void end_write()\r
{\r
- if(texture_ == 0)\r
- {\r
- GL(glGenTextures(1, &texture_));\r
-\r
- GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
-\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
- GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
-\r
- GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_, height_, 0, GL_BGRA, \r
- GL_UNSIGNED_BYTE, NULL));\r
- }\r
-\r
- GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo()));\r
- if(data_ != nullptr)\r
- {\r
- GL(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));\r
- data_ = nullptr;\r
- }\r
- GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
- GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, \r
- GL_UNSIGNED_BYTE, NULL));\r
- GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));\r
- }\r
-\r
- bool write_unlock()\r
- {\r
- if(data_ != nullptr)\r
- return false;\r
- GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo()));\r
- GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW));\r
- void* ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
- GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));\r
- data_ = reinterpret_cast<unsigned char*>(ptr);\r
- if(!data_)\r
- BOOST_THROW_EXCEPTION(invalid_operation() \r
- << msg_info("glMapBuffer failed"));\r
- return true;\r
+ data_ = static_cast<unsigned char*>(pbo_.end_write());\r
}\r
\r
- void read_lock(GLenum mode)\r
+ void begin_read()\r
{ \r
- GL(glReadBuffer(mode));\r
- GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo()));\r
- if(data_ != nullptr) \r
- { \r
- GL(glUnmapBuffer(GL_PIXEL_PACK_BUFFER)); \r
- data_ = nullptr;\r
- }\r
- GL(glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ)); \r
- GL(glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL));\r
- GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));\r
- reading_ = true;\r
+ data_ = nullptr;\r
+ pbo_.begin_read();\r
}\r
\r
- bool read_unlock()\r
+ void end_read()\r
{\r
- if(data_ != nullptr || !reading_)\r
- return false;\r
- GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo()));\r
- void* ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); \r
- GL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));\r
- data_ = reinterpret_cast<unsigned char*>(ptr);\r
- if(!data_)\r
- BOOST_THROW_EXCEPTION(std::bad_alloc());\r
- reading_ = false;\r
- return true;\r
+ data_ = static_cast<unsigned char*>(pbo_.end_read());\r
}\r
\r
void draw()\r
else if(mode_ == video_mode::lower)\r
glPolygonStipple(lower_pattern);\r
\r
- GL(glBindTexture(GL_TEXTURE_2D, texture_));\r
+ pbo_.bind_texture();\r
glBegin(GL_QUADS);\r
glTexCoord2d(texcoords_.left, texcoords_.bottom); glVertex2d(-1.0, -1.0);\r
glTexCoord2d(texcoords_.right, texcoords_.bottom); glVertex2d( 1.0, -1.0);\r
mode_ = video_mode::progressive;\r
}\r
\r
+ common::gl::pixel_buffer_object pbo_;\r
gpu_frame* self_;\r
- GLuint pbo_;\r
- GLuint texture_;\r
unsigned char* data_;\r
size_t width_;\r
size_t height_;\r
size_t size_;\r
+\r
bool reading_;\r
+ bool writing_;\r
+ bool mapped_;\r
+\r
std::vector<short> audio_data_;\r
\r
double alpha_;\r
\r
gpu_frame::gpu_frame(size_t width, size_t height) \r
: impl_(new implementation(width, height)){}\r
-void gpu_frame::write_lock(){impl_->write_lock();}\r
-bool gpu_frame::write_unlock(){return impl_->write_unlock();} \r
-void gpu_frame::read_lock(GLenum mode){impl_->read_lock(mode);}\r
-bool gpu_frame::read_unlock(){return impl_->read_unlock();}\r
+void gpu_frame::begin_write(){impl_->begin_write();}\r
+void gpu_frame::end_write(){impl_->end_write();} \r
+void gpu_frame::begin_read(){impl_->begin_read();}\r
+void gpu_frame::end_read(){impl_->end_read();}\r
void gpu_frame::draw(){impl_->draw();}\r
-bool gpu_frame::valid() const { return impl_->data_ != nullptr;}\r
unsigned char* gpu_frame::data(){return impl_->data();}\r
size_t gpu_frame::size() const { return impl_->size_; }\r
size_t gpu_frame::width() const { return impl_->width_;}\r