Use o3tl::convert in Math
[LibreOffice.git] / slideshow / source / engine / opengl / TransitionerImpl.cxx
blobfcf859b40d93406420d3b5b69d214d1af93e8ed5
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 <sal/types.h>
31 #include <memory>
33 #include <com/sun/star/beans/XFastPropertySet.hpp>
34 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
35 #include <com/sun/star/rendering/ColorComponentTag.hpp>
36 #include <com/sun/star/rendering/ColorSpaceType.hpp>
37 #include <com/sun/star/rendering/RenderingIntent.hpp>
38 #include <com/sun/star/util/Endianness.hpp>
39 #include <com/sun/star/animations/TransitionType.hpp>
40 #undef IN
41 #undef OUT
42 #include <com/sun/star/animations/TransitionSubType.hpp>
43 #include <com/sun/star/presentation/XTransitionFactory.hpp>
44 #include <com/sun/star/presentation/XTransition.hpp>
45 #include <com/sun/star/presentation/XSlideShowView.hpp>
46 #include <com/sun/star/uno/XComponentContext.hpp>
47 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
48 #include <com/sun/star/geometry/IntegerSize2D.hpp>
49 #include <com/sun/star/lang/XServiceInfo.hpp>
51 #include <cppuhelper/compbase.hxx>
52 #include <cppuhelper/basemutex.hxx>
53 #include <cppuhelper/supportsservice.hxx>
54 #include <rtl/ref.hxx>
55 #include <sal/log.hxx>
57 #include <canvas/canvastools.hxx>
59 #include <tools/diagnose_ex.h>
61 #include <vcl/canvastools.hxx>
62 #include <vcl/opengl/OpenGLContext.hxx>
63 #include <vcl/opengl/OpenGLHelper.hxx>
64 #include <vcl/syschild.hxx>
65 #include <vcl/window.hxx>
67 #include "TransitionImpl.hxx"
69 #if OSL_DEBUG_LEVEL > 0
70 #include <chrono>
71 #endif
73 using namespace ::com::sun::star;
74 using ::com::sun::star::beans::XFastPropertySet;
75 using ::com::sun::star::uno::Any;
76 using ::com::sun::star::uno::Reference;
77 using ::com::sun::star::uno::Sequence;
78 using ::com::sun::star::uno::UNO_QUERY;
79 using ::com::sun::star::uno::UNO_QUERY_THROW;
81 namespace
84 typedef cppu::WeakComponentImplHelper<presentation::XTransition> OGLTransitionerImplBase;
86 #if OSL_DEBUG_LEVEL > 0
87 class TimerContext
89 public:
90 explicit TimerContext(OUString const& rWhat)
91 : m_aWhat(rWhat)
92 , m_StartTime(std::chrono::steady_clock::now())
95 ~TimerContext()
97 auto const aDuration(std::chrono::steady_clock::now() - m_StartTime);
98 SAL_INFO("slideshow.opengl", m_aWhat << " took: " << std::chrono::duration_cast<std::chrono::microseconds>(aDuration).count());
100 private:
101 OUString const m_aWhat;
102 std::chrono::steady_clock::time_point const m_StartTime;
104 #endif
106 struct OGLFormat
108 GLint nInternalFormat;
109 GLenum eFormat;
110 GLenum eType;
113 /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
115 int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
117 using namespace rendering::ColorComponentTag;
119 static const sal_Int8 aOrderTable[] =
121 RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
122 RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
123 ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
124 ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
127 const sal_Int32 nNumComps(rTags.getLength());
128 const sal_Int8* pLine=aOrderTable;
129 for(int i=0; i<4; ++i)
131 int j=0;
132 while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
133 ++j;
135 // all of the line passed, this is a match!
136 if( j==nNumComps )
137 return i;
139 pLine+=4;
142 return -1;
145 /** This is the Transitioner class for OpenGL 3D transitions in
146 * slideshow. This class is implicitly
147 * constructed from XTransitionFactory.
149 class OGLTransitionerImpl : private cppu::BaseMutex, public OGLTransitionerImplBase
151 public:
152 OGLTransitionerImpl();
153 OGLTransitionerImpl(const OGLTransitionerImpl&) = delete;
154 OGLTransitionerImpl& operator=(const OGLTransitionerImpl&) = delete;
155 bool setTransition( const std::shared_ptr<OGLTransitionImpl>& pOGLTransition );
156 bool initialize( const Reference< presentation::XSlideShowView >& xView,
157 const Reference< rendering::XBitmap >& xLeavingSlide,
158 const Reference< rendering::XBitmap >& xEnteringSlide );
160 // XTransition
161 virtual void SAL_CALL update( double nTime ) override;
162 virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
163 const Reference< rendering::XBitmap >& rLeavingBitmap,
164 const Reference< rendering::XBitmap >& rEnteringBitmap ) override;
166 protected:
167 void disposeTextures();
169 // WeakComponentImplHelperBase
170 virtual void SAL_CALL disposing() override;
172 bool isDisposed() const
174 return (rBHelper.bDisposed || rBHelper.bInDispose);
177 void createTexture( GLuint* texID,
178 bool useMipmap,
179 uno::Sequence<sal_Int8>& data,
180 const OGLFormat* pFormat );
181 const OGLFormat* chooseFormats();
183 private:
184 void impl_initializeFlags( bool const bGLXPresent );
186 void impl_dispose();
188 void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
189 void impl_prepareSlides();
191 void impl_createTexture( bool useMipmap, uno::Sequence<sal_Int8>& data, const OGLFormat* pFormat );
193 bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
194 /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
196 void GLInitSlides();
198 bool impl_prepareTransition();
200 private:
201 rtl::Reference<OpenGLContext> mpContext;
203 /** OpenGL handle to the leaving slide's texture
205 GLuint maLeavingSlideGL;
206 /** OpenGL handle to the entering slide's texture
208 GLuint maEnteringSlideGL;
210 Reference< presentation::XSlideShowView > mxView;
211 Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
212 Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
214 /** raw bytes of the entering bitmap
216 uno::Sequence<sal_Int8> maEnteringBytes;
218 /** raw bytes of the leaving bitmap
220 uno::Sequence<sal_Int8> maLeavingBytes;
222 bool mbRestoreSync;
224 /** the form the raw bytes are in for the bitmaps
226 rendering::IntegerBitmapLayout maSlideBitmapLayout;
228 /** the size of the slides
230 geometry::IntegerSize2D maSlideSize;
232 /** Our Transition to be used.
234 std::shared_ptr<OGLTransitionImpl> mpTransition;
236 public:
237 /** whether we are running on ATI fglrx with bug related to textures
239 bool mbBrokenTexturesATI;
241 /** GL version
243 float mnGLVersion;
246 Whether the display has GLX extension on X11, always true otherwise (?)
248 bool mbValidOpenGLContext;
250 #if OSL_DEBUG_LEVEL > 0
251 std::chrono::steady_clock::time_point m_UpdateStartTime;
252 std::chrono::steady_clock::time_point m_UpdateEndTime;
253 std::chrono::steady_clock::time_point m_StartTime;
254 std::chrono::steady_clock::time_point m_EndTime;
255 std::chrono::steady_clock::duration m_TotalUpdateDuration;
256 int mnFrameCount;
257 #endif
260 bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView,
261 const Reference< rendering::XBitmap >& xLeavingSlide,
262 const Reference< rendering::XBitmap >& xEnteringSlide )
264 bool const bValidContext( initWindowFromSlideShowView( xView ) );
265 impl_initializeFlags( bValidContext );
267 setSlides( xLeavingSlide, xEnteringSlide );
269 CHECK_GL_ERROR();
270 return mbValidOpenGLContext;
273 void OGLTransitionerImpl::impl_initializeFlags( bool const bValidContext )
275 CHECK_GL_ERROR();
276 mbValidOpenGLContext = bValidContext;
277 if ( bValidContext ) {
278 mnGLVersion = OpenGLHelper::getGLVersion();
279 SAL_INFO("slideshow.opengl", "GL version: " << mnGLVersion << "" );
281 #if defined( UNX ) && !defined( MACOSX )
282 const GLubyte* vendor = glGetString( GL_VENDOR );
283 /* TODO: check for version once the bug in fglrx driver is fixed */
284 mbBrokenTexturesATI = (vendor && strcmp( reinterpret_cast<const char *>(vendor), "ATI Technologies Inc." ) == 0 );
285 #endif
287 CHECK_GL_ERROR();
290 bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
292 osl::MutexGuard const guard( m_aMutex );
294 if (isDisposed())
295 return false;
297 mxView = xView;
298 if( !mxView.is() )
299 return false;
301 #if OSL_DEBUG_LEVEL > 0
302 TimerContext aTimerContext("initWindowFromSlideShowView");
303 #endif
305 /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
306 uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
307 uno::Sequence< uno::Any > aDeviceParams;
308 ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
310 OUString aImplName;
311 aDeviceParams[ 0 ] >>= aImplName;
313 sal_Int64 aVal = 0;
314 aDeviceParams[1] >>= aVal;
316 mpContext = OpenGLContext::Create();
318 OutputDevice* pDevice = reinterpret_cast<OutputDevice*>(aVal);
319 vcl::Window* pWindow = pDevice ? pDevice->GetOwnerWindow() : nullptr;
321 if( !mpContext->init( pWindow) ) {
322 mpContext->requestLegacyContext();
323 if( !mpContext->init( pWindow ) )
324 return false;
326 SAL_INFO("slideshow.opengl", "created the context");
328 mpContext->makeCurrent();
329 CHECK_GL_ERROR();
331 awt::Rectangle aCanvasArea = mxView->getCanvasArea();
332 mpContext->setWinPosAndSize(Point(aCanvasArea.X, aCanvasArea.Y), Size(aCanvasArea.Width, aCanvasArea.Height));
333 SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea.X << "," << aCanvasArea.Y << " - " << aCanvasArea.Width << "x" << aCanvasArea.Height);
335 CHECK_GL_ERROR();
336 glEnable(GL_CULL_FACE);
337 CHECK_GL_ERROR();
338 glCullFace(GL_BACK);
339 CHECK_GL_ERROR();
340 glClearColor (0, 0, 0, 0);
341 CHECK_GL_ERROR();
342 glClear(GL_COLOR_BUFFER_BIT);
343 CHECK_GL_ERROR();
345 mpContext->swapBuffers();
347 CHECK_GL_ERROR();
349 return true;
352 void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
353 const uno::Reference< rendering::XBitmap >& xEnteringSlide )
355 osl::MutexGuard const guard( m_aMutex );
357 if (isDisposed())
358 return;
360 mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
361 mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
363 maSlideSize = mxLeavingBitmap->getSize();
364 SAL_INFO("slideshow.opengl", "leaving bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height);
365 maSlideSize = mxEnteringBitmap->getSize();
366 SAL_INFO("slideshow.opengl", "entering bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height);
368 //to avoid annoying flashing under X entering and leaving slides with opengl effects set the leaving
369 //bitmap as the background pixmap of the opengl child window and the entering bitmap as the background
370 //pixmap of the non-opengl parent window. If any expose events occur around the start and end of
371 //the transition then those windows are default filled by X with the desired start/end image so there's
372 //no visible flash
373 SystemChildWindow* pChildWindow = mpContext->getChildWindow();
374 if (!pChildWindow)
375 return;
377 css::uno::Reference<css::beans::XFastPropertySet> xEnteringFastPropertySet(mxEnteringBitmap, css::uno::UNO_QUERY);
378 css::uno::Reference<css::beans::XFastPropertySet> xLeavingFastPropertySet(mxLeavingBitmap, css::uno::UNO_QUERY);
379 css::uno::Sequence<css::uno::Any> aEnteringBitmap;
380 css::uno::Sequence<css::uno::Any> aLeavingBitmap;
381 if (xEnteringFastPropertySet && xLeavingFastPropertySet)
383 xEnteringFastPropertySet->getFastPropertyValue(1) >>= aEnteringBitmap;
384 xLeavingFastPropertySet->getFastPropertyValue(1) >>= aLeavingBitmap;
386 if (aEnteringBitmap.getLength() == 3 && aLeavingBitmap.getLength() == 3)
387 pChildWindow->SetLeaveEnterBackgrounds(aLeavingBitmap, aEnteringBitmap);
391 void OGLTransitionerImpl::impl_prepareSlides()
393 geometry::IntegerRectangle2D aSlideRect;
394 aSlideRect.X1 = 0;
395 aSlideRect.X2 = maSlideSize.Width;
396 aSlideRect.Y1 = 0;
397 aSlideRect.Y2 = maSlideSize.Height;
399 CHECK_GL_ERROR();
400 mpContext->sync();
401 CHECK_GL_ERROR();
403 maLeavingBytes = mxLeavingBitmap->getData(maSlideBitmapLayout, aSlideRect);
404 maEnteringBytes = mxEnteringBitmap->getData(maSlideBitmapLayout, aSlideRect);
406 CHECK_GL_ERROR();
407 GLInitSlides();
409 SAL_WARN_IF(maSlideBitmapLayout.PlaneStride != 0, "slideshow.opengl","only handle no plane stride now");
411 mpContext->sync();
413 CHECK_GL_ERROR();
415 // synchronized X still gives us much smoother play
416 // I suspect some issues in above code in slideshow
417 // synchronize whole transition for now
418 const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
419 mbRestoreSync = rGLWindow.Synchronize(true);
422 bool OGLTransitionerImpl::impl_prepareTransition()
424 if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
425 return mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL, mpContext.get() );
426 return false;
429 bool OGLTransitionerImpl::setTransition( const std::shared_ptr<OGLTransitionImpl>& pTransition )
431 if ( mpTransition ) // already initialized
432 return true;
434 mpTransition = pTransition;
436 mpContext->makeCurrent();
437 CHECK_GL_ERROR();
439 bool succeeded = impl_prepareTransition();
440 if (!succeeded) {
441 mpTransition = nullptr;
442 return false;
445 impl_prepareSlides();
446 return true;
449 void OGLTransitionerImpl::createTexture( GLuint* texID,
450 bool useMipmap,
451 uno::Sequence<sal_Int8>& data,
452 const OGLFormat* pFormat )
454 CHECK_GL_ERROR();
455 glDeleteTextures( 1, texID );
456 glGenTextures( 1, texID );
457 glBindTexture( GL_TEXTURE_2D, *texID );
458 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
459 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
460 CHECK_GL_ERROR();
462 impl_createTexture( useMipmap, data, pFormat );
464 SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL");
465 CHECK_GL_ERROR();
468 class OGLColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace >
470 private:
471 uno::Sequence< sal_Int8 > maComponentTags;
472 uno::Sequence< sal_Int32 > maBitCounts;
474 virtual sal_Int8 SAL_CALL getType( ) override
476 return rendering::ColorSpaceType::RGB;
478 virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) override
480 return maComponentTags;
482 virtual sal_Int8 SAL_CALL getRenderingIntent( ) override
484 return rendering::RenderingIntent::PERCEPTUAL;
486 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) override
488 return uno::Sequence< beans::PropertyValue >();
490 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
491 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
493 // TODO(P3): if we know anything about target
494 // colorspace, this can be greatly sped up
495 uno::Sequence<rendering::ARGBColor> aIntermediate(
496 convertToARGB(deviceColor));
497 return targetColorSpace->convertFromARGB(aIntermediate);
499 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) override
501 const double* pIn( deviceColor.getConstArray() );
502 const std::size_t nLen( deviceColor.getLength() );
503 ENSURE_ARG_OR_THROW2(nLen%4==0,
504 "number of channels no multiple of 4",
505 static_cast<rendering::XColorSpace*>(this), 0);
507 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
508 rendering::RGBColor* pOut( aRes.getArray() );
509 for( std::size_t i=0; i<nLen; i+=4 )
511 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
512 pIn += 4;
514 return aRes;
516 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) override
518 const double* pIn( deviceColor.getConstArray() );
519 const std::size_t nLen( deviceColor.getLength() );
520 ENSURE_ARG_OR_THROW2(nLen%4==0,
521 "number of channels no multiple of 4",
522 static_cast<rendering::XColorSpace*>(this), 0);
524 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
525 rendering::ARGBColor* pOut( aRes.getArray() );
526 for( std::size_t i=0; i<nLen; i+=4 )
528 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
529 pIn += 4;
531 return aRes;
533 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) override
535 const double* pIn( deviceColor.getConstArray() );
536 const std::size_t nLen( deviceColor.getLength() );
537 ENSURE_ARG_OR_THROW2(nLen%4==0,
538 "number of channels no multiple of 4",
539 static_cast<rendering::XColorSpace*>(this), 0);
541 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
542 rendering::ARGBColor* pOut( aRes.getArray() );
543 for( std::size_t i=0; i<nLen; i+=4 )
545 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
546 pIn += 4;
548 return aRes;
550 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
552 const sal_Int32 nLen( rgbColor.getLength() );
554 uno::Sequence< double > aRes(nLen*4);
555 double* pColors=aRes.getArray();
556 for( const rendering::RGBColor& rIn : rgbColor )
558 *pColors++ = rIn.Red;
559 *pColors++ = rIn.Green;
560 *pColors++ = rIn.Blue;
561 *pColors++ = 1.0;
563 return aRes;
565 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
567 const sal_Int32 nLen( rgbColor.getLength() );
569 uno::Sequence< double > aRes(nLen*4);
570 double* pColors=aRes.getArray();
571 for( const rendering::ARGBColor& rIn : rgbColor )
573 *pColors++ = rIn.Red;
574 *pColors++ = rIn.Green;
575 *pColors++ = rIn.Blue;
576 *pColors++ = rIn.Alpha;
578 return aRes;
580 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
582 const sal_Int32 nLen( rgbColor.getLength() );
584 uno::Sequence< double > aRes(nLen*4);
585 double* pColors=aRes.getArray();
586 for( const rendering::ARGBColor& rIn : rgbColor )
588 *pColors++ = rIn.Red/rIn.Alpha;
589 *pColors++ = rIn.Green/rIn.Alpha;
590 *pColors++ = rIn.Blue/rIn.Alpha;
591 *pColors++ = rIn.Alpha;
593 return aRes;
596 // XIntegerBitmapColorSpace
597 virtual sal_Int32 SAL_CALL getBitsPerPixel( ) override
599 return 32;
601 virtual uno::Sequence< sal_Int32 > SAL_CALL getComponentBitCounts( ) override
603 return maBitCounts;
605 virtual sal_Int8 SAL_CALL getEndianness( ) override
607 return util::Endianness::LITTLE;
609 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor,
610 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
612 if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
614 const sal_Int32 nLen( deviceColor.getLength() );
615 ENSURE_ARG_OR_THROW2(nLen%4==0,
616 "number of channels no multiple of 4",
617 static_cast<rendering::XColorSpace*>(this), 0);
619 uno::Sequence<double> aRes(nLen);
620 std::transform(deviceColor.begin(), deviceColor.end(), aRes.getArray(),
621 vcl::unotools::toDoubleColor);
622 return aRes;
624 else
626 // TODO(P3): if we know anything about target
627 // colorspace, this can be greatly sped up
628 uno::Sequence<rendering::ARGBColor> aIntermediate(
629 convertIntegerToARGB(deviceColor));
630 return targetColorSpace->convertFromARGB(aIntermediate);
633 virtual uno::Sequence< sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor,
634 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) override
636 if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
638 // it's us, so simply pass-through the data
639 return deviceColor;
641 else
643 // TODO(P3): if we know anything about target
644 // colorspace, this can be greatly sped up
645 uno::Sequence<rendering::ARGBColor> aIntermediate(
646 convertIntegerToARGB(deviceColor));
647 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
650 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< sal_Int8 >& deviceColor ) override
652 const sal_Int8* pIn( deviceColor.getConstArray() );
653 const std::size_t nLen( deviceColor.getLength() );
654 ENSURE_ARG_OR_THROW2(nLen%4==0,
655 "number of channels no multiple of 4",
656 static_cast<rendering::XColorSpace*>(this), 0);
658 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
659 rendering::RGBColor* pOut( aRes.getArray() );
660 for( std::size_t i=0; i<nLen; i+=4 )
662 *pOut++ = rendering::RGBColor(
663 vcl::unotools::toDoubleColor(pIn[0]),
664 vcl::unotools::toDoubleColor(pIn[1]),
665 vcl::unotools::toDoubleColor(pIn[2]));
666 pIn += 4;
668 return aRes;
671 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< sal_Int8 >& deviceColor ) override
673 const sal_Int8* pIn( deviceColor.getConstArray() );
674 const std::size_t nLen( deviceColor.getLength() );
675 ENSURE_ARG_OR_THROW2(nLen%4==0,
676 "number of channels no multiple of 4",
677 static_cast<rendering::XColorSpace*>(this), 0);
679 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
680 rendering::ARGBColor* pOut( aRes.getArray() );
681 for( std::size_t i=0; i<nLen; i+=4 )
683 *pOut++ = rendering::ARGBColor(
684 vcl::unotools::toDoubleColor(pIn[3]),
685 vcl::unotools::toDoubleColor(pIn[0]),
686 vcl::unotools::toDoubleColor(pIn[1]),
687 vcl::unotools::toDoubleColor(pIn[2]));
688 pIn += 4;
690 return aRes;
693 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< sal_Int8 >& deviceColor ) override
695 const sal_Int8* pIn( deviceColor.getConstArray() );
696 const std::size_t nLen( deviceColor.getLength() );
697 ENSURE_ARG_OR_THROW2(nLen%4==0,
698 "number of channels no multiple of 4",
699 static_cast<rendering::XColorSpace*>(this), 0);
701 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
702 rendering::ARGBColor* pOut( aRes.getArray() );
703 for( std::size_t i=0; i<nLen; i+=4 )
705 const sal_Int8 nAlpha( pIn[3] );
706 *pOut++ = rendering::ARGBColor(
707 vcl::unotools::toDoubleColor(nAlpha),
708 vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
709 vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
710 vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
711 pIn += 4;
713 return aRes;
716 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
718 const sal_Int32 nLen( rgbColor.getLength() );
720 uno::Sequence< sal_Int8 > aRes(nLen*4);
721 sal_Int8* pColors=aRes.getArray();
722 for( const rendering::RGBColor& rIn : rgbColor )
724 *pColors++ = vcl::unotools::toByteColor(rIn.Red);
725 *pColors++ = vcl::unotools::toByteColor(rIn.Green);
726 *pColors++ = vcl::unotools::toByteColor(rIn.Blue);
727 *pColors++ = -1;
729 return aRes;
732 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
734 const sal_Int32 nLen( rgbColor.getLength() );
736 uno::Sequence< sal_Int8 > aRes(nLen*4);
737 sal_Int8* pColors=aRes.getArray();
738 for( const rendering::ARGBColor& rIn : rgbColor )
740 *pColors++ = vcl::unotools::toByteColor(rIn.Red);
741 *pColors++ = vcl::unotools::toByteColor(rIn.Green);
742 *pColors++ = vcl::unotools::toByteColor(rIn.Blue);
743 *pColors++ = vcl::unotools::toByteColor(rIn.Alpha);
745 return aRes;
748 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
750 const sal_Int32 nLen( rgbColor.getLength() );
752 uno::Sequence< sal_Int8 > aRes(nLen*4);
753 sal_Int8* pColors=aRes.getArray();
754 for( const rendering::ARGBColor& rIn : rgbColor )
756 *pColors++ = vcl::unotools::toByteColor(rIn.Red/rIn.Alpha);
757 *pColors++ = vcl::unotools::toByteColor(rIn.Green/rIn.Alpha);
758 *pColors++ = vcl::unotools::toByteColor(rIn.Blue/rIn.Alpha);
759 *pColors++ = vcl::unotools::toByteColor(rIn.Alpha);
761 return aRes;
764 public:
765 OGLColorSpace() :
766 maComponentTags(4),
767 maBitCounts(4)
769 sal_Int8* pTags = maComponentTags.getArray();
770 sal_Int32* pBitCounts = maBitCounts.getArray();
771 pTags[0] = rendering::ColorComponentTag::RGB_RED;
772 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
773 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
774 pTags[3] = rendering::ColorComponentTag::ALPHA;
776 pBitCounts[0] =
777 pBitCounts[1] =
778 pBitCounts[2] =
779 pBitCounts[3] = 8;
783 struct OGLColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>, OGLColorSpaceHolder>
785 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
787 return new OGLColorSpace();
791 uno::Reference<rendering::XIntegerBitmapColorSpace> const &
792 getOGLColorSpace()
794 return OGLColorSpaceHolder::get();
797 void buildMipmaps(
798 GLint internalFormat, GLsizei width, GLsizei height, GLenum format,
799 GLenum type, const void * data)
801 if (epoxy_has_gl_extension("GL_ARB_framebuffer_object")) {
802 glTexImage2D(
803 GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type,
804 data);
805 glGenerateMipmap(GL_TEXTURE_2D);
806 } else {
807 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
808 glTexImage2D(
809 GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type,
810 data);
811 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
813 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
814 glTexParameteri(
815 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
818 void OGLTransitionerImpl::impl_createTexture(
819 bool useMipmap,
820 uno::Sequence<sal_Int8>& data,
821 const OGLFormat* pFormat )
823 if( !pFormat )
825 CHECK_GL_ERROR();
826 // force-convert color to ARGB8888 int color space
827 uno::Sequence<sal_Int8> tempBytes(
828 maSlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
829 data,
830 getOGLColorSpace()));
831 buildMipmaps( GL_RGBA,
832 maSlideSize.Width,
833 maSlideSize.Height,
834 GL_RGBA,
835 GL_UNSIGNED_BYTE,
836 &tempBytes[0]);
838 if (epoxy_has_gl_extension("GL_EXT_texture_filter_anisotropic"))
840 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
841 GLfloat largest_supported_anisotropy;
842 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
843 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
845 } else {
846 if( mpTransition && !mbBrokenTexturesATI && !useMipmap) {
847 glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
848 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
849 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
850 } else {
851 buildMipmaps( pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
853 if (epoxy_has_gl_extension("GL_EXT_texture_filter_anisotropic"))
855 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
856 GLfloat largest_supported_anisotropy;
857 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
858 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
862 CHECK_GL_ERROR();
865 const OGLFormat* OGLTransitionerImpl::chooseFormats()
867 const OGLFormat* pDetectedFormat=nullptr;
868 uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
869 maSlideBitmapLayout.ColorSpace);
871 if( xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
872 xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB )
874 /* table for canvas->OGL format mapping. outer index is number
875 of color components (0:3, 1:4), then comes bits per pixel
876 (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
877 2:argb, 3:abgr)
879 static const OGLFormat lcl_RGB24[] =
881 // 24 bit RGB
882 {3, GL_BGR, GL_UNSIGNED_BYTE},
883 {3, GL_RGB, GL_UNSIGNED_BYTE},
884 {3, GL_BGR, GL_UNSIGNED_BYTE},
885 {3, GL_RGB, GL_UNSIGNED_BYTE}
888 #if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
889 // more format constants available
890 static const OGLFormat lcl_RGB16[] =
892 // 16 bit RGB
893 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
894 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
895 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
896 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
899 static const OGLFormat lcl_ARGB16_4[] =
901 // 16 bit ARGB
902 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
903 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
904 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
905 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
908 static const OGLFormat lcl_ARGB16_5[] =
910 // 16 bit ARGB
911 {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
912 {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
913 {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
914 {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
917 static const OGLFormat lcl_ARGB32[] =
919 // 32 bit ARGB
920 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
921 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
922 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
923 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
926 const uno::Sequence<sal_Int8> aComponentTags(
927 xIntColorSpace->getComponentTags());
928 const uno::Sequence<sal_Int32> aComponentBitcounts(
929 xIntColorSpace->getComponentBitCounts());
930 const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
931 const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
933 // supported component ordering?
934 const int nComponentOrderIndex(
935 calcComponentOrderIndex(aComponentTags));
936 if( nComponentOrderIndex != -1 )
938 switch( nBitsPerPixel )
940 case 16:
941 if( nNumComponents == 3 )
943 pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
945 else if( nNumComponents == 4 )
947 if( aComponentBitcounts[1] == 4 )
949 pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
951 else if( aComponentBitcounts[1] == 5 )
953 pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
956 break;
957 case 24:
958 if( nNumComponents == 3 )
960 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
962 break;
963 case 32:
964 if ( nNumComponents == 4 )
966 pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
968 break;
971 #else
972 const uno::Sequence<sal_Int8> aComponentTags(
973 xIntColorSpace->getComponentTags());
974 const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
975 if( aComponentTags.getLength() == 3 &&
976 nComponentOrderIndex != -1 &&
977 xIntColorSpace->getBitsPerPixel() == 24 )
979 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
981 #endif
984 return pDetectedFormat;
987 void OGLTransitionerImpl::GLInitSlides()
989 osl::MutexGuard const guard( m_aMutex );
991 if (isDisposed() || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
992 return;
994 #if OSL_DEBUG_LEVEL > 0
995 TimerContext aTimerContext("texture creation");
996 #endif
998 mpContext->makeCurrent();
1000 const OGLFormat* pFormat = chooseFormats();
1002 CHECK_GL_ERROR();
1003 createTexture( &maLeavingSlideGL,
1004 mpTransition->getSettings().mbUseMipMapLeaving,
1005 maLeavingBytes,
1006 pFormat );
1008 createTexture( &maEnteringSlideGL,
1009 mpTransition->getSettings().mbUseMipMapEntering,
1010 maEnteringBytes,
1011 pFormat );
1013 CHECK_GL_ERROR();
1014 mpContext->sync();
1015 CHECK_GL_ERROR();
1018 void SAL_CALL OGLTransitionerImpl::update( double nTime )
1020 #if OSL_DEBUG_LEVEL > 0
1021 mnFrameCount ++;
1022 m_UpdateStartTime = std::chrono::steady_clock::now();
1023 if( mnFrameCount == 1 ) {
1024 m_StartTime = m_UpdateStartTime;
1025 m_TotalUpdateDuration = std::chrono::seconds(0);
1027 #endif
1028 osl::MutexGuard const guard( m_aMutex );
1030 if (isDisposed() || !mbValidOpenGLContext || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
1031 return;
1033 mpContext->makeCurrent();
1034 CHECK_GL_ERROR();
1036 glEnable(GL_DEPTH_TEST);
1037 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1038 CHECK_GL_ERROR();
1040 const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
1041 mpTransition->display(nTime, maLeavingSlideGL, maEnteringSlideGL,
1042 maSlideSize.Width, maSlideSize.Height,
1043 static_cast<double>(rGLWindow.Width),
1044 static_cast<double>(rGLWindow.Height),
1045 mpContext.get());
1047 mpContext->swapBuffers();
1049 mpContext->show();
1050 mpContext->sync();
1051 CHECK_GL_ERROR();
1053 #if OSL_DEBUG_LEVEL > 0
1054 m_UpdateEndTime = std::chrono::steady_clock::now();
1056 SAL_INFO("slideshow.opengl", "update time: " << nTime);
1057 SAL_INFO("slideshow.opengl", "update took: " << std::chrono::duration_cast<std::chrono::milliseconds>(m_UpdateEndTime - m_UpdateStartTime).count());
1058 m_TotalUpdateDuration += m_UpdateEndTime - m_UpdateStartTime;
1059 #endif
1062 void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
1063 const Reference< rendering::XBitmap >& rLeavingBitmap,
1064 const Reference< rendering::XBitmap >& rEnteringBitmap )
1066 SAL_INFO("slideshow.opengl", "transitioner: view changed");
1068 impl_dispose();
1070 initWindowFromSlideShowView( rView );
1071 setSlides( rLeavingBitmap, rEnteringBitmap );
1072 impl_prepareSlides();
1073 impl_prepareTransition();
1076 void OGLTransitionerImpl::disposeTextures()
1078 mpContext->makeCurrent();
1079 CHECK_GL_ERROR();
1081 glDeleteTextures(1,&maLeavingSlideGL);
1082 maLeavingSlideGL = 0;
1083 glDeleteTextures(1,&maEnteringSlideGL);
1084 maEnteringSlideGL = 0;
1086 CHECK_GL_ERROR();
1089 void OGLTransitionerImpl::impl_dispose()
1091 mpContext->makeCurrent();
1092 CHECK_GL_ERROR();
1094 if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
1095 mpTransition->finish();
1096 disposeTextures();
1097 if( mpContext.is() )
1098 mpContext->dispose();
1099 mpContext.clear();
1102 // we are about to be disposed (someone call dispose() on us)
1103 void OGLTransitionerImpl::disposing()
1105 osl::MutexGuard const guard( m_aMutex );
1107 #if OSL_DEBUG_LEVEL > 0
1108 SAL_INFO("slideshow.opengl", "dispose " << this);
1109 if( mnFrameCount ) {
1110 m_EndTime = std::chrono::steady_clock::now();
1111 auto const duration = m_EndTime - m_StartTime;
1112 SAL_INFO("slideshow.opengl",
1113 "whole transition (frames: " << mnFrameCount
1114 << ") took: " << std::chrono::duration_cast<std::chrono::microseconds>(duration).count()
1115 << " fps: "
1116 << ((static_cast<double>(mnFrameCount)*1000000000.0)/std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count())
1117 << " time spent in updates: " << std::chrono::duration_cast<std::chrono::microseconds>(m_TotalUpdateDuration).count()
1118 << " percentage of transition time: "
1119 << (100*((static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(m_TotalUpdateDuration).count()))/(static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count()))))
1120 << '%'
1123 #endif
1125 if (mbRestoreSync && mpContext.is()) {
1126 // try to reestablish synchronize state
1127 const char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
1128 mpContext->getOpenGLWindow().Synchronize(sal_synchronize && *sal_synchronize == '1' );
1131 impl_dispose();
1133 mpTransition.reset();
1135 mxLeavingBitmap.clear();
1136 mxEnteringBitmap.clear();
1137 mxView.clear();
1140 OGLTransitionerImpl::OGLTransitionerImpl()
1141 : OGLTransitionerImplBase(m_aMutex)
1142 , mpContext()
1143 , maLeavingSlideGL(0)
1144 , maEnteringSlideGL(0)
1145 , mxView()
1146 , maEnteringBytes()
1147 , maLeavingBytes()
1148 , mbRestoreSync(false)
1149 , maSlideBitmapLayout()
1150 , maSlideSize()
1151 , mbBrokenTexturesATI(false)
1152 , mnGLVersion(0)
1153 , mbValidOpenGLContext(false)
1154 #if OSL_DEBUG_LEVEL > 0
1155 , mnFrameCount(0)
1156 #endif
1160 typedef cppu::WeakComponentImplHelper<presentation::XTransitionFactory, lang::XServiceInfo> OGLTransitionFactoryImplBase;
1162 class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
1164 public:
1165 explicit OGLTransitionFactoryImpl() :
1166 OGLTransitionFactoryImplBase(m_aMutex)
1169 // XServiceInfo
1170 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override
1172 return { "com.sun.star.presentation.TransitionFactory" };
1174 virtual OUString SAL_CALL getImplementationName() override
1176 return "com.sun.star.comp.presentation.OGLTransitionFactory";
1178 virtual sal_Bool SAL_CALL supportsService(const OUString& aServiceName) override
1180 return cppu::supportsService(this, aServiceName);
1183 // XTransitionFactory
1184 virtual sal_Bool SAL_CALL hasTransition( sal_Int16 transitionType, sal_Int16 transitionSubType ) override
1186 if( !OpenGLHelper::supportsOpenGL())
1187 return false;
1188 // A set of css::animation::TransitionSubType that don't have any meaning (in the SMIL 2.0
1189 // standard) for MISCSHAPEWIPE have been chosen to refer to some of these "fancy" optional
1190 // transitions. (The only subtypes of 'miscShapeWipe' defined in the standard are 'heart'
1191 // and 'keyhole'.) The set of subtypes used seems to be a bit random; it starts from the
1192 // beginning of the list (in the order (numeric) in our TransitionSubType set of constants)
1193 // but then jumps a bit randomly. The numeric values as such have no meaning, but still.
1195 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1196 switch( transitionSubType )
1198 case animations::TransitionSubType::LEFTTORIGHT: // 1
1199 case animations::TransitionSubType::TOPTOBOTTOM: // 2
1200 case animations::TransitionSubType::TOPLEFT: // 3
1201 case animations::TransitionSubType::TOPRIGHT: // 4
1202 case animations::TransitionSubType::BOTTOMRIGHT: // 5
1203 case animations::TransitionSubType::BOTTOMLEFT: // 6
1204 case animations::TransitionSubType::TOPCENTER: // 7
1205 case animations::TransitionSubType::RIGHTCENTER: // 8
1206 case animations::TransitionSubType::BOTTOMCENTER: // 9
1207 case animations::TransitionSubType::CORNERSIN: // 11
1208 case animations::TransitionSubType::CORNERSOUT: // 12
1209 case animations::TransitionSubType::VERTICAL: // 13
1210 case animations::TransitionSubType::HORIZONTAL: // 14
1211 case animations::TransitionSubType::DIAMOND: // 26
1212 case animations::TransitionSubType::CIRCLE: // 27
1213 case animations::TransitionSubType::HEART: // 31
1214 case animations::TransitionSubType::FANOUTHORIZONTAL: // 55
1215 case animations::TransitionSubType::ACROSS: // 108
1216 return true;
1218 default:
1219 return false;
1221 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1222 return true;
1223 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1224 return true;
1225 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1226 return true;
1227 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1228 return true;
1229 } else
1230 return false;
1233 virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
1234 sal_Int16 transitionType,
1235 sal_Int16 transitionSubType,
1236 sal_Int32 transitionFadeColor,
1237 const uno::Reference< presentation::XSlideShowView >& view,
1238 const uno::Reference< rendering::XBitmap >& leavingBitmap,
1239 const uno::Reference< rendering::XBitmap >& enteringBitmap ) override
1241 if( !hasTransition( transitionType, transitionSubType ) )
1242 return uno::Reference< presentation::XTransition >();
1244 rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() );
1245 if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) )
1246 return uno::Reference< presentation::XTransition >();
1248 std::shared_ptr<OGLTransitionImpl> pTransition;
1250 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1251 switch( transitionSubType )
1253 case animations::TransitionSubType::LEFTTORIGHT:
1254 pTransition = makeFallLeaving();
1255 break;
1256 case animations::TransitionSubType::TOPTOBOTTOM:
1257 pTransition = makeTurnAround();
1258 break;
1259 case animations::TransitionSubType::TOPLEFT:
1260 pTransition = makeIris();
1261 break;
1262 case animations::TransitionSubType::TOPRIGHT:
1263 pTransition = makeTurnDown();
1264 break;
1265 case animations::TransitionSubType::BOTTOMRIGHT:
1266 pTransition = makeRochade();
1267 break;
1268 case animations::TransitionSubType::BOTTOMLEFT:
1269 pTransition = makeVenetianBlinds( true, 8 );
1270 break;
1271 case animations::TransitionSubType::TOPCENTER:
1272 pTransition = makeVenetianBlinds( false, 6 );
1273 break;
1274 case animations::TransitionSubType::RIGHTCENTER:
1275 pTransition = makeStatic();
1276 break;
1277 case animations::TransitionSubType::BOTTOMCENTER:
1278 pTransition = makeDissolve();
1279 break;
1280 case animations::TransitionSubType::CORNERSIN:
1281 pTransition = makeInsideCubeFaceToLeft();
1282 break;
1283 case animations::TransitionSubType::CORNERSOUT:
1284 pTransition = makeOutsideCubeFaceToLeft();
1285 break;
1286 case animations::TransitionSubType::VERTICAL:
1287 pTransition = makeVortex();
1288 break;
1289 case animations::TransitionSubType::HORIZONTAL:
1290 pTransition = makeRipple();
1291 break;
1292 case animations::TransitionSubType::CIRCLE:
1293 pTransition = makeRevolvingCircles(8,128);
1294 break;
1295 case animations::TransitionSubType::FANOUTHORIZONTAL:
1296 pTransition = makeHelix(20);
1297 break;
1298 case animations::TransitionSubType::ACROSS:
1299 pTransition = makeNByMTileFlip(8,6);
1300 break;
1301 case animations::TransitionSubType::DIAMOND:
1302 pTransition = makeGlitter();
1303 break;
1304 case animations::TransitionSubType::HEART:
1305 pTransition = makeHoneycomb();
1306 break;
1308 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1309 pTransition = makeFadeSmoothly();
1310 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1311 pTransition = makeFadeThroughColor( transitionFadeColor == 0xffffff );
1312 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1313 pTransition = makeDiamond();
1314 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1315 pTransition = makeNewsflash();
1318 if ( !pTransition || !xRes->setTransition(pTransition) )
1319 return uno::Reference< presentation::XTransition >();
1321 return xRes;
1327 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1328 slideshow_OGLTransitionFactoryImpl_get_implementation(
1329 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
1331 return cppu::acquire(new OGLTransitionFactoryImpl());
1333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */