diff --git a/include/vcl/opengl/OpenGLHelper.hxx b/include/vcl/opengl/OpenGLHelper.hxx index 9475aeb09355..861af021a383 100644 --- a/include/vcl/opengl/OpenGLHelper.hxx +++ b/include/vcl/opengl/OpenGLHelper.hxx @@ -55,10 +55,15 @@ public: static GLint LoadShaders(const OUString& rVertexShaderName, const OUString& rFragmentShaderName); /** - * The caller is responsible for allocate the memory for the RGBA buffer, before call - * this method. RGBA buffer size is assumed to be 4*width*height. + * The caller is responsible for allocating the memory for the buffer before calling + * this method. The buffer size is assumed to be 4*width*height and the format + * to be OptimalBufferFormat(). **/ - static BitmapEx ConvertBGRABufferToBitmapEx(const sal_uInt8* const pBuffer, long nWidth, long nHeight); + static BitmapEx ConvertBufferToBitmapEx(const sal_uInt8* const pBuffer, long nWidth, long nHeight); + /** + * Returns the optimal buffer format for OpenGL (GL_BGRA or GL_RGBA). + **/ + static GLenum OptimalBufferFormat(); static void renderToFile(long nWidth, long nHeight, const OUString& rFileName); static const char* GLErrorString(GLenum errorCode); diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index 6536141c8134..19b48967e314 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -498,8 +498,8 @@ void OpenGLTexture::Unbind() void OpenGLTexture::SaveToFile(const OUString& rFileName) { std::vector aBuffer(GetWidth() * GetHeight() * 4); - Read(GL_BGRA, GL_UNSIGNED_BYTE, aBuffer.data()); - BitmapEx aBitmap = OpenGLHelper::ConvertBGRABufferToBitmapEx(aBuffer.data(), GetWidth(), GetHeight()); + Read(OpenGLHelper::OptimalBufferFormat(), GL_UNSIGNED_BYTE, aBuffer.data()); + BitmapEx aBitmap = OpenGLHelper::ConvertBufferToBitmapEx(aBuffer.data(), GetWidth(), GetHeight()); try { vcl::PNGWriter aWriter(aBitmap); diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx index b21619e18b46..2b2e8ea4d783 100644 --- a/vcl/source/opengl/OpenGLHelper.cxx +++ b/vcl/source/opengl/OpenGLHelper.cxx @@ -541,8 +541,8 @@ void OpenGLHelper::renderToFile(long nWidth, long nHeight, const OUString& rFile OpenGLZone aZone; std::unique_ptr pBuffer(new sal_uInt8[nWidth*nHeight*4]); - glReadPixels(0, 0, nWidth, nHeight, GL_BGRA, GL_UNSIGNED_BYTE, pBuffer.get()); - BitmapEx aBitmap = ConvertBGRABufferToBitmapEx(pBuffer.get(), nWidth, nHeight); + glReadPixels(0, 0, nWidth, nHeight, OptimalBufferFormat(), GL_UNSIGNED_BYTE, pBuffer.get()); + BitmapEx aBitmap = ConvertBufferToBitmapEx(pBuffer.get(), nWidth, nHeight); try { vcl::PNGWriter aWriter( aBitmap ); SvFileStream sOutput( rFileName, StreamMode::WRITE ); @@ -555,7 +555,16 @@ void OpenGLHelper::renderToFile(long nWidth, long nHeight, const OUString& rFile CHECK_GL_ERROR(); } -BitmapEx OpenGLHelper::ConvertBGRABufferToBitmapEx(const sal_uInt8* const pBuffer, long nWidth, long nHeight) +GLenum OpenGLHelper::OptimalBufferFormat() +{ +#ifdef _WIN32 + return GL_BGRA; // OpenGLSalBitmap is internally ScanlineFormat::N24BitTcBgr +#else + return GL_RGBA; // OpenGLSalBitmap is internally ScanlineFormat::N24BitTcRgb +#endif +} + +BitmapEx OpenGLHelper::ConvertBufferToBitmapEx(const sal_uInt8* const pBuffer, long nWidth, long nHeight) { assert(pBuffer); Bitmap aBitmap( Size(nWidth, nHeight), 24 ); @@ -564,12 +573,27 @@ BitmapEx OpenGLHelper::ConvertBGRABufferToBitmapEx(const sal_uInt8* const pBuffe { BitmapScopedWriteAccess pWriteAccess( aBitmap ); AlphaScopedWriteAccess pAlphaWriteAccess( aAlpha ); +#ifdef _WIN32 + assert(pWriteAccess->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr); + assert(pWriteAccess->IsTopDown()); + assert(pAlphaWriteAccess->IsTopDown()); +#else + assert(pWriteAccess->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb); + assert(!pWriteAccess->IsTopDown()); + assert(!pAlphaWriteAccess->IsTopDown()); +#endif + assert(pAlphaWriteAccess->GetScanlineFormat() == ScanlineFormat::N8BitPal); size_t nCurPos = 0; for( long y = 0; y < nHeight; ++y) { +#ifdef _WIN32 Scanline pScan = pWriteAccess->GetScanline(y); Scanline pAlphaScan = pAlphaWriteAccess->GetScanline(y); +#else + Scanline pScan = pWriteAccess->GetScanline(nHeight-1-y); + Scanline pAlphaScan = pAlphaWriteAccess->GetScanline(nHeight-1-y); +#endif for( long x = 0; x < nWidth; ++x ) { *pScan++ = pBuffer[nCurPos];