Line data Source code
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 : #define GLX_GLXEXT_PROTOTYPES 1
30 : #include "OGLTrans_TransitionImpl.hxx"
31 :
32 : #include <com/sun/star/beans/XFastPropertySet.hpp>
33 : #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
34 : #include <com/sun/star/rendering/ColorComponentTag.hpp>
35 : #include <com/sun/star/rendering/ColorSpaceType.hpp>
36 : #include <com/sun/star/rendering/RenderingIntent.hpp>
37 : #include <com/sun/star/util/Endianness.hpp>
38 : #include <com/sun/star/animations/TransitionType.hpp>
39 : #include <com/sun/star/animations/TransitionSubType.hpp>
40 : #include <com/sun/star/presentation/XTransitionFactory.hpp>
41 : #include <com/sun/star/presentation/XTransition.hpp>
42 : #include <com/sun/star/presentation/XSlideShowView.hpp>
43 : #include <com/sun/star/uno/XComponentContext.hpp>
44 : #include <com/sun/star/rendering/XIntegerBitmap.hpp>
45 : #include <com/sun/star/geometry/IntegerSize2D.hpp>
46 :
47 : #include <cppuhelper/compbase1.hxx>
48 : #include <cppuhelper/basemutex.hxx>
49 : #include <cppuhelper/factory.hxx>
50 : #include <rtl/ref.hxx>
51 :
52 : #include <comphelper/servicedecl.hxx>
53 :
54 : #include <canvas/canvastools.hxx>
55 :
56 : #include <tools/diagnose_ex.h>
57 : #include <tools/gen.hxx>
58 :
59 : #include <vcl/canvastools.hxx>
60 : #include <vcl/window.hxx>
61 : #include <vcl/syschild.hxx>
62 :
63 : #include <boost/noncopyable.hpp>
64 :
65 : #include <GL/gl.h>
66 : #include <GL/glu.h>
67 :
68 :
69 : #if defined( WNT )
70 : #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
71 : #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
72 : #elif defined( QUARTZ )
73 : #include "premac.h"
74 : #include <Cocoa/Cocoa.h>
75 : #include "postmac.h"
76 : #elif defined( UNX )
77 : namespace unx
78 : {
79 : #include <X11/keysym.h>
80 : #include <X11/X.h>
81 : #include <GL/glx.h>
82 : #include <GL/glxext.h>
83 : }
84 : #endif
85 : #include <vcl/sysdata.hxx>
86 :
87 : #if OSL_DEBUG_LEVEL > 1
88 : #include <boost/date_time/posix_time/posix_time.hpp>
89 : using namespace ::boost::posix_time;
90 :
91 : #endif
92 :
93 : using namespace ::com::sun::star;
94 : using ::com::sun::star::beans::XFastPropertySet;
95 : using ::com::sun::star::uno::Any;
96 : using ::com::sun::star::uno::Reference;
97 : using ::com::sun::star::uno::Sequence;
98 : using ::com::sun::star::uno::UNO_QUERY;
99 : using ::com::sun::star::uno::UNO_QUERY_THROW;
100 :
101 : namespace
102 : {
103 :
104 : typedef cppu::WeakComponentImplHelper1<presentation::XTransition> OGLTransitionerImplBase;
105 :
106 : #if OSL_DEBUG_LEVEL > 1
107 : class TimerContext
108 : {
109 : public:
110 : explicit TimerContext(rtl::OUString const& rWhat)
111 : : m_aWhat(rWhat)
112 : , m_aStartTime(microsec_clock::local_time())
113 : {
114 : }
115 : ~TimerContext()
116 : {
117 : time_duration const aDuration(microsec_clock::local_time() - m_aStartTime);
118 : SAL_INFO("slideshow.opengl", m_aWhat << " took: " << aDuration);
119 : }
120 : private:
121 : rtl::OUString const m_aWhat;
122 : ptime const m_aStartTime;
123 : };
124 : #endif
125 :
126 : struct OGLFormat
127 : {
128 : GLint nInternalFormat;
129 : GLenum eFormat;
130 : GLenum eType;
131 : };
132 :
133 : /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
134 : */
135 0 : int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
136 : {
137 : using namespace rendering::ColorComponentTag;
138 :
139 : static const sal_Int8 aOrderTable[] =
140 : {
141 : RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
142 : RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
143 : ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
144 : ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
145 : };
146 :
147 0 : const sal_Int32 nNumComps(rTags.getLength());
148 0 : const sal_Int8* pLine=aOrderTable;
149 0 : for(int i=0; i<4; ++i)
150 : {
151 0 : int j=0;
152 0 : while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
153 0 : ++j;
154 :
155 : // all of the line passed, this is a match!
156 0 : if( j==nNumComps )
157 0 : return i;
158 :
159 0 : pLine+=4;
160 : }
161 :
162 0 : return -1;
163 : }
164 :
165 : // not thread safe
166 : static bool errorTriggered;
167 0 : int oglErrorHandler( unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/ )
168 : {
169 0 : errorTriggered = true;
170 :
171 0 : return 0;
172 : }
173 :
174 : /** This is the Transitioner class for OpenGL 3D transitions in
175 : * slideshow. At the moment, it's Linux only. This class is implicitly
176 : * constructed from XTransitionFactory.
177 : */
178 0 : class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable, public OGLTransitionerImplBase
179 : {
180 : public:
181 : OGLTransitionerImpl();
182 : void setTransition( boost::shared_ptr<OGLTransitionImpl> pOGLTransition );
183 : bool initialize( const Reference< presentation::XSlideShowView >& xView,
184 : const Reference< rendering::XBitmap >& xLeavingSlide,
185 : const Reference< rendering::XBitmap >& xEnteringSlide );
186 :
187 : // XTransition
188 : virtual void SAL_CALL update( double nTime )
189 : throw (uno::RuntimeException);
190 : virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
191 : const Reference< rendering::XBitmap >& rLeavingBitmap,
192 : const Reference< rendering::XBitmap >& rEnteringBitmap )
193 : throw (uno::RuntimeException);
194 :
195 : protected:
196 : void disposeContextAndWindow();
197 : void disposeTextures();
198 :
199 : // WeakComponentImplHelperBase
200 : virtual void SAL_CALL disposing();
201 :
202 0 : bool isDisposed() const
203 : {
204 0 : return (rBHelper.bDisposed || rBHelper.bInDispose);
205 : }
206 :
207 : bool createWindow( Window* pPWindow );
208 : void createTexture( unsigned int* texID,
209 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
210 : unx::GLXPixmap pixmap,
211 : bool usePixmap,
212 : #endif
213 : bool useMipmap,
214 : uno::Sequence<sal_Int8>& data,
215 : const OGLFormat* pFormat );
216 : void prepareEnvironment ();
217 : const OGLFormat* chooseFormats();
218 :
219 : private:
220 : static void impl_initializeOnce( bool const bGLXPresent );
221 :
222 : void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
223 : void impl_prepareSlides();
224 :
225 : void impl_createTexture( bool useMipmap, uno::Sequence<sal_Int8>& data, const OGLFormat* pFormat );
226 :
227 : bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
228 : /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
229 : */
230 : void GLInitSlides();
231 :
232 : void impl_prepareTransition();
233 : void impl_finishTransition();
234 :
235 : /// Holds the information of our new child window
236 : struct GLWindow
237 : {
238 : #if defined( WNT )
239 : HWND hWnd;
240 : HDC hDC;
241 : HGLRC hRC;
242 : #elif defined( QUARTZ )
243 : #elif defined( UNX )
244 : unx::Display* dpy;
245 : int screen;
246 : unx::Window win;
247 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
248 : unx::GLXFBConfig fbc;
249 : #endif
250 : unx::XVisualInfo* vi;
251 : unx::GLXContext ctx;
252 : #endif
253 : unsigned int bpp;
254 : unsigned int Width;
255 : unsigned int Height;
256 : const char* GLXExtensions;
257 : const GLubyte* GLExtensions;
258 :
259 0 : bool HasGLXExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, (const GLubyte*) GLXExtensions ); }
260 0 : bool HasGLExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, GLExtensions ); }
261 : } GLWin;
262 :
263 : /** OpenGL handle to the leaving slide's texture
264 : */
265 : unsigned int GLleavingSlide;
266 : /** OpenGL handle to the entering slide's texture
267 : */
268 : unsigned int GLenteringSlide;
269 :
270 : /** pointer to our window which we MIGHT create.
271 : */
272 : class SystemChildWindow* pWindow;
273 :
274 : Reference< presentation::XSlideShowView > mxView;
275 : Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
276 : Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
277 :
278 : /** raw bytes of the entering bitmap
279 : */
280 : uno::Sequence<sal_Int8> EnteringBytes;
281 :
282 : /** raw bytes of the leaving bitmap
283 : */
284 : uno::Sequence<sal_Int8> LeavingBytes;
285 :
286 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
287 : unx::GLXPixmap LeavingPixmap;
288 : unx::GLXPixmap EnteringPixmap;
289 : #endif
290 : bool mbRestoreSync;
291 : bool mbUseLeavingPixmap;
292 : bool mbUseEnteringPixmap;
293 : bool mbFreeLeavingPixmap;
294 : bool mbFreeEnteringPixmap;
295 : unx::Pixmap maLeavingPixmap;
296 : unx::Pixmap maEnteringPixmap;
297 :
298 : /** the form the raw bytes are in for the bitmaps
299 : */
300 : rendering::IntegerBitmapLayout SlideBitmapLayout;
301 :
302 : /** the size of the slides
303 : */
304 : geometry::IntegerSize2D SlideSize;
305 :
306 : /** Our Transition to be used.
307 : */
308 : boost::shared_ptr<OGLTransitionImpl> mpTransition;
309 :
310 : public:
311 : /** whether we are running on ATI fglrx with bug related to textures
312 : */
313 : static bool cbBrokenTexturesATI;
314 :
315 : /** GL version
316 : */
317 : static float cnGLVersion;
318 : float mnGLXVersion;
319 :
320 : /** Whether Mesa is the OpenGL vendor
321 : */
322 : static bool cbMesa;
323 :
324 : /**
325 : whether the display has GLX extension
326 : */
327 : static bool cbGLXPresent;
328 :
329 : /**
330 : whether texture from pixmap extension is available
331 : */
332 : bool mbTextureFromPixmap;
333 :
334 : /**
335 : whether to generate mipmaped textures
336 : */
337 : bool mbGenerateMipmap;
338 :
339 : /**
340 : whether we have visual which can be used for texture_from_pixmap extension
341 : */
342 : bool mbHasTFPVisual;
343 :
344 : #if OSL_DEBUG_LEVEL > 1
345 : ptime maUpdateStartTime;
346 : ptime maUpdateEndTime;
347 : ptime maStartTime;
348 : ptime maEndTime;
349 : time_duration maTotalUpdateDuration;
350 : int mnFrameCount;
351 : #endif
352 : };
353 :
354 : // declare the static variables as some gcc versions have problems declaring them automaticaly
355 : bool OGLTransitionerImpl::cbBrokenTexturesATI;
356 : float OGLTransitionerImpl::cnGLVersion;
357 : bool OGLTransitionerImpl::cbMesa;
358 : bool OGLTransitionerImpl::cbGLXPresent;
359 :
360 0 : bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView,
361 : const Reference< rendering::XBitmap >& xLeavingSlide,
362 : const Reference< rendering::XBitmap >& xEnteringSlide )
363 : {
364 0 : bool const bGLXPresent( initWindowFromSlideShowView( xView ) );
365 0 : impl_initializeOnce( bGLXPresent );
366 :
367 0 : setSlides( xLeavingSlide, xEnteringSlide );
368 :
369 0 : return cbGLXPresent;
370 : }
371 :
372 0 : void OGLTransitionerImpl::impl_initializeOnce( bool const bGLXPresent )
373 : {
374 : // not thread safe
375 : static bool initialized = false;
376 :
377 0 : if( !initialized ) {
378 0 : cbGLXPresent = bGLXPresent;
379 0 : if ( bGLXPresent ) {
380 0 : const GLubyte* version = glGetString( GL_VERSION );
381 0 : if( version && version[0] ) {
382 0 : cnGLVersion = version[0] - '0';
383 0 : if( version[1] == '.' && version[2] )
384 0 : cnGLVersion += (version[2] - '0')/10.0;
385 : } else
386 0 : cnGLVersion = 1.0;
387 : SAL_INFO("slideshow.opengl", "GL version: " << version << " parsed: " << cnGLVersion << "" );
388 :
389 0 : const GLubyte* vendor = glGetString( GL_VENDOR );
390 0 : cbMesa = ( vendor && strstr( (const char *) vendor, "Mesa" ) );
391 : SAL_INFO("slideshow.opengl", "GL vendor: " << vendor << " identified as Mesa: " << cbMesa << "" );
392 :
393 : /* TODO: check for version once the bug in fglrx driver is fixed */
394 0 : cbBrokenTexturesATI = (vendor && strcmp( (const char *) vendor, "ATI Technologies Inc." ) == 0 );
395 :
396 : }
397 0 : initialized = true;
398 : }
399 0 : }
400 :
401 : #if defined( UNX )
402 : SystemEnvData const*
403 0 : lcl_createSystemWindow(
404 : unx::XVisualInfo* const pXVisual,
405 : Window* const pParentWindow,
406 : SystemChildWindow** const pChildWindow )
407 : {
408 : assert(pChildWindow);
409 :
410 : SystemWindowData winData;
411 0 : winData.nSize = sizeof(winData);
412 : SAL_INFO("slideshow.opengl", "using VisualID " << pXVisual->visualid);
413 0 : winData.pVisual = (void*)(pXVisual->visual);
414 0 : SystemChildWindow* pWindow = new SystemChildWindow(pParentWindow, 0, &winData, sal_False);
415 0 : SystemEnvData const* const pChildSysData = pWindow->GetSystemData();
416 0 : if( !pChildSysData ) {
417 0 : delete pWindow, pWindow=NULL;
418 : }
419 :
420 0 : *pChildWindow = pWindow;
421 0 : return pChildSysData;
422 : }
423 : #endif
424 :
425 0 : bool OGLTransitionerImpl::createWindow( Window* pPWindow )
426 : {
427 0 : const SystemEnvData* sysData(pPWindow->GetSystemData());
428 : #if defined( WNT )
429 : GLWin.hWnd = sysData->hWnd;
430 : #elif defined( UNX )
431 0 : GLWin.dpy = reinterpret_cast<unx::Display*>(sysData->pDisplay);
432 :
433 0 : if( unx::glXQueryExtension( GLWin.dpy, NULL, NULL ) == false )
434 0 : return false;
435 :
436 0 : GLWin.win = sysData->aWindow;
437 :
438 : SAL_INFO("slideshow.opengl", "parent window: " << GLWin.win);
439 :
440 : unx::XWindowAttributes xattr;
441 0 : unx::XGetWindowAttributes( GLWin.dpy, GLWin.win, &xattr );
442 :
443 0 : GLWin.screen = XScreenNumberOfScreen( xattr.screen );
444 :
445 0 : unx::XVisualInfo* vi( NULL );
446 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
447 : unx::XVisualInfo* visinfo;
448 0 : unx::XVisualInfo* firstVisual( NULL );
449 : #endif
450 : static int attrList3[] =
451 : {
452 : GLX_RGBA,//only TrueColor or DirectColor
453 : //single buffered
454 : GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
455 : GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
456 : GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
457 : GLX_DEPTH_SIZE,0,//no depth buffer
458 : None
459 : };
460 : static int attrList2[] =
461 : {
462 : GLX_RGBA,//only TrueColor or DirectColor
463 : /// single buffered
464 : GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
465 : GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
466 : GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
467 : GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
468 : None
469 : };
470 : static int attrList1[] =
471 : {
472 : GLX_RGBA,//only TrueColor or DirectColor
473 : GLX_DOUBLEBUFFER,/// only double buffer
474 : GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
475 : GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
476 : GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
477 : GLX_DEPTH_SIZE,0,/// no depth buffer
478 : None
479 : };
480 : static int attrList0[] =
481 : {
482 : GLX_RGBA,//only TrueColor or DirectColor
483 : GLX_DOUBLEBUFFER,/// only double buffer
484 : GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
485 : GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
486 : GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
487 : GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
488 : None
489 : };
490 : static int* attrTable[] =
491 : {
492 : attrList0,
493 : attrList1,
494 : attrList2,
495 : attrList3,
496 : NULL
497 : };
498 0 : int** pAttributeTable = attrTable;
499 0 : const SystemEnvData* pChildSysData = NULL;
500 0 : delete pWindow;
501 0 : pWindow=NULL;
502 :
503 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
504 0 : unx::GLXFBConfig* fbconfigs = NULL;
505 0 : int nfbconfigs, value, i = 0;
506 : #endif
507 :
508 0 : while( *pAttributeTable )
509 : {
510 : // try to find a visual for the current set of attributes
511 : vi = unx::glXChooseVisual( GLWin.dpy,
512 : GLWin.screen,
513 0 : *pAttributeTable );
514 :
515 0 : if( vi ) {
516 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
517 0 : if( !firstVisual )
518 0 : firstVisual = vi;
519 : SAL_INFO("slideshow.opengl", "trying VisualID " << vi->visualid);
520 0 : fbconfigs = glXGetFBConfigs (GLWin.dpy, GLWin.screen, &nfbconfigs);
521 0 : for ( ; i < nfbconfigs; i++)
522 : {
523 0 : visinfo = glXGetVisualFromFBConfig (GLWin.dpy, fbconfigs[i]);
524 0 : if( !visinfo || visinfo->visualid != vi->visualid )
525 0 : continue;
526 :
527 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
528 0 : if (!(value & GLX_PIXMAP_BIT))
529 0 : continue;
530 :
531 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
532 : GLX_BIND_TO_TEXTURE_TARGETS_EXT,
533 0 : &value);
534 0 : if (!(value & GLX_TEXTURE_2D_BIT_EXT))
535 0 : continue;
536 :
537 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
538 : GLX_BIND_TO_TEXTURE_RGB_EXT,
539 0 : &value);
540 0 : if (value == sal_False)
541 0 : continue;
542 :
543 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
544 : GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
545 0 : &value);
546 0 : if (value == sal_False)
547 0 : continue;
548 :
549 : /* TODO: handle non Y inverted cases */
550 0 : break;
551 : }
552 :
553 0 : if( i != nfbconfigs ) {
554 0 : vi = glXGetVisualFromFBConfig( GLWin.dpy, fbconfigs[i] );
555 0 : mbHasTFPVisual = true;
556 0 : pChildSysData = lcl_createSystemWindow( vi, pPWindow, &pWindow );
557 : SAL_INFO("slideshow.opengl", "found visual suitable for texture_from_pixmap");
558 0 : } else if( firstVisual && pAttributeTable[1] == NULL ) {
559 0 : vi = firstVisual;
560 0 : mbHasTFPVisual = false;
561 0 : pChildSysData = lcl_createSystemWindow( vi, pPWindow, &pWindow );
562 : SAL_INFO("slideshow.opengl", "did not find visual suitable for texture_from_pixmap, using " << vi->visualid);
563 : }
564 : #else
565 : pChildSysData = lcl_createSystemWindow( vi, pPWindow, &pWindow );
566 : #endif
567 0 : if ( pChildSysData )
568 0 : break;
569 : }
570 :
571 0 : ++pAttributeTable;
572 : }
573 : #endif
574 :
575 : #if defined( WNT )
576 : SystemWindowData winData;
577 : winData.nSize = sizeof(winData);
578 : pWindow=new SystemChildWindow(pPWindow, 0, &winData, sal_False);
579 : pWindow->GetSystemData();
580 : #endif
581 :
582 0 : if( pWindow )
583 : {
584 0 : pWindow->SetMouseTransparent( sal_True );
585 0 : pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
586 0 : pWindow->EnableEraseBackground( sal_False );
587 0 : pWindow->SetControlForeground();
588 0 : pWindow->SetControlBackground();
589 0 : pWindow->EnablePaint(sal_False);
590 : #if defined( WNT )
591 : GLWin.hWnd = sysData->hWnd;
592 : #elif defined( UNX )
593 0 : GLWin.dpy = reinterpret_cast<unx::Display*>(pChildSysData->pDisplay);
594 0 : GLWin.win = pChildSysData->aWindow;
595 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
596 0 : if( mbHasTFPVisual )
597 0 : GLWin.fbc = fbconfigs[i];
598 : #endif
599 0 : GLWin.vi = vi;
600 0 : GLWin.GLXExtensions = unx::glXQueryExtensionsString( GLWin.dpy, GLWin.screen );
601 : SAL_INFO("slideshow.opengl", "available GLX extensions: " << GLWin.GLXExtensions);
602 : #endif
603 :
604 0 : return true;
605 : }
606 :
607 0 : return false;
608 : }
609 :
610 0 : bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
611 : {
612 0 : osl::MutexGuard const guard( m_aMutex );
613 :
614 0 : if (isDisposed())
615 0 : return false;
616 :
617 0 : mxView.set( xView, UNO_QUERY );
618 0 : if( !mxView.is() )
619 0 : return false;
620 :
621 : #if OSL_DEBUG_LEVEL > 1
622 : TimerContext aTimerContext("initWindowFromSlideShowView");
623 : #endif
624 :
625 : /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
626 0 : uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
627 0 : uno::Sequence< uno::Any > aDeviceParams;
628 0 : ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
629 :
630 0 : ::rtl::OUString aImplName;
631 0 : aDeviceParams[ 0 ] >>= aImplName;
632 :
633 0 : sal_Int64 aVal = 0;
634 0 : aDeviceParams[1] >>= aVal;
635 0 : if( !createWindow( reinterpret_cast< Window* >( aVal ) ) )
636 0 : return false;
637 :
638 0 : awt::Rectangle aCanvasArea = mxView->getCanvasArea();
639 0 : pWindow->setPosSizePixel(aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
640 0 : GLWin.Width = aCanvasArea.Width;
641 0 : GLWin.Height = aCanvasArea.Height;
642 : SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea.X << "," << aCanvasArea.Y << " - " << aCanvasArea.Width << "x" << aCanvasArea.Height);
643 :
644 : #if defined( WNT )
645 : GLWin.hDC = GetDC(GLWin.hWnd);
646 : #elif defined( UNX )
647 : GLWin.ctx = glXCreateContext(GLWin.dpy,
648 : GLWin.vi,
649 : 0,
650 0 : GL_TRUE);
651 0 : if( GLWin.ctx == NULL ) {
652 : SAL_INFO("slideshow.opengl", "unable to create GLX context");
653 0 : return false;
654 : }
655 : #endif
656 :
657 : #if defined( WNT )
658 : PIXELFORMATDESCRIPTOR PixelFormatFront = // PixelFormat Tells Windows How We Want Things To Be
659 : {
660 : sizeof(PIXELFORMATDESCRIPTOR),
661 : 1, // Version Number
662 : PFD_DRAW_TO_WINDOW |
663 : PFD_SUPPORT_OPENGL |
664 : PFD_DOUBLEBUFFER,
665 : PFD_TYPE_RGBA, // Request An RGBA Format
666 : (BYTE)32, // Select Our Color Depth
667 : 0, 0, 0, 0, 0, 0, // Color Bits Ignored
668 : 0, // No Alpha Buffer
669 : 0, // Shift Bit Ignored
670 : 0, // No Accumulation Buffer
671 : 0, 0, 0, 0, // Accumulation Bits Ignored
672 : 64, // 32 bit Z-BUFFER
673 : 0, // 0 bit stencil buffer
674 : 0, // No Auxiliary Buffer
675 : 0, // now ignored
676 : 0, // Reserved
677 : 0, 0, 0 // Layer Masks Ignored
678 : };
679 : int WindowPix = ChoosePixelFormat(GLWin.hDC,&PixelFormatFront);
680 : SetPixelFormat(GLWin.hDC,WindowPix,&PixelFormatFront);
681 : GLWin.hRC = wglCreateContext(GLWin.hDC);
682 : wglMakeCurrent(GLWin.hDC,GLWin.hRC);
683 : #elif defined( UNX )
684 0 : if( !glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx ) ) {
685 : SAL_INFO("slideshow.opengl", "unable to select current GLX context");
686 0 : return false;
687 : }
688 :
689 : int glxMinor, glxMajor;
690 0 : mnGLXVersion = 0;
691 0 : if( glXQueryVersion( GLWin.dpy, &glxMajor, &glxMinor ) )
692 0 : mnGLXVersion = glxMajor + 0.1*glxMinor;
693 : SAL_INFO("slideshow.opengl", "available GLX version: " << mnGLXVersion);
694 :
695 0 : GLWin.GLExtensions = glGetString( GL_EXTENSIONS );
696 : SAL_INFO("slideshow.opengl", "available GL extensions: " << GLWin.GLExtensions);
697 :
698 0 : mbTextureFromPixmap = GLWin.HasGLXExtension( "GLX_EXT_texture_from_pixmap" );
699 0 : mbGenerateMipmap = GLWin.HasGLExtension( "GL_SGIS_generate_mipmap" );
700 :
701 0 : if( GLWin.HasGLXExtension("GLX_SGI_swap_control" ) ) {
702 : // enable vsync
703 : typedef GLint (*glXSwapIntervalProc)(GLint);
704 0 : glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) unx::glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
705 0 : if( glXSwapInterval ) {
706 : int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
707 :
708 : // replace error handler temporarily
709 0 : oldHandler = unx::XSetErrorHandler( oglErrorHandler );
710 :
711 0 : errorTriggered = false;
712 :
713 0 : glXSwapInterval( 1 );
714 :
715 : // sync so that we possibly get an XError
716 0 : unx::glXWaitGL();
717 0 : XSync(GLWin.dpy, false);
718 :
719 0 : if( errorTriggered )
720 : SAL_INFO("slideshow.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
721 : else
722 : SAL_INFO("slideshow.opengl", "set swap interval to 1 (enable vsync)");
723 :
724 : // restore the error handler
725 0 : unx::XSetErrorHandler( oldHandler );
726 : }
727 : }
728 : #endif
729 :
730 0 : glEnable(GL_CULL_FACE);
731 0 : glCullFace(GL_BACK);
732 0 : glClearColor (0, 0, 0, 0);
733 0 : glClear(GL_COLOR_BUFFER_BIT);
734 : #if defined( WNT )
735 : SwapBuffers(GLWin.hDC);
736 : #elif defined( UNX )
737 0 : unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
738 : #endif
739 :
740 0 : glEnable(GL_LIGHTING);
741 0 : GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
742 0 : GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
743 0 : glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
744 0 : glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
745 0 : glEnable(GL_LIGHT0);
746 0 : glEnable(GL_NORMALIZE);
747 :
748 0 : return true;
749 : }
750 :
751 0 : void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
752 : const uno::Reference< rendering::XBitmap >& xEnteringSlide )
753 : {
754 0 : osl::MutexGuard const guard( m_aMutex );
755 :
756 0 : if (isDisposed())
757 0 : return;
758 :
759 0 : mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
760 0 : mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
761 :
762 0 : SlideSize = mxLeavingBitmap->getSize();
763 : SAL_INFO("slideshow.opengl", "leaving bitmap area: " << SlideSize.Width << "x" << SlideSize.Height);
764 0 : SlideSize = mxEnteringBitmap->getSize();
765 0 : SAL_INFO("slideshow.opengl", "entering bitmap area: " << SlideSize.Width << "x" << SlideSize.Height);
766 : }
767 :
768 :
769 0 : void OGLTransitionerImpl::impl_prepareSlides()
770 : {
771 0 : Reference< XFastPropertySet > xLeavingSet( mxLeavingBitmap , UNO_QUERY );
772 0 : Reference< XFastPropertySet > xEnteringSet( mxEnteringBitmap , UNO_QUERY );
773 :
774 0 : geometry::IntegerRectangle2D SlideRect;
775 0 : SlideRect.X1 = 0;
776 0 : SlideRect.X2 = SlideSize.Width;
777 0 : SlideRect.Y1 = 0;
778 0 : SlideRect.Y2 = SlideSize.Height;
779 :
780 : #ifdef UNX
781 0 : unx::glXWaitGL();
782 0 : XSync(GLWin.dpy, false);
783 : #endif
784 :
785 0 : mbUseLeavingPixmap = false;
786 0 : mbUseEnteringPixmap = false;
787 :
788 : #ifdef UNX
789 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
790 :
791 0 : if( mnGLXVersion >= 1.2999 && mbTextureFromPixmap && xLeavingSet.is() && xEnteringSet.is() && mbHasTFPVisual ) {
792 0 : Sequence< Any > leaveArgs;
793 0 : Sequence< Any > enterArgs;
794 0 : if( (xLeavingSet->getFastPropertyValue( 1 ) >>= leaveArgs) &&
795 0 : (xEnteringSet->getFastPropertyValue( 1 ) >>= enterArgs) ) {
796 : SAL_INFO("slideshow.opengl", "pixmaps available");
797 :
798 0 : sal_Int32 depth(0);
799 :
800 0 : leaveArgs[0] >>= mbFreeLeavingPixmap;
801 0 : enterArgs[0] >>= mbFreeEnteringPixmap;
802 0 : leaveArgs[1] >>= maLeavingPixmap;
803 0 : enterArgs[1] >>= maEnteringPixmap;
804 0 : leaveArgs[2] >>= depth;
805 :
806 : int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
807 : GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
808 : GLX_MIPMAP_TEXTURE_EXT, True,
809 0 : None };
810 :
811 :
812 : // sync so that we possibly get an pending XError, before we set our handler.
813 : // this way we will not miss any error from other code
814 0 : unx::glXWaitGL();
815 0 : XSync(GLWin.dpy, false);
816 :
817 : int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
818 :
819 : // replace error handler temporarily
820 0 : oldHandler = unx::XSetErrorHandler( oglErrorHandler );
821 :
822 0 : errorTriggered = false;
823 0 : LeavingPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maLeavingPixmap, pixmapAttribs );
824 :
825 : // sync so that we possibly get an XError
826 0 : unx::glXWaitGL();
827 0 : XSync(GLWin.dpy, false);
828 :
829 0 : if( !errorTriggered )
830 0 : mbUseLeavingPixmap = true;
831 : else {
832 : SAL_INFO("slideshow.opengl", "XError triggered");
833 : OSL_TRACE("XError triggered");
834 0 : if( mbFreeLeavingPixmap ) {
835 0 : unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
836 0 : mbFreeLeavingPixmap = false;
837 : }
838 0 : errorTriggered = false;
839 : }
840 :
841 0 : EnteringPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maEnteringPixmap, pixmapAttribs );
842 :
843 : // sync so that we possibly get an XError
844 0 : unx::glXWaitGL();
845 0 : XSync(GLWin.dpy, false);
846 :
847 : SAL_INFO("slideshow.opengl", "created glx pixmap " << LeavingPixmap << " and " << EnteringPixmap << " depth: " << depth);
848 0 : if( !errorTriggered )
849 0 : mbUseEnteringPixmap = true;
850 : else {
851 : SAL_INFO("slideshow.opengl", "XError triggered");
852 0 : if( mbFreeEnteringPixmap ) {
853 0 : unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
854 0 : mbFreeEnteringPixmap = false;
855 : }
856 : }
857 :
858 : // restore the error handler
859 0 : unx::XSetErrorHandler( oldHandler );
860 0 : }
861 : }
862 :
863 : #endif
864 : #endif
865 0 : if( !mbUseLeavingPixmap )
866 0 : LeavingBytes = mxLeavingBitmap->getData(SlideBitmapLayout,SlideRect);
867 0 : if( !mbUseEnteringPixmap )
868 0 : EnteringBytes = mxEnteringBitmap->getData(SlideBitmapLayout,SlideRect);
869 :
870 : // TODO
871 : #ifdef UNX
872 0 : if(GLWin.ctx)//if we have a rendering context, let's init the slides
873 : #endif
874 0 : GLInitSlides();
875 :
876 : SAL_WARN_IF(SlideBitmapLayout.PlaneStride != 0, "slideshow.opengl","only handle no plane stride now");
877 :
878 : #ifdef UNX
879 : /* flush & sync */
880 0 : unx::glXWaitGL();
881 0 : XSync( GLWin.dpy, false );
882 :
883 : // synchronized X still gives us much smoother play
884 : // I suspect some issues in above code in slideshow
885 : // synchronize whole transition for now
886 0 : XSynchronize( GLWin.dpy, true );
887 0 : mbRestoreSync = true;
888 : #endif
889 0 : }
890 :
891 0 : void OGLTransitionerImpl::impl_prepareTransition()
892 : {
893 0 : if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= cnGLVersion )
894 0 : mpTransition->prepare( GLleavingSlide, GLenteringSlide );
895 0 : }
896 :
897 0 : void OGLTransitionerImpl::impl_finishTransition()
898 : {
899 0 : if( mpTransition && mpTransition->getSettings().mnRequiredGLVersion <= cnGLVersion )
900 0 : mpTransition->finish();
901 0 : }
902 :
903 0 : void OGLTransitionerImpl::setTransition( boost::shared_ptr<OGLTransitionImpl> const pTransition )
904 : {
905 0 : if ( mpTransition ) // already initialized
906 0 : return;
907 :
908 0 : mpTransition = pTransition;
909 :
910 0 : impl_prepareSlides();
911 0 : impl_prepareTransition();
912 : }
913 :
914 0 : void OGLTransitionerImpl::createTexture( unsigned int* texID,
915 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
916 : unx::GLXPixmap pixmap,
917 : bool usePixmap,
918 : #endif
919 : bool useMipmap,
920 : uno::Sequence<sal_Int8>& data,
921 : const OGLFormat* pFormat )
922 : {
923 0 : glDeleteTextures( 1, texID );
924 0 : glGenTextures( 1, texID );
925 0 : glBindTexture( GL_TEXTURE_2D, *texID );
926 0 : glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
927 0 : glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
928 :
929 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
930 0 : unx::PFNGLXBINDTEXIMAGEEXTPROC myglXBindTexImageEXT = (unx::PFNGLXBINDTEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXBindTexImageEXT" );
931 :
932 0 : if( usePixmap ) {
933 0 : if( mbGenerateMipmap )
934 0 : glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, True);
935 0 : myglXBindTexImageEXT (GLWin.dpy, pixmap, GLX_FRONT_LEFT_EXT, NULL);
936 0 : if( mbGenerateMipmap && useMipmap ) {
937 : SAL_INFO("slideshow.opengl", "use mipmaps");
938 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
939 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
940 : } else {
941 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
942 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
943 : }
944 : } else {
945 0 : impl_createTexture( useMipmap, data, pFormat );
946 : }
947 : #else
948 : impl_createTexture( useMipmap, data, pFormat );
949 : #endif
950 : SAL_WARN_IF(!glIsTexture(*texID), "slideshow.opengl", "Can't generate Leaving slide textures in OpenGL");
951 0 : }
952 :
953 : namespace
954 : {
955 0 : class OGLColorSpace : public cppu::WeakImplHelper1< com::sun::star::rendering::XIntegerBitmapColorSpace >
956 : {
957 : private:
958 : uno::Sequence< sal_Int8 > maComponentTags;
959 : uno::Sequence< sal_Int32 > maBitCounts;
960 :
961 0 : virtual ::sal_Int8 SAL_CALL getType( ) throw (uno::RuntimeException)
962 : {
963 0 : return rendering::ColorSpaceType::RGB;
964 : }
965 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
966 : {
967 0 : return maComponentTags;
968 : }
969 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
970 : {
971 0 : return rendering::RenderingIntent::PERCEPTUAL;
972 : }
973 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
974 : {
975 0 : return uno::Sequence< beans::PropertyValue >();
976 : }
977 0 : virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
978 : const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
979 : uno::RuntimeException)
980 : {
981 : // TODO(P3): if we know anything about target
982 : // colorspace, this can be greatly sped up
983 : uno::Sequence<rendering::ARGBColor> aIntermediate(
984 0 : convertToARGB(deviceColor));
985 0 : return targetColorSpace->convertFromARGB(aIntermediate);
986 : }
987 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
988 : {
989 0 : const double* pIn( deviceColor.getConstArray() );
990 0 : const sal_Size nLen( deviceColor.getLength() );
991 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
992 : "number of channels no multiple of 4",
993 : static_cast<rendering::XColorSpace*>(this), 0);
994 :
995 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
996 0 : rendering::RGBColor* pOut( aRes.getArray() );
997 0 : for( sal_Size i=0; i<nLen; i+=4 )
998 : {
999 0 : *pOut++ = rendering::RGBColor(pIn[0],pIn[1],pIn[2]);
1000 0 : pIn += 4;
1001 : }
1002 0 : return aRes;
1003 : }
1004 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1005 : {
1006 0 : const double* pIn( deviceColor.getConstArray() );
1007 0 : const sal_Size nLen( deviceColor.getLength() );
1008 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
1009 : "number of channels no multiple of 4",
1010 : static_cast<rendering::XColorSpace*>(this), 0);
1011 :
1012 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1013 0 : rendering::ARGBColor* pOut( aRes.getArray() );
1014 0 : for( sal_Size i=0; i<nLen; i+=4 )
1015 : {
1016 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[0],pIn[1],pIn[2]);
1017 0 : pIn += 4;
1018 : }
1019 0 : return aRes;
1020 : }
1021 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1022 : {
1023 0 : const double* pIn( deviceColor.getConstArray() );
1024 0 : const sal_Size nLen( deviceColor.getLength() );
1025 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
1026 : "number of channels no multiple of 4",
1027 : static_cast<rendering::XColorSpace*>(this), 0);
1028 :
1029 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1030 0 : rendering::ARGBColor* pOut( aRes.getArray() );
1031 0 : for( sal_Size i=0; i<nLen; i+=4 )
1032 : {
1033 0 : *pOut++ = rendering::ARGBColor(pIn[3],pIn[3]*pIn[0],pIn[3]*pIn[1],pIn[3]*pIn[2]);
1034 0 : pIn += 4;
1035 : }
1036 0 : return aRes;
1037 : }
1038 0 : virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1039 : {
1040 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
1041 0 : const sal_Size nLen( rgbColor.getLength() );
1042 :
1043 0 : uno::Sequence< double > aRes(nLen*4);
1044 0 : double* pColors=aRes.getArray();
1045 0 : for( sal_Size i=0; i<nLen; ++i )
1046 : {
1047 0 : *pColors++ = pIn->Red;
1048 0 : *pColors++ = pIn->Green;
1049 0 : *pColors++ = pIn->Blue;
1050 0 : *pColors++ = 1.0;
1051 0 : ++pIn;
1052 : }
1053 0 : return aRes;
1054 : }
1055 0 : virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1056 : {
1057 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1058 0 : const sal_Size nLen( rgbColor.getLength() );
1059 :
1060 0 : uno::Sequence< double > aRes(nLen*4);
1061 0 : double* pColors=aRes.getArray();
1062 0 : for( sal_Size i=0; i<nLen; ++i )
1063 : {
1064 0 : *pColors++ = pIn->Red;
1065 0 : *pColors++ = pIn->Green;
1066 0 : *pColors++ = pIn->Blue;
1067 0 : *pColors++ = pIn->Alpha;
1068 0 : ++pIn;
1069 : }
1070 0 : return aRes;
1071 : }
1072 0 : virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1073 : {
1074 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1075 0 : const sal_Size nLen( rgbColor.getLength() );
1076 :
1077 0 : uno::Sequence< double > aRes(nLen*4);
1078 0 : double* pColors=aRes.getArray();
1079 0 : for( sal_Size i=0; i<nLen; ++i )
1080 : {
1081 0 : *pColors++ = pIn->Red/pIn->Alpha;
1082 0 : *pColors++ = pIn->Green/pIn->Alpha;
1083 0 : *pColors++ = pIn->Blue/pIn->Alpha;
1084 0 : *pColors++ = pIn->Alpha;
1085 0 : ++pIn;
1086 : }
1087 0 : return aRes;
1088 : }
1089 :
1090 : // XIntegerBitmapColorSpace
1091 0 : virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) throw (uno::RuntimeException)
1092 : {
1093 0 : return 32;
1094 : }
1095 0 : virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
1096 : {
1097 0 : return maBitCounts;
1098 : }
1099 0 : virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
1100 : {
1101 0 : return util::Endianness::LITTLE;
1102 : }
1103 0 : virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1104 : const uno::Reference< rendering::XColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
1105 : uno::RuntimeException)
1106 : {
1107 0 : if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
1108 : {
1109 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
1110 0 : const sal_Size nLen( deviceColor.getLength() );
1111 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
1112 : "number of channels no multiple of 4",
1113 : static_cast<rendering::XColorSpace*>(this), 0);
1114 :
1115 0 : uno::Sequence<double> aRes(nLen);
1116 0 : double* pOut( aRes.getArray() );
1117 0 : for( sal_Size i=0; i<nLen; i+=4 )
1118 : {
1119 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1120 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1121 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1122 0 : *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1123 : }
1124 0 : return aRes;
1125 : }
1126 : else
1127 : {
1128 : // TODO(P3): if we know anything about target
1129 : // colorspace, this can be greatly sped up
1130 : uno::Sequence<rendering::ARGBColor> aIntermediate(
1131 0 : convertIntegerToARGB(deviceColor));
1132 0 : return targetColorSpace->convertFromARGB(aIntermediate);
1133 : }
1134 : }
1135 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1136 : const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) throw (lang::IllegalArgumentException,
1137 : uno::RuntimeException)
1138 : {
1139 0 : if( dynamic_cast<OGLColorSpace*>(targetColorSpace.get()) )
1140 : {
1141 : // it's us, so simply pass-through the data
1142 0 : return deviceColor;
1143 : }
1144 : else
1145 : {
1146 : // TODO(P3): if we know anything about target
1147 : // colorspace, this can be greatly sped up
1148 : uno::Sequence<rendering::ARGBColor> aIntermediate(
1149 0 : convertIntegerToARGB(deviceColor));
1150 0 : return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1151 : }
1152 : }
1153 0 : virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1154 : {
1155 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
1156 0 : const sal_Size nLen( deviceColor.getLength() );
1157 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
1158 : "number of channels no multiple of 4",
1159 : static_cast<rendering::XColorSpace*>(this), 0);
1160 :
1161 0 : uno::Sequence< rendering::RGBColor > aRes(nLen/4);
1162 0 : rendering::RGBColor* pOut( aRes.getArray() );
1163 0 : for( sal_Size i=0; i<nLen; i+=4 )
1164 : {
1165 : *pOut++ = rendering::RGBColor(
1166 0 : vcl::unotools::toDoubleColor(pIn[0]),
1167 0 : vcl::unotools::toDoubleColor(pIn[1]),
1168 0 : vcl::unotools::toDoubleColor(pIn[2]));
1169 0 : pIn += 4;
1170 : }
1171 0 : return aRes;
1172 : }
1173 :
1174 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1175 : {
1176 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
1177 0 : const sal_Size nLen( deviceColor.getLength() );
1178 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
1179 : "number of channels no multiple of 4",
1180 : static_cast<rendering::XColorSpace*>(this), 0);
1181 :
1182 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1183 0 : rendering::ARGBColor* pOut( aRes.getArray() );
1184 0 : for( sal_Size i=0; i<nLen; i+=4 )
1185 : {
1186 : *pOut++ = rendering::ARGBColor(
1187 0 : vcl::unotools::toDoubleColor(pIn[3]),
1188 0 : vcl::unotools::toDoubleColor(pIn[0]),
1189 0 : vcl::unotools::toDoubleColor(pIn[1]),
1190 0 : vcl::unotools::toDoubleColor(pIn[2]));
1191 0 : pIn += 4;
1192 : }
1193 0 : return aRes;
1194 : }
1195 :
1196 0 : virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1197 : {
1198 0 : const sal_Int8* pIn( deviceColor.getConstArray() );
1199 0 : const sal_Size nLen( deviceColor.getLength() );
1200 0 : ENSURE_ARG_OR_THROW2(nLen%4==0,
1201 : "number of channels no multiple of 4",
1202 : static_cast<rendering::XColorSpace*>(this), 0);
1203 :
1204 0 : uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1205 0 : rendering::ARGBColor* pOut( aRes.getArray() );
1206 0 : for( sal_Size i=0; i<nLen; i+=4 )
1207 : {
1208 0 : const sal_Int8 nAlpha( pIn[3] );
1209 : *pOut++ = rendering::ARGBColor(
1210 0 : vcl::unotools::toDoubleColor(nAlpha),
1211 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[0]),
1212 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[1]),
1213 0 : vcl::unotools::toDoubleColor(nAlpha*pIn[2]));
1214 0 : pIn += 4;
1215 : }
1216 0 : return aRes;
1217 : }
1218 :
1219 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1220 : {
1221 0 : const rendering::RGBColor* pIn( rgbColor.getConstArray() );
1222 0 : const sal_Size nLen( rgbColor.getLength() );
1223 :
1224 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
1225 0 : sal_Int8* pColors=aRes.getArray();
1226 0 : for( sal_Size i=0; i<nLen; ++i )
1227 : {
1228 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
1229 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
1230 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
1231 0 : *pColors++ = 255;
1232 0 : ++pIn;
1233 : }
1234 0 : return aRes;
1235 : }
1236 :
1237 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1238 : {
1239 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1240 0 : const sal_Size nLen( rgbColor.getLength() );
1241 :
1242 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
1243 0 : sal_Int8* pColors=aRes.getArray();
1244 0 : for( sal_Size i=0; i<nLen; ++i )
1245 : {
1246 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red);
1247 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green);
1248 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
1249 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
1250 0 : ++pIn;
1251 : }
1252 0 : return aRes;
1253 : }
1254 :
1255 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) throw (lang::IllegalArgumentException, uno::RuntimeException)
1256 : {
1257 0 : const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1258 0 : const sal_Size nLen( rgbColor.getLength() );
1259 :
1260 0 : uno::Sequence< sal_Int8 > aRes(nLen*4);
1261 0 : sal_Int8* pColors=aRes.getArray();
1262 0 : for( sal_Size i=0; i<nLen; ++i )
1263 : {
1264 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Red/pIn->Alpha);
1265 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Green/pIn->Alpha);
1266 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Blue/pIn->Alpha);
1267 0 : *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
1268 0 : ++pIn;
1269 : }
1270 0 : return aRes;
1271 : }
1272 :
1273 : public:
1274 0 : OGLColorSpace() :
1275 : maComponentTags(4),
1276 0 : maBitCounts(4)
1277 : {
1278 0 : sal_Int8* pTags = maComponentTags.getArray();
1279 0 : sal_Int32* pBitCounts = maBitCounts.getArray();
1280 0 : pTags[0] = rendering::ColorComponentTag::RGB_RED;
1281 0 : pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
1282 0 : pTags[2] = rendering::ColorComponentTag::RGB_BLUE;
1283 0 : pTags[3] = rendering::ColorComponentTag::ALPHA;
1284 :
1285 : pBitCounts[0] =
1286 0 : pBitCounts[1] =
1287 0 : pBitCounts[2] =
1288 0 : pBitCounts[3] = 8;
1289 0 : }
1290 : };
1291 :
1292 : struct OGLColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>, OGLColorSpaceHolder>
1293 : {
1294 0 : uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
1295 : {
1296 0 : return new OGLColorSpace();
1297 : }
1298 : };
1299 :
1300 : uno::Reference<rendering::XIntegerBitmapColorSpace>
1301 0 : getOGLColorSpace()
1302 : {
1303 0 : return OGLColorSpaceHolder::get();
1304 : }
1305 : }
1306 :
1307 0 : void OGLTransitionerImpl::impl_createTexture(
1308 : bool useMipmap,
1309 : uno::Sequence<sal_Int8>& data,
1310 : const OGLFormat* pFormat )
1311 : {
1312 0 : if( !pFormat )
1313 : {
1314 : // force-convert color to ARGB8888 int color space
1315 : uno::Sequence<sal_Int8> tempBytes(
1316 0 : SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
1317 : data,
1318 0 : getOGLColorSpace()));
1319 : gluBuild2DMipmaps(GL_TEXTURE_2D,
1320 : 4,
1321 : SlideSize.Width,
1322 : SlideSize.Height,
1323 : GL_RGBA,
1324 : GL_UNSIGNED_BYTE,
1325 0 : &tempBytes[0]);
1326 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
1327 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
1328 :
1329 : //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
1330 : GLfloat largest_supported_anisotropy;
1331 0 : glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
1332 0 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
1333 : } else {
1334 0 : if( mpTransition && !cbBrokenTexturesATI && !useMipmap) {
1335 0 : glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
1336 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
1337 0 : glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
1338 : } else {
1339 0 : gluBuild2DMipmaps( GL_TEXTURE_2D, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
1340 0 : glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1341 0 : glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); //TRILINEAR FILTERING
1342 :
1343 : //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
1344 : GLfloat largest_supported_anisotropy;
1345 0 : glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
1346 0 : glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
1347 : }
1348 : }
1349 0 : }
1350 :
1351 0 : void OGLTransitionerImpl::prepareEnvironment()
1352 : {
1353 0 : glMatrixMode(GL_PROJECTION);
1354 0 : glLoadIdentity();
1355 0 : double EyePos(10.0);
1356 0 : double RealF(1.0);
1357 0 : double RealN(-1.0);
1358 0 : double RealL(-1.0);
1359 0 : double RealR(1.0);
1360 0 : double RealB(-1.0);
1361 0 : double RealT(1.0);
1362 0 : double ClipN(EyePos+5.0*RealN);
1363 0 : double ClipF(EyePos+15.0*RealF);
1364 0 : double ClipL(RealL*8.0);
1365 0 : double ClipR(RealR*8.0);
1366 0 : double ClipB(RealB*8.0);
1367 0 : double ClipT(RealT*8.0);
1368 : //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.
1369 : glScaled( 1.0 / ( ( ( RealR * 2.0 * ClipN ) / ( EyePos * ( ClipR - ClipL ) ) ) - ( ( ClipR + ClipL ) / ( ClipR - ClipL ) ) ),
1370 : 1.0 / ( ( ( RealT * 2.0 * ClipN ) / ( EyePos * ( ClipT - ClipB ) ) ) - ( ( ClipT + ClipB ) / ( ClipT - ClipB ) ) ),
1371 0 : 1.0 );
1372 0 : glFrustum(ClipL,ClipR,ClipB,ClipT,ClipN,ClipF);
1373 0 : glMatrixMode(GL_MODELVIEW);
1374 0 : glLoadIdentity();
1375 0 : glTranslated(0,0,-EyePos);
1376 0 : }
1377 :
1378 0 : const OGLFormat* OGLTransitionerImpl::chooseFormats()
1379 : {
1380 0 : const OGLFormat* pDetectedFormat=NULL;
1381 : uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
1382 0 : SlideBitmapLayout.ColorSpace);
1383 :
1384 0 : if( (xIntColorSpace->getType() == rendering::ColorSpaceType::RGB ||
1385 0 : xIntColorSpace->getType() == rendering::ColorSpaceType::SRGB) )
1386 : {
1387 : /* table for canvas->OGL format mapping. outer index is number
1388 : of color components (0:3, 1:4), then comes bits per pixel
1389 : (0:16, 1:24, 2:32), then channel ordering: (0:rgba, 1:bgra,
1390 : 2:argb, 3:abgr)
1391 : */
1392 : static const OGLFormat lcl_RGB24[] =
1393 : {
1394 : // 24 bit RGB
1395 : {3, GL_BGR, GL_UNSIGNED_BYTE},
1396 : {3, GL_RGB, GL_UNSIGNED_BYTE},
1397 : {3, GL_BGR, GL_UNSIGNED_BYTE},
1398 : {3, GL_RGB, GL_UNSIGNED_BYTE}
1399 : };
1400 :
1401 : #if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
1402 : // more format constants available
1403 : static const OGLFormat lcl_RGB16[] =
1404 : {
1405 : // 16 bit RGB
1406 : {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
1407 : {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
1408 : {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
1409 : {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
1410 : };
1411 :
1412 : static const OGLFormat lcl_ARGB16_4[] =
1413 : {
1414 : // 16 bit ARGB
1415 : {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
1416 : {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
1417 : {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
1418 : {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
1419 : };
1420 :
1421 : static const OGLFormat lcl_ARGB16_5[] =
1422 : {
1423 : // 16 bit ARGB
1424 : {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
1425 : {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
1426 : {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
1427 : {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
1428 : };
1429 :
1430 : static const OGLFormat lcl_ARGB32[] =
1431 : {
1432 : // 32 bit ARGB
1433 : {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
1434 : {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
1435 : {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
1436 : {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
1437 : };
1438 :
1439 : const uno::Sequence<sal_Int8> aComponentTags(
1440 0 : xIntColorSpace->getComponentTags());
1441 : const uno::Sequence<sal_Int32> aComponentBitcounts(
1442 0 : xIntColorSpace->getComponentBitCounts());
1443 0 : const sal_Int32 nNumComponents( aComponentBitcounts.getLength() );
1444 0 : const sal_Int32 nBitsPerPixel( xIntColorSpace->getBitsPerPixel() );
1445 :
1446 : // supported component ordering?
1447 : const int nComponentOrderIndex(
1448 0 : calcComponentOrderIndex(aComponentTags));
1449 0 : if( nComponentOrderIndex != -1 )
1450 : {
1451 0 : switch( nBitsPerPixel )
1452 : {
1453 : case 16:
1454 0 : if( nNumComponents == 3 )
1455 : {
1456 0 : pDetectedFormat = &lcl_RGB16[nComponentOrderIndex];
1457 : }
1458 0 : else if( nNumComponents == 4 )
1459 : {
1460 0 : if( aComponentBitcounts[1] == 4 )
1461 : {
1462 0 : pDetectedFormat = &lcl_ARGB16_4[nComponentOrderIndex];
1463 : }
1464 0 : else if( aComponentBitcounts[1] == 5 )
1465 : {
1466 0 : pDetectedFormat = &lcl_ARGB16_5[nComponentOrderIndex];
1467 : }
1468 : }
1469 0 : break;
1470 : case 24:
1471 0 : if( nNumComponents == 3 )
1472 : {
1473 0 : pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
1474 : }
1475 0 : break;
1476 : case 32:
1477 0 : if ( nNumComponents == 4 )
1478 : {
1479 0 : pDetectedFormat = &lcl_ARGB32[nComponentOrderIndex];
1480 : }
1481 0 : break;
1482 : }
1483 0 : }
1484 : #else
1485 : const uno::Sequence<sal_Int8> aComponentTags(
1486 : xIntColorSpace->getComponentTags());
1487 : const int nComponentOrderIndex(calcComponentOrderIndex(aComponentTags));
1488 : if( aComponentTags.getLength() == 3 &&
1489 : nComponentOrderIndex != -1 &&
1490 : xIntColorSpace->getBitsPerPixel() == 24 )
1491 : {
1492 : pDetectedFormat = &lcl_RGB24[nComponentOrderIndex];
1493 : }
1494 : #endif
1495 : }
1496 :
1497 0 : return pDetectedFormat;
1498 : }
1499 :
1500 0 : void OGLTransitionerImpl::GLInitSlides()
1501 : {
1502 0 : osl::MutexGuard const guard( m_aMutex );
1503 :
1504 0 : if (isDisposed() || mpTransition->getSettings().mnRequiredGLVersion > cnGLVersion)
1505 0 : return;
1506 :
1507 : #if OSL_DEBUG_LEVEL > 1
1508 : TimerContext aTimerContext("texture creation");
1509 : #endif
1510 :
1511 0 : prepareEnvironment();
1512 :
1513 0 : const OGLFormat* pFormat = NULL;
1514 0 : if( !mbUseLeavingPixmap || !mbUseEnteringPixmap )
1515 0 : pFormat = chooseFormats();
1516 :
1517 : createTexture( &GLleavingSlide,
1518 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
1519 : LeavingPixmap,
1520 : mbUseLeavingPixmap,
1521 : #endif
1522 0 : mpTransition->getSettings().mbUseMipMapLeaving,
1523 : LeavingBytes,
1524 0 : pFormat );
1525 :
1526 : createTexture( &GLenteringSlide,
1527 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
1528 : EnteringPixmap,
1529 : mbUseEnteringPixmap,
1530 : #endif
1531 0 : mpTransition->getSettings().mbUseMipMapEntering,
1532 : EnteringBytes,
1533 0 : pFormat );
1534 :
1535 : #ifdef UNX
1536 0 : unx::glXWaitGL();
1537 0 : XSync(GLWin.dpy, false);
1538 : #endif
1539 : }
1540 :
1541 0 : void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException)
1542 : {
1543 : #if OSL_DEBUG_LEVEL > 1
1544 : mnFrameCount ++;
1545 : maUpdateStartTime = microsec_clock::local_time();
1546 : if( mnFrameCount == 1 ) {
1547 : maStartTime = maUpdateStartTime;
1548 : maTotalUpdateDuration = seconds (0);
1549 : }
1550 : #endif
1551 0 : osl::MutexGuard const guard( m_aMutex );
1552 :
1553 0 : if (isDisposed() || !cbGLXPresent || mpTransition->getSettings().mnRequiredGLVersion > cnGLVersion)
1554 0 : return;
1555 :
1556 : #ifdef WNT
1557 : wglMakeCurrent(GLWin.hDC,GLWin.hRC);
1558 : #endif
1559 : #ifdef UNX
1560 0 : glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
1561 : #endif
1562 :
1563 0 : glEnable(GL_DEPTH_TEST);
1564 0 : glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1565 :
1566 0 : if(mpTransition)
1567 : mpTransition->display( nTime, GLleavingSlide, GLenteringSlide,
1568 : SlideSize.Width, SlideSize.Height,
1569 : static_cast<double>(GLWin.Width),
1570 0 : static_cast<double>(GLWin.Height) );
1571 :
1572 : #if defined( WNT )
1573 : SwapBuffers(GLWin.hDC);
1574 : #elif defined( UNX )
1575 0 : unx::glXSwapBuffers(GLWin.dpy, GLWin.win);
1576 : #endif
1577 0 : if( pWindow )
1578 0 : pWindow->Show();
1579 :
1580 : #ifdef UNX
1581 : /* flush & sync */
1582 0 : unx::glXWaitGL();
1583 0 : XSync( GLWin.dpy, false );
1584 : #endif
1585 :
1586 : #if OSL_DEBUG_LEVEL > 1
1587 : maUpdateEndTime = microsec_clock::local_time();
1588 :
1589 : SAL_INFO("slideshow.opengl", "update time: " << nTime);
1590 : SAL_INFO("slideshow.opengl", "update took: " << ( maUpdateEndTime - maUpdateStartTime ));
1591 : maTotalUpdateDuration += (maUpdateEndTime - maUpdateStartTime);
1592 : #endif
1593 : }
1594 :
1595 0 : void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
1596 : const Reference< rendering::XBitmap >& rLeavingBitmap,
1597 : const Reference< rendering::XBitmap >& rEnteringBitmap )
1598 : throw (uno::RuntimeException)
1599 : {
1600 : SAL_INFO("slideshow.opengl", "transitioner: view changed");
1601 :
1602 0 : impl_finishTransition();
1603 0 : disposeTextures();
1604 0 : disposeContextAndWindow();
1605 :
1606 0 : initWindowFromSlideShowView( rView );
1607 0 : setSlides( rLeavingBitmap, rEnteringBitmap );
1608 0 : impl_prepareSlides();
1609 0 : impl_prepareTransition();
1610 0 : }
1611 :
1612 0 : void OGLTransitionerImpl::disposeContextAndWindow()
1613 : {
1614 : #if defined( WNT )
1615 : if (GLWin.hRC)
1616 : {
1617 : wglMakeCurrent( GLWin.hDC, 0 ); // kill Device Context
1618 : wglDeleteContext( GLWin.hRC ); // Kill Render Context
1619 : ReleaseDC( GLWin.hWnd, GLWin.hDC ); // Release Window
1620 : }
1621 : #elif defined( UNX )
1622 0 : if(GLWin.ctx)
1623 : {
1624 0 : glXMakeCurrent(GLWin.dpy, None, NULL);
1625 0 : if( glGetError() != GL_NO_ERROR ) {
1626 : SAL_INFO("slideshow.opengl", "glError: " << (char *)gluErrorString(glGetError()));
1627 : }
1628 0 : glXDestroyContext(GLWin.dpy, GLWin.ctx);
1629 0 : GLWin.ctx = NULL;
1630 : }
1631 : #endif
1632 0 : if( pWindow ) {
1633 0 : delete pWindow;
1634 0 : pWindow = NULL;
1635 0 : GLWin.win = 0;
1636 : }
1637 0 : }
1638 :
1639 0 : void OGLTransitionerImpl::disposeTextures()
1640 : {
1641 : #ifdef WNT
1642 : wglMakeCurrent(GLWin.hDC,GLWin.hRC);
1643 : #endif
1644 : #ifdef UNX
1645 0 : glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
1646 : #endif
1647 :
1648 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
1649 0 : unx::PFNGLXRELEASETEXIMAGEEXTPROC myglXReleaseTexImageEXT = (unx::PFNGLXRELEASETEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXReleaseTexImageEXT" );
1650 0 : if( mbUseLeavingPixmap ) {
1651 0 : myglXReleaseTexImageEXT( GLWin.dpy, LeavingPixmap, GLX_FRONT_LEFT_EXT );
1652 0 : glXDestroyGLXPixmap( GLWin.dpy, LeavingPixmap );
1653 0 : LeavingPixmap = 0;
1654 0 : if( mbFreeLeavingPixmap ) {
1655 0 : unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
1656 0 : mbFreeLeavingPixmap = false;
1657 0 : maLeavingPixmap = 0;
1658 : }
1659 : }
1660 0 : if( mbUseEnteringPixmap ) {
1661 0 : myglXReleaseTexImageEXT( GLWin.dpy, EnteringPixmap, GLX_FRONT_LEFT_EXT );
1662 0 : glXDestroyGLXPixmap( GLWin.dpy, EnteringPixmap );
1663 0 : EnteringPixmap = 0;
1664 0 : if( mbFreeEnteringPixmap ) {
1665 0 : unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
1666 0 : mbFreeEnteringPixmap = false;
1667 0 : maEnteringPixmap = 0;
1668 : }
1669 : }
1670 : #endif
1671 :
1672 0 : if( !mbUseLeavingPixmap ) {
1673 0 : glDeleteTextures(1,&GLleavingSlide);
1674 0 : GLleavingSlide = 0;
1675 : }
1676 0 : if( !mbUseEnteringPixmap ) {
1677 0 : glDeleteTextures(1,&GLenteringSlide);
1678 0 : GLleavingSlide = 0;
1679 : }
1680 :
1681 0 : mbUseLeavingPixmap = false;
1682 0 : mbUseEnteringPixmap = false;
1683 0 : }
1684 :
1685 : // we are about to be disposed (someone call dispose() on us)
1686 0 : void OGLTransitionerImpl::disposing()
1687 : {
1688 0 : osl::MutexGuard const guard( m_aMutex );
1689 :
1690 : #if OSL_DEBUG_LEVEL > 1
1691 : SAL_INFO("slideshow.opengl", "dispose " << this);
1692 : if( mnFrameCount ) {
1693 : maEndTime = microsec_clock::local_time();
1694 : time_duration duration = maEndTime - maStartTime;
1695 : SAL_INFO("slideshow.opengl",
1696 : "whole transition (frames: " << mnFrameCount
1697 : << ") took: " << duration
1698 : << " fps: "
1699 : << (((double)mnFrameCount*1000000000.0)/duration.total_nanoseconds())
1700 : << " time spent in updates: " << maTotalUpdateDuration
1701 : << " percentage of transition time: "
1702 : << (100*(((double)maTotalUpdateDuration.total_nanoseconds())/((double)duration.total_nanoseconds())))
1703 : << '%'
1704 : );
1705 : }
1706 : #endif
1707 :
1708 0 : if( pWindow ) {
1709 0 : impl_finishTransition();
1710 0 : disposeTextures();
1711 :
1712 : #ifdef UNX
1713 0 : if( mbRestoreSync ) {
1714 : // try to reestablish synchronize state
1715 0 : char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
1716 0 : XSynchronize( GLWin.dpy, sal_synchronize && *sal_synchronize == '1' );
1717 : }
1718 : #endif
1719 :
1720 0 : disposeContextAndWindow();
1721 : }
1722 :
1723 0 : mpTransition.reset();
1724 :
1725 0 : mxLeavingBitmap.clear();
1726 0 : mxEnteringBitmap.clear();
1727 0 : mxView.clear();
1728 0 : }
1729 :
1730 0 : OGLTransitionerImpl::OGLTransitionerImpl() :
1731 : OGLTransitionerImplBase(m_aMutex),
1732 : GLWin(),
1733 : GLleavingSlide( 0 ),
1734 : GLenteringSlide( 0 ),
1735 : pWindow( NULL ),
1736 : mxView(),
1737 : EnteringBytes(),
1738 : LeavingBytes(),
1739 : mbRestoreSync( false ),
1740 : mbUseLeavingPixmap( false ),
1741 : mbUseEnteringPixmap( false ),
1742 : SlideBitmapLayout(),
1743 0 : SlideSize()
1744 : {
1745 : #if defined( WNT )
1746 : GLWin.hWnd = 0;
1747 : #elif defined( UNX )
1748 0 : GLWin.ctx = 0;
1749 : #endif
1750 :
1751 : #if OSL_DEBUG_LEVEL > 1
1752 : mnFrameCount = 0;
1753 : #endif
1754 0 : }
1755 :
1756 : typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
1757 :
1758 0 : class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
1759 : {
1760 : public:
1761 0 : explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) :
1762 0 : OGLTransitionFactoryImplBase(m_aMutex)
1763 0 : {}
1764 :
1765 : // XTransitionFactory
1766 0 : virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException)
1767 : {
1768 0 : if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1769 0 : switch( transitionSubType )
1770 : {
1771 : case animations::TransitionSubType::ACROSS:
1772 : case animations::TransitionSubType::CORNERSOUT:
1773 : case animations::TransitionSubType::CIRCLE:
1774 : case animations::TransitionSubType::FANOUTHORIZONTAL:
1775 : case animations::TransitionSubType::CORNERSIN:
1776 : case animations::TransitionSubType::LEFTTORIGHT:
1777 : case animations::TransitionSubType::TOPTOBOTTOM:
1778 : case animations::TransitionSubType::TOPRIGHT:
1779 : case animations::TransitionSubType::TOPLEFT:
1780 : case animations::TransitionSubType::BOTTOMRIGHT:
1781 : case animations::TransitionSubType::BOTTOMLEFT:
1782 : case animations::TransitionSubType::TOPCENTER:
1783 : case animations::TransitionSubType::RIGHTCENTER:
1784 : case animations::TransitionSubType::BOTTOMCENTER:
1785 0 : return sal_True;
1786 :
1787 : default:
1788 0 : return sal_False;
1789 : }
1790 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1791 0 : return sal_True;
1792 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1793 0 : return sal_True;
1794 0 : } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1795 0 : return sal_True;
1796 0 : } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1797 0 : return sal_True;
1798 : } else
1799 0 : return sal_False;
1800 : }
1801 :
1802 0 : virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
1803 : ::sal_Int16 transitionType,
1804 : ::sal_Int16 transitionSubType,
1805 : const uno::Reference< presentation::XSlideShowView >& view,
1806 : const uno::Reference< rendering::XBitmap >& leavingBitmap,
1807 : const uno::Reference< rendering::XBitmap >& enteringBitmap )
1808 : throw (uno::RuntimeException)
1809 : {
1810 0 : if( !hasTransition( transitionType, transitionSubType ) )
1811 0 : return uno::Reference< presentation::XTransition >();
1812 :
1813 0 : rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() );
1814 0 : if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) )
1815 0 : return uno::Reference< presentation::XTransition >();
1816 :
1817 0 : if( OGLTransitionerImpl::cbMesa && (
1818 : ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) ||
1819 : ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) ||
1820 : ( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) ) )
1821 0 : return uno::Reference< presentation::XTransition >();
1822 :
1823 0 : boost::shared_ptr<OGLTransitionImpl> pTransition;
1824 :
1825 0 : if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1826 0 : switch( transitionSubType )
1827 : {
1828 : case animations::TransitionSubType::ACROSS:
1829 0 : pTransition = makeNByMTileFlip(8,6);
1830 0 : break;
1831 : case animations::TransitionSubType::CORNERSOUT:
1832 0 : pTransition = makeOutsideCubeFaceToLeft();
1833 0 : break;
1834 : case animations::TransitionSubType::CIRCLE:
1835 0 : pTransition = makeRevolvingCircles(8,128);
1836 0 : break;
1837 : case animations::TransitionSubType::FANOUTHORIZONTAL:
1838 0 : pTransition = makeHelix(20);
1839 0 : break;
1840 : case animations::TransitionSubType::CORNERSIN:
1841 0 : pTransition = makeInsideCubeFaceToLeft();
1842 0 : break;
1843 : case animations::TransitionSubType::LEFTTORIGHT:
1844 0 : pTransition = makeFallLeaving();
1845 0 : break;
1846 : case animations::TransitionSubType::TOPTOBOTTOM:
1847 0 : pTransition = makeTurnAround();
1848 0 : break;
1849 : case animations::TransitionSubType::TOPRIGHT:
1850 0 : pTransition = makeTurnDown();
1851 0 : break;
1852 : case animations::TransitionSubType::TOPLEFT:
1853 0 : pTransition = makeIris();
1854 0 : break;
1855 : case animations::TransitionSubType::BOTTOMRIGHT:
1856 0 : pTransition = makeRochade();
1857 0 : break;
1858 : case animations::TransitionSubType::BOTTOMLEFT:
1859 0 : pTransition = makeVenetianBlinds( true, 8 );
1860 0 : break;
1861 : case animations::TransitionSubType::TOPCENTER:
1862 0 : pTransition = makeVenetianBlinds( false, 6 );
1863 0 : break;
1864 : case animations::TransitionSubType::RIGHTCENTER:
1865 0 : pTransition = makeStatic();
1866 0 : break;
1867 : case animations::TransitionSubType::BOTTOMCENTER:
1868 0 : pTransition = makeDissolve();
1869 0 : break;
1870 : }
1871 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1872 0 : pTransition = makeFadeSmoothly();
1873 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1874 0 : pTransition = makeFadeThroughBlack();
1875 0 : } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1876 0 : pTransition = makeDiamond();
1877 0 : } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1878 0 : pTransition = makeNewsflash();
1879 : }
1880 :
1881 0 : if ( !pTransition )
1882 0 : return uno::Reference< presentation::XTransition >();
1883 :
1884 0 : xRes->setTransition( pTransition );
1885 :
1886 0 : return uno::Reference<presentation::XTransition>(xRes.get());
1887 : }
1888 : };
1889 :
1890 : }
1891 :
1892 : namespace sdecl = comphelper::service_decl;
1893 0 : const sdecl::ServiceDecl OGLTransitionFactoryDecl(
1894 : sdecl::class_<OGLTransitionFactoryImpl>(),
1895 : "com.sun.star.comp.presentation.OGLTransitionFactory",
1896 0 : "com.sun.star.presentation.TransitionFactory" );
1897 :
1898 : // The C shared lib entry points
1899 0 : COMPHELPER_SERVICEDECL_EXPORTS1(ogltrans, OGLTransitionFactoryDecl)
1900 :
1901 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|