LCOV - code coverage report
Current view: top level - eq/compressor - compressorYUV.cpp (source / functions) Hit Total Coverage
Test: Equalizer Lines: 17 166 10.2 %
Date: 2017-12-16 05:07:20 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/fabric/pixelViewport.h>
      23             : #include <eq/gl.h>
      24             : #include <eq/util/frameBufferObject.h>
      25             : #include <eq/zoomFilter.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           6 : static void _getInfo(EqCompressorInfo* const info)
      39             : {
      40           6 :     info->version = EQ_COMPRESSOR_VERSION;
      41           6 :     info->name = EQ_COMPRESSOR_TRANSFER_RGBA_TO_YUVA_50P;
      42           6 :     info->capabilities = EQ_COMPRESSOR_TRANSFER | EQ_COMPRESSOR_DATA_2D |
      43             :                          EQ_COMPRESSOR_USE_TEXTURE_RECT |
      44             :                          EQ_COMPRESSOR_USE_FRAMEBUFFER;
      45           6 :     info->tokenType = EQ_COMPRESSOR_DATATYPE_RGBA;
      46           6 :     info->outputTokenType = EQ_COMPRESSOR_DATATYPE_YUVA_50P;
      47           6 :     info->outputTokenSize = 4;
      48           6 :     info->quality = 0.5f;
      49           6 :     info->ratio = 0.5f;
      50           6 :     info->speed = 0.5f;
      51           6 : }
      52             : 
      53           6 : static bool _register()
      54             : {
      55             :     Compressor::registerEngine(
      56          12 :         Compressor::Functions(EQ_COMPRESSOR_TRANSFER_RGBA_TO_YUVA_50P, _getInfo,
      57             :                               CompressorYUV::getNewCompressor,
      58             :                               CompressorYUV::getNewDecompressor, 0,
      59           6 :                               CompressorYUV::isCompatible));
      60           6 :     return true;
      61             : }
      62             : 
      63           6 : 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             : {
      73           0 : }
      74             : 
      75             : /** Destruct the compressor Yuv */
      76           0 : CompressorYUV::~CompressorYUV()
      77             : {
      78             :     // replace original texture
      79           0 :     delete _fbo;
      80           0 :     _fbo = 0;
      81             : 
      82           0 :     if (_texture)
      83             :     {
      84           0 :         _texture->flush();
      85           0 :         delete _texture;
      86             :     }
      87           0 :     _texture = 0;
      88           0 : }
      89             : 
      90           0 : bool CompressorYUV::isCompatible(const GLEWContext* glewContext)
      91             : {
      92           0 :     return (GLEW_ARB_texture_non_power_of_two && 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           0 : void CompressorYUV::_compress(const GLEWContext* glewContext,
     130             :                               const eq_uint64_t* /*inDims*/,
     131             :                               eq_uint64_t outDims[4])
     132             : {
     133             :     /* save the current FBO ID for bind it at the end of the compression */
     134           0 :     GLint oldFBO = 0;
     135           0 :     glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldFBO);
     136             : 
     137           0 :     if (_fbo)
     138             :     {
     139           0 :         const auto error = _fbo->resize(outDims[1], outDims[3]);
     140           0 :         if (error != ERROR_NONE)
     141             :         {
     142           0 :             LBERROR << "FBO resize failed: " << error << std::endl;
     143           0 :             return;
     144             :         }
     145           0 :         _fbo->bind();
     146             :     }
     147             :     else
     148             :     {
     149           0 :         _fbo = new util::FrameBufferObject(glewContext);
     150           0 :         const auto error = _fbo->init(outDims[1], outDims[3], GL_RGBA, 0, 0);
     151           0 :         if (error != ERROR_NONE)
     152             :         {
     153           0 :             LBERROR << "FBO init failed: " << error << std::endl;
     154           0 :             return;
     155             :         }
     156             :     }
     157             : 
     158           0 :     _texture->bind();
     159             : 
     160           0 :     glDisable(GL_LIGHTING);
     161           0 :     glEnable(GL_TEXTURE_RECTANGLE_ARB);
     162             : 
     163           0 :     _texture->applyZoomFilter(FILTER_NEAREST);
     164           0 :     _texture->applyWrap();
     165             : 
     166           0 :     _initShader(glewContext, yuv420readback_glsl.c_str());
     167             : 
     168           0 :     const GLint colorParam = glGetUniformLocation(_program, "color");
     169           0 :     EQ_GL_CALL(glUniform1i(colorParam, 0));
     170             : 
     171           0 :     glDisable(GL_DEPTH_TEST);
     172           0 :     glBegin(GL_QUADS);
     173           0 :     glVertex3i(0, 0, 0);
     174           0 :     glVertex3i(outDims[1], 0, 0);
     175           0 :     glVertex3i(outDims[1], outDims[3], 0);
     176           0 :     glVertex3i(0, outDims[3], 0);
     177           0 :     glEnd();
     178             : 
     179             :     // restore state
     180             :     // glEnable( GL_DEPTH_TEST );
     181           0 :     glDisable(GL_TEXTURE_RECTANGLE_ARB);
     182           0 :     EQ_GL_CALL(glUseProgram(0));
     183             : 
     184             :     /* apply the initial fbo */
     185           0 :     EQ_GL_CALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFBO));
     186             : }
     187             : 
     188           0 : void CompressorYUV::_download(void* data)
     189             : {
     190           0 :     util::Texture* texture = _fbo->getColorTextures()[0];
     191           0 :     LBASSERT(texture->getFormat() == GL_RGBA);
     192           0 :     LBASSERT(texture->getType() == GL_UNSIGNED_BYTE);
     193           0 :     texture->download(data);
     194           0 : }
     195             : 
     196           0 : void CompressorYUV::download(const GLEWContext* glewContext,
     197             :                              const eq_uint64_t inDims[4], const unsigned source,
     198             :                              const eq_uint64_t flags, eq_uint64_t outDims[4],
     199             :                              void** out)
     200             : {
     201             :     glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT |
     202           0 :                  GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT);
     203           0 :     glColorMask(true, true, true, true);
     204           0 :     outDims[0] = inDims[0];
     205           0 :     outDims[1] = (inDims[1] + 1) / 2;
     206           0 :     outDims[2] = inDims[2];
     207           0 :     outDims[3] = (inDims[3] + 1) / 2;
     208           0 :     outDims[3] *= 2;
     209           0 :     buffer.resize(outDims[1] * outDims[3] * 4);
     210             :     // first time we instanciate the working texture
     211           0 :     if (!_texture)
     212           0 :         _texture = new util::Texture(GL_TEXTURE_RECTANGLE_ARB, glewContext);
     213             : 
     214             :     // the data is in the frame buffer
     215           0 :     if (flags & EQ_COMPRESSOR_USE_FRAMEBUFFER)
     216             :     {
     217             :         // read data in frame Buffer
     218           0 :         const eq::fabric::PixelViewport pvp(inDims[0], inDims[2], inDims[1],
     219           0 :                                             inDims[3]);
     220           0 :         _texture->init(GL_RGBA, outDims[1] * 2, outDims[3]);
     221           0 :         _texture->copyFromFrameBuffer(GL_RGBA, pvp);
     222             : 
     223             :         // compress data
     224           0 :         _compress(glewContext, inDims, outDims);
     225           0 :         buffer.resize(outDims[1] * outDims[3] * 4);
     226           0 :         _download(buffer.getData());
     227             :     }
     228             :     // the data is in the texture id define by the field "source"
     229           0 :     else if (flags & EQ_COMPRESSOR_USE_TEXTURE_RECT)
     230             :     {
     231             :         // assign texture id to the local texture class
     232             :         // compress Data
     233             :         // allow buffer memory on cpu
     234             :         // transfer data from gpu to cpu
     235           0 :         _texture->setGLData(source, GL_RGBA, inDims[1], inDims[3]);
     236           0 :         _compress(glewContext, inDims, outDims);
     237           0 :         _download(buffer.getData());
     238           0 :         _texture->flushNoDelete();
     239             :     }
     240             :     else
     241             :     {
     242           0 :         LBUNIMPLEMENTED;
     243             :     }
     244           0 :     out[0] = buffer.getData();
     245           0 :     glPopAttrib();
     246           0 : }
     247             : 
     248           0 : void CompressorYUV::_decompress(const GLEWContext* glewContext,
     249             :                                 const eq_uint64_t inDims[4])
     250             : {
     251           0 :     glDepthMask(false);
     252           0 :     _initShader(glewContext, yuv420unpack_glsl.c_str());
     253             : 
     254           0 :     const GLint colorParam = glGetUniformLocation(_program, "color");
     255           0 :     glUniform1i(colorParam, 0);
     256             : 
     257           0 :     glDisable(GL_LIGHTING);
     258           0 :     glEnable(GL_TEXTURE_RECTANGLE_ARB);
     259             : 
     260           0 :     _texture->applyWrap();
     261           0 :     _texture->applyZoomFilter(FILTER_NEAREST);
     262             : 
     263           0 :     glColor3f(1.0f, 1.0f, 1.0f);
     264           0 :     const float startX = static_cast<float>(inDims[0]);
     265           0 :     const float endX = static_cast<float>(inDims[1]) + startX;
     266           0 :     const float startY = static_cast<float>(inDims[2]);
     267           0 :     const float endY = static_cast<float>(inDims[3]) + startY;
     268             : 
     269           0 :     const GLint shiftX = glGetUniformLocation(_program, "shiftX");
     270           0 :     glUniform1f(shiftX, startX);
     271           0 :     const GLint shiftY = glGetUniformLocation(_program, "shiftY");
     272           0 :     glUniform1f(shiftY, startY);
     273             : 
     274           0 :     glBegin(GL_QUADS);
     275           0 :     glVertex3f(startX, startY, 0.0f);
     276           0 :     glVertex3f(endX, startY, 0.0f);
     277           0 :     glVertex3f(endX, endY, 0.0f);
     278           0 :     glVertex3f(startX, endY, 0.0f);
     279           0 :     glEnd();
     280             : 
     281           0 :     glDisable(GL_TEXTURE_RECTANGLE_ARB);
     282           0 :     EQ_GL_CALL(glUseProgram(0));
     283           0 :     glDepthMask(true);
     284           0 : }
     285             : 
     286           0 : void CompressorYUV::upload(const GLEWContext* glewContext, const void* data,
     287             :                            const eq_uint64_t inDims[4], const eq_uint64_t flags,
     288             :                            const eq_uint64_t outDims[4],
     289             :                            const unsigned destination)
     290             : {
     291             :     glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT |
     292           0 :                  GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT);
     293           0 :     if (!_texture)
     294             :     {
     295           0 :         _texture = new util::Texture(GL_TEXTURE_RECTANGLE_ARB, glewContext);
     296           0 :         _texture->init(GL_RGBA, outDims[1], outDims[3]);
     297             :     }
     298             : 
     299           0 :     if (flags & EQ_COMPRESSOR_USE_FRAMEBUFFER)
     300             :     {
     301           0 :         _texture->upload(inDims[1], inDims[3], data);
     302           0 :         _decompress(glewContext, outDims);
     303             :     }
     304           0 :     else if (flags & EQ_COMPRESSOR_USE_TEXTURE_RECT)
     305             :     {
     306             :         /* save the current FBO ID for bind it at the end of the compression */
     307           0 :         GLint oldFBO = 0;
     308           0 :         glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldFBO);
     309             : 
     310           0 :         if (!_fbo)
     311           0 :             _fbo = new util::FrameBufferObject(glewContext);
     312             : 
     313           0 :         util::Texture* texture = _fbo->getColorTextures().front();
     314           0 :         texture->setGLData(destination, GL_RGBA, outDims[1], outDims[3]);
     315             : 
     316           0 :         if (_fbo->isValid())
     317             :         {
     318           0 :             _fbo->bind();
     319           0 :             texture->bindToFBO(GL_COLOR_ATTACHMENT0, outDims[1], outDims[3]);
     320             :         }
     321             :         else
     322             :         {
     323           0 :             LBCHECK(_fbo->init(outDims[1], outDims[3], GL_RGBA, 0, 0));
     324             :         }
     325             : 
     326           0 :         _texture->upload(inDims[1], inDims[3], data);
     327           0 :         _decompress(glewContext, outDims);
     328             : 
     329             :         /* apply the initial fbo */
     330           0 :         EQ_GL_CALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFBO));
     331             : 
     332           0 :         texture->flushNoDelete();
     333             :     }
     334             :     else
     335             :     {
     336           0 :         LBASSERT(0);
     337             :     }
     338           0 :     glPopAttrib();
     339           0 : }
     340             : }
     341          18 : }

Generated by: LCOV version 1.11