Line data Source code
1 :
2 : /* Copyright (c) 2010, Cedric Stalder <cedric.stalder@eyescale.ch>
3 : * 2010-2014, Stefan Eilemann <eile@eyescale.ch>
4 : * 2010-2011, Daniel Nachbaur <danielnachbaur@gmail.com>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "compressorReadDrawPixels.h"
21 :
22 : #include <eq/fabric/pixelViewport.h>
23 : #include <eq/util/texture.h>
24 : #include <eq/util/pixelBufferObject.h>
25 : #include <lunchbox/buffer.h>
26 :
27 : #define glewGetContext() glewContext
28 : #define EQ_ASYNC_PBO // remove to use textures for async RB instead of PBOs
29 :
30 : namespace eq
31 : {
32 : namespace plugin
33 : {
34 :
35 : namespace
36 : {
37 : int _warned = 0;
38 12 : static stde::hash_map< unsigned, unsigned > _depths;
39 :
40 : #define REGISTER_TRANSFER( in, out, size, quality_, ratio_, speed_, alpha ) \
41 : static void _getInfo ## in ## out( EqCompressorInfo* const info ) \
42 : { \
43 : info->version = EQ_COMPRESSOR_VERSION; \
44 : info->capabilities = EQ_COMPRESSOR_TRANSFER | \
45 : EQ_COMPRESSOR_DATA_2D | \
46 : EQ_COMPRESSOR_USE_TEXTURE_RECT | \
47 : EQ_COMPRESSOR_USE_TEXTURE_2D | \
48 : EQ_COMPRESSOR_USE_ASYNC_DOWNLOAD | \
49 : EQ_COMPRESSOR_USE_FRAMEBUFFER; \
50 : if( alpha ) \
51 : info->capabilities |= EQ_COMPRESSOR_IGNORE_ALPHA; \
52 : info->quality = quality_ ## f; \
53 : info->ratio = ratio_ ## f; \
54 : info->speed = speed_ ## f; \
55 : info->name = EQ_COMPRESSOR_TRANSFER_ ## in ## _TO_ ## out; \
56 : info->tokenType = EQ_COMPRESSOR_DATATYPE_ ## in; \
57 : info->outputTokenType = EQ_COMPRESSOR_DATATYPE_ ## out; \
58 : info->outputTokenSize = size; \
59 : } \
60 : \
61 : static bool _register ## in ## out() \
62 : { \
63 : const unsigned name = EQ_COMPRESSOR_TRANSFER_ ## in ## _TO_ ## out; \
64 : Compressor::registerEngine( \
65 : Compressor::Functions( \
66 : name, \
67 : _getInfo ## in ## out, \
68 : CompressorReadDrawPixels::getNewCompressor, \
69 : CompressorReadDrawPixels::getNewDecompressor, \
70 : 0, \
71 : CompressorReadDrawPixels::isCompatible )); \
72 : _depths[ name ] = size; \
73 : return true; \
74 : } \
75 : \
76 : static bool _initialized ## in ## out LB_UNUSED = _register ## in ## out();
77 :
78 33 : REGISTER_TRANSFER( RGBA, RGBA, 4, 1., 1., 1., false );
79 33 : REGISTER_TRANSFER( RGBA, BGRA, 4, 1., 1., 2., false );
80 33 : REGISTER_TRANSFER( RGBA, RGBA_UINT_8_8_8_8_REV, 4, 1., 1., 1., false );
81 33 : REGISTER_TRANSFER( RGBA, BGRA_UINT_8_8_8_8_REV, 4, 1., 1., 2., false );
82 33 : REGISTER_TRANSFER( RGBA, RGB, 3, 1., 1., .7, true );
83 33 : REGISTER_TRANSFER( RGBA, BGR, 3, 1., 1., .7, true );
84 :
85 33 : REGISTER_TRANSFER( RGB10_A2, BGR10_A2, 4, 1., 1., 1.1, false );
86 33 : REGISTER_TRANSFER( RGB10_A2, RGB10_A2, 4, 1., 1., 1., false );
87 :
88 33 : REGISTER_TRANSFER( RGBA16F, RGBA16F, 8, 1., 1., 1., false );
89 33 : REGISTER_TRANSFER( RGBA16F, BGRA16F, 8, 1., 1., 1.1, false );
90 33 : REGISTER_TRANSFER( RGBA16F, RGB16F, 6, 1., 1., 1., true );
91 33 : REGISTER_TRANSFER( RGBA16F, BGR16F, 6, 1., 1., 1.1, true );
92 33 : REGISTER_TRANSFER( RGBA16F, RGBA, 4, .5, .5, 1., false );
93 33 : REGISTER_TRANSFER( RGBA16F, BGRA, 4, .5, .5, 1.1, false );
94 33 : REGISTER_TRANSFER( RGBA16F, RGB, 3, .5, .5, 1., true );
95 33 : REGISTER_TRANSFER( RGBA16F, BGR, 3, .5, .5, 1.1, true );
96 :
97 33 : REGISTER_TRANSFER( RGBA32F, RGBA32F, 16, 1., 1., 1.1, false );
98 33 : REGISTER_TRANSFER( RGBA32F, BGRA32F, 16, 1., 1., 1., false );
99 33 : REGISTER_TRANSFER( RGBA32F, RGB32F, 12, 1., 1., 1., true );
100 33 : REGISTER_TRANSFER( RGBA32F, BGR32F, 12, 1., 1., 1.1, true );
101 33 : REGISTER_TRANSFER( RGBA32F, RGBA16F, 8, .5, .5, 1., false );
102 33 : REGISTER_TRANSFER( RGBA32F, BGRA16F, 8,.5, .5, 1.1, false );
103 33 : REGISTER_TRANSFER( RGBA32F, RGB16F, 6, .5, .5, 1., true );
104 33 : REGISTER_TRANSFER( RGBA32F, BGR16F, 6, .5, .5, 1.1, true );
105 33 : REGISTER_TRANSFER( RGBA32F, RGBA, 4, .25, .25, 1., false );
106 33 : REGISTER_TRANSFER( RGBA32F, BGRA, 4, .25, .25, 1.1, false );
107 33 : REGISTER_TRANSFER( RGBA32F, RGB, 3, .25, .25, 1., true );
108 33 : REGISTER_TRANSFER( RGBA32F, BGR, 3, .25, .25, 1.1, true );
109 :
110 33 : REGISTER_TRANSFER( DEPTH, DEPTH_UNSIGNED_INT, 4, 1., 1., 1., false );
111 : }
112 :
113 5 : CompressorReadDrawPixels::CompressorReadDrawPixels( const unsigned name )
114 : : Compressor()
115 : , _texture( 0 )
116 : , _pbo( 0 )
117 : , _internalFormat( 0 )
118 : , _format( 0 )
119 : , _type( 0 )
120 5 : , _depth( _depths[ name ] )
121 : {
122 5 : LBASSERT( _depth > 0 );
123 5 : switch( name )
124 : {
125 : case EQ_COMPRESSOR_TRANSFER_RGBA_TO_RGBA:
126 0 : _format = GL_RGBA;
127 0 : _type = GL_UNSIGNED_BYTE;
128 0 : _internalFormat = GL_RGBA;
129 0 : break;
130 : case EQ_COMPRESSOR_TRANSFER_RGBA_TO_RGBA_UINT_8_8_8_8_REV:
131 0 : _format = GL_RGBA;
132 0 : _type = GL_UNSIGNED_BYTE;
133 0 : _internalFormat = GL_RGBA;
134 0 : break;
135 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_RGBA:
136 0 : _format = GL_RGBA;
137 0 : _type = GL_UNSIGNED_BYTE;
138 0 : _internalFormat = GL_RGBA16F;
139 0 : break;
140 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_RGBA16F:
141 0 : _format = GL_RGBA;
142 0 : _type = GL_HALF_FLOAT;
143 0 : _internalFormat = GL_RGBA16F;
144 0 : break;
145 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_RGBA:
146 0 : _format = GL_RGBA;
147 0 : _type = GL_UNSIGNED_BYTE;
148 0 : _internalFormat = GL_RGBA32F;
149 0 : break;
150 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_RGBA16F:
151 0 : _format = GL_RGBA;
152 0 : _type = GL_HALF_FLOAT;
153 0 : _internalFormat = GL_RGBA32F;
154 0 : break;
155 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_RGBA32F:
156 0 : _format = GL_RGBA;
157 0 : _type = GL_FLOAT;
158 0 : _internalFormat = GL_RGBA32F;
159 0 : break;
160 :
161 : case EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA:
162 5 : _format = GL_BGRA;
163 5 : _type = GL_UNSIGNED_BYTE;
164 5 : _internalFormat = GL_RGBA;
165 5 : break;
166 : case EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA_UINT_8_8_8_8_REV:
167 0 : _format = GL_BGRA;
168 0 : _type = GL_UNSIGNED_BYTE;
169 0 : _internalFormat = GL_RGBA;
170 0 : break;
171 : case EQ_COMPRESSOR_TRANSFER_RGB10_A2_TO_BGR10_A2:
172 0 : _format = GL_BGRA;
173 0 : _type = GL_UNSIGNED_INT_10_10_10_2;
174 0 : _internalFormat = GL_RGB10_A2;
175 0 : break;
176 : case EQ_COMPRESSOR_TRANSFER_RGB10_A2_TO_RGB10_A2:
177 0 : _format = GL_RGBA;
178 0 : _type = GL_UNSIGNED_INT_10_10_10_2;
179 0 : _internalFormat = GL_RGB10_A2;
180 0 : break;
181 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_BGRA:
182 0 : _format = GL_BGRA;
183 0 : _type = GL_UNSIGNED_BYTE;
184 0 : _internalFormat = GL_RGBA16F;
185 0 : break;
186 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_BGRA16F:
187 0 : _format = GL_BGRA;
188 0 : _type = GL_HALF_FLOAT;
189 0 : _internalFormat = GL_RGBA16F;
190 0 : break;
191 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGRA:
192 0 : _format = GL_BGRA;
193 0 : _type = GL_UNSIGNED_BYTE;
194 0 : _internalFormat = GL_RGBA32F;
195 0 : break;
196 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGRA16F:
197 0 : _format = GL_BGRA;
198 0 : _type = GL_HALF_FLOAT;
199 0 : _internalFormat = GL_RGBA32F;
200 0 : break;
201 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGRA32F:
202 0 : _format = GL_BGRA;
203 0 : _type = GL_FLOAT;
204 0 : _internalFormat = GL_RGBA32F;
205 0 : break;
206 : case EQ_COMPRESSOR_TRANSFER_RGBA_TO_RGB:
207 0 : _format = GL_RGB;
208 0 : _type = GL_UNSIGNED_BYTE;
209 0 : _internalFormat = GL_RGBA;
210 0 : break;
211 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_RGB:
212 0 : _format = GL_RGB;
213 0 : _type = GL_UNSIGNED_BYTE;
214 0 : _internalFormat = GL_RGBA16F;
215 0 : break;
216 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_RGB16F:
217 0 : _format = GL_RGB;
218 0 : _type = GL_HALF_FLOAT;
219 0 : _internalFormat = GL_RGBA16F;
220 0 : break;
221 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_RGB:
222 0 : _format = GL_RGB;
223 0 : _type = GL_UNSIGNED_BYTE;
224 0 : _internalFormat = GL_RGBA32F;
225 0 : break;
226 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_RGB32F:
227 0 : _format = GL_RGB;
228 0 : _type = GL_FLOAT;
229 0 : _internalFormat = GL_RGBA32F;
230 0 : break;
231 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_RGB16F:
232 0 : _format = GL_RGB;
233 0 : _type = GL_HALF_FLOAT;
234 0 : _internalFormat = GL_RGBA32F;
235 0 : break;
236 : case EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGR:
237 0 : _format = GL_BGR;
238 0 : _type = GL_UNSIGNED_BYTE;
239 0 : _internalFormat = GL_RGBA;
240 0 : break;
241 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_BGR:
242 0 : _format = GL_BGR;
243 0 : _type = GL_UNSIGNED_BYTE;
244 0 : _internalFormat = GL_RGBA16F;
245 0 : break;
246 : case EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_BGR16F:
247 0 : _format = GL_BGR;
248 0 : _type = GL_HALF_FLOAT;
249 0 : _internalFormat = GL_RGBA16F;
250 0 : break;
251 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGR:
252 0 : _format = GL_BGR;
253 0 : _type = GL_UNSIGNED_BYTE;
254 0 : _internalFormat = GL_RGBA32F;
255 0 : break;
256 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGR32F:
257 0 : _format = GL_BGR;
258 0 : _type = GL_FLOAT;
259 0 : _internalFormat = GL_RGBA32F;
260 0 : break;
261 : case EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGR16F:
262 0 : _format = GL_BGR;
263 0 : _type = GL_HALF_FLOAT;
264 0 : _internalFormat = GL_RGBA32F;
265 0 : break;
266 : case EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT:
267 0 : _format = GL_DEPTH_COMPONENT;
268 0 : _type = GL_UNSIGNED_INT;
269 0 : _internalFormat = GL_DEPTH_COMPONENT;
270 0 : break;
271 :
272 0 : default: LBASSERT( false );
273 : }
274 5 : }
275 :
276 15 : CompressorReadDrawPixels::~CompressorReadDrawPixels( )
277 : {
278 5 : delete _texture;
279 5 : _texture = 0;
280 :
281 5 : if( _pbo )
282 : {
283 3 : _pbo->destroy();
284 3 : delete _pbo;
285 3 : _pbo = 0;
286 : }
287 10 : }
288 :
289 19 : bool CompressorReadDrawPixels::isCompatible( const GLEWContext* )
290 : {
291 19 : return true;
292 : }
293 :
294 : namespace
295 : {
296 3 : void _copy4( eq_uint64_t dst[4], const eq_uint64_t src[4] )
297 : {
298 3 : memcpy( &dst[0], &src[0], sizeof(eq_uint64_t)*4 );
299 3 : }
300 :
301 6 : void _initPackAlignment( const eq_uint64_t width )
302 : {
303 6 : if( (width % 4) == 0 )
304 4 : glPixelStorei( GL_PACK_ALIGNMENT, 4 );
305 2 : else if( (width % 2) == 0 )
306 2 : glPixelStorei( GL_PACK_ALIGNMENT, 2 );
307 : else
308 0 : glPixelStorei( GL_PACK_ALIGNMENT, 1 );
309 6 : }
310 :
311 2 : void _initUnpackAlignment( const eq_uint64_t width )
312 : {
313 2 : if( (width % 4) == 0 )
314 1 : glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
315 1 : else if( (width % 2) == 0 )
316 1 : glPixelStorei( GL_UNPACK_ALIGNMENT, 2 );
317 : else
318 0 : glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
319 2 : }
320 : }
321 :
322 3 : void CompressorReadDrawPixels::_resizeBuffer( const eq_uint64_t size )
323 : {
324 : // eile: The code path using realloc creates visual artefacts on my MacBook
325 : // The other crashes occasionally with KERN_BAD_ADDRESS
326 : // Seems to be only with GL_RGB. Radar #8261726.
327 : #if 1
328 3 : _buffer.reserve( size );
329 3 : _buffer.setSize( size );
330 : #else
331 : // eile: This code path using realloc creates visual artefacts on my MacBook
332 : _buffer.resize( size );
333 : #endif
334 3 : }
335 :
336 0 : void CompressorReadDrawPixels::_initDownload( const GLEWContext*,
337 : const eq_uint64_t inDims[4],
338 : eq_uint64_t outDims[4] )
339 : {
340 0 : _copy4( outDims, inDims );
341 0 : const size_t size = inDims[1] * inDims[3] * _depth;
342 0 : _resizeBuffer( size );
343 0 : _initPackAlignment( outDims[1] );
344 0 : }
345 :
346 0 : void CompressorReadDrawPixels::_initTexture( const GLEWContext* glewContext,
347 : const eq_uint64_t flags )
348 : {
349 0 : GLenum target = 0;
350 0 : if( flags & EQ_COMPRESSOR_USE_TEXTURE_2D )
351 0 : target = GL_TEXTURE_2D;
352 0 : else if( flags & EQ_COMPRESSOR_USE_TEXTURE_RECT )
353 0 : target = GL_TEXTURE_RECTANGLE_ARB;
354 : else
355 : {
356 0 : LBUNREACHABLE;
357 : }
358 :
359 0 : if ( !_texture || _texture->getTarget() != target )
360 : {
361 0 : delete _texture;
362 0 : _texture = new util::Texture( target, glewContext );
363 : }
364 0 : }
365 :
366 0 : void CompressorReadDrawPixels::_initAsyncTexture(const GLEWContext* glewContext,
367 : const eq_uint64_t w,
368 : const eq_uint64_t h )
369 : {
370 0 : if( !_texture || _texture->getTarget() != GL_TEXTURE_RECTANGLE_ARB ||
371 0 : !_texture->isValid( ))
372 : {
373 0 : delete _texture;
374 0 : _texture = new util::Texture( GL_TEXTURE_RECTANGLE_ARB, glewContext );
375 : }
376 :
377 0 : _texture->setGLEWContext( glewContext );
378 0 : _texture->init( _internalFormat, w, h );
379 0 : }
380 :
381 :
382 0 : void CompressorReadDrawPixels::download( const GLEWContext* glewContext,
383 : const eq_uint64_t inDims[4],
384 : const unsigned source,
385 : const eq_uint64_t flags,
386 : eq_uint64_t outDims[4],
387 : void** out )
388 : {
389 0 : _initDownload( glewContext, inDims, outDims );
390 :
391 0 : if( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER )
392 : {
393 0 : EQ_GL_CALL( glReadPixels( inDims[0], inDims[2], inDims[1], inDims[3],
394 : _format, _type, _buffer.getData( )));
395 0 : *out = _buffer.getData();
396 : }
397 : else
398 : {
399 0 : _initTexture( glewContext, flags );
400 0 : _texture->setGLData( source, _internalFormat, inDims[1], inDims[3] );
401 0 : _texture->setExternalFormat( _format, _type );
402 0 : *out = _downloadTexture( glewContext, FLUSH_TEXTURE );
403 : }
404 :
405 0 : }
406 :
407 2 : void CompressorReadDrawPixels::upload( const GLEWContext* glewContext,
408 : const void* buffer,
409 : const eq_uint64_t inDims[4],
410 : const eq_uint64_t flags,
411 : const eq_uint64_t outDims[4],
412 : const unsigned destination )
413 : {
414 2 : _initUnpackAlignment( inDims[1] );
415 :
416 2 : if( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER )
417 : {
418 2 : glRasterPos2i( outDims[0], outDims[2] );
419 2 : glDrawPixels( outDims[1], outDims[3], _format, _type, buffer );
420 : }
421 : else
422 : {
423 0 : LBASSERT( outDims[0] == 0 && outDims[2]==0 ); // Implement me
424 0 : _initTexture( glewContext, flags );
425 : _texture->setGLData( destination, _internalFormat,
426 0 : outDims[1], outDims[3] );
427 0 : _texture->setExternalFormat( _format, _type );
428 0 : _texture->upload( outDims[1], outDims[3], buffer );
429 0 : _texture->flushNoDelete();
430 : }
431 2 : }
432 :
433 3 : bool CompressorReadDrawPixels::_initPBO( const GLEWContext* glewContext,
434 : const eq_uint64_t size )
435 : {
436 : // create thread-safe PBO
437 3 : if( !_pbo )
438 3 : _pbo = new util::PixelBufferObject( glewContext, true );
439 :
440 3 : const Error error = _pbo->setup( size, GL_READ_ONLY_ARB );
441 3 : if( !error )
442 0 : return true;
443 :
444 3 : if( _warned < 10 )
445 : {
446 9 : LBWARN << "Can't initialize PBO for async readback: " << error
447 9 : << std::endl;
448 3 : ++_warned;
449 : }
450 3 : return false;
451 : }
452 :
453 3 : void CompressorReadDrawPixels::startDownload( const GLEWContext* glewContext,
454 : const eq_uint64_t dims[4],
455 : const unsigned source,
456 : const eq_uint64_t flags )
457 : {
458 3 : _initPackAlignment( dims[1] );
459 :
460 3 : const eq_uint64_t size = dims[1] * dims[3] * _depth;
461 3 : if( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER )
462 : {
463 : #ifdef EQ_ASYNC_PBO
464 3 : if( _initPBO( glewContext, size ))
465 : {
466 0 : EQ_GL_CALL( glReadPixels( dims[0], dims[2], dims[1], dims[3],
467 : _format, _type, 0 ));
468 0 : _pbo->unbind();
469 0 : glFlush(); // Fixes https://github.com/Eyescale/Equalizer/issues/118
470 3 : return;
471 : }
472 : #else // else async RB through texture
473 : const PixelViewport pvp( dims[0], dims[2], dims[1], dims[3] );
474 : _initAsyncTexture( glewContext, pvp.w, pvp.h );
475 : _asyncTexture->setExternalFormat( _format, _type );
476 : _asyncTexture->copyFromFrameBuffer( _internalFormat, pvp );
477 : return;
478 : #endif
479 : // else
480 3 : _resizeBuffer( size );
481 3 : EQ_GL_CALL( glReadPixels( dims[0], dims[2], dims[1], dims[3],
482 : _format, _type, _buffer.getData( )));
483 : }
484 : else
485 : {
486 0 : _resizeBuffer( size );
487 0 : _initTexture( glewContext, flags );
488 0 : _texture->setGLData( source, _internalFormat, dims[1], dims[3] );
489 0 : _texture->setExternalFormat( _format, _type );
490 0 : glFlush(); // Enough?
491 : }
492 : }
493 :
494 0 : void* CompressorReadDrawPixels::_downloadTexture(
495 : const GLEWContext* glewContext, const FlushMode mode )
496 : {
497 0 : LBASSERT( _texture );
498 0 : _texture->setGLEWContext( glewContext );
499 0 : _texture->download( _buffer.getData( ));
500 0 : if( mode == FLUSH_TEXTURE )
501 0 : _texture->flushNoDelete();
502 :
503 0 : return _buffer.getData();
504 : }
505 :
506 3 : void CompressorReadDrawPixels::finishDownload(
507 : const GLEWContext* glewContext, const eq_uint64_t inDims[4],
508 : const eq_uint64_t flags, eq_uint64_t outDims[4], void** out )
509 : {
510 3 : _copy4( outDims, inDims );
511 3 : _initPackAlignment( inDims[1] );
512 :
513 3 : if( flags & (EQ_COMPRESSOR_USE_TEXTURE_RECT|EQ_COMPRESSOR_USE_TEXTURE_2D) )
514 : {
515 0 : *out = _downloadTexture( glewContext, FLUSH_TEXTURE );
516 3 : return;
517 : }
518 :
519 3 : LBASSERT( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER );
520 :
521 : #ifdef EQ_ASYNC_PBO
522 3 : if( _pbo && _pbo->isInitialized( ))
523 : {
524 0 : const eq_uint64_t size = inDims[1] * inDims[3] * _depth;
525 0 : _resizeBuffer( size );
526 :
527 0 : const void* ptr = _pbo->mapRead();
528 0 : if( ptr )
529 : {
530 0 : memcpy( _buffer.getData(), ptr, size );
531 0 : _pbo->unmap();
532 : }
533 : else
534 : {
535 0 : LBERROR << "Can't map PBO" << std::endl;
536 0 : EQ_GL_ERROR( "PixelBufferObject::mapRead()" );
537 : }
538 : }
539 3 : *out = _buffer.getData();
540 : #else // async RB through texture
541 : *out = _downloadTexture( glewContext, KEEP_TEXTURE );
542 : #endif
543 : }
544 :
545 : }
546 36 : }
|