Line data Source code
1 :
2 : /* Copyright (c) 2012, Maxim Makhinya <maxmah@gmail.com>
3 : * 2012-2013, Stefan Eilemann <eile@eyescale.ch>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include "pixelBufferObject.h"
20 :
21 : #include <eq/client/gl.h>
22 : #include <lunchbox/debug.h>
23 : #include <lunchbox/scopedMutex.h>
24 :
25 : namespace eq
26 : {
27 : namespace util
28 : {
29 : namespace detail
30 : {
31 : class PixelBufferObject
32 : {
33 : public:
34 3 : PixelBufferObject( const GLEWContext* glewContext,
35 : const bool threadSafe )
36 3 : : lock_( threadSafe ? new lunchbox::Lock : 0 )
37 : , pboID( 0 )
38 : , size( 0 )
39 : , _glewContext( glewContext )
40 6 : , _type( 0 )
41 : {
42 3 : LBVERB << (void*)this << backtrace << std::endl;
43 3 : }
44 :
45 3 : ~PixelBufferObject()
46 : {
47 3 : LBASSERTINFO( !isInitialized(), (void*)this << backtrace );
48 3 : if( isInitialized( ))
49 0 : LBWARN << "PBO was not freed" << std::endl;
50 :
51 3 : delete lock_;
52 3 : }
53 :
54 3 : const GLEWContext* glewGetContext() const { return _glewContext; }
55 :
56 9 : bool isInitialized() const { return pboID != 0; }
57 :
58 3 : Error setup( const size_t newSize, const GLuint type )
59 : {
60 3 : LBASSERT( _glewContext );
61 :
62 3 : if( !GLEW_ARB_pixel_buffer_object )
63 3 : return Error( ERROR_PBO_UNSUPPORTED );
64 :
65 0 : if( newSize == 0 )
66 : {
67 0 : destroy();
68 0 : return Error( ERROR_PBO_SIZE_TOO_SMALL );
69 : }
70 :
71 0 : if( pboID == 0 )
72 : {
73 0 : EQ_GL_CALL( glGenBuffersARB( 1, &pboID ));
74 : }
75 0 : if( pboID == 0 )
76 0 : return Error( ERROR_PBO_NOT_INITIALIZED );
77 :
78 0 : if( _type == type && size >= newSize )
79 : {
80 0 : bind();
81 0 : return Error( ERROR_NONE );
82 : }
83 :
84 0 : _type = type;
85 0 : size = newSize;
86 0 : bind();
87 :
88 0 : switch( type )
89 : {
90 : case GL_READ_ONLY_ARB:
91 0 : EQ_GL_CALL(
92 : glBufferDataARB( GL_PIXEL_PACK_BUFFER_ARB, newSize, 0,
93 : GL_STREAM_READ_ARB ));
94 0 : return Error( ERROR_NONE );
95 :
96 : case GL_WRITE_ONLY_ARB:
97 0 : EQ_GL_CALL(
98 : glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, newSize, 0,
99 : GL_STREAM_DRAW_ARB ));
100 0 : return Error( ERROR_NONE );
101 :
102 : default:
103 0 : destroy();
104 0 : return Error( ERROR_PBO_TYPE_UNSUPPORTED );
105 : }
106 : }
107 :
108 3 : void destroy()
109 : {
110 3 : if( pboID != 0 )
111 : {
112 0 : unbind();
113 0 : EQ_GL_CALL( glDeleteBuffersARB( 1, &pboID ));
114 : }
115 3 : pboID = 0;
116 3 : size = 0;
117 3 : _type = 0;
118 3 : }
119 :
120 0 : const void* mapRead() const
121 : {
122 0 : if( !isInitialized() || _type != GL_READ_ONLY_ARB )
123 0 : return 0;
124 :
125 0 : bind();
126 0 : return glMapBufferARB( _getName(), GL_READ_ONLY_ARB );
127 : }
128 :
129 0 : void* mapWrite()
130 : {
131 0 : if( !isInitialized() || _type != GL_WRITE_ONLY_ARB )
132 0 : return 0;
133 :
134 0 : bind();
135 : // cancel all draw operations on this buffer to prevent stalling
136 0 : EQ_GL_CALL( glBufferDataARB( _getName(), size, 0, GL_STREAM_DRAW_ARB ));
137 0 : return glMapBufferARB( _getName(), GL_WRITE_ONLY_ARB );
138 : }
139 :
140 0 : void unmap() const
141 : {
142 0 : LBASSERT( isInitialized( ));
143 0 : EQ_GL_CALL( glUnmapBufferARB( _getName( )));
144 0 : unbind();
145 0 : }
146 :
147 0 : bool bind() const
148 : {
149 0 : if( !isInitialized( ))
150 0 : return false;
151 :
152 0 : EQ_GL_CALL( glBindBufferARB( _getName(), pboID ));
153 0 : return true;
154 : }
155 :
156 0 : void unbind() const
157 : {
158 0 : LBASSERT( isInitialized( ));
159 0 : EQ_GL_CALL( glBindBufferARB( _getName(), 0 ));
160 0 : }
161 :
162 0 : void lock() const { if( lock_ ) lock_->set(); }
163 0 : void unlock() const { if( lock_ ) lock_->unset(); }
164 :
165 : mutable lunchbox::Lock* lock_;
166 : GLuint pboID; //!< the PBO GL name
167 : size_t size; //!< size of the allocated PBO buffer
168 :
169 : private:
170 : const GLEWContext* const _glewContext;
171 : GLuint _type; //!< GL_READ_ONLY_ARB or GL_WRITE_ONLY_ARB
172 :
173 0 : GLuint _getName() const
174 : {
175 0 : return _type == GL_READ_ONLY_ARB ? GL_PIXEL_PACK_BUFFER_ARB :
176 0 : GL_PIXEL_UNPACK_BUFFER_ARB;
177 : }
178 : };
179 : }
180 :
181 3 : PixelBufferObject::PixelBufferObject( const GLEWContext* glewContext,
182 : const bool threadSafe )
183 3 : : _impl( new detail::PixelBufferObject( glewContext, threadSafe ))
184 : {
185 3 : }
186 :
187 6 : PixelBufferObject::~PixelBufferObject()
188 : {
189 3 : delete _impl;
190 6 : }
191 :
192 3 : Error PixelBufferObject::setup( const size_t size, const unsigned type )
193 : {
194 3 : lunchbox::ScopedWrite mutex( _impl->lock_ );
195 3 : return _impl->setup( size, type );
196 : }
197 :
198 3 : void PixelBufferObject::destroy()
199 : {
200 3 : lunchbox::ScopedWrite mutex( _impl->lock_ );
201 3 : _impl->destroy();
202 3 : }
203 :
204 0 : const void* PixelBufferObject::mapRead() const
205 : {
206 0 : _impl->lock();
207 0 : return _impl->mapRead();
208 : }
209 :
210 0 : void* PixelBufferObject::mapWrite()
211 : {
212 0 : _impl->lock();
213 0 : return _impl->mapWrite();
214 : }
215 :
216 0 : void PixelBufferObject::unmap() const
217 : {
218 0 : _impl->unmap();
219 0 : _impl->unlock();
220 0 : }
221 :
222 0 : bool PixelBufferObject::bind() const
223 : {
224 0 : _impl->lock();
225 0 : return _impl->bind();
226 : }
227 :
228 0 : void PixelBufferObject::unbind() const
229 : {
230 0 : _impl->unbind();
231 0 : _impl->unlock();
232 0 : }
233 :
234 0 : size_t PixelBufferObject::getSize() const
235 : {
236 0 : return _impl->size;
237 : }
238 :
239 3 : bool PixelBufferObject::isInitialized() const
240 : {
241 3 : return _impl->isInitialized();
242 : }
243 :
244 0 : bool PixelBufferObject::isThreadSafe() const
245 : {
246 0 : return _impl->lock_ != 0;
247 : }
248 :
249 0 : GLuint PixelBufferObject::getID() const
250 : {
251 0 : return _impl->pboID;
252 : }
253 :
254 : }
255 36 : }
|