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 <sal/types.h>
33 :
34 : #include <com/sun/star/beans/XFastPropertySet.hpp>
35 : #include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
36 : #include <com/sun/star/rendering/ColorComponentTag.hpp>
37 : #include <com/sun/star/rendering/ColorSpaceType.hpp>
38 : #include <com/sun/star/rendering/RenderingIntent.hpp>
39 : #include <com/sun/star/util/Endianness.hpp>
40 : #include <com/sun/star/animations/TransitionType.hpp>
41 : #undef IN
42 : #undef OUT
43 : #include <com/sun/star/animations/TransitionSubType.hpp>
44 : #include <com/sun/star/presentation/XTransitionFactory.hpp>
45 : #include <com/sun/star/presentation/XTransition.hpp>
46 : #include <com/sun/star/presentation/XSlideShowView.hpp>
47 : #include <com/sun/star/uno/XComponentContext.hpp>
48 : #include <com/sun/star/rendering/XIntegerBitmap.hpp>
49 : #include <com/sun/star/geometry/IntegerSize2D.hpp>
50 :
51 : #include <cppuhelper/compbase1.hxx>
52 : #include <cppuhelper/basemutex.hxx>
53 : #include <cppuhelper/factory.hxx>
54 : #include <rtl/ref.hxx>
55 :
56 : #include <comphelper/servicedecl.hxx>
57 :
58 : #include <canvas/canvastools.hxx>
59 :
60 : #include <tools/diagnose_ex.h>
61 :
62 : #include <vcl/canvastools.hxx>
63 : #include <vcl/window.hxx>
64 : #include <vcl/syschild.hxx>
65 :
66 : #include <boost/noncopyable.hpp>
67 :
68 : #if defined( _WIN32 )
69 : // OGLTrans_TransitionImpl.hxx already included <prewin.h> and thus <windows.h>
70 : #include <GL/glu.h>
71 : #include <GL/glext.h>
72 : #include <GL/wglext.h>
73 : #elif defined( MACOSX )
74 : #include "premac.h"
75 : #include <Cocoa/Cocoa.h>
76 : #include "postmac.h"
77 : #elif defined( UNX )
78 : #include <GL/glu.h>
79 : #include <GL/glext.h>
80 :
81 : namespace unx
82 : {
83 : #include <X11/keysym.h>
84 : #include <X11/X.h>
85 : #define GLX_GLXEXT_PROTOTYPES 1
86 : #include <GL/glx.h>
87 : #include <GL/glxext.h>
88 : }
89 : #endif
90 :
91 : #include <vcl/sysdata.hxx>
92 :
93 : #if OSL_DEBUG_LEVEL > 1
94 : #include <boost/date_time/posix_time/posix_time.hpp>
95 : using namespace ::boost::posix_time;
96 :
97 : #endif
98 :
99 : using namespace ::com::sun::star;
100 : using ::com::sun::star::beans::XFastPropertySet;
101 : using ::com::sun::star::uno::Any;
102 : using ::com::sun::star::uno::Reference;
103 : using ::com::sun::star::uno::Sequence;
104 : using ::com::sun::star::uno::UNO_QUERY;
105 : using ::com::sun::star::uno::UNO_QUERY_THROW;
106 :
107 : namespace
108 : {
109 :
110 : typedef cppu::WeakComponentImplHelper1<presentation::XTransition> OGLTransitionerImplBase;
111 :
112 : #if OSL_DEBUG_LEVEL > 1
113 : class TimerContext
114 : {
115 : public:
116 : explicit TimerContext(OUString const& rWhat)
117 : : m_aWhat(rWhat)
118 : , m_aStartTime(microsec_clock::local_time())
119 : {
120 : }
121 : ~TimerContext()
122 : {
123 : time_duration const aDuration(microsec_clock::local_time() - m_aStartTime);
124 : SAL_INFO("slideshow.opengl", m_aWhat << " took: " << aDuration);
125 : }
126 : private:
127 : OUString const m_aWhat;
128 : ptime const m_aStartTime;
129 : };
130 : #endif
131 :
132 : struct OGLFormat
133 : {
134 : GLint nInternalFormat;
135 : GLenum eFormat;
136 : GLenum eType;
137 : };
138 :
139 : /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
140 : */
141 0 : int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
142 : {
143 : using namespace rendering::ColorComponentTag;
144 :
145 : static const sal_Int8 aOrderTable[] =
146 : {
147 : RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
148 : RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
149 : ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
150 : ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
151 : };
152 :
153 0 : const sal_Int32 nNumComps(rTags.getLength());
154 0 : const sal_Int8* pLine=aOrderTable;
155 0 : for(int i=0; i<4; ++i)
156 : {
157 0 : int j=0;
158 0 : while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
159 0 : ++j;
160 :
161 : // all of the line passed, this is a match!
162 0 : if( j==nNumComps )
163 0 : return i;
164 :
165 0 : pLine+=4;
166 : }
167 :
168 0 : return -1;
169 : }
170 :
171 : #ifdef UNX
172 :
173 : // not thread safe
174 : static bool errorTriggered;
175 0 : int oglErrorHandler( unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/ )
176 : {
177 0 : errorTriggered = true;
178 :
179 0 : return 0;
180 : }
181 :
182 : #endif
183 :
184 : /** This is the Transitioner class for OpenGL 3D transitions in
185 : * slideshow. At the moment, it's Linux only. This class is implicitly
186 : * constructed from XTransitionFactory.
187 : */
188 0 : class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable, public OGLTransitionerImplBase
189 : {
190 : public:
191 : OGLTransitionerImpl();
192 : void setTransition( boost::shared_ptr<OGLTransitionImpl> pOGLTransition );
193 : bool initialize( const Reference< presentation::XSlideShowView >& xView,
194 : const Reference< rendering::XBitmap >& xLeavingSlide,
195 : const Reference< rendering::XBitmap >& xEnteringSlide );
196 :
197 : // XTransition
198 : virtual void SAL_CALL update( double nTime )
199 : throw (uno::RuntimeException);
200 : virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
201 : const Reference< rendering::XBitmap >& rLeavingBitmap,
202 : const Reference< rendering::XBitmap >& rEnteringBitmap )
203 : throw (uno::RuntimeException);
204 :
205 : protected:
206 : void disposeContextAndWindow();
207 : void disposeTextures();
208 :
209 : // WeakComponentImplHelperBase
210 : virtual void SAL_CALL disposing();
211 :
212 0 : bool isDisposed() const
213 : {
214 0 : return (rBHelper.bDisposed || rBHelper.bInDispose);
215 : }
216 :
217 : bool createWindow( Window* pPWindow );
218 : void createTexture( unsigned int* texID,
219 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
220 : unx::GLXPixmap pixmap,
221 : bool usePixmap,
222 : #endif
223 : bool useMipmap,
224 : uno::Sequence<sal_Int8>& data,
225 : const OGLFormat* pFormat );
226 : void prepareEnvironment ();
227 : const OGLFormat* chooseFormats();
228 :
229 : private:
230 : static void impl_initializeOnce( bool const bGLXPresent );
231 :
232 : void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
233 : void impl_prepareSlides();
234 :
235 : void impl_createTexture( bool useMipmap, uno::Sequence<sal_Int8>& data, const OGLFormat* pFormat );
236 :
237 : bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
238 : /** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
239 : */
240 : void GLInitSlides();
241 :
242 : void impl_prepareTransition();
243 : void impl_finishTransition();
244 :
245 : /// Holds the information of our new child window
246 : struct GLWindow
247 : {
248 : #if defined( _WIN32 )
249 : HWND hWnd;
250 : HDC hDC;
251 : HGLRC hRC;
252 : #elif defined( MACOSX )
253 : #elif defined( UNX )
254 : unx::Display* dpy;
255 : int screen;
256 : unx::Window win;
257 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
258 : unx::GLXFBConfig fbc;
259 : #endif
260 : unx::XVisualInfo* vi;
261 : unx::GLXContext ctx;
262 :
263 0 : bool HasGLXExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, (const GLubyte*) GLXExtensions ); }
264 : const char* GLXExtensions;
265 : #endif
266 : unsigned int bpp;
267 : unsigned int Width;
268 : unsigned int Height;
269 : const GLubyte* GLExtensions;
270 :
271 0 : bool HasGLExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, GLExtensions ); }
272 : } GLWin;
273 :
274 : /** OpenGL handle to the leaving slide's texture
275 : */
276 : unsigned int GLleavingSlide;
277 : /** OpenGL handle to the entering slide's texture
278 : */
279 : unsigned int GLenteringSlide;
280 :
281 : /** pointer to our window which we MIGHT create.
282 : */
283 : class SystemChildWindow* pWindow;
284 :
285 : Reference< presentation::XSlideShowView > mxView;
286 : Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
287 : Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
288 :
289 : /** raw bytes of the entering bitmap
290 : */
291 : uno::Sequence<sal_Int8> EnteringBytes;
292 :
293 : /** raw bytes of the leaving bitmap
294 : */
295 : uno::Sequence<sal_Int8> LeavingBytes;
296 :
297 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
298 : unx::GLXPixmap LeavingPixmap;
299 : unx::GLXPixmap EnteringPixmap;
300 : #endif
301 : bool mbRestoreSync;
302 : bool mbUseLeavingPixmap;
303 : bool mbUseEnteringPixmap;
304 : bool mbFreeLeavingPixmap;
305 : bool mbFreeEnteringPixmap;
306 : #ifdef UNX
307 : unx::Pixmap maLeavingPixmap;
308 : unx::Pixmap maEnteringPixmap;
309 : #endif
310 :
311 : /** the form the raw bytes are in for the bitmaps
312 : */
313 : rendering::IntegerBitmapLayout SlideBitmapLayout;
314 :
315 : /** the size of the slides
316 : */
317 : geometry::IntegerSize2D SlideSize;
318 :
319 : /** Our Transition to be used.
320 : */
321 : boost::shared_ptr<OGLTransitionImpl> mpTransition;
322 :
323 : public:
324 : /** whether we are running on ATI fglrx with bug related to textures
325 : */
326 : static bool cbBrokenTexturesATI;
327 :
328 : /** GL version
329 : */
330 : static float cnGLVersion;
331 :
332 : #ifdef UNX
333 : float mnGLXVersion;
334 : #endif
335 :
336 : /**
337 : Whether the display has GLX extension on X11, always true otherwise (?)
338 : */
339 : static bool cbGLXPresent;
340 :
341 : /** Whether Mesa is the OpenGL vendor
342 : */
343 : static bool cbMesa;
344 :
345 : /**
346 : whether texture from pixmap extension is available
347 : */
348 : bool mbTextureFromPixmap;
349 :
350 : /**
351 : whether to generate mipmaped textures
352 : */
353 : bool mbGenerateMipmap;
354 :
355 : /**
356 : whether we have visual which can be used for texture_from_pixmap extension
357 : */
358 : bool mbHasTFPVisual;
359 :
360 : #if OSL_DEBUG_LEVEL > 1
361 : ptime maUpdateStartTime;
362 : ptime maUpdateEndTime;
363 : ptime maStartTime;
364 : ptime maEndTime;
365 : time_duration maTotalUpdateDuration;
366 : int mnFrameCount;
367 : #endif
368 : };
369 :
370 : // declare the static variables as some gcc versions have problems declaring them automaticaly
371 : bool OGLTransitionerImpl::cbBrokenTexturesATI;
372 : float OGLTransitionerImpl::cnGLVersion;
373 : bool OGLTransitionerImpl::cbMesa;
374 : bool OGLTransitionerImpl::cbGLXPresent;
375 :
376 0 : bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView,
377 : const Reference< rendering::XBitmap >& xLeavingSlide,
378 : const Reference< rendering::XBitmap >& xEnteringSlide )
379 : {
380 0 : bool const bGLXPresent( initWindowFromSlideShowView( xView ) );
381 0 : impl_initializeOnce( bGLXPresent );
382 :
383 0 : setSlides( xLeavingSlide, xEnteringSlide );
384 :
385 0 : return cbGLXPresent;
386 : }
387 :
388 0 : void OGLTransitionerImpl::impl_initializeOnce( bool const bGLXPresent )
389 : {
390 : // not thread safe
391 : static bool initialized = false;
392 :
393 0 : if( !initialized ) {
394 0 : cbGLXPresent = bGLXPresent;
395 0 : if ( bGLXPresent ) {
396 0 : const GLubyte* version = glGetString( GL_VERSION );
397 0 : if( version && version[0] ) {
398 0 : cnGLVersion = version[0] - '0';
399 0 : if( version[1] == '.' && version[2] )
400 0 : cnGLVersion += (version[2] - '0')/10.0;
401 : } else
402 0 : cnGLVersion = 1.0;
403 : SAL_INFO("slideshow.opengl", "GL version: " << version << " parsed: " << cnGLVersion << "" );
404 :
405 0 : const GLubyte* vendor = glGetString( GL_VENDOR );
406 0 : cbMesa = ( vendor && strstr( (const char *) vendor, "Mesa" ) );
407 : SAL_INFO("slideshow.opengl", "GL vendor: " << vendor << " identified as Mesa: " << cbMesa << "" );
408 :
409 : /* TODO: check for version once the bug in fglrx driver is fixed */
410 0 : cbBrokenTexturesATI = (vendor && strcmp( (const char *) vendor, "ATI Technologies Inc." ) == 0 );
411 :
412 : }
413 0 : initialized = true;
414 : }
415 0 : }
416 :
417 : #if defined( UNX )
418 : SystemEnvData const*
419 0 : lcl_createSystemWindow(
420 : unx::XVisualInfo* const pXVisual,
421 : Window* const pParentWindow,
422 : SystemChildWindow** const pChildWindow )
423 : {
424 : assert(pChildWindow);
425 :
426 : SystemWindowData winData;
427 0 : winData.nSize = sizeof(winData);
428 : SAL_INFO("slideshow.opengl", "using VisualID " << pXVisual->visualid);
429 0 : winData.pVisual = (void*)(pXVisual->visual);
430 0 : SystemChildWindow* pWindow = new SystemChildWindow(pParentWindow, 0, &winData, sal_False);
431 0 : SystemEnvData const* const pChildSysData = pWindow->GetSystemData();
432 0 : if( !pChildSysData ) {
433 0 : delete pWindow, pWindow=NULL;
434 : }
435 :
436 0 : *pChildWindow = pWindow;
437 0 : return pChildSysData;
438 : }
439 : #endif
440 :
441 0 : bool OGLTransitionerImpl::createWindow( Window* pPWindow )
442 : {
443 0 : const SystemEnvData* sysData(pPWindow->GetSystemData());
444 : #if defined( _WIN32 )
445 : GLWin.hWnd = sysData->hWnd;
446 : #elif defined( UNX )
447 0 : GLWin.dpy = reinterpret_cast<unx::Display*>(sysData->pDisplay);
448 :
449 0 : if( unx::glXQueryExtension( GLWin.dpy, NULL, NULL ) == false )
450 0 : return false;
451 :
452 0 : GLWin.win = sysData->aWindow;
453 :
454 : SAL_INFO("slideshow.opengl", "parent window: " << GLWin.win);
455 :
456 : unx::XWindowAttributes xattr;
457 0 : unx::XGetWindowAttributes( GLWin.dpy, GLWin.win, &xattr );
458 :
459 0 : GLWin.screen = XScreenNumberOfScreen( xattr.screen );
460 :
461 0 : unx::XVisualInfo* vi( NULL );
462 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
463 : unx::XVisualInfo* visinfo;
464 0 : unx::XVisualInfo* firstVisual( NULL );
465 : #endif
466 : static int attrList3[] =
467 : {
468 : GLX_RGBA,//only TrueColor or DirectColor
469 : //single buffered
470 : GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
471 : GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
472 : GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
473 : GLX_DEPTH_SIZE,0,//no depth buffer
474 : None
475 : };
476 : static int attrList2[] =
477 : {
478 : GLX_RGBA,//only TrueColor or DirectColor
479 : /// single buffered
480 : GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
481 : GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
482 : GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
483 : GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
484 : None
485 : };
486 : static int attrList1[] =
487 : {
488 : GLX_RGBA,//only TrueColor or DirectColor
489 : GLX_DOUBLEBUFFER,/// only double buffer
490 : GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
491 : GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
492 : GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
493 : GLX_DEPTH_SIZE,0,/// no depth buffer
494 : None
495 : };
496 : static int attrList0[] =
497 : {
498 : GLX_RGBA,//only TrueColor or DirectColor
499 : GLX_DOUBLEBUFFER,/// only double buffer
500 : GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
501 : GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
502 : GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
503 : GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
504 : None
505 : };
506 : static int* attrTable[] =
507 : {
508 : attrList0,
509 : attrList1,
510 : attrList2,
511 : attrList3,
512 : NULL
513 : };
514 0 : int** pAttributeTable = attrTable;
515 0 : const SystemEnvData* pChildSysData = NULL;
516 0 : delete pWindow;
517 0 : pWindow=NULL;
518 :
519 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
520 0 : unx::GLXFBConfig* fbconfigs = NULL;
521 0 : int nfbconfigs, value, i = 0;
522 : #endif
523 :
524 0 : while( *pAttributeTable )
525 : {
526 : // try to find a visual for the current set of attributes
527 : vi = unx::glXChooseVisual( GLWin.dpy,
528 : GLWin.screen,
529 0 : *pAttributeTable );
530 :
531 0 : if( vi ) {
532 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
533 0 : if( !firstVisual )
534 0 : firstVisual = vi;
535 : SAL_INFO("slideshow.opengl", "trying VisualID " << vi->visualid);
536 0 : fbconfigs = glXGetFBConfigs (GLWin.dpy, GLWin.screen, &nfbconfigs);
537 0 : for ( ; i < nfbconfigs; i++)
538 : {
539 0 : visinfo = glXGetVisualFromFBConfig (GLWin.dpy, fbconfigs[i]);
540 0 : if( !visinfo )
541 0 : continue;
542 :
543 0 : unx::VisualID visualid = visinfo->visualid;
544 0 : XFree ( visinfo );
545 :
546 0 : if ( visualid != vi->visualid )
547 0 : continue;
548 :
549 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
550 0 : if (!(value & GLX_PIXMAP_BIT))
551 0 : continue;
552 :
553 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
554 : GLX_BIND_TO_TEXTURE_TARGETS_EXT,
555 0 : &value);
556 0 : if (!(value & GLX_TEXTURE_2D_BIT_EXT))
557 0 : continue;
558 :
559 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
560 : GLX_BIND_TO_TEXTURE_RGB_EXT,
561 0 : &value);
562 0 : if (value == sal_False)
563 0 : continue;
564 :
565 0 : glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
566 : GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
567 0 : &value);
568 0 : if (value == sal_False)
569 0 : continue;
570 :
571 : /* TODO: handle non Y inverted cases */
572 0 : break;
573 : }
574 0 : if (vi != firstVisual)
575 0 : XFree (vi);
576 :
577 0 : if( i != nfbconfigs ) {
578 0 : vi = glXGetVisualFromFBConfig( GLWin.dpy, fbconfigs[i] );
579 0 : mbHasTFPVisual = true;
580 0 : pChildSysData = lcl_createSystemWindow( vi, pPWindow, &pWindow );
581 0 : XFree ( vi );
582 : SAL_INFO("slideshow.opengl", "found visual suitable for texture_from_pixmap");
583 0 : } else if( firstVisual && pAttributeTable[1] == NULL ) {
584 0 : vi = firstVisual;
585 0 : mbHasTFPVisual = false;
586 0 : pChildSysData = lcl_createSystemWindow( vi, pPWindow, &pWindow );
587 : SAL_INFO("slideshow.opengl", "did not find visual suitable for texture_from_pixmap, using " << vi->visualid);
588 : }
589 0 : XFree ( fbconfigs );
590 : #else
591 : pChildSysData = lcl_createSystemWindow( vi, pPWindow, &pWindow );
592 : XFree ( vi );
593 : #endif
594 0 : if ( pChildSysData )
595 0 : break;
596 : }
597 :
598 0 : ++pAttributeTable;
599 : }
600 :
601 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
602 0 : if ( firstVisual )
603 0 : XFree (firstVisual);
604 : #endif
605 :
606 : #endif
607 :
608 : #if defined( _WIN32 )
609 : SystemWindowData winData;
610 : winData.nSize = sizeof(winData);
611 : pWindow=new SystemChildWindow(pPWindow, 0, &winData, sal_False);
612 : pWindow->GetSystemData();
613 : #endif
614 :
615 0 : if( pWindow )
616 : {
617 0 : pWindow->SetMouseTransparent( sal_True );
618 0 : pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
619 0 : pWindow->EnableEraseBackground( sal_False );
620 0 : pWindow->SetControlForeground();
621 0 : pWindow->SetControlBackground();
622 0 : pWindow->EnablePaint(sal_False);
623 : #if defined( _WIN32 )
624 : GLWin.hWnd = sysData->hWnd;
625 : #elif defined( UNX )
626 0 : GLWin.dpy = reinterpret_cast<unx::Display*>(pChildSysData->pDisplay);
627 0 : GLWin.win = pChildSysData->aWindow;
628 : #if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
629 0 : if( mbHasTFPVisual )
630 0 : GLWin.fbc = fbconfigs[i];
631 : #endif
632 0 : GLWin.vi = vi;
633 0 : GLWin.GLXExtensions = unx::glXQueryExtensionsString( GLWin.dpy, GLWin.screen );
634 : SAL_INFO("slideshow.opengl", "available GLX extensions: " << GLWin.GLXExtensions);
635 : #endif
636 :
637 0 : return true;
638 : }
639 :
640 0 : return false;
641 : }
642 :
643 0 : bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
644 : {
645 0 : osl::MutexGuard const guard( m_aMutex );
646 :
647 0 : if (isDisposed())
648 0 : return false;
649 :
650 0 : mxView.set( xView, UNO_QUERY );
651 0 : if( !mxView.is() )
652 0 : return false;
653 :
654 : #if OSL_DEBUG_LEVEL > 1
655 : TimerContext aTimerContext("initWindowFromSlideShowView");
656 : #endif
657 :
658 : /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
659 0 : uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
660 0 : uno::Sequence< uno::Any > aDeviceParams;
661 0 : ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
662 :
663 0 : OUString aImplName;
664 0 : aDeviceParams[ 0 ] >>= aImplName;
665 :
666 0 : sal_Int64 aVal = 0;
667 0 : aDeviceParams[1] >>= aVal;
668 0 : if( !createWindow( reinterpret_cast< Window* >( aVal ) ) )
669 0 : return false;
670 :
671 0 : awt::Rectangle aCanvasArea = mxView->getCanvasArea();
672 0 : pWindow->setPosSizePixel(aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
673 0 : GLWin.Width = aCanvasArea.Width;
674 0 : GLWin.Height = aCanvasArea.Height;
675 : SAL_INFO("slideshow.opengl", "canvas area: " << aCanvasArea.X << "," << aCanvasArea.Y << " - " << aCanvasArea.Width << "x" << aCanvasArea.Height);
676 :
677 : #if defined( _WIN32 )
678 : GLWin.hDC = GetDC(GLWin.hWnd);
679 : #elif defined( UNX )
680 : GLWin.ctx = glXCreateContext(GLWin.dpy,
681 : GLWin.vi,
682 : 0,
683 0 : GL_TRUE);
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_VERSION_1_3 ) && 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_VERSION_1_3 ) && 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_VERSION_1_3 ) && 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)
995 : {
996 0 : return rendering::ColorSpaceType::RGB;
997 : }
998 0 : virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) throw (uno::RuntimeException)
999 : {
1000 0 : return maComponentTags;
1001 : }
1002 0 : virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) throw (uno::RuntimeException)
1003 : {
1004 0 : return rendering::RenderingIntent::PERCEPTUAL;
1005 : }
1006 0 : virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) throw (uno::RuntimeException)
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)
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)
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)
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)
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)
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)
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)
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)
1125 : {
1126 0 : return 32;
1127 : }
1128 0 : virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) throw (uno::RuntimeException)
1129 : {
1130 0 : return maBitCounts;
1131 : }
1132 0 : virtual ::sal_Int8 SAL_CALL getEndianness( ) throw (uno::RuntimeException)
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)
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)
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)
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)
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)
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)
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)
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)
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_VERSION_1_3 ) && 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_VERSION_1_3 ) && 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)
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)
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_VERSION_1_3 ) && 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 : GLWin(),
1766 : GLleavingSlide( 0 ),
1767 : GLenteringSlide( 0 ),
1768 : pWindow( NULL ),
1769 : mxView(),
1770 : EnteringBytes(),
1771 : LeavingBytes(),
1772 : mbRestoreSync( false ),
1773 : mbUseLeavingPixmap( false ),
1774 : mbUseEnteringPixmap( false ),
1775 : SlideBitmapLayout(),
1776 0 : SlideSize()
1777 : {
1778 : #if defined( _WIN32 )
1779 : GLWin.hWnd = 0;
1780 : #elif defined( UNX )
1781 0 : GLWin.ctx = 0;
1782 : #endif
1783 :
1784 : #if OSL_DEBUG_LEVEL > 1
1785 : mnFrameCount = 0;
1786 : #endif
1787 0 : }
1788 :
1789 : typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
1790 :
1791 0 : class OGLTransitionFactoryImpl : private cppu::BaseMutex, public OGLTransitionFactoryImplBase
1792 : {
1793 : public:
1794 0 : explicit OGLTransitionFactoryImpl( const uno::Reference< uno::XComponentContext >& ) :
1795 0 : OGLTransitionFactoryImplBase(m_aMutex)
1796 0 : {}
1797 :
1798 : // XTransitionFactory
1799 0 : virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException)
1800 : {
1801 0 : if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1802 0 : switch( transitionSubType )
1803 : {
1804 : case animations::TransitionSubType::ACROSS:
1805 : case animations::TransitionSubType::CORNERSOUT:
1806 : case animations::TransitionSubType::CIRCLE:
1807 : case animations::TransitionSubType::FANOUTHORIZONTAL:
1808 : case animations::TransitionSubType::CORNERSIN:
1809 : case animations::TransitionSubType::LEFTTORIGHT:
1810 : case animations::TransitionSubType::TOPTOBOTTOM:
1811 : case animations::TransitionSubType::TOPRIGHT:
1812 : case animations::TransitionSubType::TOPLEFT:
1813 : case animations::TransitionSubType::BOTTOMRIGHT:
1814 : case animations::TransitionSubType::BOTTOMLEFT:
1815 : case animations::TransitionSubType::TOPCENTER:
1816 : case animations::TransitionSubType::RIGHTCENTER:
1817 : case animations::TransitionSubType::BOTTOMCENTER:
1818 0 : return sal_True;
1819 :
1820 : default:
1821 0 : return sal_False;
1822 : }
1823 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1824 0 : return sal_True;
1825 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1826 0 : return sal_True;
1827 0 : } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1828 0 : return sal_True;
1829 0 : } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1830 0 : return sal_True;
1831 : } else
1832 0 : return sal_False;
1833 : }
1834 :
1835 0 : virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
1836 : ::sal_Int16 transitionType,
1837 : ::sal_Int16 transitionSubType,
1838 : const uno::Reference< presentation::XSlideShowView >& view,
1839 : const uno::Reference< rendering::XBitmap >& leavingBitmap,
1840 : const uno::Reference< rendering::XBitmap >& enteringBitmap )
1841 : throw (uno::RuntimeException)
1842 : {
1843 0 : if( !hasTransition( transitionType, transitionSubType ) )
1844 0 : return uno::Reference< presentation::XTransition >();
1845 :
1846 0 : rtl::Reference< OGLTransitionerImpl > xRes( new OGLTransitionerImpl() );
1847 0 : if ( !xRes->initialize( view, leavingBitmap, enteringBitmap ) )
1848 0 : return uno::Reference< presentation::XTransition >();
1849 :
1850 0 : if( OGLTransitionerImpl::cbMesa && (
1851 0 : ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) ||
1852 0 : ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) ||
1853 0 : ( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) ) )
1854 0 : return uno::Reference< presentation::XTransition >();
1855 :
1856 0 : boost::shared_ptr<OGLTransitionImpl> pTransition;
1857 :
1858 0 : if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
1859 0 : switch( transitionSubType )
1860 : {
1861 : case animations::TransitionSubType::ACROSS:
1862 0 : pTransition = makeNByMTileFlip(8,6);
1863 0 : break;
1864 : case animations::TransitionSubType::CORNERSOUT:
1865 0 : pTransition = makeOutsideCubeFaceToLeft();
1866 0 : break;
1867 : case animations::TransitionSubType::CIRCLE:
1868 0 : pTransition = makeRevolvingCircles(8,128);
1869 0 : break;
1870 : case animations::TransitionSubType::FANOUTHORIZONTAL:
1871 0 : pTransition = makeHelix(20);
1872 0 : break;
1873 : case animations::TransitionSubType::CORNERSIN:
1874 0 : pTransition = makeInsideCubeFaceToLeft();
1875 0 : break;
1876 : case animations::TransitionSubType::LEFTTORIGHT:
1877 0 : pTransition = makeFallLeaving();
1878 0 : break;
1879 : case animations::TransitionSubType::TOPTOBOTTOM:
1880 0 : pTransition = makeTurnAround();
1881 0 : break;
1882 : case animations::TransitionSubType::TOPRIGHT:
1883 0 : pTransition = makeTurnDown();
1884 0 : break;
1885 : case animations::TransitionSubType::TOPLEFT:
1886 0 : pTransition = makeIris();
1887 0 : break;
1888 : case animations::TransitionSubType::BOTTOMRIGHT:
1889 0 : pTransition = makeRochade();
1890 0 : break;
1891 : case animations::TransitionSubType::BOTTOMLEFT:
1892 0 : pTransition = makeVenetianBlinds( true, 8 );
1893 0 : break;
1894 : case animations::TransitionSubType::TOPCENTER:
1895 0 : pTransition = makeVenetianBlinds( false, 6 );
1896 0 : break;
1897 : case animations::TransitionSubType::RIGHTCENTER:
1898 0 : pTransition = makeStatic();
1899 0 : break;
1900 : case animations::TransitionSubType::BOTTOMCENTER:
1901 0 : pTransition = makeDissolve();
1902 0 : break;
1903 : }
1904 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
1905 0 : pTransition = makeFadeSmoothly();
1906 0 : } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
1907 0 : pTransition = makeFadeThroughBlack();
1908 0 : } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
1909 0 : pTransition = makeDiamond();
1910 0 : } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
1911 0 : pTransition = makeNewsflash();
1912 : }
1913 :
1914 0 : if ( !pTransition )
1915 0 : return uno::Reference< presentation::XTransition >();
1916 :
1917 0 : xRes->setTransition( pTransition );
1918 :
1919 0 : return uno::Reference<presentation::XTransition>(xRes.get());
1920 : }
1921 : };
1922 :
1923 : }
1924 :
1925 : namespace sdecl = comphelper::service_decl;
1926 0 : const sdecl::ServiceDecl OGLTransitionFactoryDecl(
1927 : sdecl::class_<OGLTransitionFactoryImpl>(),
1928 : "com.sun.star.comp.presentation.OGLTransitionFactory",
1929 0 : "com.sun.star.presentation.TransitionFactory" );
1930 :
1931 : // The C shared lib entry points
1932 0 : COMPHELPER_SERVICEDECL_EXPORTS1(ogltrans, OGLTransitionFactoryDecl)
1933 :
1934 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|