From 0ead3b7142e47b89059af689de4ede47075375be Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 11 Jul 2018 15:12:56 +0200 Subject: Move arthurwidget based examples to new QOpenGL classes Several of the examples were not even working besides using deprecated classes. Change-Id: I352e0629d490593edcc5868d2ec5a8ff222eaeab Reviewed-by: Laszlo Agocs --- examples/widgets/painting/affine/affine.pro | 4 - examples/widgets/painting/affine/xform.cpp | 8 +- .../widgets/painting/composition/composition.cpp | 129 +++++++-------------- .../widgets/painting/composition/composition.h | 18 +-- .../widgets/painting/composition/composition.pro | 4 - examples/widgets/painting/composition/main.cpp | 7 +- examples/widgets/painting/deform/deform.pro | 4 - examples/widgets/painting/deform/pathdeform.cpp | 24 ++-- examples/widgets/painting/gradients/gradients.cpp | 8 +- examples/widgets/painting/gradients/gradients.pro | 4 - .../widgets/painting/pathstroke/pathstroke.cpp | 16 +-- .../widgets/painting/pathstroke/pathstroke.pro | 4 - examples/widgets/painting/shared/arthurwidgets.cpp | 80 ++++++++----- examples/widgets/painting/shared/arthurwidgets.h | 46 ++------ .../widgets/painting/shared/fbopaintdevice.cpp | 113 ++++++++++++++++++ examples/widgets/painting/shared/fbopaintdevice.h | 91 +++++++++++++++ examples/widgets/painting/shared/hoverpoints.cpp | 19 +-- examples/widgets/painting/shared/shared.pri | 6 +- 18 files changed, 346 insertions(+), 239 deletions(-) create mode 100644 examples/widgets/painting/shared/fbopaintdevice.cpp create mode 100644 examples/widgets/painting/shared/fbopaintdevice.h (limited to 'examples') diff --git a/examples/widgets/painting/affine/affine.pro b/examples/widgets/painting/affine/affine.pro index 0ad869183c..0af18b82ca 100644 --- a/examples/widgets/painting/affine/affine.pro +++ b/examples/widgets/painting/affine/affine.pro @@ -1,10 +1,6 @@ SOURCES += main.cpp xform.cpp HEADERS += xform.h -qtHaveModule(opengl) { - DEFINES += QT_OPENGL_SUPPORT - QT += opengl -} QT += widgets SHARED_FOLDER = ../shared diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp index 20f6eb3c6d..dc01acf453 100644 --- a/examples/widgets/painting/affine/xform.cpp +++ b/examples/widgets/painting/affine/xform.cpp @@ -830,13 +830,11 @@ XFormWidget::XFormWidget(QWidget *parent) QPushButton *showSourceButton = new QPushButton(mainGroup); showSourceButton->setText(tr("Show Source")); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(mainGroup); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(true); enableOpenGLButton->setChecked(view->usesOpenGL()); - if (!QGLFormat::hasOpenGL()) - enableOpenGLButton->hide(); #endif QPushButton *whatsThisButton = new QPushButton(mainGroup); whatsThisButton->setText(tr("What's This?")); @@ -871,7 +869,7 @@ XFormWidget::XFormWidget(QWidget *parent) mainGroupLayout->addWidget(resetButton); mainGroupLayout->addWidget(animateButton); mainGroupLayout->addWidget(showSourceButton); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) mainGroupLayout->addWidget(enableOpenGLButton); #endif mainGroupLayout->addWidget(whatsThisButton); @@ -897,7 +895,7 @@ XFormWidget::XFormWidget(QWidget *parent) connect(view, &XFormView::descriptionEnabledChanged, view->hoverPoints(), &HoverPoints::setDisabled); connect(view, &XFormView::descriptionEnabledChanged, whatsThisButton, &QPushButton::setChecked); connect(showSourceButton, &QPushButton::clicked, view, &XFormView::showSource); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) connect(enableOpenGLButton, &QPushButton::clicked, view, &XFormView::enableOpenGL); #endif view->loadSourceFile(":res/affine/xform.cpp"); diff --git a/examples/widgets/painting/composition/composition.cpp b/examples/widgets/painting/composition/composition.cpp index 0b57d3c7d3..3bc31b1fce 100644 --- a/examples/widgets/painting/composition/composition.cpp +++ b/examples/widgets/painting/composition/composition.cpp @@ -57,6 +57,11 @@ #include #include +#if QT_CONFIG(opengl) +#include +#include +#endif + const int animationInterval = 15; // update every 16 ms = ~60FPS CompositionWidget::CompositionWidget(QWidget *parent) @@ -136,14 +141,11 @@ CompositionWidget::CompositionWidget(QWidget *parent) QPushButton *showSourceButton = new QPushButton(mainGroup); showSourceButton->setText(tr("Show Source")); -#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES) +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(mainGroup); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(true); enableOpenGLButton->setChecked(view->usesOpenGL()); - - if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers()) - enableOpenGLButton->hide(); #endif QPushButton *whatsThisButton = new QPushButton(mainGroup); whatsThisButton->setText(tr("What's This?")); @@ -166,7 +168,7 @@ CompositionWidget::CompositionWidget(QWidget *parent) mainGroupLayout->addWidget(animateButton); mainGroupLayout->addWidget(whatsThisButton); mainGroupLayout->addWidget(showSourceButton); -#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES) +#if QT_CONFIG(opengl) mainGroupLayout->addWidget(enableOpenGLButton); #endif @@ -210,7 +212,7 @@ CompositionWidget::CompositionWidget(QWidget *parent) connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool))); connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool))); connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource())); -#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES) +#if QT_CONFIG(opengl) connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool))); #endif connect(animateButton, SIGNAL(toggled(bool)), view, SLOT(setAnimationEnabled(bool))); @@ -258,8 +260,7 @@ CompositionRenderer::CompositionRenderer(QWidget *parent) m_circle_pos = QPoint(200, 100); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); -#ifdef USE_OPENGL - m_pbuffer = 0; +#if QT_CONFIG(opengl) m_pbuffer_size = 1024; #endif } @@ -350,8 +351,11 @@ void CompositionRenderer::drawSource(QPainter &p) void CompositionRenderer::paint(QPainter *painter) { -#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES) - if (usesOpenGL()) { +#if QT_CONFIG(opengl) + if (usesOpenGL() && glWindow()->isValid()) { + + if (!m_blitter.isCreated()) + m_blitter.create(); int new_pbuf_size = m_pbuffer_size; if (size().width() > m_pbuffer_size || size().height() > m_pbuffer_size) @@ -360,95 +364,46 @@ void CompositionRenderer::paint(QPainter *painter) if (size().width() < m_pbuffer_size/2 && size().height() < m_pbuffer_size/2) new_pbuf_size /= 2; - if (!m_pbuffer || new_pbuf_size != m_pbuffer_size) { - if (m_pbuffer) { - m_pbuffer->deleteTexture(m_base_tex); - m_pbuffer->deleteTexture(m_compositing_tex); - delete m_pbuffer; - } - - m_pbuffer = new QGLPixelBuffer(QSize(new_pbuf_size, new_pbuf_size), QGLFormat::defaultFormat(), glWidget()); - m_pbuffer->makeCurrent(); - m_base_tex = m_pbuffer->generateDynamicTexture(); - m_compositing_tex = m_pbuffer->generateDynamicTexture(); + if (!m_fbo || new_pbuf_size != m_pbuffer_size) { + m_fbo.reset(new QFboPaintDevice(QSize(new_pbuf_size, new_pbuf_size), false, false)); m_pbuffer_size = new_pbuf_size; } if (size() != m_previous_size) { m_previous_size = size(); - QPainter p(m_pbuffer); - p.setCompositionMode(QPainter::CompositionMode_Source); - p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent); + QPainter p(m_fbo.data()); drawBase(p); p.end(); - m_pbuffer->updateDynamicTexture(m_base_tex); + m_base_tex = m_fbo->takeTexture(); } - qreal x_fraction = width()/float(m_pbuffer->width()); - qreal y_fraction = height()/float(m_pbuffer->height()); - + painter->beginNativePainting(); { - QPainter p(m_pbuffer); - p.setCompositionMode(QPainter::CompositionMode_Source); - p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent); - - p.save(); // Needed when using the GL1 engine - p.beginNativePainting(); // Needed when using the GL2 engine - - glBindTexture(GL_TEXTURE_2D, m_base_tex); - glEnable(GL_TEXTURE_2D); - glColor4f(1.,1.,1.,1.); - - glBegin(GL_QUADS); - { - glTexCoord2f(0, 1.0); - glVertex2f(0, 0); - - glTexCoord2f(x_fraction, 1.0); - glVertex2f(width(), 0); - - glTexCoord2f(x_fraction, 1.0-y_fraction); - glVertex2f(width(), height()); - - glTexCoord2f(0, 1.0-y_fraction); - glVertex2f(0, height()); - } - glEnd(); - - glDisable(GL_TEXTURE_2D); - - p.endNativePainting(); // Needed when using the GL2 engine - p.restore(); // Needed when using the GL1 engine - + QPainter p(m_fbo.data()); + p.beginNativePainting(); + m_blitter.bind(); + const QRect targetRect(QPoint(0, 0), m_fbo->size()); + const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(0, 0), m_fbo->size())); + m_blitter.blit(m_base_tex, target, QOpenGLTextureBlitter::OriginBottomLeft); + m_blitter.release(); + p.endNativePainting(); drawSource(p); p.end(); - m_pbuffer->updateDynamicTexture(m_compositing_tex); - } - - painter->beginNativePainting(); // Needed when using the GL2 engine - glWidget()->makeCurrent(); // Needed when using the GL1 engine - glBindTexture(GL_TEXTURE_2D, m_compositing_tex); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(1.,1.,1.,1.); - glBegin(GL_QUADS); - { - glTexCoord2f(0, 1.0); - glVertex2f(0, 0); - - glTexCoord2f(x_fraction, 1.0); - glVertex2f(width(), 0); - - glTexCoord2f(x_fraction, 1.0-y_fraction); - glVertex2f(width(), height()); - - glTexCoord2f(0, 1.0-y_fraction); - glVertex2f(0, height()); + m_compositing_tex = m_fbo->takeTexture(); } - glEnd(); - glDisable(GL_TEXTURE_2D); - painter->endNativePainting(); // Needed when using the GL2 engine + painter->endNativePainting(); + + painter->beginNativePainting(); + auto *funcs = QOpenGLContext::currentContext()->functions(); + funcs->glEnable(GL_BLEND); + funcs->glBlendEquation(GL_FUNC_ADD); + funcs->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + m_blitter.bind(); + const QRect targetRect(QPoint(0, 0), m_fbo->size()); + const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(0, 0), size())); + m_blitter.blit(m_compositing_tex, target, QOpenGLTextureBlitter::OriginBottomLeft); + m_blitter.release(); + painter->endNativePainting(); } else #endif { @@ -520,7 +475,7 @@ void CompositionRenderer::setCirclePos(const QPointF &pos) const QRect oldRect = rectangle_around(m_circle_pos).toAlignedRect(); m_circle_pos = pos; const QRect newRect = rectangle_around(m_circle_pos).toAlignedRect(); -#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES) +#if QT_CONFIG(opengl) if (usesOpenGL()) { update(); return; diff --git a/examples/widgets/painting/composition/composition.h b/examples/widgets/painting/composition/composition.h index 49853f503b..19150e2024 100644 --- a/examples/widgets/painting/composition/composition.h +++ b/examples/widgets/painting/composition/composition.h @@ -53,6 +53,11 @@ #include "arthurwidgets.h" +#if QT_CONFIG(opengl) +#include "fbopaintdevice.h" +#include +#endif + #include #include @@ -61,10 +66,6 @@ class QPushButton; class QRadioButton; QT_END_NAMESPACE -#ifdef QT_OPENGL_SUPPORT -#include -#endif - class CompositionWidget : public QWidget { Q_OBJECT @@ -186,12 +187,13 @@ private: bool m_animation_enabled; int m_animationTimer; -#ifdef QT_OPENGL_SUPPORT - QGLPixelBuffer *m_pbuffer; - GLuint m_base_tex; - GLuint m_compositing_tex; +#if QT_CONFIG(opengl) + QScopedPointer m_fbo; int m_pbuffer_size; // width==height==size of pbuffer + uint m_base_tex; + uint m_compositing_tex; QSize m_previous_size; + QOpenGLTextureBlitter m_blitter; #endif }; diff --git a/examples/widgets/painting/composition/composition.pro b/examples/widgets/painting/composition/composition.pro index 5fdbe4a5a2..15d8c6e67b 100644 --- a/examples/widgets/painting/composition/composition.pro +++ b/examples/widgets/painting/composition/composition.pro @@ -6,10 +6,6 @@ SHARED_FOLDER = ../shared include($$SHARED_FOLDER/shared.pri) RESOURCES += composition.qrc -qtHaveModule(opengl):!qtConfig(dynamicgl) { - DEFINES += USE_OPENGL - QT += opengl -} QT += widgets # install diff --git a/examples/widgets/painting/composition/main.cpp b/examples/widgets/painting/composition/main.cpp index 1a5dfd3e5e..1f4ead7165 100644 --- a/examples/widgets/painting/composition/main.cpp +++ b/examples/widgets/painting/composition/main.cpp @@ -51,17 +51,12 @@ #include "composition.h" #include -#ifdef QT_OPENGL_SUPPORT -#include -#endif int main(int argc, char *argv[]) { - // Q_INIT_RESOURCE(deform); - QApplication app(argc, argv); - CompositionWidget compWidget(0); + CompositionWidget compWidget(nullptr); QStyle *arthurStyle = new ArthurStyle(); compWidget.setStyle(arthurStyle); diff --git a/examples/widgets/painting/deform/deform.pro b/examples/widgets/painting/deform/deform.pro index 6409aaed96..498ec57686 100644 --- a/examples/widgets/painting/deform/deform.pro +++ b/examples/widgets/painting/deform/deform.pro @@ -7,10 +7,6 @@ include($$SHARED_FOLDER/shared.pri) RESOURCES += deform.qrc -qtHaveModule(opengl) { - DEFINES += QT_OPENGL_SUPPORT - QT += opengl -} QT += widgets # install diff --git a/examples/widgets/painting/deform/pathdeform.cpp b/examples/widgets/painting/deform/pathdeform.cpp index 805804716f..7c3fe45277 100644 --- a/examples/widgets/painting/deform/pathdeform.cpp +++ b/examples/widgets/painting/deform/pathdeform.cpp @@ -109,13 +109,11 @@ void PathDeformControls::layoutForDesktop() QPushButton *showSourceButton = new QPushButton(mainGroup); showSourceButton->setText(tr("Show Source")); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(mainGroup); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(true); enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); - if (!QGLFormat::hasOpenGL()) - enableOpenGLButton->hide(); #endif QPushButton *whatsThisButton = new QPushButton(mainGroup); @@ -132,7 +130,7 @@ void PathDeformControls::layoutForDesktop() mainGroupLayout->addWidget(textGroup); mainGroupLayout->addWidget(animateButton); mainGroupLayout->addStretch(1); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) mainGroupLayout->addWidget(enableOpenGLButton); #endif mainGroupLayout->addWidget(showSourceButton); @@ -158,7 +156,7 @@ void PathDeformControls::layoutForDesktop() connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int))); connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int))); connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool))); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); #endif @@ -201,13 +199,11 @@ void PathDeformControls::layoutForSmallScreen() QPushButton *animateButton = new QPushButton(tr("Animated"), mainGroup); animateButton->setCheckable(true); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(mainGroup); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(mainGroup); enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); - if (!QGLFormat::hasOpenGL()) - enableOpenGLButton->hide(); #endif QPushButton *quitButton = new QPushButton(tr("Quit"), mainGroup); @@ -223,7 +219,7 @@ void PathDeformControls::layoutForSmallScreen() mainGroupLayout->addWidget(fontSizeLabel, 2, 0, Qt::AlignRight); mainGroupLayout->addWidget(fontSizeSlider, 2, 1); mainGroupLayout->addWidget(animateButton, 3,0, 1,2); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) mainGroupLayout->addWidget(enableOpenGLButton, 4,0, 1,2); #endif @@ -239,7 +235,7 @@ void PathDeformControls::layoutForSmallScreen() connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int))); connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int))); connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool))); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); #endif @@ -463,7 +459,7 @@ void PathDeformRenderer::timerEvent(QTimerEvent *e) m_pos.setY(height() - m_radius); } -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) if (usesOpenGL()) { update(); } else @@ -527,7 +523,7 @@ void PathDeformRenderer::mouseMoveEvent(QMouseEvent *e) m_direction = (m_direction + dir) / 2; } m_pos = e->pos() + m_offset; -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) if (usesOpenGL()) { update(); } else @@ -620,7 +616,7 @@ void PathDeformRenderer::setRadius(int radius) m_radius = radius; generateLensPixmap(); if (!m_animated || m_radius < max) { -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) if (usesOpenGL()){ update(); return; @@ -634,7 +630,7 @@ void PathDeformRenderer::setIntensity(int intensity) { m_intensity = intensity; if (!m_animated) { -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) if (usesOpenGL()) { update(); return; diff --git a/examples/widgets/painting/gradients/gradients.cpp b/examples/widgets/painting/gradients/gradients.cpp index 6d9f514a8d..004f6710cd 100644 --- a/examples/widgets/painting/gradients/gradients.cpp +++ b/examples/widgets/painting/gradients/gradients.cpp @@ -317,13 +317,11 @@ GradientWidget::GradientWidget(QWidget *parent) QPushButton *showSourceButton = new QPushButton(mainGroup); showSourceButton->setText(tr("Show Source")); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(mainGroup); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(true); enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); - if (!QGLFormat::hasOpenGL()) - enableOpenGLButton->hide(); #endif QPushButton *whatsThisButton = new QPushButton(mainGroup); whatsThisButton->setText(tr("What's This?")); @@ -343,7 +341,7 @@ GradientWidget::GradientWidget(QWidget *parent) mainGroupLayout->addWidget(defaultsGroup); mainGroupLayout->addStretch(1); mainGroupLayout->addWidget(showSourceButton); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) mainGroupLayout->addWidget(enableOpenGLButton); #endif mainGroupLayout->addWidget(whatsThisButton); @@ -406,7 +404,7 @@ GradientWidget::GradientWidget(QWidget *parent) connect(showSourceButton, &QPushButton::clicked, m_renderer, &GradientRenderer::showSource); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) connect(enableOpenGLButton, QOverload::of(&QPushButton::clicked), m_renderer, &ArthurFrame::enableOpenGL); #endif diff --git a/examples/widgets/painting/gradients/gradients.pro b/examples/widgets/painting/gradients/gradients.pro index 73f3974c62..14eccb6500 100644 --- a/examples/widgets/painting/gradients/gradients.pro +++ b/examples/widgets/painting/gradients/gradients.pro @@ -6,10 +6,6 @@ SHARED_FOLDER = ../shared include($$SHARED_FOLDER/shared.pri) RESOURCES += gradients.qrc -qtHaveModule(opengl) { - DEFINES += QT_OPENGL_SUPPORT - QT += opengl -} QT += widgets # install diff --git a/examples/widgets/painting/pathstroke/pathstroke.cpp b/examples/widgets/painting/pathstroke/pathstroke.cpp index 5a7b8fd9fe..b04998afac 100644 --- a/examples/widgets/painting/pathstroke/pathstroke.cpp +++ b/examples/widgets/painting/pathstroke/pathstroke.cpp @@ -211,13 +211,11 @@ void PathStrokeControls::layoutForDesktop() QPushButton *showSourceButton = new QPushButton(mainGroup); showSourceButton->setText(tr("Show Source")); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(mainGroup); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(true); enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); - if (!QGLFormat::hasOpenGL()) - enableOpenGLButton->hide(); #endif QPushButton *whatsThisButton = new QPushButton(mainGroup); whatsThisButton->setText(tr("What's This?")); @@ -242,7 +240,7 @@ void PathStrokeControls::layoutForDesktop() mainGroupLayout->addWidget(animated); mainGroupLayout->addStretch(1); mainGroupLayout->addWidget(showSourceButton); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) mainGroupLayout->addWidget(enableOpenGLButton); #endif mainGroupLayout->addWidget(whatsThisButton); @@ -254,7 +252,7 @@ void PathStrokeControls::layoutForDesktop() connect(penWidth, SIGNAL(valueChanged(int)), m_renderer, SLOT(setPenWidth(int))); connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource())); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); #endif connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool))); @@ -290,13 +288,11 @@ void PathStrokeControls::layoutForSmallScreens() penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); penWidth->setRange(0, 500); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) QPushButton *enableOpenGLButton = new QPushButton(this); enableOpenGLButton->setText(tr("Use OpenGL")); enableOpenGLButton->setCheckable(true); enableOpenGLButton->setChecked(m_renderer->usesOpenGL()); - if (!QGLFormat::hasOpenGL()) - enableOpenGLButton->hide(); #endif // Layouts: @@ -307,7 +303,7 @@ void PathStrokeControls::layoutForSmallScreens() QVBoxLayout *leftLayout = new QVBoxLayout(0); leftLayout->addWidget(m_capGroup); leftLayout->addWidget(m_joinGroup); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) leftLayout->addWidget(enableOpenGLButton); #endif leftLayout->addLayout(penWidthLayout); @@ -330,7 +326,7 @@ void PathStrokeControls::layoutForSmallScreens() mainLayout->addWidget(quitBtn, 2, 1, Qt::AlignHCenter | Qt::AlignTop); mainLayout->addWidget(okBtn, 2, 2, Qt::AlignHCenter | Qt::AlignTop); -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool))); #endif diff --git a/examples/widgets/painting/pathstroke/pathstroke.pro b/examples/widgets/painting/pathstroke/pathstroke.pro index 8ab3cb9244..3e71b2db56 100644 --- a/examples/widgets/painting/pathstroke/pathstroke.pro +++ b/examples/widgets/painting/pathstroke/pathstroke.pro @@ -7,10 +7,6 @@ include($$SHARED_FOLDER/shared.pri) RESOURCES += pathstroke.qrc -qtHaveModule(opengl) { - DEFINES += QT_OPENGL_SUPPORT - QT += opengl -} QT += widgets # install diff --git a/examples/widgets/painting/shared/arthurwidgets.cpp b/examples/widgets/painting/shared/arthurwidgets.cpp index 965660a3a3..442fb69ac1 100644 --- a/examples/widgets/painting/shared/arthurwidgets.cpp +++ b/examples/widgets/painting/shared/arthurwidgets.cpp @@ -60,6 +60,10 @@ #include #include #include +#include +#include +#include +#include extern QPixmap cached(const QString &img); @@ -67,17 +71,12 @@ ArthurFrame::ArthurFrame(QWidget *parent) : QWidget(parent) , m_prefer_image(false) { -#ifdef QT_OPENGL_SUPPORT - glw = 0; +#if QT_CONFIG(opengl) + m_glWindow = nullptr; + m_glWidget = nullptr; m_use_opengl = false; - QGLFormat f = QGLFormat::defaultFormat(); - f.setSampleBuffers(true); - f.setStencil(true); - f.setAlpha(true); - f.setAlphaBufferSize(8); - QGLFormat::setDefaultFormat(f); #endif - m_document = 0; + m_document = nullptr; m_show_doc = false; m_tile = QPixmap(128, 128); @@ -94,37 +93,55 @@ ArthurFrame::ArthurFrame(QWidget *parent) } -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) void ArthurFrame::enableOpenGL(bool use_opengl) { if (m_use_opengl == use_opengl) return; - if (!glw && use_opengl) { - glw = new GLWidget(this); - glw->setAutoFillBackground(false); - glw->disableAutoBufferSwap(); + m_use_opengl = use_opengl; + + if (!m_glWindow && use_opengl) { + createGlWindow(); QApplication::postEvent(this, new QResizeEvent(size(), size())); } - m_use_opengl = use_opengl; if (use_opengl) { - glw->show(); + m_glWidget->show(); } else { - if (glw) - glw->hide(); + if (m_glWidget) + m_glWidget->hide(); } update(); } + +void ArthurFrame::createGlWindow() +{ + Q_ASSERT(m_use_opengl); + + m_glWindow = new QOpenGLWindow(); + QSurfaceFormat f = QSurfaceFormat::defaultFormat(); + f.setSamples(4); + f.setAlphaBufferSize(8); + f.setStencilBufferSize(8); + m_glWindow->setFormat(f); + m_glWindow->setFlags(Qt::WindowTransparentForInput); + m_glWindow->resize(width() - 1, height() - 1); + m_glWindow->create(); + m_glWidget = QWidget::createWindowContainer(m_glWindow, this); +} #endif + void ArthurFrame::paintEvent(QPaintEvent *e) { static QImage *static_image = 0; + QPainter painter; + if (preferImage() -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) && !m_use_opengl #endif ) { @@ -142,10 +159,12 @@ void ArthurFrame::paintEvent(QPaintEvent *e) painter.fillRect(0, height() - o, o, o, bg); painter.fillRect(width() - o, height() - o, o, o, bg); } else { -#ifdef QT_OPENGL_SUPPORT - if (m_use_opengl) { - painter.begin(glw); - painter.fillRect(QRectF(0, 0, glw->width(), glw->height()), palette().color(backgroundRole())); +#if QT_CONFIG(opengl) + if (m_use_opengl && m_glWindow->isValid()) { + m_glWindow->makeCurrent(); + + painter.begin(m_glWindow); + painter.fillRect(QRectF(0, 0, m_glWindow->width(), m_glWindow->height()), palette().color(backgroundRole())); } else { painter.begin(this); } @@ -196,7 +215,7 @@ void ArthurFrame::paintEvent(QPaintEvent *e) painter.drawPath(clipPath); if (preferImage() -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) && !m_use_opengl #endif ) { @@ -204,18 +223,17 @@ void ArthurFrame::paintEvent(QPaintEvent *e) painter.begin(this); painter.drawImage(e->rect(), *static_image, e->rect()); } - -#ifdef QT_OPENGL_SUPPORT - if (m_use_opengl && (inherits("PathDeformRenderer") || inherits("PathStrokeRenderer") || inherits("CompositionRenderer") || m_show_doc)) - glw->swapBuffers(); +#if QT_CONFIG(opengl) + if (m_use_opengl) + m_glWindow->update(); #endif } void ArthurFrame::resizeEvent(QResizeEvent *e) { -#ifdef QT_OPENGL_SUPPORT - if (glw) - glw->setGeometry(0, 0, e->size().width()-1, e->size().height()-1); +#if QT_CONFIG(opengl) + if (m_glWidget) + m_glWidget->setGeometry(0, 0, e->size().width()-1, e->size().height()-1); #endif QWidget::resizeEvent(e); } diff --git a/examples/widgets/painting/shared/arthurwidgets.h b/examples/widgets/painting/shared/arthurwidgets.h index d6e1e44b3a..73e1310c0e 100644 --- a/examples/widgets/painting/shared/arthurwidgets.h +++ b/examples/widgets/painting/shared/arthurwidgets.h @@ -56,42 +56,13 @@ #include #include -#if defined(QT_OPENGL_SUPPORT) -#include -#include -class GLWidget : public QGLWidget -{ -public: - GLWidget(QWidget *parent) - : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) - { - setAttribute(Qt::WA_AcceptTouchEvents); - } - void disableAutoBufferSwap() { setAutoBufferSwap(false); } - void paintEvent(QPaintEvent *) override { parentWidget()->update(); } -protected: - bool event(QEvent *event) override - { - switch (event->type()) { - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - event->ignore(); - return false; - break; - default: - break; - } - return QGLWidget::event(event); - } -}; -#endif - +QT_FORWARD_DECLARE_CLASS(QOpenGLWindow) QT_FORWARD_DECLARE_CLASS(QTextDocument) QT_FORWARD_DECLARE_CLASS(QTextEdit) QT_FORWARD_DECLARE_CLASS(QVBoxLayout) class ArthurFrame : public QWidget + { Q_OBJECT public: @@ -107,9 +78,8 @@ public: void loadSourceFile(const QString &fileName); bool preferImage() const { return m_prefer_image; } - -#if defined(QT_OPENGL_SUPPORT) - QGLWidget *glWidget() const { return glw; } +#if QT_CONFIG(opengl) + QOpenGLWindow *glWindow() const { return m_glWindow; } #endif public slots: @@ -117,7 +87,7 @@ public slots: void setDescriptionEnabled(bool enabled); void showSource(); -#if defined(QT_OPENGL_SUPPORT) +#if QT_CONFIG(opengl) void enableOpenGL(bool use_opengl); bool usesOpenGL() { return m_use_opengl; } #endif @@ -129,8 +99,10 @@ protected: void paintEvent(QPaintEvent *) override; void resizeEvent(QResizeEvent *) override; -#if defined(QT_OPENGL_SUPPORT) - GLWidget *glw; +#if QT_CONFIG(opengl) + virtual void createGlWindow(); + QOpenGLWindow *m_glWindow; + QWidget *m_glWidget; bool m_use_opengl; #endif QPixmap m_tile; diff --git a/examples/widgets/painting/shared/fbopaintdevice.cpp b/examples/widgets/painting/shared/fbopaintdevice.cpp new file mode 100644 index 0000000000..8207090cc8 --- /dev/null +++ b/examples/widgets/painting/shared/fbopaintdevice.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fbopaintdevice.h" + +#include +#include + +QFboPaintDevice::QFboPaintDevice(const QSize& size, bool flipped, bool clearOnInit, + QOpenGLFramebufferObject::Attachment attachment) + : QOpenGLPaintDevice(size) +{ + QOpenGLFramebufferObjectFormat format; + format.setAttachment(attachment); + format.setSamples(4); + m_framebufferObject = new QOpenGLFramebufferObject(size, format); + QOffscreenSurface *surface = new QOffscreenSurface(); + surface->create(); + m_surface = surface; + setPaintFlipped(flipped); + if (clearOnInit) { + m_framebufferObject->bind(); + + context()->functions()->glClearColor(0, 0, 0, 0); + context()->functions()->glClear(GL_COLOR_BUFFER_BIT); + } +} + +QFboPaintDevice::~QFboPaintDevice() +{ + delete m_framebufferObject; + delete m_surface; +} + +void QFboPaintDevice::ensureActiveTarget() +{ + if (QOpenGLContext::currentContext() != context()) + context()->makeCurrent(m_surface); + + m_framebufferObject->bind(); +} + +GLuint QFboPaintDevice::takeTexture() +{ + // We have multisamples so we can't just forward takeTexture(). + QOpenGLFramebufferObject resolvedFbo(m_framebufferObject->size(), m_framebufferObject->attachment()); + QOpenGLFramebufferObject::blitFramebuffer(&resolvedFbo, m_framebufferObject); + return resolvedFbo.takeTexture(); +} + +QImage QFboPaintDevice::toImage() const +{ + QOpenGLContext* currentContext = QOpenGLContext::currentContext(); + QSurface* currentSurface = currentContext ? currentContext->surface() : 0; + + context()->makeCurrent(m_surface); + + QImage image = m_framebufferObject->toImage(!paintFlipped()); + + if (currentContext) + currentContext->makeCurrent(currentSurface); + else + context()->doneCurrent(); + + return image; +} diff --git a/examples/widgets/painting/shared/fbopaintdevice.h b/examples/widgets/painting/shared/fbopaintdevice.h new file mode 100644 index 0000000000..78451af895 --- /dev/null +++ b/examples/widgets/painting/shared/fbopaintdevice.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFBOPAINTDEVICE_H +#define QFBOPAINTDEVICE_H + +#ifndef QT_NO_OPENGL + +#include +#include +#include +#include + +class QFboPaintDevice : public QOpenGLPaintDevice { +public: + QFboPaintDevice(const QSize&, bool flipped = false, bool clearOnInit = true, + QOpenGLFramebufferObject::Attachment = QOpenGLFramebufferObject::CombinedDepthStencil); + ~QFboPaintDevice(); + + // QOpenGLPaintDevice: + void ensureActiveTarget() override; + + bool isValid() const { return m_framebufferObject->isValid(); } + GLuint handle() const { return m_framebufferObject->handle(); } + GLuint takeTexture(); + QImage toImage() const; + + bool bind() { return m_framebufferObject->bind(); } + bool release() { return m_framebufferObject->release(); } + QSize size() const { return m_framebufferObject->size(); } + + QOpenGLFramebufferObject* framebufferObject() { return m_framebufferObject; } + const QOpenGLFramebufferObject* framebufferObject() const { return m_framebufferObject; } + + static bool isSupported() { return QOpenGLFramebufferObject::hasOpenGLFramebufferObjects(); } + +private: + QOpenGLFramebufferObject *m_framebufferObject; + QSurface* m_surface; +}; + +#endif // QT_NO_OPENGL + +#endif // QFBOPAINTDEVICE_H diff --git a/examples/widgets/painting/shared/hoverpoints.cpp b/examples/widgets/painting/shared/hoverpoints.cpp index c735c83f6a..7cd8cc0b29 100644 --- a/examples/widgets/painting/shared/hoverpoints.cpp +++ b/examples/widgets/painting/shared/hoverpoints.cpp @@ -48,10 +48,6 @@ ** ****************************************************************************/ -#ifdef QT_OPENGL_SUPPORT -#include -#endif - #include "arthurwidgets.h" #include "hoverpoints.h" @@ -269,11 +265,6 @@ bool HoverPoints::eventFilter(QObject *object, QEvent *event) QApplication::sendEvent(object, event); m_widget = that_widget; paintPoints(); -#ifdef QT_OPENGL_SUPPORT - ArthurFrame *af = qobject_cast(that_widget); - if (af && af->usesOpenGL()) - af->glWidget()->swapBuffers(); -#endif return true; } default: @@ -288,12 +279,14 @@ bool HoverPoints::eventFilter(QObject *object, QEvent *event) void HoverPoints::paintPoints() { QPainter p; -#ifdef QT_OPENGL_SUPPORT +#if QT_CONFIG(opengl) ArthurFrame *af = qobject_cast(m_widget); - if (af && af->usesOpenGL()) - p.begin(af->glWidget()); - else + if (af && af->usesOpenGL() && af->glWindow()->isValid()) { + af->glWindow()->makeCurrent(); + p.begin(af->glWindow()); + } else { p.begin(m_widget); + } #else p.begin(m_widget); #endif diff --git a/examples/widgets/painting/shared/shared.pri b/examples/widgets/painting/shared/shared.pri index 362cc6819c..cb08b00348 100644 --- a/examples/widgets/painting/shared/shared.pri +++ b/examples/widgets/painting/shared/shared.pri @@ -1,8 +1,8 @@ INCLUDEPATH += $$PWD -qtHaveModule(opengl)|qtConfig(opengles2) { - DEFINES += QT_OPENGL_SUPPORT - QT += opengl widgets +qtConfig(opengl) { + SOURCES += $$PWD/fbopaintdevice.cpp + HEADERS += $$PWD/fbopaintdevice.h } SOURCES += \ -- cgit v1.2.3