00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <pthread.h>
00019 #include <eq/base/perThread.h>
00020
00021 #include "channel.h"
00022 #include "channelStatistics.h"
00023 #include "client.h"
00024 #include "compositor.h"
00025 #include "image.h"
00026 #include "log.h"
00027 #include "server.h"
00028 #include "windowSystem.h"
00029
00030 #include <eq/util/accum.h>
00031
00032 #include <eq/base/debug.h>
00033 #include <eq/base/executionListener.h>
00034 #include <eq/base/monitor.h>
00035
00036 #ifdef EQ_USE_PARACOMP
00037 # include <pcapi.h>
00038 #endif
00039
00040 #ifdef WIN32
00041 # define bzero( ptr, size ) memset( ptr, 0, size );
00042 #endif
00043
00044 using eq::base::Monitor;
00045
00046 namespace eq
00047 {
00048
00049 #define glewGetContext channel->glewGetContext
00050
00051 namespace
00052 {
00053
00054 static const char seed = 42;
00055 static const char* shaderDBKey = &seed;
00056 static const char* colorDBKey = shaderDBKey + 1;
00057 static const char* depthDBKey = shaderDBKey + 2;
00058 static const char* colorKey = shaderDBKey + 3;
00059 static const char* depthKey = shaderDBKey + 4;
00060
00061 class ResultImage : public Image
00062 {
00063 public:
00064 virtual ~ResultImage() {}
00065
00066 void notifyPerThreadDelete() { delete this; }
00067 };
00068
00069
00070
00071 static base::PerThread< ResultImage > _resultImage;
00072
00073
00074 static bool _useCPUAssembly( const FrameVector& frames, Channel* channel,
00075 const bool blendAlpha = false )
00076 {
00077
00078 if( frames.size() < 2 )
00079 return false;
00080
00081
00082
00083
00084
00085 const uint32_t desiredBuffers = blendAlpha ? Frame::BUFFER_COLOR :
00086 Frame::BUFFER_COLOR | Frame::BUFFER_DEPTH;
00087 size_t nFrames = 0;
00088 for( FrameVector::const_iterator i = frames.begin();
00089 i != frames.end(); ++i )
00090 {
00091 const Frame* frame = *i;
00092 if( frame->getPixel() != Pixel::ALL ||
00093 frame->getSubPixel() != SubPixel::ALL )
00094 {
00095 return false;
00096 }
00097
00098 if( frame->getBuffers() == desiredBuffers )
00099 ++nFrames;
00100 }
00101 if( nFrames < 2 )
00102 return false;
00103
00104
00105
00106
00107
00108 size_t nImages = 0;
00109 uint32_t colorFormat = 0;
00110 uint32_t colorType = 0;
00111 uint32_t depthFormat = 0;
00112 uint32_t depthType = 0;
00113
00114 for( FrameVector::const_iterator i = frames.begin();
00115 i != frames.end(); ++i )
00116 {
00117 const Frame* frame = *i;
00118 {
00119 ChannelStatistics event( Statistic::CHANNEL_WAIT_FRAME, channel );
00120 frame->waitReady();
00121 }
00122
00123 const ImageVector& images = frame->getImages();
00124 for( ImageVector::const_iterator j = images.begin();
00125 j != images.end(); ++j )
00126 {
00127 const Image* image = *j;
00128
00129 const bool hasColor = image->hasPixelData( Frame::BUFFER_COLOR );
00130 const bool hasDepth = image->hasPixelData( Frame::BUFFER_DEPTH );
00131
00132 if(( blendAlpha && hasColor && image->hasAlpha( )) ||
00133 ( hasColor && hasDepth ))
00134 {
00135 if( colorFormat == 0 )
00136 {
00137 colorFormat = image->getFormat( Frame::BUFFER_COLOR );
00138 colorType = image->getType( Frame::BUFFER_COLOR );
00139
00140 if (( colorType == GL_HALF_FLOAT ) ||
00141 ( colorType == GL_FLOAT ))
00142 return false;
00143 }
00144
00145 if( colorFormat != image->getFormat( Frame::BUFFER_COLOR ) ||
00146 colorType != image->getType( Frame::BUFFER_COLOR ))
00147
00148 return false;
00149
00150 if( image->hasPixelData( Frame::BUFFER_DEPTH ))
00151 {
00152 if( depthFormat == 0 )
00153 {
00154 depthFormat = image->getFormat( Frame::BUFFER_DEPTH );
00155 depthType = image->getType( Frame::BUFFER_DEPTH );
00156 }
00157
00158 if( depthFormat != image->getFormat(Frame::BUFFER_DEPTH ) ||
00159 depthType != image->getType( Frame::BUFFER_DEPTH ))
00160
00161 return false;
00162 }
00163
00164 ++nImages;
00165 }
00166 }
00167
00168 if( nImages > 1 )
00169 return true;
00170 }
00171
00172 return false;
00173 }
00174 }
00175
00176 uint32_t Compositor::assembleFrames( const FrameVector& frames,
00177 Channel* channel, util::Accum* accum )
00178 {
00179 if( frames.empty( ))
00180 return 0;
00181
00182 if( _useCPUAssembly( frames, channel ))
00183 return assembleFramesCPU( frames, channel );
00184
00185
00186 return assembleFramesUnsorted( frames, channel, accum );
00187 }
00188
00189 util::Accum* Compositor::_obtainAccum( Channel* channel )
00190 {
00191 const PixelViewport& pvp = channel->getPixelViewport();
00192
00193 EQASSERT( pvp.isValid( ));
00194
00195 Window::ObjectManager* objects = channel->getObjectManager();
00196 util::Accum* accum = objects->getEqAccum( channel );
00197 if( !accum )
00198 {
00199 accum = objects->newEqAccum( channel );
00200 if( !accum->init( pvp, channel->getWindow()->getColorFormat( )))
00201 {
00202 EQERROR << "Accumulation initialization failed." << std::endl;
00203 }
00204 }
00205 else
00206 accum->resize( pvp.w, pvp.h );
00207
00208 accum->clear();
00209 return accum;
00210 }
00211
00212 uint32_t Compositor::assembleFramesSorted( const FrameVector& frames,
00213 Channel* channel, util::Accum* accum,
00214 const bool blendAlpha )
00215 {
00216 if( frames.empty( ))
00217 return 0;
00218
00219 if( _isSubPixelDecomposition( frames ))
00220 {
00221 uint32_t count = 0;
00222 if( !accum )
00223 {
00224 accum = _obtainAccum( channel );
00225 accum->clear();
00226
00227 const SubPixel& subpixel = frames.back()->getSubPixel();
00228 accum->setTotalSteps( subpixel.size );
00229 }
00230
00231 FrameVector framesLeft = frames;
00232 while( !framesLeft.empty( ))
00233 {
00234 FrameVector current = _extractOneSubPixel( framesLeft );
00235 const uint32_t subCount = assembleFramesSorted( current, channel,
00236 accum );
00237 EQASSERT( subCount < 2 );
00238
00239 if( subCount > 0 )
00240 accum->accum();
00241 count += subCount;
00242 }
00243 if( count > 0 )
00244 accum->display();
00245 return count;
00246 }
00247
00248 uint32_t count = 0;
00249 if( blendAlpha )
00250 {
00251 glEnable( GL_BLEND );
00252 EQASSERT( GLEW_EXT_blend_func_separate );
00253 glBlendFuncSeparate( GL_ONE, GL_SRC_ALPHA, GL_ZERO, GL_SRC_ALPHA );
00254 }
00255
00256 if( _useCPUAssembly( frames, channel, blendAlpha ))
00257 count |= assembleFramesCPU( frames, channel, blendAlpha );
00258 else
00259 {
00260 for( FrameVector::const_iterator i = frames.begin();
00261 i != frames.end(); ++i )
00262 {
00263 Frame* frame = *i;
00264 {
00265 ChannelStatistics event( Statistic::CHANNEL_WAIT_FRAME,
00266 channel );
00267 frame->waitReady( );
00268 }
00269
00270 if( !frame->getImages().empty( ))
00271 {
00272 count = 1;
00273 assembleFrame( frame, channel );
00274 }
00275 }
00276 }
00277
00278 if( blendAlpha )
00279 glDisable( GL_BLEND );
00280
00281 return count;
00282 }
00283
00284 bool Compositor::_isSubPixelDecomposition( const FrameVector& frames )
00285 {
00286 if( frames.empty( ))
00287 return false;
00288
00289 FrameVector::const_iterator i = frames.begin();
00290 Frame* frame = *i;
00291 const SubPixel& subpixel = frame->getSubPixel();
00292
00293 for( ++i; i != frames.end(); ++i)
00294 {
00295 frame = *i;
00296 if( subpixel != frame->getSubPixel( ))
00297 return true;
00298 }
00299
00300 return false;
00301 }
00302
00303 const FrameVector Compositor::_extractOneSubPixel( FrameVector& frames )
00304 {
00305 FrameVector current;
00306
00307 const SubPixel& subpixel = frames.back()->getSubPixel();
00308 current.push_back( frames.back( ));
00309 frames.pop_back();
00310
00311 for( FrameVector::iterator i = frames.begin();
00312 i != frames.end(); )
00313 {
00314 Frame* frame = *i;
00315
00316 if( frame->getSubPixel() == subpixel )
00317 {
00318 current.push_back( frame );
00319 i = frames.erase( i );
00320 }
00321 else
00322 ++i;
00323 }
00324
00325 return current;
00326 }
00327
00328 uint32_t Compositor::assembleFramesUnsorted( const FrameVector& frames,
00329 Channel* channel,
00330 util::Accum* accum )
00331 {
00332 if( frames.empty( ))
00333 return 0;
00334
00335 EQVERB << "Unsorted GPU assembly" << std::endl;
00336 if( _isSubPixelDecomposition( frames ))
00337 {
00338 uint32_t count = 0;
00339
00340 if( !accum )
00341 {
00342 accum = _obtainAccum( channel );
00343 accum->clear();
00344
00345 const SubPixel& subpixel = frames.back()->getSubPixel();
00346 accum->setTotalSteps( subpixel.size );
00347 }
00348
00349 FrameVector framesLeft = frames;
00350 while( !framesLeft.empty( ))
00351 {
00352
00353 FrameVector current = _extractOneSubPixel( framesLeft );
00354
00355
00356 const uint32_t subCount = assembleFrames( current, channel, accum );
00357 EQASSERT( subCount < 2 )
00358 if( subCount > 0 )
00359 accum->accum();
00360 count += subCount;
00361 }
00362 if( count > 1 )
00363 accum->display();
00364 return count;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 Monitor<uint32_t> monitor;
00377 for( FrameVector::const_iterator i = frames.begin();
00378 i != frames.end(); ++i )
00379 {
00380 Frame* frame = *i;
00381 frame->addListener( monitor );
00382 }
00383
00384 uint32_t nUsedFrames = 0;
00385 FrameVector unusedFrames = frames;
00386
00387 uint32_t count = 0;
00388
00389 while( !unusedFrames.empty( ))
00390 {
00391 {
00392 ChannelStatistics event( Statistic::CHANNEL_WAIT_FRAME, channel );
00393 monitor.waitGE( ++nUsedFrames );
00394 }
00395
00396 for( FrameVector::iterator i = unusedFrames.begin();
00397 i != unusedFrames.end(); ++i )
00398 {
00399 Frame* frame = *i;
00400 if( !frame->isReady( ))
00401 continue;
00402
00403 if( !frame->getImages().empty( ))
00404 {
00405 count = 1;
00406 assembleFrame( frame, channel );
00407 }
00408
00409 unusedFrames.erase( i );
00410 break;
00411 }
00412 }
00413
00414
00415 for( FrameVector::const_iterator i = frames.begin(); i != frames.end();
00416 ++i )
00417 {
00418 Frame* frame = *i;
00419
00420 frame->removeListener( monitor );
00421 }
00422
00423 return count;
00424 }
00425
00426 uint32_t Compositor::assembleFramesCPU( const FrameVector& frames,
00427 Channel* channel,
00428 const bool blendAlpha )
00429 {
00430 if( frames.empty( ))
00431 return 0;
00432
00433 EQVERB << "Sorted CPU assembly" << std::endl;
00434
00435
00436
00437
00438 const Image* result = mergeFramesCPU( frames, blendAlpha );
00439 if( !result )
00440 return 0;
00441
00442
00443 ImageOp operation;
00444 operation.channel = channel;
00445 operation.buffers = Frame::BUFFER_COLOR | Frame::BUFFER_DEPTH;
00446 assembleImage( result, operation );
00447
00448 #if 0
00449 static uint32_t counter = 0;
00450 ostringstream stringstream;
00451 stringstream << "Image_" << ++counter;
00452 result->writeImages( stringstream.str( ));
00453 #endif
00454
00455 return 1;
00456 }
00457
00458 const Image* Compositor::mergeFramesCPU( const FrameVector& frames,
00459 const bool blendAlpha )
00460 {
00461 EQVERB << "Sorted CPU assembly" << std::endl;
00462
00463
00464 PixelViewport destPVP;
00465 uint32_t colorFormat = GL_NONE;
00466 uint32_t colorType = GL_NONE;
00467 uint32_t depthFormat = GL_NONE;
00468 uint32_t depthType = GL_NONE;
00469
00470 if( !_collectOutputData( frames, destPVP,
00471 colorFormat, colorType, depthFormat, depthType ))
00472 {
00473 return 0;
00474 }
00475
00476
00477 Image* result = _resultImage.get();
00478 if( !result )
00479 {
00480 _resultImage = new ResultImage;
00481 result = _resultImage.get();
00482 }
00483
00484
00485 EQASSERT( colorFormat != GL_NONE );
00486 EQASSERT( colorType != GL_NONE );
00487
00488 result->setFormat( Frame::BUFFER_COLOR, colorFormat );
00489 result->setType( Frame::BUFFER_COLOR, colorType );
00490 result->setPixelViewport( destPVP );
00491 result->clearPixelData( Frame::BUFFER_COLOR );
00492
00493 void* destDepth = 0;
00494 if( depthFormat != GL_NONE )
00495 {
00496 EQASSERT( depthFormat == GL_DEPTH_COMPONENT );
00497 EQASSERT( depthType == GL_UNSIGNED_INT );
00498
00499 result->setFormat( Frame::BUFFER_DEPTH, depthFormat );
00500 result->setType( Frame::BUFFER_DEPTH, depthType );
00501 result->clearPixelData( Frame::BUFFER_DEPTH );
00502 destDepth = result->getPixelPointer( Frame::BUFFER_DEPTH );
00503 }
00504
00505
00506 _mergeFrames( frames, blendAlpha,
00507 result->getPixelPointer( Frame::BUFFER_COLOR ),
00508 destDepth, destPVP );
00509 return result;
00510 }
00511
00512 bool Compositor::_collectOutputData( const FrameVector& frames,
00513 PixelViewport& destPVP,
00514 uint32_t& colorFormat, uint32_t& colorType,
00515 uint32_t& depthFormat, uint32_t& depthType)
00516 {
00517 for( FrameVector::const_iterator i = frames.begin(); i != frames.end(); ++i)
00518 {
00519 Frame* frame = *i;
00520 frame->waitReady();
00521
00522 EQASSERTINFO( frame->getPixel() == Pixel::ALL ||
00523 frame->getSubPixel() == SubPixel::ALL,
00524 "CPU-based (sub)pixel recomposition not implemented" );
00525 if( frame->getPixel() != Pixel::ALL )
00526 return false;
00527
00528 const ImageVector& images = frame->getImages();
00529 for( ImageVector::const_iterator j = images.begin();
00530 j != images.end(); ++j )
00531 {
00532 const Image* image = *j;
00533 EQASSERT( image->getStorageType() == Frame::TYPE_MEMORY );
00534 if( image->getStorageType() != Frame::TYPE_MEMORY )
00535 return false;
00536
00537 if( !image->hasPixelData( Frame::BUFFER_COLOR ))
00538 continue;
00539
00540 destPVP.merge( image->getPixelViewport() + frame->getOffset( ));
00541
00542 EQASSERT( colorFormat == GL_NONE ||
00543 colorFormat == image->getFormat( Frame::BUFFER_COLOR ));
00544 EQASSERT( colorType == GL_NONE ||
00545 colorType == image->getType( Frame::BUFFER_COLOR ));
00546
00547 colorFormat = image->getFormat( Frame::BUFFER_COLOR );
00548 colorType = image->getType( Frame::BUFFER_COLOR );
00549
00550 if( image->hasPixelData( Frame::BUFFER_DEPTH ))
00551 {
00552 EQASSERT( depthFormat == GL_NONE ||
00553 depthFormat == image->getFormat(Frame::BUFFER_DEPTH));
00554 EQASSERT( depthType == GL_NONE ||
00555 depthType == image->getType( Frame::BUFFER_DEPTH ));
00556
00557 depthFormat = image->getFormat( Frame::BUFFER_DEPTH );
00558 depthType = image->getType( Frame::BUFFER_DEPTH );
00559 }
00560 }
00561 }
00562
00563 if( !destPVP.hasArea( ))
00564 {
00565 EQWARN << "Nothing to assemble: " << destPVP << std::endl;
00566 return false;
00567 }
00568
00569 return true;
00570 }
00571
00572 bool Compositor::mergeFramesCPU( const FrameVector& frames,
00573 const bool blendAlpha, void* colorBuffer,
00574 const uint32_t colorBufferSize,
00575 void* depthBuffer,
00576 const uint32_t depthBufferSize,
00577 PixelViewport& outPVP )
00578 {
00579 EQASSERT( colorBuffer );
00580 EQVERB << "Sorted CPU assembly" << std::endl;
00581
00582
00583 uint32_t colorFormat = GL_NONE;
00584 uint32_t colorType = GL_NONE;
00585 uint32_t depthFormat = GL_NONE;
00586 uint32_t depthType = GL_NONE;
00587 outPVP.invalidate();
00588
00589 if( !_collectOutputData( frames, outPVP,
00590 colorFormat, colorType, depthFormat, depthType ))
00591 {
00592 return false;
00593 }
00594
00595
00596 EQASSERT( colorFormat != GL_NONE );
00597 EQASSERT( colorType != GL_NONE );
00598
00599
00600 const uint32_t area = outPVP.getArea();
00601 const uint32_t colorPixelDepth = (colorFormat == GL_RGB) ? 3 : 4;
00602
00603 if( colorBufferSize < area * colorPixelDepth )
00604 {
00605 EQWARN << "Color output buffer to small" << std::endl;
00606 return false;
00607 }
00608
00609 if( depthFormat != GL_NONE )
00610 {
00611 EQASSERT( depthBuffer );
00612 EQASSERT( depthFormat == GL_DEPTH_COMPONENT );
00613 EQASSERT( depthType == GL_UNSIGNED_INT );
00614
00615 if( !depthBuffer )
00616 {
00617 EQWARN << "No depth output buffer provided" << std::endl;
00618 return false;
00619 }
00620
00621 if( depthBufferSize < area * 4 )
00622 {
00623 EQWARN << "Depth output buffer to small" << std::endl;
00624 return false;
00625 }
00626 }
00627
00628
00629 _mergeFrames( frames, blendAlpha, colorBuffer, depthBuffer, outPVP );
00630 return true;
00631 }
00632
00633 void Compositor::_mergeFrames( const FrameVector& frames,
00634 const bool blendAlpha,
00635 void* colorBuffer, void* depthBuffer,
00636 const PixelViewport& destPVP )
00637 {
00638 for( FrameVector::const_iterator i = frames.begin(); i != frames.end(); ++i)
00639 {
00640 const Frame* frame = *i;
00641 const ImageVector& images = frame->getImages();
00642 for( ImageVector::const_iterator j = images.begin();
00643 j != images.end(); ++j )
00644 {
00645 const Image* image = *j;
00646
00647 if( !image->hasPixelData( Frame::BUFFER_COLOR ))
00648 continue;
00649
00650 if( image->hasPixelData( Frame::BUFFER_DEPTH ))
00651 _mergeDBImage( colorBuffer, depthBuffer, destPVP,
00652 image, frame->getOffset( ));
00653 else if( blendAlpha && image->hasAlpha( ))
00654 _mergeBlendImage( colorBuffer, destPVP,
00655 image, frame->getOffset( ));
00656 else
00657 _merge2DImage( colorBuffer, depthBuffer, destPVP,
00658 image, frame->getOffset());
00659 }
00660 }
00661 }
00662
00663
00664 void Compositor::_mergeDBImage( void* destColor, void* destDepth,
00665 const PixelViewport& destPVP,
00666 const Image* image,
00667 const Vector2i& offset )
00668 {
00669 EQASSERT( destColor && destDepth );
00670
00671 EQVERB << "CPU-DB assembly" << std::endl;
00672
00673 uint32_t* destC = reinterpret_cast< uint32_t* >( destColor );
00674 uint32_t* destD = reinterpret_cast< uint32_t* >( destDepth );
00675
00676 const PixelViewport& pvp = image->getPixelViewport();
00677
00678 #ifdef EQ_USE_PARACOMP_DEPTH
00679 if( pvp == destPVP && offset == eq::Vector2i::ZERO )
00680 {
00681
00682 if( _mergeImage_PC( PC_COMP_DEPTH, destColor, destDepth, image ))
00683 return;
00684
00685 EQWARN << "Paracomp compositing failed, using fallback" << std::endl;
00686 }
00687 #endif
00688
00689 const int32_t destX = offset.x() + pvp.x - destPVP.x;
00690 const int32_t destY = offset.y() + pvp.y - destPVP.y;
00691
00692 const uint32_t* color = reinterpret_cast< const uint32_t* >
00693 ( image->getPixelPointer( Frame::BUFFER_COLOR ));
00694 const uint32_t* depth = reinterpret_cast< const uint32_t* >
00695 ( image->getPixelPointer( Frame::BUFFER_DEPTH ));
00696
00697 #ifdef EQ_USE_OPENMP
00698 # pragma omp parallel for
00699 #endif
00700 for( int32_t y = 0; y < pvp.h; ++y )
00701 {
00702 const uint32_t skip = (destY + y) * destPVP.w + destX;
00703 uint32_t* destColorIt = destC + skip;
00704 uint32_t* destDepthIt = destD + skip;
00705 const uint32_t* colorIt = color + y * pvp.w;
00706 const uint32_t* depthIt = depth + y * pvp.w;
00707
00708 for( int32_t x = 0; x < pvp.w; ++x )
00709 {
00710 if( *destDepthIt > *depthIt )
00711 {
00712 *destColorIt = *colorIt;
00713 *destDepthIt = *depthIt;
00714 }
00715
00716 ++destColorIt;
00717 ++destDepthIt;
00718 ++colorIt;
00719 ++depthIt;
00720 }
00721 }
00722 }
00723
00724 void Compositor::_merge2DImage( void* destColor, void* destDepth,
00725 const eq::PixelViewport& destPVP,
00726 const Image* image,
00727 const Vector2i& offset )
00728 {
00729
00730 EQVERB << "CPU-2D assembly" << std::endl;
00731
00732 uint8_t* destC = reinterpret_cast< uint8_t* >( destColor );
00733 uint8_t* destD = reinterpret_cast< uint8_t* >( destDepth );
00734
00735 const PixelViewport& pvp = image->getPixelViewport();
00736 const int32_t destX = offset.x() + pvp.x - destPVP.x;
00737 const int32_t destY = offset.y() + pvp.y - destPVP.y;
00738
00739 EQASSERT( image->hasPixelData( Frame::BUFFER_COLOR ));
00740
00741 const uint8_t* color = image->getPixelPointer( Frame::BUFFER_COLOR );
00742 const size_t pixelSize = image->getDepth( Frame::BUFFER_COLOR );
00743 const size_t rowLength = pvp.w * pixelSize;
00744
00745 #ifdef EQ_USE_OPENMP
00746 # pragma omp parallel for
00747 #endif
00748 for( int32_t y = 0; y < pvp.h; ++y )
00749 {
00750 const size_t skip = ( (destY + y) * destPVP.w + destX ) * pixelSize;
00751 memcpy( destC + skip, color + y * pvp.w * pixelSize, rowLength);
00752 if( destD )
00753 bzero( destD + skip, rowLength );
00754 }
00755 }
00756
00757
00758 void Compositor::_mergeBlendImage( void* dest, const eq::PixelViewport& destPVP,
00759 const Image* image,
00760 const Vector2i& offset )
00761 {
00762 EQVERB << "CPU-Blend assembly"<< std::endl;
00763
00764 int32_t* destColor = reinterpret_cast< int32_t* >( dest );
00765
00766 const PixelViewport& pvp = image->getPixelViewport();
00767 const int32_t destX = offset.x() + pvp.x - destPVP.x;
00768 const int32_t destY = offset.y() + pvp.y - destPVP.y;
00769
00770 EQASSERT( image->getDepth( Frame::BUFFER_COLOR ) == 4 );
00771 EQASSERT( image->hasPixelData( Frame::BUFFER_COLOR ));
00772 EQASSERT( image->hasAlpha( ));
00773
00774 #ifdef EQ_USE_PARACOMP_BLEND
00775 if( pvp == destPVP && offset == eq::Vector2i::ZERO )
00776 {
00777
00778 if( !_mergeImage_PC( PC_COMP_ALPHA_SORT2_HP, dest, 0, image ))
00779 EQWARN << "Paracomp compositing failed, using fallback" << std::endl;
00780 else
00781 return;
00782 }
00783 #endif
00784
00785 const int32_t* color = reinterpret_cast< const int32_t* >
00786 ( image->getPixelPointer( Frame::BUFFER_COLOR ));
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 int32_t* destColorStart = destColor + destY*destPVP.w + destX;
00798 const uint32_t step = sizeof( int32_t );
00799
00800 #ifdef EQ_USE_OPENMP
00801 # pragma omp parallel for
00802 #endif
00803 for( int32_t y = 0; y < pvp.h; ++y )
00804 {
00805 const unsigned char* src =
00806 reinterpret_cast< const uint8_t* >( color + pvp.w * y );
00807 unsigned char* dst =
00808 reinterpret_cast< uint8_t* >( destColorStart + destPVP.w * y );
00809
00810 for( int32_t x = 0; x < pvp.w; ++x )
00811 {
00812 dst[0] = EQ_MIN( src[0] + (src[3]*dst[0] >> 8), 255 );
00813 dst[1] = EQ_MIN( src[1] + (src[3]*dst[1] >> 8), 255 );
00814 dst[2] = EQ_MIN( src[2] + (src[3]*dst[2] >> 8), 255 );
00815 dst[3] = src[3]*dst[3] >> 8;
00816
00817 src += step;
00818 dst += step;
00819 }
00820 }
00821 }
00822
00823 #ifdef EQ_USE_PARACOMP
00824 namespace
00825 {
00826 static unsigned glToPCFormat( const unsigned glFormat, const unsigned glType )
00827 {
00828 switch( glFormat )
00829 {
00830 case GL_RGBA:
00831 case GL_RGBA8:
00832 if( glType == GL_UNSIGNED_BYTE )
00833 return PC_PF_RGBA8;
00834 break;
00835
00836 case GL_BGRA:
00837 if( glType == GL_UNSIGNED_BYTE )
00838 return PC_PF_BGRA8;
00839 break;
00840
00841 case GL_BGR:
00842 if( glType == GL_UNSIGNED_BYTE )
00843 return PC_PF_BGR8;
00844 break;
00845
00846 case GL_DEPTH_COMPONENT:
00847 if( glType == GL_FLOAT )
00848 return PC_PF_Z32F;
00849 break;
00850 }
00851
00852 return 0;
00853 }
00854 }
00855 #endif
00856
00857 bool Compositor::_mergeImage_PC( int operation, void* destColor,
00858 void* destDepth, const Image* source )
00859 {
00860 #ifdef EQ_USE_PARACOMP
00861 const unsigned colorFormat =
00862 glToPCFormat( source->getFormat( Frame::BUFFER_COLOR ),
00863 source->getType( Frame::BUFFER_COLOR ));
00864
00865 if( colorFormat == 0 )
00866 {
00867 EQWARN << "Format or type of image not supported by Paracomp" << std::endl;
00868 return false;
00869 }
00870
00871 PCchannel input[2];
00872 PCchannel output[2];
00873
00874 input[0].pixelFormat = colorFormat;
00875 input[0].size = source->getDepth( Frame::BUFFER_COLOR );
00876 output[0].pixelFormat = colorFormat;
00877 output[0].size = source->getDepth( Frame::BUFFER_COLOR );
00878
00879 const PixelViewport& pvp = source->getPixelViewport();
00880 EQASSERT( pvp == source->getPixelViewport( ));
00881
00882 input[0].xOffset = 0;
00883 input[0].yOffset = 0;
00884 input[0].width = pvp.w;
00885 input[0].height = pvp.h;
00886 input[0].rowLength = pvp.w * input[0].size;
00887 input[0].address = source->getPixelPointer( Frame::BUFFER_COLOR );
00888
00889 output[0].xOffset = 0;
00890 output[0].yOffset = 0;
00891 output[0].width = pvp.w;
00892 output[0].height = pvp.h;
00893 output[0].rowLength = pvp.w * output[0].size;
00894 output[0].address = destColor;
00895
00896 const bool useDepth = ( operation == PC_COMP_DEPTH );
00897 if( useDepth )
00898 {
00899 const unsigned depthFormat =
00900 glToPCFormat( source->getFormat( Frame::BUFFER_DEPTH ),
00901 source->getType( Frame::BUFFER_DEPTH ));
00902
00903 if( depthFormat == 0 )
00904 {
00905 EQWARN << "Format or type of image not supported by Paracomp"
00906 << std::endl;
00907 return false;
00908 }
00909
00910 input[1].pixelFormat = depthFormat;
00911 input[1].size = source->getDepth( Frame::BUFFER_DEPTH );
00912 output[1].pixelFormat = depthFormat;
00913 output[1].size = source->getDepth( Frame::BUFFER_DEPTH );
00914
00915 input[1].xOffset = 0;
00916 input[1].yOffset = 0;
00917 input[1].width = pvp.w;
00918 input[1].height = pvp.h;
00919 input[1].rowLength = pvp.w * input[1].size;
00920 input[1].address = source->getPixelPointer( Frame::BUFFER_DEPTH );
00921
00922 output[1].xOffset = 0;
00923 output[1].yOffset = 0;
00924 output[1].width = pvp.w;
00925 output[1].height = pvp.h;
00926 output[1].rowLength = pvp.w * output[1].size;
00927 output[1].address = destDepth;
00928 }
00929
00930
00931 PCchannel* inputImages[2] = { output, input };
00932 PCchannel* outputImage[1] = { output };
00933 PCuint nInputChannels[2] = { 1, 1 };
00934 PCuint nOutputChannels[1] = { 1 };
00935
00936 if( useDepth )
00937 {
00938 nInputChannels[ 0 ] = 2;
00939 nInputChannels[ 1 ] = 2;
00940 nOutputChannels[ 0 ] = 2;
00941 }
00942
00943 const PCerr error = pcCompositeEXT( operation,
00944 2, nInputChannels, inputImages,
00945 1, nOutputChannels, outputImage );
00946 if( error != PC_NO_ERROR )
00947 {
00948 EQWARN << "Paracomp compositing failed: " << error << std::endl;
00949 return false;
00950 }
00951
00952 EQINFO << "Paracomp compositing successful" << std::endl;
00953 return true;
00954 #else
00955 return false;
00956 #endif
00957 }
00958
00959
00960 void Compositor::assembleFrame( const Frame* frame, Channel* channel )
00961 {
00962 const ImageVector& images = frame->getImages();
00963 if( images.empty( ))
00964 EQINFO << "No images to assemble" << std::endl;
00965
00966 ImageOp operation;
00967 operation.channel = channel;
00968 operation.buffers = frame->getBuffers();
00969 operation.offset = frame->getOffset();
00970 operation.pixel = frame->getPixel();
00971 operation.zoom = frame->getZoom();
00972
00973 for( ImageVector::const_iterator i = images.begin();
00974 i != images.end(); ++i )
00975 {
00976 const Image* image = *i;
00977 assembleImage( image, operation );
00978 }
00979 }
00980
00981 void Compositor::assembleImage( const Image* image, const ImageOp& op )
00982 {
00983 ImageOp operation = op;
00984 operation.buffers = Frame::BUFFER_NONE;
00985
00986 if( op.buffers&Frame::BUFFER_COLOR && image->hasData( Frame::BUFFER_COLOR ))
00987 operation.buffers |= Frame::BUFFER_COLOR;
00988
00989 if( op.buffers&Frame::BUFFER_DEPTH && image->hasData( Frame::BUFFER_DEPTH ))
00990 operation.buffers |= Frame::BUFFER_DEPTH;
00991
00992 if( operation.buffers == Frame::BUFFER_NONE )
00993 {
00994 EQWARN << "No image attachment buffers to assemble" << std::endl;
00995 return;
00996 }
00997
00998 setupStencilBuffer( image, operation );
00999
01000 if( operation.buffers == Frame::BUFFER_COLOR )
01001 assembleImage2D( image, operation );
01002 else if( operation.buffers == ( Frame::BUFFER_COLOR | Frame::BUFFER_DEPTH ))
01003 assembleImageDB( image, operation );
01004 else
01005 EQWARN << "Don't know how to assemble using buffers "
01006 << operation.buffers << std::endl;
01007
01008 clearStencilBuffer( operation );
01009 }
01010
01011 void Compositor::setupStencilBuffer( const Image* image, const ImageOp& op )
01012 {
01013 if( op.pixel == Pixel::ALL )
01014 return;
01015
01016
01017
01018 glClear( GL_STENCIL_BUFFER_BIT );
01019 glEnable( GL_STENCIL_TEST );
01020 glEnable( GL_DEPTH_TEST );
01021
01022 glStencilFunc( GL_ALWAYS, 1, 1 );
01023 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
01024
01025 glLineWidth( 1.0f );
01026 glDepthMask( false );
01027 glColorMask( false, false, false, false );
01028
01029 const PixelViewport& pvp = image->getPixelViewport();
01030
01031 glPixelZoom( static_cast< float >( op.pixel.w ),
01032 static_cast< float >( op.pixel.h ));
01033
01034 if( op.pixel.w > 1 )
01035 {
01036 const float width = static_cast< float >( pvp.w * op.pixel.w );
01037 const float step = static_cast< float >( op.pixel.w );
01038
01039 const float startX =
01040 static_cast< float >( op.offset.x() + pvp.x ) + 0.5f -
01041 static_cast< float >( op.pixel.w );
01042 const float endX = startX + width + op.pixel.w + step;
01043
01044 const float startY =
01045 static_cast< float >( op.offset.y() + pvp.y + op.pixel.y );
01046 const float endY = static_cast< float >( startY + pvp.h*op.pixel.h );
01047
01048 glBegin( GL_QUADS );
01049 for( float x = startX + op.pixel.x + 1.0f ; x < endX; x += step)
01050 {
01051 glVertex3f( x-step, startY, 0.0f );
01052 glVertex3f( x-1.0f, startY, 0.0f );
01053 glVertex3f( x-1.0f, endY, 0.0f );
01054 glVertex3f( x-step, endY, 0.0f );
01055 }
01056 glEnd();
01057 }
01058 if( op.pixel.h > 1 )
01059 {
01060 const float height = static_cast< float >( pvp.h * op.pixel.h );
01061 const float step = static_cast< float >( op.pixel.h );
01062
01063 const float startX =
01064 static_cast< float >( op.offset.x() + pvp.x + op.pixel.x );
01065 const float endX = static_cast< float >( startX + pvp.w*op.pixel.w );
01066
01067 const float startY =
01068 static_cast< float >( op.offset.y() + pvp.y ) + 0.5f -
01069 static_cast< float >( op.pixel.h );
01070 const float endY = startY + height + op.pixel.h + step;
01071
01072 glBegin( GL_QUADS );
01073 for( float y = startY + op.pixel.y; y < endY; y += step)
01074 {
01075 glVertex3f( startX, y-step, 0.0f );
01076 glVertex3f( endX, y-step, 0.0f );
01077 glVertex3f( endX, y-1.0f, 0.0f );
01078 glVertex3f( startX, y-1.0f, 0.0f );
01079 }
01080 glEnd();
01081 }
01082
01083 glDisable( GL_DEPTH_TEST );
01084 glStencilFunc( GL_EQUAL, 0, 1 );
01085 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
01086
01087 const ColorMask& colorMask = op.channel->getDrawBufferMask();
01088 glColorMask( colorMask.red, colorMask.green, colorMask.blue, true );
01089 glDepthMask( true );
01090 }
01091
01092 void Compositor::clearStencilBuffer( const ImageOp& op )
01093 {
01094 if( op.pixel == Pixel::ALL )
01095 return;
01096
01097 glPixelZoom( 1.f, 1.f );
01098 glDisable( GL_STENCIL_TEST );
01099 }
01100
01101 void Compositor::setupAssemblyState( const PixelViewport& pvp )
01102 {
01103 EQ_GL_ERROR( "before setupAssemblyState" );
01104 glPushAttrib( GL_ENABLE_BIT | GL_STENCIL_BUFFER_BIT | GL_VIEWPORT_BIT |
01105 GL_SCISSOR_BIT | GL_LINE_BIT | GL_PIXEL_MODE_BIT |
01106 GL_POLYGON_BIT );
01107
01108 glDisable( GL_DEPTH_TEST );
01109 glDisable( GL_BLEND );
01110 glDisable( GL_ALPHA_TEST );
01111 glDisable( GL_STENCIL_TEST );
01112 glDisable( GL_TEXTURE_1D );
01113 glDisable( GL_TEXTURE_2D );
01114 glDisable( GL_TEXTURE_3D );
01115 glDisable( GL_FOG );
01116 glDisable( GL_CLIP_PLANE0 );
01117 glDisable( GL_CLIP_PLANE1 );
01118 glDisable( GL_CLIP_PLANE2 );
01119 glDisable( GL_CLIP_PLANE3 );
01120 glDisable( GL_CLIP_PLANE4 );
01121 glDisable( GL_CLIP_PLANE5 );
01122
01123 glPolygonMode( GL_FRONT, GL_FILL );
01124
01125 if( pvp.hasArea( ))
01126 {
01127 glViewport( pvp.x, pvp.y, pvp.w, pvp.h );
01128 glScissor( pvp.x, pvp.y, pvp.w, pvp.h );
01129 }
01130 else
01131 EQERROR << "Can't apply viewport " << pvp << std::endl;
01132
01133 glMatrixMode( GL_PROJECTION );
01134 glPushMatrix();
01135 glLoadIdentity();
01136 if( pvp.hasArea( ))
01137 glOrtho( pvp.x, pvp.x + pvp.w, pvp.y, pvp.y + pvp.h, -1.0f, 1.0f );
01138
01139 glMatrixMode( GL_MODELVIEW );
01140 glPushMatrix();
01141 glLoadIdentity();
01142 EQ_GL_ERROR( "after setupAssemblyState" );
01143 }
01144
01145 void Compositor::resetAssemblyState()
01146 {
01147 EQ_GL_ERROR( "before resetAssemblyState" );
01148 glMatrixMode( GL_PROJECTION );
01149 glPopMatrix();
01150
01151 glMatrixMode( GL_MODELVIEW );
01152 glPopMatrix();
01153
01154 glPopAttrib();
01155 EQ_GL_ERROR( "after resetAssemblyState" );
01156 }
01157
01158 void Compositor::assembleImage2D( const Image* image, const ImageOp& op )
01159 {
01160 EQASSERT( image->hasData( Frame::BUFFER_COLOR ));
01161 _drawPixels( image, op, Frame::BUFFER_COLOR );
01162 }
01163
01164 void Compositor::_drawPixels( const Image* image,
01165 const ImageOp& op,
01166 const Frame::Buffer which )
01167 {
01168 const PixelViewport& pvp = image->getPixelViewport();
01169 EQLOG( LOG_ASSEMBLY ) << "_drawPixels " << pvp << " offset " << op.offset
01170 << std::endl;
01171
01172 if ( image->getStorageType() == Frame::TYPE_MEMORY )
01173 {
01174 EQASSERT( image->hasPixelData( which ));
01175
01176 if( op.zoom == eq::Zoom::NONE )
01177 {
01178 glRasterPos2i( op.offset.x() + pvp.x, op.offset.y() + pvp.y );
01179 glDrawPixels( pvp.w, pvp.h,
01180 image->getFormat( which ),
01181 image->getType( which ),
01182 image->getPixelPointer( which ));
01183 return;
01184 }
01185
01186
01187 Channel* channel = op.channel;
01188 Window::ObjectManager* objects = channel->getObjectManager();
01189
01190 util::Texture* texture = objects->obtainEqTexture(
01191 which == Frame::BUFFER_COLOR ? colorKey : depthKey );
01192
01193 texture->upload( image, which );
01194 }
01195 else
01196 {
01197 EQASSERT( image->hasTextureData( which ));
01198 image->getTexture( which ).bind();
01199 }
01200
01201 if ( which == Frame::BUFFER_COLOR )
01202 glDepthMask( false );
01203 else
01204 {
01205 EQASSERT( which == Frame::BUFFER_DEPTH )
01206 glColorMask( false, false, false, false );
01207 }
01208
01209 glDisable( GL_LIGHTING );
01210 glEnable( GL_TEXTURE_RECTANGLE_ARB );
01211 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
01212 GL_CLAMP_TO_EDGE );
01213 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
01214 GL_CLAMP_TO_EDGE );
01215
01216 if( op.zoom == eq::Zoom::NONE )
01217 {
01218 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
01219 GL_NEAREST );
01220 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
01221 GL_NEAREST );
01222 }else
01223 {
01224 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
01225 GL_LINEAR );
01226 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
01227 GL_LINEAR );
01228 }
01229
01230 glColor3f( 1.0f, 1.0f, 1.0f );
01231
01232 const float startX = static_cast< float >
01233 ( op.offset.x() + pvp.x * op.pixel.w + op.pixel.x ) * op.zoom.x();
01234 const float endX = static_cast< float >
01235 (op.offset.x() + (pvp.x+pvp.w) * op.pixel.w + op.pixel.x) *op.zoom.x();
01236 const float startY = static_cast< float >
01237 ( op.offset.y() + pvp.y * op.pixel.h + op.pixel.y ) * op.zoom.y();
01238 const float endY = static_cast< float >
01239 (op.offset.y() + (pvp.y+pvp.h) * op.pixel.h + op.pixel.y) *op.zoom.y();
01240
01241 glBegin( GL_QUADS );
01242 glTexCoord2f( 0.0f, 0.0f );
01243 glVertex3f( startX, startY, 0.0f );
01244
01245 glTexCoord2f( static_cast< float >( pvp.w ), 0.0f );
01246 glVertex3f( endX, startY, 0.0f );
01247
01248 glTexCoord2f( static_cast<float>( pvp.w ), static_cast<float>( pvp.h ));
01249 glVertex3f( endX, endY, 0.0f );
01250
01251 glTexCoord2f( 0.0f, static_cast< float >( pvp.h ));
01252 glVertex3f( startX, endY, 0.0f );
01253 glEnd();
01254
01255
01256 glDisable( GL_TEXTURE_RECTANGLE_ARB );
01257
01258 if ( which == Frame::BUFFER_COLOR )
01259 glDepthMask( true );
01260 else
01261 {
01262 const ColorMask& colorMask = op.channel->getDrawBufferMask();
01263 glColorMask( colorMask.red, colorMask.green, colorMask.blue, true );
01264 }
01265 }
01266
01267 void Compositor::assembleImageDB( const Image* image, const ImageOp& op )
01268 {
01269 Channel* channel = op.channel;
01270
01271 if( GLEW_VERSION_2_0 )
01272 assembleImageDB_GLSL( image, op );
01273 else
01274 assembleImageDB_FF( image, op );
01275 }
01276
01277 void Compositor::assembleImageDB_FF( const Image* image, const ImageOp& op )
01278 {
01279 const PixelViewport& pvp = image->getPixelViewport();
01280
01281 EQLOG( LOG_ASSEMBLY ) << "assembleImageDB, fixed function " << pvp
01282 << std::endl;
01283 EQASSERT( image->hasData( Frame::BUFFER_COLOR ));
01284 EQASSERT( image->hasData( Frame::BUFFER_DEPTH ));
01285
01286
01287 glRasterPos2i( op.offset.x() + pvp.x, op.offset.y() + pvp.y );
01288 glEnable( GL_STENCIL_TEST );
01289
01290
01291 glEnable( GL_DEPTH_TEST );
01292
01293 const bool pixelComposite = ( op.pixel != Pixel::ALL );
01294 if( pixelComposite )
01295 {
01296 glStencilFunc( GL_EQUAL, 1, 1 );
01297 glStencilOp( GL_KEEP, GL_ZERO, GL_REPLACE );
01298 }
01299 else
01300 {
01301 glStencilFunc( GL_ALWAYS, 1, 1 );
01302 glStencilOp( GL_ZERO, GL_ZERO, GL_REPLACE );
01303 }
01304
01305 _drawPixels( image, op, Frame::BUFFER_DEPTH );
01306
01307 glDisable( GL_DEPTH_TEST );
01308
01309
01310 glStencilFunc( GL_EQUAL, 1, 1 );
01311 glStencilOp( GL_KEEP, GL_ZERO, GL_ZERO );
01312
01313 _drawPixels( image, op, Frame::BUFFER_COLOR );
01314
01315 glDisable( GL_STENCIL_TEST );
01316 }
01317
01318 void Compositor::assembleImageDB_GLSL( const Image* image, const ImageOp& op )
01319 {
01320 const PixelViewport& pvp = image->getPixelViewport();
01321
01322 EQLOG( LOG_ASSEMBLY ) << "assembleImageDB, GLSL " << pvp
01323 << std::endl;
01324
01325 Channel* channel = op.channel;
01326 Window::ObjectManager* objects = channel->getObjectManager();
01327
01328 GLuint program = objects->getProgram( shaderDBKey );
01329
01330 if( program == Window::ObjectManager::INVALID )
01331 {
01332
01333
01334 const GLuint shader = objects->newShader( shaderDBKey,
01335 GL_FRAGMENT_SHADER );
01336 EQASSERT( shader != Window::ObjectManager::INVALID );
01337
01338 const char* source =
01339 "uniform sampler2DRect color; \
01340 uniform sampler2DRect depth; \
01341 void main(void){ \
01342 gl_FragColor = texture2DRect( color, gl_TexCoord[0].st ); \
01343 gl_FragDepth = texture2DRect( depth, gl_TexCoord[0].st ).x; }";
01344
01345 EQ_GL_CALL( glShaderSource( shader, 1, &source, 0 ));
01346 EQ_GL_CALL( glCompileShader( shader ));
01347
01348 GLint status;
01349 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
01350 if( !status )
01351 EQERROR << "Failed to compile fragment shader for DB compositing"
01352 << std::endl;
01353
01354 program = objects->newProgram( shaderDBKey );
01355
01356 EQ_GL_CALL( glAttachShader( program, shader ));
01357 EQ_GL_CALL( glLinkProgram( program ));
01358
01359 glGetProgramiv( program, GL_LINK_STATUS, &status );
01360 if( !status )
01361 {
01362 EQWARN << "Failed to link shader program for DB compositing"
01363 << std::endl;
01364 return;
01365 }
01366
01367
01368 EQ_GL_CALL( glUseProgram( program ));
01369
01370 const GLint depthParam = glGetUniformLocation( program, "depth" );
01371 glUniform1i( depthParam, 0 );
01372 const GLint colorParam = glGetUniformLocation( program, "color" );
01373 glUniform1i( colorParam, 1 );
01374 }
01375 else
01376 {
01377
01378 EQ_GL_CALL( glUseProgram( program ));
01379 }
01380
01381
01382 glEnable( GL_TEXTURE_RECTANGLE_ARB );
01383
01384 EQ_GL_CALL( glActiveTexture( GL_TEXTURE1 ));
01385 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
01386 GL_NEAREST );
01387 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
01388 GL_NEAREST );
01389
01390 const bool useImageTexture = image->getStorageType() == Frame::TYPE_TEXTURE;
01391 if( useImageTexture )
01392 image->getTexture( Frame::BUFFER_COLOR ).bind();
01393 else
01394 {
01395 util::Texture* texture = objects->obtainEqTexture( colorDBKey );
01396 texture->upload( image, Frame::BUFFER_COLOR );
01397 }
01398
01399 EQ_GL_CALL( glActiveTexture( GL_TEXTURE0 ));
01400 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
01401 GL_NEAREST );
01402 glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
01403 GL_NEAREST );
01404
01405 if( useImageTexture )
01406 image->getTexture( Frame::BUFFER_DEPTH ).bind();
01407 else
01408 {
01409 util::Texture* texture = objects->obtainEqTexture( depthDBKey );
01410 texture->upload( image, Frame::BUFFER_DEPTH );
01411 }
01412
01413
01414 glEnable( GL_DEPTH_TEST );
01415 glColor3f( 1.0f, 1.0f, 1.0f );
01416
01417 const float startX = static_cast< float >
01418 ( op.offset.x() + pvp.x * op.pixel.w + op.pixel.x );
01419 const float endX = static_cast< float >
01420 ( op.offset.x() + (pvp.x + pvp.w) * op.pixel.w + op.pixel.x );
01421 const float startY = static_cast< float >
01422 ( op.offset.y() + pvp.y * op.pixel.h + op.pixel.y );
01423 const float endY = static_cast< float >
01424 ( op.offset.y() + (pvp.y + pvp.h) * op.pixel.h + op.pixel.y );
01425
01426 const float w = static_cast< float >( pvp.w );
01427 const float h = static_cast< float >( pvp.h );
01428
01429 glBegin( GL_TRIANGLE_STRIP );
01430 glMultiTexCoord2f( GL_TEXTURE0, 0.0f, 0.0f );
01431 glMultiTexCoord2f( GL_TEXTURE1, 0.0f, 0.0f );
01432 glVertex3f( startX, startY, 0.0f );
01433
01434 glMultiTexCoord2f( GL_TEXTURE0, w, 0.0f );
01435 glMultiTexCoord2f( GL_TEXTURE1, w, 0.0f );
01436 glVertex3f( endX, startY, 0.0f );
01437
01438 glMultiTexCoord2f( GL_TEXTURE0, 0.0f, h );
01439 glMultiTexCoord2f( GL_TEXTURE1, 0.0f, h );
01440 glVertex3f( startX, endY, 0.0f );
01441
01442 glMultiTexCoord2f( GL_TEXTURE0, w, h );
01443 glMultiTexCoord2f( GL_TEXTURE1, w, h );
01444 glVertex3f( endX, endY, 0.0f );
01445
01446 glEnd();
01447
01448
01449 glDisable( GL_TEXTURE_RECTANGLE_ARB );
01450 glDisable( GL_DEPTH_TEST );
01451 EQ_GL_CALL( glUseProgram( 0 ));
01452 }
01453
01454
01455 }