Improve wxQt OpenGL canvas implementation:
- Support wxGLContext::SetCurrent. - Pass GL canvas attributes via ParseAttribList to handle defaults. - Remove OpenGL not implemented message. - Prevent QGLWidget from changing OpenGL state before we paint. - Set Qt::StrongFocus for wxQtGLWidget to allow keyboard input. - Use QtCanPaintWithoutActivePainter to fix wxPaintDCImpl assert when using wxGLCanvas.
This commit is contained in:
parent
57349c2aaa
commit
966b6e9460
5 changed files with 184 additions and 69 deletions
|
|
@ -24,6 +24,9 @@ public:
|
|||
|
||||
virtual bool SetCurrent(const wxGLCanvas& win) const override;
|
||||
|
||||
private:
|
||||
QGLContext* m_glContext = nullptr;
|
||||
|
||||
wxDECLARE_CLASS(wxGLContext);
|
||||
};
|
||||
|
||||
|
|
@ -78,7 +81,9 @@ public:
|
|||
|
||||
virtual bool SwapBuffers() override;
|
||||
|
||||
static bool ConvertWXAttrsToQtGL(const int *wxattrs, QGLFormat &format);
|
||||
virtual bool QtCanPaintWithoutActivePainter() const override;
|
||||
|
||||
static bool ConvertWXAttrsToQtGL(const wxGLAttributes &glattrs, const wxGLContextAttrs ctxAttrs, QGLFormat &format);
|
||||
|
||||
private:
|
||||
wxDECLARE_CLASS(wxGLCanvas);
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ public:
|
|||
void QtSetPicture( QPicture* pict );
|
||||
|
||||
QPainter *QtGetPainter();
|
||||
virtual bool QtCanPaintWithoutActivePainter() const;
|
||||
|
||||
virtual bool QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event );
|
||||
virtual bool QtHandleResizeEvent ( QWidget *handler, QResizeEvent *event );
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ wxPaintDCImpl::wxPaintDCImpl( wxDC *owner )
|
|||
wxPaintDCImpl::wxPaintDCImpl( wxDC *owner, wxWindow *win )
|
||||
: wxWindowDCImpl( owner, win )
|
||||
{
|
||||
wxCHECK_RET( m_isWindowPainter,
|
||||
wxCHECK_RET( m_isWindowPainter || win->QtCanPaintWithoutActivePainter(),
|
||||
"wxPaintDC can't be created outside wxEVT_PAINT handler" );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,26 +16,20 @@
|
|||
#include <QtWidgets/QGestureRecognizer>
|
||||
#include <QtWidgets/QGestureEvent>
|
||||
|
||||
#if defined(__VISUALC__)
|
||||
#pragma message("OpenGL support is not implemented in wxQt")
|
||||
#else
|
||||
#warning "OpenGL support is not implemented in wxQt"
|
||||
#endif
|
||||
wxGCC_WARNING_SUPPRESS(unused-parameter)
|
||||
|
||||
class wxQtGLWidget : public wxQtEventSignalHandler< QGLWidget, wxGLCanvas >
|
||||
{
|
||||
public:
|
||||
wxQtGLWidget(wxWindow *parent, wxGLCanvas *handler, QGLFormat format)
|
||||
: wxQtEventSignalHandler<QGLWidget,wxGLCanvas>(parent, handler)
|
||||
{
|
||||
setFormat(format);
|
||||
setAutoBufferSwap( false );
|
||||
}
|
||||
: wxQtEventSignalHandler<QGLWidget, wxGLCanvas>(parent, handler)
|
||||
{
|
||||
setFormat(format);
|
||||
setAutoBufferSwap(false);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void showEvent ( QShowEvent * event ) override;
|
||||
virtual void hideEvent ( QHideEvent * event ) override;
|
||||
virtual void resizeEvent ( QResizeEvent * event ) override;
|
||||
virtual void paintEvent ( QPaintEvent * event ) override;
|
||||
|
||||
|
|
@ -43,16 +37,6 @@ protected:
|
|||
virtual void paintGL() override;
|
||||
};
|
||||
|
||||
void wxQtGLWidget::showEvent ( QShowEvent * event )
|
||||
{
|
||||
QGLWidget::showEvent( event );
|
||||
}
|
||||
|
||||
void wxQtGLWidget::hideEvent ( QHideEvent * event )
|
||||
{
|
||||
QGLWidget::hideEvent( event );
|
||||
}
|
||||
|
||||
void wxQtGLWidget::resizeEvent ( QResizeEvent * event )
|
||||
{
|
||||
QGLWidget::resizeEvent(event);
|
||||
|
|
@ -84,6 +68,7 @@ wxGLContextAttrs& wxGLContextAttrs::CoreProfile()
|
|||
{
|
||||
// AddAttribBits(GLX_CONTEXT_PROFILE_MASK_ARB,
|
||||
// GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
|
||||
AddAttribute(wx_GL_COMPAT_PROFILE);
|
||||
SetNeedsARB();
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -92,6 +77,9 @@ wxGLContextAttrs& wxGLContextAttrs::MajorVersion(int val)
|
|||
{
|
||||
if ( val > 0 )
|
||||
{
|
||||
AddAttribute(WX_GL_MAJOR_VERSION);
|
||||
AddAttribute(val);
|
||||
|
||||
if ( val >= 3 )
|
||||
SetNeedsARB();
|
||||
}
|
||||
|
|
@ -102,12 +90,15 @@ wxGLContextAttrs& wxGLContextAttrs::MinorVersion(int val)
|
|||
{
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(WX_GL_MINOR_VERSION);
|
||||
AddAttribute(val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxGLContextAttrs& wxGLContextAttrs::CompatibilityProfile()
|
||||
{
|
||||
AddAttribute(wx_GL_COMPAT_PROFILE);
|
||||
SetNeedsARB();
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -168,7 +159,7 @@ wxGLContextAttrs& wxGLContextAttrs::PlatformDefaults()
|
|||
|
||||
void wxGLContextAttrs::EndList()
|
||||
{
|
||||
// AddAttribute(None);
|
||||
AddAttribute(0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -190,6 +181,7 @@ void wxGLContextAttrs::EndList()
|
|||
|
||||
wxGLAttributes& wxGLAttributes::RGBA()
|
||||
{
|
||||
AddAttribute(WX_GL_RGBA);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -197,24 +189,28 @@ wxGLAttributes& wxGLAttributes::BufferSize(int val)
|
|||
{
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(WX_GL_BUFFER_SIZE);
|
||||
AddAttribute(val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxGLAttributes& wxGLAttributes::Level(int val)
|
||||
{
|
||||
// AddAttribute(GLX_LEVEL);
|
||||
AddAttribute(WX_GL_LEVEL);
|
||||
AddAttribute(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxGLAttributes& wxGLAttributes::DoubleBuffer()
|
||||
{
|
||||
AddAttribute(WX_GL_DOUBLEBUFFER);
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxGLAttributes& wxGLAttributes::Stereo()
|
||||
{
|
||||
AddAttribute(WX_GL_STEREO);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -222,6 +218,8 @@ wxGLAttributes& wxGLAttributes::AuxBuffers(int val)
|
|||
{
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(WX_GL_AUX_BUFFERS);
|
||||
AddAttribute(val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -230,15 +228,23 @@ wxGLAttributes& wxGLAttributes::MinRGBA(int mRed, int mGreen, int mBlue, int mAl
|
|||
{
|
||||
if ( mRed >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_RED);
|
||||
AddAttribute(mRed);
|
||||
}
|
||||
if ( mGreen >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_GREEN);
|
||||
AddAttribute(mGreen);
|
||||
}
|
||||
if ( mBlue >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_BLUE);
|
||||
AddAttribute(mBlue);
|
||||
}
|
||||
if ( mAlpha >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_ALPHA);
|
||||
AddAttribute(mAlpha);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -247,6 +253,8 @@ wxGLAttributes& wxGLAttributes::Depth(int val)
|
|||
{
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(WX_GL_DEPTH_SIZE);
|
||||
AddAttribute(val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -255,6 +263,8 @@ wxGLAttributes& wxGLAttributes::Stencil(int val)
|
|||
{
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(WX_GL_DEPTH_SIZE);
|
||||
AddAttribute(val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -263,40 +273,44 @@ wxGLAttributes& wxGLAttributes::MinAcumRGBA(int mRed, int mGreen, int mBlue, int
|
|||
{
|
||||
if ( mRed >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_ACCUM_RED);
|
||||
AddAttribute(mRed);
|
||||
}
|
||||
if ( mGreen >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_ACCUM_GREEN);
|
||||
AddAttribute(mGreen);
|
||||
}
|
||||
if ( mBlue >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_ACCUM_BLUE);
|
||||
AddAttribute(mBlue);
|
||||
}
|
||||
if ( mAlpha >= 0)
|
||||
{
|
||||
AddAttribute(WX_GL_MIN_ACCUM_ALPHA);
|
||||
AddAttribute(mAlpha);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxGLAttributes& wxGLAttributes::SampleBuffers(int val)
|
||||
{
|
||||
#ifdef GLX_SAMPLE_BUFFERS_ARB
|
||||
if ( val >= 0 && wxGLCanvasX11::IsGLXMultiSampleAvailable() )
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(GLX_SAMPLE_BUFFERS_ARB);
|
||||
AddAttribute(WX_GL_SAMPLE_BUFFERS);
|
||||
AddAttribute(val);
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxGLAttributes& wxGLAttributes::Samplers(int val)
|
||||
{
|
||||
#ifdef GLX_SAMPLES_ARB
|
||||
if ( val >= 0 && wxGLCanvasX11::IsGLXMultiSampleAvailable() )
|
||||
if ( val >= 0 )
|
||||
{
|
||||
AddAttribute(GLX_SAMPLES_ARB);
|
||||
AddAttribute(WX_GL_SAMPLES);
|
||||
AddAttribute(val);
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -309,11 +323,12 @@ wxGLAttributes& wxGLAttributes::FrameBuffersRGB()
|
|||
|
||||
void wxGLAttributes::EndList()
|
||||
{
|
||||
AddAttribute(0);
|
||||
}
|
||||
|
||||
wxGLAttributes& wxGLAttributes::PlatformDefaults()
|
||||
{
|
||||
// No GLX specific values
|
||||
// No Qt specific values
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -324,15 +339,33 @@ wxGLAttributes& wxGLAttributes::PlatformDefaults()
|
|||
|
||||
wxIMPLEMENT_CLASS(wxGLContext, wxWindow);
|
||||
|
||||
wxGLContext::wxGLContext(wxGLCanvas *WXUNUSED(win), const wxGLContext* WXUNUSED(other), const wxGLContextAttrs *WXUNUSED(ctxAttrs))
|
||||
wxGLContext::wxGLContext(wxGLCanvas *win,
|
||||
const wxGLContext *other,
|
||||
const wxGLContextAttrs *ctxAttrs)
|
||||
{
|
||||
QGLWidget *qglWidget = static_cast<QGLWidget *>(win->GetHandle());
|
||||
m_glContext = qglWidget->context();
|
||||
|
||||
if (m_glContext != nullptr)
|
||||
{
|
||||
m_isOk = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxGLContext::SetCurrent(const wxGLCanvas&) const
|
||||
bool wxGLContext::SetCurrent(const wxGLCanvas& win) const
|
||||
{
|
||||
// I think I must destroy and recreate the QGLWidget to change the context?
|
||||
// win->GetHandle()->makeCurrent();
|
||||
return false;
|
||||
QGLWidget *qglWidget = static_cast<QGLWidget *>(win.GetHandle());
|
||||
QGLContext *context = qglWidget->context();
|
||||
|
||||
if (context != m_glContext)
|
||||
{
|
||||
// I think I must destroy and recreate the QGLWidget to change the context?
|
||||
wxLogDebug("Calling wxGLContext::SetCurrent with a different canvas is not supported in wxQt");
|
||||
return false;
|
||||
}
|
||||
|
||||
qglWidget->makeCurrent();
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -403,8 +436,11 @@ bool wxGLCanvas::Create(wxWindow *parent,
|
|||
const wxString& name,
|
||||
const wxPalette& palette)
|
||||
{
|
||||
wxLogError("Missing implementation of " + wxString(__FUNCTION__));
|
||||
return false;
|
||||
const int* attrsList = dispAttrs.GetGLAttrs();
|
||||
|
||||
wxCHECK_MSG(attrsList, false, "wxGLAttributes object is empty.");
|
||||
|
||||
return Create(parent, id, pos, size, style, name, attrsList, palette);
|
||||
}
|
||||
|
||||
bool wxGLCanvas::Create(wxWindow *parent,
|
||||
|
|
@ -421,17 +457,35 @@ bool wxGLCanvas::Create(wxWindow *parent,
|
|||
#endif // wxUSE_PALETTE
|
||||
wxUnusedVar(palette); // Unused when wxDEBUG_LEVEL==0
|
||||
|
||||
QGLFormat format;
|
||||
if (!wxGLCanvas::ConvertWXAttrsToQtGL(attribList, format))
|
||||
// Separate display/context attributes, set defaults.
|
||||
wxGLAttributes dispAttrs;
|
||||
wxGLContextAttrs ctxAttrs;
|
||||
if (!ParseAttribList(attribList, dispAttrs, &ctxAttrs))
|
||||
return false;
|
||||
|
||||
QGLFormat format;
|
||||
if (!wxGLCanvas::ConvertWXAttrsToQtGL(dispAttrs, ctxAttrs, format))
|
||||
return false;
|
||||
|
||||
// Return false if any attribute is unsupported
|
||||
if ( !IsDisplaySupported(attribList) )
|
||||
{
|
||||
wxFAIL_MSG("Can't find a pixel format for the requested attributes");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_qtWindow = new wxQtGLWidget(parent, this, format);
|
||||
|
||||
// Create and register a custom pan recognizer, available to all instances of this class.
|
||||
QGestureRecognizer* pPanRecognizer = new PanGestureRecognizer();
|
||||
QGestureRecognizer::registerRecognizer(pPanRecognizer);
|
||||
|
||||
return wxWindow::Create( parent, id, pos, size, style, name );
|
||||
if ( !wxWindow::Create( parent, id, pos, size, style, name ) )
|
||||
return false;
|
||||
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxGLCanvas::SwapBuffers()
|
||||
|
|
@ -440,11 +494,16 @@ bool wxGLCanvas::SwapBuffers()
|
|||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool wxGLCanvas::ConvertWXAttrsToQtGL(const int *wxattrs, QGLFormat &format)
|
||||
bool wxGLCanvas::QtCanPaintWithoutActivePainter() const
|
||||
{
|
||||
if (!wxattrs)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool wxGLCanvas::ConvertWXAttrsToQtGL(const wxGLAttributes &wxGLAttrs, const wxGLContextAttrs wxCtxAttrs, QGLFormat &format)
|
||||
{
|
||||
const int *glattrs = wxGLAttrs.GetGLAttrs();
|
||||
const int *ctxattrs = wxCtxAttrs.GetGLAttrs();
|
||||
|
||||
// set default parameters to false
|
||||
format.setDoubleBuffer(false);
|
||||
|
|
@ -452,14 +511,16 @@ bool wxGLCanvas::ConvertWXAttrsToQtGL(const int *wxattrs, QGLFormat &format)
|
|||
format.setAlpha(false);
|
||||
format.setStencil(false);
|
||||
|
||||
for ( int arg = 0; wxattrs[arg] != 0; arg++ )
|
||||
for (int arg = 0; glattrs && glattrs[arg] != 0; arg++)
|
||||
{
|
||||
// indicates whether we have a boolean attribute
|
||||
bool isBoolAttr = false;
|
||||
|
||||
int v = wxattrs[arg+1];
|
||||
switch ( wxattrs[arg] )
|
||||
int v = glattrs[arg+1];
|
||||
switch ( glattrs[arg] )
|
||||
{
|
||||
// Pixel format attributes
|
||||
|
||||
case WX_GL_BUFFER_SIZE:
|
||||
format.setRgba(false);
|
||||
// I do not know how to set the buffer size, so fail
|
||||
|
|
@ -489,7 +550,7 @@ bool wxGLCanvas::ConvertWXAttrsToQtGL(const int *wxattrs, QGLFormat &format)
|
|||
return false;
|
||||
|
||||
case WX_GL_MIN_RED:
|
||||
format.setRedBufferSize(v*8);
|
||||
format.setRedBufferSize(v);
|
||||
break;
|
||||
|
||||
case WX_GL_MIN_GREEN:
|
||||
|
|
@ -532,17 +593,54 @@ bool wxGLCanvas::ConvertWXAttrsToQtGL(const int *wxattrs, QGLFormat &format)
|
|||
// can we somehow indicate if it's not supported?
|
||||
break;
|
||||
|
||||
case WX_GL_MAJOR_VERSION:
|
||||
format.setVersion ( v,0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogDebug(wxT("Unsupported OpenGL attribute %d"),
|
||||
wxattrs[arg]);
|
||||
glattrs[arg]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !isBoolAttr ) {
|
||||
if ( !isBoolAttr )
|
||||
{
|
||||
if ( !v )
|
||||
return false; // zero parameter
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int arg = 0; ctxattrs && ctxattrs[arg] != 0; arg++)
|
||||
{
|
||||
// indicates whether we have a boolean attribute
|
||||
bool isBoolAttr = false;
|
||||
|
||||
int v = ctxattrs[arg+1];
|
||||
switch ( ctxattrs[arg] )
|
||||
{
|
||||
// Context attributes
|
||||
|
||||
case WX_GL_MAJOR_VERSION:
|
||||
format.setVersion ( v, format.minorVersion() );
|
||||
break;
|
||||
|
||||
case WX_GL_MINOR_VERSION:
|
||||
format.setVersion ( format.majorVersion(), v );
|
||||
break;
|
||||
|
||||
case WX_GL_CORE_PROFILE:
|
||||
format.setProfile(QGLFormat::CoreProfile);
|
||||
break;
|
||||
|
||||
case wx_GL_COMPAT_PROFILE:
|
||||
format.setProfile(QGLFormat::CompatibilityProfile);
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogDebug(wxT("Unsupported OpenGL attribute %d"),
|
||||
ctxattrs[arg]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !isBoolAttr )
|
||||
{
|
||||
if ( !v )
|
||||
return false; // zero parameter
|
||||
arg++;
|
||||
|
|
@ -553,23 +651,29 @@ bool wxGLCanvas::ConvertWXAttrsToQtGL(const int *wxattrs, QGLFormat &format)
|
|||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
wxGLCanvasBase::IsDisplaySupported(const int *attribList)
|
||||
bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
|
||||
{
|
||||
QGLFormat format;
|
||||
const int* attrsList = dispAttrs.GetGLAttrs();
|
||||
|
||||
if (!wxGLCanvas::ConvertWXAttrsToQtGL(attribList, format))
|
||||
return false;
|
||||
wxCHECK_MSG(attrsList, false, "wxGLAttributes object is empty.");
|
||||
|
||||
return QGLWidget(format).isValid();
|
||||
return IsDisplaySupported(attrsList);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
|
||||
bool wxGLCanvasBase::IsDisplaySupported(const int *attribList)
|
||||
{
|
||||
wxLogError("Missing implementation of " + wxString(__FUNCTION__));
|
||||
return false;
|
||||
// Separate display/context attributes, set defaults.
|
||||
wxGLAttributes dispAttrs;
|
||||
wxGLContextAttrs ctxAttrs;
|
||||
if (!ParseAttribList(attribList, dispAttrs, &ctxAttrs))
|
||||
return false;
|
||||
|
||||
QGLFormat format;
|
||||
if (!wxGLCanvas::ConvertWXAttrsToQtGL(dispAttrs, ctxAttrs, format))
|
||||
return false;
|
||||
|
||||
return QGLWidget(format).isValid();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1830,6 +1830,11 @@ QPainter *wxWindowQt::QtGetPainter()
|
|||
return m_qtPainter.get();
|
||||
}
|
||||
|
||||
bool wxWindowQt::QtCanPaintWithoutActivePainter() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxWindowQt::EnableTouchEvents(int eventsMask)
|
||||
{
|
||||
wxCHECK_MSG( GetHandle(), false, "can't be called before creating the window" );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue