LCOV - code coverage report
Current view: top level - vcl/source/opengl - OpenGLHelper.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 176 0.6 %
Date: 2014-11-03 Functions: 2 15 13.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <vcl/opengl/GLMHelper.hxx>
      11             : #include <vcl/opengl/OpenGLHelper.hxx>
      12             : 
      13             : #include <osl/file.hxx>
      14             : #include <rtl/bootstrap.hxx>
      15             : #include <config_folders.h>
      16             : #include <vcl/salbtype.hxx>
      17             : #include <vcl/bmpacc.hxx>
      18             : #include <boost/scoped_array.hpp>
      19             : #include <vcl/pngwrite.hxx>
      20             : #include <vcl/graph.hxx>
      21             : 
      22             : #include <vector>
      23             : 
      24             : namespace {
      25             : 
      26           0 : OUString getShaderFolder()
      27             : {
      28           0 :     OUString aUrl("$BRAND_BASE_DIR/" LIBO_ETC_FOLDER);
      29           0 :     rtl::Bootstrap::expandMacros(aUrl);
      30             : 
      31           0 :     return aUrl + "/opengl/";
      32             : }
      33             : 
      34           0 : OString loadShader(const OUString& rFilename)
      35             : {
      36           0 :     OUString aFileURL = getShaderFolder() + rFilename +".glsl";
      37           0 :     osl::File aFile(aFileURL);
      38           0 :     if(aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None)
      39             :     {
      40           0 :         sal_uInt64 nSize = 0;
      41           0 :         aFile.getSize(nSize);
      42           0 :         boost::scoped_array<char> content(new char[nSize+1]);
      43           0 :         sal_uInt64 nBytesRead = 0;
      44           0 :         aFile.read(content.get(), nSize, nBytesRead);
      45           0 :         if(nSize != nBytesRead)
      46             :             assert(false);
      47             : 
      48           0 :         content[nSize] = 0;
      49           0 :         return OString(content.get());
      50             :     }
      51             :     else
      52             :     {
      53             :         SAL_WARN("vcl.opengl", "could not load the file: " << aFileURL);
      54             :     }
      55             : 
      56           0 :     return OString();
      57             : }
      58             : 
      59             : }
      60             : 
      61           0 : GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString& rFragmentShaderName)
      62             : {
      63             :     // Create the shaders
      64           0 :     GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
      65           0 :     GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
      66             : 
      67           0 :     GLint Result = GL_FALSE;
      68             :     int InfoLogLength;
      69             : 
      70             :     // Compile Vertex Shader
      71           0 :     OString aVertexShaderSource = loadShader(rVertexShaderName);
      72           0 :     char const * VertexSourcePointer = aVertexShaderSource.getStr();
      73           0 :     glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
      74           0 :     glCompileShader(VertexShaderID);
      75             : 
      76             :     // Check Vertex Shader
      77           0 :     glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
      78           0 :     if ( !Result )
      79             :     {
      80           0 :         glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
      81           0 :         if ( InfoLogLength > 0 )
      82             :         {
      83           0 :             std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
      84           0 :             glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
      85           0 :             VertexShaderErrorMessage.push_back('\0');
      86           0 :             SAL_WARN("vcl.opengl", "vertex shader compile for " << rVertexShaderName << " failed : " << &VertexShaderErrorMessage[0]);
      87             :         }
      88             :         else
      89             :             SAL_WARN("vcl.opengl", "vertex shader compile failed without error log");
      90             : 
      91           0 :         return 0;
      92             :     }
      93             : 
      94             :     // Compile Fragment Shader
      95           0 :     OString aFragmentShaderSource = loadShader(rFragmentShaderName);
      96           0 :     char const * FragmentSourcePointer = aFragmentShaderSource.getStr();
      97           0 :     glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
      98           0 :     glCompileShader(FragmentShaderID);
      99             : 
     100             :     // Check Fragment Shader
     101           0 :     glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
     102           0 :     if ( !Result )
     103             :     {
     104           0 :         glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
     105           0 :         if ( InfoLogLength > 0 )
     106             :         {
     107           0 :             std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
     108           0 :             glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
     109           0 :             FragmentShaderErrorMessage.push_back('\0');
     110           0 :             SAL_WARN("vcl.opengl", "fragment shader compile for " << rFragmentShaderName << " failed : " << &FragmentShaderErrorMessage[0]);
     111             :         }
     112             :         else
     113             :             SAL_WARN("vcl.opengl", "fragment shader compile failed without error log");
     114             : 
     115             : 
     116           0 :         return 0;
     117             :     }
     118             : 
     119             :     // Link the program
     120           0 :     GLint ProgramID = glCreateProgram();
     121           0 :     glAttachShader(ProgramID, VertexShaderID);
     122           0 :     glAttachShader(ProgramID, FragmentShaderID);
     123           0 :     glLinkProgram(ProgramID);
     124             : 
     125           0 :     glDeleteShader(VertexShaderID);
     126           0 :     glDeleteShader(FragmentShaderID);
     127             : 
     128             :     // Check the program
     129           0 :     glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
     130           0 :     if ( !Result )
     131             :     {
     132           0 :         glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
     133           0 :         if ( InfoLogLength > 0 )
     134             :         {
     135           0 :             std::vector<char> ProgramErrorMessage(InfoLogLength+1);
     136           0 :             glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
     137           0 :             ProgramErrorMessage.push_back('\0');
     138           0 :             SAL_WARN("vcl.opengl", "Shader Program failed : " << &ProgramErrorMessage[0]);
     139             :         }
     140             :         else
     141             :             SAL_WARN("vcl.opengl", "shader program link failed without error log");
     142             : 
     143           0 :         return 0;
     144             :     }
     145             : 
     146           0 :     return ProgramID;
     147             : }
     148             : 
     149           0 : void OpenGLHelper::ConvertBitmapExToRGBATextureBuffer(const BitmapEx& rBitmapEx, sal_uInt8* o_pRGBABuffer, const bool bFlip)
     150             : {
     151           0 :     long nBmpWidth = rBitmapEx.GetSizePixel().Width();
     152           0 :     long nBmpHeight = rBitmapEx.GetSizePixel().Height();
     153             : 
     154           0 :     Bitmap aBitmap (rBitmapEx.GetBitmap());
     155           0 :     AlphaMask aAlpha (rBitmapEx.GetAlpha());
     156           0 :     Bitmap::ScopedReadAccess pReadAccces( aBitmap );
     157           0 :     AlphaMask::ScopedReadAccess pAlphaReadAccess( aAlpha );
     158           0 :     size_t i = 0;
     159           0 :     for (long ny = (bFlip ? nBmpHeight - 1 : 0); (bFlip ? ny >= 0 : ny < nBmpHeight); (bFlip ? ny-- : ny++))
     160             :     {
     161           0 :         Scanline pAScan = pAlphaReadAccess ? pAlphaReadAccess->GetScanline(ny) : 0;
     162           0 :         for(long nx = 0; nx < nBmpWidth; nx++)
     163             :         {
     164           0 :             BitmapColor aCol = pReadAccces->GetColor( ny, nx );
     165           0 :             o_pRGBABuffer[i++] = aCol.GetRed();
     166           0 :             o_pRGBABuffer[i++] = aCol.GetGreen();
     167           0 :             o_pRGBABuffer[i++] = aCol.GetBlue();
     168           0 :             o_pRGBABuffer[i++] = pAScan ? 255 - *pAScan++ : 255;
     169           0 :         }
     170           0 :     }
     171           0 : }
     172             : 
     173           0 : void OpenGLHelper::renderToFile(long nWidth, long nHeight, const OUString& rFileName)
     174             : {
     175           0 :     boost::scoped_array<sal_uInt8> pBuffer(new sal_uInt8[nWidth*nHeight*4]);
     176           0 :     glReadPixels(0, 0, nWidth, nHeight, GL_BGRA, GL_UNSIGNED_BYTE, pBuffer.get());
     177           0 :     BitmapEx aBitmap = ConvertBGRABufferToBitmapEx(pBuffer.get(), nWidth, nHeight);
     178             :     try {
     179           0 :         vcl::PNGWriter aWriter( aBitmap );
     180           0 :         SvFileStream sOutput( rFileName, STREAM_WRITE );
     181           0 :         aWriter.Write( sOutput );
     182           0 :         sOutput.Close();
     183           0 :     } catch (...) {
     184             :         SAL_WARN("vcl.opengl", "Error writing png to " << rFileName);
     185           0 :     }
     186           0 : }
     187             : 
     188           0 : BitmapEx OpenGLHelper::ConvertBGRABufferToBitmapEx(const sal_uInt8* const pBuffer, long nWidth, long nHeight)
     189             : {
     190             :     assert(pBuffer);
     191           0 :     Bitmap aBitmap( Size(nWidth, nHeight), 24 );
     192           0 :     AlphaMask aAlpha( Size(nWidth, nHeight) );
     193             : 
     194             :     {
     195           0 :         Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
     196           0 :         AlphaMask::ScopedWriteAccess pAlphaWriteAccess( aAlpha );
     197             : 
     198           0 :         size_t nCurPos = 0;
     199           0 :         for( int y = 0; y < nHeight; ++y)
     200             :         {
     201           0 :             Scanline pScan = pWriteAccess->GetScanline(y);
     202           0 :             Scanline pAlphaScan = pAlphaWriteAccess->GetScanline(y);
     203           0 :             for( int x = 0; x < nWidth; ++x )
     204             :             {
     205           0 :                 *pScan++ = pBuffer[nCurPos];
     206           0 :                 *pScan++ = pBuffer[nCurPos+1];
     207           0 :                 *pScan++ = pBuffer[nCurPos+2];
     208             : 
     209           0 :                 nCurPos += 3;
     210           0 :                 *pAlphaScan++ = static_cast<sal_uInt8>( 255 - pBuffer[nCurPos++] );
     211             :             }
     212           0 :         }
     213             :     }
     214           0 :     return BitmapEx(aBitmap, aAlpha);
     215             : }
     216             : 
     217           0 : const char* OpenGLHelper::GLErrorString(GLenum errorCode)
     218             : {
     219             :     static const struct {
     220             :         GLenum code;
     221             :         const char *string;
     222             :     } errors[]=
     223             :     {
     224             :         /* GL */
     225             :         {GL_NO_ERROR, "no error"},
     226             :         {GL_INVALID_ENUM, "invalid enumerant"},
     227             :         {GL_INVALID_VALUE, "invalid value"},
     228             :         {GL_INVALID_OPERATION, "invalid operation"},
     229             :         {GL_STACK_OVERFLOW, "stack overflow"},
     230             :         {GL_STACK_UNDERFLOW, "stack underflow"},
     231             :         {GL_OUT_OF_MEMORY, "out of memory"},
     232             :         {GL_INVALID_FRAMEBUFFER_OPERATION, "invalid framebuffer operation"},
     233             : 
     234             :         {0, NULL }
     235             :     };
     236             : 
     237             :     int i;
     238             : 
     239           0 :     for (i=0; errors[i].string; i++)
     240             :     {
     241           0 :         if (errors[i].code == errorCode)
     242             :         {
     243           0 :             return errors[i].string;
     244             :         }
     245             :      }
     246             : 
     247           0 :     return NULL;
     248             : }
     249             : 
     250           0 : std::ostream& operator<<(std::ostream& rStrm, const glm::vec4& rPos)
     251             : {
     252           0 :     rStrm << "( " << rPos[0] << ", " << rPos[1] << ", " << rPos[2] << ", " << rPos[3] << ")";
     253           0 :     return rStrm;
     254             : }
     255             : 
     256           0 : std::ostream& operator<<(std::ostream& rStrm, const glm::vec3& rPos)
     257             : {
     258           0 :     rStrm << "( " << rPos[0] << ", " << rPos[1] << ", " << rPos[2] << ")";
     259           0 :     return rStrm;
     260             : }
     261             : 
     262           0 : std::ostream& operator<<(std::ostream& rStrm, const glm::mat4& rMatrix)
     263             : {
     264           0 :     for(int i = 0; i < 4; ++i)
     265             :     {
     266           0 :         rStrm << "\n( ";
     267           0 :         for(int j = 0; j < 4; ++j)
     268             :         {
     269           0 :             rStrm << rMatrix[j][i];
     270           0 :             rStrm << " ";
     271             :         }
     272           0 :         rStrm << ")\n";
     273             :     }
     274           0 :     return rStrm;
     275             : }
     276             : 
     277           0 : void OpenGLHelper::createFramebuffer(long nWidth, long nHeight, GLuint& nFramebufferId,
     278             :         GLuint& nRenderbufferDepthId, GLuint& nRenderbufferColorId, bool bRenderbuffer)
     279             : {
     280             :     // create a renderbuffer for depth attachment
     281           0 :     glGenRenderbuffers(1, &nRenderbufferDepthId);
     282           0 :     glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferDepthId);
     283           0 :     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, nWidth, nHeight);
     284           0 :     glBindRenderbuffer(GL_RENDERBUFFER, 0);
     285             : 
     286           0 :     if(bRenderbuffer)
     287             :     {
     288             :         // create a renderbuffer for color attachment
     289           0 :         glGenRenderbuffers(1, &nRenderbufferColorId);
     290           0 :         glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferColorId);
     291           0 :         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, nWidth, nHeight);
     292           0 :         glBindRenderbuffer(GL_RENDERBUFFER, 0);
     293             :     }
     294             :     else
     295             :     {
     296           0 :         glGenTextures(1, &nRenderbufferColorId);
     297           0 :         glBindTexture(GL_TEXTURE_2D, nRenderbufferColorId);
     298           0 :         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     299           0 :         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
     300           0 :         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     301           0 :         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     302             :         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 0,
     303           0 :                              GL_RGBA, GL_UNSIGNED_BYTE, 0);
     304           0 :         glBindTexture(GL_TEXTURE_2D, 0);
     305             : 
     306             :         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
     307           0 :                 GL_TEXTURE_2D, nRenderbufferColorId, 0);
     308             :     }
     309             : 
     310             :     // create a framebuffer object and attach renderbuffer
     311           0 :     glGenFramebuffers(1, &nFramebufferId);
     312           0 :     glCheckFramebufferStatus(GL_FRAMEBUFFER);
     313           0 :     glBindFramebuffer(GL_FRAMEBUFFER, nFramebufferId);
     314             :     // attach a renderbuffer to FBO color attachement point
     315           0 :     glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferColorId);
     316           0 :     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, nRenderbufferColorId);
     317           0 :     glCheckFramebufferStatus(GL_FRAMEBUFFER);
     318             :     // attach a renderbuffer to depth attachment point
     319           0 :     glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferDepthId);
     320           0 :     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, nRenderbufferDepthId);
     321           0 :     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
     322           0 :     if (status != GL_FRAMEBUFFER_COMPLETE)
     323             :     {
     324             :         SAL_WARN("vcl.opengl", "invalid framebuffer status");
     325             :     }
     326           0 :     glBindRenderbuffer(GL_RENDERBUFFER, 0);
     327           0 :     glBindFramebuffer(GL_FRAMEBUFFER, 0);
     328           0 : }
     329             : 
     330           0 : float OpenGLHelper::getGLVersion()
     331             : {
     332           0 :     float fVersion = 1.0;
     333           0 :     const GLubyte* aVersion = glGetString( GL_VERSION );
     334           0 :     if( aVersion && aVersion[0] )
     335             :     {
     336           0 :         fVersion = aVersion[0] - '0';
     337           0 :         if( aVersion[1] == '.' && aVersion[2] )
     338             :         {
     339           0 :             fVersion += (aVersion[2] - '0')/10.0;
     340             :         }
     341             :     }
     342           0 :     return fVersion;
     343             : }
     344             : 
     345           0 : void OpenGLHelper::checkGLError(const char* pFile, size_t nLine)
     346             : {
     347           0 :     GLenum glErr = glGetError();
     348           0 :     while (glErr != GL_NO_ERROR)
     349             :     {
     350           0 :         const char* sError = OpenGLHelper::GLErrorString(glErr);
     351             : 
     352           0 :         if (sError)
     353             :             SAL_WARN("vcl.opengl", "GL Error #" << glErr << "(" << sError << ") in File " << pFile << " at line: " << nLine);
     354             :         else
     355             :             SAL_WARN("vcl.opengl", "GL Error #" << glErr << " (no message available) in File " << pFile << " at line: " << nLine);
     356             : 
     357           0 :         glErr = glGetError();
     358             :     }
     359         651 : }
     360             : 
     361             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10