build fix
[LibreOffice.git] / slideshow / source / engine / opengl / TransitionerImpl.cxx
blob61a28e9422ff595ec9e90184caca73b3e798d4fc
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>
30 #include <glm/gtc/matrix_transform.hpp>
31 #include <glm/gtc/type_ptr.hpp>
33 #include <memory>
35 #include <com/sun/star/beans/XFastPropertySet.hpp>
36 #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
37 #include <com/sun/star/rendering/ColorComponentTag.hpp>
38 #include <com/sun/star/rendering/ColorSpaceType.hpp>
39 #include <com/sun/star/rendering/RenderingIntent.hpp>
40 #include <com/sun/star/util/Endianness.hpp>
41 #include <com/sun/star/animations/TransitionType.hpp>
42 #undef IN
43 #undef OUT
44 #include <com/sun/star/animations/TransitionSubType.hpp>
45 #include <com/sun/star/presentation/XTransitionFactory.hpp>
46 #include <com/sun/star/presentation/XTransition.hpp>
47 #include <com/sun/star/presentation/XSlideShowView.hpp>
48 #include <com/sun/star/uno/XComponentContext.hpp>
49 #include <com/sun/star/rendering/XIntegerBitmap.hpp>
50 #include <com/sun/star/geometry/IntegerSize2D.hpp>
52 #include <cppuhelper/compbase.hxx>
53 #include <cppuhelper/basemutex.hxx>
54 #include <cppuhelper/factory.hxx>
55 #include <rtl/ref.hxx>
57 #include <comphelper/servicedecl.hxx>
59 #include <canvas/canvastools.hxx>
61 #include <tools/diagnose_ex.h>
63 #include <vcl/canvastools.hxx>
64 #include <vcl/opengl/OpenGLContext.hxx>
65 #include <vcl/opengl/OpenGLHelper.hxx>
66 #include <vcl/window.hxx>
68 #include "TransitionImpl.hxx"
70 #include <vcl/sysdata.hxx>
72 #if OSL_DEBUG_LEVEL > 0
73 #include <chrono>
74 #endif
76 using namespace ::com::sun::star;
77 using ::com::sun::star::beans::XFastPropertySet;
78 using ::com::sun::star::uno::Any;
79 using ::com::sun::star::uno::Reference;
80 using ::com::sun::star::uno::Sequence;
81 using ::com::sun::star::uno::UNO_QUERY;
82 using ::com::sun::star::uno::UNO_QUERY_THROW;
84 namespace
87 typedef cppu::WeakComponentImplHelper<presentation::XTransition> OGLTransitionerImplBase;
89 #if OSL_DEBUG_LEVEL > 0
90 class TimerContext
92 public:
93 explicit TimerContext(OUString const& rWhat)
94 : m_aWhat(rWhat)
95 , m_StartTime(std::chrono::steady_clock::now())
98 ~TimerContext()
100 auto const aDuration(std::chrono::steady_clock::now() - m_StartTime);
101 SAL_INFO("slideshow.opengl", m_aWhat << " took: " << std::chrono::duration_cast<std::chrono::microseconds>(aDuration).count());
103 private:
104 OUString const m_aWhat;
105 std::chrono::steady_clock::time_point const m_StartTime;
107 #endif
109 struct OGLFormat
111 GLint nInternalFormat;
112 GLenum eFormat;
113 GLenum eType;
116 /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
118 int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
120 using namespace rendering::ColorComponentTag;
122 static const sal_Int8 aOrderTable[] =
124 RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
125 RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
126 ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
127 ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
130 const sal_Int32 nNumComps(rTags.getLength());
131 const sal_Int8* pLine=aOrderTable;
132 for(int i=0; i<4; ++i)
134 int j=0;
135 while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
136 ++j;
138 // all of the line passed, this is a match!
139 if( j==nNumComps )
140 return i;
142 pLine+=4;
145 return -1;
148 /** This is the Transitioner class for OpenGL 3D transitions in
149 * slideshow. This class is implicitly
150 * constructed from XTransitionFactory.
152 class OGLTransitionerImpl : private cppu::BaseMutex, public OGLTransitionerImplBase
154 public:
155 OGLTransitionerImpl();
156 OGLTransitionerImpl(const OGLTransitionerImpl&) = delete;
157 OGLTransitionerImpl& operator=(const OGLTransitionerImpl&) = delete;
158 bool setTransition( const std::shared_ptr<OGLTransitionImpl>& pOGLTransition );
159 bool initialize( const Reference< presentation::XSlideShowView >& xView,
160 const Reference< rendering::XBitmap >& xLeavingSlide,
161 const Reference< rendering::XBitmap >& xEnteringSlide );
163 // XTransition
164 virtual void SAL_CALL update( double nTime )
165 throw (uno::RuntimeException, std::exception) override;
166 virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
167 const Reference< rendering::XBitmap >& rLeavingBitmap,
168 const Reference< rendering::XBitmap >& rEnteringBitmap )
169 throw (uno::RuntimeException, std::exception) override;
171 protected:
172 void disposeTextures();
174 // WeakComponentImplHelperBase
175 virtual void SAL_CALL disposing() override;
177 bool isDisposed() const
179 return (rBHelper.bDisposed || rBHelper.bInDispose);
182 void createTexture( GLuint* texID,
183 bool useMipmap,
184 uno::Sequence<sal_Int8>& data,
185 const OGLFormat* pFormat );
186 const OGLFormat* chooseFormats();
188 private:
189 void impl_initializeFlags( bool const bGLXPresent );
191 void impl_dispose();
193 void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
194 void impl_prepareSlides();
196 void impl_createTexture( bool useMipmap, uno::Sequence<sal_Int8>& data, const OGLFormat* pFormat );
198 bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
199 /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
201 void GLInitSlides();
203 bool impl_prepareTransition();
205 private:
206 rtl::Reference<OpenGLContext> mpContext;
208 /** OpenGL handle to the leaving slide's texture
210 GLuint maLeavingSlideGL;
211 /** OpenGL handle to the entering slide's texture
213 GLuint maEnteringSlideGL;
215 Reference< presentation::XSlideShowView > mxView;
216 Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
217 Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
219 /** raw bytes of the entering bitmap
221 uno::Sequence<sal_Int8> maEnteringBytes;
223 /** raw bytes of the leaving bitmap
225 uno::Sequence<sal_Int8> maLeavingBytes;
227 bool mbRestoreSync;
229 /** the form the raw bytes are in for the bitmaps
231 rendering::IntegerBitmapLayout maSlideBitmapLayout;
233 /** the size of the slides
235 geometry::IntegerSize2D maSlideSize;
237 /** Our Transition to be used.
239 std::shared_ptr<OGLTransitionImpl> mpTransition;
241 public:
242 /** whether we are running on ATI fglrx with bug related to textures
244 bool mbBrokenTexturesATI;
246 /** GL version
248 float mnGLVersion;
251 Whether the display has GLX extension on X11, always true otherwise (?)
253 bool mbValidOpenGLContext;
255 #if OSL_DEBUG_LEVEL > 0
256 std::chrono::steady_clock::time_point m_UpdateStartTime;
257 std::chrono::steady_clock::time_point m_UpdateEndTime;
258 std::chrono::steady_clock::time_point m_StartTime;
259 std::chrono::steady_clock::time_point m_EndTime;
260 std::chrono::steady_clock::duration m_TotalUpdateDuration;
261 int mnFrameCount;
262 #endif
265 bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView,
266 const Reference< rendering::XBitmap >& xLeavingSlide,
267 const Reference< rendering::XBitmap >& xEnteringSlide )
269 bool const bValidContext( initWindowFromSlideShowView( xView ) );
270 impl_initializeFlags( bValidContext );
272 setSlides( xLeavingSlide, xEnteringSlide );
274 CHECK_GL_ERROR();
275 return mbValidOpenGLContext;
278 void OGLTransitionerImpl::impl_initializeFlags( bool const bValidContext )
280 CHECK_GL_ERROR();
281 mbValidOpenGLContext = bValidContext;
282 if ( bValidContext ) {
283 mnGLVersion = OpenGLHelper::getGLVersion();
284 SAL_INFO("slideshow.opengl", "GL version: " << mnGLVersion << "" );
286 #if defined( UNX ) && !defined( MACOSX )
287 const GLubyte* vendor = glGetString( GL_VENDOR );
288 /* TODO: check for version once the bug in fglrx driver is fixed */
289 mbBrokenTexturesATI = (vendor && strcmp( reinterpret_cast<const char *>(vendor), "ATI Technologies Inc." ) == 0 );
290 #endif
292 CHECK_GL_ERROR();
295 bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
297 osl::MutexGuard const guard( m_aMutex );
299 if (isDisposed())
300 return false;
302 mxView.set( xView, UNO_QUERY );
303 if( !mxView.is() )
304 return false;
306 #if OSL_DEBUG_LEVEL > 0
307 TimerContext aTimerContext("initWindowFromSlideShowView");
308 #endif
310 /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
311 uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
312 uno::Sequence< uno::Any > aDeviceParams;
313 ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
315 OUString aImplName;
316 aDeviceParams[ 0 ] >>= aImplName;
318 sal_Int64 aVal = 0;
319 aDeviceParams[1] >>= aVal;
321 mpContext = OpenGLContext::Create();
323 if( !mpContext->init( reinterpret_cast< vcl::Window* >( aVal ) ) ) {
324 mpContext->requestLegacyContext();
325 if( !mpContext->init( reinterpret_cast< vcl::Window* >( aVal ) ) )
326 return false;
328 SAL_INFO("slideshow", "created the context");
330 mpContext->makeCurrent();
331 CHECK_GL_ERROR();
333 awt::Rectangle aCanvasArea = mxView->getCanvasArea();
334 mpContext->setWinPosAndSize(Point(aCanvasArea.X, aCanvasArea.Y), Size(aCanvasArea.Width, aCanvasArea.Height));
335 SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea.X << "," << aCanvasArea.Y << " - " << aCanvasArea.Width << "x" << aCanvasArea.Height);
337 CHECK_GL_ERROR();
338 glEnable(GL_CULL_FACE);
339 CHECK_GL_ERROR();
340 glCullFace(GL_BACK);
341 CHECK_GL_ERROR();
342 glClearColor (0, 0, 0, 0);
343 CHECK_GL_ERROR();
344 glClear(GL_COLOR_BUFFER_BIT);
345 CHECK_GL_ERROR();
347 mpContext->swapBuffers();
349 glViewport(0, 0, aCanvasArea.Width, aCanvasArea.Height);
350 CHECK_GL_ERROR();
352 return true;
355 void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
356 const uno::Reference< rendering::XBitmap >& xEnteringSlide )
358 osl::MutexGuard const guard( m_aMutex );
360 if (isDisposed())
361 return;
363 mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
364 mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
366 maSlideSize = mxLeavingBitmap->getSize();
367 SAL_INFO("slideshow.opengl", "leaving bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height);
368 maSlideSize = mxEnteringBitmap->getSize();
369 SAL_INFO("slideshow.opengl", "entering bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height);
371 //to avoid annoying flashing under X entering and leaving slides with opengl effects set the leaving
372 //bitmap as the background pixmap of the opengl child window and the entering bitmap as the background
373 //pixmap of the non-opengl parent window. If any expose events occur around the start and end of
374 //the transition then those windows are default filled by X with the desired start/end image so there's
375 //no visible flash
376 if (SystemChildWindow* pChildWindow = mpContext->getChildWindow())
378 css::uno::Reference<css::beans::XFastPropertySet> xEnteringFastPropertySet(mxEnteringBitmap, css::uno::UNO_QUERY);
379 css::uno::Reference<css::beans::XFastPropertySet> xLeavingFastPropertySet(mxLeavingBitmap, css::uno::UNO_QUERY);
380 css::uno::Sequence<css::uno::Any> aEnteringBitmap;
381 css::uno::Sequence<css::uno::Any> aLeavingBitmap;
382 if (xEnteringFastPropertySet.get() && xLeavingFastPropertySet.get())
384 xEnteringFastPropertySet->getFastPropertyValue(1) >>= aEnteringBitmap;
385 xLeavingFastPropertySet->getFastPropertyValue(1) >>= aLeavingBitmap;
387 if (aEnteringBitmap.getLength() == 3 && aLeavingBitmap.getLength() == 3)
388 pChildWindow->SetLeaveEnterBackgrounds(aLeavingBitmap, aEnteringBitmap);
393 void OGLTransitionerImpl::impl_prepareSlides()
395 Reference< XFastPropertySet > xLeavingSet( mxLeavingBitmap , UNO_QUERY );
396 Reference< XFastPropertySet > xEnteringSet( mxEnteringBitmap , UNO_QUERY );
398 geometry::IntegerRectangle2D aSlideRect;
399 aSlideRect.X1 = 0;
400 aSlideRect.X2 = maSlideSize.Width;
401 aSlideRect.Y1 = 0;
402 aSlideRect.Y2 = maSlideSize.Height;
404 CHECK_GL_ERROR();
405 mpContext->sync();
406 CHECK_GL_ERROR();
408 maLeavingBytes = mxLeavingBitmap->getData(maSlideBitmapLayout, aSlideRect);
409 maEnteringBytes = mxEnteringBitmap->getData(maSlideBitmapLayout, aSlideRect);
411 CHECK_GL_ERROR();
412 GLInitSlides();
414 SAL_WARN_IF(maSlideBitmapLayout.PlaneStride != 0, "slideshow.opengl","only handle no plane stride now");
416 mpContext->sync();
418 CHECK_GL_ERROR();
420 // synchronized X still gives us much smoother play
421 // I suspect some issues in above code in slideshow
422 // synchronize whole transition for now
423 const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
424 mbRestoreSync = rGLWindow.Synchronize(true);
427 bool OGLTransitionerImpl::impl_prepareTransition()
429 if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
430 return mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL );
431 return false;
434 bool OGLTransitionerImpl::setTransition( const std::shared_ptr<OGLTransitionImpl>& pTransition )
436 if ( mpTransition ) // already initialized
437 return true;
439 mpTransition = pTransition;
441 mpContext->makeCurrent();
442 CHECK_GL_ERROR();
444 bool succeeded = impl_prepareTransition();
445 if (!succeeded) {
446 mpTransition = nullptr;
447 return false;
450 impl_prepareSlides();
451 return true;
454 void OGLTransitionerImpl::createTexture( GLuint* texID,
455 bool useMipmap,
456 uno::Sequence<sal_Int8>& data,
457 const OGLFormat* pFormat )
459 CHECK_GL_ERROR();
460 glDeleteTextures( 1, texID );
461 glGenTextures( 1, texID );
462 glBindTexture( GL_TEXTURE_2D, *texID );
463 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
464 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
465 CHECK_GL_ERROR();
467 impl_createTexture( useMipmap, data, pFormat );
469 SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL");
470 CHECK_GL_ERROR();
473 namespace
475 class OGLColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace >
477 private:
478 uno::Sequence< sal_Int8 > maComponentTags;
479 uno::Sequence< sal_Int32 > maBitCounts;
481 virtual sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException, std::exception) override
483 return rendering::ColorSpaceType::RGB;
485 virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException, std::exception) override
487 return maComponentTags;
489 virtual sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException, std::exception) override
491 return rendering::RenderingIntent::PERCEPTUAL;
493 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException, std::exception) override
495 return uno::Sequence< beans::PropertyValue >();
497 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
498 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
499 uno::RuntimeException, std::exception) override
501 // TODO(P3): if we know anything about target
502 // colorspace, this can be greatly sped up
503 uno::Sequence<rendering::ARGBColor> aIntermediate(
504 convertToARGB(deviceColor));
505 return targetColorSpace->convertFromARGB(aIntermediate);
507 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
509 const double* pIn( deviceColor.getConstArray() );
510 const std::size_t nLen( deviceColor.getLength() );
511 ENSURE_ARG_OR_THROW2(nLen%4==0,
512 "number of channels no multiple of 4",
513 static_cast<rendering::XColorSpace*>(this), 0);
515 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
516 rendering::RGBColor* pOut( aRes.getArray() );
517 for( std::size_t i=0; i<nLen; i+=4 )
519 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
520 pIn += 4;
522 return aRes;
524 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
526 const double* pIn( deviceColor.getConstArray() );
527 const std::size_t nLen( deviceColor.getLength() );
528 ENSURE_ARG_OR_THROW2(nLen%4==0,
529 "number of channels no multiple of 4",
530 static_cast<rendering::XColorSpace*>(this), 0);
532 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
533 rendering::ARGBColor* pOut( aRes.getArray() );
534 for( std::size_t i=0; i<nLen; i+=4 )
536 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
537 pIn += 4;
539 return aRes;
541 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
543 const double* pIn( deviceColor.getConstArray() );
544 const std::size_t nLen( deviceColor.getLength() );
545 ENSURE_ARG_OR_THROW2(nLen%4==0,
546 "number of channels no multiple of 4",
547 static_cast<rendering::XColorSpace*>(this), 0);
549 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
550 rendering::ARGBColor* pOut( aRes.getArray() );
551 for( std::size_t i=0; i<nLen; i+=4 )
553 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
554 pIn += 4;
556 return aRes;
558 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
560 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
561 const std::size_t nLen( rgbColor.getLength() );
563 uno::Sequence< double > aRes(nLen*4);
564 double* pColors=aRes.getArray();
565 for( std::size_t i=0; i<nLen; ++i )
567 *pColors++ = pIn->Red;
568 *pColors++ = pIn->Green;
569 *pColors++ = pIn->Blue;
570 *pColors++ = 1.0;
571 ++pIn;
573 return aRes;
575 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
577 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
578 const std::size_t nLen( rgbColor.getLength() );
580 uno::Sequence< double > aRes(nLen*4);
581 double* pColors=aRes.getArray();
582 for( std::size_t i=0; i<nLen; ++i )
584 *pColors++ = pIn->Red;
585 *pColors++ = pIn->Green;
586 *pColors++ = pIn->Blue;
587 *pColors++ = pIn->Alpha;
588 ++pIn;
590 return aRes;
592 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
594 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
595 const std::size_t nLen( rgbColor.getLength() );
597 uno::Sequence< double > aRes(nLen*4);
598 double* pColors=aRes.getArray();
599 for( std::size_t i=0; i<nLen; ++i )
601 *pColors++ = pIn->Red/pIn->Alpha;
602 *pColors++ = pIn->Green/pIn->Alpha;
603 *pColors++ = pIn->Blue/pIn->Alpha;
604 *pColors++ = pIn->Alpha;
605 ++pIn;
607 return aRes;
610 // XIntegerBitmapColorSpace
611 virtual sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException, std::exception) override
613 return 32;
615 virtual uno::Sequence< sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException, std::exception) override
617 return maBitCounts;
619 virtual sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException, std::exception) override
621 return util::Endianness::LITTLE;
623 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor,
624 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
625 uno::RuntimeException, std::exception) override
627 if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
629 const sal_Int8* pIn( deviceColor.getConstArray() );
630 const std::size_t nLen( deviceColor.getLength() );
631 ENSURE_ARG_OR_THROW2(nLen%4==0,
632 "number of channels no multiple of 4",
633 static_cast<rendering::XColorSpace*>(this), 0);
635 uno::Sequence<double> aRes(nLen);
636 double* pOut( aRes.getArray() );
637 for( std::size_t i=0; i<nLen; i+=4 )
639 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
640 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
641 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
642 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
644 return aRes;
646 else
648 // TODO(P3): if we know anything about target
649 // colorspace, this can be greatly sped up
650 uno::Sequence<rendering::ARGBColor> aIntermediate(
651 convertIntegerToARGB(deviceColor));
652 return targetColorSpace->convertFromARGB(aIntermediate);
655 virtual uno::Sequence< sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor,
656 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
657 uno::RuntimeException, std::exception) override
659 if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
661 // it's us, so simply pass-through the data
662 return deviceColor;
664 else
666 // TODO(P3): if we know anything about target
667 // colorspace, this can be greatly sped up
668 uno::Sequence<rendering::ARGBColor> aIntermediate(
669 convertIntegerToARGB(deviceColor));
670 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
673 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
675 const sal_Int8* pIn( deviceColor.getConstArray() );
676 const std::size_t nLen( deviceColor.getLength() );
677 ENSURE_ARG_OR_THROW2(nLen%4==0,
678 "number of channels no multiple of 4",
679 static_cast<rendering::XColorSpace*>(this), 0);
681 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
682 rendering::RGBColor* pOut( aRes.getArray() );
683 for( std::size_t i=0; i<nLen; i+=4 )
685 *pOut++ = rendering::RGBColor(
686 vcl::unotools::toDoubleColor(pIn[0]),
687 vcl::unotools::toDoubleColor(pIn[1]),
688 vcl::unotools::toDoubleColor(pIn[2]));
689 pIn += 4;
691 return aRes;
694 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
696 const sal_Int8* pIn( deviceColor.getConstArray() );
697 const std::size_t nLen( deviceColor.getLength() );
698 ENSURE_ARG_OR_THROW2(nLen%4==0,
699 "number of channels no multiple of 4",
700 static_cast<rendering::XColorSpace*>(this), 0);
702 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
703 rendering::ARGBColor* pOut( aRes.getArray() );
704 for( std::size_t i=0; i<nLen; i+=4 )
706 *pOut++ = rendering::ARGBColor(
707 vcl::unotools::toDoubleColor(pIn[3]),
708 vcl::unotools::toDoubleColor(pIn[0]),
709 vcl::unotools::toDoubleColor(pIn[1]),
710 vcl::unotools::toDoubleColor(pIn[2]));
711 pIn += 4;
713 return aRes;
716 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
718 const sal_Int8* pIn( deviceColor.getConstArray() );
719 const std::size_t nLen( deviceColor.getLength() );
720 ENSURE_ARG_OR_THROW2(nLen%4==0,
721 "number of channels no multiple of 4",
722 static_cast<rendering::XColorSpace*>(this), 0);
724 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
725 rendering::ARGBColor* pOut( aRes.getArray() );
726 for( std::size_t i=0; i<nLen; i+=4 )
728 const sal_Int8 nAlpha( pIn[3] );
729 *pOut++ = rendering::ARGBColor(
730 vcl::unotools::toDoubleColor(nAlpha),
731 vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
732 vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
733 vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
734 pIn += 4;
736 return aRes;
739 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
741 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
742 const std::size_t nLen( rgbColor.getLength() );
744 uno::Sequence< sal_Int8 > aRes(nLen*4);
745 sal_Int8* pColors=aRes.getArray();
746 for( std::size_t i=0; i<nLen; ++i )
748 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
749 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
750 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
751 *pColors++ = -1;
752 ++pIn;
754 return aRes;
757 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
759 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
760 const std::size_t nLen( rgbColor.getLength() );
762 uno::Sequence< sal_Int8 > aRes(nLen*4);
763 sal_Int8* pColors=aRes.getArray();
764 for( std::size_t i=0; i<nLen; ++i )
766 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
767 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
768 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
769 *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
770 ++pIn;
772 return aRes;
775 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) override
777 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
778 const std::size_t nLen( rgbColor.getLength() );
780 uno::Sequence< sal_Int8 > aRes(nLen*4);
781 sal_Int8* pColors=aRes.getArray();
782 for( std::size_t i=0; i<nLen; ++i )
784 *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
785 *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
786 *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
787 *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
788 ++pIn;
790 return aRes;
793 public:
794 OGLColorSpace() :
795 maComponentTags(4),
796 maBitCounts(4)
798 sal_Int8* pTags = maComponentTags.getArray();
799 sal_Int32* pBitCounts = maBitCounts.getArray();
800 pTags[0] = rendering::ColorComponentTag::RGB_RED;
801 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
802 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
803 pTags[3] = rendering::ColorComponentTag::ALPHA;
805 pBitCounts[0] =
806 pBitCounts[1] =
807 pBitCounts[2] =
808 pBitCounts[3] = 8;
812 struct OGLColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>, OGLColorSpaceHolder>
814 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
816 return new OGLColorSpace();
820 uno::Reference<rendering::XIntegerBitmapColorSpace>
821 getOGLColorSpace()
823 return OGLColorSpaceHolder::get();
827 namespace {
829 void buildMipmaps(
830 GLint internalFormat, GLsizei width, GLsizei height, GLenum format,
831 GLenum type, const void * data)
833 if (GLEW_ARB_framebuffer_object) {
834 glTexImage2D(
835 GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type,
836 data);
837 glGenerateMipmap(GL_TEXTURE_2D);
838 } else {
839 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
840 glTexImage2D(
841 GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type,
842 data);
843 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
846 glTexParameteri(
847 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
852 void OGLTransitionerImpl::impl_createTexture(
853 bool useMipmap,
854 uno::Sequence<sal_Int8>& data,
855 const OGLFormat* pFormat )
857 if( !pFormat )
859 CHECK_GL_ERROR();
860 // force-convert color to ARGB8888 int color space
861 uno::Sequence<sal_Int8> tempBytes(
862 maSlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
863 data,
864 getOGLColorSpace()));
865 buildMipmaps( GL_RGBA,
866 maSlideSize.Width,
867 maSlideSize.Height,
868 GL_RGBA,
869 GL_UNSIGNED_BYTE,
870 &tempBytes[0]);
872 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
873 GLfloat largest_supported_anisotropy;
874 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
875 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
876 } else {
877 if( mpTransition && !mbBrokenTexturesATI && !useMipmap) {
878 glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
879 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
880 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
881 } else {
882 buildMipmaps( pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
884 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
885 GLfloat largest_supported_anisotropy;
886 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
887 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
890 CHECK_GL_ERROR();
893 const OGLFormat* OGLTransitionerImpl::chooseFormats()
895 const OGLFormat* pDetectedFormat=nullptr;
896 uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
897 maSlideBitmapLayout.ColorSpace);
899 if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
900 xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) )
902 /* table for canvas->OGL format mapping. outer index is number
903 of color components (0:3, 1:4), then comes bits per pixel
904 (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
905 2:argb, 3:abgr)
907 static const OGLFormat lcl_RGB24[] =
909 // 24 bit RGB
910 {3, GL_BGR, GL_UNSIGNED_BYTE},
911 {3, GL_RGB, GL_UNSIGNED_BYTE},
912 {3, GL_BGR, GL_UNSIGNED_BYTE},
913 {3, GL_RGB, GL_UNSIGNED_BYTE}
916 #if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
917 // more format constants available
918 static const OGLFormat lcl_RGB16[] =
920 // 16 bit RGB
921 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
922 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
923 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
924 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
927 static const OGLFormat lcl_ARGB16_4[] =
929 // 16 bit ARGB
930 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
931 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
932 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
933 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
936 static const OGLFormat lcl_ARGB16_5[] =
938 // 16 bit ARGB
939 {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
940 {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
941 {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
942 {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
945 static const OGLFormat lcl_ARGB32[] =
947 // 32 bit ARGB
948 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
949 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
950 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
951 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
954 const uno::Sequence<sal_Int8> aComponentTags(
955 xIntColorSpace->getComponentTags());
956 const uno::Sequence<sal_Int32> aComponentBitcounts(
957 xIntColorSpace->getComponentBitCounts());
958 const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
959 const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
961 // supported component ordering?
962 const int nComponentOrderIndex(
963 calcComponentOrderIndex(aComponentTags));
964 if( nComponentOrderIndex != -1 )
966 switch( nBitsPerPixel )
968 case 16:
969 if( nNumComponents == 3 )
971 pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
973 else if( nNumComponents == 4 )
975 if( aComponentBitcounts[1] == 4 )
977 pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
979 else if( aComponentBitcounts[1] == 5 )
981 pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
984 break;
985 case 24:
986 if( nNumComponents == 3 )
988 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
990 break;
991 case 32:
992 if ( nNumComponents == 4 )
994 pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
996 break;
999 #else
1000 const uno::Sequence<sal_Int8> aComponentTags(
1001 xIntColorSpace->getComponentTags());
1002 const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
1003 if( aComponentTags.getLength() == 3 &&
1004 nComponentOrderIndex != -1 &&
1005 xIntColorSpace->getBitsPerPixel() == 24 )
1007 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
1009 #endif
1012 return pDetectedFormat;
1015 void OGLTransitionerImpl::GLInitSlides()
1017 osl::MutexGuard const guard( m_aMutex );
1019 if (isDisposed() || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
1020 return;
1022 #if OSL_DEBUG_LEVEL > 0
1023 TimerContext aTimerContext("texture creation");
1024 #endif
1026 mpContext->makeCurrent();
1028 const OGLFormat* pFormat = chooseFormats();
1030 CHECK_GL_ERROR();
1031 createTexture( &maLeavingSlideGL,
1032 mpTransition->getSettings().mbUseMipMapLeaving,
1033 maLeavingBytes,
1034 pFormat );
1036 createTexture( &maEnteringSlideGL,
1037 mpTransition->getSettings().mbUseMipMapEntering,
1038 maEnteringBytes,
1039 pFormat );
1041 CHECK_GL_ERROR();
1042 mpContext->sync();
1043 CHECK_GL_ERROR();
1046 void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException, std::exception)
1048 #if OSL_DEBUG_LEVEL > 0
1049 mnFrameCount ++;
1050 m_UpdateStartTime = std::chrono::steady_clock::now();
1051 if( mnFrameCount == 1 ) {
1052 m_StartTime = m_UpdateStartTime;
1053 m_TotalUpdateDuration = std::chrono::seconds(0);
1055 #endif
1056 osl::MutexGuard const guard( m_aMutex );
1058 if (isDisposed() || !mbValidOpenGLContext || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
1059 return;
1061 mpContext->makeCurrent();
1062 CHECK_GL_ERROR();
1064 glEnable(GL_DEPTH_TEST);
1065 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1066 CHECK_GL_ERROR();
1068 const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
1069 mpTransition->display( nTime, maLeavingSlideGL, maEnteringSlideGL,
1070 maSlideSize.Width, maSlideSize.Height,
1071 static_cast<double>(rGLWindow.Width),
1072 static_cast<double>(rGLWindow.Height) );
1074 mpContext->swapBuffers();
1076 mpContext->show();
1077 mpContext->sync();
1078 CHECK_GL_ERROR();
1080 #if OSL_DEBUG_LEVEL > 0
1081 m_UpdateEndTime = std::chrono::steady_clock::now();
1083 SAL_INFO("slideshow.opengl", "update time: " << nTime);
1084 SAL_INFO("slideshow.opengl", "update took: " << std::chrono::duration_cast<std::chrono::milliseconds>(m_UpdateEndTime - m_UpdateStartTime).count());
1085 m_TotalUpdateDuration += (m_UpdateEndTime - m_UpdateStartTime);
1086 #endif
1089 void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
1090 const Reference< rendering::XBitmap >& rLeavingBitmap,
1091 const Reference< rendering::XBitmap >& rEnteringBitmap )
1092 throw (uno::RuntimeException, std::exception)
1094 SAL_INFO("slideshow.opengl", "transitioner: view changed");
1096 impl_dispose();
1098 initWindowFromSlideShowView( rView );
1099 setSlides( rLeavingBitmap, rEnteringBitmap );
1100 impl_prepareSlides();
1101 impl_prepareTransition();
1104 void OGLTransitionerImpl::disposeTextures()
1106 mpContext->makeCurrent();
1107 CHECK_GL_ERROR();
1109 glDeleteTextures(1,&maLeavingSlideGL);
1110 maLeavingSlideGL = 0;
1111 glDeleteTextures(1,&maEnteringSlideGL);
1112 maEnteringSlideGL = 0;
1114 CHECK_GL_ERROR();
1117 void OGLTransitionerImpl::impl_dispose()
1119 mpContext->makeCurrent();
1120 CHECK_GL_ERROR();
1122 if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
1123 mpTransition->finish();
1124 disposeTextures();
1125 if( mpContext.is() )
1126 mpContext->dispose();
1127 mpContext.clear();
1130 // we are about to be disposed (someone call dispose() on us)
1131 void OGLTransitionerImpl::disposing()
1133 osl::MutexGuard const guard( m_aMutex );
1135 #if OSL_DEBUG_LEVEL > 0
1136 SAL_INFO("slideshow.opengl", "dispose " << this);
1137 if( mnFrameCount ) {
1138 m_EndTime = std::chrono::steady_clock::now();
1139 auto const duration = m_EndTime - m_StartTime;
1140 SAL_INFO("slideshow.opengl",
1141 "whole transition (frames: " << mnFrameCount
1142 << ") took: " << std::chrono::duration_cast<std::chrono::microseconds>(duration).count()
1143 << " fps: "
1144 << (((double)mnFrameCount*1000000000.0)/std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count())
1145 << " time spent in updates: " << std::chrono::duration_cast<std::chrono::microseconds>(m_TotalUpdateDuration).count()
1146 << " percentage of transition time: "
1147 << (100*(((double)std::chrono::duration_cast<std::chrono::nanoseconds>(m_TotalUpdateDuration).count())/((double)std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count())))
1148 << '%'
1151 #endif
1153 if (mbRestoreSync && bool(mpContext.is())) {
1154 // try to reestablish synchronize state
1155 const char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
1156 mpContext->getOpenGLWindow().Synchronize(sal_synchronize && *sal_synchronize == '1' );
1159 impl_dispose();
1161 mpTransition.reset();
1163 mxLeavingBitmap.clear();
1164 mxEnteringBitmap.clear();
1165 mxView.clear();
1168 OGLTransitionerImpl::OGLTransitionerImpl()
1169 : OGLTransitionerImplBase(m_aMutex)
1170 , mpContext()
1171 , maLeavingSlideGL(0)
1172 , maEnteringSlideGL(0)
1173 , mxView()
1174 , maEnteringBytes()
1175 , maLeavingBytes()
1176 , mbRestoreSync(false)
1177 , maSlideBitmapLayout()
1178 , maSlideSize()
1179 , mbBrokenTexturesATI(false)
1180 , mnGLVersion(0)
1181 , mbValidOpenGLContext(false)
1182 #if OSL_DEBUG_LEVEL > 0
1183 , mnFrameCount(0)
1184 #endif
1188 typedef cppu::WeakComponentImplHelper<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
1190 class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
1192 public:
1193 explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) :
1194 OGLTransitionFactoryImplBase(m_aMutex)
1197 // XTransitionFactory
1198 virtual sal_Bool SAL_CALL hasTransition( sal_Int16 transitionType, sal_Int16 transitionSubType ) throw (uno::RuntimeException, std::exception) override
1200 // A set of css::animation::TransitionSubType that don't have any meaning (in the SMIL 2.0
1201 // standard) for MISCSHAPEWIPE have been chosen to refer to some of these "fancy" optional
1202 // transitions. (The only subtypes of 'miscShapeWipe' defined in the standard are 'heart'
1203 // and 'keyhole'.) The set of subtypes used seems to be a bit random; it starts from the
1204 // beginning of the list (in the order (numeric) in our TransitionSubType set of constants)
1205 // but then jumps a bit randomly. The numeric values as such have no meaning, but still.
1207 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1208 switch( transitionSubType )
1210 case animations::TransitionSubType::LEFTTORIGHT: // 1
1211 case animations::TransitionSubType::TOPTOBOTTOM: // 2
1212 case animations::TransitionSubType::TOPLEFT: // 3
1213 case animations::TransitionSubType::TOPRIGHT: // 4
1214 case animations::TransitionSubType::BOTTOMRIGHT: // 5
1215 case animations::TransitionSubType::BOTTOMLEFT: // 6
1216 case animations::TransitionSubType::TOPCENTER: // 7
1217 case animations::TransitionSubType::RIGHTCENTER: // 8
1218 case animations::TransitionSubType::BOTTOMCENTER: // 9
1219 case animations::TransitionSubType::CORNERSIN: // 11
1220 case animations::TransitionSubType::CORNERSOUT: // 12
1221 case animations::TransitionSubType::VERTICAL: // 13
1222 case animations::TransitionSubType::HORIZONTAL: // 14
1223 case animations::TransitionSubType::DIAMOND: // 26
1224 case animations::TransitionSubType::CIRCLE: // 27
1225 case animations::TransitionSubType::HEART: // 31
1226 case animations::TransitionSubType::FANOUTHORIZONTAL: // 55
1227 case animations::TransitionSubType::ACROSS: // 108
1228 return true;
1230 default:
1231 return false;
1233 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1234 return true;
1235 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1236 return true;
1237 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1238 return true;
1239 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1240 return true;
1241 } else
1242 return false;
1245 virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
1246 sal_Int16 transitionType,
1247 sal_Int16 transitionSubType,
1248 const uno::Reference< presentation::XSlideShowView >& view,
1249 const uno::Reference< rendering::XBitmap >& leavingBitmap,
1250 const uno::Reference< rendering::XBitmap >& enteringBitmap )
1251 throw (uno::RuntimeException, std::exception) override
1253 if( !hasTransition( transitionType, transitionSubType ) )
1254 return uno::Reference< presentation::XTransition >();
1256 rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() );
1257 if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) )
1258 return uno::Reference< presentation::XTransition >();
1260 std::shared_ptr<OGLTransitionImpl> pTransition;
1262 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1263 switch( transitionSubType )
1265 case animations::TransitionSubType::LEFTTORIGHT:
1266 pTransition = makeFallLeaving();
1267 break;
1268 case animations::TransitionSubType::TOPTOBOTTOM:
1269 pTransition = makeTurnAround();
1270 break;
1271 case animations::TransitionSubType::TOPLEFT:
1272 pTransition = makeIris();
1273 break;
1274 case animations::TransitionSubType::TOPRIGHT:
1275 pTransition = makeTurnDown();
1276 break;
1277 case animations::TransitionSubType::BOTTOMRIGHT:
1278 pTransition = makeRochade();
1279 break;
1280 case animations::TransitionSubType::BOTTOMLEFT:
1281 pTransition = makeVenetianBlinds( true, 8 );
1282 break;
1283 case animations::TransitionSubType::TOPCENTER:
1284 pTransition = makeVenetianBlinds( false, 6 );
1285 break;
1286 case animations::TransitionSubType::RIGHTCENTER:
1287 pTransition = makeStatic();
1288 break;
1289 case animations::TransitionSubType::BOTTOMCENTER:
1290 pTransition = makeDissolve();
1291 break;
1292 case animations::TransitionSubType::CORNERSIN:
1293 pTransition = makeInsideCubeFaceToLeft();
1294 break;
1295 case animations::TransitionSubType::CORNERSOUT:
1296 pTransition = makeOutsideCubeFaceToLeft();
1297 break;
1298 case animations::TransitionSubType::VERTICAL:
1299 pTransition = makeVortex();
1300 break;
1301 case animations::TransitionSubType::HORIZONTAL:
1302 pTransition = makeRipple();
1303 break;
1304 case animations::TransitionSubType::CIRCLE:
1305 pTransition = makeRevolvingCircles(8,128);
1306 break;
1307 case animations::TransitionSubType::FANOUTHORIZONTAL:
1308 pTransition = makeHelix(20);
1309 break;
1310 case animations::TransitionSubType::ACROSS:
1311 pTransition = makeNByMTileFlip(8,6);
1312 break;
1313 case animations::TransitionSubType::DIAMOND:
1314 pTransition = makeGlitter();
1315 break;
1316 case animations::TransitionSubType::HEART:
1317 pTransition = makeHoneycomb();
1318 break;
1320 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1321 pTransition = makeFadeSmoothly();
1322 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1323 pTransition = makeFadeThroughBlack();
1324 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1325 pTransition = makeDiamond();
1326 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1327 pTransition = makeNewsflash();
1330 if ( !pTransition || !xRes->setTransition(pTransition) )
1331 return uno::Reference< presentation::XTransition >();
1333 return uno::Reference<presentation::XTransition>(xRes.get());
1339 namespace sdecl = comphelper::service_decl;
1340 const sdecl::ServiceDecl OGLTransitionFactoryDecl(
1341 sdecl::class_<OGLTransitionFactoryImpl>(),
1342 "com.sun.star.comp.presentation.OGLTransitionFactory",
1343 "com.sun.star.presentation.TransitionFactory" );
1345 // The C shared lib entry points
1346 extern "C"
1347 SAL_DLLPUBLIC_EXPORT void* SAL_CALL ogltrans_component_getFactory( sal_Char const* pImplName,
1348 void*, void* )
1350 return sdecl::component_getFactoryHelper( pImplName, {&OGLTransitionFactoryDecl} );
1353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */