Loading common/gal/opengl/opengl_gal.cpp +113 −59 Original line number Diff line number Diff line Loading @@ -36,46 +36,29 @@ #endif /* __WXDEBUG__ */ #include <limits> #include <boost/bind.hpp> using namespace KIGFX; // Prototypes void InitTesselatorCallbacks( GLUtesselator* aTesselator ); static 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, wxEXPAND, aName ), parentWindow( aParent ), mouseListener( aMouseListener ), paintListener( aPaintListener ), cachedManager( true ), nonCachedManager( false ), overlayManager( false ) { // Create the OpenGL-Context if( glContext == NULL ) glContext = new wxGLContext( this ); aParent->Show(); // wxWidgets require the window to be visible to set its GL context // Initialize GLEW, FBOs & VBOs SetCurrent( *glContext ); initGlew(); // Prepare shaders if( !shader.LoadBuiltinShader( 0, SHADER_TYPE_VERTEX ) ) throw std::runtime_error( "Cannot compile vertex shader!" ); if( !shader.LoadBuiltinShader( 1, SHADER_TYPE_FRAGMENT ) ) throw std::runtime_error( "Cannot compile fragment shader!" ); if( !shader.Link() ) throw std::runtime_error( "Cannot link the shaders!" ); // Check if OpenGL requirements are met runTest(); // Make VBOs use shaders cachedManager.SetShader( shader ); Loading Loading @@ -145,7 +128,8 @@ void OPENGL_GAL::BeginDrawing() 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 ); glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); if( !isFramebufferInitialized ) { Loading Loading @@ -914,37 +898,6 @@ void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent ) } void OPENGL_GAL::initGlew() { // Initialize GLEW library GLenum err = glewInit(); if( GLEW_OK != err ) { throw std::runtime_error( (const char*) glewGetErrorString( err ) ); } else { wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) + FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) ); } // Check the OpenGL version (minimum 2.1 is required) if( GLEW_VERSION_2_1 ) wxLogInfo( wxT( "OpenGL 2.1 supported." ) ); else throw std::runtime_error( "OpenGL 2.1 or higher is required!" ); // Framebuffers have to be supported if( !GLEW_EXT_framebuffer_object ) throw std::runtime_error( "Framebuffer objects are not supported!" ); // Vertex buffer has to be supported if( !GLEW_ARB_vertex_buffer_object ) throw std::runtime_error( "Vertex buffer objects are not supported!" ); } void OPENGL_GAL::blitCursor() { if( !isCursorEnabled ) Loading Loading @@ -984,11 +937,112 @@ unsigned int OPENGL_GAL::getNewGroupNumber() } // ------------------------------------- // Callback functions for the tesselator // ------------------------------------- bool OPENGL_GAL::runTest() { wxDialog* dialog = new wxDialog( GetParent(), -1, wxT( "opengl test" ), wxPoint( 50, 50 ), wxSize( 50, 50 ) ); OPENGL_TEST* test = new OPENGL_TEST( dialog, this ); dialog->ShowModal(); bool result = test->IsOk(); if( !result ) throw std::runtime_error( test->GetError() ); return result; } OPENGL_GAL::OPENGL_TEST::OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal ) : wxGLCanvas( aParent, wxID_ANY, glAttributes, wxDefaultPosition, wxDefaultSize, 0, wxT( "GLCanvas" ) ), m_parent( aParent ), m_gal( aGal ), m_tested( false ), m_result( false ) { Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::OPENGL_TEST::Render ) ); } void OPENGL_GAL::OPENGL_TEST::Render( wxPaintEvent& WXUNUSED( aEvent ) ) { if( !m_tested ) { m_result = true; // Assume everything is fine, until proven otherwise // One test is enough - close the testing dialog when the test is finished Disconnect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::OPENGL_TEST::Render ) ); CallAfter( boost::bind( &wxDialog::EndModal, m_parent, wxID_NONE ) ); SetCurrent( *OPENGL_GAL::glContext ); GLenum err = glewInit(); if( GLEW_OK != err ) { error( (const char*) glewGetErrorString( err ) ); return; } else { wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) + FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) ); } // Check the OpenGL version (minimum 2.1 is required) if( GLEW_VERSION_2_1 ) { wxLogInfo( wxT( "OpenGL 2.1 supported." ) ); } else { error( "OpenGL 2.1 or higher is required!" ); return; } // Framebuffers have to be supported if( !GLEW_EXT_framebuffer_object ) { error( "Framebuffer objects are not supported!" ); return; } // Vertex buffer has to be supported if( !GLEW_ARB_vertex_buffer_object ) { error( "Vertex buffer objects are not supported!" ); return; } // Prepare shaders if( !m_gal->shader.LoadBuiltinShader( 0, SHADER_TYPE_VERTEX ) ) { error( "Cannot compile vertex shader!" ); return; } if( !m_gal->shader.LoadBuiltinShader( 1, SHADER_TYPE_FRAGMENT ) ) { error( "Cannot compile fragment shader!" ); return; } if( !m_gal->shader.Link() ) { error( "Cannot link the shaders!" ); return; } m_tested = true; } } void OPENGL_GAL::OPENGL_TEST::error(const std::string& aError ) { m_result = false; m_tested = true; m_error = aError; } // Compare Redbook Chapter 11 // ------------------------------------- // Callback functions for the tesselator // ------------------------------------- // Compare Redbook Chapter 11 void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData ) { GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr ); Loading Loading @@ -1029,7 +1083,7 @@ void CALLBACK ErrorCallback( GLenum aErrorCode ) } void InitTesselatorCallbacks( GLUtesselator* aTesselator ) static void InitTesselatorCallbacks( GLUtesselator* aTesselator ) { gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback ); gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback ); Loading include/gal/opengl/opengl_gal.h +30 −6 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN * @author Maciej Suminski <maciej.suminski@cern.ch> * * Graphics Abstraction Layer (GAL) for OpenGL Loading Loading @@ -55,7 +55,7 @@ class SHADER; * @brief Class OpenGL_GAL is the OpenGL implementation of the Graphics Abstraction Layer. * * This is a direct OpenGL-implementation and uses low-level graphics primitives like triangles * and quads. The purpuse is to provide a fast graphics interface, that takes advantage of modern * and quads. The purpose is to provide a fast graphics interface, that takes advantage of modern * graphics card GPUs. All methods here benefit thus from the hardware acceleration. */ class OPENGL_GAL : public GAL, public wxGLCanvas Loading Loading @@ -254,7 +254,6 @@ private: wxClientDC* clientDC; ///< Drawing context static wxGLContext* glContext; ///< OpenGL context of wxWidgets wxWindow* parentWindow; ///< Parent window wxEvtHandler* mouseListener; wxEvtHandler* paintListener; Loading Loading @@ -340,9 +339,6 @@ private: */ void skipMouseEvent( wxMouseEvent& aEvent ); /// Initialize GLEW void initGlew(); /** * @brief Blits cursor into the current screen. */ Loading @@ -354,6 +350,34 @@ private: * @return An unique group number that is not used by any other group. */ unsigned int getNewGroupNumber(); /** * @brief Checks if the required OpenGL version and extensions are supported. * @return true in case of success. */ bool runTest(); // Helper class to determine OpenGL capabilities class OPENGL_TEST: public wxGLCanvas { public: OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal ); void Render( wxPaintEvent& aEvent ); inline bool IsTested() const { return m_tested; } inline bool IsOk() const { return m_result && m_tested; } inline std::string GetError() const { return m_error; } private: void error( const std::string& aError ); wxDialog* m_parent; OPENGL_GAL* m_gal; bool m_tested; bool m_result; std::string m_error; }; friend class OPENGL_TEST; }; } // namespace KIGFX Loading Loading
common/gal/opengl/opengl_gal.cpp +113 −59 Original line number Diff line number Diff line Loading @@ -36,46 +36,29 @@ #endif /* __WXDEBUG__ */ #include <limits> #include <boost/bind.hpp> using namespace KIGFX; // Prototypes void InitTesselatorCallbacks( GLUtesselator* aTesselator ); static 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, wxEXPAND, aName ), parentWindow( aParent ), mouseListener( aMouseListener ), paintListener( aPaintListener ), cachedManager( true ), nonCachedManager( false ), overlayManager( false ) { // Create the OpenGL-Context if( glContext == NULL ) glContext = new wxGLContext( this ); aParent->Show(); // wxWidgets require the window to be visible to set its GL context // Initialize GLEW, FBOs & VBOs SetCurrent( *glContext ); initGlew(); // Prepare shaders if( !shader.LoadBuiltinShader( 0, SHADER_TYPE_VERTEX ) ) throw std::runtime_error( "Cannot compile vertex shader!" ); if( !shader.LoadBuiltinShader( 1, SHADER_TYPE_FRAGMENT ) ) throw std::runtime_error( "Cannot compile fragment shader!" ); if( !shader.Link() ) throw std::runtime_error( "Cannot link the shaders!" ); // Check if OpenGL requirements are met runTest(); // Make VBOs use shaders cachedManager.SetShader( shader ); Loading Loading @@ -145,7 +128,8 @@ void OPENGL_GAL::BeginDrawing() 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 ); glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); if( !isFramebufferInitialized ) { Loading Loading @@ -914,37 +898,6 @@ void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent ) } void OPENGL_GAL::initGlew() { // Initialize GLEW library GLenum err = glewInit(); if( GLEW_OK != err ) { throw std::runtime_error( (const char*) glewGetErrorString( err ) ); } else { wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) + FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) ); } // Check the OpenGL version (minimum 2.1 is required) if( GLEW_VERSION_2_1 ) wxLogInfo( wxT( "OpenGL 2.1 supported." ) ); else throw std::runtime_error( "OpenGL 2.1 or higher is required!" ); // Framebuffers have to be supported if( !GLEW_EXT_framebuffer_object ) throw std::runtime_error( "Framebuffer objects are not supported!" ); // Vertex buffer has to be supported if( !GLEW_ARB_vertex_buffer_object ) throw std::runtime_error( "Vertex buffer objects are not supported!" ); } void OPENGL_GAL::blitCursor() { if( !isCursorEnabled ) Loading Loading @@ -984,11 +937,112 @@ unsigned int OPENGL_GAL::getNewGroupNumber() } // ------------------------------------- // Callback functions for the tesselator // ------------------------------------- bool OPENGL_GAL::runTest() { wxDialog* dialog = new wxDialog( GetParent(), -1, wxT( "opengl test" ), wxPoint( 50, 50 ), wxSize( 50, 50 ) ); OPENGL_TEST* test = new OPENGL_TEST( dialog, this ); dialog->ShowModal(); bool result = test->IsOk(); if( !result ) throw std::runtime_error( test->GetError() ); return result; } OPENGL_GAL::OPENGL_TEST::OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal ) : wxGLCanvas( aParent, wxID_ANY, glAttributes, wxDefaultPosition, wxDefaultSize, 0, wxT( "GLCanvas" ) ), m_parent( aParent ), m_gal( aGal ), m_tested( false ), m_result( false ) { Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::OPENGL_TEST::Render ) ); } void OPENGL_GAL::OPENGL_TEST::Render( wxPaintEvent& WXUNUSED( aEvent ) ) { if( !m_tested ) { m_result = true; // Assume everything is fine, until proven otherwise // One test is enough - close the testing dialog when the test is finished Disconnect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::OPENGL_TEST::Render ) ); CallAfter( boost::bind( &wxDialog::EndModal, m_parent, wxID_NONE ) ); SetCurrent( *OPENGL_GAL::glContext ); GLenum err = glewInit(); if( GLEW_OK != err ) { error( (const char*) glewGetErrorString( err ) ); return; } else { wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) + FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) ); } // Check the OpenGL version (minimum 2.1 is required) if( GLEW_VERSION_2_1 ) { wxLogInfo( wxT( "OpenGL 2.1 supported." ) ); } else { error( "OpenGL 2.1 or higher is required!" ); return; } // Framebuffers have to be supported if( !GLEW_EXT_framebuffer_object ) { error( "Framebuffer objects are not supported!" ); return; } // Vertex buffer has to be supported if( !GLEW_ARB_vertex_buffer_object ) { error( "Vertex buffer objects are not supported!" ); return; } // Prepare shaders if( !m_gal->shader.LoadBuiltinShader( 0, SHADER_TYPE_VERTEX ) ) { error( "Cannot compile vertex shader!" ); return; } if( !m_gal->shader.LoadBuiltinShader( 1, SHADER_TYPE_FRAGMENT ) ) { error( "Cannot compile fragment shader!" ); return; } if( !m_gal->shader.Link() ) { error( "Cannot link the shaders!" ); return; } m_tested = true; } } void OPENGL_GAL::OPENGL_TEST::error(const std::string& aError ) { m_result = false; m_tested = true; m_error = aError; } // Compare Redbook Chapter 11 // ------------------------------------- // Callback functions for the tesselator // ------------------------------------- // Compare Redbook Chapter 11 void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData ) { GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr ); Loading Loading @@ -1029,7 +1083,7 @@ void CALLBACK ErrorCallback( GLenum aErrorCode ) } void InitTesselatorCallbacks( GLUtesselator* aTesselator ) static void InitTesselatorCallbacks( GLUtesselator* aTesselator ) { gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback ); gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback ); Loading
include/gal/opengl/opengl_gal.h +30 −6 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2013 CERN * Copyright (C) 2013-2015 CERN * @author Maciej Suminski <maciej.suminski@cern.ch> * * Graphics Abstraction Layer (GAL) for OpenGL Loading Loading @@ -55,7 +55,7 @@ class SHADER; * @brief Class OpenGL_GAL is the OpenGL implementation of the Graphics Abstraction Layer. * * This is a direct OpenGL-implementation and uses low-level graphics primitives like triangles * and quads. The purpuse is to provide a fast graphics interface, that takes advantage of modern * and quads. The purpose is to provide a fast graphics interface, that takes advantage of modern * graphics card GPUs. All methods here benefit thus from the hardware acceleration. */ class OPENGL_GAL : public GAL, public wxGLCanvas Loading Loading @@ -254,7 +254,6 @@ private: wxClientDC* clientDC; ///< Drawing context static wxGLContext* glContext; ///< OpenGL context of wxWidgets wxWindow* parentWindow; ///< Parent window wxEvtHandler* mouseListener; wxEvtHandler* paintListener; Loading Loading @@ -340,9 +339,6 @@ private: */ void skipMouseEvent( wxMouseEvent& aEvent ); /// Initialize GLEW void initGlew(); /** * @brief Blits cursor into the current screen. */ Loading @@ -354,6 +350,34 @@ private: * @return An unique group number that is not used by any other group. */ unsigned int getNewGroupNumber(); /** * @brief Checks if the required OpenGL version and extensions are supported. * @return true in case of success. */ bool runTest(); // Helper class to determine OpenGL capabilities class OPENGL_TEST: public wxGLCanvas { public: OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal ); void Render( wxPaintEvent& aEvent ); inline bool IsTested() const { return m_tested; } inline bool IsOk() const { return m_result && m_tested; } inline std::string GetError() const { return m_error; } private: void error( const std::string& aError ); wxDialog* m_parent; OPENGL_GAL* m_gal; bool m_tested; bool m_result; std::string m_error; }; friend class OPENGL_TEST; }; } // namespace KIGFX Loading