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 @@
#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 );
......@@ -88,7 +71,7 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
groupCounter = 0;
// 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
Connect( wxEVT_MOTION, wxMouseEventHandler( OPENGL_GAL::skipMouseEvent ) );
......@@ -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 )
{
......@@ -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 )
......@@ -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 );
......@@ -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 );
......
......@@ -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
......@@ -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
......@@ -254,7 +254,6 @@ private:
wxClientDC* clientDC; ///< Drawing context
static wxGLContext* glContext; ///< OpenGL context of wxWidgets
wxWindow* parentWindow; ///< Parent window
wxEvtHandler* mouseListener;
wxEvtHandler* paintListener;
......@@ -340,9 +339,6 @@ private:
*/
void skipMouseEvent( wxMouseEvent& aEvent );
/// Initialize GLEW
void initGlew();
/**
* @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.
*/
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
......
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