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