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