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