2012-01-31 01:07:48 +01:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2015-08-10 14:04:31 -05:00
|
|
|
#include <sal/config.h>
|
2012-01-31 01:07:48 +01:00
|
|
|
|
|
|
|
#include <basegfx/tools/canvastools.hxx>
|
|
|
|
#include <basegfx/tools/unopolypolygon.hxx>
|
|
|
|
#include <com/sun/star/lang/NoSupportException.hpp>
|
|
|
|
#include <com/sun/star/rendering/XColorSpace.hpp>
|
|
|
|
#include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
|
2015-08-10 14:04:31 -05:00
|
|
|
#include <com/sun/star/uno/Reference.hxx>
|
|
|
|
#include <osl/mutex.hxx>
|
|
|
|
#include <rtl/instance.hxx>
|
2012-01-31 01:07:48 +01:00
|
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
2015-08-10 14:04:31 -05:00
|
|
|
#include <vcl/canvastools.hxx>
|
2014-08-08 01:55:33 +02:00
|
|
|
#include <vcl/opengl/OpenGLHelper.hxx>
|
2015-08-10 14:04:31 -05:00
|
|
|
#include <vcl/syschild.hxx>
|
|
|
|
#include <vcl/sysdata.hxx>
|
|
|
|
|
|
|
|
#include "ogl_spritedevicehelper.hxx"
|
|
|
|
#include "ogl_spritecanvas.hxx"
|
|
|
|
#include "ogl_canvasbitmap.hxx"
|
|
|
|
#include "ogl_canvastools.hxx"
|
|
|
|
#include "ogl_canvascustomsprite.hxx"
|
|
|
|
#include "ogl_texturecache.hxx"
|
2012-01-31 01:07:48 +01:00
|
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
|
|
|
|
static void initContext()
|
|
|
|
{
|
|
|
|
// need the backside for mirror effects
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
|
|
|
|
// no perspective, we're 2D
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
// misc preferences
|
|
|
|
glEnable(GL_POINT_SMOOTH);
|
|
|
|
glEnable(GL_LINE_SMOOTH);
|
|
|
|
glEnable(GL_POLYGON_SMOOTH);
|
|
|
|
glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
|
|
|
|
glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
|
|
|
|
glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
|
|
|
|
glShadeModel(GL_FLAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void initTransformation(const ::Size& rSize, bool bMirror=false)
|
|
|
|
{
|
|
|
|
// use whole window
|
|
|
|
glViewport( 0,0,
|
|
|
|
(GLsizei)rSize.Width(),
|
|
|
|
(GLsizei)rSize.Height() );
|
|
|
|
|
|
|
|
// model coordinate system is already in device pixel
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslated(-1.0, (bMirror ? -1.0 : 1.0), 0.0);
|
|
|
|
glScaled( 2.0 / rSize.Width(),
|
|
|
|
(bMirror ? 2.0 : -2.0) / rSize.Height(),
|
|
|
|
1.0 );
|
|
|
|
|
|
|
|
// clear to black
|
|
|
|
glClearColor(0,0,0,0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace oglcanvas
|
|
|
|
{
|
|
|
|
|
|
|
|
SpriteDeviceHelper::SpriteDeviceHelper() :
|
|
|
|
mpDevice(NULL),
|
|
|
|
mpSpriteCanvas(NULL),
|
|
|
|
maActiveSprites(),
|
|
|
|
maLastUpdate(),
|
|
|
|
mpTextureCache(new TextureCache()),
|
|
|
|
mnLinearTwoColorGradientProgram(0),
|
|
|
|
mnLinearMultiColorGradientProgram(0),
|
|
|
|
mnRadialTwoColorGradientProgram(0),
|
|
|
|
mnRadialMultiColorGradientProgram(0),
|
|
|
|
mnRectangularTwoColorGradientProgram(0),
|
2015-09-08 11:46:13 +01:00
|
|
|
mnRectangularMultiColorGradientProgram(0),
|
|
|
|
mxContext(OpenGLContext::Create())
|
2012-01-31 01:07:48 +01:00
|
|
|
{}
|
|
|
|
|
2014-08-11 21:04:20 +02:00
|
|
|
SpriteDeviceHelper::~SpriteDeviceHelper()
|
2015-09-08 15:57:55 +01:00
|
|
|
{ mxContext->dispose(); }
|
2014-08-11 21:04:20 +02:00
|
|
|
|
2014-09-23 11:20:40 +02:00
|
|
|
void SpriteDeviceHelper::init( vcl::Window& rWindow,
|
2012-01-31 01:07:48 +01:00
|
|
|
SpriteCanvas& rSpriteCanvas,
|
|
|
|
const awt::Rectangle& rViewArea )
|
|
|
|
{
|
|
|
|
mpSpriteCanvas = &rSpriteCanvas;
|
|
|
|
|
|
|
|
rSpriteCanvas.setWindow(
|
|
|
|
uno::Reference<awt::XWindow2>(
|
|
|
|
VCLUnoHelper::GetInterface(&rWindow),
|
|
|
|
uno::UNO_QUERY_THROW) );
|
|
|
|
|
2015-09-08 11:46:13 +01:00
|
|
|
mxContext->requestLegacyContext();
|
|
|
|
mxContext->init(&rWindow);
|
2014-08-08 01:55:33 +02:00
|
|
|
// init window context
|
|
|
|
initContext();
|
2014-08-07 00:01:02 +02:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
mnLinearMultiColorGradientProgram =
|
2014-08-16 05:39:31 +02:00
|
|
|
OpenGLHelper::LoadShaders("dummyVertexShader", "linearMultiColorGradientFragmentShader");
|
2014-08-07 00:01:02 +02:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
mnLinearTwoColorGradientProgram =
|
2014-08-16 05:39:31 +02:00
|
|
|
OpenGLHelper::LoadShaders("dummyVertexShader", "linearTwoColorGradientFragmentShader");
|
2014-08-07 00:01:02 +02:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
mnRadialMultiColorGradientProgram =
|
2014-08-16 05:39:31 +02:00
|
|
|
OpenGLHelper::LoadShaders("dummyVertexShader", "radialMultiColorGradientFragmentShader");
|
2014-08-07 00:01:02 +02:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
mnRadialTwoColorGradientProgram =
|
2014-08-16 05:39:31 +02:00
|
|
|
OpenGLHelper::LoadShaders("dummyVertexShader", "radialTwoColorGradientFragmentShader");
|
2014-08-07 00:01:02 +02:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
mnRectangularMultiColorGradientProgram =
|
2014-08-16 05:39:31 +02:00
|
|
|
OpenGLHelper::LoadShaders("dummyVertexShader", "rectangularMultiColorGradientFragmentShader");
|
2012-01-31 01:07:48 +01:00
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
mnRectangularTwoColorGradientProgram =
|
2014-08-16 05:39:31 +02:00
|
|
|
OpenGLHelper::LoadShaders("dummyVertexShader", "rectangularTwoColorGradientFragmentShader");
|
2012-01-31 01:07:48 +01:00
|
|
|
|
2015-09-08 11:46:13 +01:00
|
|
|
mxContext->makeCurrent();
|
2012-01-31 01:07:48 +01:00
|
|
|
|
|
|
|
notifySizeUpdate(rViewArea);
|
|
|
|
// TODO(E3): check for GL_ARB_imaging extension
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::disposing()
|
|
|
|
{
|
|
|
|
// release all references
|
|
|
|
mpSpriteCanvas = NULL;
|
|
|
|
mpDevice = NULL;
|
|
|
|
mpTextureCache.reset();
|
|
|
|
|
2015-09-08 11:46:13 +01:00
|
|
|
if( mxContext->isInitialized() )
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
|
|
|
glDeleteProgram( mnRectangularTwoColorGradientProgram );
|
|
|
|
glDeleteProgram( mnRectangularMultiColorGradientProgram );
|
|
|
|
glDeleteProgram( mnRadialTwoColorGradientProgram );
|
|
|
|
glDeleteProgram( mnRadialMultiColorGradientProgram );
|
|
|
|
glDeleteProgram( mnLinearTwoColorGradientProgram );
|
|
|
|
glDeleteProgram( mnLinearMultiColorGradientProgram );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
geometry::RealSize2D SpriteDeviceHelper::getPhysicalResolution()
|
|
|
|
{
|
2015-09-08 11:46:13 +01:00
|
|
|
if( !mxContext->isInitialized() )
|
2012-01-31 01:07:48 +01:00
|
|
|
return ::canvas::tools::createInfiniteSize2D(); // we're disposed
|
|
|
|
|
|
|
|
// Map a one-by-one millimeter box to pixel
|
2015-09-08 11:46:13 +01:00
|
|
|
SystemChildWindow* pChildWindow = mxContext->getChildWindow();
|
2014-08-08 01:55:33 +02:00
|
|
|
const MapMode aOldMapMode( pChildWindow->GetMapMode() );
|
|
|
|
pChildWindow->SetMapMode( MapMode(MAP_MM) );
|
|
|
|
const Size aPixelSize( pChildWindow->LogicToPixel(Size(1,1)) );
|
|
|
|
pChildWindow->SetMapMode( aOldMapMode );
|
2012-01-31 01:07:48 +01:00
|
|
|
|
2015-04-28 23:09:13 +03:00
|
|
|
return vcl::unotools::size2DFromSize( aPixelSize );
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
geometry::RealSize2D SpriteDeviceHelper::getPhysicalSize()
|
|
|
|
{
|
2015-09-08 11:46:13 +01:00
|
|
|
if( !mxContext->isInitialized() )
|
2012-01-31 01:07:48 +01:00
|
|
|
return ::canvas::tools::createInfiniteSize2D(); // we're disposed
|
|
|
|
|
|
|
|
// Map the pixel dimensions of the output window to millimeter
|
2015-09-08 11:46:13 +01:00
|
|
|
SystemChildWindow* pChildWindow = mxContext->getChildWindow();
|
2014-08-08 01:55:33 +02:00
|
|
|
const MapMode aOldMapMode( pChildWindow->GetMapMode() );
|
|
|
|
pChildWindow->SetMapMode( MapMode(MAP_MM) );
|
|
|
|
const Size aLogSize( pChildWindow->PixelToLogic(pChildWindow->GetOutputSizePixel()) );
|
|
|
|
pChildWindow->SetMapMode( aOldMapMode );
|
2012-01-31 01:07:48 +01:00
|
|
|
|
2015-04-28 23:09:13 +03:00
|
|
|
return vcl::unotools::size2DFromSize( aLogSize );
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< rendering::XLinePolyPolygon2D > SpriteDeviceHelper::createCompatibleLinePolyPolygon(
|
|
|
|
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
|
|
|
const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
|
|
|
|
{
|
|
|
|
// disposed?
|
|
|
|
if( !mpSpriteCanvas )
|
|
|
|
return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
|
|
|
|
|
|
|
|
return uno::Reference< rendering::XLinePolyPolygon2D >(
|
|
|
|
new ::basegfx::unotools::UnoPolyPolygon(
|
|
|
|
::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points )));
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< rendering::XBezierPolyPolygon2D > SpriteDeviceHelper::createCompatibleBezierPolyPolygon(
|
|
|
|
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
|
|
|
const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
|
|
|
|
{
|
|
|
|
// disposed?
|
|
|
|
if( !mpSpriteCanvas )
|
|
|
|
return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
|
|
|
|
|
|
|
|
return uno::Reference< rendering::XBezierPolyPolygon2D >(
|
|
|
|
new ::basegfx::unotools::UnoPolyPolygon(
|
|
|
|
::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
|
|
|
|
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
|
|
|
const geometry::IntegerSize2D& size )
|
|
|
|
{
|
|
|
|
// disposed?
|
|
|
|
if( !mpSpriteCanvas )
|
|
|
|
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
|
|
|
|
|
|
|
return uno::Reference< rendering::XBitmap >(
|
|
|
|
new CanvasBitmap( size,
|
|
|
|
mpSpriteCanvas,
|
|
|
|
*this,
|
|
|
|
false ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
|
|
|
|
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
|
|
|
const geometry::IntegerSize2D& /*size*/ )
|
|
|
|
{
|
|
|
|
return uno::Reference< rendering::XVolatileBitmap >();
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
|
|
|
|
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
|
|
|
const geometry::IntegerSize2D& size )
|
|
|
|
{
|
|
|
|
// disposed?
|
|
|
|
if( !mpSpriteCanvas )
|
|
|
|
return uno::Reference< rendering::XBitmap >(); // we're disposed
|
|
|
|
|
|
|
|
return uno::Reference< rendering::XBitmap >(
|
|
|
|
new CanvasBitmap( size,
|
|
|
|
mpSpriteCanvas,
|
|
|
|
*this,
|
|
|
|
true ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
|
|
|
|
const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
|
|
|
|
const geometry::IntegerSize2D& /*size*/ )
|
|
|
|
{
|
|
|
|
return uno::Reference< rendering::XVolatileBitmap >();
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
/** Functor providing a StrictWeakOrdering for XSprites (over
|
|
|
|
priority)
|
|
|
|
*/
|
|
|
|
struct SpriteComparator
|
|
|
|
{
|
|
|
|
bool operator()( const ::rtl::Reference<CanvasCustomSprite>& rLHS,
|
|
|
|
const ::rtl::Reference<CanvasCustomSprite>& rRHS ) const
|
|
|
|
{
|
|
|
|
const double nPrioL( rLHS->getPriority() );
|
|
|
|
const double nPrioR( rRHS->getPriority() );
|
|
|
|
|
|
|
|
// if prios are equal, tie-break on ptr value
|
|
|
|
return nPrioL == nPrioR ? rLHS.get() < rRHS.get() : nPrioL < nPrioR;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-07-02 11:45:45 +02:00
|
|
|
bool SpriteDeviceHelper::showBuffer( bool bIsVisible, bool /*bUpdateAll*/ )
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
|
|
|
// hidden or disposed?
|
2015-09-08 11:46:13 +01:00
|
|
|
if( !bIsVisible || !mxContext->isInitialized() || !mpSpriteCanvas )
|
2012-01-31 01:07:48 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if( !activateWindowContext() )
|
|
|
|
return false;
|
|
|
|
|
2015-09-08 11:46:13 +01:00
|
|
|
SystemChildWindow* pChildWindow = mxContext->getChildWindow();
|
2014-08-08 01:55:33 +02:00
|
|
|
const ::Size& rOutputSize = pChildWindow->GetSizePixel();
|
2012-01-31 01:07:48 +01:00
|
|
|
initTransformation(rOutputSize);
|
|
|
|
|
|
|
|
// render the actual spritecanvas content
|
|
|
|
mpSpriteCanvas->renderRecordedActions();
|
|
|
|
|
|
|
|
// render all sprites (in order of priority) on top of that
|
|
|
|
std::vector< ::rtl::Reference<CanvasCustomSprite> > aSprites;
|
|
|
|
std::copy(maActiveSprites.begin(),
|
|
|
|
maActiveSprites.end(),
|
|
|
|
std::back_insert_iterator<
|
|
|
|
std::vector< ::rtl::Reference< CanvasCustomSprite > > >(aSprites));
|
|
|
|
std::sort(aSprites.begin(),
|
|
|
|
aSprites.end(),
|
|
|
|
SpriteComparator());
|
2015-08-14 21:35:00 -04:00
|
|
|
for( const auto& rSprite : aSprites )
|
|
|
|
rSprite->renderSprite();
|
2012-01-31 01:07:48 +01:00
|
|
|
|
|
|
|
|
|
|
|
// frame counter, other info
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
glTranslated(-1.0, 1.0, 0.0);
|
|
|
|
glScaled( 2.0 / rOutputSize.Width(),
|
|
|
|
-2.0 / rOutputSize.Height(),
|
|
|
|
1.0 );
|
|
|
|
|
|
|
|
const double denominator( maLastUpdate.getElapsedTime() );
|
|
|
|
maLastUpdate.reset();
|
|
|
|
|
|
|
|
const double fps(denominator == 0.0 ? 100.0 : 1.0/denominator);
|
|
|
|
std::vector<double> aVec; aVec.push_back(fps);
|
|
|
|
aVec.push_back(maActiveSprites.size());
|
|
|
|
aVec.push_back(mpTextureCache->getCacheSize());
|
|
|
|
aVec.push_back(mpTextureCache->getCacheMissCount());
|
|
|
|
aVec.push_back(mpTextureCache->getCacheHitCount());
|
|
|
|
renderOSD( aVec, 20 );
|
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
/*
|
|
|
|
* TODO: moggi: fix it!
|
2012-01-31 01:07:48 +01:00
|
|
|
// switch buffer, sync etc.
|
2014-08-08 01:55:33 +02:00
|
|
|
const unx::Window aXWindow=pChildWindow->GetSystemData()->aWindow;
|
2012-01-31 01:07:48 +01:00
|
|
|
unx::glXSwapBuffers(reinterpret_cast<unx::Display*>(mpDisplay),
|
|
|
|
aXWindow);
|
2014-08-08 01:55:33 +02:00
|
|
|
pChildWindow->Show();
|
2012-01-31 01:07:48 +01:00
|
|
|
unx::glXWaitGL();
|
|
|
|
XSync( reinterpret_cast<unx::Display*>(mpDisplay), false );
|
2014-08-08 01:55:33 +02:00
|
|
|
*/
|
2015-09-08 11:46:13 +01:00
|
|
|
mxContext->swapBuffers();
|
2012-01-31 01:07:48 +01:00
|
|
|
|
|
|
|
// flush texture cache, such that it does not build up
|
|
|
|
// indefinitely.
|
|
|
|
// TODO: have max cache size/LRU time in config, prune only on
|
|
|
|
// demand
|
|
|
|
mpTextureCache->prune();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-07-02 11:45:45 +02:00
|
|
|
bool SpriteDeviceHelper::switchBuffer( bool bIsVisible, bool bUpdateAll )
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
|
|
|
// no difference for VCL canvas
|
|
|
|
return showBuffer( bIsVisible, bUpdateAll );
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Any SpriteDeviceHelper::isAccelerated() const
|
|
|
|
{
|
2015-07-21 12:16:45 +02:00
|
|
|
return css::uno::makeAny(false);
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uno::Any SpriteDeviceHelper::getDeviceHandle() const
|
|
|
|
{
|
2015-09-08 11:46:13 +01:00
|
|
|
const SystemChildWindow* pChildWindow = mxContext->getChildWindow();
|
2014-08-08 01:55:33 +02:00
|
|
|
return uno::makeAny( reinterpret_cast< sal_Int64 >(pChildWindow) );
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uno::Any SpriteDeviceHelper::getSurfaceHandle() const
|
|
|
|
{
|
|
|
|
return uno::Any();
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference<rendering::XColorSpace> SpriteDeviceHelper::getColorSpace() const
|
|
|
|
{
|
|
|
|
// always the same
|
|
|
|
return uno::Reference<rendering::XColorSpace>(
|
|
|
|
::canvas::tools::getStdColorSpace(),
|
|
|
|
uno::UNO_QUERY);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
|
|
|
|
{
|
2015-09-08 11:46:13 +01:00
|
|
|
if( mxContext->isInitialized() )
|
2014-08-08 01:55:33 +02:00
|
|
|
{
|
2015-09-08 11:46:13 +01:00
|
|
|
SystemChildWindow* pChildWindow = mxContext->getChildWindow();
|
2014-08-08 01:55:33 +02:00
|
|
|
pChildWindow->setPosSizePixel(
|
2012-01-31 01:07:48 +01:00
|
|
|
0,0,rBounds.Width,rBounds.Height);
|
2014-08-08 01:55:33 +02:00
|
|
|
}
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::dumpScreenContent() const
|
|
|
|
{
|
|
|
|
SAL_INFO("canvas.ogl", BOOST_CURRENT_FUNCTION );
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::show( const ::rtl::Reference< CanvasCustomSprite >& xSprite )
|
|
|
|
{
|
|
|
|
maActiveSprites.insert(xSprite);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::hide( const ::rtl::Reference< CanvasCustomSprite >& xSprite )
|
|
|
|
{
|
|
|
|
maActiveSprites.erase(xSprite);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setupUniforms( unsigned int nProgramId,
|
|
|
|
const ::basegfx::B2DHomMatrix& rTexTransform )
|
|
|
|
{
|
|
|
|
const GLint nTransformLocation = glGetUniformLocation(nProgramId,
|
|
|
|
"m_transform" );
|
|
|
|
// OGL is column-major
|
|
|
|
float aTexTransform[] =
|
|
|
|
{
|
|
|
|
float(rTexTransform.get(0,0)), float(rTexTransform.get(1,0)),
|
|
|
|
float(rTexTransform.get(0,1)), float(rTexTransform.get(1,1)),
|
|
|
|
float(rTexTransform.get(0,2)), float(rTexTransform.get(1,2))
|
|
|
|
};
|
|
|
|
glUniformMatrix3x2fv(nTransformLocation,1,false,aTexTransform);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setupUniforms( unsigned int nProgramId,
|
|
|
|
const rendering::ARGBColor* pColors,
|
|
|
|
const uno::Sequence< double >& rStops,
|
|
|
|
const ::basegfx::B2DHomMatrix& rTexTransform )
|
|
|
|
{
|
|
|
|
glUseProgram(nProgramId);
|
|
|
|
|
|
|
|
GLuint nColorsTexture;
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glGenTextures(1, &nColorsTexture);
|
|
|
|
glBindTexture(GL_TEXTURE_1D, nColorsTexture);
|
|
|
|
|
|
|
|
const sal_Int32 nColors=rStops.getLength();
|
|
|
|
glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, nColors, 0, GL_RGBA, GL_DOUBLE, pColors );
|
|
|
|
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
|
|
|
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
|
|
|
|
|
|
|
GLuint nStopsTexture;
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
|
glGenTextures(1, &nStopsTexture);
|
|
|
|
glBindTexture(GL_TEXTURE_1D, nStopsTexture);
|
|
|
|
|
|
|
|
glTexImage1D( GL_TEXTURE_1D, 0, GL_ALPHA, nColors, 0, GL_ALPHA, GL_DOUBLE, rStops.getConstArray() );
|
|
|
|
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
|
|
|
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
|
|
|
|
|
|
|
const GLint nColorArrayLocation = glGetUniformLocation(nProgramId,
|
|
|
|
"t_colorArray4d" );
|
|
|
|
glUniform1i( nColorArrayLocation, 0 ); // unit 0
|
|
|
|
|
|
|
|
const GLint nStopArrayLocation = glGetUniformLocation(nProgramId,
|
|
|
|
"t_stopArray1d" );
|
|
|
|
glUniform1i( nStopArrayLocation, 1 ); // unit 1
|
|
|
|
|
|
|
|
const GLint nNumColorLocation = glGetUniformLocation(nProgramId,
|
|
|
|
"i_nColors" );
|
|
|
|
glUniform1i( nNumColorLocation, nColors-1 );
|
|
|
|
|
|
|
|
setupUniforms(nProgramId,rTexTransform);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setupUniforms( unsigned int nProgramId,
|
|
|
|
const rendering::ARGBColor& rStartColor,
|
|
|
|
const rendering::ARGBColor& rEndColor,
|
|
|
|
const ::basegfx::B2DHomMatrix& rTexTransform )
|
|
|
|
{
|
|
|
|
glUseProgram(nProgramId);
|
|
|
|
|
|
|
|
const GLint nStartColorLocation = glGetUniformLocation(nProgramId,
|
|
|
|
"v_startColor4d" );
|
|
|
|
glUniform4f(nStartColorLocation,
|
|
|
|
rStartColor.Red,
|
|
|
|
rStartColor.Green,
|
|
|
|
rStartColor.Blue,
|
|
|
|
rStartColor.Alpha);
|
|
|
|
|
|
|
|
const GLint nEndColorLocation = glGetUniformLocation(nProgramId,
|
|
|
|
"v_endColor4d" );
|
|
|
|
glUniform4f(nEndColorLocation,
|
|
|
|
rEndColor.Red,
|
|
|
|
rEndColor.Green,
|
|
|
|
rEndColor.Blue,
|
|
|
|
rEndColor.Alpha);
|
|
|
|
|
|
|
|
setupUniforms(nProgramId,rTexTransform);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::useLinearGradientShader( const rendering::ARGBColor* pColors,
|
|
|
|
const uno::Sequence< double >& rStops,
|
|
|
|
const ::basegfx::B2DHomMatrix& rTexTransform )
|
|
|
|
{
|
|
|
|
if( rStops.getLength() > 2 )
|
|
|
|
setupUniforms(mnLinearMultiColorGradientProgram, pColors, rStops, rTexTransform);
|
|
|
|
else
|
|
|
|
setupUniforms(mnLinearTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::useRadialGradientShader( const rendering::ARGBColor* pColors,
|
|
|
|
const uno::Sequence< double >& rStops,
|
|
|
|
const ::basegfx::B2DHomMatrix& rTexTransform )
|
|
|
|
{
|
|
|
|
if( rStops.getLength() > 2 )
|
|
|
|
setupUniforms(mnRadialMultiColorGradientProgram, pColors, rStops, rTexTransform);
|
|
|
|
else
|
|
|
|
setupUniforms(mnRadialTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteDeviceHelper::useRectangularGradientShader( const rendering::ARGBColor* pColors,
|
|
|
|
const uno::Sequence< double >& rStops,
|
|
|
|
const ::basegfx::B2DHomMatrix& rTexTransform )
|
|
|
|
{
|
|
|
|
if( rStops.getLength() > 2 )
|
|
|
|
setupUniforms(mnRectangularMultiColorGradientProgram, pColors, rStops, rTexTransform);
|
|
|
|
else
|
|
|
|
setupUniforms(mnRectangularTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
|
|
|
|
}
|
|
|
|
|
2014-08-08 01:55:33 +02:00
|
|
|
bool SpriteDeviceHelper::activateWindowContext()
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
2015-09-08 11:46:13 +01:00
|
|
|
mxContext->makeCurrent();
|
2012-01-31 01:07:48 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
2014-08-08 01:55:33 +02:00
|
|
|
|
2012-01-31 01:07:48 +01:00
|
|
|
class BufferContextImpl : public IBufferContext
|
|
|
|
{
|
|
|
|
::basegfx::B2IVector maSize;
|
2014-08-08 05:28:02 +02:00
|
|
|
GLuint mnFrambufferId;
|
|
|
|
GLuint mnDepthId;
|
|
|
|
GLuint mnTextureId;
|
2012-01-31 01:07:48 +01:00
|
|
|
|
2014-03-26 16:37:00 +01:00
|
|
|
virtual bool startBufferRendering() SAL_OVERRIDE
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
2014-08-08 05:28:02 +02:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mnFrambufferId);
|
|
|
|
return true;
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
2014-03-26 16:37:00 +01:00
|
|
|
virtual bool endBufferRendering() SAL_OVERRIDE
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
2014-08-08 05:28:02 +02:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual GLuint getTextureId() SAL_OVERRIDE
|
|
|
|
{
|
|
|
|
return mnTextureId;
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2015-06-08 09:29:35 +01:00
|
|
|
explicit BufferContextImpl(const ::basegfx::B2IVector& rSize) :
|
2012-01-31 01:07:48 +01:00
|
|
|
maSize(rSize),
|
2014-08-08 05:28:02 +02:00
|
|
|
mnFrambufferId(0),
|
|
|
|
mnDepthId(0),
|
|
|
|
mnTextureId(0)
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
2014-08-08 05:28:02 +02:00
|
|
|
OpenGLHelper::createFramebuffer(maSize.getX(), maSize.getY(), mnFrambufferId,
|
|
|
|
mnDepthId, mnTextureId, false);
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
2014-04-01 19:18:35 +02:00
|
|
|
virtual ~BufferContextImpl()
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
2014-08-08 05:28:02 +02:00
|
|
|
glDeleteTextures(1, &mnTextureId);
|
|
|
|
glDeleteRenderbuffers(1, &mnDepthId);
|
|
|
|
glDeleteFramebuffers(1, &mnFrambufferId);
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-08-08 05:28:02 +02:00
|
|
|
IBufferContextSharedPtr SpriteDeviceHelper::createBufferContext(const ::basegfx::B2IVector& rSize) const
|
2012-01-31 01:07:48 +01:00
|
|
|
{
|
2014-08-08 10:10:00 +02:00
|
|
|
return IBufferContextSharedPtr(new BufferContextImpl(rSize));
|
2012-01-31 01:07:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TextureCache& SpriteDeviceHelper::getTextureCache() const
|
|
|
|
{
|
|
|
|
return *mpTextureCache;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|