Add code showing stereo support to the OpenGL cube sample.
Show how WX_GL_STEREO attribute can be used, if available. See #15434. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74819 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -268,22 +268,38 @@ bool MyApp::OnInit()
 | 
				
			|||||||
int MyApp::OnExit()
 | 
					int MyApp::OnExit()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    delete m_glContext;
 | 
					    delete m_glContext;
 | 
				
			||||||
 | 
					    delete m_glStereoContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return wxApp::OnExit();
 | 
					    return wxApp::OnExit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TestGLContext& MyApp::GetContext(wxGLCanvas *canvas)
 | 
					TestGLContext& MyApp::GetContext(wxGLCanvas *canvas, bool useStereo)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TestGLContext *glContext;
 | 
				
			||||||
 | 
					    if ( useStereo )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ( !m_glStereoContext )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Create the OpenGL context for the first stereo window which needs it:
 | 
				
			||||||
 | 
					            // subsequently created windows will all share the same context.
 | 
				
			||||||
 | 
					            m_glStereoContext = new TestGLContext(canvas);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        glContext = m_glStereoContext;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if ( !m_glContext )
 | 
					        if ( !m_glContext )
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
        // Create the OpenGL context for the first window which needs it:
 | 
					            // Create the OpenGL context for the first mono window which needs it:
 | 
				
			||||||
            // subsequently created windows will all share the same context.
 | 
					            // subsequently created windows will all share the same context.
 | 
				
			||||||
            m_glContext = new TestGLContext(canvas);
 | 
					            m_glContext = new TestGLContext(canvas);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        glContext = m_glContext;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m_glContext->SetCurrent(*canvas);
 | 
					    glContext->SetCurrent(*canvas);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return *m_glContext;
 | 
					    return *glContext;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
@@ -296,18 +312,30 @@ BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
 | 
				
			|||||||
    EVT_TIMER(SpinTimer, TestGLCanvas::OnSpinTimer)
 | 
					    EVT_TIMER(SpinTimer, TestGLCanvas::OnSpinTimer)
 | 
				
			||||||
END_EVENT_TABLE()
 | 
					END_EVENT_TABLE()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TestGLCanvas::TestGLCanvas(wxWindow *parent)
 | 
					TestGLCanvas::TestGLCanvas(wxWindow *parent, int *attribList)
 | 
				
			||||||
    // With perspective OpenGL graphics, the wxFULL_REPAINT_ON_RESIZE style
 | 
					    // With perspective OpenGL graphics, the wxFULL_REPAINT_ON_RESIZE style
 | 
				
			||||||
    // flag should always be set, because even making the canvas smaller should
 | 
					    // flag should always be set, because even making the canvas smaller should
 | 
				
			||||||
    // be followed by a paint event that updates the entire canvas with new
 | 
					    // be followed by a paint event that updates the entire canvas with new
 | 
				
			||||||
    // viewport settings.
 | 
					    // viewport settings.
 | 
				
			||||||
    : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */,
 | 
					    : wxGLCanvas(parent, wxID_ANY, attribList,
 | 
				
			||||||
                 wxDefaultPosition, wxDefaultSize,
 | 
					                 wxDefaultPosition, wxDefaultSize,
 | 
				
			||||||
                 wxFULL_REPAINT_ON_RESIZE),
 | 
					                 wxFULL_REPAINT_ON_RESIZE),
 | 
				
			||||||
      m_xangle(30.0),
 | 
					      m_xangle(30.0),
 | 
				
			||||||
      m_yangle(30.0),
 | 
					      m_yangle(30.0),
 | 
				
			||||||
      m_spinTimer(this,SpinTimer)
 | 
					      m_spinTimer(this,SpinTimer),
 | 
				
			||||||
 | 
					      m_useStereo(false),
 | 
				
			||||||
 | 
					      m_stereoWarningAlreadyDisplayed(false)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    if ( attribList )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int i = 0;
 | 
				
			||||||
 | 
					        while ( attribList[i] != 0 )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ( attribList[i] == WX_GL_STEREO )
 | 
				
			||||||
 | 
					                m_useStereo = true;
 | 
				
			||||||
 | 
					            ++i;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 | 
					void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 | 
				
			||||||
