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