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