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