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