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