]> git.sesse.net Git - casparcg/blobdiff - core/frame/gpu_frame.cpp
2.0.0.2:
[casparcg] / core / frame / gpu_frame.cpp
index 2bbc4d5e8d47fca9e271a86518e22e36f90eb944..f66b3581536f3bd2a511db68cf24ad0cfed6702a 100644 (file)
@@ -3,6 +3,7 @@
 #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
@@ -64,99 +65,35 @@ GLubyte lower_pattern[] = {
 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
@@ -172,7 +109,7 @@ struct gpu_frame::implementation : boost::noncopyable
                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
@@ -199,14 +136,17 @@ struct gpu_frame::implementation : boost::noncopyable
                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
@@ -218,12 +158,11 @@ struct gpu_frame::implementation : boost::noncopyable
 \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