@@ -323,11 +351,36 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 | 
				
			|||||||
    // is wrong when next another canvas is repainted.
 | 
					    // is wrong when next another canvas is repainted.
 | 
				
			||||||
    const wxSize ClientSize = GetClientSize();
 | 
					    const wxSize ClientSize = GetClientSize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TestGLContext& canvas = wxGetApp().GetContext(this);
 | 
					    TestGLContext& canvas = wxGetApp().GetContext(this, m_useStereo);
 | 
				
			||||||
    glViewport(0, 0, ClientSize.x, ClientSize.y);
 | 
					    glViewport(0, 0, ClientSize.x, ClientSize.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Render the graphics and swap the buffers.
 | 
					    // Render the graphics and swap the buffers.
 | 
				
			||||||
 | 
					    GLboolean quadStereoSupported;
 | 
				
			||||||
 | 
					    glGetBooleanv( GL_STEREO, &quadStereoSupported);
 | 
				
			||||||
 | 
					    if ( quadStereoSupported )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        glDrawBuffer( GL_BACK_LEFT );
 | 
				
			||||||
 | 
					        glMatrixMode(GL_PROJECTION);
 | 
				
			||||||
 | 
					        glLoadIdentity();
 | 
				
			||||||
 | 
					        glFrustum(-0.47f, 0.53f, -0.5f, 0.5f, 1.0f, 3.0f);
 | 
				
			||||||
        canvas.DrawRotatedCube(m_xangle, m_yangle);
 | 
					        canvas.DrawRotatedCube(m_xangle, m_yangle);
 | 
				
			||||||
 | 
					        CheckGLError();
 | 
				
			||||||
 | 
					        glDrawBuffer( GL_BACK_RIGHT );
 | 
				
			||||||
 | 
					        glMatrixMode(GL_PROJECTION);
 | 
				
			||||||
 | 
					        glLoadIdentity();
 | 
				
			||||||
 | 
					        glFrustum(-0.53f, 0.47f, -0.5f, 0.5f, 1.0f, 3.0f);
 | 
				
			||||||
 | 
					        canvas.DrawRotatedCube(m_xangle, m_yangle);
 | 
				
			||||||
 | 
					        CheckGLError();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        canvas.DrawRotatedCube(m_xangle, m_yangle);
 | 
				
			||||||
 | 
					        if ( m_useStereo && !m_stereoWarningAlreadyDisplayed )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            m_stereoWarningAlreadyDisplayed = true;
 | 
				
			||||||
 | 
					            wxLogError("Stereo not supported by the graphics card.");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    SwapBuffers();
 | 
					    SwapBuffers();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -379,6 +432,21 @@ void TestGLCanvas::OnSpinTimer(wxTimerEvent& WXUNUSED(event))
 | 
				
			|||||||
    Spin(0.0, 4.0);
 | 
					    Spin(0.0, 4.0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					wxString glGetwxString(GLenum name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const GLubyte *v = glGetString(name);
 | 
				
			||||||
 | 
					    if ( v == 0 )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // The error is not important. It is GL_INVALID_ENUM.
 | 
				
			||||||
 | 
					        // We just want to clear the error stack.
 | 
				
			||||||
 | 
					        glGetError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return wxString();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return wxString((const char*)v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------------------------------------------------------------------
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
// MyFrame: main application window
 | 
					// MyFrame: main application window
 | 
				
			||||||
@@ -386,19 +454,23 @@ void TestGLCanvas::OnSpinTimer(wxTimerEvent& WXUNUSED(event))
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 | 
					BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 | 
				
			||||||
    EVT_MENU(wxID_NEW, MyFrame::OnNewWindow)
 | 
					    EVT_MENU(wxID_NEW, MyFrame::OnNewWindow)
 | 
				
			||||||
 | 
					    EVT_MENU(NEW_STEREO_WINDOW, MyFrame::OnNewStereoWindow)
 | 
				
			||||||
    EVT_MENU(wxID_CLOSE, MyFrame::OnClose)
 | 
					    EVT_MENU(wxID_CLOSE, MyFrame::OnClose)
 | 
				
			||||||
END_EVENT_TABLE()
 | 
					END_EVENT_TABLE()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MyFrame::MyFrame()
 | 
					MyFrame::MyFrame( bool stereoWindow )
 | 
				
			||||||
       : wxFrame(NULL, wxID_ANY, wxT("wxWidgets OpenGL Cube Sample"))
 | 
					       : wxFrame(NULL, wxID_ANY, wxT("wxWidgets OpenGL Cube Sample"))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    new TestGLCanvas(this);
 | 
					    int stereoAttribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_STEREO, 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    new TestGLCanvas(this, stereoWindow ? stereoAttribList : NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SetIcon(wxICON(sample));
 | 
					    SetIcon(wxICON(sample));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Make a menubar
 | 
					    // Make a menubar
 | 
				
			||||||
    wxMenu *menu = new wxMenu;
 | 
					    wxMenu *menu = new wxMenu;
 | 
				
			||||||
    menu->Append(wxID_NEW);
 | 
					    menu->Append(wxID_NEW);
 | 
				
			||||||
 | 
					    menu->Append(NEW_STEREO_WINDOW, "New Stereo Window");
 | 
				
			||||||
    menu->AppendSeparator();
 | 
					    menu->AppendSeparator();
 | 
				
			||||||
    menu->Append(wxID_CLOSE);
 | 
					    menu->Append(wxID_CLOSE);
 | 
				
			||||||
    wxMenuBar *menuBar = new wxMenuBar;
 | 
					    wxMenuBar *menuBar = new wxMenuBar;
 | 
				
			||||||
@@ -415,6 +487,15 @@ MyFrame::MyFrame()
 | 
				
			|||||||
    static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
 | 
					    static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
 | 
				
			||||||
    wxLogStatus("Double-buffered display %s supported",
 | 
					    wxLogStatus("Double-buffered display %s supported",
 | 
				
			||||||
                wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
 | 
					                wxGLCanvas::IsDisplaySupported(attribs) ? "is" : "not");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ( stereoWindow )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const wxString vendor = glGetwxString(GL_VENDOR).Lower();
 | 
				
			||||||
 | 
					        const wxString renderer = glGetwxString(GL_RENDERER).Lower();
 | 
				
			||||||
 | 
					        if ( vendor.find("nvidia") != wxString::npos &&
 | 
				
			||||||
 | 
					                renderer.find("quadro") == wxString::npos )
 | 
				
			||||||
 | 
					            ShowFullScreen(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event))
 | 
					void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event))
 | 
				
			||||||
@@ -428,3 +509,7 @@ void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
 | 
				
			|||||||
    new MyFrame();
 | 
					    new MyFrame();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MyFrame::OnNewStereoWindow( wxCommandEvent& WXUNUSED(event) )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    new MyFrame(true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,30 +31,33 @@ private:
 | 
				
			|||||||
class MyApp : public wxApp
 | 
					class MyApp : public wxApp
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    MyApp() { m_glContext = NULL; }
 | 
					    MyApp() { m_glContext = NULL; m_glStereoContext = NULL; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Returns the shared context used by all frames and sets it as current for
 | 
					    // Returns the shared context used by all frames and sets it as current for
 | 
				
			||||||
    // the given canvas.
 | 
					    // the given canvas.
 | 
				
			||||||
    TestGLContext& GetContext(wxGLCanvas *canvas);
 | 
					    TestGLContext& GetContext(wxGLCanvas *canvas, bool useStereo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // virtual wxApp methods
 | 
					    // virtual wxApp methods
 | 
				
			||||||
    virtual bool OnInit();
 | 
					    virtual bool OnInit();
 | 
				
			||||||
    virtual int OnExit();
 | 
					    virtual int OnExit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    // the GL context we use for all our windows
 | 
					    // the GL context we use for all our mono rendering windows
 | 
				
			||||||
    TestGLContext *m_glContext;
 | 
					    TestGLContext *m_glContext;
 | 
				
			||||||
 | 
					    // the GL context we use for all our stereo rendering windows
 | 
				
			||||||
 | 
					    TestGLContext *m_glStereoContext;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Define a new frame type
 | 
					// Define a new frame type
 | 
				
			||||||
class MyFrame : public wxFrame
 | 
					class MyFrame : public wxFrame
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    MyFrame();
 | 
					    MyFrame(bool stereoWindow = false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void OnClose(wxCommandEvent& event);
 | 
					    void OnClose(wxCommandEvent& event);
 | 
				
			||||||
    void OnNewWindow(wxCommandEvent& event);
 | 
					    void OnNewWindow(wxCommandEvent& event);
 | 
				
			||||||
 | 
					    void OnNewStereoWindow(wxCommandEvent& event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DECLARE_EVENT_TABLE()
 | 
					    DECLARE_EVENT_TABLE()
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -62,7 +65,7 @@ private:
 | 
				
			|||||||
class TestGLCanvas : public wxGLCanvas
 | 
					class TestGLCanvas : public wxGLCanvas
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    TestGLCanvas(wxWindow *parent);
 | 
					    TestGLCanvas(wxWindow *parent, int *attribList = NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    void OnPaint(wxPaintEvent& event);
 | 
					    void OnPaint(wxPaintEvent& event);
 | 
				
			||||||
@@ -75,8 +78,15 @@ private:
 | 
				
			|||||||
          m_yangle;
 | 
					          m_yangle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    wxTimer m_spinTimer;
 | 
					    wxTimer m_spinTimer;
 | 
				
			||||||
 | 
					    bool m_useStereo,
 | 
				
			||||||
 | 
					         m_stereoWarningAlreadyDisplayed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DECLARE_EVENT_TABLE()
 | 
					    DECLARE_EVENT_TABLE()
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    NEW_STEREO_WINDOW = wxID_HIGHEST + 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // _WX_CUBE_H_
 | 
					#endif // _WX_CUBE_H_
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user