merge the formfield patch from ooo-build
[ooovba.git] / slideshow / source / engine / OGLTrans / OGLTrans_TransitionerImpl.cxx
blob01d513cc7a06cd7e222c3ad518089bbc667af400
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: OGLTrans_TransitionerImpl.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #define GLX_GLXEXT_PROTOTYPES 1
32 #include "OGLTrans_TransitionImpl.hxx"
34 #include <com/sun/star/beans/XFastPropertySet.hpp>
35 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
36 #include <com/sun/star/rendering/ColorComponentTag.hpp>
37 #include <com/sun/star/rendering/ColorSpaceType.hpp>
38 #include <com/sun/star/animations/TransitionType.hpp>
39 #include <com/sun/star/animations/TransitionSubType.hpp>
40 #include <com/sun/star/presentation/XTransitionFactory.hpp>
41 #include <com/sun/star/presentation/XTransition.hpp>
42 #include <com/sun/star/presentation/XSlideShowView.hpp>
43 #include <com/sun/star/uno/XComponentContext.hpp>
44 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
45 #include <com/sun/star/geometry/IntegerSize2D.hpp>
47 #include <cppuhelper/compbase1.hxx>
48 #include <cppuhelper/basemutex.hxx>
49 #include <cppuhelper/factory.hxx>
50 #include <rtl/ref.hxx>
52 #include <comphelper/servicedecl.hxx>
54 #include <canvas/canvastools.hxx>
55 #include <tools/gen.hxx>
56 #include <vcl/window.hxx>
57 #include <vcl/syschild.hxx>
59 #include <boost/noncopyable.hpp>
61 #include <GL/gl.h>
62 #include <GL/glu.h>
65 #if defined( WNT )
66 #include <tools/prewin.h>
67 #include <windows.h>
68 #include <tools/postwin.h>
69 #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
70 #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
71 #elif defined( OS2 )
72 #elif defined( QUARTZ )
73 #include "premac.h"
74 #include <Cocoa/Cocoa.h>
75 #include "postmac.h"
76 #elif defined( UNX )
77 namespace unx
79 #include <X11/keysym.h>
80 #include <X11/X.h>
81 #include <GL/glx.h>
82 #include <GL/glxext.h>
84 #endif
85 #include <vcl/sysdata.hxx>
87 #ifdef DEBUG
88 #include <boost/date_time/posix_time/posix_time.hpp>
89 using namespace ::boost::posix_time;
91 static ptime t1;
92 static ptime t2;
94 #define DBG(x) x
95 #else
96 #define DBG(x)
97 #endif
99 using namespace ::com::sun::star;
100 using ::com::sun::star::beans::XFastPropertySet;
101 using ::com::sun::star::uno::Any;
102 using ::com::sun::star::uno::Reference;
103 using ::com::sun::star::uno::Sequence;
104 using ::com::sun::star::uno::UNO_QUERY;
105 using ::com::sun::star::uno::UNO_QUERY_THROW;
107 namespace
110 typedef cppu::WeakComponentImplHelper1<presentation::XTransition> OGLTransitionerImplBase;
112 namespace
114 struct OGLFormat
116 GLint nInternalFormat;
117 GLenum eFormat;
118 GLenum eType;
121 /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
123 int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
125 using namespace rendering::ColorComponentTag;
127 static const sal_Int8 aOrderTable[] =
129 RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
130 RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
131 ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
132 ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
135 const sal_Int32 nNumComps(rTags.getLength());
136 const sal_Int8* pLine=aOrderTable;
137 for(int i=0; i<4; ++i)
139 int j=0;
140 while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
141 ++j;
143 // all of the line passed, this is a match!
144 if( j==nNumComps )
145 return i;
147 pLine+=4;
150 return -1;
154 // not thread safe
155 static bool errorTriggered;
156 int oglErrorHandler( unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/ )
158 errorTriggered = true;
160 return 0;
163 /** This is the Transitioner class for OpenGL 3D transitions in
164 * slideshow. At the moment, it's Linux only. This class is implicitly
165 * constructed from XTransitionFactory.
167 class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable, public OGLTransitionerImplBase
169 public:
170 explicit OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition);
171 bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
172 void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
173 static bool initialize( const Reference< presentation::XSlideShowView >& xView );
175 // XTransition
176 virtual void SAL_CALL update( double nTime )
177 throw (uno::RuntimeException);
178 virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
179 const Reference< rendering::XBitmap >& rLeavingBitmap,
180 const Reference< rendering::XBitmap >& rEnteringBitmap )
181 throw (uno::RuntimeException);
183 protected:
184 void disposeContextAndWindow();
185 void disposeTextures();
187 // WeakComponentImplHelperBase
188 virtual void SAL_CALL disposing();
190 bool isDisposed() const
192 return (rBHelper.bDisposed || rBHelper.bInDispose);
195 bool createWindow( Window* pPWindow );
196 void createTexture( unsigned int* texID,
197 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
198 unx::GLXPixmap pixmap,
199 bool usePixmap,
200 #endif
201 bool useMipmap,
202 uno::Sequence<sal_Int8>& data,
203 const OGLFormat* pFormat );
204 void prepareEnvironment ();
205 const OGLFormat* chooseFormats();
207 private:
208 /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
210 void GLInitSlides();
213 /// Holds the information of our new child window
214 struct GLWindow
216 #if defined( WNT )
217 HWND hWnd;
218 HDC hDC;
219 HGLRC hRC;
220 #elif defined( OS2 )
221 #elif defined( QUARTZ )
222 #elif defined( UNX )
223 unx::Display* dpy;
224 int screen;
225 unx::Window win;
226 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
227 unx::GLXFBConfig fbc;
228 #endif
229 unx::XVisualInfo* vi;
230 unx::GLXContext ctx;
231 #endif
232 unsigned int bpp;
233 unsigned int Width;
234 unsigned int Height;
235 const char* GLXExtensions;
236 const GLubyte* GLExtensions;
238 bool HasGLXExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, (const GLubyte*) GLXExtensions ); }
239 bool HasGLExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, GLExtensions ); }
240 } GLWin;
242 /** OpenGL handle to the leaving slide's texture
244 unsigned int GLleavingSlide;
245 /** OpenGL handle to the entering slide's texture
247 unsigned int GLenteringSlide;
249 /** pointer to our window which we MIGHT create.
251 class SystemChildWindow* pWindow;
253 Reference< presentation::XSlideShowView > mxView;
254 Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
255 Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
257 /** raw bytes of the entering bitmap
259 uno::Sequence<sal_Int8> EnteringBytes;
261 /** raw bytes of the leaving bitmap
263 uno::Sequence<sal_Int8> LeavingBytes;
265 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
266 unx::GLXPixmap LeavingPixmap;
267 unx::GLXPixmap EnteringPixmap;
268 #endif
269 bool mbRestoreSync;
270 bool mbUseLeavingPixmap;
271 bool mbUseEnteringPixmap;
272 bool mbFreeLeavingPixmap;
273 bool mbFreeEnteringPixmap;
274 unx::Pixmap maLeavingPixmap;
275 unx::Pixmap maEnteringPixmap;
277 /** the form the raw bytes are in for the bitmaps
279 rendering::IntegerBitmapLayout SlideBitmapLayout;
281 /** the size of the slides
283 geometry::IntegerSize2D SlideSize;
285 /** Our Transition to be used.
287 OGLTransitionImpl* pTransition;
289 public:
290 /** whether we are running on ATI fglrx with bug related to textures
292 static bool cbBrokenTexturesATI;
294 /** GL version
296 static float cnGLVersion;
297 float mnGLXVersion;
299 /** Whether Mesa is the OpenGL vendor
301 static bool cbMesa;
304 whether the display has GLX extension
306 static bool cbGLXPresent;
309 whether texture from pixmap extension is available
311 bool mbTextureFromPixmap;
314 whether to generate mipmaped textures
316 bool mbGenerateMipmap;
319 whether we have visual which can be used for texture_from_pixmap extension
321 bool mbHasTFPVisual;
323 #ifdef DEBUG
324 ptime t3;
325 ptime t4;
326 ptime t5;
327 ptime t6;
328 time_duration total_update;
329 int frame_count;
330 #endif
333 // declare the static variables as some gcc versions have problems declaring them automaticaly
334 bool OGLTransitionerImpl::cbBrokenTexturesATI;
335 float OGLTransitionerImpl::cnGLVersion;
336 bool OGLTransitionerImpl::cbMesa;
337 bool OGLTransitionerImpl::cbGLXPresent;
339 bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView )
341 // not thread safe
342 static bool initialized = false;
344 if( !initialized ) {
345 OGLTransitionerImpl *instance;
347 instance = new OGLTransitionerImpl( NULL );
348 if( instance->initWindowFromSlideShowView( xView ) ) {
350 const GLubyte* version = glGetString( GL_VERSION );
351 if( version && version[0] ) {
352 cnGLVersion = version[0] - '0';
353 if( version[1] == '.' && version[2] )
354 cnGLVersion += (version[2] - '0')/10.0;
355 } else
356 cnGLVersion = 1.0;
357 OSL_TRACE("GL version: %s parsed: %f", version, cnGLVersion );
359 const GLubyte* vendor = glGetString( GL_VENDOR );
360 cbMesa = ( vendor && strstr( (const char *) vendor, "Mesa" ) );
361 OSL_TRACE("GL vendor: %s identified as Mesa: %d", vendor, cbMesa );
363 /* TODO: check for version once the bug in fglrx driver is fixed */
364 cbBrokenTexturesATI = (vendor && strcmp( (const char *) vendor, "ATI Technologies Inc." ) == 0 );
366 instance->disposing();
367 cbGLXPresent = true;
368 } else
369 cbGLXPresent = false;
371 delete instance;
372 initialized = true;
375 return cbGLXPresent;
378 bool OGLTransitionerImpl::createWindow( Window* pPWindow )
380 const SystemEnvData* sysData(pPWindow->GetSystemData());
381 #if defined( WNT )
382 GLWin.hWnd = sysData->hWnd;
383 #elif defined( UNX )
384 GLWin.dpy = reinterpret_cast<unx::Display*>(sysData->pDisplay);
386 if( unx::glXQueryExtension( GLWin.dpy, NULL, NULL ) == false )
387 return false;
389 GLWin.win = sysData->aWindow;
391 OSL_TRACE("parent window: %d", GLWin.win);
393 unx::XWindowAttributes xattr;
394 unx::XGetWindowAttributes( GLWin.dpy, GLWin.win, &xattr );
396 GLWin.screen = XScreenNumberOfScreen( xattr.screen );
398 unx::XVisualInfo* vi( NULL );
399 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
400 unx::XVisualInfo* visinfo;
401 unx::XVisualInfo* firstVisual( NULL );
402 #endif
403 static int attrList3[] =
405 GLX_RGBA,//only TrueColor or DirectColor
406 //single buffered
407 GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
408 GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
409 GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
410 GLX_DEPTH_SIZE,0,//no depth buffer
411 None
413 static int attrList2[] =
415 GLX_RGBA,//only TrueColor or DirectColor
416 /// single buffered
417 GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
418 GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
419 GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
420 GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
421 None
423 static int attrList1[] =
425 GLX_RGBA,//only TrueColor or DirectColor
426 GLX_DOUBLEBUFFER,/// only double buffer
427 GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
428 GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
429 GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
430 GLX_DEPTH_SIZE,0,/// no depth buffer
431 None
433 static int attrList0[] =
435 GLX_RGBA,//only TrueColor or DirectColor
436 GLX_DOUBLEBUFFER,/// only double buffer
437 GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
438 GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
439 GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
440 GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
441 None
443 static int* attrTable[] =
445 attrList0,
446 attrList1,
447 attrList2,
448 attrList3,
449 NULL
451 int** pAttributeTable = attrTable;
452 const SystemEnvData* pChildSysData = NULL;
453 delete pWindow;
454 pWindow=NULL;
456 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
457 unx::GLXFBConfig* fbconfigs = NULL;
458 int nfbconfigs, value, i = 0;
459 #endif
461 while( *pAttributeTable )
463 // try to find a visual for the current set of attributes
464 vi = unx::glXChooseVisual( GLWin.dpy,
465 GLWin.screen,
466 *pAttributeTable );
468 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
469 if( vi ) {
470 if( !firstVisual )
471 firstVisual = vi;
472 OSL_TRACE("trying VisualID %08X", vi->visualid);
473 fbconfigs = glXGetFBConfigs (GLWin.dpy, GLWin.screen, &nfbconfigs);
474 for ( ; i < nfbconfigs; i++)
476 visinfo = glXGetVisualFromFBConfig (GLWin.dpy, fbconfigs[i]);
477 if( !visinfo || visinfo->visualid != vi->visualid )
478 continue;
480 glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
481 if (!(value & GLX_PIXMAP_BIT))
482 continue;
484 glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
485 GLX_BIND_TO_TEXTURE_TARGETS_EXT,
486 &value);
487 if (!(value & GLX_TEXTURE_2D_BIT_EXT))
488 continue;
490 glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
491 GLX_BIND_TO_TEXTURE_RGB_EXT,
492 &value);
493 if (value == FALSE)
494 continue;
496 glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
497 GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
498 &value);
499 if (value == FALSE)
500 continue;
502 /* TODO: handle non Y inverted cases */
503 break;
506 if( i != nfbconfigs || ( firstVisual && pAttributeTable[1] == NULL ) ) {
507 if( i != nfbconfigs ) {
508 vi = glXGetVisualFromFBConfig( GLWin.dpy, fbconfigs[i] );
509 mbHasTFPVisual = true;
510 OSL_TRACE("found visual suitable for texture_from_pixmap");
511 } else {
512 vi = firstVisual;
513 mbHasTFPVisual = false;
514 OSL_TRACE("did not find visual suitable for texture_from_pixmap, using %08X", vi->visualid);
516 #else
517 if( vi ) {
518 #endif
519 SystemWindowData winData;
520 winData.nSize = sizeof(winData);
521 OSL_TRACE("using VisualID %08X", vi->visualid);
522 winData.pVisual = (void*)(vi->visual);
523 pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
524 pChildSysData = pWindow->GetSystemData();
525 if( pChildSysData ) {
526 break;
527 } else {
528 delete pWindow, pWindow=NULL;
531 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
533 #endif
535 ++pAttributeTable;
537 #endif
539 #if defined( WNT )
540 const SystemEnvData* pChildSysData = NULL;
541 SystemWindowData winData;
542 winData.nSize = sizeof(winData);
543 pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
544 pChildSysData = pWindow->GetSystemData();
545 #endif
547 if( pWindow )
549 pWindow->SetMouseTransparent( TRUE );
550 pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
551 pWindow->EnableEraseBackground( FALSE );
552 pWindow->SetControlForeground();
553 pWindow->SetControlBackground();
554 pWindow->EnablePaint(FALSE);
555 #if defined( WNT )
556 GLWin.hWnd = sysData->hWnd;
557 #elif defined( UNX )
558 GLWin.dpy = reinterpret_cast<unx::Display*>(pChildSysData->pDisplay);
559 GLWin.win = pChildSysData->aWindow;
560 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
561 if( mbHasTFPVisual )
562 GLWin.fbc = fbconfigs[i];
563 #endif
564 GLWin.vi = vi;
565 GLWin.GLXExtensions = unx::glXQueryExtensionsString( GLWin.dpy, GLWin.screen );
566 OSL_TRACE("available GLX extensions: %s", GLWin.GLXExtensions);
567 #endif
569 return true;
572 return false;
575 bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
577 osl::MutexGuard const guard( m_aMutex );
579 if (isDisposed())
580 return false;
582 mxView.set( xView, UNO_QUERY );
583 if( !mxView.is() )
584 return false;
586 /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
587 uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
588 uno::Sequence< uno::Any > aDeviceParams;
589 ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
591 ::rtl::OUString aImplName;
592 aDeviceParams[ 0 ] >>= aImplName;
594 sal_Int64 aVal = 0;
595 aDeviceParams[1] >>= aVal;
596 if( !createWindow( reinterpret_cast< Window* >( aVal ) ) )
597 return false;
599 awt::Rectangle aCanvasArea = mxView->getCanvasArea();
600 pWindow->SetPosSizePixel(aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
601 GLWin.Width = aCanvasArea.Width;
602 GLWin.Height = aCanvasArea.Height;
603 OSL_TRACE("canvas area: %d,%d - %dx%d", aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
605 #if defined( WNT )
606 GLWin.hDC = GetDC(GLWin.hWnd);
607 #elif defined( UNX )
608 GLWin.ctx = glXCreateContext(GLWin.dpy,
609 GLWin.vi,
611 GL_TRUE);
612 if( GLWin.ctx == NULL ) {
613 OSL_TRACE("unable to create GLX context");
614 return false;
616 #endif
618 #if defined( WNT )
619 PIXELFORMATDESCRIPTOR PixelFormatFront = // PixelFormat Tells Windows How We Want Things To Be
621 sizeof(PIXELFORMATDESCRIPTOR),
622 1, // Version Number
623 PFD_DRAW_TO_WINDOW |
624 PFD_SUPPORT_OPENGL |
625 PFD_DOUBLEBUFFER,
626 PFD_TYPE_RGBA, // Request An RGBA Format
627 (BYTE)32, // Select Our Color Depth
628 0, 0, 0, 0, 0, 0, // Color Bits Ignored
629 0, // No Alpha Buffer
630 0, // Shift Bit Ignored
631 0, // No Accumulation Buffer
632 0, 0, 0, 0, // Accumulation Bits Ignored
633 64, // 32 bit Z-BUFFER
634 0, // 0 bit stencil buffer
635 0, // No Auxiliary Buffer
636 0, // now ignored
637 0, // Reserved
638 0, 0, 0 // Layer Masks Ignored
640 int WindowPix = ChoosePixelFormat(GLWin.hDC,&PixelFormatFront);
641 SetPixelFormat(GLWin.hDC,WindowPix,&PixelFormatFront);
642 GLWin.hRC = wglCreateContext(GLWin.hDC);
643 wglMakeCurrent(GLWin.hDC,GLWin.hRC);
644 #elif defined( UNX )
645 if( !glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx ) ) {
646 OSL_TRACE("unable to select current GLX context");
647 return false;
650 int glxMinor, glxMajor;
651 mnGLXVersion = 0;
652 if( glXQueryVersion( GLWin.dpy, &glxMajor, &glxMinor ) )
653 mnGLXVersion = glxMajor + 0.1*glxMinor;
654 OSL_TRACE("available GLX version: %f", mnGLXVersion);
656 GLWin.GLExtensions = glGetString( GL_EXTENSIONS );
657 OSL_TRACE("available GL extensions: %s", GLWin.GLExtensions);
659 mbTextureFromPixmap = GLWin.HasGLXExtension( "GLX_EXT_texture_from_pixmap" );
660 mbGenerateMipmap = GLWin.HasGLExtension( "GL_SGIS_generate_mipmap" );
662 if( GLWin.HasGLXExtension("GLX_SGI_swap_control" ) ) {
663 // enable vsync
664 typedef GLint (*glXSwapIntervalProc)(GLint);
665 glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) unx::glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
666 if( glXSwapInterval ) {
667 int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
669 // replace error handler temporarily
670 oldHandler = unx::XSetErrorHandler( oglErrorHandler );
672 errorTriggered = false;
674 glXSwapInterval( 1 );
676 // sync so that we possibly get an XError
677 unx::glXWaitGL();
678 XSync(GLWin.dpy, false);
680 if( errorTriggered )
681 OSL_TRACE("error when trying to set swap interval, NVIDIA or Mesa bug?");
682 else
683 OSL_TRACE("set swap interval to 1 (enable vsync)");
685 // restore the error handler
686 unx::XSetErrorHandler( oldHandler );
689 #endif
691 glEnable(GL_CULL_FACE);
692 glCullFace(GL_BACK);
693 glClearColor (0, 0, 0, 0);
694 glClear(GL_COLOR_BUFFER_BIT);
695 #if defined( WNT )
696 SwapBuffers(GLWin.hDC);
697 #elif defined( UNX )
698 unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
699 #endif
701 glEnable(GL_LIGHTING);
702 GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
703 GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
704 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
705 glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
706 glEnable(GL_LIGHT0);
707 glEnable(GL_NORMALIZE);
709 if( LeavingBytes.hasElements() && EnteringBytes.hasElements())
710 GLInitSlides();//we already have uninitialized slides, let's initialize
712 if( pTransition && pTransition->mnRequiredGLVersion <= cnGLVersion )
713 pTransition->prepare( GLleavingSlide, GLenteringSlide );
715 return true;
718 void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
719 const uno::Reference< rendering::XBitmap >& xEnteringSlide )
721 osl::MutexGuard const guard( m_aMutex );
723 if (isDisposed())
724 return;
726 mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
727 mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
728 Reference< XFastPropertySet > xLeavingSet( xLeavingSlide , UNO_QUERY );
729 Reference< XFastPropertySet > xEnteringSet( xEnteringSlide , UNO_QUERY );
731 geometry::IntegerRectangle2D SlideRect;
732 SlideSize = mxLeavingBitmap->getSize();
733 SlideRect.X1 = 0;
734 SlideRect.X2 = SlideSize.Width;
735 SlideRect.Y1 = 0;
736 SlideRect.Y2 = SlideSize.Height;
738 OSL_TRACE("leaving bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
739 SlideSize = mxEnteringBitmap->getSize();
740 OSL_TRACE("entering bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
742 #ifdef UNX
743 unx::glXWaitGL();
744 XSync(GLWin.dpy, false);
745 #endif
747 #ifdef DEBUG
748 t1 = microsec_clock::local_time();
749 #endif
751 mbUseLeavingPixmap = false;
752 mbUseEnteringPixmap = false;
754 #ifdef UNX
755 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
757 if( mnGLXVersion >= 1.2999 && mbTextureFromPixmap && xLeavingSet.is() && xEnteringSet.is() && mbHasTFPVisual ) {
758 Sequence< Any > leaveArgs;
759 Sequence< Any > enterArgs;
760 if( (xLeavingSet->getFastPropertyValue( 1 ) >>= leaveArgs) &&
761 (xEnteringSet->getFastPropertyValue( 1 ) >>= enterArgs) ) {
762 OSL_TRACE ("pixmaps available");
764 sal_Int32 depth;
766 leaveArgs[0] >>= mbFreeLeavingPixmap;
767 enterArgs[0] >>= mbFreeEnteringPixmap;
768 leaveArgs[1] >>= maLeavingPixmap;
769 enterArgs[1] >>= maEnteringPixmap;
770 leaveArgs[2] >>= depth;
772 int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
773 GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
774 GLX_MIPMAP_TEXTURE_EXT, True,
775 None };
778 // sync so that we possibly get an pending XError, before we set our handler.
779 // this way we will not miss any error from other code
780 unx::glXWaitGL();
781 XSync(GLWin.dpy, false);
783 int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
785 // replace error handler temporarily
786 oldHandler = unx::XSetErrorHandler( oglErrorHandler );
788 errorTriggered = false;
789 LeavingPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maLeavingPixmap, pixmapAttribs );
791 // sync so that we possibly get an XError
792 unx::glXWaitGL();
793 XSync(GLWin.dpy, false);
795 if( !errorTriggered )
796 mbUseLeavingPixmap = true;
797 else {
798 OSL_TRACE("XError triggered");
799 if( mbFreeLeavingPixmap ) {
800 unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
801 mbFreeLeavingPixmap = false;
803 errorTriggered = false;
806 EnteringPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maEnteringPixmap, pixmapAttribs );
808 // sync so that we possibly get an XError
809 unx::glXWaitGL();
810 XSync(GLWin.dpy, false);
812 OSL_TRACE("created glx pixmap %p and %p depth: %d", LeavingPixmap, EnteringPixmap, depth);
813 if( !errorTriggered )
814 mbUseEnteringPixmap = true;
815 else {
816 OSL_TRACE("XError triggered");
817 if( mbFreeEnteringPixmap ) {
818 unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
819 mbFreeEnteringPixmap = false;
823 // restore the error handler
824 unx::XSetErrorHandler( oldHandler );
828 #endif
829 #endif
830 if( !mbUseLeavingPixmap )
831 LeavingBytes = mxLeavingBitmap->getData(SlideBitmapLayout,SlideRect);
832 if( !mbUseEnteringPixmap )
833 EnteringBytes = mxEnteringBitmap->getData(SlideBitmapLayout,SlideRect);
835 // TODO
836 #ifdef UNX
837 if(GLWin.ctx)//if we have a rendering context, let's init the slides
838 #endif
839 GLInitSlides();
841 OSL_ENSURE(SlideBitmapLayout.PlaneStride == 0,"only handle no plane stride now");
843 #ifdef UNX
844 /* flush & sync */
845 unx::glXWaitGL();
846 XSync( GLWin.dpy, false );
848 // synchronized X still gives us much smoother play
849 // I suspect some issues in above code in slideshow
850 // synchronize whole transition for now
851 XSynchronize( GLWin.dpy, true );
852 mbRestoreSync = true;
853 #endif
856 void OGLTransitionerImpl::createTexture( unsigned int* texID,
857 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
858 unx::GLXPixmap pixmap,
859 bool usePixmap,
860 #endif
861 bool useMipmap,
862 uno::Sequence<sal_Int8>& data,
863 const OGLFormat* pFormat )
865 glDeleteTextures( 1, texID );
866 glGenTextures( 1, texID );
867 glBindTexture( GL_TEXTURE_2D, *texID );
868 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
869 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
871 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
872 unx::PFNGLXBINDTEXIMAGEEXTPROC myglXBindTexImageEXT = (unx::PFNGLXBINDTEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXBindTexImageEXT" );
874 if( usePixmap ) {
875 if( mbGenerateMipmap )
876 glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, True);
877 myglXBindTexImageEXT (GLWin.dpy, pixmap, GLX_FRONT_LEFT_EXT, NULL);
878 if( mbGenerateMipmap && useMipmap ) {
879 OSL_TRACE("use mipmaps");
880 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
881 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
882 } else {
883 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
884 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
886 } else {
887 #endif
888 if( !pFormat )
890 // force-convert color to ARGB8888 int color space
891 uno::Sequence<sal_Int8> tempBytes(
892 SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
893 data,
894 canvas::tools::getStdColorSpace()));
895 gluBuild2DMipmaps(GL_TEXTURE_2D,
897 SlideSize.Width,
898 SlideSize.Height,
899 GL_RGBA,
900 GL_UNSIGNED_BYTE,
901 &tempBytes[0]);
902 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
903 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
905 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
906 GLfloat largest_supported_anisotropy;
907 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
908 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
909 } else {
910 if( pTransition && !cbBrokenTexturesATI && !useMipmap) {
911 glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
912 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
913 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
914 } else {
915 gluBuild2DMipmaps( GL_TEXTURE_2D, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
916 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
917 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); //TRILINEAR FILTERING
919 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
920 GLfloat largest_supported_anisotropy;
921 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
922 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
925 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
927 #endif
928 OSL_ENSURE(glIsTexture(*texID), "Can't generate Leaving slide textures in OpenGL");
931 void OGLTransitionerImpl::prepareEnvironment()
933 glMatrixMode(GL_PROJECTION);
934 glLoadIdentity();
935 double EyePos(10.0);
936 double RealF(1.0);
937 double RealN(-1.0);
938 double RealL(-1.0);
939 double RealR(1.0);
940 double RealB(-1.0);
941 double RealT(1.0);
942 double ClipN(EyePos+5.0*RealN);
943 double ClipF(EyePos+15.0*RealF);
944 double ClipL(RealL*8.0);
945 double ClipR(RealR*8.0);
946 double ClipB(RealB*8.0);
947 double ClipT(RealT*8.0);
948 //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.
949 glScaled( 1.0 / ( ( ( RealR * 2.0 * ClipN ) / ( EyePos * ( ClipR - ClipL ) ) ) - ( ( ClipR + ClipL ) / ( ClipR - ClipL ) ) ),
950 1.0 / ( ( ( RealT * 2.0 * ClipN ) / ( EyePos * ( ClipT - ClipB ) ) ) - ( ( ClipT + ClipB ) / ( ClipT - ClipB ) ) ),
951 1.0 );
952 glFrustum(ClipL,ClipR,ClipB,ClipT,ClipN,ClipF);
953 glMatrixMode(GL_MODELVIEW);
954 glLoadIdentity();
955 glTranslated(0,0,-EyePos);
958 const OGLFormat* OGLTransitionerImpl::chooseFormats()
960 const OGLFormat* pDetectedFormat=NULL;
961 uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
962 SlideBitmapLayout.ColorSpace);
964 if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
965 xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) )
967 /* table for canvas->OGL format mapping. outer index is number
968 of color components (0:3, 1:4), then comes bits per pixel
969 (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
970 2:argb, 3:abgr)
972 static const OGLFormat lcl_RGB24[] =
974 // 24 bit RGB
975 {3, GL_BGR, GL_UNSIGNED_BYTE},
976 {3, GL_RGB, GL_UNSIGNED_BYTE},
977 {3, GL_BGR, GL_UNSIGNED_BYTE},
978 {3, GL_RGB, GL_UNSIGNED_BYTE}
981 #if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
982 // more format constants available
983 static const OGLFormat lcl_RGB16[] =
985 // 16 bit RGB
986 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
987 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
988 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
989 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
992 static const OGLFormat lcl_ARGB16_4[] =
994 // 16 bit ARGB
995 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
996 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
997 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
998 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
1001 static const OGLFormat lcl_ARGB16_5[] =
1003 // 16 bit ARGB
1004 {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
1005 {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
1006 {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
1007 {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
1010 static const OGLFormat lcl_ARGB32[] =
1012 // 32 bit ARGB
1013 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
1014 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
1015 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
1016 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
1019 const uno::Sequence<sal_Int8> aComponentTags(
1020 xIntColorSpace->getComponentTags());
1021 const uno::Sequence<sal_Int32> aComponentBitcounts(
1022 xIntColorSpace->getComponentBitCounts());
1023 const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
1024 const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
1026 // supported component ordering?
1027 const int nComponentOrderIndex(
1028 calcComponentOrderIndex(aComponentTags));
1029 if( nComponentOrderIndex != -1 )
1031 switch( nBitsPerPixel )
1033 case 16:
1034 if( nNumComponents == 3 )
1036 pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
1038 else if( nNumComponents == 4 )
1040 if( aComponentBitcounts[1] == 4 )
1042 pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
1044 else if( aComponentBitcounts[1] == 5 )
1046 pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
1049 break;
1050 case 24:
1051 if( nNumComponents == 3 )
1053 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
1055 break;
1056 case 32:
1057 pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
1058 break;
1061 #else
1062 const uno::Sequence<sal_Int8> aComponentTags(
1063 xIntColorSpace->getComponentTags());
1064 const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
1065 if( aComponentTags.getLength() == 3 &&
1066 nComponentOrderIndex != -1 &&
1067 xIntColorSpace->getBitsPerPixel() == 24 )
1069 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
1071 #endif
1074 return pDetectedFormat;
1077 void OGLTransitionerImpl::GLInitSlides()
1079 osl::MutexGuard const guard( m_aMutex );
1081 if (isDisposed() || pTransition->mnRequiredGLVersion > cnGLVersion)
1082 return;
1084 prepareEnvironment();
1086 const OGLFormat* pFormat = NULL;
1087 if( !mbUseLeavingPixmap || !mbUseEnteringPixmap )
1088 pFormat = chooseFormats();
1090 createTexture( &GLleavingSlide,
1091 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
1092 LeavingPixmap,
1093 mbUseLeavingPixmap,
1094 #endif
1095 pTransition->mbUseMipMapLeaving,
1096 LeavingBytes,
1097 pFormat );
1099 createTexture( &GLenteringSlide,
1100 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
1101 EnteringPixmap,
1102 mbUseEnteringPixmap,
1103 #endif
1104 pTransition->mbUseMipMapEntering,
1105 EnteringBytes,
1106 pFormat );
1108 #ifdef UNX
1109 unx::glXWaitGL();
1110 XSync(GLWin.dpy, false);
1111 #endif
1113 #ifdef DEBUG
1114 t2 = microsec_clock::local_time();
1115 OSL_TRACE("textures created in: %s", to_simple_string( t2 - t1 ).c_str());
1116 #endif
1119 void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException)
1121 #ifdef DEBUG
1122 frame_count ++;
1123 t3 = microsec_clock::local_time();
1124 if( frame_count == 1 ) {
1125 t5 = t3;
1126 total_update = seconds (0);
1128 #endif
1129 osl::MutexGuard const guard( m_aMutex );
1131 if (isDisposed() || !cbGLXPresent || pTransition->mnRequiredGLVersion > cnGLVersion)
1132 return;
1134 #ifdef WNT
1135 wglMakeCurrent(GLWin.hDC,GLWin.hRC);
1136 #endif
1137 #ifdef UNX
1138 glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
1139 #endif
1141 glEnable(GL_DEPTH_TEST);
1142 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1144 if(pTransition)
1145 pTransition->display( nTime, GLleavingSlide, GLenteringSlide,
1146 SlideSize.Width, SlideSize.Height,
1147 static_cast<double>(GLWin.Width),
1148 static_cast<double>(GLWin.Height) );
1150 #if defined( WNT )
1151 SwapBuffers(GLWin.hDC);
1152 #elif defined( UNX )
1153 unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
1154 #endif
1155 if( pWindow )
1156 pWindow->Show();
1158 #ifdef UNX
1159 /* flush & sync */
1160 unx::glXWaitGL();
1161 XSync( GLWin.dpy, false );
1162 #endif
1164 #ifdef DEBUG
1165 t4 = microsec_clock::local_time();
1167 OSL_TRACE("update time: %f", nTime);
1168 OSL_TRACE("update took: %s", to_simple_string( t4 - t3 ).c_str());
1169 total_update += (t4 - t3);
1170 #endif
1173 void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
1174 const Reference< rendering::XBitmap >& rLeavingBitmap,
1175 const Reference< rendering::XBitmap >& rEnteringBitmap )
1176 throw (uno::RuntimeException)
1178 OSL_TRACE("transitioner: view changed");
1180 disposeTextures();
1181 disposeContextAndWindow();
1183 initWindowFromSlideShowView( rView );
1184 setSlides( rLeavingBitmap, rEnteringBitmap );
1187 void OGLTransitionerImpl::disposeContextAndWindow()
1189 #if defined( WNT )
1190 if (GLWin.hRC)
1192 wglMakeCurrent( GLWin.hDC, 0 ); // kill Device Context
1193 wglDeleteContext( GLWin.hRC ); // Kill Render Context
1194 ReleaseDC( GLWin.hWnd, GLWin.hDC ); // Release Window
1196 #elif defined( UNX )
1197 if(GLWin.ctx)
1199 glXMakeCurrent(GLWin.dpy, None, NULL);
1200 if( glGetError() != GL_NO_ERROR ) {
1201 OSL_TRACE("glError: %s", (char *)gluErrorString(glGetError()));
1203 glXDestroyContext(GLWin.dpy, GLWin.ctx);
1204 GLWin.ctx = NULL;
1206 #endif
1207 if( pWindow ) {
1208 delete pWindow;
1209 pWindow = NULL;
1210 GLWin.win = 0;
1214 void OGLTransitionerImpl::disposeTextures()
1216 #ifdef WNT
1217 wglMakeCurrent(GLWin.hDC,GLWin.hRC);
1218 #endif
1219 #ifdef UNX
1220 glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
1221 #endif
1223 #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
1224 unx::PFNGLXRELEASETEXIMAGEEXTPROC myglXReleaseTexImageEXT = (unx::PFNGLXRELEASETEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXReleaseTexImageEXT" );
1225 if( mbUseLeavingPixmap ) {
1227 myglXReleaseTexImageEXT( GLWin.dpy, LeavingPixmap, GLX_FRONT_LEFT_EXT );
1228 glXDestroyGLXPixmap( GLWin.dpy, LeavingPixmap );
1229 LeavingPixmap = 0;
1230 if( mbFreeLeavingPixmap ) {
1231 unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
1232 mbFreeLeavingPixmap = false;
1233 maLeavingPixmap = 0;
1236 if( mbUseEnteringPixmap ) {
1237 myglXReleaseTexImageEXT( GLWin.dpy, EnteringPixmap, GLX_FRONT_LEFT_EXT );
1238 glXDestroyGLXPixmap( GLWin.dpy, EnteringPixmap );
1239 EnteringPixmap = 0;
1240 if( mbFreeEnteringPixmap ) {
1241 unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
1242 mbFreeEnteringPixmap = false;
1243 maEnteringPixmap = 0;
1246 #endif
1248 if( !mbUseLeavingPixmap ) {
1249 glDeleteTextures(1,&GLleavingSlide);
1250 GLleavingSlide = 0;
1252 if( !mbUseEnteringPixmap ) {
1253 glDeleteTextures(1,&GLenteringSlide);
1254 GLleavingSlide = 0;
1257 mbUseLeavingPixmap = false;
1258 mbUseEnteringPixmap = false;
1261 // we are about to be disposed (someone call dispose() on us)
1262 void OGLTransitionerImpl::disposing()
1264 osl::MutexGuard const guard( m_aMutex );
1266 #ifdef DEBUG
1267 OSL_TRACE("dispose %p\n", this);
1268 if( frame_count ) {
1269 t6 = microsec_clock::local_time();
1270 time_duration duration = t6 - t5;
1271 OSL_TRACE("whole transition (frames: %d) took: %s fps: %f time spent in updates: %s percentage of transition time: %f%%",
1272 frame_count, to_simple_string( duration ).c_str(),
1273 ((double)frame_count*1000000000.0)/duration.total_nanoseconds(),
1274 to_simple_string( total_update ).c_str(),
1275 100*(((double)total_update.total_nanoseconds())/((double)duration.total_nanoseconds()))
1278 #endif
1280 if( pWindow ) {
1282 disposeTextures();
1284 if (pTransition)
1285 pTransition->finish();
1287 #ifdef UNX
1288 if( mbRestoreSync ) {
1289 // try to reestablish synchronize state
1290 char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
1291 XSynchronize( GLWin.dpy, sal_synchronize && *sal_synchronize == '1' );
1293 #endif
1295 disposeContextAndWindow();
1298 if (pTransition)
1299 delete pTransition;
1301 mxLeavingBitmap.clear();
1302 mxEnteringBitmap.clear();
1303 mxView.clear();
1306 OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) :
1307 OGLTransitionerImplBase(m_aMutex),
1308 GLWin(),
1309 GLleavingSlide( 0 ),
1310 GLenteringSlide( 0 ),
1311 pWindow( NULL ),
1312 mxView(),
1313 EnteringBytes(),
1314 LeavingBytes(),
1315 mbRestoreSync( false ),
1316 mbUseLeavingPixmap( false ),
1317 mbUseEnteringPixmap( false ),
1318 SlideBitmapLayout(),
1319 SlideSize(),
1320 pTransition(pOGLTransition)
1322 #if defined( WNT )
1323 GLWin.hWnd = 0;
1324 #elif defined( UNX )
1325 GLWin.ctx = 0;
1326 #endif
1328 DBG(frame_count = 0);
1331 typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
1333 class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
1335 public:
1336 explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) :
1337 OGLTransitionFactoryImplBase(m_aMutex)
1340 // XTransitionFactory
1341 virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException)
1343 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1344 switch( transitionSubType )
1346 case animations::TransitionSubType::ACROSS:
1347 case animations::TransitionSubType::CORNERSOUT:
1348 case animations::TransitionSubType::CIRCLE:
1349 case animations::TransitionSubType::FANOUTHORIZONTAL:
1350 case animations::TransitionSubType::CORNERSIN:
1351 case animations::TransitionSubType::LEFTTORIGHT:
1352 case animations::TransitionSubType::TOPTOBOTTOM:
1353 case animations::TransitionSubType::TOPRIGHT:
1354 case animations::TransitionSubType::TOPLEFT:
1355 case animations::TransitionSubType::BOTTOMRIGHT:
1356 case animations::TransitionSubType::BOTTOMLEFT:
1357 case animations::TransitionSubType::TOPCENTER:
1358 case animations::TransitionSubType::RIGHTCENTER:
1359 case animations::TransitionSubType::BOTTOMCENTER:
1360 return sal_True;
1362 default:
1363 return sal_False;
1365 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1366 return sal_True;
1367 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1368 return sal_True;
1369 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1370 return sal_True;
1371 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1372 return sal_True;
1373 } else
1374 return sal_False;
1377 virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
1378 ::sal_Int16 transitionType,
1379 ::sal_Int16 transitionSubType,
1380 const uno::Reference< presentation::XSlideShowView >& view,
1381 const uno::Reference< rendering::XBitmap >& leavingBitmap,
1382 const uno::Reference< rendering::XBitmap >& enteringBitmap )
1383 throw (uno::RuntimeException)
1385 if( !hasTransition( transitionType, transitionSubType ) )
1386 return uno::Reference< presentation::XTransition >();
1388 bool bGLXPresent = OGLTransitionerImpl::initialize( view );
1390 if( OGLTransitionerImpl::cbMesa && (
1391 ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) ||
1392 ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) ||
1393 ( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) ) )
1394 return uno::Reference< presentation::XTransition >();
1397 OGLTransitionImpl* pTransition = NULL;
1399 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1400 pTransition = new OGLTransitionImpl();
1401 switch( transitionSubType )
1403 case animations::TransitionSubType::ACROSS:
1404 pTransition->makeNByMTileFlip(8,6);
1405 break;
1406 case animations::TransitionSubType::CORNERSOUT:
1407 pTransition->makeOutsideCubeFaceToLeft();
1408 break;
1409 case animations::TransitionSubType::CIRCLE:
1410 pTransition->makeRevolvingCircles(8,128);
1411 break;
1412 case animations::TransitionSubType::FANOUTHORIZONTAL:
1413 pTransition->makeHelix(20);
1414 break;
1415 case animations::TransitionSubType::CORNERSIN:
1416 pTransition->makeInsideCubeFaceToLeft();
1417 break;
1418 case animations::TransitionSubType::LEFTTORIGHT:
1419 pTransition->makeFallLeaving();
1420 break;
1421 case animations::TransitionSubType::TOPTOBOTTOM:
1422 pTransition->makeTurnAround();
1423 break;
1424 case animations::TransitionSubType::TOPRIGHT:
1425 pTransition->makeTurnDown();
1426 break;
1427 case animations::TransitionSubType::TOPLEFT:
1428 pTransition->makeIris();
1429 break;
1430 case animations::TransitionSubType::BOTTOMRIGHT:
1431 pTransition->makeRochade();
1432 break;
1433 case animations::TransitionSubType::BOTTOMLEFT:
1434 pTransition->makeVenetianBlinds( true, 8 );
1435 break;
1436 case animations::TransitionSubType::TOPCENTER:
1437 pTransition->makeVenetianBlinds( false, 6 );
1438 break;
1439 case animations::TransitionSubType::RIGHTCENTER:
1440 pTransition->makeStatic();
1441 break;
1442 case animations::TransitionSubType::BOTTOMCENTER:
1443 pTransition->makeDissolve();
1444 break;
1446 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1447 pTransition = new OGLTransitionImpl();
1448 pTransition->makeFadeSmoothly();
1449 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1450 pTransition = new OGLTransitionImpl();
1451 pTransition->makeFadeThroughBlack();
1452 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1453 pTransition = new OGLTransitionImpl();
1454 pTransition->makeDiamond();
1455 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1456 pTransition = new OGLTransitionImpl();
1457 pTransition->makeNewsflash();
1460 rtl::Reference<OGLTransitionerImpl> xRes(
1461 new OGLTransitionerImpl(pTransition) );
1462 if( bGLXPresent ) {
1463 if( !xRes->initWindowFromSlideShowView(view))
1464 return uno::Reference< presentation::XTransition >();
1465 xRes->setSlides(leavingBitmap,enteringBitmap);
1468 return uno::Reference<presentation::XTransition>(xRes.get());
1474 namespace sdecl = comphelper::service_decl;
1475 #if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
1476 sdecl::class_<OGLTransitionFactoryImpl> serviceImpl;
1477 const sdecl::ServiceDecl OGLTransitionFactoryDecl(
1478 serviceImpl,
1479 #else
1480 const sdecl::ServiceDecl OGLTransitionFactoryDecl(
1481 sdecl::class_<OGLTransitionFactoryImpl>(),
1482 #endif
1483 "com.sun.star.comp.presentation.OGLTransitionFactory",
1484 "com.sun.star.presentation.TransitionFactory" );
1486 // The C shared lib entry points
1487 COMPHELPER_SERVICEDECL_EXPORTS1(OGLTransitionFactoryDecl)