1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2008 by Sun Microsystems, Inc.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <boost/make_shared.hpp>
30 #include <boost/shared_ptr.hpp>
32 #include <sal/types.h>
34 #include <com/sun/star/beans/XFastPropertySet.hpp>
35 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
36 #include <com/sun/star/rendering/ColorComponentTag.hpp>
37 #include <com/sun/star/rendering/ColorSpaceType.hpp>
38 #include <com/sun/star/rendering/RenderingIntent.hpp>
39 #include <com/sun/star/util/Endianness.hpp>
40 #include <com/sun/star/animations/TransitionType.hpp>
43 #include <com/sun/star/animations/TransitionSubType.hpp>
44 #include <com/sun/star/presentation/XTransitionFactory.hpp>
45 #include <com/sun/star/presentation/XTransition.hpp>
46 #include <com/sun/star/presentation/XSlideShowView.hpp>
47 #include <com/sun/star/uno/XComponentContext.hpp>
48 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
49 #include <com/sun/star/geometry/IntegerSize2D.hpp>
51 #include <cppuhelper/compbase1.hxx>
52 #include <cppuhelper/basemutex.hxx>
53 #include <cppuhelper/factory.hxx>
54 #include <rtl/ref.hxx>
56 #include <comphelper/servicedecl.hxx>
58 #include <canvas/canvastools.hxx>
60 #include <tools/diagnose_ex.h>
62 #include <vcl/canvastools.hxx>
63 #include <vcl/opengl/OpenGLContext.hxx>
64 #include <vcl/opengl/OpenGLHelper.hxx>
65 #include <vcl/window.hxx>
67 #include <boost/noncopyable.hpp>
69 #include "OGLTrans_TransitionImpl.hxx"
71 #if defined( UNX ) && !defined( MACOSX )
72 #include <X11/keysym.h>
76 #include <vcl/sysdata.hxx>
78 #if OSL_DEBUG_LEVEL > 1
79 #include <boost/date_time/posix_time/posix_time.hpp>
80 using namespace ::boost::posix_time
;
84 using namespace ::com::sun::star
;
85 using ::com::sun::star::beans::XFastPropertySet
;
86 using ::com::sun::star::uno::Any
;
87 using ::com::sun::star::uno::Reference
;
88 using ::com::sun::star::uno::Sequence
;
89 using ::com::sun::star::uno::UNO_QUERY
;
90 using ::com::sun::star::uno::UNO_QUERY_THROW
;
95 typedef cppu::WeakComponentImplHelper1
<presentation::XTransition
> OGLTransitionerImplBase
;
97 #if OSL_DEBUG_LEVEL > 1
101 explicit TimerContext(OUString
const& rWhat
)
103 , m_aStartTime(microsec_clock::local_time())
108 time_duration
const aDuration(microsec_clock::local_time() - m_aStartTime
);
109 SAL_INFO("slideshow.opengl", m_aWhat
<< " took: " << aDuration
);
112 OUString
const m_aWhat
;
113 ptime
const m_aStartTime
;
119 GLint nInternalFormat
;
124 /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
126 int calcComponentOrderIndex(const uno::Sequence
<sal_Int8
>& rTags
)
128 using namespace rendering::ColorComponentTag
;
130 static const sal_Int8 aOrderTable
[] =
132 RGB_RED
, RGB_GREEN
, RGB_BLUE
, ALPHA
,
133 RGB_BLUE
, RGB_GREEN
, RGB_RED
, ALPHA
,
134 ALPHA
, RGB_RED
, RGB_GREEN
, RGB_BLUE
,
135 ALPHA
, RGB_BLUE
, RGB_GREEN
, RGB_RED
,
138 const sal_Int32
nNumComps(rTags
.getLength());
139 const sal_Int8
* pLine
=aOrderTable
;
140 for(int i
=0; i
<4; ++i
)
143 while( j
<4 && j
<nNumComps
&& pLine
[j
] == rTags
[j
] )
146 // all of the line passed, this is a match!
156 #if defined( UNX ) && !defined( MACOSX )
159 static bool errorTriggered
;
160 int oglErrorHandler( Display
* /*dpy*/, XErrorEvent
* /*evnt*/ )
162 errorTriggered
= true;
169 /** This is the Transitioner class for OpenGL 3D transitions in
170 * slideshow. At the moment, it's Linux only. This class is implicitly
171 * constructed from XTransitionFactory.
173 class OGLTransitionerImpl
: private cppu::BaseMutex
, private boost::noncopyable
, public OGLTransitionerImplBase
176 OGLTransitionerImpl();
177 void setTransition( boost::shared_ptr
<OGLTransitionImpl
> pOGLTransition
);
178 bool initialize( const Reference
< presentation::XSlideShowView
>& xView
,
179 const Reference
< rendering::XBitmap
>& xLeavingSlide
,
180 const Reference
< rendering::XBitmap
>& xEnteringSlide
);
183 virtual void SAL_CALL
update( double nTime
)
184 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
185 virtual void SAL_CALL
viewChanged( const Reference
< presentation::XSlideShowView
>& rView
,
186 const Reference
< rendering::XBitmap
>& rLeavingBitmap
,
187 const Reference
< rendering::XBitmap
>& rEnteringBitmap
)
188 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
191 void disposeTextures();
193 // WeakComponentImplHelperBase
194 virtual void SAL_CALL
disposing() SAL_OVERRIDE
;
196 bool isDisposed() const
198 return (rBHelper
.bDisposed
|| rBHelper
.bInDispose
);
201 void createTexture( GLuint
* texID
,
202 #if defined( GLX_EXT_texture_from_pixmap )
207 uno::Sequence
<sal_Int8
>& data
,
208 const OGLFormat
* pFormat
);
209 static void prepareEnvironment();
210 const OGLFormat
* chooseFormats();
213 void impl_initializeFlags( bool const bGLXPresent
);
217 void setSlides( const Reference
< rendering::XBitmap
>& xLeavingSlide
, const uno::Reference
< rendering::XBitmap
>& xEnteringSlide
);
218 void impl_prepareSlides();
220 void impl_createTexture( bool useMipmap
, uno::Sequence
<sal_Int8
>& data
, const OGLFormat
* pFormat
);
222 bool initWindowFromSlideShowView( const uno::Reference
< presentation::XSlideShowView
>& xView
);
223 /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
227 void impl_prepareTransition();
228 void impl_finishTransition();
231 rtl::Reference
<OpenGLContext
> mpContext
;
233 /** OpenGL handle to the leaving slide's texture
235 GLuint maLeavingSlideGL
;
236 /** OpenGL handle to the entering slide's texture
238 GLuint maEnteringSlideGL
;
240 Reference
< presentation::XSlideShowView
> mxView
;
241 Reference
< rendering::XIntegerBitmap
> mxLeavingBitmap
;
242 Reference
< rendering::XIntegerBitmap
> mxEnteringBitmap
;
244 /** raw bytes of the entering bitmap
246 uno::Sequence
<sal_Int8
> maEnteringBytes
;
248 /** raw bytes of the leaving bitmap
250 uno::Sequence
<sal_Int8
> maLeavingBytes
;
252 #if defined( GLX_EXT_texture_from_pixmap )
253 GLXPixmap maLeavingPixmapGL
;
254 GLXPixmap maEnteringPixmapGL
;
256 #if defined( UNX ) && !defined( MACOSX )
259 bool mbUseLeavingPixmap
;
260 bool mbUseEnteringPixmap
;
261 #if defined( GLX_EXT_texture_from_pixmap )
262 bool mbFreeLeavingPixmap
;
263 bool mbFreeEnteringPixmap
;
265 #if defined( UNX ) && !defined( MACOSX )
266 Pixmap maLeavingPixmap
;
267 Pixmap maEnteringPixmap
;
270 /** the form the raw bytes are in for the bitmaps
272 rendering::IntegerBitmapLayout maSlideBitmapLayout
;
274 /** the size of the slides
276 geometry::IntegerSize2D maSlideSize
;
278 /** Our Transition to be used.
280 boost::shared_ptr
<OGLTransitionImpl
> mpTransition
;
283 /** whether we are running on ATI fglrx with bug related to textures
285 bool mbBrokenTexturesATI
;
292 Whether the display has GLX extension on X11, always true otherwise (?)
294 bool mbValidOpenGLContext
;
297 whether to generate mipmaped textures
299 bool mbGenerateMipmap
;
302 whether we have visual which can be used for texture_from_pixmap extension
306 #if OSL_DEBUG_LEVEL > 1
307 ptime maUpdateStartTime
;
308 ptime maUpdateEndTime
;
311 time_duration maTotalUpdateDuration
;
316 bool OGLTransitionerImpl::initialize( const Reference
< presentation::XSlideShowView
>& xView
,
317 const Reference
< rendering::XBitmap
>& xLeavingSlide
,
318 const Reference
< rendering::XBitmap
>& xEnteringSlide
)
320 bool const bValidContext( initWindowFromSlideShowView( xView
) );
321 impl_initializeFlags( bValidContext
);
323 setSlides( xLeavingSlide
, xEnteringSlide
);
326 return mbValidOpenGLContext
;
329 void OGLTransitionerImpl::impl_initializeFlags( bool const bValidContext
)
332 mbValidOpenGLContext
= bValidContext
;
333 if ( bValidContext
) {
334 mnGLVersion
= OpenGLHelper::getGLVersion();
335 SAL_INFO("slideshow.opengl", "GL version: " << mnGLVersion
<< "" );
337 const GLubyte
* vendor
= glGetString( GL_VENDOR
);
339 /* TODO: check for version once the bug in fglrx driver is fixed */
340 mbBrokenTexturesATI
= (vendor
&& strcmp( reinterpret_cast<const char *>(vendor
), "ATI Technologies Inc." ) == 0 );
345 bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference
< presentation::XSlideShowView
>& xView
)
347 osl::MutexGuard
const guard( m_aMutex
);
352 mxView
.set( xView
, UNO_QUERY
);
356 #if OSL_DEBUG_LEVEL > 1
357 TimerContext
aTimerContext("initWindowFromSlideShowView");
360 /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
361 uno::Reference
< rendering::XCanvas
> xCanvas(mxView
->getCanvas(), uno::UNO_QUERY_THROW
);
362 uno::Sequence
< uno::Any
> aDeviceParams
;
363 ::canvas::tools::getDeviceInfo( xCanvas
, aDeviceParams
);
366 aDeviceParams
[ 0 ] >>= aImplName
;
369 aDeviceParams
[1] >>= aVal
;
371 mpContext
= OpenGLContext::Create();
372 mpContext
->requestLegacyContext();
374 if( !mpContext
->init( reinterpret_cast< vcl::Window
* >( aVal
) ) )
376 SAL_INFO("slideshow", "created the context");
379 awt::Rectangle aCanvasArea
= mxView
->getCanvasArea();
380 mpContext
->setWinPosAndSize(Point(aCanvasArea
.X
, aCanvasArea
.Y
), Size(aCanvasArea
.Width
, aCanvasArea
.Height
));
381 SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea
.X
<< "," << aCanvasArea
.Y
<< " - " << aCanvasArea
.Width
<< "x" << aCanvasArea
.Height
);
383 mbGenerateMipmap
= GLEW_SGIS_generate_mipmap
;
386 glEnable(GL_CULL_FACE
);
390 glClearColor (0, 0, 0, 0);
392 glClear(GL_COLOR_BUFFER_BIT
);
395 mpContext
->swapBuffers();
397 glEnable(GL_LIGHTING
);
398 GLfloat light_direction
[] = { 0.0 , 0.0 , 1.0 };
399 GLfloat materialDiffuse
[] = { 1.0 , 1.0 , 1.0 , 1.0};
400 glLightfv(GL_LIGHT0
, GL_SPOT_DIRECTION
, light_direction
);
401 glMaterialfv(GL_FRONT
,GL_DIFFUSE
,materialDiffuse
);
403 glEnable(GL_NORMALIZE
);
405 glViewport(0, 0, aCanvasArea
.Width
, aCanvasArea
.Height
);
411 void OGLTransitionerImpl::setSlides( const uno::Reference
< rendering::XBitmap
>& xLeavingSlide
,
412 const uno::Reference
< rendering::XBitmap
>& xEnteringSlide
)
414 osl::MutexGuard
const guard( m_aMutex
);
419 mxLeavingBitmap
.set( xLeavingSlide
, UNO_QUERY_THROW
);
420 mxEnteringBitmap
.set( xEnteringSlide
, UNO_QUERY_THROW
);
422 maSlideSize
= mxLeavingBitmap
->getSize();
423 SAL_INFO("slideshow.opengl", "leaving bitmap area: " << maSlideSize
.Width
<< "x" << maSlideSize
.Height
);
424 maSlideSize
= mxEnteringBitmap
->getSize();
425 SAL_INFO("slideshow.opengl", "entering bitmap area: " << maSlideSize
.Width
<< "x" << maSlideSize
.Height
);
429 void OGLTransitionerImpl::impl_prepareSlides()
431 Reference
< XFastPropertySet
> xLeavingSet( mxLeavingBitmap
, UNO_QUERY
);
432 Reference
< XFastPropertySet
> xEnteringSet( mxEnteringBitmap
, UNO_QUERY
);
434 geometry::IntegerRectangle2D aSlideRect
;
436 aSlideRect
.X2
= maSlideSize
.Width
;
438 aSlideRect
.Y2
= maSlideSize
.Height
;
444 mbUseLeavingPixmap
= false;
445 mbUseEnteringPixmap
= false;
447 #if defined( GLX_EXT_texture_from_pixmap )
449 const GLWindow
& rGLWindow(mpContext
->getOpenGLWindow());
451 if( GLXEW_EXT_texture_from_pixmap
&& xLeavingSet
.is() && xEnteringSet
.is() && mbHasTFPVisual
) {
452 Sequence
< Any
> leaveArgs
;
453 Sequence
< Any
> enterArgs
;
454 if( (xLeavingSet
->getFastPropertyValue( 1 ) >>= leaveArgs
) &&
455 (xEnteringSet
->getFastPropertyValue( 1 ) >>= enterArgs
) ) {
456 SAL_INFO("slideshow.opengl", "pixmaps available");
460 leaveArgs
[0] >>= mbFreeLeavingPixmap
;
461 enterArgs
[0] >>= mbFreeEnteringPixmap
;
462 leaveArgs
[1] >>= maLeavingPixmap
;
463 enterArgs
[1] >>= maEnteringPixmap
;
464 leaveArgs
[2] >>= depth
;
466 int pixmapAttribs
[] = { GLX_TEXTURE_TARGET_EXT
, GLX_TEXTURE_2D_EXT
,
467 GLX_TEXTURE_FORMAT_EXT
, GLX_TEXTURE_FORMAT_RGB_EXT
,
468 GLX_MIPMAP_TEXTURE_EXT
, True
,
472 // sync so that we possibly get an pending XError, before we set our handler.
473 // this way we will not miss any error from other code
476 int (*oldHandler
)(Display
* /*dpy*/, XErrorEvent
* /*evnt*/);
478 // replace error handler temporarily
479 oldHandler
= XSetErrorHandler( oglErrorHandler
);
481 errorTriggered
= false;
482 maLeavingPixmapGL
= glXCreatePixmap( rGLWindow
.dpy
, rGLWindow
.fbc
, maLeavingPixmap
, pixmapAttribs
);
484 // sync so that we possibly get an XError
487 if( !errorTriggered
)
488 mbUseLeavingPixmap
= true;
490 SAL_INFO("slideshow.opengl", "XError triggered");
491 OSL_TRACE("XError triggered");
492 if( mbFreeLeavingPixmap
) {
493 XFreePixmap( rGLWindow
.dpy
, maLeavingPixmap
);
494 mbFreeLeavingPixmap
= false;
496 errorTriggered
= false;
499 maEnteringPixmapGL
= glXCreatePixmap( rGLWindow
.dpy
, rGLWindow
.fbc
, maEnteringPixmap
, pixmapAttribs
);
501 // sync so that we possibly get an XError
504 SAL_INFO("slideshow.opengl", "created glx pixmap " << maLeavingPixmapGL
<< " and " << maEnteringPixmapGL
<< " depth: " << depth
);
505 if( !errorTriggered
)
506 mbUseEnteringPixmap
= true;
508 SAL_INFO("slideshow.opengl", "XError triggered");
509 if( mbFreeEnteringPixmap
) {
510 XFreePixmap( rGLWindow
.dpy
, maEnteringPixmap
);
511 mbFreeEnteringPixmap
= false;
515 // restore the error handler
516 XSetErrorHandler( oldHandler
);
521 if( !mbUseLeavingPixmap
)
522 maLeavingBytes
= mxLeavingBitmap
->getData(maSlideBitmapLayout
, aSlideRect
);
523 if( !mbUseEnteringPixmap
)
524 maEnteringBytes
= mxEnteringBitmap
->getData(maSlideBitmapLayout
, aSlideRect
);
529 SAL_WARN_IF(maSlideBitmapLayout
.PlaneStride
!= 0, "slideshow.opengl","only handle no plane stride now");
534 #if defined( UNX ) && !defined( MACOSX )
535 // synchronized X still gives us much smoother play
536 // I suspect some issues in above code in slideshow
537 // synchronize whole transition for now
538 XSynchronize( rGLWindow
.dpy
, true );
539 mbRestoreSync
= true;
543 void OGLTransitionerImpl::impl_prepareTransition()
545 if( mpTransition
&& mpTransition
->getSettings().mnRequiredGLVersion
<= mnGLVersion
)
546 mpTransition
->prepare( maLeavingSlideGL
, maEnteringSlideGL
);
549 void OGLTransitionerImpl::impl_finishTransition()
551 if( mpTransition
&& mpTransition
->getSettings().mnRequiredGLVersion
<= mnGLVersion
)
552 mpTransition
->finish();
555 void OGLTransitionerImpl::setTransition( boost::shared_ptr
<OGLTransitionImpl
> pTransition
)
557 if ( mpTransition
) // already initialized
560 mpTransition
= pTransition
;
562 impl_prepareSlides();
563 impl_prepareTransition();
566 void OGLTransitionerImpl::createTexture( GLuint
* texID
,
567 #if defined( GLX_EXT_texture_from_pixmap )
572 uno::Sequence
<sal_Int8
>& data
,
573 const OGLFormat
* pFormat
)
576 glDeleteTextures( 1, texID
);
577 glGenTextures( 1, texID
);
578 glBindTexture( GL_TEXTURE_2D
, *texID
);
579 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
580 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
583 #if defined( GLX_EXT_texture_from_pixmap )
585 if( mbGenerateMipmap
)
586 glTexParameteri( GL_TEXTURE_2D
, GL_GENERATE_MIPMAP_SGIS
, True
);
587 glXBindTexImageEXT (mpContext
->getOpenGLWindow().dpy
, pixmap
, GLX_FRONT_LEFT_EXT
, NULL
);
588 if( mbGenerateMipmap
&& useMipmap
) {
589 SAL_INFO("slideshow.opengl", "use mipmaps");
590 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_LINEAR
);
591 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_LINEAR_MIPMAP_LINEAR
); //TRILINEAR FILTERING
593 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_NEAREST
);
594 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_NEAREST
);
597 impl_createTexture( useMipmap
, data
, pFormat
);
600 impl_createTexture( useMipmap
, data
, pFormat
);
602 SAL_WARN_IF(!glIsTexture(*texID
), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL");
608 class OGLColorSpace
: public cppu::WeakImplHelper1
< com::sun::star::rendering::XIntegerBitmapColorSpace
>
611 uno::Sequence
< sal_Int8
> maComponentTags
;
612 uno::Sequence
< sal_Int32
> maBitCounts
;
614 virtual ::sal_Int8 SAL_CALL
getType( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
616 return rendering::ColorSpaceType::RGB
;
618 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
getComponentTags( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
620 return maComponentTags
;
622 virtual ::sal_Int8 SAL_CALL
getRenderingIntent( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
624 return rendering::RenderingIntent::PERCEPTUAL
;
626 virtual uno::Sequence
< beans::PropertyValue
> SAL_CALL
getProperties( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
628 return uno::Sequence
< beans::PropertyValue
>();
630 virtual uno::Sequence
< double > SAL_CALL
convertColorSpace( const uno::Sequence
< double >& deviceColor
,
631 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
632 uno::RuntimeException
, std::exception
) SAL_OVERRIDE
634 // TODO(P3): if we know anything about target
635 // colorspace, this can be greatly sped up
636 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
637 convertToARGB(deviceColor
));
638 return targetColorSpace
->convertFromARGB(aIntermediate
);
640 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertToRGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
642 const double* pIn( deviceColor
.getConstArray() );
643 const sal_Size
nLen( deviceColor
.getLength() );
644 ENSURE_ARG_OR_THROW2(nLen
%4==0,
645 "number of channels no multiple of 4",
646 static_cast<rendering::XColorSpace
*>(this), 0);
648 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
649 rendering::RGBColor
* pOut( aRes
.getArray() );
650 for( sal_Size i
=0; i
<nLen
; i
+=4 )
652 *pOut
++ = rendering::RGBColor(pIn
[0],pIn
[1],pIn
[2]);
657 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
659 const double* pIn( deviceColor
.getConstArray() );
660 const sal_Size
nLen( deviceColor
.getLength() );
661 ENSURE_ARG_OR_THROW2(nLen
%4==0,
662 "number of channels no multiple of 4",
663 static_cast<rendering::XColorSpace
*>(this), 0);
665 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
666 rendering::ARGBColor
* pOut( aRes
.getArray() );
667 for( sal_Size i
=0; i
<nLen
; i
+=4 )
669 *pOut
++ = rendering::ARGBColor(pIn
[3],pIn
[0],pIn
[1],pIn
[2]);
674 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertToPARGB( const uno::Sequence
< double >& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
676 const double* pIn( deviceColor
.getConstArray() );
677 const sal_Size
nLen( deviceColor
.getLength() );
678 ENSURE_ARG_OR_THROW2(nLen
%4==0,
679 "number of channels no multiple of 4",
680 static_cast<rendering::XColorSpace
*>(this), 0);
682 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
683 rendering::ARGBColor
* pOut( aRes
.getArray() );
684 for( sal_Size i
=0; i
<nLen
; i
+=4 )
686 *pOut
++ = rendering::ARGBColor(pIn
[3],pIn
[3]*pIn
[0],pIn
[3]*pIn
[1],pIn
[3]*pIn
[2]);
691 virtual uno::Sequence
< double > SAL_CALL
convertFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
693 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
694 const sal_Size
nLen( rgbColor
.getLength() );
696 uno::Sequence
< double > aRes(nLen
*4);
697 double* pColors
=aRes
.getArray();
698 for( sal_Size i
=0; i
<nLen
; ++i
)
700 *pColors
++ = pIn
->Red
;
701 *pColors
++ = pIn
->Green
;
702 *pColors
++ = pIn
->Blue
;
708 virtual uno::Sequence
< double > SAL_CALL
convertFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
710 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
711 const sal_Size
nLen( rgbColor
.getLength() );
713 uno::Sequence
< double > aRes(nLen
*4);
714 double* pColors
=aRes
.getArray();
715 for( sal_Size i
=0; i
<nLen
; ++i
)
717 *pColors
++ = pIn
->Red
;
718 *pColors
++ = pIn
->Green
;
719 *pColors
++ = pIn
->Blue
;
720 *pColors
++ = pIn
->Alpha
;
725 virtual uno::Sequence
< double > SAL_CALL
convertFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
727 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
728 const sal_Size
nLen( rgbColor
.getLength() );
730 uno::Sequence
< double > aRes(nLen
*4);
731 double* pColors
=aRes
.getArray();
732 for( sal_Size i
=0; i
<nLen
; ++i
)
734 *pColors
++ = pIn
->Red
/pIn
->Alpha
;
735 *pColors
++ = pIn
->Green
/pIn
->Alpha
;
736 *pColors
++ = pIn
->Blue
/pIn
->Alpha
;
737 *pColors
++ = pIn
->Alpha
;
743 // XIntegerBitmapColorSpace
744 virtual ::sal_Int32 SAL_CALL
getBitsPerPixel( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
748 virtual uno::Sequence
< ::sal_Int32
> SAL_CALL
getComponentBitCounts( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
752 virtual ::sal_Int8 SAL_CALL
getEndianness( ) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
754 return util::Endianness::LITTLE
;
756 virtual uno::Sequence
<double> SAL_CALL
convertFromIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
757 const uno::Reference
< rendering::XColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
758 uno::RuntimeException
, std::exception
) SAL_OVERRIDE
760 if( dynamic_cast<OGLColorSpace
*>(targetColorSpace
.get()) )
762 const sal_Int8
* pIn( deviceColor
.getConstArray() );
763 const sal_Size
nLen( deviceColor
.getLength() );
764 ENSURE_ARG_OR_THROW2(nLen
%4==0,
765 "number of channels no multiple of 4",
766 static_cast<rendering::XColorSpace
*>(this), 0);
768 uno::Sequence
<double> aRes(nLen
);
769 double* pOut( aRes
.getArray() );
770 for( sal_Size i
=0; i
<nLen
; i
+=4 )
772 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
773 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
774 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
775 *pOut
++ = vcl::unotools::toDoubleColor(*pIn
++);
781 // TODO(P3): if we know anything about target
782 // colorspace, this can be greatly sped up
783 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
784 convertIntegerToARGB(deviceColor
));
785 return targetColorSpace
->convertFromARGB(aIntermediate
);
788 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertToIntegerColorSpace( const uno::Sequence
< ::sal_Int8
>& deviceColor
,
789 const uno::Reference
< rendering::XIntegerBitmapColorSpace
>& targetColorSpace
) throw (lang::IllegalArgumentException
,
790 uno::RuntimeException
, std::exception
) SAL_OVERRIDE
792 if( dynamic_cast<OGLColorSpace
*>(targetColorSpace
.get()) )
794 // it's us, so simply pass-through the data
799 // TODO(P3): if we know anything about target
800 // colorspace, this can be greatly sped up
801 uno::Sequence
<rendering::ARGBColor
> aIntermediate(
802 convertIntegerToARGB(deviceColor
));
803 return targetColorSpace
->convertIntegerFromARGB(aIntermediate
);
806 virtual uno::Sequence
< rendering::RGBColor
> SAL_CALL
convertIntegerToRGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
808 const sal_Int8
* pIn( deviceColor
.getConstArray() );
809 const sal_Size
nLen( deviceColor
.getLength() );
810 ENSURE_ARG_OR_THROW2(nLen
%4==0,
811 "number of channels no multiple of 4",
812 static_cast<rendering::XColorSpace
*>(this), 0);
814 uno::Sequence
< rendering::RGBColor
> aRes(nLen
/4);
815 rendering::RGBColor
* pOut( aRes
.getArray() );
816 for( sal_Size i
=0; i
<nLen
; i
+=4 )
818 *pOut
++ = rendering::RGBColor(
819 vcl::unotools::toDoubleColor(pIn
[0]),
820 vcl::unotools::toDoubleColor(pIn
[1]),
821 vcl::unotools::toDoubleColor(pIn
[2]));
827 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
829 const sal_Int8
* pIn( deviceColor
.getConstArray() );
830 const sal_Size
nLen( deviceColor
.getLength() );
831 ENSURE_ARG_OR_THROW2(nLen
%4==0,
832 "number of channels no multiple of 4",
833 static_cast<rendering::XColorSpace
*>(this), 0);
835 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
836 rendering::ARGBColor
* pOut( aRes
.getArray() );
837 for( sal_Size i
=0; i
<nLen
; i
+=4 )
839 *pOut
++ = rendering::ARGBColor(
840 vcl::unotools::toDoubleColor(pIn
[3]),
841 vcl::unotools::toDoubleColor(pIn
[0]),
842 vcl::unotools::toDoubleColor(pIn
[1]),
843 vcl::unotools::toDoubleColor(pIn
[2]));
849 virtual uno::Sequence
< rendering::ARGBColor
> SAL_CALL
convertIntegerToPARGB( const uno::Sequence
< ::sal_Int8
>& deviceColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
851 const sal_Int8
* pIn( deviceColor
.getConstArray() );
852 const sal_Size
nLen( deviceColor
.getLength() );
853 ENSURE_ARG_OR_THROW2(nLen
%4==0,
854 "number of channels no multiple of 4",
855 static_cast<rendering::XColorSpace
*>(this), 0);
857 uno::Sequence
< rendering::ARGBColor
> aRes(nLen
/4);
858 rendering::ARGBColor
* pOut( aRes
.getArray() );
859 for( sal_Size i
=0; i
<nLen
; i
+=4 )
861 const sal_Int8
nAlpha( pIn
[3] );
862 *pOut
++ = rendering::ARGBColor(
863 vcl::unotools::toDoubleColor(nAlpha
),
864 vcl::unotools::toDoubleColor(nAlpha
*pIn
[0]),
865 vcl::unotools::toDoubleColor(nAlpha
*pIn
[1]),
866 vcl::unotools::toDoubleColor(nAlpha
*pIn
[2]));
872 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromRGB( const uno::Sequence
< rendering::RGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
874 const rendering::RGBColor
* pIn( rgbColor
.getConstArray() );
875 const sal_Size
nLen( rgbColor
.getLength() );
877 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
878 sal_Int8
* pColors
=aRes
.getArray();
879 for( sal_Size i
=0; i
<nLen
; ++i
)
881 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
882 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
883 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
890 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
892 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
893 const sal_Size
nLen( rgbColor
.getLength() );
895 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
896 sal_Int8
* pColors
=aRes
.getArray();
897 for( sal_Size i
=0; i
<nLen
; ++i
)
899 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
);
900 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
);
901 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
);
902 *pColors
++ = vcl::unotools::toByteColor(pIn
->Alpha
);
908 virtual uno::Sequence
< ::sal_Int8
> SAL_CALL
convertIntegerFromPARGB( const uno::Sequence
< rendering::ARGBColor
>& rgbColor
) throw (lang::IllegalArgumentException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
910 const rendering::ARGBColor
* pIn( rgbColor
.getConstArray() );
911 const sal_Size
nLen( rgbColor
.getLength() );
913 uno::Sequence
< sal_Int8
> aRes(nLen
*4);
914 sal_Int8
* pColors
=aRes
.getArray();
915 for( sal_Size i
=0; i
<nLen
; ++i
)
917 *pColors
++ = vcl::unotools::toByteColor(pIn
->Red
/pIn
->Alpha
);
918 *pColors
++ = vcl::unotools::toByteColor(pIn
->Green
/pIn
->Alpha
);
919 *pColors
++ = vcl::unotools::toByteColor(pIn
->Blue
/pIn
->Alpha
);
920 *pColors
++ = vcl::unotools::toByteColor(pIn
->Alpha
);
931 sal_Int8
* pTags
= maComponentTags
.getArray();
932 sal_Int32
* pBitCounts
= maBitCounts
.getArray();
933 pTags
[0] = rendering::ColorComponentTag::RGB_RED
;
934 pTags
[1] = rendering::ColorComponentTag::RGB_GREEN
;
935 pTags
[2] = rendering::ColorComponentTag::RGB_BLUE
;
936 pTags
[3] = rendering::ColorComponentTag::ALPHA
;
945 struct OGLColorSpaceHolder
: public rtl::StaticWithInit
<uno::Reference
<rendering::XIntegerBitmapColorSpace
>, OGLColorSpaceHolder
>
947 uno::Reference
<rendering::XIntegerBitmapColorSpace
> operator()()
949 return new OGLColorSpace();
953 uno::Reference
<rendering::XIntegerBitmapColorSpace
>
956 return OGLColorSpaceHolder::get();
963 GLint internalFormat
, GLsizei width
, GLsizei height
, GLenum format
,
964 GLenum type
, const void * data
)
966 if (GLEW_ARB_framebuffer_object
) {
968 GL_TEXTURE_2D
, 0, internalFormat
, width
, height
, 0, format
, type
,
970 glGenerateMipmap(GL_TEXTURE_2D
);
972 glTexParameteri(GL_TEXTURE_2D
, GL_GENERATE_MIPMAP
, GL_TRUE
);
974 GL_TEXTURE_2D
, 0, internalFormat
, width
, height
, 0, format
, type
,
976 glTexParameteri(GL_TEXTURE_2D
, GL_GENERATE_MIPMAP
, GL_FALSE
);
978 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
980 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR_MIPMAP_LINEAR
);
985 void OGLTransitionerImpl::impl_createTexture(
987 uno::Sequence
<sal_Int8
>& data
,
988 const OGLFormat
* pFormat
)
993 // force-convert color to ARGB8888 int color space
994 uno::Sequence
<sal_Int8
> tempBytes(
995 maSlideBitmapLayout
.ColorSpace
->convertToIntegerColorSpace(
997 getOGLColorSpace()));
1005 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
1006 GLfloat largest_supported_anisotropy
;
1007 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &largest_supported_anisotropy
);
1008 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, largest_supported_anisotropy
);
1010 if( mpTransition
&& !mbBrokenTexturesATI
&& !useMipmap
) {
1011 glTexImage2D( GL_TEXTURE_2D
, 0, pFormat
->nInternalFormat
, maSlideSize
.Width
, maSlideSize
.Height
, 0, pFormat
->eFormat
, pFormat
->eType
, &data
[0] );
1012 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MAG_FILTER
,GL_NEAREST
);
1013 glTexParameteri(GL_TEXTURE_2D
,GL_TEXTURE_MIN_FILTER
,GL_NEAREST
);
1015 buildMipmaps( pFormat
->nInternalFormat
, maSlideSize
.Width
, maSlideSize
.Height
, pFormat
->eFormat
, pFormat
->eType
, &data
[0] );
1017 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
1018 GLfloat largest_supported_anisotropy
;
1019 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &largest_supported_anisotropy
);
1020 glTexParameterf( GL_TEXTURE_2D
, GL_TEXTURE_MAX_ANISOTROPY_EXT
, largest_supported_anisotropy
);
1026 void OGLTransitionerImpl::prepareEnvironment()
1029 glMatrixMode(GL_PROJECTION
);
1031 double EyePos(10.0);
1038 double ClipN(EyePos
+5.0*RealN
);
1039 double ClipF(EyePos
+15.0*RealF
);
1040 double ClipL(RealL
*8.0);
1041 double ClipR(RealR
*8.0);
1042 double ClipB(RealB
*8.0);
1043 double ClipT(RealT
*8.0);
1044 //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.
1045 glScaled( 1.0 / ( ( ( RealR
* 2.0 * ClipN
) / ( EyePos
* ( ClipR
- ClipL
) ) ) - ( ( ClipR
+ ClipL
) / ( ClipR
- ClipL
) ) ),
1046 1.0 / ( ( ( RealT
* 2.0 * ClipN
) / ( EyePos
* ( ClipT
- ClipB
) ) ) - ( ( ClipT
+ ClipB
) / ( ClipT
- ClipB
) ) ),
1048 glFrustum(ClipL
,ClipR
,ClipB
,ClipT
,ClipN
,ClipF
);
1049 glMatrixMode(GL_MODELVIEW
);
1051 glTranslated(0,0,-EyePos
);
1055 const OGLFormat
* OGLTransitionerImpl::chooseFormats()
1057 const OGLFormat
* pDetectedFormat
=NULL
;
1058 uno::Reference
<rendering::XIntegerBitmapColorSpace
> xIntColorSpace(
1059 maSlideBitmapLayout
.ColorSpace
);
1061 if( (xIntColorSpace
->getType() == rendering::ColorSpaceType::RGB
||
1062 xIntColorSpace
->getType() == rendering::ColorSpaceType::SRGB
) )
1064 /* table for canvas->OGL format mapping. outer index is number
1065 of color components (0:3, 1:4), then comes bits per pixel
1066 (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
1069 static const OGLFormat lcl_RGB24
[] =
1072 {3, GL_BGR
, GL_UNSIGNED_BYTE
},
1073 {3, GL_RGB
, GL_UNSIGNED_BYTE
},
1074 {3, GL_BGR
, GL_UNSIGNED_BYTE
},
1075 {3, GL_RGB
, GL_UNSIGNED_BYTE
}
1078 #if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
1079 // more format constants available
1080 static const OGLFormat lcl_RGB16
[] =
1083 {3, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5_REV
},
1084 {3, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
},
1085 {3, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5_REV
},
1086 {3, GL_RGB
, GL_UNSIGNED_SHORT_5_6_5
}
1089 static const OGLFormat lcl_ARGB16_4
[] =
1092 {4, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4_REV
},
1093 {4, GL_BGRA
, GL_UNSIGNED_SHORT_4_4_4_4_REV
},
1094 {4, GL_BGRA
, GL_UNSIGNED_SHORT_4_4_4_4
},
1095 {4, GL_RGBA
, GL_UNSIGNED_SHORT_4_4_4_4
}
1098 static const OGLFormat lcl_ARGB16_5
[] =
1101 {4, GL_RGBA
, GL_UNSIGNED_SHORT_1_5_5_5_REV
},
1102 {4, GL_BGRA
, GL_UNSIGNED_SHORT_1_5_5_5_REV
},
1103 {4, GL_BGRA
, GL_UNSIGNED_SHORT_5_5_5_1
},
1104 {4, GL_RGBA
, GL_UNSIGNED_SHORT_5_5_5_1
}
1107 static const OGLFormat lcl_ARGB32
[] =
1110 {4, GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8_REV
},
1111 {4, GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
},
1112 {4, GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8
},
1113 {4, GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
}
1116 const uno::Sequence
<sal_Int8
> aComponentTags(
1117 xIntColorSpace
->getComponentTags());
1118 const uno::Sequence
<sal_Int32
> aComponentBitcounts(
1119 xIntColorSpace
->getComponentBitCounts());
1120 const sal_Int32
nNumComponents( aComponentBitcounts
.getLength() );
1121 const sal_Int32
nBitsPerPixel( xIntColorSpace
->getBitsPerPixel() );
1123 // supported component ordering?
1124 const int nComponentOrderIndex(
1125 calcComponentOrderIndex(aComponentTags
));
1126 if( nComponentOrderIndex
!= -1 )
1128 switch( nBitsPerPixel
)
1131 if( nNumComponents
== 3 )
1133 pDetectedFormat
= &lcl_RGB16
[nComponentOrderIndex
];
1135 else if( nNumComponents
== 4 )
1137 if( aComponentBitcounts
[1] == 4 )
1139 pDetectedFormat
= &lcl_ARGB16_4
[nComponentOrderIndex
];
1141 else if( aComponentBitcounts
[1] == 5 )
1143 pDetectedFormat
= &lcl_ARGB16_5
[nComponentOrderIndex
];
1148 if( nNumComponents
== 3 )
1150 pDetectedFormat
= &lcl_RGB24
[nComponentOrderIndex
];
1154 if ( nNumComponents
== 4 )
1156 pDetectedFormat
= &lcl_ARGB32
[nComponentOrderIndex
];
1162 const uno::Sequence
<sal_Int8
> aComponentTags(
1163 xIntColorSpace
->getComponentTags());
1164 const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags
));
1165 if( aComponentTags
.getLength() == 3 &&
1166 nComponentOrderIndex
!= -1 &&
1167 xIntColorSpace
->getBitsPerPixel() == 24 )
1169 pDetectedFormat
= &lcl_RGB24
[nComponentOrderIndex
];
1174 return pDetectedFormat
;
1177 void OGLTransitionerImpl::GLInitSlides()
1179 osl::MutexGuard
const guard( m_aMutex
);
1181 if (isDisposed() || mpTransition
->getSettings().mnRequiredGLVersion
> mnGLVersion
)
1184 #if OSL_DEBUG_LEVEL > 1
1185 TimerContext
aTimerContext("texture creation");
1188 mpContext
->makeCurrent();
1189 prepareEnvironment();
1191 const OGLFormat
* pFormat
= NULL
;
1192 if( !mbUseLeavingPixmap
|| !mbUseEnteringPixmap
)
1193 pFormat
= chooseFormats();
1196 createTexture( &maLeavingSlideGL
,
1197 #if defined( GLX_EXT_texture_from_pixmap )
1201 mpTransition
->getSettings().mbUseMipMapLeaving
,
1205 createTexture( &maEnteringSlideGL
,
1206 #if defined( GLX_EXT_texture_from_pixmap )
1208 mbUseEnteringPixmap
,
1210 mpTransition
->getSettings().mbUseMipMapEntering
,
1219 void SAL_CALL
OGLTransitionerImpl::update( double nTime
) throw (uno::RuntimeException
, std::exception
)
1221 #if OSL_DEBUG_LEVEL > 1
1223 maUpdateStartTime
= microsec_clock::local_time();
1224 if( mnFrameCount
== 1 ) {
1225 maStartTime
= maUpdateStartTime
;
1226 maTotalUpdateDuration
= seconds (0);
1229 osl::MutexGuard
const guard( m_aMutex
);
1231 if (isDisposed() || !mbValidOpenGLContext
|| mpTransition
->getSettings().mnRequiredGLVersion
> mnGLVersion
)
1234 mpContext
->makeCurrent();
1237 glEnable(GL_DEPTH_TEST
);
1238 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1243 const GLWindow
& rGLWindow(mpContext
->getOpenGLWindow());
1244 mpTransition
->display( nTime
, maLeavingSlideGL
, maEnteringSlideGL
,
1245 maSlideSize
.Width
, maSlideSize
.Height
,
1246 static_cast<double>(rGLWindow
.Width
),
1247 static_cast<double>(rGLWindow
.Height
) );
1250 mpContext
->swapBuffers();
1256 #if OSL_DEBUG_LEVEL > 1
1257 maUpdateEndTime
= microsec_clock::local_time();
1259 SAL_INFO("slideshow.opengl", "update time: " << nTime
);
1260 SAL_INFO("slideshow.opengl", "update took: " << ( maUpdateEndTime
- maUpdateStartTime
));
1261 maTotalUpdateDuration
+= (maUpdateEndTime
- maUpdateStartTime
);
1265 void SAL_CALL
OGLTransitionerImpl::viewChanged( const Reference
< presentation::XSlideShowView
>& rView
,
1266 const Reference
< rendering::XBitmap
>& rLeavingBitmap
,
1267 const Reference
< rendering::XBitmap
>& rEnteringBitmap
)
1268 throw (uno::RuntimeException
, std::exception
)
1270 SAL_INFO("slideshow.opengl", "transitioner: view changed");
1274 initWindowFromSlideShowView( rView
);
1275 setSlides( rLeavingBitmap
, rEnteringBitmap
);
1276 impl_prepareSlides();
1277 impl_prepareTransition();
1280 void OGLTransitionerImpl::disposeTextures()
1282 mpContext
->makeCurrent();
1285 #if defined( GLX_EXT_texture_from_pixmap )
1286 const GLWindow
& rGLWindow(mpContext
->getOpenGLWindow());
1288 if( mbUseLeavingPixmap
) {
1289 glXReleaseTexImageEXT( rGLWindow
.dpy
, maLeavingPixmapGL
, GLX_FRONT_LEFT_EXT
);
1290 glXDestroyGLXPixmap( rGLWindow
.dpy
, maLeavingPixmapGL
);
1291 maLeavingPixmapGL
= 0;
1292 if( mbFreeLeavingPixmap
) {
1293 XFreePixmap( rGLWindow
.dpy
, maLeavingPixmap
);
1294 mbFreeLeavingPixmap
= false;
1295 maLeavingPixmap
= 0;
1298 if( mbUseEnteringPixmap
) {
1299 glXReleaseTexImageEXT( rGLWindow
.dpy
, maEnteringPixmapGL
, GLX_FRONT_LEFT_EXT
);
1300 glXDestroyGLXPixmap( rGLWindow
.dpy
, maEnteringPixmapGL
);
1301 maEnteringPixmapGL
= 0;
1302 if( mbFreeEnteringPixmap
) {
1303 XFreePixmap( rGLWindow
.dpy
, maEnteringPixmap
);
1304 mbFreeEnteringPixmap
= false;
1305 maEnteringPixmap
= 0;
1310 if( !mbUseLeavingPixmap
) {
1311 glDeleteTextures(1,&maLeavingSlideGL
);
1312 maLeavingSlideGL
= 0;
1314 if( !mbUseEnteringPixmap
) {
1315 glDeleteTextures(1,&maEnteringSlideGL
);
1316 maEnteringSlideGL
= 0;
1319 mbUseLeavingPixmap
= false;
1320 mbUseEnteringPixmap
= false;
1324 void OGLTransitionerImpl::impl_dispose()
1326 impl_finishTransition();
1328 if( mpContext
.is() )
1329 mpContext
->dispose();
1333 // we are about to be disposed (someone call dispose() on us)
1334 void OGLTransitionerImpl::disposing()
1336 osl::MutexGuard
const guard( m_aMutex
);
1338 #if OSL_DEBUG_LEVEL > 1
1339 SAL_INFO("slideshow.opengl", "dispose " << this);
1340 if( mnFrameCount
) {
1341 maEndTime
= microsec_clock::local_time();
1342 time_duration duration
= maEndTime
- maStartTime
;
1343 SAL_INFO("slideshow.opengl",
1344 "whole transition (frames: " << mnFrameCount
1345 << ") took: " << duration
1347 << (((double)mnFrameCount
*1000000000.0)/duration
.total_nanoseconds())
1348 << " time spent in updates: " << maTotalUpdateDuration
1349 << " percentage of transition time: "
1350 << (100*(((double)maTotalUpdateDuration
.total_nanoseconds())/((double)duration
.total_nanoseconds())))
1356 #if defined( UNX ) && !defined( MACOSX )
1357 if( mbRestoreSync
&& bool(mpContext
.is()) ) {
1358 // try to reestablish synchronize state
1359 char* sal_synchronize
= getenv("SAL_SYNCHRONIZE");
1360 XSynchronize( mpContext
->getOpenGLWindow().dpy
, sal_synchronize
&& *sal_synchronize
== '1' );
1366 mpTransition
.reset();
1368 mxLeavingBitmap
.clear();
1369 mxEnteringBitmap
.clear();
1373 OGLTransitionerImpl::OGLTransitionerImpl()
1374 : OGLTransitionerImplBase(m_aMutex
)
1376 , maLeavingSlideGL(0)
1377 , maEnteringSlideGL(0)
1381 #if defined( GLX_EXT_texture_from_pixmap )
1382 , maLeavingPixmapGL(0)
1383 , maEnteringPixmapGL(0)
1385 #if defined( UNX ) && !defined( MACOSX )
1386 , mbRestoreSync(false)
1388 , mbUseLeavingPixmap(false)
1389 , mbUseEnteringPixmap(false)
1390 #if defined( GLX_EXT_texture_from_pixmap )
1391 , mbFreeLeavingPixmap(false)
1392 , mbFreeEnteringPixmap(false)
1394 #if defined( UNX ) && !defined( MACOSX )
1395 , maLeavingPixmap(0)
1396 , maEnteringPixmap(0)
1398 , maSlideBitmapLayout()
1400 , mbBrokenTexturesATI(false)
1402 , mbValidOpenGLContext(false)
1403 , mbGenerateMipmap(false)
1404 , mbHasTFPVisual(false)
1408 typedef cppu::WeakComponentImplHelper1
<presentation::XTransitionFactory
> OGLTransitionFactoryImplBase
;
1410 class OGLTransitionFactoryImpl
: private cppu::BaseMutex
, public OGLTransitionFactoryImplBase
1413 explicit OGLTransitionFactoryImpl( const uno::Reference
< uno::XComponentContext
>& ) :
1414 OGLTransitionFactoryImplBase(m_aMutex
)
1417 // XTransitionFactory
1418 virtual sal_Bool SAL_CALL
hasTransition( ::sal_Int16 transitionType
, ::sal_Int16 transitionSubType
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1420 if( transitionType
== animations::TransitionType::MISCSHAPEWIPE
) {
1421 switch( transitionSubType
)
1423 case animations::TransitionSubType::ACROSS
:
1424 case animations::TransitionSubType::CORNERSOUT
:
1425 case animations::TransitionSubType::CIRCLE
:
1426 case animations::TransitionSubType::FANOUTHORIZONTAL
:
1427 case animations::TransitionSubType::CORNERSIN
:
1428 case animations::TransitionSubType::LEFTTORIGHT
:
1429 case animations::TransitionSubType::TOPTOBOTTOM
:
1430 case animations::TransitionSubType::TOPRIGHT
:
1431 case animations::TransitionSubType::TOPLEFT
:
1432 case animations::TransitionSubType::BOTTOMRIGHT
:
1433 case animations::TransitionSubType::BOTTOMLEFT
:
1434 case animations::TransitionSubType::TOPCENTER
:
1435 case animations::TransitionSubType::RIGHTCENTER
:
1436 case animations::TransitionSubType::BOTTOMCENTER
:
1442 } else if( transitionType
== animations::TransitionType::FADE
&& transitionSubType
== animations::TransitionSubType::CROSSFADE
) {
1444 } else if( transitionType
== animations::TransitionType::FADE
&& transitionSubType
== animations::TransitionSubType::FADEOVERCOLOR
) {
1446 } else if( transitionType
== animations::TransitionType::IRISWIPE
&& transitionSubType
== animations::TransitionSubType::DIAMOND
) {
1448 } else if( transitionType
== animations::TransitionType::ZOOM
&& transitionSubType
== animations::TransitionSubType::ROTATEIN
) {
1454 virtual uno::Reference
< presentation::XTransition
> SAL_CALL
createTransition(
1455 ::sal_Int16 transitionType
,
1456 ::sal_Int16 transitionSubType
,
1457 const uno::Reference
< presentation::XSlideShowView
>& view
,
1458 const uno::Reference
< rendering::XBitmap
>& leavingBitmap
,
1459 const uno::Reference
< rendering::XBitmap
>& enteringBitmap
)
1460 throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
1462 if( !hasTransition( transitionType
, transitionSubType
) )
1463 return uno::Reference
< presentation::XTransition
>();
1465 rtl::Reference
< OGLTransitionerImpl
> xRes( new OGLTransitionerImpl() );
1466 if ( !xRes
->initialize( view
, leavingBitmap
, enteringBitmap
) )
1467 return uno::Reference
< presentation::XTransition
>();
1469 boost::shared_ptr
<OGLTransitionImpl
> pTransition
;
1471 if( transitionType
== animations::TransitionType::MISCSHAPEWIPE
) {
1472 switch( transitionSubType
)
1474 case animations::TransitionSubType::ACROSS
:
1475 pTransition
= makeNByMTileFlip(8,6);
1477 case animations::TransitionSubType::CORNERSOUT
:
1478 pTransition
= makeOutsideCubeFaceToLeft();
1480 case animations::TransitionSubType::CIRCLE
:
1481 pTransition
= makeRevolvingCircles(8,128);
1483 case animations::TransitionSubType::FANOUTHORIZONTAL
:
1484 pTransition
= makeHelix(20);
1486 case animations::TransitionSubType::CORNERSIN
:
1487 pTransition
= makeInsideCubeFaceToLeft();
1489 case animations::TransitionSubType::LEFTTORIGHT
:
1490 pTransition
= makeFallLeaving();
1492 case animations::TransitionSubType::TOPTOBOTTOM
:
1493 pTransition
= makeTurnAround();
1495 case animations::TransitionSubType::TOPRIGHT
:
1496 pTransition
= makeTurnDown();
1498 case animations::TransitionSubType::TOPLEFT
:
1499 pTransition
= makeIris();
1501 case animations::TransitionSubType::BOTTOMRIGHT
:
1502 pTransition
= makeRochade();
1504 case animations::TransitionSubType::BOTTOMLEFT
:
1505 pTransition
= makeVenetianBlinds( true, 8 );
1507 case animations::TransitionSubType::TOPCENTER
:
1508 pTransition
= makeVenetianBlinds( false, 6 );
1510 case animations::TransitionSubType::RIGHTCENTER
:
1511 pTransition
= makeStatic();
1513 case animations::TransitionSubType::BOTTOMCENTER
:
1514 pTransition
= makeDissolve();
1517 } else if( transitionType
== animations::TransitionType::FADE
&& transitionSubType
== animations::TransitionSubType::CROSSFADE
) {
1518 pTransition
= makeFadeSmoothly();
1519 } else if( transitionType
== animations::TransitionType::FADE
&& transitionSubType
== animations::TransitionSubType::FADEOVERCOLOR
) {
1520 pTransition
= makeFadeThroughBlack();
1521 } else if( transitionType
== animations::TransitionType::IRISWIPE
&& transitionSubType
== animations::TransitionSubType::DIAMOND
) {
1522 pTransition
= makeDiamond();
1523 } else if( transitionType
== animations::TransitionType::ZOOM
&& transitionSubType
== animations::TransitionSubType::ROTATEIN
) {
1524 pTransition
= makeNewsflash();
1528 return uno::Reference
< presentation::XTransition
>();
1530 xRes
->setTransition( pTransition
);
1532 return uno::Reference
<presentation::XTransition
>(xRes
.get());
1538 namespace sdecl
= comphelper::service_decl
;
1539 const sdecl::ServiceDecl
OGLTransitionFactoryDecl(
1540 sdecl::class_
<OGLTransitionFactoryImpl
>(),
1541 "com.sun.star.comp.presentation.OGLTransitionFactory",
1542 "com.sun.star.presentation.TransitionFactory" );
1544 // The C shared lib entry points
1545 COMPHELPER_SERVICEDECL_EXPORTS1(ogltrans
, OGLTransitionFactoryDecl
)
1547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */