Commit 709697ea authored by Maciej Suminski's avatar Maciej Suminski

Better way to determine supported OpenGL version and extensions.

parent 9a6a3c8b
...@@ -36,46 +36,29 @@ ...@@ -36,46 +36,29 @@
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
#include <limits> #include <limits>
#include <boost/bind.hpp>
using namespace KIGFX; using namespace KIGFX;
// Prototypes static void InitTesselatorCallbacks( GLUtesselator* aTesselator );
void InitTesselatorCallbacks( GLUtesselator* aTesselator );
const int glAttributes[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 }; const int glAttributes[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 };
wxGLContext* OPENGL_GAL::glContext = NULL; wxGLContext* OPENGL_GAL::glContext = NULL;
OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
wxEvtHandler* aPaintListener, const wxString& aName ) : wxEvtHandler* aPaintListener, const wxString& aName ) :
wxGLCanvas( aParent, wxID_ANY, (int*) glAttributes, wxDefaultPosition, wxDefaultSize, wxGLCanvas( aParent, wxID_ANY, (int*) glAttributes, wxDefaultPosition, wxDefaultSize,
wxEXPAND, aName ), wxEXPAND, aName ),
parentWindow( aParent ),
mouseListener( aMouseListener ), mouseListener( aMouseListener ),
paintListener( aPaintListener ), paintListener( aPaintListener ),
cachedManager( true ), cachedManager( true ),
nonCachedManager( false ), nonCachedManager( false ),
overlayManager( false ) overlayManager( false )
{ {
// Create the OpenGL-Context
if( glContext == NULL ) if( glContext == NULL )
glContext = new wxGLContext( this ); glContext = new wxGLContext( this );
aParent->Show(); // wxWidgets require the window to be visible to set its GL context // Check if OpenGL requirements are met
runTest();
// 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!" );
// Make VBOs use shaders // Make VBOs use shaders
cachedManager.SetShader( shader ); cachedManager.SetShader( shader );
...@@ -88,7 +71,7 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, ...@@ -88,7 +71,7 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
groupCounter = 0; groupCounter = 0;
// Connecting the event handlers // Connecting the event handlers
Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::onPaint ) ); Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::onPaint ) );
// Mouse events are skipped to the parent // Mouse events are skipped to the parent
Connect( wxEVT_MOTION, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) ); Connect( wxEVT_MOTION, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) );
...@@ -145,7 +128,8 @@ void OPENGL_GAL::BeginDrawing() ...@@ -145,7 +128,8 @@ void OPENGL_GAL::BeginDrawing()
glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y );
// Create the screen transformation // 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 ) if( !isFramebufferInitialized )
{ {
...@@ -914,37 +898,6 @@ void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent ) ...@@ -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() void OPENGL_GAL::blitCursor()
{ {
if( !isCursorEnabled ) if( !isCursorEnabled )
...@@ -984,11 +937,112 @@ unsigned int OPENGL_GAL::getNewGroupNumber() ...@@ -984,11 +937,112 @@ unsigned int OPENGL_GAL::getNewGroupNumber()
} }
// ------------------------------------- bool OPENGL_GAL::runTest()
// Callback functions for the tesselator {
// ------------------------------------- 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 ) void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
{ {
GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr ); GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr );
...@@ -1029,7 +1083,7 @@ void CALLBACK ErrorCallback( GLenum aErrorCode ) ...@@ -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_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback );
gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback ); gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback );
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. * 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> * @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* Graphics Abstraction Layer (GAL) for OpenGL * Graphics Abstraction Layer (GAL) for OpenGL
...@@ -55,7 +55,7 @@ class SHADER; ...@@ -55,7 +55,7 @@ class SHADER;
* @brief Class OpenGL_GAL is the OpenGL implementation of the Graphics Abstraction Layer. * @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 * 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. * graphics card GPUs. All methods here benefit thus from the hardware acceleration.
*/ */
class OPENGL_GAL : public GAL, public wxGLCanvas class OPENGL_GAL : public GAL, public wxGLCanvas
...@@ -254,7 +254,6 @@ private: ...@@ -254,7 +254,6 @@ private:
wxClientDC* clientDC; ///< Drawing context wxClientDC* clientDC; ///< Drawing context
static wxGLContext* glContext; ///< OpenGL context of wxWidgets static wxGLContext* glContext; ///< OpenGL context of wxWidgets
wxWindow* parentWindow; ///< Parent window
wxEvtHandler* mouseListener; wxEvtHandler* mouseListener;
wxEvtHandler* paintListener; wxEvtHandler* paintListener;
...@@ -340,9 +339,6 @@ private: ...@@ -340,9 +339,6 @@ private:
*/ */
void skipMouseEvent( wxMouseEvent& aEvent ); void skipMouseEvent( wxMouseEvent& aEvent );
/// Initialize GLEW
void initGlew();
/** /**
* @brief Blits cursor into the current screen. * @brief Blits cursor into the current screen.
*/ */
...@@ -354,6 +350,34 @@ private: ...@@ -354,6 +350,34 @@ private:
* @return An unique group number that is not used by any other group. * @return An unique group number that is not used by any other group.
*/ */
unsigned int getNewGroupNumber(); 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 } // namespace KIGFX
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment