| /************************************************************** |
| * |
| * 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) |