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