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