]> git.sesse.net Git - casparcg/blob - core/frame/gpu_frame.cpp
2.0.0.2:
[casparcg] / core / frame / gpu_frame.cpp
1 #include "../StdAfx.h"\r
2 \r
3 #include "gpu_frame.h"\r
4 #include "../../common/utility/memory.h"\r
5 #include "../../common/gl/gl_check.h"\r
6 #include "../../common/gl/pixel_buffer_object.h"\r
7 \r
8 namespace caspar { namespace core {\r
9         \r
10 GLubyte progressive_pattern[] = {\r
11         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
12         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
13         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
14         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
15         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
16         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
17         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
18         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
19         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
20         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
21         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
22         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
23         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
24         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
25         0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff,\r
26         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
27         \r
28 GLubyte upper_pattern[] = {\r
29         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
30         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
31         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
32         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
33         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
34         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
35         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
36         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
37         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
38         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
39         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
40         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
41         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
42         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
43         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
44         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
45                 \r
46 GLubyte lower_pattern[] = {\r
47                                                         0x00, 0x00, 0x00, 0x00,\r
48         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
49         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
50         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
51         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
52         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
53         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
54         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
55         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
56         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
57         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
58         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
59         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
60         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
61         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
62         0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
63         0xff, 0xff, 0xff, 0xff};\r
64                                                                                                                                                                                                                                                                                                                 \r
65 struct gpu_frame::implementation : boost::noncopyable\r
66 {\r
67         implementation(size_t width, size_t height)\r
68                 : reading_(false), alpha_(1.0f),        x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
69                         texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra)\r
70         {                       \r
71                 data_.resize(1, 0);\r
72                 pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(width, height, GL_BGRA));\r
73                 if(width > 0 && height > 0)\r
74                         end_write();\r
75         }\r
76 \r
77         implementation(const planar_frame_dimension& data_size)\r
78                 : reading_(false), alpha_(1.0f),        x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
79                         texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra)\r
80         {                       \r
81                 data_.resize(data_size.size(), 0);\r
82                 for(size_t n = 0; n < data_size.size() && data_size[n].first > 0 && data_size[n].second > 0; ++n)\r
83                         pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(data_size[n].first, data_size[n].second, GL_LUMINANCE));\r
84                 end_write();\r
85         }\r
86         \r
87         void begin_write()\r
88         {\r
89                 data_ = std::vector<unsigned char*>(4, 0);\r
90                 for(size_t n = 0; n < pbo_.size(); ++n)\r
91                         pbo_[n]->begin_write();         \r
92         }\r
93 \r
94         void end_write()\r
95         {\r
96                 for(size_t n = 0; n < pbo_.size(); ++n)\r
97                         data_[n] = static_cast<unsigned char*>(pbo_[n]->end_write());\r
98         }\r
99         \r
100         void begin_read()\r
101         {       \r
102                 data_ = std::vector<unsigned char*>(4, 0);\r
103                 for(size_t n = 0; n < pbo_.size(); ++n)\r
104                         pbo_[n]->begin_read();  \r
105         }\r
106 \r
107         void end_read()\r
108         {\r
109                 for(size_t n = 0; n < pbo_.size(); ++n)\r
110                         data_[n] = static_cast<unsigned char*>(pbo_[n]->end_read());\r
111         }\r
112 \r
113         void draw(const gpu_frame_transform_ptr& transform)\r
114         {\r
115                 transform->set_pixel_format(pix_format_);\r
116                 glPushMatrix();\r
117                 glTranslated(x_*2.0, y_*2.0, 0.0);\r
118                 glColor4d(1.0, 1.0, 1.0, alpha_);\r
119 \r
120                 if(mode_ == video_mode::progressive)\r
121                         glPolygonStipple(progressive_pattern);\r
122                 else if(mode_ == video_mode::upper)\r
123                         glPolygonStipple(upper_pattern);\r
124                 else if(mode_ == video_mode::lower)\r
125                         glPolygonStipple(lower_pattern);\r
126 \r
127                 for(size_t n = 0; n < pbo_.size(); ++n)\r
128                 {\r
129                         glActiveTexture(GL_TEXTURE0+n);\r
130                         pbo_[n]->bind_texture();\r
131                 }\r
132                 glBegin(GL_QUADS);\r
133                         glTexCoord2d(texcoords_.left,   texcoords_.bottom); glVertex2d(-1.0, -1.0);\r
134                         glTexCoord2d(texcoords_.right,  texcoords_.bottom); glVertex2d( 1.0, -1.0);\r
135                         glTexCoord2d(texcoords_.right,  texcoords_.top);        glVertex2d( 1.0,  1.0);\r
136                         glTexCoord2d(texcoords_.left,   texcoords_.top);        glVertex2d(-1.0,  1.0);\r
137                 glEnd();\r
138                 glPopMatrix();\r
139         }\r
140                 \r
141         unsigned char* data(size_t index)\r
142         {\r
143                 if(pbo_.size() < index || data_[index] == nullptr)\r
144                         BOOST_THROW_EXCEPTION(invalid_operation());\r
145                 return data_[index];\r
146         }\r
147 \r
148         void reset()\r
149         {\r
150                 audio_data_.clear();\r
151                 alpha_     = 1.0f;\r
152                 x_         = 0.0f;\r
153                 y_         = 0.0f;\r
154                 texcoords_ = rectangle(0.0, 1.0, 1.0, 0.0);\r
155                 mode_      = video_mode::progressive;\r
156         }\r
157 \r
158         std::vector<common::gl::pixel_buffer_object_ptr> pbo_;\r
159         std::vector<unsigned char*> data_;\r
160 \r
161         gpu_frame* self_;\r
162 \r
163         bool reading_;\r
164         bool writing_;\r
165         bool mapped_;\r
166 \r
167         std::vector<short> audio_data_;\r
168 \r
169         double alpha_;\r
170         double x_;\r
171         double y_;\r
172         video_mode mode_;\r
173         rectangle texcoords_;\r
174         pixel_format pix_format_;\r
175 };\r
176 \r
177 gpu_frame::gpu_frame(size_t width, size_t height) \r
178         : impl_(new implementation(width, height)){}\r
179 gpu_frame::gpu_frame(const planar_frame_dimension& data_size)\r
180         : impl_(new implementation(data_size)){}\r
181 void gpu_frame::begin_write(){impl_->begin_write();}\r
182 void gpu_frame::end_write(){impl_->end_write();}        \r
183 void gpu_frame::begin_read(){impl_->begin_read();}\r
184 void gpu_frame::end_read(){impl_->end_read();}\r
185 void gpu_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);}\r
186 void gpu_frame::set_pixel_format(pixel_format format) {impl_->pix_format_ = format;}\r
187 unsigned char* gpu_frame::data(size_t index){return impl_->data(index);}\r
188 size_t gpu_frame::size(size_t index) const { return impl_->pbo_.at(index)->size(); }\r
189 size_t gpu_frame::width(size_t index) const { return impl_->pbo_.at(index)->width();}\r
190 size_t gpu_frame::height(size_t index) const { return impl_->pbo_.at(index)->height();}\r
191 std::vector<short>& gpu_frame::audio_data() { return impl_->audio_data_; }\r
192 void gpu_frame::reset(){impl_->reset();}\r
193 double gpu_frame::alpha() const{ return impl_->alpha_;}\r
194 void gpu_frame::alpha(double value){ impl_->alpha_ = value;}\r
195 double gpu_frame::x() const { return impl_->x_;}\r
196 double gpu_frame::y() const { return impl_->y_;}\r
197 void gpu_frame::translate(double x, double y) { impl_->x_ += x; impl_->y_ += y; }\r
198 void gpu_frame::texcoords(const rectangle& texcoords){impl_->texcoords_ = texcoords;}\r
199 void gpu_frame::mode(video_mode mode){ impl_->mode_ = mode;}\r
200 video_mode gpu_frame::mode() const{ return impl_->mode_;}\r
201 }}