From f4f03d7b2d217e6b1da12499b2750410605dfa29 Mon Sep 17 00:00:00 2001 From: ouv Date: Thu, 15 Dec 2011 07:09:29 +0000 Subject: [PATCH] GUITHARE 2011. Issue 0000837: External 0020550: Dump VTK WIndows 7 --- src/SVTK/SVTK_FrameBuffer.cxx | 202 ++++++++++++++++++++++++++++++++++ src/SVTK/SVTK_FrameBuffer.h | 52 +++++++++ src/SVTK/SVTK_ViewWindow.cxx | 61 ++++++++-- src/SVTK/SVTK_ViewWindow.h | 2 + 4 files changed, 308 insertions(+), 9 deletions(-) create mode 100644 src/SVTK/SVTK_FrameBuffer.cxx create mode 100644 src/SVTK/SVTK_FrameBuffer.h diff --git a/src/SVTK/SVTK_FrameBuffer.cxx b/src/SVTK/SVTK_FrameBuffer.cxx new file mode 100644 index 000000000..63f2d80ad --- /dev/null +++ b/src/SVTK/SVTK_FrameBuffer.cxx @@ -0,0 +1,202 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SVTK_FrameBuffer.cxx +// Module : SALOME +// +#include "SVTK_FrameBuffer.h" + +#include + +#include + +#ifndef WNT +# ifndef GLX_GLXEXT_LEGACY +# define GLX_GLXEXT_LEGACY +# endif +# include +# include +#else +# include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifndef GL_FRAMEBUFFER_EXT +#define GL_FRAMEBUFFER_EXT 0x8D40 +#endif + +#ifndef GL_RENDERBUFFER_EXT +#define GL_RENDERBUFFER_EXT 0x8D41 +#endif + +#ifndef GL_COLOR_ATTACHMENT0_EXT +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#endif + +#ifndef GL_DEPTH_ATTACHMENT_EXT +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#endif + +#ifndef GL_FRAMEBUFFER_COMPLETE_EXT +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#endif + +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); + +static PFNGLGENFRAMEBUFFERSEXTPROC vglGenFramebuffersEXT = NULL; +static PFNGLBINDFRAMEBUFFEREXTPROC vglBindFramebufferEXT = NULL; +static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC vglFramebufferTexture2DEXT = NULL; +static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC vglCheckFramebufferStatusEXT = NULL; +static PFNGLDELETEFRAMEBUFFERSEXTPROC vglDeleteFramebuffersEXT = NULL; +static PFNGLGENRENDERBUFFERSEXTPROC vglGenRenderbuffersEXT = NULL; +static PFNGLBINDRENDERBUFFEREXTPROC vglBindRenderbufferEXT = NULL; +static PFNGLRENDERBUFFERSTORAGEEXTPROC vglRenderbufferStorageEXT = NULL; +static PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC vglFramebufferRenderbufferEXT = NULL; +static PFNGLDELETERENDERBUFFERSEXTPROC vglDeleteRenderbuffersEXT = NULL; + +#ifndef WNT +#define GL_GetProcAddress( x ) glXGetProcAddressARB( (const GLubyte*)x ) +#else +#define GL_GetProcAddress( x ) wglGetProcAddress( (const LPCSTR)x ) +#endif + +bool InitializeEXT() +{ + vglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)GL_GetProcAddress( "glGenFramebuffersEXT" ); + vglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)GL_GetProcAddress( "glBindFramebufferEXT" ); + vglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)GL_GetProcAddress( "glFramebufferTexture2DEXT" ); + vglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)GL_GetProcAddress( "glCheckFramebufferStatusEXT" ); + vglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)GL_GetProcAddress( "glDeleteFramebuffersEXT" ); + vglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)GL_GetProcAddress( "glGenRenderbuffersEXT" ); + vglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)GL_GetProcAddress( "glBindRenderbufferEXT" ); + vglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)GL_GetProcAddress( "glRenderbufferStorageEXT" ); + vglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)GL_GetProcAddress( "glFramebufferRenderbufferEXT" ); + vglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)GL_GetProcAddress( "glDeleteRenderbuffersEXT" ); + + bool ok = vglGenFramebuffersEXT && vglBindFramebufferEXT && vglFramebufferTexture2DEXT && + vglCheckFramebufferStatusEXT && vglDeleteFramebuffersEXT && vglGenRenderbuffersEXT && + vglBindRenderbufferEXT && vglRenderbufferStorageEXT && vglFramebufferRenderbufferEXT && + vglDeleteRenderbuffersEXT; + + return ok; +} + +static bool IsEXTInitialized = InitializeEXT(); + +SVTK_FrameBuffer::SVTK_FrameBuffer() + : textureId( 0 ), + fboId( 0 ), + rboId( 0 ) +{ +} + +SVTK_FrameBuffer::~SVTK_FrameBuffer() +{ + release(); +} + +bool SVTK_FrameBuffer::init( const GLsizei& xSize, const GLsizei& ySize ) +{ + char* ext = (char*)glGetString( GL_EXTENSIONS ); + if( !IsEXTInitialized || + strstr( ext, "GL_EXT_framebuffer_object" ) == NULL ) + { + MESSAGE( "Initializing OpenGL FrameBuffer extension failed" ); + return false; + } + + // create a texture object + glEnable( GL_TEXTURE_2D ); + glGenTextures( 1, &textureId ); + glBindTexture( GL_TEXTURE_2D, textureId ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, xSize, ySize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); + glBindTexture( GL_TEXTURE_2D, 0 ); + + // create a renderbuffer object to store depth info + vglGenRenderbuffersEXT( 1, &rboId ); + vglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rboId ); + vglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, xSize, ySize ); + vglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 ); + + // create a framebuffer object + vglGenFramebuffersEXT( 1, &fboId ); + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId ); + + // attach the texture to FBO color attachment point + vglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0 ); + + // attach the renderbuffer to depth attachment point + vglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId ); + + // check FBO status + GLenum status = vglCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + + // Unbind FBO + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); + + return status == GL_FRAMEBUFFER_COMPLETE_EXT; +} + +void SVTK_FrameBuffer::release() +{ + if( !IsEXTInitialized ) + return; + + glDeleteTextures( 1, &textureId ); + textureId = 0; + + vglDeleteFramebuffersEXT( 1, &fboId ); + fboId = 0; + + vglDeleteRenderbuffersEXT( 1, &rboId ); + rboId = 0; +} + +void SVTK_FrameBuffer::bind() +{ + if( !IsEXTInitialized ) + return; + + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId ); +} + +void SVTK_FrameBuffer::unbind() +{ + if( !IsEXTInitialized ) + return; + + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); +} diff --git a/src/SVTK/SVTK_FrameBuffer.h b/src/SVTK/SVTK_FrameBuffer.h new file mode 100644 index 000000000..07224e039 --- /dev/null +++ b/src/SVTK/SVTK_FrameBuffer.h @@ -0,0 +1,52 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SVTK_FrameBuffer.h +// Module : SALOME +// +#ifndef SVTK_FRAMEBUFFER_H +#define SVTK_FRAMEBUFFER_H + +#include "SVTK.h" + +#ifdef WIN32 +#include +#endif + +#include + +class SVTK_EXPORT SVTK_FrameBuffer +{ +public: + SVTK_FrameBuffer(); + ~SVTK_FrameBuffer(); + + bool init( const GLsizei&, const GLsizei& ); + void release(); + + void bind(); + void unbind(); + +private: + GLuint textureId; + GLuint fboId; + GLuint rboId; +}; + +#endif diff --git a/src/SVTK/SVTK_ViewWindow.cxx b/src/SVTK/SVTK_ViewWindow.cxx index 3093d1ba5..abfe67de3 100755 --- a/src/SVTK/SVTK_ViewWindow.cxx +++ b/src/SVTK/SVTK_ViewWindow.cxx @@ -73,6 +73,7 @@ #include "SVTK_Selector.h" #include "SVTK_Recorder.h" #include "SVTK_RecorderDlg.h" +#include "SVTK_FrameBuffer.h" #include "SALOME_ListIteratorOfListIO.hxx" @@ -862,17 +863,61 @@ void SVTK_ViewWindow::RemoveActor( VTKViewer_Actor* theActor, emit actorRemoved(theActor); } +/*! + Auxiliary method intended to dump contents of the view to an image +*/ +QImage SVTK_ViewWindow::dumpViewContent() +{ + vtkRenderWindow* aWindow = getRenderWindow(); + int* aSize = aWindow->GetSize(); + int aWidth = aSize[0]; + int aHeight = aSize[1]; + + SVTK_FrameBuffer aFrameBuffer; + if( aFrameBuffer.init( aWidth, aHeight ) ) + { + glPushAttrib( GL_VIEWPORT_BIT ); + glViewport( 0, 0, aWidth, aHeight ); + aFrameBuffer.bind(); + + // draw scene + aWindow->Render(); + + aFrameBuffer.unbind(); + glPopAttrib(); + + QImage anImage( aWidth, aHeight, QImage::Format_RGB32 ); + + aFrameBuffer.bind(); + glReadPixels( 0, 0, aWidth, aHeight, GL_RGBA, GL_UNSIGNED_BYTE, anImage.bits() ); + aFrameBuffer.unbind(); + + anImage = anImage.rgbSwapped(); + anImage = anImage.mirrored(); + return anImage; + } + + // if frame buffers are unsupported, use old functionality + unsigned char *aData = + aWindow->GetRGBACharPixelData( 0, 0, aWidth-1, aHeight-1, 0 ); + + QImage anImage( aData, aWidth, aHeight, QImage::Format_ARGB32 ); + + anImage = anImage.rgbSwapped(); + anImage = anImage.mirrored(); + return anImage; +} + /*! \return QImage, containing all scene rendering in window */ QImage SVTK_ViewWindow::dumpView() { -// if ( myMainWindow->getToolBar()->testAttribute(Qt::WA_UnderMouse) || myDumpImage.isNull() ) -// return myMainWindow->dumpView(); - -// return myDumpImage; - QPixmap px = QPixmap::grabWindow( GetInteractor()->winId() ); - return px.toImage(); + if( myDumpImage.isNull() ) + return dumpViewContent(); + + RefreshDumpImage(); + return myDumpImage; } QString SVTK_ViewWindow::filter() const @@ -919,9 +964,7 @@ bool SVTK_ViewWindow::dumpViewToFormat( const QImage& img, const QString& fileNa */ void SVTK_ViewWindow::RefreshDumpImage() { - //myDumpImage = myMainWindow->dumpView(); - QPixmap px = QPixmap::grabWindow( GetInteractor()->winId() ); - myDumpImage = px.toImage(); + myDumpImage = dumpViewContent(); } /*! diff --git a/src/SVTK/SVTK_ViewWindow.h b/src/SVTK/SVTK_ViewWindow.h index b3b8ba34e..0afebefce 100755 --- a/src/SVTK/SVTK_ViewWindow.h +++ b/src/SVTK/SVTK_ViewWindow.h @@ -345,6 +345,8 @@ protected: void doSetVisualParameters( const QString& ); void SetEventDispatcher(vtkObject* theDispatcher); + QImage dumpViewContent(); + virtual QString filter() const; virtual bool dumpViewToFormat( const QImage& img, const QString& fileName, const QString& format ); -- 2.39.2