LCOV - code coverage report
Current view: top level - eq/util - texture.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 72 215 33.5 %
Date: 2014-06-18 Functions: 14 37 37.8 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2014, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                    2010, Cedric Stalder <cedric.stalder@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #include "texture.h"
      20             : 
      21             : #include <eq/fabric/pixelViewport.h>
      22             : 
      23             : #include <eq/client/image.h>
      24             : #include <eq/client/gl.h>
      25             : #include <lunchbox/plugins/compressor.h>
      26             : 
      27             : namespace eq
      28             : {
      29             : namespace util
      30             : {
      31             : namespace detail
      32             : {
      33             : class Texture
      34             : {
      35             : public:
      36        1700 :     Texture( const GLenum tgt, const GLEWContext* const gl )
      37             :         : name( 0 )
      38             :         , target( tgt )
      39             :         , internalFormat( 0 )
      40             :         , format( 0 )
      41             :         , type( 0 )
      42             :         , width( 0 )
      43             :         , height( 0 )
      44             :         , defined( false )
      45        1700 :         , glewContext( gl )
      46        1700 :         {}
      47             : 
      48          80 :     ~Texture()
      49             :     {
      50          80 :         if( name != 0 )
      51           0 :             LBWARN << "OpenGL texture " << name << " not freed" << std::endl;
      52             : 
      53          80 :         name = 0;
      54          80 :         defined = false;
      55          80 :     }
      56             : 
      57             :     GLuint name;
      58             :     const GLenum target;
      59             :     GLuint internalFormat;
      60             :     GLuint format;
      61             :     GLuint type;
      62             :     int32_t width;
      63             :     int32_t height;
      64             :     bool defined;
      65             :     const GLEWContext* glewContext;
      66             : };
      67             : }
      68             : 
      69        1700 : Texture::Texture( const unsigned target, const GLEWContext* const glewContext )
      70        1700 :     : _impl( new detail::Texture( target, glewContext ))
      71        1700 : {}
      72             : 
      73         173 : Texture::~Texture()
      74             : {
      75          80 :     delete _impl;
      76          93 : }
      77           0 : bool Texture::isValid() const
      78             : {
      79           0 :     return ( _impl->name != 0 && _impl->defined );
      80             : }
      81             : 
      82          74 : void Texture::flush()
      83             : {
      84          74 :     if( _impl->name == 0 )
      85         122 :         return;
      86             : 
      87          26 :     LB_TS_THREAD( _thread );
      88          26 :     glDeleteTextures( 1, &_impl->name );
      89          26 :     _impl->name = 0;
      90          26 :     _impl->defined = false;
      91             : }
      92             : 
      93           0 : void Texture::flushNoDelete()
      94             : {
      95           0 :     LB_TS_THREAD( _thread );
      96           0 :     _impl->name = 0;
      97           0 :     _impl->defined = false;
      98           0 : }
      99             : 
     100           0 : uint32_t Texture::getCompressorTarget() const
     101             : {
     102           0 :     switch( _impl->target )
     103             :     {
     104             :         case GL_TEXTURE_RECTANGLE_ARB:
     105           0 :             return EQ_COMPRESSOR_USE_TEXTURE_RECT;
     106             : 
     107             :         default:
     108           0 :             LBUNIMPLEMENTED;
     109             :         case GL_TEXTURE_2D:
     110           0 :             return EQ_COMPRESSOR_USE_TEXTURE_2D;
     111             :     }
     112             : }
     113             : 
     114          26 : void Texture::_setInternalFormat( const GLuint internalFormat )
     115             : {
     116          26 :     if( _impl->internalFormat == internalFormat )
     117          26 :         return;
     118             : 
     119          26 :     _impl->defined = false;
     120          26 :     _impl->internalFormat = internalFormat;
     121             : 
     122          26 :     switch( internalFormat )
     123             :     {
     124             :         // depth format
     125             :         case GL_DEPTH_COMPONENT:
     126           0 :             setExternalFormat( GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
     127           0 :             break;
     128             :         case GL_RGB10_A2:
     129           0 :             setExternalFormat( GL_RGBA, GL_UNSIGNED_INT_10_10_10_2 );
     130           0 :             break;
     131             :         case GL_RGBA:
     132             :         case GL_RGBA8:
     133          13 :             setExternalFormat( GL_RGBA, GL_UNSIGNED_BYTE );
     134          13 :             break;
     135             :         case GL_RGBA16F:
     136           0 :             setExternalFormat( GL_RGBA, GL_HALF_FLOAT );
     137           0 :             break;
     138             :         case GL_RGBA32F:
     139           0 :             setExternalFormat( GL_RGBA, GL_FLOAT );
     140           0 :             break;
     141             :         case GL_RGB:
     142             :         case GL_RGB8:
     143           0 :             setExternalFormat( GL_RGB, GL_UNSIGNED_BYTE );
     144           0 :             break;
     145             :         case GL_RGB16F:
     146           0 :             setExternalFormat( GL_RGB, GL_HALF_FLOAT );
     147           0 :             break;
     148             :         case GL_RGB32F:
     149           0 :             setExternalFormat( GL_RGB, GL_FLOAT );
     150           0 :             break;
     151             :         case GL_ALPHA32F_ARB:
     152           0 :             setExternalFormat( GL_ALPHA, GL_FLOAT );
     153           0 :             break;
     154             :         case GL_DEPTH24_STENCIL8:
     155          13 :             setExternalFormat( GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
     156          13 :             break;
     157             :         case GL_RGBA32UI:
     158           0 :             LBASSERT( _impl->glewContext );
     159           0 :             if( GLEW_EXT_texture_integer )
     160           0 :                 setExternalFormat( GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT );
     161             :             else
     162           0 :                 LBUNIMPLEMENTED;
     163           0 :             break;
     164             : 
     165             :         default:
     166           0 :             LBUNIMPLEMENTED;
     167           0 :             setExternalFormat( internalFormat, GL_UNSIGNED_BYTE );
     168             :     }
     169             : }
     170             : 
     171          26 : void Texture::setExternalFormat( const uint32_t format, const uint32_t type )
     172             : {
     173          26 :      _impl->format = format;
     174          26 :      _impl->type   = type;
     175          26 : }
     176             : 
     177          52 : void Texture::_generate()
     178             : {
     179          52 :     LB_TS_THREAD( _thread );
     180          52 :     if( _impl->name != 0 )
     181          78 :         return;
     182             : 
     183          26 :     _impl->defined = false;
     184          26 :     EQ_GL_CALL( glGenTextures( 1, &_impl->name ));
     185             : }
     186             : 
     187          26 : void Texture::init( const GLuint format, const int32_t width,
     188             :                     const int32_t height )
     189             : {
     190          26 :     _generate();
     191          26 :     _setInternalFormat( format );
     192          26 :     resize( width, height );
     193          26 : }
     194             : 
     195           0 : void Texture::setGLData( const GLuint id, const GLuint internalFormat,
     196             :                          const int32_t width, const int32_t height )
     197             : {
     198           0 :     flush();
     199           0 :     _setInternalFormat( internalFormat );
     200           0 :     _impl->name = id;
     201           0 :     _impl->width = width;
     202           0 :     _impl->height = height;
     203           0 :     _impl->defined = true;
     204           0 : }
     205             : 
     206             : namespace
     207             : {
     208             : /* Check if the texture dimensions are power of two. */
     209           0 : static bool _isPOT( const uint32_t width, const uint32_t height )
     210             : {
     211           0 :     return ( width > 0 && height > 0 &&
     212           0 :            ( width & ( width - 1 )) == 0 &&
     213           0 :            ( height & ( height - 1 )) == 0 );
     214             : }
     215             : }
     216             : 
     217           0 : void Texture::_grow( const int32_t width, const int32_t height )
     218             : {
     219           0 :     if( _impl->width < width )
     220             :     {
     221           0 :         _impl->width   = width;
     222           0 :         _impl->defined = false;
     223             :     }
     224             : 
     225           0 :     if( _impl->height < height )
     226             :     {
     227           0 :         _impl->height  = height;
     228           0 :         _impl->defined = false;
     229             :     }
     230           0 : }
     231             : 
     232           0 : void Texture::applyZoomFilter( const ZoomFilter zoomFilter ) const
     233             : {
     234           0 :     glTexParameteri( _impl->target, GL_TEXTURE_MAG_FILTER, zoomFilter );
     235           0 :     glTexParameteri( _impl->target, GL_TEXTURE_MIN_FILTER, zoomFilter );
     236           0 : }
     237             : 
     238           0 : void Texture::applyWrap() const
     239             : {
     240           0 :     glTexParameteri( _impl->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
     241           0 :     glTexParameteri( _impl->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
     242           0 : }
     243             : 
     244           0 : void Texture::copyFromFrameBuffer( const GLuint internalFormat,
     245             :                                    const fabric::PixelViewport& pvp )
     246             : {
     247           0 :     EQ_GL_ERROR( "before Texture::copyFromFrameBuffer" );
     248           0 :     LB_TS_THREAD( _thread );
     249             : 
     250           0 :     _generate();
     251           0 :     _setInternalFormat( internalFormat );
     252           0 :     _grow( pvp.w, pvp.h );
     253             : 
     254           0 :     if( _impl->defined )
     255           0 :         glBindTexture( _impl->target, _impl->name );
     256             :     else
     257           0 :         resize( _impl->width, _impl->height );
     258             : 
     259           0 :     glCopyTexSubImage2D( _impl->target, 0, 0, 0, pvp.x, pvp.y, pvp.w, pvp.h );
     260           0 :     EQ_GL_ERROR( "after Texture::copyFromFrameBuffer" );
     261           0 : }
     262             : 
     263           0 : void Texture::upload( const int32_t width, const int32_t height,
     264             :                       const void* ptr )
     265             : {
     266           0 :     _generate();
     267           0 :     _grow( width, height );
     268             : 
     269           0 :     if( _impl->defined )
     270           0 :         glBindTexture( _impl->target, _impl->name );
     271             :     else
     272           0 :         resize( _impl->width, _impl->height );
     273             : 
     274             :     glTexSubImage2D( _impl->target, 0, 0, 0, width, height,
     275           0 :                      _impl->format, _impl->type, ptr );
     276           0 : }
     277             : 
     278           0 : void Texture::download( void* buffer ) const
     279             : {
     280           0 :     LB_TS_THREAD( _thread );
     281           0 :     LBASSERT( isValid( ));
     282           0 :     glBindTexture( _impl->target, _impl->name );
     283           0 :     glGetTexImage( _impl->target, 0, _impl->format, _impl->type, buffer );
     284           0 : }
     285             : 
     286           0 : void Texture::bind() const
     287             : {
     288           0 :     LBASSERT( _impl->name );
     289           0 :     glBindTexture( _impl->target, _impl->name );
     290           0 : }
     291             : 
     292          26 : void Texture::bindToFBO( const GLenum target, const int32_t width,
     293             :                          const int32_t height )
     294             : {
     295          26 :     LB_TS_THREAD( _thread );
     296          26 :     LBASSERT( _impl->internalFormat );
     297          26 :     LBASSERT( _impl->glewContext );
     298             : 
     299          26 :     _generate();
     300             : 
     301          26 :     glBindTexture( _impl->target, _impl->name );
     302             :     glTexImage2D( _impl->target, 0, _impl->internalFormat, width, height, 0,
     303          26 :                   _impl->format, _impl->type, 0 );
     304             :     glFramebufferTexture2DEXT( GL_FRAMEBUFFER, target, _impl->target,
     305          26 :                                _impl->name, 0 );
     306             : 
     307          26 :     _impl->width = width;
     308          26 :     _impl->height = height;
     309          26 :     _impl->defined = true;
     310          26 : }
     311             : 
     312          26 : void Texture::resize( const int32_t width, const int32_t height )
     313             : {
     314          26 :     LB_TS_THREAD( _thread );
     315          26 :     LBASSERT( _impl->name );
     316          26 :     LBASSERT( _impl->internalFormat );
     317          26 :     LBASSERT( width > 0 && height > 0 );
     318             : 
     319          26 :     if( _impl->width == width && _impl->height == height && _impl->defined )
     320          26 :         return;
     321             : 
     322          26 :     if( _impl->target == GL_TEXTURE_2D && !_isPOT( width, height ))
     323             :     {
     324           0 :         LBASSERT( _impl->glewContext );
     325           0 :         LBASSERT( GLEW_ARB_texture_non_power_of_two );
     326             :     }
     327             : 
     328          26 :     EQ_GL_CALL( glBindTexture( _impl->target, _impl->name ));
     329          26 :     EQ_GL_CALL( glTexImage2D( _impl->target, 0, _impl->internalFormat, width,
     330             :                               height, 0, _impl->format, _impl->type, 0 ));
     331          26 :     _impl->width  = width;
     332          26 :     _impl->height = height;
     333          26 :     _impl->defined = true;
     334             : }
     335             : 
     336           0 : void Texture::writeRGB( const std::string& filename ) const
     337             : {
     338           0 :     LBASSERT( _impl->defined );
     339           0 :     if( !_impl->defined )
     340           0 :         return;
     341             : 
     342           0 :     eq::Image image;
     343             : 
     344           0 :     switch( _impl->internalFormat )
     345             :     {
     346             :         case GL_DEPTH_COMPONENT:
     347             :             image.allocDownloader( Frame::BUFFER_COLOR,
     348             :                              EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
     349           0 :                                    _impl->glewContext );
     350           0 :             break;
     351             :         case GL_RGB10_A2:
     352             :             image.allocDownloader( Frame::BUFFER_COLOR,
     353             :                                    EQ_COMPRESSOR_TRANSFER_RGB10_A2_TO_BGR10_A2,
     354           0 :                                    _impl->glewContext );
     355           0 :             break;
     356             :         case GL_RGBA:
     357             :         case GL_RGBA8:
     358             :             image.allocDownloader( Frame::BUFFER_COLOR,
     359             :                                    EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGRA,
     360           0 :                                    _impl->glewContext );
     361           0 :             break;
     362             :         case GL_RGBA16F:
     363             :             image.allocDownloader( Frame::BUFFER_COLOR,
     364             :                                    EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_BGRA16F,
     365           0 :                                    _impl->glewContext );
     366           0 :             break;
     367             :         case GL_RGBA32F:
     368             :             image.allocDownloader( Frame::BUFFER_COLOR,
     369             :                                    EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGRA32F,
     370           0 :                                    _impl->glewContext );
     371           0 :             break;
     372             :         case GL_RGB:
     373             :         case GL_RGB8:
     374             :             image.allocDownloader( Frame::BUFFER_COLOR,
     375             :                                    EQ_COMPRESSOR_TRANSFER_RGBA_TO_BGR,
     376           0 :                                    _impl->glewContext );
     377           0 :             break;
     378             :         case GL_RGB16F:
     379             :             image.allocDownloader( Frame::BUFFER_COLOR,
     380             :                                    EQ_COMPRESSOR_TRANSFER_RGBA16F_TO_BGR16F,
     381           0 :                                    _impl->glewContext );
     382           0 :             break;
     383             :         case GL_RGB32F:
     384             :             image.allocDownloader( Frame::BUFFER_COLOR,
     385             :                                    EQ_COMPRESSOR_TRANSFER_RGBA32F_TO_BGR32F,
     386           0 :                                    _impl->glewContext );
     387           0 :             break;
     388             :         case GL_DEPTH24_STENCIL8:
     389             :             image.allocDownloader( Frame::BUFFER_COLOR,
     390             :                              EQ_COMPRESSOR_TRANSFER_DEPTH_TO_DEPTH_UNSIGNED_INT,
     391           0 :                                    _impl->glewContext );
     392           0 :             break;
     393             : 
     394             :         default:
     395           0 :             LBUNIMPLEMENTED;
     396           0 :             return;
     397             :     }
     398             : 
     399             :     image.setPixelViewport( eq::PixelViewport( 0, 0,
     400           0 :                                                _impl->width, _impl->height ));
     401           0 :     if( image.startReadback( Frame::BUFFER_COLOR, this, _impl->glewContext ))
     402           0 :         image.finishReadback( _impl->glewContext );
     403           0 :     image.writeImage( filename + ".rgb", Frame::BUFFER_COLOR );
     404           0 :     image.resetPlugins();
     405             : }
     406             : 
     407           0 : GLenum Texture::getTarget() const { return _impl->target; }
     408           0 : GLuint Texture::getInternalFormat() const { return _impl->internalFormat; }
     409           0 : GLuint Texture::getFormat() const { return _impl->format; }
     410           0 : GLuint Texture::getType() const { return _impl->type; }
     411           0 : GLuint Texture::getName() const { return _impl->name; }
     412           0 : int32_t Texture::getWidth() const { return _impl->width; }
     413           0 : int32_t Texture::getHeight() const { return _impl->height; }
     414           0 : const GLEWContext* Texture::glewGetContext() const{ return _impl->glewContext; }
     415             : 
     416           0 : void Texture::setGLEWContext( const GLEWContext* context )
     417             : {
     418           0 :     _impl->glewContext = context;
     419           0 : }
     420             : 
     421           0 : std::ostream& operator << ( std::ostream& os, const Texture& texture )
     422             : {
     423             :     return os
     424           0 :         << "Texture " << texture.getWidth() << "x" << texture.getHeight()
     425           0 :         << " id " << texture.getName() << std::hex << " format "
     426           0 :         << texture.getFormat() << " type " << texture.getType() << std::dec
     427           0 :         << (texture.isValid() ? "" : " invalid");
     428             : }
     429             : 
     430             : }
     431          36 : }

Generated by: LCOV version 1.10