1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <vcl/opengl/OpenGLHelper.hxx>
24 #include "vcl/bitmap.hxx"
25 #include "vcl/checksum.hxx"
26 #include "vcl/outdev.hxx"
27 #include "vcl/salbtype.hxx"
31 #include "opengl/zone.hxx"
32 #include "opengl/program.hxx"
33 #include "opengl/salbmp.hxx"
35 #include "opengl/FixedTextureAtlas.hxx"
40 static bool isValidBitCount( sal_uInt16 nBitCount
)
42 return (nBitCount
== 1) || (nBitCount
== 4) || (nBitCount
== 8) || (nBitCount
== 16) || (nBitCount
== 24) || (nBitCount
== 32);
45 static std::vector
<std::unique_ptr
<FixedTextureAtlasManager
>> sTextureAtlases
;
49 OpenGLSalBitmap::OpenGLSalBitmap()
51 , mbDirtyTexture(true)
61 OpenGLSalBitmap::~OpenGLSalBitmap()
64 SAL_INFO( "vcl.opengl", "~OpenGLSalBitmap" );
67 bool OpenGLSalBitmap::Create( const OpenGLTexture
& rTex
, long nX
, long nY
, long nWidth
, long nHeight
)
69 static const BitmapPalette aEmptyPalette
;
73 SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create from FBO: [" << nX
<< ", " << nY
<< "] " << nWidth
<< "x" << nHeight
);
80 // TODO Check the framebuffer configuration
82 maPalette
= aEmptyPalette
;
85 maTexture
= OpenGLTexture( rTex
, nX
, nY
, nWidth
, nHeight
);
87 maTexture
= OpenGLTexture( nX
, nY
, nWidth
, nHeight
);
88 mbDirtyTexture
= false;
89 SAL_INFO( "vcl.opengl", "Created texture " << maTexture
.Id() );
94 bool OpenGLSalBitmap::Create( const Size
& rSize
, sal_uInt16 nBits
, const BitmapPalette
& rBitmapPalette
)
99 SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create with size: " << rSize
);
101 if( !isValidBitCount( nBits
) )
103 maPalette
= rBitmapPalette
;
105 mnWidth
= mnBufWidth
= rSize
.Width();
106 mnHeight
= mnBufHeight
= rSize
.Height();
110 bool OpenGLSalBitmap::Create( const SalBitmap
& rSalBmp
)
112 return Create( rSalBmp
, rSalBmp
.GetBitCount() );
115 bool OpenGLSalBitmap::Create( const SalBitmap
& rSalBmp
, SalGraphics
* pGraphics
)
117 return Create( rSalBmp
, pGraphics
? pGraphics
->GetBitCount() : rSalBmp
.GetBitCount() );
120 bool OpenGLSalBitmap::Create( const SalBitmap
& rSalBmp
, sal_uInt16 nNewBitCount
)
124 // check that carefully only in the debug mode
125 assert(dynamic_cast<const OpenGLSalBitmap
*>(&rSalBmp
));
127 const OpenGLSalBitmap
& rSourceBitmap
= static_cast<const OpenGLSalBitmap
&>(rSalBmp
);
129 SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::Create from BMP: " << rSourceBitmap
.mnWidth
<< "x" << rSourceBitmap
.mnHeight
);
131 if( isValidBitCount( nNewBitCount
) )
133 // TODO: lfrb: What about the pending operations?!
134 mnBits
= nNewBitCount
;
135 mnBytesPerRow
= rSourceBitmap
.mnBytesPerRow
;
136 mnWidth
= rSourceBitmap
.mnWidth
;
137 mnHeight
= rSourceBitmap
.mnHeight
;
138 mnBufWidth
= rSourceBitmap
.mnBufWidth
;
139 mnBufHeight
= rSourceBitmap
.mnBufHeight
;
140 maPalette
= rSourceBitmap
.maPalette
;
141 // execute any pending operations on the source bitmap
142 maTexture
= rSourceBitmap
.GetTexture();
143 mbDirtyTexture
= false;
145 // be careful here, we are share & reference-count the
146 // maUserBuffer, BUT this Create() is called from
147 // Bitmap::ImplMakeUnique().
148 // Consequently, there might be cases when this needs to be made
149 // unique later (when we don't do that right away here), like when
150 // using the BitmapWriteAccess.
151 maUserBuffer
= rSourceBitmap
.maUserBuffer
;
158 bool OpenGLSalBitmap::Create( const ::com::sun::star::uno::Reference
< ::com::sun::star::rendering::XBitmapCanvas
>& /*xBitmapCanvas*/, Size
& /*rSize*/, bool /*bMask*/ )
160 // TODO Is this method needed?
164 OpenGLTexture
& OpenGLSalBitmap::GetTexture() const
166 OpenGLSalBitmap
* pThis
= const_cast<OpenGLSalBitmap
*>(this);
167 if( !maTexture
|| mbDirtyTexture
)
168 pThis
->CreateTexture();
169 else if( !maPendingOps
.empty() )
170 pThis
->ExecuteOperations();
171 SAL_INFO( "vcl.opengl", "Got texture " << maTexture
.Id() );
172 return pThis
->maTexture
;
175 void OpenGLSalBitmap::Destroy()
179 SAL_INFO( "vcl.opengl", "Destroy OpenGLSalBitmap" );
180 maPendingOps
.clear();
181 maTexture
= OpenGLTexture();
182 maUserBuffer
.reset();
185 bool OpenGLSalBitmap::AllocateUserData()
187 SAL_INFO( "vcl.opengl", "OpenGLSalBitmap::AllocateUserData" );
189 if( mnWidth
&& mnHeight
)
195 case 1: mnBytesPerRow
= (mnWidth
+ 7) >> 3; break;
196 case 4: mnBytesPerRow
= (mnWidth
+ 1) >> 1; break;
197 case 8: mnBytesPerRow
= mnWidth
; break;
198 case 16: mnBytesPerRow
= mnWidth
<< 1; break;
199 case 24: mnBytesPerRow
= (mnWidth
<< 1) + mnWidth
; break;
200 case 32: mnBytesPerRow
= mnWidth
<< 2; break;
202 OSL_FAIL("vcl::OpenGLSalBitmap::AllocateUserData(), illegal bitcount!");
207 if (mnBytesPerRow
!= 0 && mnHeight
&&
208 mnBytesPerRow
<= std::numeric_limits
<sal_uInt32
>::max() / mnHeight
)
212 maUserBuffer
.reset( new sal_uInt8
[static_cast<sal_uInt32
>(mnBytesPerRow
) * mnHeight
] );
215 catch (const std::bad_alloc
&) {}
219 SAL_WARN("vcl.opengl", "bad alloc " << mnBytesPerRow
<< "x" << mnHeight
);
220 maUserBuffer
.reset( static_cast<sal_uInt8
*>(NULL
) );
226 for (size_t i
= 0; i
< size_t(mnBytesPerRow
* mnHeight
); i
++)
227 maUserBuffer
.get()[i
] = (i
& 0xFF);
231 return maUserBuffer
.get() != 0;
236 class ImplPixelFormat
241 static ImplPixelFormat
* GetFormat( sal_uInt16 nBits
, const BitmapPalette
& rPalette
);
243 virtual void StartLine( sal_uInt8
* pLine
) { mpData
= pLine
; }
244 virtual const BitmapColor
& ReadPixel() = 0;
245 virtual ~ImplPixelFormat() { }
248 class ImplPixelFormat8
: public ImplPixelFormat
251 const BitmapPalette
& mrPalette
;
254 ImplPixelFormat8( const BitmapPalette
& rPalette
)
255 : mrPalette( rPalette
)
258 virtual const BitmapColor
& ReadPixel() SAL_OVERRIDE
260 assert( mrPalette
.GetEntryCount() > *mpData
);
261 return mrPalette
[ *mpData
++ ];
265 class ImplPixelFormat4
: public ImplPixelFormat
268 const BitmapPalette
& mrPalette
;
273 ImplPixelFormat4( const BitmapPalette
& rPalette
)
274 : mrPalette( rPalette
)
279 virtual void StartLine( sal_uInt8
* pLine
) SAL_OVERRIDE
285 virtual const BitmapColor
& ReadPixel() SAL_OVERRIDE
287 sal_uInt32 nIdx
= ( mpData
[mnX
>> 1] >> mnShift
) & 0x0f;
288 assert( mrPalette
.GetEntryCount() > nIdx
);
289 const BitmapColor
& rColor
= mrPalette
[nIdx
];
296 class ImplPixelFormat1
: public ImplPixelFormat
299 const BitmapPalette
& mrPalette
;
303 ImplPixelFormat1( const BitmapPalette
& rPalette
)
304 : mrPalette(rPalette
)
308 virtual void StartLine( sal_uInt8
* pLine
) SAL_OVERRIDE
313 virtual const BitmapColor
& ReadPixel() SAL_OVERRIDE
315 const BitmapColor
& rColor
= mrPalette
[ (mpData
[mnX
>> 3 ] >> ( 7 - ( mnX
& 7 ) )) & 1];
321 ImplPixelFormat
* ImplPixelFormat::GetFormat( sal_uInt16 nBits
, const BitmapPalette
& rPalette
)
325 case 1: return new ImplPixelFormat1( rPalette
);
326 case 4: return new ImplPixelFormat4( rPalette
);
327 case 8: return new ImplPixelFormat8( rPalette
);
333 void lclInstantiateTexture(OpenGLTexture
& rTexture
, const int nWidth
, const int nHeight
,
334 const GLenum nFormat
, const GLenum nType
, sal_uInt8
* pData
)
336 if (nWidth
== nHeight
)
338 if (sTextureAtlases
.empty())
340 sTextureAtlases
.push_back(std::unique_ptr
<FixedTextureAtlasManager
>(new FixedTextureAtlasManager(8, 8, 16)));
341 sTextureAtlases
.push_back(std::unique_ptr
<FixedTextureAtlasManager
>(new FixedTextureAtlasManager(8, 8, 24)));
342 sTextureAtlases
.push_back(std::unique_ptr
<FixedTextureAtlasManager
>(new FixedTextureAtlasManager(8, 8, 32)));
343 sTextureAtlases
.push_back(std::unique_ptr
<FixedTextureAtlasManager
>(new FixedTextureAtlasManager(8, 8, 48)));
344 sTextureAtlases
.push_back(std::unique_ptr
<FixedTextureAtlasManager
>(new FixedTextureAtlasManager(8, 8, 64)));
346 for (size_t i
= 0; i
< sTextureAtlases
.size(); i
++)
348 if (nWidth
== sTextureAtlases
[i
]->GetSubtextureSize())
350 rTexture
= sTextureAtlases
[i
]->InsertBuffer(nWidth
, nHeight
, nFormat
, nType
, pData
);
355 rTexture
= OpenGLTexture (nWidth
, nHeight
, nFormat
, nType
, pData
);
360 Size
OpenGLSalBitmap::GetSize() const
364 std::deque
< OpenGLSalBitmapOp
* >::const_iterator it
= maPendingOps
.begin();
365 Size
aSize( mnWidth
, mnHeight
);
367 while( it
!= maPendingOps
.end() )
368 (*it
++)->GetSize( aSize
);
373 void OpenGLSalBitmap::ExecuteOperations()
376 while( !maPendingOps
.empty() )
378 OpenGLSalBitmapOp
* pOp
= maPendingOps
.front();
380 maPendingOps
.pop_front();
384 GLuint
OpenGLSalBitmap::CreateTexture()
386 SAL_INFO( "vcl.opengl", "::CreateTexture" );
387 GLenum nFormat
= GL_RGBA
;
388 GLenum nType
= GL_UNSIGNED_BYTE
;
389 sal_uInt8
* pData( NULL
);
390 bool bAllocated( false );
392 if( maUserBuffer
.get() != 0 )
394 if( mnBits
== 16 || mnBits
== 24 || mnBits
== 32 )
396 // no conversion needed for truecolor
397 pData
= maUserBuffer
.get();
401 case 16: nFormat
= GL_RGB
;
402 nType
= GL_UNSIGNED_SHORT_5_6_5
;
404 case 24: nFormat
= GL_RGB
;
405 nType
= GL_UNSIGNED_BYTE
;
407 case 32: nFormat
= GL_RGBA
;
408 nType
= GL_UNSIGNED_BYTE
;
412 else if( mnBits
== 8 && maPalette
.IsGreyPalette() )
414 // no conversion needed for grayscale
415 pData
= maUserBuffer
.get();
416 nFormat
= GL_LUMINANCE
;
417 nType
= GL_UNSIGNED_BYTE
;
421 // convert to 32 bits RGBA using palette
422 pData
= new sal_uInt8
[mnBufHeight
* mnBufWidth
* 4];
425 nType
= GL_UNSIGNED_BYTE
;
427 ImplPixelFormat
* pSrcFormat
= ImplPixelFormat::GetFormat( mnBits
, maPalette
);
428 sal_uInt8
* pSrcData
= maUserBuffer
.get();
429 sal_uInt8
* pDstData
= pData
;
431 sal_uInt32 nY
= mnBufHeight
;
434 pSrcFormat
->StartLine( pSrcData
);
436 sal_uInt32 nX
= mnBufWidth
;
439 const BitmapColor
& c
= pSrcFormat
->ReadPixel();
441 *pDstData
++ = c
.GetRed();
442 *pDstData
++ = c
.GetGreen();
443 *pDstData
++ = c
.GetBlue();
447 pSrcData
+= mnBytesPerRow
;
454 lclInstantiateTexture(maTexture
, mnBufWidth
, mnBufHeight
, nFormat
, nType
, pData
);
456 SAL_INFO( "vcl.opengl", "Created texture " << maTexture
.Id() );
462 mbDirtyTexture
= false;
465 return maTexture
.Id();
468 bool OpenGLSalBitmap::ReadTexture()
470 sal_uInt8
* pData
= maUserBuffer
.get();
472 SAL_INFO( "vcl.opengl", "::ReadTexture " << mnWidth
<< "x" << mnHeight
);
477 if (mnBits
== 8 || mnBits
== 16 || mnBits
== 24 || mnBits
== 32)
479 GLenum nFormat
= GL_RGBA
;
480 GLenum nType
= GL_UNSIGNED_BYTE
;
484 case 8: nFormat
= GL_LUMINANCE
;
485 nType
= GL_UNSIGNED_BYTE
;
487 case 16: nFormat
= GL_RGB
;
488 nType
= GL_UNSIGNED_SHORT_5_6_5
;
490 case 24: nFormat
= GL_RGB
;
491 nType
= GL_UNSIGNED_BYTE
;
493 case 32: nFormat
= GL_RGBA
;
494 nType
= GL_UNSIGNED_BYTE
;
499 maTexture
.Read(nFormat
, nType
, pData
);
500 mnBufWidth
= mnWidth
;
501 mnBufHeight
= mnHeight
;
504 else if (mnBits
== 1)
505 { // convert buffers from 24-bit RGB to 1-bit Mask
506 std::vector
<sal_uInt8
> aBuffer(mnWidth
* mnHeight
* 3);
508 sal_uInt8
* pBuffer
= aBuffer
.data();
509 maTexture
.Read(GL_RGB
, GL_UNSIGNED_BYTE
, pBuffer
);
514 sal_uInt8
* pCurrent
= pBuffer
;
516 for (int y
= 0; y
< mnHeight
; ++y
)
518 for (int x
= 0; x
< mnWidth
; ++x
)
527 sal_uInt8 nR
= *pCurrent
++;
528 sal_uInt8 nG
= *pCurrent
++;
529 sal_uInt8 nB
= *pCurrent
++;
531 if (nR
> 0 && nG
> 0 && nB
> 0)
533 pData
[nIndex
] |= (1 << nShift
);
541 mnBufWidth
= mnWidth
;
542 mnBufHeight
= mnHeight
;
546 SAL_WARN("vcl.opengl", "::ReadTexture - tx:" << maTexture
.Id() << " @ "
547 << mnWidth
<< "x" << mnHeight
<< "- unimplemented bit depth: "
553 sal_uInt16
OpenGLSalBitmap::GetBitCount() const
558 bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture
& rInputTexture
, ChecksumType
& rChecksum
) const
560 OUString
FragShader("areaHashCRC64TFragmentShader");
562 static const OpenGLTexture
aCRCTableTexture(512, 1, GL_RGBA
, GL_UNSIGNED_BYTE
,
563 vcl_get_crc64_table());
567 int nWidth
= rInputTexture
.GetWidth();
568 int nHeight
= rInputTexture
.GetHeight();
570 OpenGLProgram
* pProgram
= mpContext
->UseProgram("textureVertexShader", FragShader
);
574 int nNewWidth
= ceil( nWidth
/ 4.0 );
575 int nNewHeight
= ceil( nHeight
/ 4.0 );
577 OpenGLTexture aFirstPassTexture
= OpenGLTexture(nNewWidth
, nNewHeight
);
578 OpenGLFramebuffer
* pFramebuffer
= mpContext
->AcquireFramebuffer(aFirstPassTexture
);
580 pProgram
->SetUniform1f( "xstep", 1.0 / mnWidth
);
581 pProgram
->SetUniform1f( "ystep", 1.0 / mnHeight
);
583 pProgram
->SetTexture("crc_table", (OpenGLTexture
&)(aCRCTableTexture
));
584 pProgram
->SetTexture("sampler", rInputTexture
);
585 pProgram
->DrawTexture(rInputTexture
);
588 OpenGLContext::ReleaseFramebuffer(pFramebuffer
);
595 nWidth
= aFirstPassTexture
.GetWidth();
596 nHeight
= aFirstPassTexture
.GetHeight();
598 pProgram
= mpContext
->UseProgram("textureVertexShader", FragShader
);
602 nNewWidth
= ceil( nWidth
/ 4.0 );
603 nNewHeight
= ceil( nHeight
/ 4.0 );
605 OpenGLTexture aSecondPassTexture
= OpenGLTexture(nNewWidth
, nNewHeight
);
606 pFramebuffer
= mpContext
->AcquireFramebuffer(aSecondPassTexture
);
608 pProgram
->SetUniform1f( "xstep", 1.0 / mnWidth
);
609 pProgram
->SetUniform1f( "ystep", 1.0 / mnHeight
);
611 pProgram
->SetTexture("crc_table", (OpenGLTexture
&)(aCRCTableTexture
));
612 pProgram
->SetTexture("sampler", aFirstPassTexture
);
613 pProgram
->DrawTexture(aFirstPassTexture
);
616 OpenGLContext::ReleaseFramebuffer(pFramebuffer
);
621 OpenGLTexture
& aFinalTexture
= aSecondPassTexture
;
622 std::vector
<sal_uInt8
> aBuf( aFinalTexture
.GetWidth() * aFinalTexture
.GetHeight() * 4 );
623 aFinalTexture
.Read(GL_RGBA
, GL_UNSIGNED_BYTE
, aBuf
.data());
625 ChecksumType nCrc
= vcl_get_checksum(0, aBuf
.data(), aBuf
.size());
631 void OpenGLSalBitmap::updateChecksum() const
636 OpenGLSalBitmap
* pThis
= const_cast<OpenGLSalBitmap
*>(this);
640 pThis
->CreateTexture();
643 OpenGLTexture
& rInputTexture
= pThis
->maTexture
;
644 int nWidth
= rInputTexture
.GetWidth();
645 int nHeight
= rInputTexture
.GetHeight();
647 if( (nWidth
* nHeight
) < (1024*768) || nWidth
< 128 || nHeight
< 128 )
649 SalBitmap::updateChecksum();
653 pThis
->mbChecksumValid
= calcChecksumGL(rInputTexture
, pThis
->mnChecksum
);
657 rtl::Reference
<OpenGLContext
> OpenGLSalBitmap::GetBitmapContext()
659 return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
662 void OpenGLSalBitmap::makeCurrent()
664 ImplSVData
* pSVData
= ImplGetSVData();
666 // TODO: make sure we can really use the last used context
667 OpenGLContext
*pContext
= pSVData
->maGDIData
.mpLastContext
;
668 while( pContext
&& !pContext
->isInitialized() )
669 pContext
= pContext
->mpPrevContext
;
671 mpContext
= pContext
;
673 mpContext
= GetBitmapContext();
674 assert(mpContext
.is() && "Couldn't get an OpenGL context");
675 mpContext
->makeCurrent();
678 BitmapBuffer
* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode
)
682 if( nMode
!= BITMAP_INFO_ACCESS
)
684 if( !maUserBuffer
.get() )
686 if( !AllocateUserData() )
688 if( maTexture
&& !ReadTexture() )
692 if( !maPendingOps
.empty() )
694 SAL_INFO( "vcl.opengl", "** Creating texture and reading it back immediately" );
695 if( !CreateTexture() || !AllocateUserData() || !ReadTexture() )
700 // maUserBuffer must be unique when we are doing the write access
701 if (nMode
== BITMAP_WRITE_ACCESS
&& maUserBuffer
&& !maUserBuffer
.unique())
703 basebmp::RawMemorySharedArray
aBuffer(maUserBuffer
);
705 maUserBuffer
.reset();
707 memcpy(maUserBuffer
.get(), aBuffer
.get(), static_cast<sal_uInt32
>(mnBytesPerRow
) * mnHeight
);
710 BitmapBuffer
* pBuffer
= new BitmapBuffer
;
711 pBuffer
->mnWidth
= mnWidth
;
712 pBuffer
->mnHeight
= mnHeight
;
713 pBuffer
->maPalette
= maPalette
;
714 pBuffer
->mnScanlineSize
= mnBytesPerRow
;
715 pBuffer
->mpBits
= maUserBuffer
.get();
716 pBuffer
->mnBitCount
= mnBits
;
719 case 1: pBuffer
->mnFormat
= BMP_FORMAT_1BIT_MSB_PAL
; break;
720 case 4: pBuffer
->mnFormat
= BMP_FORMAT_4BIT_MSN_PAL
; break;
721 case 8: pBuffer
->mnFormat
= BMP_FORMAT_8BIT_PAL
; break;
722 case 16: pBuffer
->mnFormat
= BMP_FORMAT_16BIT_TC_MSB_MASK
;
723 pBuffer
->maColorMask
= ColorMask( 0xf800, 0x07e0, 0x001f );
725 case 24: pBuffer
->mnFormat
= BMP_FORMAT_24BIT_TC_RGB
; break;
726 case 32: pBuffer
->mnFormat
= BMP_FORMAT_32BIT_TC_RGBA
;
727 pBuffer
->maColorMask
= ColorMask( 0xff000000, 0x00ff0000, 0x0000ff00 );
734 void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer
* pBuffer
, BitmapAccessMode nMode
)
738 if( nMode
== BITMAP_WRITE_ACCESS
)
740 maTexture
= OpenGLTexture();
741 mbDirtyTexture
= true;
742 mbChecksumValid
= false;
744 // The palette is modified on read during the BitmapWriteAccess,
745 // but of course, often it is not modified; interesting.
746 maPalette
= pBuffer
->maPalette
;
748 // Are there any more ground movements underneath us ?
749 assert( pBuffer
->mnWidth
== mnWidth
);
750 assert( pBuffer
->mnHeight
== mnHeight
);
751 assert( pBuffer
->mnBitCount
== mnBits
);
756 bool OpenGLSalBitmap::GetSystemData( BitmapSystemData
& /*rData*/ )
758 SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** GetSystemData" );
760 // TODO Implement for ANDROID/OSX/IOS/WIN32
761 X11SalBitmap rBitmap
;
762 BitmapBuffer
* pBuffer
;
764 rBitmap
.Create( GetSize(), mnBits
, maPalette
);
765 pBuffer
= rBitmap
.AcquireBuffer( false );
766 if( pBuffer
== NULL
)
769 if( !maUserBuffer
.get() )
771 if( !AllocateUserData() || !ReadTexture() )
773 rBitmap
.ReleaseBuffer( pBuffer
, false );
778 // TODO Might be more efficient to add a static method to SalBitmap
779 // to get system data from a buffer
780 memcpy( pBuffer
->mpBits
, maUserBuffer
.get(), mnBytesPerRow
* mnHeight
);
782 rBitmap
.ReleaseBuffer( pBuffer
, false );
783 return rBitmap
.GetSystemData( rData
);
789 bool OpenGLSalBitmap::Crop( const Rectangle
& /*rRectPixel*/ )
794 bool OpenGLSalBitmap::Erase( const ::Color
& /*rFillColor*/ )
799 bool OpenGLSalBitmap::Replace( const Color
& rSearchColor
, const Color
& rReplaceColor
, sal_uLong nTol
)
803 OpenGLFramebuffer
* pFramebuffer
;
804 OpenGLProgram
* pProgram
;
808 pProgram
= mpContext
->UseProgram( "textureVertexShader",
809 "replaceColorFragmentShader" );
813 OpenGLTexture aNewTex
= OpenGLTexture( mnWidth
, mnHeight
);
814 pFramebuffer
= mpContext
->AcquireFramebuffer( aNewTex
);
816 pProgram
->SetTexture( "sampler", maTexture
);
817 pProgram
->SetColor( "search_color", rSearchColor
);
818 pProgram
->SetColor( "replace_color", rReplaceColor
);
819 pProgram
->SetUniform1f( "epsilon", nTol
/ 255.0f
);
820 pProgram
->DrawTexture( maTexture
);
823 OpenGLContext::ReleaseFramebuffer( pFramebuffer
);
830 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */