From 08771175f92acfa2ed90b38baaea87e44880b50f Mon Sep 17 00:00:00 2001 From: dmv Date: Tue, 27 Jul 2010 15:20:27 +0000 Subject: [PATCH] Correct Dump view and integrate DLViewer_FrameBuffer to use it in Diagram module. --- src/GLViewer/GLViewer_FrameBuffer.cxx | 196 ++++++++++++++++++++++++++ src/GLViewer/GLViewer_FrameBuffer.h | 53 +++++++ src/GLViewer/GLViewer_ViewFrame.cxx | 38 ++++- src/GLViewer/Makefile.am | 9 +- 4 files changed, 289 insertions(+), 7 deletions(-) create mode 100755 src/GLViewer/GLViewer_FrameBuffer.cxx create mode 100755 src/GLViewer/GLViewer_FrameBuffer.h diff --git a/src/GLViewer/GLViewer_FrameBuffer.cxx b/src/GLViewer/GLViewer_FrameBuffer.cxx new file mode 100755 index 000000000..51e7ee9b5 --- /dev/null +++ b/src/GLViewer/GLViewer_FrameBuffer.cxx @@ -0,0 +1,196 @@ +// Copyright (C) 2007-2010 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 : GLViewer_FrameBuffer.cxx +// Module : SALOME +// +#include "GLViewer_FrameBuffer.h" + +#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; +} + +GLViewer_FrameBuffer::GLViewer_FrameBuffer() + : textureId( 0 ), + fboId( 0 ), + rboId( 0 ), + myIsInitializeEXT ( false ) +{ +} + +GLViewer_FrameBuffer::~GLViewer_FrameBuffer() +{ + release(); +} + +bool GLViewer_FrameBuffer::init( const GLsizei& xSize, const GLsizei& ySize ) +{ + myIsInitializeEXT = InitializeEXT(); + char* ext = (char*)glGetString( GL_EXTENSIONS ); + if( !myIsInitializeEXT || strstr( ext, "GL_EXT_framebuffer_object" ) == NULL ) + 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 GLViewer_FrameBuffer::release() +{ + if( !myIsInitializeEXT ) + return; + + glDeleteTextures( 1, &textureId ); + textureId = 0; + + vglDeleteFramebuffersEXT( 1, &fboId ); + fboId = 0; + + vglDeleteRenderbuffersEXT( 1, &rboId ); + rboId = 0; +} + +void GLViewer_FrameBuffer::bind() +{ + if( !myIsInitializeEXT ) + return; + + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId ); +} + +void GLViewer_FrameBuffer::unbind() +{ + if( !myIsInitializeEXT ) + return; + + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); +} diff --git a/src/GLViewer/GLViewer_FrameBuffer.h b/src/GLViewer/GLViewer_FrameBuffer.h new file mode 100755 index 000000000..83627d011 --- /dev/null +++ b/src/GLViewer/GLViewer_FrameBuffer.h @@ -0,0 +1,53 @@ +// Copyright (C) 2007-2010 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 : GLViewer_FrameBuffer.h +// Module : SALOME +// +#ifndef GLVIEWER_FRAMEBUFFER_H +#define GLVIEWER_FRAMEBUFFER_H + +#include "GLViewer.h" + +#ifdef WIN32 +#include +#endif + +#include + +class GLVIEWER_API GLViewer_FrameBuffer +{ +public: + GLViewer_FrameBuffer(); + ~GLViewer_FrameBuffer(); + + bool init( const GLsizei&, const GLsizei& ); + void release(); + + void bind(); + void unbind(); + +private: + GLuint textureId; + GLuint fboId; + GLuint rboId; + bool myIsInitializeEXT; +}; + +#endif diff --git a/src/GLViewer/GLViewer_ViewFrame.cxx b/src/GLViewer/GLViewer_ViewFrame.cxx index 86a3436d0..b3a2cbfcd 100644 --- a/src/GLViewer/GLViewer_ViewFrame.cxx +++ b/src/GLViewer/GLViewer_ViewFrame.cxx @@ -26,6 +26,7 @@ #include "GLViewer_ViewFrame.h" #include "GLViewer_Viewer.h" #include "GLViewer_ViewPort2d.h" +#include "GLViewer_FrameBuffer.h" #include #include @@ -270,13 +271,42 @@ void GLViewer_ViewFrame::onUpdate( int ) QImage GLViewer_ViewFrame::dumpView() { - QImage img; + GLViewer_ViewPort2d* aViewPort = ((GLViewer_ViewPort2d*)myVP); + int aWidth = aViewPort->getWidth(); + int aHeight = aViewPort->getHeight(); + + GLViewer_FrameBuffer aFrameBuffer; + if( aFrameBuffer.init( aWidth, aHeight ) ) + { + glPushAttrib( GL_VIEWPORT_BIT ); + glViewport( 0, 0, aWidth, aHeight ); + aFrameBuffer.bind(); + + // draw scene + aViewPort->getGLWidget()->updateGL(); + + 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; + } - GLViewer_Widget* aWidget = ((GLViewer_ViewPort2d*)myVP)->getGLWidget(); + QImage anImage; + GLViewer_Widget* aWidget = aViewPort->getGLWidget(); if ( aWidget ) - img = aWidget->grabFrameBuffer(); + anImage = aWidget->grabFrameBuffer(); - return img; + return anImage; } /*! diff --git a/src/GLViewer/Makefile.am b/src/GLViewer/Makefile.am index 003d71047..317185948 100644 --- a/src/GLViewer/Makefile.am +++ b/src/GLViewer/Makefile.am @@ -51,7 +51,8 @@ salomeinclude_HEADERS = \ GLViewer_ViewPort2d.h \ GLViewer_Viewer.h \ GLViewer_Viewer2d.h \ - GLViewer_Widget.h + GLViewer_Widget.h \ + GLViewer_FrameBuffer.h dist_libGLViewer_la_SOURCES = \ GLViewer_AspectLine.cxx \ @@ -77,7 +78,8 @@ dist_libGLViewer_la_SOURCES = \ GLViewer_ViewPort2d.cxx \ GLViewer_Viewer.cxx \ GLViewer_Viewer2d.cxx \ - GLViewer_Widget.cxx + GLViewer_Widget.cxx \ + GLViewer_FrameBuffer.cxx MOC_FILES = \ GLViewer_Selector_moc.cxx \ @@ -89,7 +91,8 @@ MOC_FILES = \ GLViewer_ViewPort2d_moc.cxx \ GLViewer_Viewer_moc.cxx \ GLViewer_Viewer2d_moc.cxx \ - GLViewer_Widget_moc.cxx + GLViewer_Widget_moc.cxx \ + GLViewer_FrameBuffer_moc.cxx nodist_libGLViewer_la_SOURCES = $(MOC_FILES) dist_salomeres_DATA = \ -- 2.39.2