LCOV - code coverage report
Current view: top level - eq/client/compressor - compressorYUV.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 16 161 9.9 %
Date: 2014-06-18 Functions: 4 14 28.6 %

          Line data    Source code
       1             : /* Copyright (c)      2009, Cedric Stalder <cedric.stalder@gmail.com>
       2             :  *                    2009, Maxim Makhinya
       3             :  *               2010-2013, Stefan Eilemann <eile@eyescale.ch>
       4             :  *                    2012, 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 "compressorYUV.h"
      21             : 
      22             : #include <eq/util/frameBufferObject.h>
      23             : #include <eq/client/gl.h>
      24             : #include <eq/client/zoomFilter.h>
      25             : #include <eq/fabric/pixelViewport.h>
      26             : 
      27             : #include "yuv420readback_glsl.h"
      28             : #include "yuv420unpack_glsl.h"
      29             : 
      30             : #define glewGetContext() glewContext
      31             : 
      32             : namespace eq
      33             : {
      34             : namespace plugin
      35             : {
      36             : namespace
      37             : {
      38           9 : static void _getInfo( EqCompressorInfo* const info )
      39             : {
      40           9 :     info->version         = EQ_COMPRESSOR_VERSION;
      41           9 :     info->name            = EQ_COMPRESSOR_TRANSFER_RGBA_TO_YUVA_50P;
      42             :     info->capabilities    = EQ_COMPRESSOR_TRANSFER | EQ_COMPRESSOR_DATA_2D |
      43             :                             EQ_COMPRESSOR_USE_TEXTURE_RECT |
      44           9 :                             EQ_COMPRESSOR_USE_FRAMEBUFFER;
      45           9 :     info->tokenType       = EQ_COMPRESSOR_DATATYPE_RGBA;
      46           9 :     info->outputTokenType = EQ_COMPRESSOR_DATATYPE_YUVA_50P;
      47           9 :     info->outputTokenSize = 4;
      48           9 :     info->quality         = 0.5f;
      49           9 :     info->ratio           = 0.5f;
      50           9 :     info->speed           = 0.5f;
      51           9 : }
      52             : 
      53          12 : static bool _register()
      54             : {
      55             :     Compressor::registerEngine(
      56             :         Compressor::Functions( EQ_COMPRESSOR_TRANSFER_RGBA_TO_YUVA_50P,
      57             :                                _getInfo, CompressorYUV::getNewCompressor,
      58             :                                CompressorYUV::getNewDecompressor, 0,
      59          12 :                                CompressorYUV::isCompatible ));
      60          12 :     return true;
      61             : }
      62             : 
      63          12 : static bool _initialized LB_UNUSED = _register();
      64             : }
      65             : 
      66             : /** Construct a new compressor Yuv */
      67           0 : CompressorYUV::CompressorYUV()
      68             :         : Compressor()
      69             :         , _program( 0 )
      70             :         , _fbo( 0 )
      71           0 :         , _texture( 0 )
      72           0 : { }
      73             : 
      74             : /** Destruct the compressor Yuv */
      75           0 : CompressorYUV::~CompressorYUV( )
      76             : {
      77             :     // replace original texture
      78           0 :     delete _fbo;
      79           0 :     _fbo = 0;
      80             : 
      81           0 :     if ( _texture )
      82             :     {
      83           0 :         _texture->flush();
      84           0 :         delete _texture;
      85             :     }
      86           0 :     _texture = 0;
      87           0 : }
      88             : 
      89           0 : bool CompressorYUV::isCompatible( const GLEWContext* glewContext )
      90             : {
      91           0 :     return ( GLEW_ARB_texture_non_power_of_two &&
      92           0 :              GLEW_VERSION_2_0 &&
      93           0 :              GLEW_EXT_framebuffer_object );
      94             : }
      95             : 
      96           0 : void CompressorYUV::_initShader( const GLEWContext* glewContext LB_UNUSED,
      97             :                                  const char* fShaderPtr )
      98             : {
      99           0 :     if ( _program )
     100             :     {
     101             :         // use fragment shader and setup uniforms
     102           0 :         EQ_GL_CALL( glUseProgram( _program ));
     103           0 :         return ;
     104             :     }
     105             : 
     106             :     // Create fragment shader which reads depth values from
     107             :     // rectangular textures
     108           0 :     const GLuint shader = glCreateShader( GL_FRAGMENT_SHADER );
     109             : 
     110           0 :     EQ_GL_CALL( glShaderSource( shader, 1, &fShaderPtr, 0 ));
     111           0 :     EQ_GL_CALL( glCompileShader( shader ));
     112             : 
     113             :     GLint status;
     114           0 :     glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
     115           0 :     LBASSERT( status );
     116             : 
     117           0 :     _program = glCreateProgram( );
     118             : 
     119           0 :     EQ_GL_CALL( glAttachShader( _program, shader ));
     120           0 :     EQ_GL_CALL( glLinkProgram( _program ));
     121             : 
     122           0 :     glGetProgramiv( _program, GL_LINK_STATUS, &status );
     123           0 :     LBASSERT( status );
     124             : 
     125             :     // use fragment shader and setup uniforms
     126           0 :     EQ_GL_CALL( glUseProgram( _program ));
     127             : 
     128             : }
     129             : 
     130             : 
     131           0 : void CompressorYUV::_compress( const GLEWContext* glewContext,
     132             :                                const eq_uint64_t* /*inDims*/,
     133             :                                eq_uint64_t outDims[4] )
     134             : {
     135             :     /* save the current FBO ID for bind it at the end of the compression */
     136           0 :     GLint oldFBO = 0;
     137           0 :     glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &oldFBO );
     138             : 
     139           0 :     if ( _fbo )
     140             :     {
     141           0 :         LBCHECK( _fbo->resize( outDims[1], outDims[3] ));
     142           0 :         _fbo->bind();
     143             :     }
     144             :     else
     145             :     {
     146           0 :         _fbo = new util::FrameBufferObject( glewContext );
     147           0 :         LBCHECK( _fbo->init( outDims[1], outDims[3], GL_RGBA, 0, 0 ));
     148             :     }
     149             : 
     150           0 :     _texture->bind();
     151             : 
     152           0 :     glDisable( GL_LIGHTING );
     153           0 :     glEnable( GL_TEXTURE_RECTANGLE_ARB );
     154             : 
     155           0 :     _texture->applyZoomFilter( FILTER_NEAREST );
     156           0 :     _texture->applyWrap();
     157             : 
     158           0 :     _initShader( glewContext, yuv420readback_glsl.c_str() );
     159             : 
     160           0 :     const GLint colorParam = glGetUniformLocation( _program, "color" );
     161           0 :     EQ_GL_CALL( glUniform1i( colorParam, 0 ));
     162             : 
     163           0 :     glDisable( GL_DEPTH_TEST );
     164           0 :     glBegin( GL_QUADS );
     165           0 :         glVertex3i(     0,     0, 0 );
     166           0 :         glVertex3i( outDims[1],     0, 0 );
     167           0 :         glVertex3i( outDims[1], outDims[3], 0 );
     168           0 :         glVertex3i(     0, outDims[3], 0 );
     169           0 :     glEnd();
     170             : 
     171             :     // restore state
     172             :     //glEnable( GL_DEPTH_TEST );
     173           0 :     glDisable( GL_TEXTURE_RECTANGLE_ARB );
     174           0 :     EQ_GL_CALL( glUseProgram( 0 ));
     175             : 
     176             :     /* apply the initial fbo */
     177           0 :     EQ_GL_CALL( glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, oldFBO ));
     178           0 : }
     179             : 
     180           0 : void CompressorYUV::_download( void* data )
     181             : {
     182           0 :     util::Texture* texture = _fbo->getColorTextures()[0];
     183           0 :     LBASSERT( texture->getFormat() == GL_RGBA );
     184           0 :     LBASSERT( texture->getType() == GL_UNSIGNED_BYTE );
     185           0 :     texture->download( data );
     186           0 : }
     187             : 
     188           0 : void CompressorYUV::download( const GLEWContext* glewContext,
     189             :                               const eq_uint64_t  inDims[4],
     190             :                               const unsigned     source,
     191             :                               const eq_uint64_t  flags,
     192             :                                     eq_uint64_t  outDims[4],
     193             :                               void**             out )
     194             : {
     195             :     glPushAttrib( GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT |
     196           0 :                   GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT );
     197           0 :     glColorMask( true, true, true, true );
     198           0 :     outDims[0] = inDims[0];
     199           0 :     outDims[1] = (inDims[1] + 1) / 2;
     200           0 :     outDims[2] = inDims[2];
     201           0 :     outDims[3] = (inDims[3] + 1) / 2;
     202           0 :     outDims[3] *= 2;
     203           0 :     buffer.resize( outDims[1] * outDims[3] * 4 );
     204             :     // first time we instanciate the working texture
     205           0 :     if ( !_texture )
     206           0 :         _texture = new util::Texture( GL_TEXTURE_RECTANGLE_ARB, glewContext );
     207             : 
     208             :     // the data is in the frame buffer
     209           0 :     if( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER )
     210             :     {
     211             :          // read data in frame Buffer
     212           0 :         const eq::fabric::PixelViewport pvp( inDims[0], inDims[2],
     213           0 :                                              inDims[1], inDims[3] );
     214           0 :         _texture->init( GL_RGBA, outDims[1]*2, outDims[3] );
     215           0 :         _texture->copyFromFrameBuffer( GL_RGBA, pvp );
     216             : 
     217             :         // compress data
     218           0 :         _compress( glewContext, inDims, outDims );
     219           0 :         buffer.resize( outDims[1] * outDims[3] * 4 );
     220           0 :         _download( buffer.getData( ));
     221             :     }
     222             :     // the data is in the texture id define by the field "source"
     223           0 :     else if( flags & EQ_COMPRESSOR_USE_TEXTURE_RECT )
     224             :     {
     225             :         // assign texture id to the local texture class
     226             :         // compress Data
     227             :         // allow buffer memory on cpu
     228             :         // transfer data from gpu to cpu
     229           0 :         _texture->setGLData( source, GL_RGBA, inDims[1], inDims[3] );
     230           0 :         _compress( glewContext, inDims, outDims );
     231           0 :         _download( buffer.getData( ));
     232           0 :         _texture->flushNoDelete();
     233             :     }
     234             :     else
     235             :     {
     236           0 :         LBUNIMPLEMENTED;
     237             :     }
     238           0 :     out[0] = buffer.getData();
     239           0 :     glPopAttrib();
     240           0 : }
     241             : 
     242           0 : void CompressorYUV::_decompress( const GLEWContext* glewContext,
     243             :                                  const eq_uint64_t inDims[4] )
     244             : {
     245           0 :     glDepthMask( false );
     246           0 :     _initShader( glewContext, yuv420unpack_glsl.c_str() );
     247             : 
     248           0 :     const GLint colorParam = glGetUniformLocation( _program, "color" );
     249           0 :     glUniform1i( colorParam, 0 );
     250             : 
     251           0 :     glDisable( GL_LIGHTING );
     252           0 :     glEnable( GL_TEXTURE_RECTANGLE_ARB );
     253             : 
     254           0 :     _texture->applyWrap();
     255           0 :     _texture->applyZoomFilter( FILTER_NEAREST );
     256             : 
     257           0 :     glColor3f( 1.0f, 1.0f, 1.0f );
     258           0 :     const float startX = static_cast< float >( inDims[0] );
     259           0 :     const float endX   = static_cast< float >( inDims[1] ) + startX;
     260           0 :     const float startY = static_cast< float >( inDims[2] );
     261           0 :     const float endY   = static_cast< float >( inDims[3] ) + startY;
     262             : 
     263           0 :     const GLint shiftX = glGetUniformLocation( _program, "shiftX" );
     264           0 :     glUniform1f( shiftX, startX );
     265           0 :     const GLint shiftY = glGetUniformLocation( _program, "shiftY" );
     266           0 :     glUniform1f( shiftY, startY );
     267             : 
     268           0 :     glBegin( GL_QUADS );
     269           0 :         glVertex3f( startX, startY, 0.0f );
     270           0 :         glVertex3f(   endX, startY, 0.0f );
     271           0 :         glVertex3f(   endX,   endY, 0.0f );
     272           0 :         glVertex3f( startX,   endY, 0.0f );
     273           0 :     glEnd();
     274             : 
     275           0 :     glDisable( GL_TEXTURE_RECTANGLE_ARB );
     276           0 :     EQ_GL_CALL( glUseProgram( 0 ));
     277           0 :     glDepthMask( true );
     278           0 : }
     279             : 
     280           0 : void CompressorYUV::upload( const GLEWContext* glewContext,
     281             :                             const void*        data,
     282             :                             const eq_uint64_t  inDims[4],
     283             :                             const eq_uint64_t  flags,
     284             :                             const eq_uint64_t  outDims[4],
     285             :                             const unsigned     destination )
     286             : {
     287             :     glPushAttrib( GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT |
     288           0 :                   GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT );
     289           0 :     if ( !_texture )
     290             :     {
     291           0 :         _texture = new util::Texture( GL_TEXTURE_RECTANGLE_ARB, glewContext );
     292           0 :         _texture->init( GL_RGBA, outDims[1], outDims[3] );
     293             :     }
     294             : 
     295           0 :     if ( flags & EQ_COMPRESSOR_USE_FRAMEBUFFER )
     296             :     {
     297           0 :         _texture->upload( inDims[1], inDims[3], data );
     298           0 :         _decompress( glewContext, outDims );
     299             :     }
     300           0 :     else if( flags & EQ_COMPRESSOR_USE_TEXTURE_RECT  )
     301             :     {
     302             :         /* save the current FBO ID for bind it at the end of the compression */
     303           0 :         GLint oldFBO = 0;
     304           0 :         glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &oldFBO );
     305             : 
     306           0 :         if ( !_fbo )
     307           0 :             _fbo = new util::FrameBufferObject( glewContext );
     308             : 
     309           0 :         util::Texture* texture = _fbo->getColorTextures().front();
     310           0 :         texture->setGLData( destination, GL_RGBA, outDims[1], outDims[3] );
     311             : 
     312           0 :         if( _fbo->isValid() )
     313             :         {
     314           0 :             _fbo->bind();
     315           0 :             texture->bindToFBO( GL_COLOR_ATTACHMENT0, outDims[1], outDims[3] );
     316             :         }
     317             :         else
     318             :         {
     319           0 :             LBCHECK( _fbo->init( outDims[1], outDims[3], GL_RGBA, 0, 0 ));
     320             :         }
     321             : 
     322           0 :         _texture->upload( inDims[1], inDims[3], data );
     323           0 :         _decompress( glewContext, outDims );
     324             : 
     325             :         /* apply the initial fbo */
     326           0 :         EQ_GL_CALL( glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, oldFBO ));
     327             : 
     328           0 :         texture->flushNoDelete();
     329             :     }
     330             :     else
     331             :     {
     332           0 :         LBASSERT( 0 );
     333             :     }
     334           0 :     glPopAttrib();
     335           0 : }
     336             : 
     337             : }
     338          36 : }

Generated by: LCOV version 1.10