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