diff options
Diffstat (limited to 'slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx')
-rw-r--r-- | slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx | 1201 |
1 files changed, 924 insertions, 277 deletions
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx index 62da933baa96..6c07065e2904 100644 --- a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx +++ b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx @@ -28,8 +28,10 @@ * ************************************************************************/ +#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> @@ -70,17 +72,88 @@ namespace unx { #include <X11/keysym.h> +#include <X11/X.h> #include <GL/glx.h> +#include <GL/glxext.h> } #endif +#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. @@ -89,13 +162,22 @@ class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable, { public: explicit OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition); - void initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView, double, double); - void setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide ); + 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 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(); @@ -104,6 +186,18 @@ protected: 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. */ @@ -114,20 +208,29 @@ private: struct GLWindow { #if defined( WNT ) - HWND hWnd; - HDC hDC; - HGLRC hRC; + HWND hWnd; + HDC hDC; + HGLRC hRC; #elif defined( OS2 ) #elif defined( QUARTZ ) #elif defined( UNX ) - unx::Display* dpy; - int screen; - unx::Window win; - unx::GLXContext ctx; + 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 @@ -141,6 +244,10 @@ private: */ 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; @@ -149,6 +256,18 @@ private: */ 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; @@ -160,38 +279,124 @@ private: /** 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 }; -void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView, double, double) -{ - osl::MutexGuard const guard( m_aMutex ); +// 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; - if (isDisposed()) - return; +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; + } - /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx - uno::Reference< rendering::XCanvas > xCanvas(xView->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; - Window* pPWindow = reinterpret_cast< Window* >( aVal ); - GLWin.Width = pPWindow->GetSizePixel().Width(); - GLWin.Height = pPWindow->GetSizePixel().Height(); + 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; - GLWin.screen = unx::XDefaultScreen(GLWin.dpy); + + 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 + 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 @@ -200,8 +405,8 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre None }; static int attrList2[] = - { - GLX_RGBA,/// only TrueColor or DirectColor + { + 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 @@ -211,7 +416,7 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre }; static int attrList1[] = { - GLX_RGBA,/// only TrueColor or DirectColor + 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 @@ -221,7 +426,7 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre }; static int attrList0[] = { - GLX_RGBA,/// only TrueColor or DirectColor + 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 @@ -241,6 +446,12 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre 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 @@ -248,59 +459,154 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre GLWin.screen, *pAttributeTable ); - if( vi ) - { - SystemWindowData winData; - winData.nSize = sizeof(winData); - winData.pVisual = (void*)(vi->visual); - pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE); - pChildSysData = pWindow->GetSystemData(); - if( pChildSysData ) - { - break; - } - else - { - delete pWindow, pWindow=NULL; - } - } +#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 == FALSE) + continue; + + glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], + GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value); + if (value == FALSE) + 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, 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, FALSE); - pChildSysData = pWindow->GetSystemData(); + const SystemEnvData* pChildSysData = NULL; + SystemWindowData winData; + winData.nSize = sizeof(winData); + pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE); + pChildSysData = pWindow->GetSystemData(); #endif - if( pWindow ) - { - pWindow->SetMouseTransparent( TRUE ); - pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP ); - pWindow->EnableEraseBackground( FALSE ); - pWindow->SetControlForeground(); - pWindow->SetControlBackground(); - pWindow->EnablePaint(FALSE); - pWindow->SetPosSizePixel(pPWindow->GetPosPixel(),pPWindow->GetSizePixel()); - + if( pWindow ) + { + pWindow->SetMouseTransparent( TRUE ); + pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP ); + pWindow->EnableEraseBackground( FALSE ); + pWindow->SetControlForeground(); + pWindow->SetControlBackground(); + pWindow->EnablePaint(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, - vi, + GLWin.vi, 0, GL_TRUE); + if( GLWin.ctx == NULL ) { + OSL_TRACE("unable to create GLX context"); + return false; + } #endif #if defined( WNT ) @@ -330,8 +636,52 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre GLWin.hRC = wglCreateContext(GLWin.hDC); wglMakeCurrent(GLWin.hDC,GLWin.hRC); #elif defined( UNX ) - glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx ); + 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); @@ -353,8 +703,10 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre if( LeavingBytes.hasElements() && EnteringBytes.hasElements()) GLInitSlides();//we already have uninitialized slides, let's initialize - if (pTransition) - pTransition->prepare (); + if( pTransition && pTransition->mnRequiredGLVersion <= cnGLVersion ) + pTransition->prepare( GLleavingSlide, GLenteringSlide ); + + return true; } void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide, @@ -365,75 +717,213 @@ void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& if (isDisposed()) return; - uno::Reference< rendering::XIntegerBitmap > LeavingSlideIntBitmap( xLeavingSlide , uno::UNO_QUERY_THROW ); - uno::Reference< rendering::XIntegerBitmap > EnteringSlideIntBitmap( xEnteringSlide , uno::UNO_QUERY_THROW ); + 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 = LeavingSlideIntBitmap->getSize(); + SlideSize = mxLeavingBitmap->getSize(); SlideRect.X1 = 0; SlideRect.X2 = SlideSize.Width; SlideRect.Y1 = 0; SlideRect.Y2 = SlideSize.Height; - LeavingBytes = LeavingSlideIntBitmap->getData(SlideBitmapLayout,SlideRect); - EnteringBytes = EnteringSlideIntBitmap->getData(SlideBitmapLayout,SlideRect); + 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); -// TODO if(GLWin.ctx)//if we have a rendering context, let's init the slides - GLInitSlides(); +#ifdef UNX + unx::glXWaitGL(); + XSync(GLWin.dpy, false); +#endif - OSL_ENSURE(SlideBitmapLayout.PlaneStride == 0,"only handle no plane stride now"); -} +#ifdef DEBUG + t1 = microsec_clock::local_time(); +#endif -namespace -{ - struct OGLFormat - { - GLint nInternalFormat; - GLenum eFormat; - GLenum eType; - }; + mbUseLeavingPixmap = false; + mbUseEnteringPixmap = false; - /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr) - */ - int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags) - { - using namespace rendering::ColorComponentTag; +#ifdef UNX +#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap ) - 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, - }; + 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"); - 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; + sal_Int32 depth; - // all of the line passed, this is a match! - if( j==nNumComps ) - return i; + leaveArgs[0] >>= mbFreeLeavingPixmap; + enterArgs[0] >>= mbFreeEnteringPixmap; + leaveArgs[1] >>= maLeavingPixmap; + enterArgs[1] >>= maEnteringPixmap; + leaveArgs[2] >>= depth; - pLine+=4; + 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; } - return -1; + 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(); -void OGLTransitionerImpl::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 ) { - osl::MutexGuard const guard( m_aMutex ); + 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 - if (isDisposed()) - return; + //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); @@ -457,7 +947,10 @@ void OGLTransitionerImpl::GLInitSlides() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(0,0,-EyePos); +} +const OGLFormat* OGLTransitionerImpl::chooseFormats() +{ const OGLFormat* pDetectedFormat=NULL; uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace( SlideBitmapLayout.ColorSpace); @@ -473,10 +966,10 @@ void OGLTransitionerImpl::GLInitSlides() 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}, - // {3, GL_BGR, 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) @@ -484,37 +977,37 @@ void OGLTransitionerImpl::GLInitSlides() static const OGLFormat lcl_RGB16[] = { // 16 bit RGB - {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}, - {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV} + {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}, -// {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4}, - // {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, - {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV} + {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_5_5_5_1}, - // {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1}, - // {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, - {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV} + {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}, -// {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8}, - // {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, - {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV} + {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( @@ -572,95 +1065,78 @@ void OGLTransitionerImpl::GLInitSlides() #endif } - glDeleteTextures(1,&GLleavingSlide); + return pDetectedFormat; +} - glGenTextures(1, &GLleavingSlide); - glBindTexture(GL_TEXTURE_2D, GLleavingSlide); - if( !pDetectedFormat ) - { - // force-convert color to ARGB8888 int color space - uno::Sequence<sal_Int8> tempBytes( - SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace( - LeavingBytes, - canvas::tools::getStdColorSpace())); - gluBuild2DMipmaps(GL_TEXTURE_2D, - 4, - SlideSize.Width, - SlideSize.Height, - GL_RGBA, - GL_UNSIGNED_BYTE, - &tempBytes[0]); - } - else - { - gluBuild2DMipmaps(GL_TEXTURE_2D, - pDetectedFormat->nInternalFormat, - SlideSize.Width, - SlideSize.Height, - pDetectedFormat->eFormat, - pDetectedFormat->eType, - &LeavingBytes[0]); - } - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);//TRILINEAR FILTERING - 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);//anistropic filtering (to make texturing not suck when looking at polygons from oblique angles) +void OGLTransitionerImpl::GLInitSlides() +{ + osl::MutexGuard const guard( m_aMutex ); - OSL_ENSURE(glIsTexture(GLleavingSlide), "Can't generate Leaving slide textures in OpenGL"); + if (isDisposed() || pTransition->mnRequiredGLVersion > cnGLVersion) + return; - glDeleteTextures(1,&GLenteringSlide); + prepareEnvironment(); - glGenTextures(1, &GLenteringSlide); - glBindTexture(GL_TEXTURE_2D, GLenteringSlide); - if( !pDetectedFormat ) - { - // force-convert color to ARGB8888 int color space - uno::Sequence<sal_Int8> tempBytes( - SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace( - EnteringBytes, - canvas::tools::getStdColorSpace())); - gluBuild2DMipmaps(GL_TEXTURE_2D, - 4, - SlideSize.Width, - SlideSize.Height, - GL_RGBA, - GL_UNSIGNED_BYTE, - &tempBytes[0]); - } - else - { - gluBuild2DMipmaps(GL_TEXTURE_2D, - pDetectedFormat->nInternalFormat, - SlideSize.Width, - SlideSize.Height, - pDetectedFormat->eFormat, - pDetectedFormat->eType, - &EnteringBytes[0]); - } - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);//TRILINEAR FILTERING - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);//anistropic filtering (to make texturing not suck when looking at polygons from oblique angles) + 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 - OSL_ENSURE( glIsTexture(GLenteringSlide), "Can't generate entering slide textures in OpenGL" ); +#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()) + 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 , + pTransition->display( nTime, GLleavingSlide, GLenteringSlide, SlideSize.Width, SlideSize.Height, static_cast<double>(GLWin.Width), static_cast<double>(GLWin.Height) ); @@ -672,38 +1148,153 @@ void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeExc #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 } -// we are about to be disposed (someone call dispose() on us) -void OGLTransitionerImpl::disposing() +void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView, + const Reference< rendering::XBitmap >& rLeavingBitmap, + const Reference< rendering::XBitmap >& rEnteringBitmap ) + throw (uno::RuntimeException) { - osl::MutexGuard const guard( m_aMutex ); - glDeleteTextures(1,&GLleavingSlide); - glDeleteTextures(1,&GLenteringSlide); + OSL_TRACE("transitioner: view changed"); - if (pTransition) - pTransition->finish(); + 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 + 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) { - OSL_ENSURE( glXMakeCurrent(GLWin.dpy, None, NULL) , "Error releasing glX context" ); - glXDestroyContext(GLWin.dpy, GLWin.ctx); - GLWin.ctx = NULL; + 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 - if (pWindow) - delete pWindow; + + disposeContextAndWindow(); + } + if (pTransition) delete pTransition; + + mxLeavingBitmap.clear(); + mxEnteringBitmap.clear(); + mxView.clear(); } OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) : @@ -712,8 +1303,12 @@ OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) : GLleavingSlide( 0 ), GLenteringSlide( 0 ), pWindow( NULL ), + mxView(), EnteringBytes(), LeavingBytes(), + mbRestoreSync( false ), + mbUseLeavingPixmap( false ), + mbUseEnteringPixmap( false ), SlideBitmapLayout(), SlideSize(), pTransition(pOGLTransition) @@ -723,6 +1318,8 @@ OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) : #elif defined( UNX ) GLWin.ctx = 0; #endif + + DBG(frame_count = 0); } typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase; @@ -737,26 +1334,38 @@ public: // XTransitionFactory virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException) { - if( transitionType != animations::TransitionType::MISCSHAPEWIPE ) + 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; - - 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: - return sal_True; - - default: - return sal_False; - } } virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition( @@ -764,53 +1373,91 @@ public: ::sal_Int16 transitionSubType, const uno::Reference< presentation::XSlideShowView >& view, const uno::Reference< rendering::XBitmap >& leavingBitmap, - const uno::Reference< rendering::XBitmap >& enteringBitmap, - const geometry::RealPoint2D& slideOffset ) throw (uno::RuntimeException) + const uno::Reference< rendering::XBitmap >& enteringBitmap ) + throw (uno::RuntimeException) { - if( transitionType != animations::TransitionType::MISCSHAPEWIPE ) + if( !hasTransition( transitionType, transitionSubType ) ) return uno::Reference< presentation::XTransition >(); - OGLTransitionImpl* 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; - default: - 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) ); - xRes->initWindowFromSlideShowView(view,slideOffset.X,slideOffset.Y); - xRes->setSlides(leavingBitmap,enteringBitmap); + if( bGLXPresent ) { + if( !xRes->initWindowFromSlideShowView(view)) + return uno::Reference< presentation::XTransition >(); + xRes->setSlides(leavingBitmap,enteringBitmap); + } return uno::Reference<presentation::XTransition>(xRes.get()); } |