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