void AccumBufferObject::_reset() { EQ_GL_CALL( glMatrixMode(GL_PROJECTION)); EQ_GL_CALL( glPopMatrix()); EQ_GL_CALL( glPopAttrib()); EQ_GL_CALL( glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, _previousFBO )); }
bool Window::configInitGL( const uint128_t& ) { const bool coreProfile = getIAttribute( WindowSettings::IATTR_HINT_CORE_PROFILE ) == ON; if( !coreProfile ) { EQ_GL_CALL( glEnable( GL_LIGHTING )); EQ_GL_CALL( glEnable( GL_LIGHT0 )); EQ_GL_CALL( glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )); EQ_GL_CALL( glEnable( GL_COLOR_MATERIAL )); } EQ_GL_CALL( glEnable( GL_SCISSOR_TEST )); // to constrain channel viewport EQ_GL_CALL( glEnable( GL_DEPTH_TEST )); EQ_GL_CALL( glDepthFunc( GL_LESS )); EQ_GL_CALL( glClearDepth( 1.f )); EQ_GL_CALL( glClear( GL_COLOR_BUFFER_BIT )); swapBuffers(); EQ_GL_CALL( glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )); return true; }
bool setup( const size_t newSize, const GLuint type ) { if( !GLEW_ARB_pixel_buffer_object ) { _setError( ERROR_PBO_UNSUPPORTED ); return false; } if( newSize == 0 ) { _setError( ERROR_PBO_SIZE_TOO_SMALL ); destroy(); return false; } if( pboID == 0 ) { EQ_GL_CALL( glGenBuffersARB( 1, &pboID )); } if( pboID == 0 ) { _setError( ERROR_PBO_NOT_INITIALIZED ); return false; } if( _type == type && size >= newSize ) { bind(); return true; } _type = type; size = newSize; bind(); switch( type ) { case GL_READ_ONLY_ARB: EQ_GL_CALL( glBufferDataARB( GL_PIXEL_PACK_BUFFER_ARB, newSize, 0, GL_STREAM_READ_ARB )); return true; case GL_WRITE_ONLY_ARB: EQ_GL_CALL( glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, newSize, 0, GL_STREAM_DRAW_ARB )); return true; default: _setError( ERROR_PBO_TYPE_UNSUPPORTED ); destroy(); return false; } }
void applyCamera() { ConstCameraSettingsPtr cameraSettings = getFrameData()->getCameraSettings( ); const Matrix4f& cameraRotation = cameraSettings->getCameraRotation( ); const Matrix4f& modelRotation = cameraSettings->getModelRotation( ); const Vector3f& cameraPosition = cameraSettings->getCameraPosition( ); EQ_GL_CALL( glMultMatrixf( cameraRotation.array ) ); EQ_GL_CALL( glTranslatef( cameraPosition[ 0 ], cameraPosition[ 1 ], cameraPosition[ 2 ] ) ); EQ_GL_CALL( glMultMatrixf( modelRotation.array ) ); }
void AccumBufferObject::accum( const GLfloat value ) { _texture->copyFromFrameBuffer( _texture->getInternalFormat(), _pvp ); const PixelViewport pvp( 0, 0, getWidth(), getHeight( )); _setup( pvp ); EQ_GL_CALL( glEnable( GL_BLEND )); EQ_GL_CALL( glBlendFunc( GL_ONE, GL_ONE )); _drawQuadWithTexture( _texture, pvp, value ); EQ_GL_CALL( glBlendFunc( GL_ONE, GL_ZERO )); EQ_GL_CALL( glDisable( GL_BLEND )); _reset(); }
void CompressorReadDrawPixels::download( const GLEWContext* glewContext, const eq_uint64_t inDims[4], const unsigned source, const eq_uint64_t flags, eq_uint64_t outDims[4], void** out ) { _init( inDims, outDims ); if( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER ) { EQ_GL_CALL( glReadPixels( inDims[0], inDims[2], inDims[1], inDims[3], _format, _type, _buffer.getData() ) ); } else { _initTexture( glewContext, flags ); _texture->setGLData( source, _internalFormat, inDims[1], inDims[3] ); _texture->setExternalFormat( _format, _type ); _texture->download( _buffer.getData( )); _texture->flushNoDelete(); } *out = _buffer.getData(); }
/** * Function for creating and holding of shared context. * Generation and uploading of new textures over some period with sleep time. */ void AsyncFetcher::run() { EQASSERT( !_sharedContextWindow ); _sharedContextWindow = initSharedContextWindow( _wnd ); _outQueue.push( TextureId( )); // unlock pipe thread if( !_sharedContextWindow ) return; _objectManager = new ObjectManager( glewGetContext( )); EQINFO << "async fetcher initialized: " << _wnd << std::endl; int i = 0; bool running = true; co::base::sleep( 1000 ); // imitate loading of the first texture while( running ) { // generate new texture eq::util::Texture* tx = _objectManager->newEqTexture( ++i, GL_TEXTURE_2D ); tx->init( GL_RGBA8, 64, 64 ); int j = 0; co::base::RNG rng; for( int y = 0; y < 64; ++y ) { for( int x = 0; x < 64; ++x ) { const GLbyte rnd = rng.get< uint8_t >() % 127; const GLbyte val = (x / 8) % 2 == (y / 8) % 2 ? rnd : 0; _tmpTexture[ j++ ] = val; _tmpTexture[ j++ ] = val; _tmpTexture[ j++ ] = val; _tmpTexture[ j++ ] = val; } } tx->upload( 64, 64, _tmpTexture ); EQ_GL_CALL( glFinish( )); // add new texture to the pool _outQueue.push( TextureId( tx->getName( ), i )); // imitate hard work of loading something else co::base::sleep( rng.get< uint32_t >() % 5000u ); // clean unused textures int keyToDelete = 0; while( _inQueue.tryPop( keyToDelete )) { if( keyToDelete ) { EQWARN << "Deleting eq texture " << keyToDelete << std::endl; _objectManager->deleteEqTexture( keyToDelete ); } else running = false; } } deleteSharedContextWindow( _wnd, &_sharedContextWindow, &_objectManager ); }
bool bind() const { if( !_testInitialized( )) return false; EQ_GL_CALL( glBindBufferARB( _getName(), pboID )); return true; }
/** * Function for creating and holding of shared context. * Generation and uploading of new textures over some period with sleep time. */ void AsyncFetcher::run() { LBASSERT( _sharedWindow ); if( !_sharedWindow ) return; _sharedWindow->makeCurrent(); eq::util::ObjectManager objects( glewGetContext( )); lunchbox::Bufferb textureData( 64*64*4 ); LBINFO << "async fetcher initialized" << std::endl; bool running = true; lunchbox::sleep( 1000 ); // imitate loading of the first texture for( uint8_t* i = 0; running; ++i ) { // generate new texture eq::util::Texture* tx = objects.newEqTexture( i, GL_TEXTURE_2D ); tx->init( GL_RGBA8, 64, 64 ); int j = 0; lunchbox::RNG rng; for( int y = 0; y < 64; ++y ) { for( int x = 0; x < 64; ++x ) { const GLbyte rnd = rng.get< uint8_t >() % 127; const GLbyte val = (x / 8) % 2 == (y / 8) % 2 ? rnd : 0; textureData[ j++ ] = val; textureData[ j++ ] = val; textureData[ j++ ] = val; textureData[ j++ ] = val; } } tx->upload( 64, 64, textureData.getData( )); EQ_GL_CALL( glFinish( )); // add new texture to the pool _outQueue.push( TextureId( tx->getName(), i )); // imitate hard work of loading something else lunchbox::sleep( rng.get< uint32_t >() % 5000u ); // clean unused textures const void* keyToDelete = 0; while( _inQueue.tryPop( keyToDelete )) { if( keyToDelete ) { LBWARN << "Deleting eq texture " << keyToDelete << std::endl; objects.deleteEqTexture( keyToDelete ); } else running = false; } } objects.deleteAll(); }
void Texture::_generate() { LB_TS_THREAD( _thread ); if( _impl->name != 0 ) return; _impl->defined = false; EQ_GL_CALL( glGenTextures( 1, &_impl->name )); }
void ObjectManager::deleteShader( const void* key ) { ObjectHash::iterator i = _impl->shaders.find( key ); if( i == _impl->shaders.end() ) return; const Object& object = i->second; EQ_GL_CALL( glDeleteShader( object.id )); _impl->shaders.erase( i ); }
void ObjectManager::deleteList( const void* key ) { ObjectHash::iterator i = _impl->lists.find( key ); if( i == _impl->lists.end( )) return; const Object& object = i->second; EQ_GL_CALL( glDeleteLists( object.id, object.num )); _impl->lists.erase( i ); }
void CompressorReadDrawPixels::startDownload( const GLEWContext* glewContext, const eq_uint64_t dims[4], const unsigned source, const eq_uint64_t flags ) { const eq_uint64_t size = dims[1] * dims[3] * _depth; if( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER ) { #ifdef EQ_ASYNC_PBO if( _initPBO( glewContext, size )) { EQ_GL_CALL( glReadPixels( dims[0], dims[2], dims[1], dims[3], _format, _type, 0 )); _pbo->unbind(); glFlush(); // Fixes https://github.com/Eyescale/Equalizer/issues/118 return; } #else // async RB through texture const PixelViewport pvp( dims[0], dims[2], dims[1], dims[3] ); _initAsyncTexture( glewContext, pvp.w, pvp.h ); _asyncTexture->setExternalFormat( _format, _type ); _asyncTexture->copyFromFrameBuffer( _internalFormat, pvp ); return; #endif // else LBWARN << "Can't initialize PBO for async readback" << std::endl; _resizeBuffer( size ); EQ_GL_CALL( glReadPixels( dims[0], dims[2], dims[1], dims[3], _format, _type, _buffer.getData( ))); } else { // TODO: fix Texture class for async texture download _resizeBuffer( size ); _initTexture( glewContext, flags ); _texture->setGLData( source, _internalFormat, dims[1], dims[3] ); _texture->setExternalFormat( _format, _type ); _texture->download( _buffer.getData( )); _texture->flushNoDelete(); } }
void Channel::_drawOverlay() { // Draw the overlay logo const Window* window = static_cast<Window*>( getWindow( )); const eq::util::Texture* texture = window->getLogoTexture(); if( !texture ) return; applyOverlayState(); EQ_GL_CALL( glDisable( GL_COLOR_LOGIC_OP )); EQ_GL_CALL( glPolygonMode( GL_FRONT_AND_BACK, GL_FILL )); // logo EQ_GL_CALL( glEnable( GL_BLEND )); EQ_GL_CALL( glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )); const GLenum target = texture->getTarget(); EQ_GL_CALL( glEnable( target )); texture->bind(); EQ_GL_CALL( glTexParameteri( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR )); EQ_GL_CALL( glTexParameteri( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR )); const float tWidth = float( texture->getWidth( )); const float tHeight = float( texture->getHeight( )); const float width = target == GL_TEXTURE_2D ? 1.0f : tWidth; const float height = target == GL_TEXTURE_2D ? 1.0f : tHeight; glBegin( GL_QUADS ); { glTexCoord2f( 0, 0 ); glVertex3f( 5.0f, 5.0f, 0.0f ); glTexCoord2f( width, 0 ); glVertex3f( tWidth + 5.0f, 5.0f, 0.0f ); glTexCoord2f( width, height ); glVertex3f( tWidth + 5.0f, tHeight + 5.0f, 0.0f ); glTexCoord2f( 0, height ); glVertex3f( 5.0f, tHeight + 5.0f, 0.0f ); } glEnd(); EQ_GL_CALL( glDisable( target )); EQ_GL_CALL( glDisable( GL_BLEND )); resetOverlayState(); }
void ObjectManager::deleteVertexArray( const void* key ) { ObjectHash::iterator i = _impl->vertexArrays.find( key ); if( i == _impl->vertexArrays.end( )) return; const Object& object = i->second; EQ_GL_CALL( glDeleteVertexArrays( 1, &object.id )); _impl->vertexArrays.erase( i ); }
bool eqHello::Renderer::_loadShaders() { seq::ObjectManager& om = getObjectManager(); if (_program) return true; _program = om.newProgram(&_program); if (!seq::linkProgram(om.glewGetContext(), _program, vertexShader_glsl, fragmentShader_glsl)) { return false; } EQ_GL_CALL(glUseProgram(_program)); _matrixUniform = glGetUniformLocation(_program, "MVP"); EQ_GL_CALL(glUseProgram(0)); return true; }
void AccumBufferObject::_setup( const PixelViewport& pvp ) { EQ_GL_CALL( glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &_previousFBO )); bind(); EQ_GL_CALL( glPushAttrib( GL_SCISSOR_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT )); EQ_GL_CALL( glMatrixMode(GL_PROJECTION)); EQ_GL_CALL( glPushMatrix()); EQ_GL_CALL( glLoadIdentity()); EQ_GL_CALL( glOrtho(0, pvp.w, 0, pvp.h, -1, 1)); EQ_GL_CALL( glScissor(0, 0, pvp.w, pvp.h)); EQ_GL_CALL( glViewport(0, 0, pvp.w, pvp.h)); }
void Window::swapBuffers() { const Pipe* pipe = static_cast<Pipe*>( getPipe( )); const FrameData& frameData = pipe->getFrameData(); const eq::Channels& channels = getChannels(); if( frameData.useStatistics() && !channels.empty( )) EQ_GL_CALL( channels.back()->drawStatistics( )); eq::Window::swapBuffers(); }
void destroy() { if( pboID != 0 ) { unbind(); EQ_GL_CALL( glDeleteBuffersARB( 1, &pboID )); } pboID = 0; size = 0; _type = 0; }
void Channel::frameDraw( const eq::uint128_t& ) { // Setup frustum EQ_GL_CALL( applyBuffer( )); EQ_GL_CALL( applyViewport( )); EQ_GL_CALL( glMatrixMode( GL_PROJECTION )); EQ_GL_CALL( glLoadIdentity( )); EQ_GL_CALL( applyFrustum( )); EQ_GL_CALL( glMatrixMode( GL_MODELVIEW )); EQ_GL_CALL( glLoadIdentity( )); // Setup lights before applying head transform, so the light will be // consistent in the cave const FrameData& frameData = _getFrameData(); const eq::Matrix4f& rotation = frameData.getRotation(); const eq::Vector3f& translation = frameData.getTranslation(); eq::Matrix4f invRotationM; rotation.inverse( invRotationM ); setLights( invRotationM ); EQ_GL_CALL( applyHeadTransform( )); glTranslatef( translation.x(), translation.y(), translation.z() ); glMultMatrixf( rotation.array ); Pipe* pipe = static_cast<Pipe*>( getPipe( )); Renderer* renderer = pipe->getRenderer(); LBASSERT( renderer ); const eq::Matrix4f& modelview = _computeModelView(); // set fancy data colors const eq::Vector4f taintColor = _getTaintColor( frameData.getColorMode(), getUniqueColor( )); const int normalsQuality = _getFrameData().getNormalsQuality(); const eq::Range& range = getRange(); renderer->render( range, modelview, invRotationM, taintColor, normalsQuality ); checkError( "error during rendering " ); _drawRange = range; #ifndef NDEBUG outlineViewport(); #endif }
void GPUAsyncLoader::cleanup() { _decompressor.reset(); if( _storageTexture3D ) { EQ_GL_CALL( glDeleteTextures( 1, &_storageTexture3D )); _storageTexture3D = 0; } if( _pbo ) _pbo->destroy(); }
void GLWindow::updateFrameBuffer() const { if( !_impl->glewContext || !_impl->fboMultiSample ) return; _impl->fboMultiSample->bind( GL_READ_FRAMEBUFFER_EXT ); _impl->fbo->bind( GL_DRAW_FRAMEBUFFER_EXT ); const PixelViewport& pvp = getPixelViewport(); EQ_GL_CALL( glBlitFramebuffer( 0, 0, pvp.w, pvp.h, 0, 0, pvp.w, pvp.h, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST )); }
void Texture::resize( const int32_t width, const int32_t height ) { LB_TS_THREAD( _thread ); LBASSERT( _impl->name ); LBASSERT( _impl->internalFormat ); LBASSERT( width > 0 && height > 0 ); if( _impl->width == width && _impl->height == height && _impl->defined ) return; if( _impl->target == GL_TEXTURE_2D && !_isPOT( width, height )) { LBASSERT( _impl->glewContext ); LBASSERT( GLEW_ARB_texture_non_power_of_two ); } EQ_GL_CALL( glBindTexture( _impl->target, _impl->name )); EQ_GL_CALL( glTexImage2D( _impl->target, 0, _impl->internalFormat, width, height, 0, _impl->format, _impl->type, 0 )); _impl->width = width; _impl->height = height; _impl->defined = true; }
void Channel::frameDraw( const eq::uint128_t& frameID ) { // Setup frustum EQ_GL_CALL( applyBuffer( )); EQ_GL_CALL( applyViewport( )); EQ_GL_CALL( glMatrixMode( GL_PROJECTION )); EQ_GL_CALL( glLoadIdentity( )); EQ_GL_CALL( applyFrustum( )); EQ_GL_CALL( glMatrixMode( GL_MODELVIEW )); EQ_GL_CALL( glLoadIdentity( )); // Setup lights before applying head transform, so the light will be // consistent in the cave const FrameData& frameData = _getFrameData(); const eq::Matrix4f& rotation = frameData.getRotation(); const eq::Vector3f& translation = frameData.getTranslation(); eq::Matrix4f invRotationM; rotation.inverse( invRotationM ); setLights( invRotationM ); EQ_GL_CALL( applyHeadTransform( )); glTranslatef( translation.x(), translation.y(), translation.z() ); glMultMatrixf( rotation.array ); Pipe* pipe = static_cast<Pipe*>( getPipe( )); Renderer* renderer = pipe->getRenderer(); EQASSERT( renderer ); eq::Matrix4f modelviewM; // modelview matrix eq::Matrix3f modelviewITM; // modelview inversed transposed matrix _calcMVandITMV( modelviewM, modelviewITM ); const eq::Range& range = getRange(); renderer->render( range, modelviewM, modelviewITM, invRotationM ); checkError( "error during rendering " ); _drawRange = range; #ifndef NDEBUG outlineViewport(); #endif }
void* mapWrite() { if( !_testInitialized( )) return 0; if( _type != GL_WRITE_ONLY_ARB ) { _setError( ERROR_PBO_READ_ONLY ); return 0; } bind(); // cancel all draw operations on this buffer to prevent stalling EQ_GL_CALL( glBufferDataARB( GL_PIXEL_UNPACK_BUFFER_ARB, size, 0, GL_STREAM_DRAW_ARB )); return glMapBufferARB( GL_PIXEL_UNPACK_BUFFER_ARB, _type ); }
GLuint ObjectManager::newVertexArray( const void* key ) { if( _impl->vertexArrays.find( key ) != _impl->vertexArrays.end( )) { LBWARN << "Requested new vertex array for existing key" << std::endl; return INVALID; } GLuint id = INVALID; EQ_GL_CALL( glGenVertexArrays( 1, &id )); if( !id ) { LBWARN << "glGenVertexArrays failed: " << glGetError() << std::endl; return INVALID; } Object& object = _impl->vertexArrays[ key ]; object.id = id; return id; }
void AccumBufferObject::_drawQuadWithTexture( Texture* texture, const PixelViewport& pvp, const GLfloat value ) { texture->bind(); EQ_GL_CALL( glDepthMask( false )); EQ_GL_CALL( glDisable( GL_LIGHTING )); EQ_GL_CALL( glEnable( GL_TEXTURE_RECTANGLE_ARB )); EQ_GL_CALL( glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE )); texture->applyWrap(); texture->applyZoomFilter( FILTER_NEAREST ); EQ_GL_CALL( glColor4f( value, value, value, value )); const float startX = static_cast< float >( pvp.x ); const float endX = static_cast< float >( pvp.x + pvp.w ); const float startY = static_cast< float >( pvp.y ); const float endY = static_cast< float >( pvp.y + pvp.h ); glBegin( GL_QUADS ); glTexCoord2f( 0.0f, 0.0f ); glVertex3f( startX, startY, 0.0f ); glTexCoord2f( static_cast< float >( pvp.w ), 0.0f ); glVertex3f( endX, startY, 0.0f ); glTexCoord2f( static_cast<float>( pvp.w ), static_cast<float>( pvp.h )); glVertex3f( endX, endY, 0.0f ); glTexCoord2f( 0.0f, static_cast< float >( pvp.h )); glVertex3f( startX, endY, 0.0f ); glEnd(); // restore state EQ_GL_CALL( glDisable( GL_TEXTURE_RECTANGLE_ARB )); EQ_GL_CALL( glDepthMask( true )); }
void GLWindow::queryDrawableConfig( DrawableConfig& dc ) { dc = DrawableConfig(); // GL version const char* glVersion = (const char*)glGetString( GL_VERSION ); if( !glVersion ) // most likely no context { LBWARN << "glGetString(GL_VERSION) returned 0, assuming GL version 1.1" << std::endl; dc.glVersion = 1.1f; } else dc.glVersion = static_cast<float>( std::atof( glVersion )); if( dc.glVersion >= 3.2f ) { GLint mask; EQ_GL_CALL( glGetIntegerv( GL_CONTEXT_PROFILE_MASK, &mask )); dc.coreProfile = mask & GL_CONTEXT_CORE_PROFILE_BIT; } TEST_GLEW_VERSION( 1, 1 ); TEST_GLEW_VERSION( 1, 2 ); TEST_GLEW_VERSION( 1, 3 ); TEST_GLEW_VERSION( 1, 4 ); TEST_GLEW_VERSION( 1, 5 ); TEST_GLEW_VERSION( 2, 0 ); TEST_GLEW_VERSION( 2, 1 ); TEST_GLEW_VERSION( 3, 0 ); TEST_GLEW_VERSION( 3, 1 ); TEST_GLEW_VERSION( 3, 2 ); TEST_GLEW_VERSION( 3, 3 ); TEST_GLEW_VERSION( 4, 0 ); TEST_GLEW_VERSION( 4, 1 ); TEST_GLEW_VERSION( 4, 2 ); TEST_GLEW_VERSION( 4, 3 ); #ifdef GLEW_VERSION_4_5 TEST_GLEW_VERSION( 4, 4 ); TEST_GLEW_VERSION( 4, 5 ); #endif // Framebuffer capabilities GLboolean result; EQ_GL_CALL( glGetBooleanv( GL_STEREO, &result )); dc.stereo = result; EQ_GL_CALL( glGetBooleanv( GL_DOUBLEBUFFER, &result )); dc.doublebuffered = result; if( dc.coreProfile ) { if( getFrameBufferObject( )) { glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &dc.stencilBits ); // eat GL error if no stencil attachment; should return '0' bits // according to spec, but gives GL_INVALID_OPERATION glGetError(); EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &dc.colorBits )); EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &dc.alphaBits )); } else { EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &dc.stencilBits )); EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &dc.colorBits )); EQ_GL_CALL( glGetFramebufferAttachmentParameteriv( GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &dc.alphaBits )); } } else { EQ_GL_CALL( glGetIntegerv( GL_STENCIL_BITS, &dc.stencilBits )); EQ_GL_CALL( glGetIntegerv( GL_RED_BITS, &dc.colorBits )); EQ_GL_CALL( glGetIntegerv( GL_ALPHA_BITS, &dc.alphaBits )); EQ_GL_CALL( glGetIntegerv( GL_ACCUM_RED_BITS, &dc.accumBits )); } dc.accumBits *= 4; LBDEBUG << "Window drawable config: " << dc << std::endl; }
void ROIFinder::_readbackInfo( util::ObjectManager& glObjects ) { LBASSERT( glObjects.supportsEqTexture( )); LBASSERT( glObjects.supportsEqFrameBufferObject( )); PixelViewport pvp = _pvp; pvp.apply( Zoom( GRID_SIZE, GRID_SIZE )); pvp.w = LB_MIN( pvp.w+pvp.x, _pvpOriginal.w+_pvpOriginal.x ) - pvp.x; pvp.h = LB_MIN( pvp.h+pvp.y, _pvpOriginal.h+_pvpOriginal.y ) - pvp.y; LBASSERT( pvp.isValid()); // copy frame buffer to texture const void* bufferKey = _getInfoKey( ); util::Texture* texture = glObjects.obtainEqTexture( bufferKey, GL_TEXTURE_RECTANGLE_ARB ); #ifdef EQ_ROI_USE_DEPTH_TEXTURE texture->copyFromFrameBuffer( GL_DEPTH_COMPONENT, pvp ); #else texture->copyFromFrameBuffer( GL_RGBA, pvp ); #endif // draw zoomed quad into FBO const void* fboKey = _getInfoKey( ); util::FrameBufferObject* fbo = glObjects.getEqFrameBufferObject( fboKey ); if( fbo ) { LBCHECK( fbo->resize( _pvp.w, _pvp.h )); } else { fbo = glObjects.newEqFrameBufferObject( fboKey ); LBCHECK( fbo->init( _pvp.w, _pvp.h, GL_RGBA32F, 0, 0 )); } fbo->bind(); texture->bind(); // Enable & download depth texture glEnable( GL_TEXTURE_RECTANGLE_ARB ); texture->applyWrap(); texture->applyZoomFilter( FILTER_LINEAR ); // Enable shaders GLuint program = glObjects.getProgram( shaderRBInfo ); if( program == util::ObjectManager::INVALID ) { // Create fragment shader which reads depth values from // rectangular textures const GLuint shader = glObjects.newShader( shaderRBInfo, GL_FRAGMENT_SHADER ); LBASSERT( shader != util::ObjectManager::INVALID ); #ifdef EQ_ROI_USE_DEPTH_TEXTURE const GLchar* fShaderPtr = roiFragmentShader_glsl.c_str(); #else const GLchar* fShaderPtr = roiFragmentShaderRGB_glsl.c_str(); #endif EQ_GL_CALL( glShaderSource( shader, 1, &fShaderPtr, 0 )); EQ_GL_CALL( glCompileShader( shader )); GLint status; glGetShaderiv( shader, GL_COMPILE_STATUS, &status ); if( !status ) LBERROR << "Failed to compile fragment shader for ROI finder" << std::endl; program = glObjects.newProgram( shaderRBInfo ); EQ_GL_CALL( glAttachShader( program, shader )); EQ_GL_CALL( glLinkProgram( program )); glGetProgramiv( program, GL_LINK_STATUS, &status ); if( !status ) { LBWARN << "Failed to link shader program for ROI finder" << std::endl; return; } // use fragment shader and setup uniforms EQ_GL_CALL( glUseProgram( program )); GLint param = glGetUniformLocation( program, "texture" ); glUniform1i( param, 0 ); } else { // use fragment shader EQ_GL_CALL( glUseProgram( program )); } // Draw Quad glDisable( GL_LIGHTING ); glColor3f( 1.0f, 1.0f, 1.0f ); glBegin( GL_QUADS ); glVertex3i( 0, 0, 0 ); glVertex3i( _pvp.w, 0, 0 ); glVertex3i( _pvp.w, _pvp.h, 0 ); glVertex3i( 0, _pvp.h, 0 ); glEnd(); // restore state glDisable( GL_TEXTURE_RECTANGLE_ARB ); EQ_GL_CALL( glUseProgram( 0 )); fbo->unbind(); // finish readback of info LBASSERT( static_cast<int32_t>(_perBlockInfo.size()) >= _pvp.w*_pvp.h*4 ); texture = fbo->getColorTextures()[0]; LBASSERT( texture->getFormat() == GL_RGBA ); LBASSERT( texture->getType() == GL_FLOAT ); texture->download( &_perBlockInfo[0] ); }
void FrameBufferObject::unbind() { EQ_GL_CALL( glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 )); }