Better way to determine supported OpenGL version and extensions.
This commit is contained in:
parent
9a6a3c8b58
commit
709697ea40
|
@ -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,
|
||||||
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()
|
||||||
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 )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------
|
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 );
|
||||||
|
|
||||||
// Compare Redbook Chapter 11
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------- // 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 )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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 @@
|
||||||
*
|
*
|
||||||
* 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;
|
||||||
* @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:
|
||||||
|
|
||||||
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:
|
||||||
*/
|
*/
|
||||||
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:
|
||||||
* @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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue