From a7807c4ee16f0d1f30c2cd22acbc32561af3db8f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 9 Jul 2014 11:22:42 +0200 Subject: [PATCH] Rework to support multiple views with OpenGL GAL canvas. --- common/gal/opengl/opengl_compositor.cpp | 67 ++++++++++++------------- common/gal/opengl/opengl_gal.cpp | 29 +++++------ common/gal/opengl/vertex_container.cpp | 7 ++- common/view/view.cpp | 2 +- include/gal/opengl/opengl_compositor.h | 15 +++--- include/gal/opengl/opengl_gal.h | 14 +----- include/gal/opengl/vertex_container.h | 2 +- 7 files changed, 62 insertions(+), 74 deletions(-) diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp index 3a6721e5c9..2843204d78 100644 --- a/common/gal/opengl/opengl_compositor.cpp +++ b/common/gal/opengl/opengl_compositor.cpp @@ -35,7 +35,7 @@ using namespace KIGFX; OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() : - m_initialized( false ), m_current( 0 ) + m_initialized( false ), m_current( 0 ), m_currentFbo( DIRECT_RENDERING ) { } @@ -52,9 +52,6 @@ void OPENGL_COMPOSITOR::Initialize() if( m_initialized ) return; - // Get the maximum number of buffers - glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &m_maxBuffers ); - // We need framebuffer objects for drawing the screen contents // Generate framebuffer and a depth buffer glGenFramebuffersEXT( 1, &m_framebuffer ); @@ -68,15 +65,13 @@ void OPENGL_COMPOSITOR::Initialize() // Use here a size of 24 bits for the depth buffer, 8 bits for the stencil buffer // this is required later for anti-aliasing - glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL, m_width, m_height ); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height ); glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER_EXT, m_depthBuffer ); - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER_EXT, m_depthBuffer ); + GL_RENDERBUFFER_EXT, m_depthBuffer ); // Unbind the framebuffer, so by default all the rendering goes directly to the display glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING ); - m_currentFbo = 0; + m_currentFbo = DIRECT_RENDERING; m_initialized = true; } @@ -96,9 +91,14 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() { wxASSERT( m_initialized ); - if( usedBuffers() >= m_maxBuffers ) + unsigned int maxBuffers; + + // Get the maximum number of buffers + glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers ); + + if( usedBuffers() >= maxBuffers ) { - DisplayError( NULL, wxT( "Cannot create more framebuffers. OpenGL rendering " + DisplayError( NULL, _( "Cannot create more framebuffers. OpenGL rendering " "backend requires at least 3 framebuffers. You may try to update/change " "your graphic drivers." ) ); return 0; // Unfortunately we have no more free buffers left @@ -114,7 +114,7 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() // Set texture parameters glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); @@ -122,7 +122,8 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() // Bind the texture to the specific attachment point, clear and rebind the screen glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_framebuffer ); m_currentFbo = m_framebuffer; - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 ); + glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, + GL_TEXTURE_2D, textureTarget, 0 ); // Check the status, exit if the framebuffer can't be created GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); @@ -132,38 +133,38 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() switch( status ) { case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - DisplayError( NULL, wxT( "Cannot create the framebuffer." ) ); + DisplayError( NULL, _( "Cannot create the framebuffer." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - DisplayError( NULL, wxT( "The framebuffer attachment points are incomplete." ) ); + DisplayError( NULL, _( "The framebuffer attachment points are incomplete." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - DisplayError( NULL, wxT( "The framebuffer does not have at least " - "one image attached to it." ) ); + DisplayError( NULL, _( "The framebuffer does not have at least " + "one image attached to it." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - DisplayError( NULL, wxT( "The framebuffer read buffer is incomplete." ) ); + DisplayError( NULL, _( "The framebuffer read buffer is incomplete." ) ); break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - DisplayError( NULL, wxT( "The combination of internal formats of the attached images " - "violates an implementation-dependent set of restrictions." ) ); + DisplayError( NULL, _( "The combination of internal formats of the attached images " + "violates an implementation-dependent set of restrictions." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: - DisplayError( NULL, wxT( "GL_RENDERBUFFER_SAMPLES is not the same " - "for all attached renderbuffers" ) ); + DisplayError( NULL, _( "GL_RENDERBUFFER_SAMPLES is not the same " + "for all attached renderbuffers" ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT: - DisplayError( NULL, wxT( "Framebuffer incomplete layer targets errors." ) ); + DisplayError( NULL, _( "Framebuffer incomplete layer targets errors." ) ); break; default: - DisplayError( NULL, wxT( "Cannot create the framebuffer." ) ); + DisplayError( NULL, _( "Cannot create the framebuffer." ) ); break; } @@ -192,7 +193,6 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) // Change the rendering destination to the selected attachment point if( aBufferHandle == DIRECT_RENDERING ) { - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING ); m_currentFbo = DIRECT_RENDERING; } else if( m_currentFbo != m_framebuffer ) @@ -221,12 +221,7 @@ void OPENGL_COMPOSITOR::ClearBuffer() void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) { wxASSERT( m_initialized ); - - if( aBufferHandle == 0 || aBufferHandle > usedBuffers() ) - { - DisplayError( NULL, wxT( "Wrong framebuffer handle" ) ); - return; - } + wxASSERT( aBufferHandle != 0 && aBufferHandle <= usedBuffers() ); // Switch to the main framebuffer and blit the scene glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING ); @@ -274,8 +269,8 @@ void OPENGL_COMPOSITOR::clean() { wxASSERT( m_initialized ); - glDeleteFramebuffersEXT( 1, &m_framebuffer ); - glDeleteRenderbuffersEXT( 1, &m_depthBuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING ); + m_currentFbo = DIRECT_RENDERING; OPENGL_BUFFERS::const_iterator it; @@ -286,8 +281,8 @@ void OPENGL_COMPOSITOR::clean() m_buffers.clear(); + glDeleteFramebuffersEXT( 1, &m_framebuffer ); + glDeleteRenderbuffersEXT( 1, &m_depthBuffer ); + m_initialized = false; } - - -GLuint OPENGL_COMPOSITOR::m_currentFbo = DIRECT_RENDERING; diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 568772f96a..f7b7842a04 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -45,6 +45,8 @@ void InitTesselatorCallbacks( GLUtesselator* aTesselator ); const int glAttributes[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 }; +wxGLContext* OPENGL_GAL::glContext = NULL; + OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener, const wxString& aName ) : wxGLCanvas( aParent, wxID_ANY, (int*) glAttributes, wxDefaultPosition, wxDefaultSize, @@ -54,7 +56,9 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, overlayManager( false ) { // Create the OpenGL-Context - glContext = new wxGLContext( this ); + if( glContext == NULL ) + glContext = new wxGLContext( this ); + parentWindow = aParent; mouseListener = aMouseListener; paintListener = aPaintListener; @@ -113,8 +117,6 @@ OPENGL_GAL::~OPENGL_GAL() gluDeleteTess( tesselator ); ClearCache(); - - delete glContext; } @@ -122,23 +124,22 @@ void OPENGL_GAL::BeginDrawing() { SetCurrent( *glContext ); - clientDC = new wxClientDC( this ); + clientDC = new wxPaintDC( this ); // Initialize GLEW, FBOs & VBOs if( !isGlewInitialized ) initGlew(); + // Set up the view port + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); + + // Create the screen transformation + glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); + if( !isFramebufferInitialized ) { - // Set up the view port - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); - - // Create the screen transformation - glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, - -depthRange.x, -depthRange.y ); - // Prepare rendering target buffers compositor.Initialize(); mainBuffer = compositor.CreateBuffer(); @@ -967,7 +968,7 @@ void OPENGL_GAL::initGlew() exit( 1 ); } - // Vertex buffer have to be supported + // Vertex buffer has to be supported if( !GLEW_ARB_vertex_buffer_object ) { DisplayError( parentWindow, wxT( "Vertex buffer objects are not supported!" ) ); diff --git a/common/gal/opengl/vertex_container.cpp b/common/gal/opengl/vertex_container.cpp index 82658e11ae..fa41ecb808 100644 --- a/common/gal/opengl/vertex_container.cpp +++ b/common/gal/opengl/vertex_container.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include using namespace KIGFX; @@ -45,9 +46,11 @@ VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached ) VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) : - m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_failed( false ) + m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), + m_failed( false ), m_dirty( true ) { m_vertices = static_cast( malloc( aSize * sizeof( VERTEX ) ) ); + memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) ); } diff --git a/common/view/view.cpp b/common/view/view.cpp index 44d808e4ed..d4b20e9b42 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -1027,7 +1027,7 @@ struct VIEW::extentsVisitor { bool operator()( VIEW_ITEM* aItem ) { - if(first) + if( first ) extents = aItem->ViewBBox(); else extents.Merge ( aItem->ViewBBox() ); diff --git a/include/gal/opengl/opengl_compositor.h b/include/gal/opengl/opengl_compositor.h index 642a7f7bbc..c06add7d2e 100644 --- a/include/gal/opengl/opengl_compositor.h +++ b/include/gal/opengl/opengl_compositor.h @@ -80,18 +80,17 @@ protected: GLuint attachmentPoint; ///< Point to which an image from texture is attached } OPENGL_BUFFER; - bool m_initialized; ///< Initialization status flag - unsigned int m_current; ///< Currently used buffer handle - GLuint m_framebuffer; ///< Main FBO handle - GLuint m_depthBuffer; ///< Depth buffer handle - unsigned int m_maxBuffers; ///< Maximal amount of buffers + bool m_initialized; ///< Initialization status flag + unsigned int m_current; ///< Currently used buffer handle + GLuint m_framebuffer; ///< Main FBO handle + GLuint m_depthBuffer; ///< Depth buffer handle typedef std::deque OPENGL_BUFFERS; /// Stores information about initialized buffers - OPENGL_BUFFERS m_buffers; + OPENGL_BUFFERS m_buffers; /// Store the currently used FBO name in case there was more than one compositor used - static GLuint m_currentFbo; + GLuint m_currentFbo; /** * Function clean() @@ -100,7 +99,7 @@ protected: void clean(); /// Returns number of used buffers - unsigned int usedBuffers() + inline unsigned int usedBuffers() { return m_buffers.size(); } diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index 10c4fea54d..417cdd389e 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -37,22 +37,12 @@ #include #include -#include #include -#include -#include -#include -#include -#include #include #include #include -#include -#include -#include - #ifndef CALLBACK #define CALLBACK #endif @@ -262,8 +252,8 @@ private: static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation static const int CURVE_POINTS = 32; ///< The number of points for curve approximation - wxClientDC* clientDC; ///< Drawing context - wxGLContext* glContext; ///< OpenGL context of wxWidgets + wxPaintDC* clientDC; ///< Drawing context + static wxGLContext* glContext; ///< OpenGL context of wxWidgets wxWindow* parentWindow; ///< Parent window wxEvtHandler* mouseListener; wxEvtHandler* paintListener; diff --git a/include/gal/opengl/vertex_container.h b/include/gal/opengl/vertex_container.h index 50c8d7fec1..807731bb37 100644 --- a/include/gal/opengl/vertex_container.h +++ b/include/gal/opengl/vertex_container.h @@ -163,7 +163,7 @@ protected: * returns size of the reserved memory space. * @return Size of the reserved memory space (expressed as a number of vertices). */ - unsigned int reservedSpace() + inline unsigned int reservedSpace() { return m_currentSize - m_freeSpace; }