LCOV - code coverage report
Current view: top level - eq/util - texture.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 15 216 6.9 %
Date: 2016-09-29 05:02:09 Functions: 6 37 16.2 %

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

Generated by: LCOV version 1.11