LibreOffice Module slideshow (master) 1
TransitionerImpl.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * Copyright 2008 by Sun Microsystems, Inc.
7 *
8 * OpenOffice.org - a multi-platform office productivity suite
9 *
10 * This file is part of OpenOffice.org.
11 *
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.
15 *
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).
21 *
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.
26 *
27 ************************************************************************/
28
29#include <sal/types.h>
30
31#include <memory>
32
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>
50
54#include <rtl/ref.hxx>
55#include <sal/log.hxx>
56
58
60
61#include <utility>
62#include <vcl/canvastools.hxx>
65#include <vcl/syschild.hxx>
66#include <vcl/window.hxx>
67
68#include "TransitionImpl.hxx"
69
70#if OSL_DEBUG_LEVEL > 0
71#include <chrono>
72#endif
73
74using namespace ::com::sun::star;
75using ::com::sun::star::beans::XFastPropertySet;
76using ::com::sun::star::uno::Any;
77using ::com::sun::star::uno::Reference;
78using ::com::sun::star::uno::Sequence;
79using ::com::sun::star::uno::UNO_QUERY;
80using ::com::sun::star::uno::UNO_QUERY_THROW;
81
82namespace
83{
84
85typedef cppu::WeakComponentImplHelper<presentation::XTransition> OGLTransitionerImplBase;
86
87#if OSL_DEBUG_LEVEL > 0
88class TimerContext
89{
90public:
91 explicit TimerContext(OUString aWhat)
92 : m_aWhat(std::move(aWhat))
93 , m_StartTime(std::chrono::steady_clock::now())
94 {
95 }
96 ~TimerContext()
97 {
98 auto const aDuration(std::chrono::steady_clock::now() - m_StartTime);
99 SAL_INFO("slideshow.opengl", m_aWhat << " took: " << std::chrono::duration_cast<std::chrono::microseconds>(aDuration).count());
100 }
101private:
102 OUString const m_aWhat;
103 std::chrono::steady_clock::time_point const m_StartTime;
104};
105#endif
106
107struct OGLFormat
108{
109 GLint nInternalFormat;
110 GLenum eFormat;
111 GLenum eType;
112};
113
114/* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
115 */
116int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
117{
118 using namespace rendering::ColorComponentTag;
119
120 static const sal_Int8 aOrderTable[] =
121 {
122 RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
123 RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
124 ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
125 ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
126 };
127
128 const sal_Int32 nNumComps(rTags.getLength());
129 const sal_Int8* pLine=aOrderTable;
130 for(int i=0; i<4; ++i)
131 {
132 int j=0;
133 while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
134 ++j;
135
136 // all of the line passed, this is a match!
137 if( j==nNumComps )
138 return i;
139
140 pLine+=4;
141 }
142
143 return -1;
144}
145
150class OGLTransitionerImpl : private cppu::BaseMutex, public OGLTransitionerImplBase
151{
152public:
153 OGLTransitionerImpl();
154 OGLTransitionerImpl(const OGLTransitionerImpl&) = delete;
155 OGLTransitionerImpl& operator=(const OGLTransitionerImpl&) = delete;
156 bool setTransition( const std::shared_ptr<OGLTransitionImpl>& pOGLTransition );
157 bool initialize( const Reference< presentation::XSlideShowView >& xView,
158 const Reference< rendering::XBitmap >& xLeavingSlide,
159 const Reference< rendering::XBitmap >& xEnteringSlide );
160
161 // XTransition
162 virtual void SAL_CALL update( double nTime ) override;
163 virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
164 const Reference< rendering::XBitmap >& rLeavingBitmap,
165 const Reference< rendering::XBitmap >& rEnteringBitmap ) override;
166
167protected:
168 void disposeTextures();
169
170 // WeakComponentImplHelperBase
171 virtual void SAL_CALL disposing() override;
172
173 bool isDisposed() const
174 {
175 return (rBHelper.bDisposed || rBHelper.bInDispose);
176 }
177
178 void createTexture( GLuint* texID,
179 bool useMipmap,
180 const uno::Sequence<sal_Int8>& data,
181 const OGLFormat* pFormat );
182 const OGLFormat* chooseFormats();
183
184private:
185 void impl_initializeFlags( bool const bGLXPresent );
186
187 void impl_dispose();
188
189 void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
190 void impl_prepareSlides();
191
192 void impl_createTexture( bool useMipmap, const uno::Sequence<sal_Int8>& data, const OGLFormat* pFormat );
193
194 bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
197 void GLInitSlides();
198
199 bool impl_prepareTransition();
200
201private:
203
206 GLuint maLeavingSlideGL;
209 GLuint maEnteringSlideGL;
210
211 Reference< presentation::XSlideShowView > mxView;
212 Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
213 Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
214
217 uno::Sequence<sal_Int8> maEnteringBytes;
218
221 uno::Sequence<sal_Int8> maLeavingBytes;
222
223 bool mbRestoreSync;
224
227 rendering::IntegerBitmapLayout maSlideBitmapLayout;
228
231 geometry::IntegerSize2D maSlideSize;
232
235 std::shared_ptr<OGLTransitionImpl> mpTransition;
236
237public:
240 bool mbBrokenTexturesATI;
241
244 float mnGLVersion;
245
249 bool mbValidOpenGLContext;
250
251#if OSL_DEBUG_LEVEL > 0
252 std::chrono::steady_clock::time_point m_UpdateStartTime;
253 std::chrono::steady_clock::time_point m_UpdateEndTime;
254 std::chrono::steady_clock::time_point m_StartTime;
255 std::chrono::steady_clock::time_point m_EndTime;
256 std::chrono::steady_clock::duration m_TotalUpdateDuration;
257 int mnFrameCount;
258#endif
259};
260
261bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView,
262 const Reference< rendering::XBitmap >& xLeavingSlide,
263 const Reference< rendering::XBitmap >& xEnteringSlide )
264{
265 bool const bValidContext( initWindowFromSlideShowView( xView ) );
266 impl_initializeFlags( bValidContext );
267
268 setSlides( xLeavingSlide, xEnteringSlide );
269
270 return mbValidOpenGLContext;
271}
272
273void OGLTransitionerImpl::impl_initializeFlags( bool const bValidContext )
274{
275 mbValidOpenGLContext = bValidContext;
276 if ( bValidContext ) {
278
279 mnGLVersion = OpenGLHelper::getGLVersion();
280 SAL_INFO("slideshow.opengl", "GL version: " << mnGLVersion << "" );
281
282#if defined( UNX ) && !defined( MACOSX )
283 const GLubyte* vendor = glGetString( GL_VENDOR );
284 /* TODO: check for version once the bug in fglrx driver is fixed */
285 mbBrokenTexturesATI = (vendor && strcmp( reinterpret_cast<const char *>(vendor), "ATI Technologies Inc." ) == 0 );
286#endif
287
289 }
290}
291
292bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
293{
294 osl::MutexGuard const guard( m_aMutex );
295
296 if (isDisposed())
297 return false;
298
299 mxView = xView;
300 if( !mxView.is() )
301 return false;
302
303#if OSL_DEBUG_LEVEL > 0
304 TimerContext aTimerContext("initWindowFromSlideShowView");
305#endif
306
308 uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
309 uno::Sequence< uno::Any > aDeviceParams;
310 ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
311
312 OUString aImplName;
313 aDeviceParams[ 0 ] >>= aImplName;
314
315 sal_Int64 aVal = 0;
316 aDeviceParams[1] >>= aVal;
317
319
320 OutputDevice* pDevice = reinterpret_cast<OutputDevice*>(aVal);
321 vcl::Window* pWindow = pDevice ? pDevice->GetOwnerWindow() : nullptr;
322
323 if( !mpContext->init( pWindow) ) {
324 mpContext->requestLegacyContext();
325 if( !mpContext->init( pWindow ) )
326 return false;
327 }
328 SAL_INFO("slideshow.opengl", "created the context");
329
330 mpContext->makeCurrent();
332
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);
336
338 glEnable(GL_CULL_FACE);
340 glCullFace(GL_BACK);
342 glClearColor (0, 0, 0, 0);
344 glClear(GL_COLOR_BUFFER_BIT);
346
347 mpContext->swapBuffers();
348
350
351 return true;
352}
353
354void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
355 const uno::Reference< rendering::XBitmap >& xEnteringSlide )
356{
357 osl::MutexGuard const guard( m_aMutex );
358
359 if (isDisposed())
360 return;
361
362 mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
363 mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
364
365 maSlideSize = mxLeavingBitmap->getSize();
366 SAL_INFO("slideshow.opengl", "leaving bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height);
367 maSlideSize = mxEnteringBitmap->getSize();
368 SAL_INFO("slideshow.opengl", "entering bitmap area: " << maSlideSize.Width << "x" << maSlideSize.Height);
369
370 //to avoid annoying flashing under X entering and leaving slides with opengl effects set the leaving
371 //bitmap as the background pixmap of the opengl child window and the entering bitmap as the background
372 //pixmap of the non-opengl parent window. If any expose events occur around the start and end of
373 //the transition then those windows are default filled by X with the desired start/end image so there's
374 //no visible flash
375 SystemChildWindow* pChildWindow = mpContext->getChildWindow();
376 if (!pChildWindow)
377 return;
378
379 css::uno::Reference<css::beans::XFastPropertySet> xEnteringFastPropertySet(mxEnteringBitmap, css::uno::UNO_QUERY);
380 css::uno::Reference<css::beans::XFastPropertySet> xLeavingFastPropertySet(mxLeavingBitmap, css::uno::UNO_QUERY);
381 css::uno::Sequence<css::uno::Any> aEnteringBitmap;
382 css::uno::Sequence<css::uno::Any> aLeavingBitmap;
383 if (xEnteringFastPropertySet && xLeavingFastPropertySet)
384 {
385 xEnteringFastPropertySet->getFastPropertyValue(1) >>= aEnteringBitmap;
386 xLeavingFastPropertySet->getFastPropertyValue(1) >>= aLeavingBitmap;
387 }
388 if (aEnteringBitmap.getLength() == 2 && aLeavingBitmap.getLength() == 2)
389 pChildWindow->SetLeaveEnterBackgrounds(aLeavingBitmap, aEnteringBitmap);
390}
391
392
393void OGLTransitionerImpl::impl_prepareSlides()
394{
395 geometry::IntegerRectangle2D aSlideRect;
396 aSlideRect.X1 = 0;
397 aSlideRect.X2 = maSlideSize.Width;
398 aSlideRect.Y1 = 0;
399 aSlideRect.Y2 = maSlideSize.Height;
400
402 mpContext->sync();
404
405 maLeavingBytes = mxLeavingBitmap->getData(maSlideBitmapLayout, aSlideRect);
406 maEnteringBytes = mxEnteringBitmap->getData(maSlideBitmapLayout, aSlideRect);
407
409 GLInitSlides();
410
411 SAL_WARN_IF(maSlideBitmapLayout.PlaneStride != 0, "slideshow.opengl","only handle no plane stride now");
412
413 mpContext->sync();
414
416
417 // synchronized X still gives us much smoother play
418 // I suspect some issues in above code in slideshow
419 // synchronize whole transition for now
420 const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
421 mbRestoreSync = rGLWindow.Synchronize(true);
422}
423
424bool OGLTransitionerImpl::impl_prepareTransition()
425{
426 if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
427 return mpTransition->prepare( maLeavingSlideGL, maEnteringSlideGL, mpContext.get() );
428 return false;
429}
430
431bool OGLTransitionerImpl::setTransition( const std::shared_ptr<OGLTransitionImpl>& pTransition )
432{
433 if ( mpTransition ) // already initialized
434 return true;
435
436 mpTransition = pTransition;
437
438 mpContext->makeCurrent();
440
441 bool succeeded = impl_prepareTransition();
442 if (!succeeded) {
443 mpTransition = nullptr;
444 return false;
445 }
446
447 impl_prepareSlides();
448
449 // tdf#91456: When the OpenGL context is initialized but nothing has been rendered on it
450 // it can happen, that an "empty" screen is drawn. Therefore, drawing the content of time 0
451 // onto the context
452 update(0);
453
454 return true;
455}
456
457void OGLTransitionerImpl::createTexture( GLuint* texID,
458 bool useMipmap,
459 const uno::Sequence<sal_Int8>& data,
460 const OGLFormat* pFormat )
461{
463 glDeleteTextures( 1, texID );
464 glGenTextures( 1, texID );
465 glBindTexture( GL_TEXTURE_2D, *texID );
466 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
467 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
469
470 impl_createTexture( useMipmap, data, pFormat );
471
472 SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL");
474}
475
476class OGLColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace >
477{
478private:
479 uno::Sequence< sal_Int8 > maComponentTags;
480 uno::Sequence< sal_Int32 > maBitCounts;
481
482 virtual sal_Int8 SAL_CALL getType( ) override
483 {
484 return rendering::ColorSpaceType::RGB;
485 }
486 virtual uno::Sequence< sal_Int8 > SAL_CALL getComponentTags( ) override
487 {
488 return maComponentTags;
489 }
490 virtual sal_Int8 SAL_CALL getRenderingIntent( ) override
491 {
492 return rendering::RenderingIntent::PERCEPTUAL;
493 }
494 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) override
495 {
496 return uno::Sequence< beans::PropertyValue >();
497 }
498 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
499 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
500 {
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);
506 }
507 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) override
508 {
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);
514
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 )
518 {
519 *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
520 pIn += 4;
521 }
522 return aRes;
523 }
524 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) override
525 {
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);
531
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 )
535 {
536 *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
537 pIn += 4;
538 }
539 return aRes;
540 }
541 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) override
542 {
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);
548
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 )
552 {
553 *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
554 pIn += 4;
555 }
556 return aRes;
557 }
558 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
559 {
560 const sal_Int32 nLen( rgbColor.getLength() );
561
562 uno::Sequence< double > aRes(nLen*4);
563 double* pColors=aRes.getArray();
564 for( const rendering::RGBColor& rIn : rgbColor )
565 {
566 *pColors++ = rIn.Red;
567 *pColors++ = rIn.Green;
568 *pColors++ = rIn.Blue;
569 *pColors++ = 1.0;
570 }
571 return aRes;
572 }
573 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
574 {
575 const sal_Int32 nLen( rgbColor.getLength() );
576
577 uno::Sequence< double > aRes(nLen*4);
578 double* pColors=aRes.getArray();
579 for( const rendering::ARGBColor& rIn : rgbColor )
580 {
581 *pColors++ = rIn.Red;
582 *pColors++ = rIn.Green;
583 *pColors++ = rIn.Blue;
584 *pColors++ = rIn.Alpha;
585 }
586 return aRes;
587 }
588 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
589 {
590 const sal_Int32 nLen( rgbColor.getLength() );
591
592 uno::Sequence< double > aRes(nLen*4);
593 double* pColors=aRes.getArray();
594 for( const rendering::ARGBColor& rIn : rgbColor )
595 {
596 *pColors++ = rIn.Red/rIn.Alpha;
597 *pColors++ = rIn.Green/rIn.Alpha;
598 *pColors++ = rIn.Blue/rIn.Alpha;
599 *pColors++ = rIn.Alpha;
600 }
601 return aRes;
602 }
603
604 // XIntegerBitmapColorSpace
605 virtual sal_Int32 SAL_CALL getBitsPerPixel( ) override
606 {
607 return 32;
608 }
609 virtual uno::Sequence< sal_Int32 > SAL_CALL getComponentBitCounts( ) override
610 {
611 return maBitCounts;
612 }
613 virtual sal_Int8 SAL_CALL getEndianness( ) override
614 {
615 return util::Endianness::LITTLE;
616 }
617 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor,
618 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
619 {
620 if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
621 {
622 const sal_Int32 nLen( deviceColor.getLength() );
623 ENSURE_ARG_OR_THROW2(nLen%4==0,
624 "number of channels no multiple of 4",
625 static_cast<rendering::XColorSpace*>(this), 0);
626
627 uno::Sequence<double> aRes(nLen);
628 std::transform(deviceColor.begin(), deviceColor.end(), aRes.getArray(),
630 return aRes;
631 }
632 else
633 {
634 // TODO(P3): if we know anything about target
635 // colorspace, this can be greatly sped up
636 uno::Sequence<rendering::ARGBColor> aIntermediate(
637 convertIntegerToARGB(deviceColor));
638 return targetColorSpace->convertFromARGB(aIntermediate);
639 }
640 }
641 virtual uno::Sequence< sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< sal_Int8 >& deviceColor,
642 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) override
643 {
644 if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
645 {
646 // it's us, so simply pass-through the data
647 return deviceColor;
648 }
649 else
650 {
651 // TODO(P3): if we know anything about target
652 // colorspace, this can be greatly sped up
653 uno::Sequence<rendering::ARGBColor> aIntermediate(
654 convertIntegerToARGB(deviceColor));
655 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
656 }
657 }
658 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< sal_Int8 >& deviceColor ) override
659 {
660 const sal_Int8* pIn( deviceColor.getConstArray() );
661 const std::size_t nLen( deviceColor.getLength() );
662 ENSURE_ARG_OR_THROW2(nLen%4==0,
663 "number of channels no multiple of 4",
664 static_cast<rendering::XColorSpace*>(this), 0);
665
666 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
667 rendering::RGBColor* pOut( aRes.getArray() );
668 for( std::size_t i=0; i<nLen; i+=4 )
669 {
670 *pOut++ = rendering::RGBColor(
674 pIn += 4;
675 }
676 return aRes;
677 }
678
679 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< sal_Int8 >& deviceColor ) override
680 {
681 const sal_Int8* pIn( deviceColor.getConstArray() );
682 const std::size_t nLen( deviceColor.getLength() );
683 ENSURE_ARG_OR_THROW2(nLen%4==0,
684 "number of channels no multiple of 4",
685 static_cast<rendering::XColorSpace*>(this), 0);
686
687 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
688 rendering::ARGBColor* pOut( aRes.getArray() );
689 for( std::size_t i=0; i<nLen; i+=4 )
690 {
691 *pOut++ = rendering::ARGBColor(
696 pIn += 4;
697 }
698 return aRes;
699 }
700
701 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< sal_Int8 >& deviceColor ) override
702 {
703 const sal_Int8* pIn( deviceColor.getConstArray() );
704 const std::size_t nLen( deviceColor.getLength() );
705 ENSURE_ARG_OR_THROW2(nLen%4==0,
706 "number of channels no multiple of 4",
707 static_cast<rendering::XColorSpace*>(this), 0);
708
709 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
710 rendering::ARGBColor* pOut( aRes.getArray() );
711 for( std::size_t i=0; i<nLen; i+=4 )
712 {
713 const sal_Int8 nAlpha( pIn[3] );
714 *pOut++ = rendering::ARGBColor(
716 vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
717 vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
718 vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
719 pIn += 4;
720 }
721 return aRes;
722 }
723
724 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
725 {
726 const sal_Int32 nLen( rgbColor.getLength() );
727
728 uno::Sequence< sal_Int8 > aRes(nLen*4);
729 sal_Int8* pColors=aRes.getArray();
730 for( const rendering::RGBColor& rIn : rgbColor )
731 {
732 *pColors++ = vcl::unotools::toByteColor(rIn.Red);
733 *pColors++ = vcl::unotools::toByteColor(rIn.Green);
734 *pColors++ = vcl::unotools::toByteColor(rIn.Blue);
735 *pColors++ = -1;
736 }
737 return aRes;
738 }
739
740 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
741 {
742 const sal_Int32 nLen( rgbColor.getLength() );
743
744 uno::Sequence< sal_Int8 > aRes(nLen*4);
745 sal_Int8* pColors=aRes.getArray();
746 for( const rendering::ARGBColor& rIn : rgbColor )
747 {
748 *pColors++ = vcl::unotools::toByteColor(rIn.Red);
749 *pColors++ = vcl::unotools::toByteColor(rIn.Green);
750 *pColors++ = vcl::unotools::toByteColor(rIn.Blue);
751 *pColors++ = vcl::unotools::toByteColor(rIn.Alpha);
752 }
753 return aRes;
754 }
755
756 virtual uno::Sequence< sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
757 {
758 const sal_Int32 nLen( rgbColor.getLength() );
759
760 uno::Sequence< sal_Int8 > aRes(nLen*4);
761 sal_Int8* pColors=aRes.getArray();
762 for( const rendering::ARGBColor& rIn : rgbColor )
763 {
764 *pColors++ = vcl::unotools::toByteColor(rIn.Red/rIn.Alpha);
765 *pColors++ = vcl::unotools::toByteColor(rIn.Green/rIn.Alpha);
766 *pColors++ = vcl::unotools::toByteColor(rIn.Blue/rIn.Alpha);
767 *pColors++ = vcl::unotools::toByteColor(rIn.Alpha);
768 }
769 return aRes;
770 }
771
772public:
773 OGLColorSpace() :
775 maBitCounts(4)
776 {
777 sal_Int8* pTags = maComponentTags.getArray();
778 sal_Int32* pBitCounts = maBitCounts.getArray();
779 pTags[0] = rendering::ColorComponentTag::RGB_RED;
780 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
781 pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
782 pTags[3] = rendering::ColorComponentTag::ALPHA;
783
784 pBitCounts[0] =
785 pBitCounts[1] =
786 pBitCounts[2] =
787 pBitCounts[3] = 8;
788 }
789};
790
791uno::Reference<rendering::XIntegerBitmapColorSpace> const &
792getOGLColorSpace()
793{
794 static uno::Reference<rendering::XIntegerBitmapColorSpace> theSpace = new OGLColorSpace();
795 return theSpace;
796}
797
798void buildMipmaps(
799 GLint internalFormat, GLsizei width, GLsizei height, GLenum format,
800 GLenum type, const void * data)
801{
802 if (epoxy_has_gl_extension("GL_ARB_framebuffer_object")) {
803 glTexImage2D(
804 GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type,
805 data);
806 glGenerateMipmap(GL_TEXTURE_2D);
807 } else {
808 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
809 glTexImage2D(
810 GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type,
811 data);
812 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
813 }
814 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
815 glTexParameteri(
816 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
817}
818
819void OGLTransitionerImpl::impl_createTexture(
820 bool useMipmap,
821 const uno::Sequence<sal_Int8>& data,
822 const OGLFormat* pFormat )
823{
824 if( !pFormat )
825 {
827 // force-convert color to ARGB8888 int color space
828 uno::Sequence<sal_Int8> tempBytes(
829 maSlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
830 data,
831 getOGLColorSpace()));
832 buildMipmaps( GL_RGBA,
833 maSlideSize.Width,
834 maSlideSize.Height,
835 GL_RGBA,
836 GL_UNSIGNED_BYTE,
837 &tempBytes[0]);
838
839 if (epoxy_has_gl_extension("GL_EXT_texture_filter_anisotropic"))
840 {
841 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
842 GLfloat largest_supported_anisotropy;
843 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
844 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
845 }
846 } else {
847 if( mpTransition && !mbBrokenTexturesATI && !useMipmap) {
848 glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
849 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
850 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
851 } else {
852 buildMipmaps( pFormat->nInternalFormat, maSlideSize.Width, maSlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
853
854 if (epoxy_has_gl_extension("GL_EXT_texture_filter_anisotropic"))
855 {
856 //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
857 GLfloat largest_supported_anisotropy;
858 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
859 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
860 }
861 }
862 }
864}
865
866const OGLFormat* OGLTransitionerImpl::chooseFormats()
867{
868 const OGLFormat* pDetectedFormat=nullptr;
869 uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
870 maSlideBitmapLayout.ColorSpace);
871
872 if( xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
873 xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB )
874 {
875 /* table for canvas->OGL format mapping. outer index is number
876 of color components (0:3, 1:4), then comes bits per pixel
877 (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
878 2:argb, 3:abgr)
879 */
880 static const OGLFormat lcl_RGB24[] =
881 {
882 // 24 bit RGB
883 {3, GL_BGR, GL_UNSIGNED_BYTE},
884 {3, GL_RGB, GL_UNSIGNED_BYTE},
885 {3, GL_BGR, GL_UNSIGNED_BYTE},
886 {3, GL_RGB, GL_UNSIGNED_BYTE}
887 };
888
889#if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
890 // more format constants available
891 static const OGLFormat lcl_RGB16[] =
892 {
893 // 16 bit RGB
894 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
895 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
896 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
897 {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
898 };
899
900 static const OGLFormat lcl_ARGB16_4[] =
901 {
902 // 16 bit ARGB
903 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
904 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
905 {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
906 {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
907 };
908
909 static const OGLFormat lcl_ARGB16_5[] =
910 {
911 // 16 bit ARGB
912 {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
913 {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
914 {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
915 {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
916 };
917
918 static const OGLFormat lcl_ARGB32[] =
919 {
920 // 32 bit ARGB
921 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
922 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
923 {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
924 {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
925 };
926
927 const uno::Sequence<sal_Int8> aComponentTags(
928 xIntColorSpace->getComponentTags());
929 const uno::Sequence<sal_Int32> aComponentBitcounts(
930 xIntColorSpace->getComponentBitCounts());
931 const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
932 const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
933
934 // supported component ordering?
935 const int nComponentOrderIndex(
936 calcComponentOrderIndex(aComponentTags));
937 if( nComponentOrderIndex != -1 )
938 {
939 switch( nBitsPerPixel )
940 {
941 case 16:
942 if( nNumComponents == 3 )
943 {
944 pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
945 }
946 else if( nNumComponents == 4 )
947 {
948 if( aComponentBitcounts[1] == 4 )
949 {
950 pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
951 }
952 else if( aComponentBitcounts[1] == 5 )
953 {
954 pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
955 }
956 }
957 break;
958 case 24:
959 if( nNumComponents == 3 )
960 {
961 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
962 }
963 break;
964 case 32:
965 if ( nNumComponents == 4 )
966 {
967 pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
968 }
969 break;
970 }
971 }
972#else
973 const uno::Sequence<sal_Int8> aComponentTags(
974 xIntColorSpace->getComponentTags());
975 const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
976 if( aComponentTags.getLength() == 3 &&
977 nComponentOrderIndex != -1 &&
978 xIntColorSpace->getBitsPerPixel() == 24 )
979 {
980 pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
981 }
982#endif
983 }
984
985 return pDetectedFormat;
986}
987
988void OGLTransitionerImpl::GLInitSlides()
989{
990 osl::MutexGuard const guard( m_aMutex );
991
992 if (isDisposed() || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
993 return;
994
995#if OSL_DEBUG_LEVEL > 0
996 TimerContext aTimerContext("texture creation");
997#endif
998
999 mpContext->makeCurrent();
1000
1001 const OGLFormat* pFormat = chooseFormats();
1002
1004 createTexture( &maLeavingSlideGL,
1005 mpTransition->getSettings().mbUseMipMapLeaving,
1006 maLeavingBytes,
1007 pFormat );
1008
1009 createTexture( &maEnteringSlideGL,
1010 mpTransition->getSettings().mbUseMipMapEntering,
1011 maEnteringBytes,
1012 pFormat );
1013
1015 mpContext->sync();
1017}
1018
1019void SAL_CALL OGLTransitionerImpl::update( double nTime )
1020{
1021#if OSL_DEBUG_LEVEL > 0
1022 mnFrameCount ++;
1023 m_UpdateStartTime = std::chrono::steady_clock::now();
1024 if( mnFrameCount == 1 ) {
1025 m_StartTime = m_UpdateStartTime;
1026 m_TotalUpdateDuration = std::chrono::seconds(0);
1027 }
1028#endif
1029 osl::MutexGuard const guard( m_aMutex );
1030
1031 if (isDisposed() || !mbValidOpenGLContext || !mpTransition || mpTransition->getSettings().mnRequiredGLVersion > mnGLVersion)
1032 return;
1033
1034 mpContext->makeCurrent();
1036
1037 glEnable(GL_DEPTH_TEST);
1038 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1040
1041 const GLWindow& rGLWindow(mpContext->getOpenGLWindow());
1042 mpTransition->display(nTime, maLeavingSlideGL, maEnteringSlideGL,
1043 maSlideSize.Width, maSlideSize.Height,
1044 static_cast<double>(rGLWindow.Width),
1045 static_cast<double>(rGLWindow.Height),
1046 mpContext.get());
1047
1048 mpContext->swapBuffers();
1049
1050 mpContext->show();
1051 mpContext->sync();
1053
1054#if OSL_DEBUG_LEVEL > 0
1055 m_UpdateEndTime = std::chrono::steady_clock::now();
1056
1057 SAL_INFO("slideshow.opengl", "update time: " << nTime);
1058 SAL_INFO("slideshow.opengl", "update took: " << std::chrono::duration_cast<std::chrono::milliseconds>(m_UpdateEndTime - m_UpdateStartTime).count());
1059 m_TotalUpdateDuration += m_UpdateEndTime - m_UpdateStartTime;
1060#endif
1061}
1062
1063void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
1064 const Reference< rendering::XBitmap >& rLeavingBitmap,
1065 const Reference< rendering::XBitmap >& rEnteringBitmap )
1066{
1067 SAL_INFO("slideshow.opengl", "transitioner: view changed");
1068
1069 impl_dispose();
1070
1071 initWindowFromSlideShowView( rView );
1072 setSlides( rLeavingBitmap, rEnteringBitmap );
1073 impl_prepareSlides();
1074 impl_prepareTransition();
1075}
1076
1077void OGLTransitionerImpl::disposeTextures()
1078{
1079 if (!mbValidOpenGLContext)
1080 return;
1081
1082 mpContext->makeCurrent();
1084
1085 glDeleteTextures(1,&maLeavingSlideGL);
1086 maLeavingSlideGL = 0;
1087 glDeleteTextures(1,&maEnteringSlideGL);
1088 maEnteringSlideGL = 0;
1089
1091}
1092
1093void OGLTransitionerImpl::impl_dispose()
1094{
1095 if (mbValidOpenGLContext)
1096 {
1097 mpContext->makeCurrent();
1099 }
1100
1101 if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= mnGLVersion )
1102 mpTransition->finish();
1103 disposeTextures();
1104 if( mpContext.is() )
1105 mpContext->dispose();
1106 mpContext.clear();
1107}
1108
1109// we are about to be disposed (someone call dispose() on us)
1110void OGLTransitionerImpl::disposing()
1111{
1112 osl::MutexGuard const guard( m_aMutex );
1113
1114#if OSL_DEBUG_LEVEL > 0
1115 SAL_INFO("slideshow.opengl", "dispose " << this);
1116 if( mnFrameCount ) {
1117 m_EndTime = std::chrono::steady_clock::now();
1118 auto const duration = m_EndTime - m_StartTime;
1119 SAL_INFO("slideshow.opengl",
1120 "whole transition (frames: " << mnFrameCount
1121 << ") took: " << std::chrono::duration_cast<std::chrono::microseconds>(duration).count()
1122 << " fps: "
1123 << ((static_cast<double>(mnFrameCount)*1000000000.0)/std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count())
1124 << " time spent in updates: " << std::chrono::duration_cast<std::chrono::microseconds>(m_TotalUpdateDuration).count()
1125 << " percentage of transition time: "
1126 << (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()))))
1127 << '%'
1128 );
1129 }
1130#endif
1131
1132 if (mbRestoreSync && mpContext.is()) {
1133 // try to reestablish synchronize state
1134 const char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
1135 mpContext->getOpenGLWindow().Synchronize(sal_synchronize && *sal_synchronize == '1' );
1136 }
1137
1138 impl_dispose();
1139
1140 mpTransition.reset();
1141
1142 mxLeavingBitmap.clear();
1143 mxEnteringBitmap.clear();
1144 mxView.clear();
1145}
1146
1147OGLTransitionerImpl::OGLTransitionerImpl()
1148 : OGLTransitionerImplBase(m_aMutex)
1149 , mpContext()
1150 , maLeavingSlideGL(0)
1151 , maEnteringSlideGL(0)
1152 , mxView()
1153 , maEnteringBytes()
1154 , maLeavingBytes()
1155 , mbRestoreSync(false)
1156 , maSlideBitmapLayout()
1157 , maSlideSize()
1158 , mbBrokenTexturesATI(false)
1159 , mnGLVersion(0)
1160 , mbValidOpenGLContext(false)
1161#if OSL_DEBUG_LEVEL > 0
1162 , mnFrameCount(0)
1163#endif
1164{
1165}
1166
1167typedef cppu::WeakComponentImplHelper<presentation::XTransitionFactory, lang::XServiceInfo> OGLTransitionFactoryImplBase;
1168
1169class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
1170{
1171public:
1172 explicit OGLTransitionFactoryImpl() :
1173 OGLTransitionFactoryImplBase(m_aMutex)
1174 {}
1175
1176 // XServiceInfo
1177 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override
1178 {
1179 return { "com.sun.star.presentation.TransitionFactory" };
1180 }
1181 virtual OUString SAL_CALL getImplementationName() override
1182 {
1183 return "com.sun.star.comp.presentation.OGLTransitionFactory";
1184 }
1185 virtual sal_Bool SAL_CALL supportsService(const OUString& aServiceName) override
1186 {
1187 return cppu::supportsService(this, aServiceName);
1188 }
1189
1190 // XTransitionFactory
1191 virtual sal_Bool SAL_CALL hasTransition( sal_Int16 transitionType, sal_Int16 transitionSubType ) override
1192 {
1194 return false;
1195 // A set of css::animation::TransitionSubType that don't have any meaning (in the SMIL 2.0
1196 // standard) for MISCSHAPEWIPE have been chosen to refer to some of these "fancy" optional
1197 // transitions. (The only subtypes of 'miscShapeWipe' defined in the standard are 'heart'
1198 // and 'keyhole'.) The set of subtypes used seems to be a bit random; it starts from the
1199 // beginning of the list (in the order (numeric) in our TransitionSubType set of constants)
1200 // but then jumps a bit randomly. The numeric values as such have no meaning, but still.
1201
1202 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1203 switch( transitionSubType )
1204 {
1205 case animations::TransitionSubType::LEFTTORIGHT: // 1
1206 case animations::TransitionSubType::TOPTOBOTTOM: // 2
1207 case animations::TransitionSubType::TOPLEFT: // 3
1208 case animations::TransitionSubType::TOPRIGHT: // 4
1209 case animations::TransitionSubType::BOTTOMRIGHT: // 5
1210 case animations::TransitionSubType::BOTTOMLEFT: // 6
1211 case animations::TransitionSubType::TOPCENTER: // 7
1212 case animations::TransitionSubType::RIGHTCENTER: // 8
1213 case animations::TransitionSubType::BOTTOMCENTER: // 9
1214 case animations::TransitionSubType::CORNERSIN: // 11
1215 case animations::TransitionSubType::CORNERSOUT: // 12
1216 case animations::TransitionSubType::VERTICAL: // 13
1217 case animations::TransitionSubType::HORIZONTAL: // 14
1218 case animations::TransitionSubType::DIAMOND: // 26
1219 case animations::TransitionSubType::CIRCLE: // 27
1220 case animations::TransitionSubType::HEART: // 31
1221 case animations::TransitionSubType::FANOUTHORIZONTAL: // 55
1222 case animations::TransitionSubType::ACROSS: // 108
1223 return true;
1224
1225 default:
1226 return false;
1227 }
1228 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1229 return true;
1230 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1231 return true;
1232 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1233 return true;
1234 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1235 return true;
1236 } else
1237 return false;
1238 }
1239
1240 virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
1241 sal_Int16 transitionType,
1242 sal_Int16 transitionSubType,
1243 sal_Int32 transitionFadeColor,
1244 const uno::Reference< presentation::XSlideShowView >& view,
1245 const uno::Reference< rendering::XBitmap >& leavingBitmap,
1246 const uno::Reference< rendering::XBitmap >& enteringBitmap ) override
1247 {
1248 if( !hasTransition( transitionType, transitionSubType ) )
1249 return uno::Reference< presentation::XTransition >();
1250
1251 rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() );
1252 if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) )
1253 return uno::Reference< presentation::XTransition >();
1254
1255 std::shared_ptr<OGLTransitionImpl> pTransition;
1256
1257 if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1258 switch( transitionSubType )
1259 {
1260 case animations::TransitionSubType::LEFTTORIGHT:
1261 pTransition = makeFallLeaving();
1262 break;
1263 case animations::TransitionSubType::TOPTOBOTTOM:
1264 pTransition = makeTurnAround();
1265 break;
1266 case animations::TransitionSubType::TOPLEFT:
1267 pTransition = makeIris();
1268 break;
1269 case animations::TransitionSubType::TOPRIGHT:
1270 pTransition = makeTurnDown();
1271 break;
1272 case animations::TransitionSubType::BOTTOMRIGHT:
1273 pTransition = makeRochade();
1274 break;
1275 case animations::TransitionSubType::BOTTOMLEFT:
1276 pTransition = makeVenetianBlinds( true, 8 );
1277 break;
1278 case animations::TransitionSubType::TOPCENTER:
1279 pTransition = makeVenetianBlinds( false, 6 );
1280 break;
1281 case animations::TransitionSubType::RIGHTCENTER:
1282 pTransition = makeStatic();
1283 break;
1284 case animations::TransitionSubType::BOTTOMCENTER:
1285 pTransition = makeDissolve();
1286 break;
1287 case animations::TransitionSubType::CORNERSIN:
1288 pTransition = makeInsideCubeFaceToLeft();
1289 break;
1290 case animations::TransitionSubType::CORNERSOUT:
1291 pTransition = makeOutsideCubeFaceToLeft();
1292 break;
1293 case animations::TransitionSubType::VERTICAL:
1294 pTransition = makeVortex();
1295 break;
1296 case animations::TransitionSubType::HORIZONTAL:
1297 pTransition = makeRipple();
1298 break;
1299 case animations::TransitionSubType::CIRCLE:
1300 pTransition = makeRevolvingCircles(8,128);
1301 break;
1302 case animations::TransitionSubType::FANOUTHORIZONTAL:
1303 pTransition = makeHelix(20);
1304 break;
1305 case animations::TransitionSubType::ACROSS:
1306 pTransition = makeNByMTileFlip(8,6);
1307 break;
1308 case animations::TransitionSubType::DIAMOND:
1309 pTransition = makeGlitter();
1310 break;
1311 case animations::TransitionSubType::HEART:
1312 pTransition = makeHoneycomb();
1313 break;
1314 }
1315 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1316 pTransition = makeFadeSmoothly();
1317 } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1318 pTransition = makeFadeThroughColor( transitionFadeColor == 0xffffff );
1319 } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1320 pTransition = makeDiamond();
1321 } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1322 pTransition = makeNewsflash();
1323 }
1324
1325 if ( !pTransition || !xRes->setTransition(pTransition) )
1326 return uno::Reference< presentation::XTransition >();
1327
1328 return xRes;
1329 }
1330};
1331
1332}
1333
1334extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1336 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
1337{
1338 return cppu::acquire(new OGLTransitionFactoryImpl());
1339}
1340/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define CHECK_GL_ERROR()
std::shared_ptr< OGLTransitionImpl > makeTurnAround()
std::shared_ptr< OGLTransitionImpl > makeHoneycomb()
std::shared_ptr< OGLTransitionImpl > makeRipple()
std::shared_ptr< OGLTransitionImpl > makeVenetianBlinds(bool vertical, int parts)
std::shared_ptr< OGLTransitionImpl > makeGlitter()
std::shared_ptr< OGLTransitionImpl > makeDiamond()
2D replacements
std::shared_ptr< OGLTransitionImpl > makeDissolve()
std::shared_ptr< OGLTransitionImpl > makeRochade()
std::shared_ptr< OGLTransitionImpl > makeRevolvingCircles(sal_uInt16 nCircles, sal_uInt16 nPointsOnCircles)
std::shared_ptr< OGLTransitionImpl > makeNByMTileFlip(sal_uInt16 n, sal_uInt16 m)
std::shared_ptr< OGLTransitionImpl > makeFallLeaving()
std::shared_ptr< OGLTransitionImpl > makeFadeSmoothly()
std::shared_ptr< OGLTransitionImpl > makeIris()
std::shared_ptr< OGLTransitionImpl > makeNewsflash()
std::shared_ptr< OGLTransitionImpl > makeStatic()
std::shared_ptr< OGLTransitionImpl > makeOutsideCubeFaceToLeft()
std::shared_ptr< OGLTransitionImpl > makeTurnDown()
std::shared_ptr< OGLTransitionImpl > makeVortex()
std::shared_ptr< OGLTransitionImpl > makeFadeThroughColor(bool white)
std::shared_ptr< OGLTransitionImpl > makeHelix(sal_uInt16 nRows)
std::shared_ptr< OGLTransitionImpl > makeInsideCubeFaceToLeft()
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * slideshow_OGLTransitionFactoryImpl_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
uno::Sequence< sal_Int32 > maBitCounts
uno::Sequence< sal_Int8 > maComponentTags
static rtl::Reference< OpenGLContext > Create()
virtual vcl::Window * GetOwnerWindow() const
void SetLeaveEnterBackgrounds(const css::uno::Sequence< css::uno::Any > &rLeaveArgs, const css::uno::Sequence< css::uno::Any > &rEnterArgs)
#define ENSURE_ARG_OR_THROW2(c, m, ifc, arg)
DocumentType eType
std::mutex m_aMutex
#define SAL_WARN_IF(condition, area, stream)
#define SAL_INFO(area, stream)
DateTime now
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
sal_Int8 toByteColor(double val)
double toDoubleColor(sal_uInt8 val)
bool getType(BSTR name, Type &type)
const basegfx::B2ISize maSlideSize
Definition: slideimpl.cxx:221
uno::Reference< presentation::XSlideShowView > mxView
Definition: slideview.cxx:725
ParserContextSharedPtr mpContext
static float getGLVersion()
static bool supportsOpenGL()
unsigned char sal_Bool
signed char sal_Int8
bool update()
oslFileHandle & pOut