blob: b0200da1be9182c861a57f0d018de6101a5be998 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#define GLX_GLXEXT_PROTOTYPES 1
#include "OGLTrans_TransitionImpl.hxx"
#include <com/sun/star/beans/XFastPropertySet.hpp>
#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
#include <com/sun/star/rendering/ColorComponentTag.hpp>
#include <com/sun/star/rendering/ColorSpaceType.hpp>
#include <com/sun/star/animations/TransitionType.hpp>
#include <com/sun/star/animations/TransitionSubType.hpp>
#include <com/sun/star/presentation/XTransitionFactory.hpp>
#include <com/sun/star/presentation/XTransition.hpp>
#include <com/sun/star/presentation/XSlideShowView.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/rendering/XIntegerBitmap.hpp>
#include <com/sun/star/geometry/IntegerSize2D.hpp>
#include <cppuhelper/compbase1.hxx>
#include <cppuhelper/basemutex.hxx>
#include <cppuhelper/factory.hxx>
#include <rtl/ref.hxx>
#include <comphelper/servicedecl.hxx>
#include <canvas/canvastools.hxx>
#include <tools/gen.hxx>
#include <vcl/window.hxx>
#include <vcl/syschild.hxx>
#include <boost/noncopyable.hpp>
#include <GL/gl.h>
#include <GL/glu.h>
#if defined( WNT )
#include <tools/prewin.h>
#include <windows.h>
#include <tools/postwin.h>
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#elif defined( OS2 )
#elif defined( QUARTZ )
#include "premac.h"
#include <Cocoa/Cocoa.h>
#include "postmac.h"
#elif defined( UNX )
namespace unx
{
#include <X11/keysym.h>
#include <X11/X.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#if GLX_GLXEXT_VERSION<18
typedef void(*PFNGLXBINDTEXIMAGEEXTPROC)(Display*dpy,GLXDrawable,int,const int*);
typedef void(*PFNGLXRELEASETEXIMAGEEXTPROC)(Display*,GLXDrawable,int);
#endif
}
#endif
#include <vcl/sysdata.hxx>
#ifdef DEBUG
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace ::boost::posix_time;
static ptime t1;
static ptime t2;
#define DBG(x) x
#else
#define DBG(x)
#endif
using namespace ::com::sun::star;
using ::com::sun::star::beans::XFastPropertySet;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
namespace
{
typedef cppu::WeakComponentImplHelper1<presentation::XTransition> OGLTransitionerImplBase;
namespace
{
struct OGLFormat
{
GLint nInternalFormat;
GLenum eFormat;
GLenum eType;
};
/* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
*/
int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
{
using namespace rendering::ColorComponentTag;
static const sal_Int8 aOrderTable[] =
{
RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
};
const sal_Int32 nNumComps(rTags.getLength());
const sal_Int8* pLine=aOrderTable;
for(int i=0; i<4; ++i)
{
int j=0;
while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
++j;
// all of the line passed, this is a match!
if( j==nNumComps )
return i;
pLine+=4;
}
return -1;
}
}
// not thread safe
static bool errorTriggered;
int oglErrorHandler( unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/ )
{
errorTriggered = true;
return 0;
}
/** This is the Transitioner class for OpenGL 3D transitions in
* slideshow. At the moment, it's Linux only. This class is implicitly
* constructed from XTransitionFactory.
*/
class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable, public OGLTransitionerImplBase
{
public:
explicit OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition);
bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
static bool initialize( const Reference< presentation::XSlideShowView >& xView );
// XTransition
virtual void SAL_CALL update( double nTime )
throw (uno::RuntimeException);
virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
const Reference< rendering::XBitmap >& rLeavingBitmap,
const Reference< rendering::XBitmap >& rEnteringBitmap )
throw (uno::RuntimeException);
protected:
void disposeContextAndWindow();
void disposeTextures();
// WeakComponentImplHelperBase
virtual void SAL_CALL disposing();
bool isDisposed() const
{
return (rBHelper.bDisposed || rBHelper.bInDispose);
}
bool createWindow( Window* pPWindow );
void createTexture( unsigned int* texID,
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::GLXPixmap pixmap,
bool usePixmap,
#endif
bool useMipmap,
uno::Sequence<sal_Int8>& data,
const OGLFormat* pFormat );
void prepareEnvironment ();
const OGLFormat* chooseFormats();
private:
/** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
*/
void GLInitSlides();
/// Holds the information of our new child window
struct GLWindow
{
#if defined( WNT )
HWND hWnd;
HDC hDC;
HGLRC hRC;
#elif defined( OS2 )
#elif defined( QUARTZ )
#elif defined( UNX )
unx::Display* dpy;
int screen;
unx::Window win;
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::GLXFBConfig fbc;
#endif
unx::XVisualInfo* vi;
unx::GLXContext ctx;
#endif
unsigned int bpp;
unsigned int Width;
unsigned int Height;
const char* GLXExtensions;
const GLubyte* GLExtensions;
bool HasGLXExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, (const GLubyte*) GLXExtensions ); }
bool HasGLExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, GLExtensions ); }
} GLWin;
/** OpenGL handle to the leaving slide's texture
*/
unsigned int GLleavingSlide;
/** OpenGL handle to the entering slide's texture
*/
unsigned int GLenteringSlide;
/** pointer to our window which we MIGHT create.
*/
class SystemChildWindow* pWindow;
Reference< presentation::XSlideShowView > mxView;
Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
/** raw bytes of the entering bitmap
*/
uno::Sequence<sal_Int8> EnteringBytes;
/** raw bytes of the leaving bitmap
*/
uno::Sequence<sal_Int8> LeavingBytes;
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::GLXPixmap LeavingPixmap;
unx::GLXPixmap EnteringPixmap;
#endif
bool mbRestoreSync;
bool mbUseLeavingPixmap;
bool mbUseEnteringPixmap;
bool mbFreeLeavingPixmap;
bool mbFreeEnteringPixmap;
unx::Pixmap maLeavingPixmap;
unx::Pixmap maEnteringPixmap;
/** the form the raw bytes are in for the bitmaps
*/
rendering::IntegerBitmapLayout SlideBitmapLayout;
/** the size of the slides
*/
geometry::IntegerSize2D SlideSize;
/** Our Transition to be used.
*/
OGLTransitionImpl* pTransition;
public:
/** whether we are running on ATI fglrx with bug related to textures
*/
static bool cbBrokenTexturesATI;
/** GL version
*/
static float cnGLVersion;
float mnGLXVersion;
/** Whether Mesa is the OpenGL vendor
*/
static bool cbMesa;
/**
whether the display has GLX extension
*/
static bool cbGLXPresent;
/**
whether texture from pixmap extension is available
*/
bool mbTextureFromPixmap;
/**
whether to generate mipmaped textures
*/
bool mbGenerateMipmap;
/**
whether we have visual which can be used for texture_from_pixmap extension
*/
bool mbHasTFPVisual;
#ifdef DEBUG
ptime t3;
ptime t4;
ptime t5;
ptime t6;
time_duration total_update;
int frame_count;
#endif
};
// declare the static variables as some gcc versions have problems declaring them automaticaly
bool OGLTransitionerImpl::cbBrokenTexturesATI;
float OGLTransitionerImpl::cnGLVersion;
bool OGLTransitionerImpl::cbMesa;
bool OGLTransitionerImpl::cbGLXPresent;
bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView )
{
// not thread safe
static bool initialized = false;
if( !initialized ) {
OGLTransitionerImpl *instance;
instance = new OGLTransitionerImpl( NULL );
if( instance->initWindowFromSlideShowView( xView ) ) {
const GLubyte* version = glGetString( GL_VERSION );
if( version && version[0] ) {
cnGLVersion = version[0] - '0';
if( version[1] == '.' && version[2] )
cnGLVersion += (version[2] - '0')/10.0;
} else
cnGLVersion = 1.0;
OSL_TRACE("GL version: %s parsed: %f", version, cnGLVersion );
const GLubyte* vendor = glGetString( GL_VENDOR );
cbMesa = ( vendor && strstr( (const char *) vendor, "Mesa" ) );
OSL_TRACE("GL vendor: %s identified as Mesa: %d", vendor, cbMesa );
/* TODO: check for version once the bug in fglrx driver is fixed */
cbBrokenTexturesATI = (vendor && strcmp( (const char *) vendor, "ATI Technologies Inc." ) == 0 );
instance->disposing();
cbGLXPresent = true;
} else
cbGLXPresent = false;
delete instance;
initialized = true;
}
return cbGLXPresent;
}
bool OGLTransitionerImpl::createWindow( Window* pPWindow )
{
const SystemEnvData* sysData(pPWindow->GetSystemData());
#if defined( WNT )
GLWin.hWnd = sysData->hWnd;
#elif defined( UNX )
GLWin.dpy = reinterpret_cast<unx::Display*>(sysData->pDisplay);
if( unx::glXQueryExtension( GLWin.dpy, NULL, NULL ) == false )
return false;
GLWin.win = sysData->aWindow;
OSL_TRACE("parent window: %d", GLWin.win);
unx::XWindowAttributes xattr;
unx::XGetWindowAttributes( GLWin.dpy, GLWin.win, &xattr );
GLWin.screen = XScreenNumberOfScreen( xattr.screen );
unx::XVisualInfo* vi( NULL );
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::XVisualInfo* visinfo;
unx::XVisualInfo* firstVisual( NULL );
#endif
static int attrList3[] =
{
GLX_RGBA,//only TrueColor or DirectColor
//single buffered
GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
GLX_DEPTH_SIZE,0,//no depth buffer
None
};
static int attrList2[] =
{
GLX_RGBA,//only TrueColor or DirectColor
/// single buffered
GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
None
};
static int attrList1[] =
{
GLX_RGBA,//only TrueColor or DirectColor
GLX_DOUBLEBUFFER,/// only double buffer
GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
GLX_DEPTH_SIZE,0,/// no depth buffer
None
};
static int attrList0[] =
{
GLX_RGBA,//only TrueColor or DirectColor
GLX_DOUBLEBUFFER,/// only double buffer
GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
None
};
static int* attrTable[] =
{
attrList0,
attrList1,
attrList2,
attrList3,
NULL
};
int** pAttributeTable = attrTable;
const SystemEnvData* pChildSysData = NULL;
delete pWindow;
pWindow=NULL;
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::GLXFBConfig* fbconfigs = NULL;
int nfbconfigs, value, i = 0;
#endif
while( *pAttributeTable )
{
// try to find a visual for the current set of attributes
vi = unx::glXChooseVisual( GLWin.dpy,
GLWin.screen,
*pAttributeTable );
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
if( vi ) {
if( !firstVisual )
firstVisual = vi;
OSL_TRACE("trying VisualID %08X", vi->visualid);
fbconfigs = glXGetFBConfigs (GLWin.dpy, GLWin.screen, &nfbconfigs);
for ( ; i < nfbconfigs; i++)
{
visinfo = glXGetVisualFromFBConfig (GLWin.dpy, fbconfigs[i]);
if( !visinfo || visinfo->visualid != vi->visualid )
continue;
glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
if (!(value & GLX_PIXMAP_BIT))
continue;
glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
GLX_BIND_TO_TEXTURE_TARGETS_EXT,
&value);
if (!(value & GLX_TEXTURE_2D_BIT_EXT))
continue;
glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
GLX_BIND_TO_TEXTURE_RGB_EXT,
&value);
if (!value)
continue;
glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
&value);
if (!value)
continue;
/* TODO: handle non Y inverted cases */
break;
}
if( i != nfbconfigs || ( firstVisual && pAttributeTable[1] == NULL ) ) {
if( i != nfbconfigs ) {
vi = glXGetVisualFromFBConfig( GLWin.dpy, fbconfigs[i] );
mbHasTFPVisual = true;
OSL_TRACE("found visual suitable for texture_from_pixmap");
} else {
vi = firstVisual;
mbHasTFPVisual = false;
OSL_TRACE("did not find visual suitable for texture_from_pixmap, using %08X", vi->visualid);
}
#else
if( vi ) {
#endif
SystemWindowData winData;
winData.nSize = sizeof(winData);
OSL_TRACE("using VisualID %08X", vi->visualid);
winData.pVisual = (void*)(vi->visual);
pWindow=new SystemChildWindow(pPWindow, 0, &winData, sal_False);
pChildSysData = pWindow->GetSystemData();
if( pChildSysData ) {
break;
} else {
delete pWindow, pWindow=NULL;
}
}
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
}
#endif
++pAttributeTable;
}
#endif
#if defined( WNT )
const SystemEnvData* pChildSysData = NULL;
SystemWindowData winData;
winData.nSize = sizeof(winData);
pWindow=new SystemChildWindow(pPWindow, 0, &winData, sal_False);
pChildSysData = pWindow->GetSystemData();
#endif
if( pWindow )
{
pWindow->SetMouseTransparent( sal_True );
pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
pWindow->EnableEraseBackground( sal_False );
pWindow->SetControlForeground();
pWindow->SetControlBackground();
pWindow->EnablePaint(sal_False);
#if defined( WNT )
GLWin.hWnd = sysData->hWnd;
#elif defined( UNX )
GLWin.dpy = reinterpret_cast<unx::Display*>(pChildSysData->pDisplay);
GLWin.win = pChildSysData->aWindow;
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
if( mbHasTFPVisual )
GLWin.fbc = fbconfigs[i];
#endif
GLWin.vi = vi;
GLWin.GLXExtensions = unx::glXQueryExtensionsString( GLWin.dpy, GLWin.screen );
OSL_TRACE("available GLX extensions: %s", GLWin.GLXExtensions);
#endif
return true;
}
return false;
}
bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
{
osl::MutexGuard const guard( m_aMutex );
if (isDisposed())
return false;
mxView.set( xView, UNO_QUERY );
if( !mxView.is() )
return false;
/// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
uno::Sequence< uno::Any > aDeviceParams;
::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
::rtl::OUString aImplName;
aDeviceParams[ 0 ] >>= aImplName;
sal_Int64 aVal = 0;
aDeviceParams[1] >>= aVal;
if( !createWindow( reinterpret_cast< Window* >( aVal ) ) )
return false;
awt::Rectangle aCanvasArea = mxView->getCanvasArea();
pWindow->SetPosSizePixel(aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
GLWin.Width = aCanvasArea.Width;
GLWin.Height = aCanvasArea.Height;
OSL_TRACE("canvas area: %d,%d - %dx%d", aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
#if defined( WNT )
GLWin.hDC = GetDC(GLWin.hWnd);
#elif defined( UNX )
GLWin.ctx = glXCreateContext(GLWin.dpy,
GLWin.vi,
0,
GL_TRUE);
if( GLWin.ctx == NULL ) {
OSL_TRACE("unable to create GLX context");
return false;
}
#endif
#if defined( WNT )
PIXELFORMATDESCRIPTOR PixelFormatFront = // PixelFormat Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR),
1, // Version Number
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA, // Request An RGBA Format
(BYTE)32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
64, // 32 bit Z-BUFFER
0, // 0 bit stencil buffer
0, // No Auxiliary Buffer
0, // now ignored
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
int WindowPix = ChoosePixelFormat(GLWin.hDC,&PixelFormatFront);
SetPixelFormat(GLWin.hDC,WindowPix,&PixelFormatFront);
GLWin.hRC = wglCreateContext(GLWin.hDC);
wglMakeCurrent(GLWin.hDC,GLWin.hRC);
#elif defined( UNX )
if( !glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx ) ) {
OSL_TRACE("unable to select current GLX context");
return false;
}
int glxMinor, glxMajor;
mnGLXVersion = 0;
if( glXQueryVersion( GLWin.dpy, &glxMajor, &glxMinor ) )
mnGLXVersion = glxMajor + 0.1*glxMinor;
OSL_TRACE("available GLX version: %f", mnGLXVersion);
GLWin.GLExtensions = glGetString( GL_EXTENSIONS );
OSL_TRACE("available GL extensions: %s", GLWin.GLExtensions);
mbTextureFromPixmap = GLWin.HasGLXExtension( "GLX_EXT_texture_from_pixmap" );
mbGenerateMipmap = GLWin.HasGLExtension( "GL_SGIS_generate_mipmap" );
if( GLWin.HasGLXExtension("GLX_SGI_swap_control" ) ) {
// enable vsync
typedef GLint (*glXSwapIntervalProc)(GLint);
glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) unx::glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
if( glXSwapInterval ) {
int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
// replace error handler temporarily
oldHandler = unx::XSetErrorHandler( oglErrorHandler );
errorTriggered = false;
glXSwapInterval( 1 );
// sync so that we possibly get an XError
unx::glXWaitGL();
XSync(GLWin.dpy, false);
if( errorTriggered )
OSL_TRACE("error when trying to set swap interval, NVIDIA or Mesa bug?");
else
OSL_TRACE("set swap interval to 1 (enable vsync)");
// restore the error handler
unx::XSetErrorHandler( oldHandler );
}
}
#endif
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor (0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
#if defined( WNT )
SwapBuffers(GLWin.hDC);
#elif defined( UNX )
unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
#endif
glEnable(GL_LIGHTING);
GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
if( LeavingBytes.hasElements() && EnteringBytes.hasElements())
GLInitSlides();//we already have uninitialized slides, let's initialize
if( pTransition && pTransition->mnRequiredGLVersion <= cnGLVersion )
pTransition->prepare( GLleavingSlide, GLenteringSlide );
return true;
}
void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
const uno::Reference< rendering::XBitmap >& xEnteringSlide )
{
osl::MutexGuard const guard( m_aMutex );
if (isDisposed())
return;
mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
Reference< XFastPropertySet > xLeavingSet( xLeavingSlide , UNO_QUERY );
Reference< XFastPropertySet > xEnteringSet( xEnteringSlide , UNO_QUERY );
geometry::IntegerRectangle2D SlideRect;
SlideSize = mxLeavingBitmap->getSize();
SlideRect.X1 = 0;
SlideRect.X2 = SlideSize.Width;
SlideRect.Y1 = 0;
SlideRect.Y2 = SlideSize.Height;
OSL_TRACE("leaving bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
SlideSize = mxEnteringBitmap->getSize();
OSL_TRACE("entering bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
#ifdef UNX
unx::glXWaitGL();
XSync(GLWin.dpy, false);
#endif
#ifdef DEBUG
t1 = microsec_clock::local_time();
#endif
mbUseLeavingPixmap = false;
mbUseEnteringPixmap = false;
#ifdef UNX
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
if( mnGLXVersion >= 1.2999 && mbTextureFromPixmap && xLeavingSet.is() && xEnteringSet.is() && mbHasTFPVisual ) {
Sequence< Any > leaveArgs;
Sequence< Any > enterArgs;
if( (xLeavingSet->getFastPropertyValue( 1 ) >>= leaveArgs) &&
(xEnteringSet->getFastPropertyValue( 1 ) >>= enterArgs) ) {
OSL_TRACE ("pixmaps available");
sal_Int32 depth;
leaveArgs[0] >>= mbFreeLeavingPixmap;
enterArgs[0] >>= mbFreeEnteringPixmap;
leaveArgs[1] >>= maLeavingPixmap;
enterArgs[1] >>= maEnteringPixmap;
leaveArgs[2] >>= depth;
int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
GLX_MIPMAP_TEXTURE_EXT, True,
None };
// sync so that we possibly get an pending XError, before we set our handler.
// this way we will not miss any error from other code
unx::glXWaitGL();
XSync(GLWin.dpy, false);
int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
// replace error handler temporarily
oldHandler = unx::XSetErrorHandler( oglErrorHandler );
errorTriggered = false;
LeavingPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maLeavingPixmap, pixmapAttribs );
// sync so that we possibly get an XError
unx::glXWaitGL();
XSync(GLWin.dpy, false);
if( !errorTriggered )
mbUseLeavingPixmap = true;
else {
OSL_TRACE("XError triggered");
if( mbFreeLeavingPixmap ) {
unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
mbFreeLeavingPixmap = false;
}
errorTriggered = false;
}
EnteringPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maEnteringPixmap, pixmapAttribs );
// sync so that we possibly get an XError
unx::glXWaitGL();
XSync(GLWin.dpy, false);
OSL_TRACE("created glx pixmap %p and %p depth: %d", LeavingPixmap, EnteringPixmap, depth);
if( !errorTriggered )
mbUseEnteringPixmap = true;
else {
OSL_TRACE("XError triggered");
if( mbFreeEnteringPixmap ) {
unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
mbFreeEnteringPixmap = false;
}
}
// restore the error handler
unx::XSetErrorHandler( oldHandler );
}
}
#endif
#endif
if( !mbUseLeavingPixmap )
LeavingBytes = mxLeavingBitmap->getData(SlideBitmapLayout,SlideRect);
if( !mbUseEnteringPixmap )
EnteringBytes = mxEnteringBitmap->getData(SlideBitmapLayout,SlideRect);
// TODO
#ifdef UNX
if(GLWin.ctx)//if we have a rendering context, let's init the slides
#endif
GLInitSlides();
OSL_ENSURE(SlideBitmapLayout.PlaneStride == 0,"only handle no plane stride now");
#ifdef UNX
/* flush & sync */
unx::glXWaitGL();
XSync( GLWin.dpy, false );
// synchronized X still gives us much smoother play
// I suspect some issues in above code in slideshow
// synchronize whole transition for now
XSynchronize( GLWin.dpy, true );
mbRestoreSync = true;
#endif
}
void OGLTransitionerImpl::createTexture( unsigned int* texID,
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::GLXPixmap pixmap,
bool usePixmap,
#endif
bool useMipmap,
uno::Sequence<sal_Int8>& data,
const OGLFormat* pFormat )
{
glDeleteTextures( 1, texID );
glGenTextures( 1, texID );
glBindTexture( GL_TEXTURE_2D, *texID );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::PFNGLXBINDTEXIMAGEEXTPROC myglXBindTexImageEXT = (unx::PFNGLXBINDTEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXBindTexImageEXT" );
if( usePixmap ) {
if( mbGenerateMipmap )
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, True);
myglXBindTexImageEXT (GLWin.dpy, pixmap, GLX_FRONT_LEFT_EXT, NULL);
if( mbGenerateMipmap && useMipmap ) {
OSL_TRACE("use mipmaps");
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
} else {
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
}
} else {
#endif
if( !pFormat )
{
// force-convert color to ARGB8888 int color space
uno::Sequence<sal_Int8> tempBytes(
SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
data,
canvas::tools::getStdColorSpace()));
gluBuild2DMipmaps(GL_TEXTURE_2D,
4,
SlideSize.Width,
SlideSize.Height,
GL_RGBA,
GL_UNSIGNED_BYTE,
&tempBytes[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
//anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
GLfloat largest_supported_anisotropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
} else {
if( pTransition && !cbBrokenTexturesATI && !useMipmap) {
glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
} else {
gluBuild2DMipmaps( GL_TEXTURE_2D, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); //TRILINEAR FILTERING
//anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
GLfloat largest_supported_anisotropy;
glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
}
}
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
}
#endif
OSL_ENSURE(glIsTexture(*texID), "Can't generate Leaving slide textures in OpenGL");
}
void OGLTransitionerImpl::prepareEnvironment()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double EyePos(10.0);
double RealF(1.0);
double RealN(-1.0);
double RealL(-1.0);
double RealR(1.0);
double RealB(-1.0);
double RealT(1.0);
double ClipN(EyePos+5.0*RealN);
double ClipF(EyePos+15.0*RealF);
double ClipL(RealL*8.0);
double ClipR(RealR*8.0);
double ClipB(RealB*8.0);
double ClipT(RealT*8.0);
//This scaling is to take the plane with BottomLeftCorner(-1,-1,0) and TopRightCorner(1,1,0) and map it to the screen after the perspective division.
glScaled( 1.0 / ( ( ( RealR * 2.0 * ClipN ) / ( EyePos * ( ClipR - ClipL ) ) ) - ( ( ClipR + ClipL ) / ( ClipR - ClipL ) ) ),
1.0 / ( ( ( RealT * 2.0 * ClipN ) / ( EyePos * ( ClipT - ClipB ) ) ) - ( ( ClipT + ClipB ) / ( ClipT - ClipB ) ) ),
1.0 );
glFrustum(ClipL,ClipR,ClipB,ClipT,ClipN,ClipF);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0,0,-EyePos);
}
const OGLFormat* OGLTransitionerImpl::chooseFormats()
{
const OGLFormat* pDetectedFormat=NULL;
uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
SlideBitmapLayout.ColorSpace);
if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) )
{
/* table for canvas->OGL format mapping. outer index is number
of color components (0:3, 1:4), then comes bits per pixel
(0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
2:argb, 3:abgr)
*/
static const OGLFormat lcl_RGB24[] =
{
// 24 bit RGB
{3, GL_BGR, GL_UNSIGNED_BYTE},
{3, GL_RGB, GL_UNSIGNED_BYTE},
{3, GL_BGR, GL_UNSIGNED_BYTE},
{3, GL_RGB, GL_UNSIGNED_BYTE}
};
#if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
// more format constants available
static const OGLFormat lcl_RGB16[] =
{
// 16 bit RGB
{3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
{3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
{3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
{3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
};
static const OGLFormat lcl_ARGB16_4[] =
{
// 16 bit ARGB
{4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
{4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
{4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
{4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
};
static const OGLFormat lcl_ARGB16_5[] =
{
// 16 bit ARGB
{4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
{4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
{4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
{4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
};
static const OGLFormat lcl_ARGB32[] =
{
// 32 bit ARGB
{4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
{4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
{4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
{4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
};
const uno::Sequence<sal_Int8> aComponentTags(
xIntColorSpace->getComponentTags());
const uno::Sequence<sal_Int32> aComponentBitcounts(
xIntColorSpace->getComponentBitCounts());
const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
// supported component ordering?
const int nComponentOrderIndex(
calcComponentOrderIndex(aComponentTags));
if( nComponentOrderIndex != -1 )
{
switch( nBitsPerPixel )
{
case 16:
if( nNumComponents == 3 )
{
pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
}
else if( nNumComponents == 4 )
{
if( aComponentBitcounts[1] == 4 )
{
pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
}
else if( aComponentBitcounts[1] == 5 )
{
pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
}
}
break;
case 24:
if( nNumComponents == 3 )
{
pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
}
break;
case 32:
pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
break;
}
}
#else
const uno::Sequence<sal_Int8> aComponentTags(
xIntColorSpace->getComponentTags());
const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
if( aComponentTags.getLength() == 3 &&
nComponentOrderIndex != -1 &&
xIntColorSpace->getBitsPerPixel() == 24 )
{
pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
}
#endif
}
return pDetectedFormat;
}
void OGLTransitionerImpl::GLInitSlides()
{
osl::MutexGuard const guard( m_aMutex );
if (isDisposed() || pTransition->mnRequiredGLVersion > cnGLVersion)
return;
prepareEnvironment();
const OGLFormat* pFormat = NULL;
if( !mbUseLeavingPixmap || !mbUseEnteringPixmap )
pFormat = chooseFormats();
createTexture( &GLleavingSlide,
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
LeavingPixmap,
mbUseLeavingPixmap,
#endif
pTransition->mbUseMipMapLeaving,
LeavingBytes,
pFormat );
createTexture( &GLenteringSlide,
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
EnteringPixmap,
mbUseEnteringPixmap,
#endif
pTransition->mbUseMipMapEntering,
EnteringBytes,
pFormat );
#ifdef UNX
unx::glXWaitGL();
XSync(GLWin.dpy, false);
#endif
#ifdef DEBUG
t2 = microsec_clock::local_time();
OSL_TRACE("textures created in: %s", to_simple_string( t2 - t1 ).c_str());
#endif
}
void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException)
{
#ifdef DEBUG
frame_count ++;
t3 = microsec_clock::local_time();
if( frame_count == 1 ) {
t5 = t3;
total_update = seconds (0);
}
#endif
osl::MutexGuard const guard( m_aMutex );
if (isDisposed() || !cbGLXPresent || pTransition->mnRequiredGLVersion > cnGLVersion)
return;
#ifdef WNT
wglMakeCurrent(GLWin.hDC,GLWin.hRC);
#endif
#ifdef UNX
glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
#endif
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(pTransition)
pTransition->display( nTime, GLleavingSlide, GLenteringSlide,
SlideSize.Width, SlideSize.Height,
static_cast<double>(GLWin.Width),
static_cast<double>(GLWin.Height) );
#if defined( WNT )
SwapBuffers(GLWin.hDC);
#elif defined( UNX )
unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
#endif
if( pWindow )
pWindow->Show();
#ifdef UNX
/* flush & sync */
unx::glXWaitGL();
XSync( GLWin.dpy, false );
#endif
#ifdef DEBUG
t4 = microsec_clock::local_time();
OSL_TRACE("update time: %f", nTime);
OSL_TRACE("update took: %s", to_simple_string( t4 - t3 ).c_str());
total_update += (t4 - t3);
#endif
}
void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
const Reference< rendering::XBitmap >& rLeavingBitmap,
const Reference< rendering::XBitmap >& rEnteringBitmap )
throw (uno::RuntimeException)
{
OSL_TRACE("transitioner: view changed");
disposeTextures();
disposeContextAndWindow();
initWindowFromSlideShowView( rView );
setSlides( rLeavingBitmap, rEnteringBitmap );
}
void OGLTransitionerImpl::disposeContextAndWindow()
{
#if defined( WNT )
if (GLWin.hRC)
{
wglMakeCurrent( GLWin.hDC, 0 ); // kill Device Context
wglDeleteContext( GLWin.hRC ); // Kill Render Context
ReleaseDC( GLWin.hWnd, GLWin.hDC ); // Release Window
}
#elif defined( UNX )
if(GLWin.ctx)
{
glXMakeCurrent(GLWin.dpy, None, NULL);
if( glGetError() != GL_NO_ERROR ) {
OSL_TRACE("glError: %s", (char *)gluErrorString(glGetError()));
}
glXDestroyContext(GLWin.dpy, GLWin.ctx);
GLWin.ctx = NULL;
}
#endif
if( pWindow ) {
delete pWindow;
pWindow = NULL;
GLWin.win = 0;
}
}
void OGLTransitionerImpl::disposeTextures()
{
#ifdef WNT
wglMakeCurrent(GLWin.hDC,GLWin.hRC);
#endif
#ifdef UNX
glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
#endif
#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
unx::PFNGLXRELEASETEXIMAGEEXTPROC myglXReleaseTexImageEXT = (unx::PFNGLXRELEASETEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXReleaseTexImageEXT" );
if( mbUseLeavingPixmap ) {
myglXReleaseTexImageEXT( GLWin.dpy, LeavingPixmap, GLX_FRONT_LEFT_EXT );
glXDestroyGLXPixmap( GLWin.dpy, LeavingPixmap );
LeavingPixmap = 0;
if( mbFreeLeavingPixmap ) {
unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
mbFreeLeavingPixmap = false;
maLeavingPixmap = 0;
}
}
if( mbUseEnteringPixmap ) {
myglXReleaseTexImageEXT( GLWin.dpy, EnteringPixmap, GLX_FRONT_LEFT_EXT );
glXDestroyGLXPixmap( GLWin.dpy, EnteringPixmap );
EnteringPixmap = 0;
if( mbFreeEnteringPixmap ) {
unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
mbFreeEnteringPixmap = false;
maEnteringPixmap = 0;
}
}
#endif
if( !mbUseLeavingPixmap ) {
glDeleteTextures(1,&GLleavingSlide);
GLleavingSlide = 0;
}
if( !mbUseEnteringPixmap ) {
glDeleteTextures(1,&GLenteringSlide);
GLleavingSlide = 0;
}
mbUseLeavingPixmap = false;
mbUseEnteringPixmap = false;
}
// we are about to be disposed (someone call dispose() on us)
void OGLTransitionerImpl::disposing()
{
osl::MutexGuard const guard( m_aMutex );
#ifdef DEBUG
OSL_TRACE("dispose %p\n", this);
if( frame_count ) {
t6 = microsec_clock::local_time();
time_duration duration = t6 - t5;
OSL_TRACE("whole transition (frames: %d) took: %s fps: %f time spent in updates: %s percentage of transition time: %f%%",
frame_count, to_simple_string( duration ).c_str(),
((double)frame_count*1000000000.0)/duration.total_nanoseconds(),
to_simple_string( total_update ).c_str(),
100*(((double)total_update.total_nanoseconds())/((double)duration.total_nanoseconds()))
);
}
#endif
if( pWindow ) {
disposeTextures();
if (pTransition)
pTransition->finish();
#ifdef UNX
if( mbRestoreSync ) {
// try to reestablish synchronize state
char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
XSynchronize( GLWin.dpy, sal_synchronize && *sal_synchronize == '1' );
}
#endif
disposeContextAndWindow();
}
if (pTransition)
delete pTransition;
mxLeavingBitmap.clear();
mxEnteringBitmap.clear();
mxView.clear();
}
OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) :
OGLTransitionerImplBase(m_aMutex),
GLWin(),
GLleavingSlide( 0 ),
GLenteringSlide( 0 ),
pWindow( NULL ),
mxView(),
EnteringBytes(),
LeavingBytes(),
mbRestoreSync( false ),
mbUseLeavingPixmap( false ),
mbUseEnteringPixmap( false ),
SlideBitmapLayout(),
SlideSize(),
pTransition(pOGLTransition)
{
#if defined( WNT )
GLWin.hWnd = 0;
#elif defined( UNX )
GLWin.ctx = 0;
#endif
DBG(frame_count = 0);
}
typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
{
public:
explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) :
OGLTransitionFactoryImplBase(m_aMutex)
{}
// XTransitionFactory
virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException)
{
if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
switch( transitionSubType )
{
case animations::TransitionSubType::ACROSS:
case animations::TransitionSubType::CORNERSOUT:
case animations::TransitionSubType::CIRCLE:
case animations::TransitionSubType::FANOUTHORIZONTAL:
case animations::TransitionSubType::CORNERSIN:
case animations::TransitionSubType::LEFTTORIGHT:
case animations::TransitionSubType::TOPTOBOTTOM:
case animations::TransitionSubType::TOPRIGHT:
case animations::TransitionSubType::TOPLEFT:
case animations::TransitionSubType::BOTTOMRIGHT:
case animations::TransitionSubType::BOTTOMLEFT:
case animations::TransitionSubType::TOPCENTER:
case animations::TransitionSubType::RIGHTCENTER:
case animations::TransitionSubType::BOTTOMCENTER:
return sal_True;
default:
return sal_False;
}
} else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
return sal_True;
} else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
return sal_True;
} else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
return sal_True;
} else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
return sal_True;
} else
return sal_False;
}
virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
::sal_Int16 transitionType,
::sal_Int16 transitionSubType,
const uno::Reference< presentation::XSlideShowView >& view,
const uno::Reference< rendering::XBitmap >& leavingBitmap,
const uno::Reference< rendering::XBitmap >& enteringBitmap )
throw (uno::RuntimeException)
{
if( !hasTransition( transitionType, transitionSubType ) )
return uno::Reference< presentation::XTransition >();
bool bGLXPresent = OGLTransitionerImpl::initialize( view );
if( OGLTransitionerImpl::cbMesa && (
( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) ||
( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) ||
( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) ) )
return uno::Reference< presentation::XTransition >();
OGLTransitionImpl* pTransition = NULL;
if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
pTransition = new OGLTransitionImpl();
switch( transitionSubType )
{
case animations::TransitionSubType::ACROSS:
pTransition->makeNByMTileFlip(8,6);
break;
case animations::TransitionSubType::CORNERSOUT:
pTransition->makeOutsideCubeFaceToLeft();
break;
case animations::TransitionSubType::CIRCLE:
pTransition->makeRevolvingCircles(8,128);
break;
case animations::TransitionSubType::FANOUTHORIZONTAL:
pTransition->makeHelix(20);
break;
case animations::TransitionSubType::CORNERSIN:
pTransition->makeInsideCubeFaceToLeft();
break;
case animations::TransitionSubType::LEFTTORIGHT:
pTransition->makeFallLeaving();
break;
case animations::TransitionSubType::TOPTOBOTTOM:
pTransition->makeTurnAround();
break;
case animations::TransitionSubType::TOPRIGHT:
pTransition->makeTurnDown();
break;
case animations::TransitionSubType::TOPLEFT:
pTransition->makeIris();
break;
case animations::TransitionSubType::BOTTOMRIGHT:
pTransition->makeRochade();
break;
case animations::TransitionSubType::BOTTOMLEFT:
pTransition->makeVenetianBlinds( true, 8 );
break;
case animations::TransitionSubType::TOPCENTER:
pTransition->makeVenetianBlinds( false, 6 );
break;
case animations::TransitionSubType::RIGHTCENTER:
pTransition->makeStatic();
break;
case animations::TransitionSubType::BOTTOMCENTER:
pTransition->makeDissolve();
break;
}
} else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
pTransition = new OGLTransitionImpl();
pTransition->makeFadeSmoothly();
} else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
pTransition = new OGLTransitionImpl();
pTransition->makeFadeThroughBlack();
} else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
pTransition = new OGLTransitionImpl();
pTransition->makeDiamond();
} else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
pTransition = new OGLTransitionImpl();
pTransition->makeNewsflash();
}
rtl::Reference<OGLTransitionerImpl> xRes(
new OGLTransitionerImpl(pTransition) );
if( bGLXPresent ) {
if( !xRes->initWindowFromSlideShowView(view))
return uno::Reference< presentation::XTransition >();
xRes->setSlides(leavingBitmap,enteringBitmap);
}
return uno::Reference<presentation::XTransition>(xRes.get());
}
};
}
namespace sdecl = comphelper::service_decl;
#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
sdecl::class_<OGLTransitionFactoryImpl> serviceImpl;
const sdecl::ServiceDecl OGLTransitionFactoryDecl(
serviceImpl,
#else
const sdecl::ServiceDecl OGLTransitionFactoryDecl(
sdecl::class_<OGLTransitionFactoryImpl>(),
#endif
"com.sun.star.comp.presentation.OGLTransitionFactory",
"com.sun.star.presentation.TransitionFactory" );
// The C shared lib entry points
COMPHELPER_SERVICEDECL_EXPORTS1(OGLTransitionFactoryDecl)