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