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)
|
||||||
{
|
{
|
||||||
if ( !m_glContext )
|
TestGLContext *glContext;
|
||||||
|
if ( useStereo )
|
||||||
{
|
{
|
||||||
// Create the OpenGL context for the first window which needs it:
|
if ( !m_glStereoContext )
|
||||||
// subsequently created windows will all share the same context.
|
{
|
||||||
m_glContext = new TestGLContext(canvas);
|
// 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 )
|
||||||
|
{
|
||||||
|
// Create the OpenGL context for the first mono window which needs it:
|
||||||
|
// subsequently created windows will all share the same context.
|
||||||
|
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.
|
||||||
canvas.DrawRotatedCube(m_xangle, m_yangle);
|
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);
|
||||||
|
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