summaryrefslogtreecommitdiff
path: root/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx')
-rw-r--r--slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx1201
1 files changed, 924 insertions, 277 deletions
diff --git a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx
index 62da933baa96..6c07065e2904 100644
--- a/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx
+++ b/slideshow/source/engine/OGLTrans/OGLTrans_TransitionerImpl.cxx
@@ -28,8 +28,10 @@
*
************************************************************************/
+#define GLX_GLXEXT_PROTOTYPES 1
#include "OGLTrans_TransitionImpl.hxx"
+#include <com/sun/star/beans/XFastPropertySet.hpp>
#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
#include <com/sun/star/rendering/ColorComponentTag.hpp>
#include <com/sun/star/rendering/ColorSpaceType.hpp>
@@ -70,17 +72,88 @@
namespace unx
{
#include <X11/keysym.h>
+#include <X11/X.h>
#include <GL/glx.h>
+#include <GL/glxext.h>
}
#endif
+#ifdef DEBUG
+#include <boost/date_time/posix_time/posix_time.hpp>
+using namespace ::boost::posix_time;
+
+static ptime t1;
+static ptime t2;
+
+#define DBG(x) x
+#else
+#define DBG(x)
+#endif
+
using namespace ::com::sun::star;
+using ::com::sun::star::beans::XFastPropertySet;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
namespace
{
typedef cppu::WeakComponentImplHelper1<presentation::XTransition> OGLTransitionerImplBase;
+namespace
+{
+ struct OGLFormat
+ {
+ GLint nInternalFormat;
+ GLenum eFormat;
+ GLenum eType;
+ };
+
+ /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
+ */
+ int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
+ {
+ using namespace rendering::ColorComponentTag;
+
+ static const sal_Int8 aOrderTable[] =
+ {
+ RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
+ RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
+ ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
+ ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
+ };
+
+ const sal_Int32 nNumComps(rTags.getLength());
+ const sal_Int8* pLine=aOrderTable;
+ for(int i=0; i<4; ++i)
+ {
+ int j=0;
+ while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
+ ++j;
+
+ // all of the line passed, this is a match!
+ if( j==nNumComps )
+ return i;
+
+ pLine+=4;
+ }
+
+ return -1;
+ }
+}
+
+// not thread safe
+static bool errorTriggered;
+int oglErrorHandler( unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/ )
+{
+ errorTriggered = true;
+
+ return 0;
+}
+
/** This is the Transitioner class for OpenGL 3D transitions in
* slideshow. At the moment, it's Linux only. This class is implicitly
* constructed from XTransitionFactory.
@@ -89,13 +162,22 @@ class OGLTransitionerImpl : private cppu::BaseMutex, private boost::noncopyable,
{
public:
explicit OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition);
- void initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView, double, double);
- void setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
+ bool initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView );
+ void setSlides( const Reference< rendering::XBitmap >& xLeavingSlide , const uno::Reference< rendering::XBitmap >& xEnteringSlide );
+ static bool initialize( const Reference< presentation::XSlideShowView >& xView );
// XTransition
- virtual void SAL_CALL update( double nTime ) throw (uno::RuntimeException);
+ virtual void SAL_CALL update( double nTime )
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL viewChanged( const Reference< presentation::XSlideShowView >& rView,
+ const Reference< rendering::XBitmap >& rLeavingBitmap,
+ const Reference< rendering::XBitmap >& rEnteringBitmap )
+ throw (uno::RuntimeException);
protected:
+ void disposeContextAndWindow();
+ void disposeTextures();
+
// WeakComponentImplHelperBase
virtual void SAL_CALL disposing();
@@ -104,6 +186,18 @@ protected:
return (rBHelper.bDisposed || rBHelper.bInDispose);
}
+ bool createWindow( Window* pPWindow );
+ void createTexture( unsigned int* texID,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXPixmap pixmap,
+ bool usePixmap,
+#endif
+ bool useMipmap,
+ uno::Sequence<sal_Int8>& data,
+ const OGLFormat* pFormat );
+ void prepareEnvironment ();
+ const OGLFormat* chooseFormats();
+
private:
/** After the window has been created, and the slides have been set, we'll initialize the slides with OpenGL.
*/
@@ -114,20 +208,29 @@ private:
struct GLWindow
{
#if defined( WNT )
- HWND hWnd;
- HDC hDC;
- HGLRC hRC;
+ HWND hWnd;
+ HDC hDC;
+ HGLRC hRC;
#elif defined( OS2 )
#elif defined( QUARTZ )
#elif defined( UNX )
- unx::Display* dpy;
- int screen;
- unx::Window win;
- unx::GLXContext ctx;
+ unx::Display* dpy;
+ int screen;
+ unx::Window win;
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXFBConfig fbc;
+#endif
+ unx::XVisualInfo* vi;
+ unx::GLXContext ctx;
#endif
unsigned int bpp;
unsigned int Width;
unsigned int Height;
+ const char* GLXExtensions;
+ const GLubyte* GLExtensions;
+
+ bool HasGLXExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, (const GLubyte*) GLXExtensions ); }
+ bool HasGLExtension( const char* name ) { return gluCheckExtension( (const GLubyte*) name, GLExtensions ); }
} GLWin;
/** OpenGL handle to the leaving slide's texture
@@ -141,6 +244,10 @@ private:
*/
class SystemChildWindow* pWindow;
+ Reference< presentation::XSlideShowView > mxView;
+ Reference< rendering::XIntegerBitmap > mxLeavingBitmap;
+ Reference< rendering::XIntegerBitmap > mxEnteringBitmap;
+
/** raw bytes of the entering bitmap
*/
uno::Sequence<sal_Int8> EnteringBytes;
@@ -149,6 +256,18 @@ private:
*/
uno::Sequence<sal_Int8> LeavingBytes;
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXPixmap LeavingPixmap;
+ unx::GLXPixmap EnteringPixmap;
+#endif
+ bool mbRestoreSync;
+ bool mbUseLeavingPixmap;
+ bool mbUseEnteringPixmap;
+ bool mbFreeLeavingPixmap;
+ bool mbFreeEnteringPixmap;
+ unx::Pixmap maLeavingPixmap;
+ unx::Pixmap maEnteringPixmap;
+
/** the form the raw bytes are in for the bitmaps
*/
rendering::IntegerBitmapLayout SlideBitmapLayout;
@@ -160,38 +279,124 @@ private:
/** Our Transition to be used.
*/
OGLTransitionImpl* pTransition;
+
+public:
+ /** whether we are running on ATI fglrx with bug related to textures
+ */
+ static bool cbBrokenTexturesATI;
+
+ /** GL version
+ */
+ static float cnGLVersion;
+ float mnGLXVersion;
+
+ /** Whether Mesa is the OpenGL vendor
+ */
+ static bool cbMesa;
+
+ /**
+ whether the display has GLX extension
+ */
+ static bool cbGLXPresent;
+
+ /**
+ whether texture from pixmap extension is available
+ */
+ bool mbTextureFromPixmap;
+
+ /**
+ whether to generate mipmaped textures
+ */
+ bool mbGenerateMipmap;
+
+ /**
+ whether we have visual which can be used for texture_from_pixmap extension
+ */
+ bool mbHasTFPVisual;
+
+#ifdef DEBUG
+ ptime t3;
+ ptime t4;
+ ptime t5;
+ ptime t6;
+ time_duration total_update;
+ int frame_count;
+#endif
};
-void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< presentation::XSlideShowView >& xView, double, double)
-{
- osl::MutexGuard const guard( m_aMutex );
+// declare the static variables as some gcc versions have problems declaring them automaticaly
+bool OGLTransitionerImpl::cbBrokenTexturesATI;
+float OGLTransitionerImpl::cnGLVersion;
+bool OGLTransitionerImpl::cbMesa;
+bool OGLTransitionerImpl::cbGLXPresent;
- if (isDisposed())
- return;
+bool OGLTransitionerImpl::initialize( const Reference< presentation::XSlideShowView >& xView )
+{
+ // not thread safe
+ static bool initialized = false;
+
+ if( !initialized ) {
+ OGLTransitionerImpl *instance;
+
+ instance = new OGLTransitionerImpl( NULL );
+ if( instance->initWindowFromSlideShowView( xView ) ) {
+
+ const GLubyte* version = glGetString( GL_VERSION );
+ if( version && version[0] ) {
+ cnGLVersion = version[0] - '0';
+ if( version[1] == '.' && version[2] )
+ cnGLVersion += (version[2] - '0')/10.0;
+ } else
+ cnGLVersion = 1.0;
+ OSL_TRACE("GL version: %s parsed: %f", version, cnGLVersion );
+
+ const GLubyte* vendor = glGetString( GL_VENDOR );
+ cbMesa = ( vendor && strstr( (const char *) vendor, "Mesa" ) );
+ OSL_TRACE("GL vendor: %s identified as Mesa: %d", vendor, cbMesa );
+
+ /* TODO: check for version once the bug in fglrx driver is fixed */
+ cbBrokenTexturesATI = (vendor && strcmp( (const char *) vendor, "ATI Technologies Inc." ) == 0 );
+
+ instance->disposing();
+ cbGLXPresent = true;
+ } else
+ cbGLXPresent = false;
+
+ delete instance;
+ initialized = true;
+ }
- /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
- uno::Reference< rendering::XCanvas > xCanvas(xView->getCanvas(), uno::UNO_QUERY_THROW);
- uno::Sequence< uno::Any > aDeviceParams;
- ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
- ::rtl::OUString aImplName;
- aDeviceParams[ 0 ] >>= aImplName;
- sal_Int64 aVal = 0;
- aDeviceParams[1] >>= aVal;
- Window* pPWindow = reinterpret_cast< Window* >( aVal );
- GLWin.Width = pPWindow->GetSizePixel().Width();
- GLWin.Height = pPWindow->GetSizePixel().Height();
+ return cbGLXPresent;
+}
+bool OGLTransitionerImpl::createWindow( Window* pPWindow )
+{
const SystemEnvData* sysData(pPWindow->GetSystemData());
#if defined( WNT )
GLWin.hWnd = sysData->hWnd;
#elif defined( UNX )
GLWin.dpy = reinterpret_cast<unx::Display*>(sysData->pDisplay);
+
+ if( unx::glXQueryExtension( GLWin.dpy, NULL, NULL ) == false )
+ return false;
+
GLWin.win = sysData->aWindow;
- GLWin.screen = unx::XDefaultScreen(GLWin.dpy);
+
+ OSL_TRACE("parent window: %d", GLWin.win);
+
+ unx::XWindowAttributes xattr;
+ unx::XGetWindowAttributes( GLWin.dpy, GLWin.win, &xattr );
+
+ GLWin.screen = XScreenNumberOfScreen( xattr.screen );
+
unx::XVisualInfo* vi( NULL );
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::XVisualInfo* visinfo;
+ unx::XVisualInfo* firstVisual( NULL );
+#endif
static int attrList3[] =
{
- GLX_RGBA,//only TrueColor or DirectColor
+ GLX_RGBA,//only TrueColor or DirectColor
//single buffered
GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
@@ -200,8 +405,8 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
None
};
static int attrList2[] =
- {
- GLX_RGBA,/// only TrueColor or DirectColor
+ {
+ GLX_RGBA,//only TrueColor or DirectColor
/// single buffered
GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
@@ -211,7 +416,7 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
};
static int attrList1[] =
{
- GLX_RGBA,/// only TrueColor or DirectColor
+ GLX_RGBA,//only TrueColor or DirectColor
GLX_DOUBLEBUFFER,/// only double buffer
GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
@@ -221,7 +426,7 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
};
static int attrList0[] =
{
- GLX_RGBA,/// only TrueColor or DirectColor
+ GLX_RGBA,//only TrueColor or DirectColor
GLX_DOUBLEBUFFER,/// only double buffer
GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
@@ -241,6 +446,12 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
const SystemEnvData* pChildSysData = NULL;
delete pWindow;
pWindow=NULL;
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXFBConfig* fbconfigs = NULL;
+ int nfbconfigs, value, i = 0;
+#endif
+
while( *pAttributeTable )
{
// try to find a visual for the current set of attributes
@@ -248,59 +459,154 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
GLWin.screen,
*pAttributeTable );
- if( vi )
- {
- SystemWindowData winData;
- winData.nSize = sizeof(winData);
- winData.pVisual = (void*)(vi->visual);
- pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
- pChildSysData = pWindow->GetSystemData();
- if( pChildSysData )
- {
- break;
- }
- else
- {
- delete pWindow, pWindow=NULL;
- }
- }
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ if( vi ) {
+ if( !firstVisual )
+ firstVisual = vi;
+ OSL_TRACE("trying VisualID %08X", vi->visualid);
+ fbconfigs = glXGetFBConfigs (GLWin.dpy, GLWin.screen, &nfbconfigs);
+ for ( ; i < nfbconfigs; i++)
+ {
+ visinfo = glXGetVisualFromFBConfig (GLWin.dpy, fbconfigs[i]);
+ if( !visinfo || visinfo->visualid != vi->visualid )
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
+ if (!(value & GLX_PIXMAP_BIT))
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+ &value);
+ if (!(value & GLX_TEXTURE_2D_BIT_EXT))
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGB_EXT,
+ &value);
+ if (value == FALSE)
+ continue;
+
+ glXGetFBConfigAttrib (GLWin.dpy, fbconfigs[i],
+ GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+ &value);
+ if (value == FALSE)
+ continue;
+
+ /* TODO: handle non Y inverted cases */
+ break;
+ }
+
+ if( i != nfbconfigs || ( firstVisual && pAttributeTable[1] == NULL ) ) {
+ if( i != nfbconfigs ) {
+ vi = glXGetVisualFromFBConfig( GLWin.dpy, fbconfigs[i] );
+ mbHasTFPVisual = true;
+ OSL_TRACE("found visual suitable for texture_from_pixmap");
+ } else {
+ vi = firstVisual;
+ mbHasTFPVisual = false;
+ OSL_TRACE("did not find visual suitable for texture_from_pixmap, using %08X", vi->visualid);
+ }
+#else
+ if( vi ) {
+#endif
+ SystemWindowData winData;
+ winData.nSize = sizeof(winData);
+ OSL_TRACE("using VisualID %08X", vi->visualid);
+ winData.pVisual = (void*)(vi->visual);
+ pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
+ pChildSysData = pWindow->GetSystemData();
+ if( pChildSysData ) {
+ break;
+ } else {
+ delete pWindow, pWindow=NULL;
+ }
+ }
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ }
+#endif
+
++pAttributeTable;
- }
+ }
#endif
#if defined( WNT )
- const SystemEnvData* pChildSysData = NULL;
- SystemWindowData winData;
- winData.nSize = sizeof(winData);
- pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
- pChildSysData = pWindow->GetSystemData();
+ const SystemEnvData* pChildSysData = NULL;
+ SystemWindowData winData;
+ winData.nSize = sizeof(winData);
+ pWindow=new SystemChildWindow(pPWindow, 0, &winData, FALSE);
+ pChildSysData = pWindow->GetSystemData();
#endif
- if( pWindow )
- {
- pWindow->SetMouseTransparent( TRUE );
- pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
- pWindow->EnableEraseBackground( FALSE );
- pWindow->SetControlForeground();
- pWindow->SetControlBackground();
- pWindow->EnablePaint(FALSE);
- pWindow->SetPosSizePixel(pPWindow->GetPosPixel(),pPWindow->GetSizePixel());
-
+ if( pWindow )
+ {
+ pWindow->SetMouseTransparent( TRUE );
+ pWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
+ pWindow->EnableEraseBackground( FALSE );
+ pWindow->SetControlForeground();
+ pWindow->SetControlBackground();
+ pWindow->EnablePaint(FALSE);
#if defined( WNT )
GLWin.hWnd = sysData->hWnd;
#elif defined( UNX )
GLWin.dpy = reinterpret_cast<unx::Display*>(pChildSysData->pDisplay);
GLWin.win = pChildSysData->aWindow;
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ if( mbHasTFPVisual )
+ GLWin.fbc = fbconfigs[i];
#endif
+ GLWin.vi = vi;
+ GLWin.GLXExtensions = unx::glXQueryExtensionsString( GLWin.dpy, GLWin.screen );
+ OSL_TRACE("available GLX extensions: %s", GLWin.GLXExtensions);
+#endif
+
+ return true;
}
+ return false;
+}
+
+bool OGLTransitionerImpl::initWindowFromSlideShowView( const Reference< presentation::XSlideShowView >& xView )
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ if (isDisposed())
+ return false;
+
+ mxView.set( xView, UNO_QUERY );
+ if( !mxView.is() )
+ return false;
+
+ /// take the XSlideShowView and extract the parent window from it. see viewmediashape.cxx
+ uno::Reference< rendering::XCanvas > xCanvas(mxView->getCanvas(), uno::UNO_QUERY_THROW);
+ uno::Sequence< uno::Any > aDeviceParams;
+ ::canvas::tools::getDeviceInfo( xCanvas, aDeviceParams );
+
+ ::rtl::OUString aImplName;
+ aDeviceParams[ 0 ] >>= aImplName;
+
+ sal_Int64 aVal = 0;
+ aDeviceParams[1] >>= aVal;
+ if( !createWindow( reinterpret_cast< Window* >( aVal ) ) )
+ return false;
+
+ awt::Rectangle aCanvasArea = mxView->getCanvasArea();
+ pWindow->SetPosSizePixel(aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
+ GLWin.Width = aCanvasArea.Width;
+ GLWin.Height = aCanvasArea.Height;
+ OSL_TRACE("canvas area: %d,%d - %dx%d", aCanvasArea.X, aCanvasArea.Y, aCanvasArea.Width, aCanvasArea.Height);
+
#if defined( WNT )
GLWin.hDC = GetDC(GLWin.hWnd);
#elif defined( UNX )
GLWin.ctx = glXCreateContext(GLWin.dpy,
- vi,
+ GLWin.vi,
0,
GL_TRUE);
+ if( GLWin.ctx == NULL ) {
+ OSL_TRACE("unable to create GLX context");
+ return false;
+ }
#endif
#if defined( WNT )
@@ -330,8 +636,52 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
GLWin.hRC = wglCreateContext(GLWin.hDC);
wglMakeCurrent(GLWin.hDC,GLWin.hRC);
#elif defined( UNX )
- glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+ if( !glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx ) ) {
+ OSL_TRACE("unable to select current GLX context");
+ return false;
+ }
+
+ int glxMinor, glxMajor;
+ mnGLXVersion = 0;
+ if( glXQueryVersion( GLWin.dpy, &glxMajor, &glxMinor ) )
+ mnGLXVersion = glxMajor + 0.1*glxMinor;
+ OSL_TRACE("available GLX version: %f", mnGLXVersion);
+
+ GLWin.GLExtensions = glGetString( GL_EXTENSIONS );
+ OSL_TRACE("available GL extensions: %s", GLWin.GLExtensions);
+
+ mbTextureFromPixmap = GLWin.HasGLXExtension( "GLX_EXT_texture_from_pixmap" );
+ mbGenerateMipmap = GLWin.HasGLExtension( "GL_SGIS_generate_mipmap" );
+
+ if( GLWin.HasGLXExtension("GLX_SGI_swap_control" ) ) {
+ // enable vsync
+ typedef GLint (*glXSwapIntervalProc)(GLint);
+ glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) unx::glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
+ if( glXSwapInterval ) {
+ int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
+
+ // replace error handler temporarily
+ oldHandler = unx::XSetErrorHandler( oglErrorHandler );
+
+ errorTriggered = false;
+
+ glXSwapInterval( 1 );
+
+ // sync so that we possibly get an XError
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ if( errorTriggered )
+ OSL_TRACE("error when trying to set swap interval, NVIDIA or Mesa bug?");
+ else
+ OSL_TRACE("set swap interval to 1 (enable vsync)");
+
+ // restore the error handler
+ unx::XSetErrorHandler( oldHandler );
+ }
+ }
#endif
+
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glClearColor (0, 0, 0, 0);
@@ -353,8 +703,10 @@ void OGLTransitionerImpl::initWindowFromSlideShowView( const uno::Reference< pre
if( LeavingBytes.hasElements() && EnteringBytes.hasElements())
GLInitSlides();//we already have uninitialized slides, let's initialize
- if (pTransition)
- pTransition->prepare ();
+ if( pTransition && pTransition->mnRequiredGLVersion <= cnGLVersion )
+ pTransition->prepare( GLleavingSlide, GLenteringSlide );
+
+ return true;
}
void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >& xLeavingSlide,
@@ -365,75 +717,213 @@ void OGLTransitionerImpl::setSlides( const uno::Reference< rendering::XBitmap >&
if (isDisposed())
return;
- uno::Reference< rendering::XIntegerBitmap > LeavingSlideIntBitmap( xLeavingSlide , uno::UNO_QUERY_THROW );
- uno::Reference< rendering::XIntegerBitmap > EnteringSlideIntBitmap( xEnteringSlide , uno::UNO_QUERY_THROW );
+ mxLeavingBitmap.set( xLeavingSlide , UNO_QUERY_THROW );
+ mxEnteringBitmap.set( xEnteringSlide , UNO_QUERY_THROW );
+ Reference< XFastPropertySet > xLeavingSet( xLeavingSlide , UNO_QUERY );
+ Reference< XFastPropertySet > xEnteringSet( xEnteringSlide , UNO_QUERY );
geometry::IntegerRectangle2D SlideRect;
- SlideSize = LeavingSlideIntBitmap->getSize();
+ SlideSize = mxLeavingBitmap->getSize();
SlideRect.X1 = 0;
SlideRect.X2 = SlideSize.Width;
SlideRect.Y1 = 0;
SlideRect.Y2 = SlideSize.Height;
- LeavingBytes = LeavingSlideIntBitmap->getData(SlideBitmapLayout,SlideRect);
- EnteringBytes = EnteringSlideIntBitmap->getData(SlideBitmapLayout,SlideRect);
+ OSL_TRACE("leaving bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
+ SlideSize = mxEnteringBitmap->getSize();
+ OSL_TRACE("entering bitmap area: %dx%d", SlideSize.Width, SlideSize.Height);
-// TODO if(GLWin.ctx)//if we have a rendering context, let's init the slides
- GLInitSlides();
+#ifdef UNX
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+#endif
- OSL_ENSURE(SlideBitmapLayout.PlaneStride == 0,"only handle no plane stride now");
-}
+#ifdef DEBUG
+ t1 = microsec_clock::local_time();
+#endif
-namespace
-{
- struct OGLFormat
- {
- GLint nInternalFormat;
- GLenum eFormat;
- GLenum eType;
- };
+ mbUseLeavingPixmap = false;
+ mbUseEnteringPixmap = false;
- /* channel ordering: (0:rgba, 1:bgra, 2:argb, 3:abgr)
- */
- int calcComponentOrderIndex(const uno::Sequence<sal_Int8>& rTags)
- {
- using namespace rendering::ColorComponentTag;
+#ifdef UNX
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
- static const sal_Int8 aOrderTable[] =
- {
- RGB_RED, RGB_GREEN, RGB_BLUE, ALPHA,
- RGB_BLUE, RGB_GREEN, RGB_RED, ALPHA,
- ALPHA, RGB_RED, RGB_GREEN, RGB_BLUE,
- ALPHA, RGB_BLUE, RGB_GREEN, RGB_RED,
- };
+ if( mnGLXVersion >= 1.2999 && mbTextureFromPixmap && xLeavingSet.is() && xEnteringSet.is() && mbHasTFPVisual ) {
+ Sequence< Any > leaveArgs;
+ Sequence< Any > enterArgs;
+ if( (xLeavingSet->getFastPropertyValue( 1 ) >>= leaveArgs) &&
+ (xEnteringSet->getFastPropertyValue( 1 ) >>= enterArgs) ) {
+ OSL_TRACE ("pixmaps available");
- const sal_Int32 nNumComps(rTags.getLength());
- const sal_Int8* pLine=aOrderTable;
- for(int i=0; i<4; ++i)
- {
- int j=0;
- while( j<4 && j<nNumComps && pLine[j] == rTags[j] )
- ++j;
+ sal_Int32 depth;
- // all of the line passed, this is a match!
- if( j==nNumComps )
- return i;
+ leaveArgs[0] >>= mbFreeLeavingPixmap;
+ enterArgs[0] >>= mbFreeEnteringPixmap;
+ leaveArgs[1] >>= maLeavingPixmap;
+ enterArgs[1] >>= maEnteringPixmap;
+ leaveArgs[2] >>= depth;
- pLine+=4;
+ int pixmapAttribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+ GLX_MIPMAP_TEXTURE_EXT, True,
+ None };
+
+
+ // sync so that we possibly get an pending XError, before we set our handler.
+ // this way we will not miss any error from other code
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ int (*oldHandler)(unx::Display* /*dpy*/, unx::XErrorEvent* /*evnt*/);
+
+ // replace error handler temporarily
+ oldHandler = unx::XSetErrorHandler( oglErrorHandler );
+
+ errorTriggered = false;
+ LeavingPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maLeavingPixmap, pixmapAttribs );
+
+ // sync so that we possibly get an XError
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ if( !errorTriggered )
+ mbUseLeavingPixmap = true;
+ else {
+ OSL_TRACE("XError triggered");
+ if( mbFreeLeavingPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
+ mbFreeLeavingPixmap = false;
+ }
+ errorTriggered = false;
}
- return -1;
+ EnteringPixmap = glXCreatePixmap( GLWin.dpy, GLWin.fbc, maEnteringPixmap, pixmapAttribs );
+
+ // sync so that we possibly get an XError
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+
+ OSL_TRACE("created glx pixmap %p and %p depth: %d", LeavingPixmap, EnteringPixmap, depth);
+ if( !errorTriggered )
+ mbUseEnteringPixmap = true;
+ else {
+ OSL_TRACE("XError triggered");
+ if( mbFreeEnteringPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
+ mbFreeEnteringPixmap = false;
+ }
+ }
+
+ // restore the error handler
+ unx::XSetErrorHandler( oldHandler );
+ }
}
-}
+#endif
+#endif
+ if( !mbUseLeavingPixmap )
+ LeavingBytes = mxLeavingBitmap->getData(SlideBitmapLayout,SlideRect);
+ if( !mbUseEnteringPixmap )
+ EnteringBytes = mxEnteringBitmap->getData(SlideBitmapLayout,SlideRect);
+
+// TODO
+#ifdef UNX
+ if(GLWin.ctx)//if we have a rendering context, let's init the slides
+#endif
+ GLInitSlides();
-void OGLTransitionerImpl::GLInitSlides()
+ OSL_ENSURE(SlideBitmapLayout.PlaneStride == 0,"only handle no plane stride now");
+
+#ifdef UNX
+ /* flush & sync */
+ unx::glXWaitGL();
+ XSync( GLWin.dpy, false );
+
+ // synchronized X still gives us much smoother play
+ // I suspect some issues in above code in slideshow
+ // synchronize whole transition for now
+ XSynchronize( GLWin.dpy, true );
+ mbRestoreSync = true;
+#endif
+}
+
+void OGLTransitionerImpl::createTexture( unsigned int* texID,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::GLXPixmap pixmap,
+ bool usePixmap,
+#endif
+ bool useMipmap,
+ uno::Sequence<sal_Int8>& data,
+ const OGLFormat* pFormat )
{
- osl::MutexGuard const guard( m_aMutex );
+ glDeleteTextures( 1, texID );
+ glGenTextures( 1, texID );
+ glBindTexture( GL_TEXTURE_2D, *texID );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::PFNGLXBINDTEXIMAGEEXTPROC myglXBindTexImageEXT = (unx::PFNGLXBINDTEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXBindTexImageEXT" );
+
+ if( usePixmap ) {
+ if( mbGenerateMipmap )
+ glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, True);
+ myglXBindTexImageEXT (GLWin.dpy, pixmap, GLX_FRONT_LEFT_EXT, NULL);
+ if( mbGenerateMipmap && useMipmap ) {
+ OSL_TRACE("use mipmaps");
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
+ } else {
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ }
+ } else {
+#endif
+ if( !pFormat )
+ {
+ // force-convert color to ARGB8888 int color space
+ uno::Sequence<sal_Int8> tempBytes(
+ SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
+ data,
+ canvas::tools::getStdColorSpace()));
+ gluBuild2DMipmaps(GL_TEXTURE_2D,
+ 4,
+ SlideSize.Width,
+ SlideSize.Height,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ &tempBytes[0]);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //TRILINEAR FILTERING
- if (isDisposed())
- return;
+ //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
+ GLfloat largest_supported_anisotropy;
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
+ } else {
+ if( pTransition && !cbBrokenTexturesATI && !useMipmap) {
+ glTexImage2D( GL_TEXTURE_2D, 0, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, 0, pFormat->eFormat, pFormat->eType, &data[0] );
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ } else {
+ gluBuild2DMipmaps( GL_TEXTURE_2D, pFormat->nInternalFormat, SlideSize.Width, SlideSize.Height, pFormat->eFormat, pFormat->eType, &data[0] );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); //TRILINEAR FILTERING
+
+ //anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
+ GLfloat largest_supported_anisotropy;
+ glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy );
+ }
+ }
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ }
+#endif
+ OSL_ENSURE(glIsTexture(*texID), "Can't generate Leaving slide textures in OpenGL");
+}
+void OGLTransitionerImpl::prepareEnvironment()
+{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double EyePos(10.0);
@@ -457,7 +947,10 @@ void OGLTransitionerImpl::GLInitSlides()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0,0,-EyePos);
+}
+const OGLFormat* OGLTransitionerImpl::chooseFormats()
+{
const OGLFormat* pDetectedFormat=NULL;
uno::Reference<rendering::XIntegerBitmapColorSpace> xIntColorSpace(
SlideBitmapLayout.ColorSpace);
@@ -473,10 +966,10 @@ void OGLTransitionerImpl::GLInitSlides()
static const OGLFormat lcl_RGB24[] =
{
// 24 bit RGB
+ {3, GL_BGR, GL_UNSIGNED_BYTE},
{3, GL_RGB, GL_UNSIGNED_BYTE},
-// {3, GL_BGR, GL_UNSIGNED_BYTE},
- {3, GL_RGB, GL_UNSIGNED_BYTE},
- // {3, GL_BGR, GL_UNSIGNED_BYTE}
+ {3, GL_BGR, GL_UNSIGNED_BYTE},
+ {3, GL_RGB, GL_UNSIGNED_BYTE}
};
#if defined(GL_VERSION_1_2) && defined(GLU_VERSION_1_3)
@@ -484,37 +977,37 @@ void OGLTransitionerImpl::GLInitSlides()
static const OGLFormat lcl_RGB16[] =
{
// 16 bit RGB
- {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
{3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
{3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
- {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}
+ {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV},
+ {3, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}
};
static const OGLFormat lcl_ARGB16_4[] =
{
// 16 bit ARGB
- {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
-// {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
- // {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
- {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4},
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}
};
static const OGLFormat lcl_ARGB16_5[] =
{
// 16 bit ARGB
- {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
- // {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
- // {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
- {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV},
+ {4, GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1},
+ {4, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}
};
static const OGLFormat lcl_ARGB32[] =
{
// 32 bit ARGB
- {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8},
-// {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
- // {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
- {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}
+ {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
+ {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
+ {4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8},
+ {4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
};
const uno::Sequence<sal_Int8> aComponentTags(
@@ -572,95 +1065,78 @@ void OGLTransitionerImpl::GLInitSlides()
#endif
}
- glDeleteTextures(1,&GLleavingSlide);
+ return pDetectedFormat;
+}
- glGenTextures(1, &GLleavingSlide);
- glBindTexture(GL_TEXTURE_2D, GLleavingSlide);
- if( !pDetectedFormat )
- {
- // force-convert color to ARGB8888 int color space
- uno::Sequence<sal_Int8> tempBytes(
- SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
- LeavingBytes,
- canvas::tools::getStdColorSpace()));
- gluBuild2DMipmaps(GL_TEXTURE_2D,
- 4,
- SlideSize.Width,
- SlideSize.Height,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- &tempBytes[0]);
- }
- else
- {
- gluBuild2DMipmaps(GL_TEXTURE_2D,
- pDetectedFormat->nInternalFormat,
- SlideSize.Width,
- SlideSize.Height,
- pDetectedFormat->eFormat,
- pDetectedFormat->eType,
- &LeavingBytes[0]);
- }
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);//TRILINEAR FILTERING
- GLfloat largest_supported_anisotropy;
- glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);//anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
+void OGLTransitionerImpl::GLInitSlides()
+{
+ osl::MutexGuard const guard( m_aMutex );
- OSL_ENSURE(glIsTexture(GLleavingSlide), "Can't generate Leaving slide textures in OpenGL");
+ if (isDisposed() || pTransition->mnRequiredGLVersion > cnGLVersion)
+ return;
- glDeleteTextures(1,&GLenteringSlide);
+ prepareEnvironment();
- glGenTextures(1, &GLenteringSlide);
- glBindTexture(GL_TEXTURE_2D, GLenteringSlide);
- if( !pDetectedFormat )
- {
- // force-convert color to ARGB8888 int color space
- uno::Sequence<sal_Int8> tempBytes(
- SlideBitmapLayout.ColorSpace->convertToIntegerColorSpace(
- EnteringBytes,
- canvas::tools::getStdColorSpace()));
- gluBuild2DMipmaps(GL_TEXTURE_2D,
- 4,
- SlideSize.Width,
- SlideSize.Height,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- &tempBytes[0]);
- }
- else
- {
- gluBuild2DMipmaps(GL_TEXTURE_2D,
- pDetectedFormat->nInternalFormat,
- SlideSize.Width,
- SlideSize.Height,
- pDetectedFormat->eFormat,
- pDetectedFormat->eType,
- &EnteringBytes[0]);
- }
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);//TRILINEAR FILTERING
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);//anistropic filtering (to make texturing not suck when looking at polygons from oblique angles)
+ const OGLFormat* pFormat = NULL;
+ if( !mbUseLeavingPixmap || !mbUseEnteringPixmap )
+ pFormat = chooseFormats();
+
+ createTexture( &GLleavingSlide,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ LeavingPixmap,
+ mbUseLeavingPixmap,
+#endif
+ pTransition->mbUseMipMapLeaving,
+ LeavingBytes,
+ pFormat );
+
+ createTexture( &GLenteringSlide,
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ EnteringPixmap,
+ mbUseEnteringPixmap,
+#endif
+ pTransition->mbUseMipMapEntering,
+ EnteringBytes,
+ pFormat );
+
+#ifdef UNX
+ unx::glXWaitGL();
+ XSync(GLWin.dpy, false);
+#endif
- OSL_ENSURE( glIsTexture(GLenteringSlide), "Can't generate entering slide textures in OpenGL" );
+#ifdef DEBUG
+ t2 = microsec_clock::local_time();
+ OSL_TRACE("textures created in: %s", to_simple_string( t2 - t1 ).c_str());
+#endif
}
void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeException)
{
+#ifdef DEBUG
+ frame_count ++;
+ t3 = microsec_clock::local_time();
+ if( frame_count == 1 ) {
+ t5 = t3;
+ total_update = seconds (0);
+ }
+#endif
osl::MutexGuard const guard( m_aMutex );
- if (isDisposed())
+ if (isDisposed() || !cbGLXPresent || pTransition->mnRequiredGLVersion > cnGLVersion)
return;
+#ifdef WNT
+ wglMakeCurrent(GLWin.hDC,GLWin.hRC);
+#endif
+#ifdef UNX
+ glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+#endif
+
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(pTransition)
- pTransition->display( nTime , GLleavingSlide , GLenteringSlide ,
+ pTransition->display( nTime, GLleavingSlide, GLenteringSlide,
SlideSize.Width, SlideSize.Height,
static_cast<double>(GLWin.Width),
static_cast<double>(GLWin.Height) );
@@ -672,38 +1148,153 @@ void SAL_CALL OGLTransitionerImpl::update( double nTime ) throw (uno::RuntimeExc
#endif
if( pWindow )
pWindow->Show();
+
+#ifdef UNX
+ /* flush & sync */
+ unx::glXWaitGL();
+ XSync( GLWin.dpy, false );
+#endif
+
+#ifdef DEBUG
+ t4 = microsec_clock::local_time();
+
+ OSL_TRACE("update time: %f", nTime);
+ OSL_TRACE("update took: %s", to_simple_string( t4 - t3 ).c_str());
+ total_update += (t4 - t3);
+#endif
}
-// we are about to be disposed (someone call dispose() on us)
-void OGLTransitionerImpl::disposing()
+void SAL_CALL OGLTransitionerImpl::viewChanged( const Reference< presentation::XSlideShowView >& rView,
+ const Reference< rendering::XBitmap >& rLeavingBitmap,
+ const Reference< rendering::XBitmap >& rEnteringBitmap )
+ throw (uno::RuntimeException)
{
- osl::MutexGuard const guard( m_aMutex );
- glDeleteTextures(1,&GLleavingSlide);
- glDeleteTextures(1,&GLenteringSlide);
+ OSL_TRACE("transitioner: view changed");
- if (pTransition)
- pTransition->finish();
+ disposeTextures();
+ disposeContextAndWindow();
+ initWindowFromSlideShowView( rView );
+ setSlides( rLeavingBitmap, rEnteringBitmap );
+}
+void OGLTransitionerImpl::disposeContextAndWindow()
+{
#if defined( WNT )
if (GLWin.hRC)
{
- wglMakeCurrent( GLWin.hDC, 0 ); // kill Device Context
- wglDeleteContext( GLWin.hRC ); // Kill Render Context
- ReleaseDC( GLWin.hWnd, GLWin.hDC );// Release Window
+ wglMakeCurrent( GLWin.hDC, 0 ); // kill Device Context
+ wglDeleteContext( GLWin.hRC ); // Kill Render Context
+ ReleaseDC( GLWin.hWnd, GLWin.hDC ); // Release Window
}
#elif defined( UNX )
if(GLWin.ctx)
{
- OSL_ENSURE( glXMakeCurrent(GLWin.dpy, None, NULL) , "Error releasing glX context" );
- glXDestroyContext(GLWin.dpy, GLWin.ctx);
- GLWin.ctx = NULL;
+ glXMakeCurrent(GLWin.dpy, None, NULL);
+ if( glGetError() != GL_NO_ERROR ) {
+ OSL_TRACE("glError: %s", (char *)gluErrorString(glGetError()));
+ }
+ glXDestroyContext(GLWin.dpy, GLWin.ctx);
+ GLWin.ctx = NULL;
+ }
+#endif
+ if( pWindow ) {
+ delete pWindow;
+ pWindow = NULL;
+ GLWin.win = 0;
+ }
+}
+
+void OGLTransitionerImpl::disposeTextures()
+{
+#ifdef WNT
+ wglMakeCurrent(GLWin.hDC,GLWin.hRC);
+#endif
+#ifdef UNX
+ glXMakeCurrent( GLWin.dpy, GLWin.win, GLWin.ctx );
+#endif
+
+#if defined( GLX_VERSION_1_3 ) && defined( GLX_EXT_texture_from_pixmap )
+ unx::PFNGLXRELEASETEXIMAGEEXTPROC myglXReleaseTexImageEXT = (unx::PFNGLXRELEASETEXIMAGEEXTPROC) unx::glXGetProcAddress( (const GLubyte*) "glXReleaseTexImageEXT" );
+ if( mbUseLeavingPixmap ) {
+
+ myglXReleaseTexImageEXT( GLWin.dpy, LeavingPixmap, GLX_FRONT_LEFT_EXT );
+ glXDestroyGLXPixmap( GLWin.dpy, LeavingPixmap );
+ LeavingPixmap = 0;
+ if( mbFreeLeavingPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maLeavingPixmap );
+ mbFreeLeavingPixmap = false;
+ maLeavingPixmap = 0;
+ }
+ }
+ if( mbUseEnteringPixmap ) {
+ myglXReleaseTexImageEXT( GLWin.dpy, EnteringPixmap, GLX_FRONT_LEFT_EXT );
+ glXDestroyGLXPixmap( GLWin.dpy, EnteringPixmap );
+ EnteringPixmap = 0;
+ if( mbFreeEnteringPixmap ) {
+ unx::XFreePixmap( GLWin.dpy, maEnteringPixmap );
+ mbFreeEnteringPixmap = false;
+ maEnteringPixmap = 0;
+ }
+ }
+#endif
+
+ if( !mbUseLeavingPixmap ) {
+ glDeleteTextures(1,&GLleavingSlide);
+ GLleavingSlide = 0;
+ }
+ if( !mbUseEnteringPixmap ) {
+ glDeleteTextures(1,&GLenteringSlide);
+ GLleavingSlide = 0;
+ }
+
+ mbUseLeavingPixmap = false;
+ mbUseEnteringPixmap = false;
+}
+
+// we are about to be disposed (someone call dispose() on us)
+void OGLTransitionerImpl::disposing()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+#ifdef DEBUG
+ OSL_TRACE("dispose %p\n", this);
+ if( frame_count ) {
+ t6 = microsec_clock::local_time();
+ time_duration duration = t6 - t5;
+ OSL_TRACE("whole transition (frames: %d) took: %s fps: %f time spent in updates: %s percentage of transition time: %f%%",
+ frame_count, to_simple_string( duration ).c_str(),
+ ((double)frame_count*1000000000.0)/duration.total_nanoseconds(),
+ to_simple_string( total_update ).c_str(),
+ 100*(((double)total_update.total_nanoseconds())/((double)duration.total_nanoseconds()))
+ );
+ }
+#endif
+
+ if( pWindow ) {
+
+ disposeTextures();
+
+ if (pTransition)
+ pTransition->finish();
+
+#ifdef UNX
+ if( mbRestoreSync ) {
+ // try to reestablish synchronize state
+ char* sal_synchronize = getenv("SAL_SYNCHRONIZE");
+ XSynchronize( GLWin.dpy, sal_synchronize && *sal_synchronize == '1' );
}
#endif
- if (pWindow)
- delete pWindow;
+
+ disposeContextAndWindow();
+ }
+
if (pTransition)
delete pTransition;
+
+ mxLeavingBitmap.clear();
+ mxEnteringBitmap.clear();
+ mxView.clear();
}
OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) :
@@ -712,8 +1303,12 @@ OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) :
GLleavingSlide( 0 ),
GLenteringSlide( 0 ),
pWindow( NULL ),
+ mxView(),
EnteringBytes(),
LeavingBytes(),
+ mbRestoreSync( false ),
+ mbUseLeavingPixmap( false ),
+ mbUseEnteringPixmap( false ),
SlideBitmapLayout(),
SlideSize(),
pTransition(pOGLTransition)
@@ -723,6 +1318,8 @@ OGLTransitionerImpl::OGLTransitionerImpl(OGLTransitionImpl* pOGLTransition) :
#elif defined( UNX )
GLWin.ctx = 0;
#endif
+
+ DBG(frame_count = 0);
}
typedef cppu::WeakComponentImplHelper1<presentation::XTransitionFactory> OGLTransitionFactoryImplBase;
@@ -737,26 +1334,38 @@ public:
// XTransitionFactory
virtual ::sal_Bool SAL_CALL hasTransition( ::sal_Int16 transitionType, ::sal_Int16 transitionSubType ) throw (uno::RuntimeException)
{
- if( transitionType != animations::TransitionType::MISCSHAPEWIPE )
+ if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
+ switch( transitionSubType )
+ {
+ case animations::TransitionSubType::ACROSS:
+ case animations::TransitionSubType::CORNERSOUT:
+ case animations::TransitionSubType::CIRCLE:
+ case animations::TransitionSubType::FANOUTHORIZONTAL:
+ case animations::TransitionSubType::CORNERSIN:
+ case animations::TransitionSubType::LEFTTORIGHT:
+ case animations::TransitionSubType::TOPTOBOTTOM:
+ case animations::TransitionSubType::TOPRIGHT:
+ case animations::TransitionSubType::TOPLEFT:
+ case animations::TransitionSubType::BOTTOMRIGHT:
+ case animations::TransitionSubType::BOTTOMLEFT:
+ case animations::TransitionSubType::TOPCENTER:
+ case animations::TransitionSubType::RIGHTCENTER:
+ case animations::TransitionSubType::BOTTOMCENTER:
+ return sal_True;
+
+ default:
+ return sal_False;
+ }
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
+ return sal_True;
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
+ return sal_True;
+ } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
+ return sal_True;
+ } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
+ return sal_True;
+ } else
return sal_False;
-
- switch( transitionSubType )
- {
- case animations::TransitionSubType::ACROSS:
- case animations::TransitionSubType::CORNERSOUT:
- case animations::TransitionSubType::CIRCLE:
- case animations::TransitionSubType::FANOUTHORIZONTAL:
- case animations::TransitionSubType::CORNERSIN:
- case animations::TransitionSubType::LEFTTORIGHT:
- case animations::TransitionSubType::TOPTOBOTTOM:
- case animations::TransitionSubType::TOPRIGHT:
- case animations::TransitionSubType::TOPLEFT:
- case animations::TransitionSubType::BOTTOMRIGHT:
- return sal_True;
-
- default:
- return sal_False;
- }
}
virtual uno::Reference< presentation::XTransition > SAL_CALL createTransition(
@@ -764,53 +1373,91 @@ public:
::sal_Int16 transitionSubType,
const uno::Reference< presentation::XSlideShowView >& view,
const uno::Reference< rendering::XBitmap >& leavingBitmap,
- const uno::Reference< rendering::XBitmap >& enteringBitmap,
- const geometry::RealPoint2D& slideOffset ) throw (uno::RuntimeException)
+ const uno::Reference< rendering::XBitmap >& enteringBitmap )
+ throw (uno::RuntimeException)
{
- if( transitionType != animations::TransitionType::MISCSHAPEWIPE )
+ if( !hasTransition( transitionType, transitionSubType ) )
return uno::Reference< presentation::XTransition >();
- OGLTransitionImpl* pTransition = new OGLTransitionImpl();
- switch( transitionSubType )
- {
- case animations::TransitionSubType::ACROSS:
- pTransition->makeNByMTileFlip(8,6);
- break;
- case animations::TransitionSubType::CORNERSOUT:
- pTransition->makeOutsideCubeFaceToLeft();
- break;
- case animations::TransitionSubType::CIRCLE:
- pTransition->makeRevolvingCircles(8,128);
- break;
- case animations::TransitionSubType::FANOUTHORIZONTAL:
- pTransition->makeHelix(20);
- break;
- case animations::TransitionSubType::CORNERSIN:
- pTransition->makeInsideCubeFaceToLeft();
- break;
- case animations::TransitionSubType::LEFTTORIGHT:
- pTransition->makeFallLeaving();
- break;
- case animations::TransitionSubType::TOPTOBOTTOM:
- pTransition->makeTurnAround();
- break;
- case animations::TransitionSubType::TOPRIGHT:
- pTransition->makeTurnDown();
- break;
- case animations::TransitionSubType::TOPLEFT:
- pTransition->makeIris();
- break;
- case animations::TransitionSubType::BOTTOMRIGHT:
- pTransition->makeRochade();
- break;
- default:
- return uno::Reference< presentation::XTransition >();
+ bool bGLXPresent = OGLTransitionerImpl::initialize( view );
+
+ if( OGLTransitionerImpl::cbMesa && (
+ ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) ||
+ ( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) ||
+ ( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) ) )
+ return uno::Reference< presentation::XTransition >();
+
+
+ OGLTransitionImpl* pTransition = NULL;
+
+ if( transitionType == animations::TransitionType::MISCSHAPEWIPE ) {
+ pTransition = new OGLTransitionImpl();
+ switch( transitionSubType )
+ {
+ case animations::TransitionSubType::ACROSS:
+ pTransition->makeNByMTileFlip(8,6);
+ break;
+ case animations::TransitionSubType::CORNERSOUT:
+ pTransition->makeOutsideCubeFaceToLeft();
+ break;
+ case animations::TransitionSubType::CIRCLE:
+ pTransition->makeRevolvingCircles(8,128);
+ break;
+ case animations::TransitionSubType::FANOUTHORIZONTAL:
+ pTransition->makeHelix(20);
+ break;
+ case animations::TransitionSubType::CORNERSIN:
+ pTransition->makeInsideCubeFaceToLeft();
+ break;
+ case animations::TransitionSubType::LEFTTORIGHT:
+ pTransition->makeFallLeaving();
+ break;
+ case animations::TransitionSubType::TOPTOBOTTOM:
+ pTransition->makeTurnAround();
+ break;
+ case animations::TransitionSubType::TOPRIGHT:
+ pTransition->makeTurnDown();
+ break;
+ case animations::TransitionSubType::TOPLEFT:
+ pTransition->makeIris();
+ break;
+ case animations::TransitionSubType::BOTTOMRIGHT:
+ pTransition->makeRochade();
+ break;
+ case animations::TransitionSubType::BOTTOMLEFT:
+ pTransition->makeVenetianBlinds( true, 8 );
+ break;
+ case animations::TransitionSubType::TOPCENTER:
+ pTransition->makeVenetianBlinds( false, 6 );
+ break;
+ case animations::TransitionSubType::RIGHTCENTER:
+ pTransition->makeStatic();
+ break;
+ case animations::TransitionSubType::BOTTOMCENTER:
+ pTransition->makeDissolve();
+ break;
+ }
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::CROSSFADE ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeFadeSmoothly();
+ } else if( transitionType == animations::TransitionType::FADE && transitionSubType == animations::TransitionSubType::FADEOVERCOLOR ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeFadeThroughBlack();
+ } else if( transitionType == animations::TransitionType::IRISWIPE && transitionSubType == animations::TransitionSubType::DIAMOND ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeDiamond();
+ } else if( transitionType == animations::TransitionType::ZOOM && transitionSubType == animations::TransitionSubType::ROTATEIN ) {
+ pTransition = new OGLTransitionImpl();
+ pTransition->makeNewsflash();
}
rtl::Reference<OGLTransitionerImpl> xRes(
new OGLTransitionerImpl(pTransition) );
- xRes->initWindowFromSlideShowView(view,slideOffset.X,slideOffset.Y);
- xRes->setSlides(leavingBitmap,enteringBitmap);
+ if( bGLXPresent ) {
+ if( !xRes->initWindowFromSlideShowView(view))
+ return uno::Reference< presentation::XTransition >();
+ xRes->setSlides(leavingBitmap,enteringBitmap);
+ }
return uno::Reference<presentation::XTransition>(xRes.get());
}