Fix hellowindow example

It seems this example never worked as expected.
It has a 'multiple' option which should show extra
windows with rendering taking place in different
thread, however although render is moved to other thread
render() function was never called in that thread.

Fix following things:
 * make rendering in other thread
 * stop requestUpdate if nothing is exposed
 * add timer so animation works at the same speed despite
   of number of windows (renderer B renders two windows)
 * wait for render to finish before triggering requestUdpate
 * remove mutex where not needed

Pick-to: 5.15
Change-Id: I420436bd28d0357534332dd55b088d634d906c14
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Michal Klocek 2020-05-20 11:05:17 +02:00
parent 71d63049f7
commit 5786ac12f0
2 changed files with 30 additions and 59 deletions

View File

@ -54,11 +54,11 @@
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QRandomGenerator> #include <QRandomGenerator>
#include <qmath.h> #include <qmath.h>
#include <QElapsedTimer>
Renderer::Renderer(const QSurfaceFormat &format, Renderer *share, QScreen *screen) Renderer::Renderer(const QSurfaceFormat &format, Renderer *share, QScreen *screen)
: m_initialized(false) : m_initialized(false)
, m_format(format) , m_format(format)
, m_currentWindow(0)
{ {
m_context = new QOpenGLContext(this); m_context = new QOpenGLContext(this);
if (screen) if (screen)
@ -89,24 +89,33 @@ HelloWindow::HelloWindow(const QSharedPointer<Renderer> &renderer, QScreen *scre
create(); create();
updateColor(); updateColor();
connect(renderer.data(), &Renderer::requestUpdate, this, &QWindow::requestUpdate);
} }
void HelloWindow::exposeEvent(QExposeEvent *) void HelloWindow::exposeEvent(QExposeEvent *)
{ {
m_renderer->setAnimating(this, isExposed());
if (isExposed()) if (isExposed())
m_renderer->render(); render();
} }
bool HelloWindow::event(QEvent *ev) bool HelloWindow::event(QEvent *ev)
{ {
if (ev->type() == QEvent::UpdateRequest) { if (ev->type() == QEvent::UpdateRequest && isExposed())
m_renderer->render(); render();
requestUpdate();
}
return QWindow::event(ev); return QWindow::event(ev);
} }
void HelloWindow::render()
{
static QElapsedTimer timer;
if (!timer.isValid())
timer.start();
qreal a = (qreal)(((timer.elapsed() * 3) % 36000) / 100.0);
auto call = [this, r = m_renderer.data(), a, c = color()]() { r->render(this, a, c); };
QMetaObject::invokeMethod(m_renderer.data(), call);
}
void HelloWindow::mousePressEvent(QMouseEvent *) void HelloWindow::mousePressEvent(QMouseEvent *)
{ {
updateColor(); updateColor();
@ -114,14 +123,11 @@ void HelloWindow::mousePressEvent(QMouseEvent *)
QColor HelloWindow::color() const QColor HelloWindow::color() const
{ {
QMutexLocker locker(&m_colorLock);
return m_color; return m_color;
} }
void HelloWindow::updateColor() void HelloWindow::updateColor()
{ {
QMutexLocker locker(&m_colorLock);
QColor colors[] = QColor colors[] =
{ {
QColor(100, 255, 0), QColor(100, 255, 0),
@ -132,41 +138,13 @@ void HelloWindow::updateColor()
m_colorIndex = 1 - m_colorIndex; m_colorIndex = 1 - m_colorIndex;
} }
void Renderer::setAnimating(HelloWindow *window, bool animating) void Renderer::render(HelloWindow *surface, qreal angle, const QColor &color)
{ {
QMutexLocker locker(&m_windowLock);
if (m_windows.contains(window) == animating)
return;
if (animating) {
m_windows << window;
if (m_windows.size() == 1)
window->requestUpdate();
} else {
m_currentWindow = 0;
m_windows.removeOne(window);
}
}
void Renderer::render()
{
QMutexLocker locker(&m_windowLock);
if (m_windows.isEmpty())
return;
HelloWindow *surface = m_windows.at(m_currentWindow);
QColor color = surface->color();
m_currentWindow = (m_currentWindow + 1) % m_windows.size();
if (!m_context->makeCurrent(surface)) if (!m_context->makeCurrent(surface))
return; return;
QSize viewSize = surface->size(); QSize viewSize = surface->size();
locker.unlock();
if (!m_initialized) { if (!m_initialized) {
initialize(); initialize();
m_initialized = true; m_initialized = true;
@ -192,9 +170,9 @@ void Renderer::render()
m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3); m_program->setAttributeBuffer(normalAttr, GL_FLOAT, verticesSize, 3);
QMatrix4x4 modelview; QMatrix4x4 modelview;
modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f); modelview.rotate(angle, 0.0f, 1.0f, 0.0f);
modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f); modelview.rotate(angle, 1.0f, 0.0f, 0.0f);
modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f); modelview.rotate(angle, 0.0f, 0.0f, 1.0f);
modelview.translate(0.0f, -0.2f, 0.0f); modelview.translate(0.0f, -0.2f, 0.0f);
m_program->setUniformValue(matrixUniform, modelview); m_program->setUniformValue(matrixUniform, modelview);
@ -204,7 +182,7 @@ void Renderer::render()
m_context->swapBuffers(surface); m_context->swapBuffers(surface);
m_fAngle += 1.0f; emit requestUpdate();
} }
Q_GLOBAL_STATIC(QMutex, initMutex) Q_GLOBAL_STATIC(QMutex, initMutex)
@ -250,7 +228,6 @@ void Renderer::initialize()
matrixUniform = m_program->uniformLocation("matrix"); matrixUniform = m_program->uniformLocation("matrix");
colorUniform = m_program->uniformLocation("sourceColor"); colorUniform = m_program->uniformLocation("sourceColor");
m_fAngle = 0;
createGeometry(); createGeometry();
m_vbo.create(); m_vbo.create();

View File

@ -52,7 +52,7 @@
#include <QColor> #include <QColor>
#include <QMutex> #include <QMutex>
#include <QtOpenGL/QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLBuffer> #include <QOpenGLBuffer>
#include <QSharedPointer> #include <QSharedPointer>
#include <QTimer> #include <QTimer>
@ -64,14 +64,16 @@ class Renderer : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit Renderer(const QSurfaceFormat &format, Renderer *share = 0, QScreen *screen = 0); explicit Renderer(const QSurfaceFormat &format, Renderer *share = nullptr,
QScreen *screen = nullptr);
QSurfaceFormat format() const { return m_format; } QSurfaceFormat format() const { return m_format; }
void setAnimating(HelloWindow *window, bool animating);
public slots: public slots:
void render(); void render(HelloWindow *surface, qreal angle, const QColor &color);
signals:
void requestUpdate();
private: private:
void initialize(); void initialize();
@ -81,8 +83,6 @@ private:
void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4); void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4);
void extrude(qreal x1, qreal y1, qreal x2, qreal y2); void extrude(qreal x1, qreal y1, qreal x2, qreal y2);
qreal m_fAngle;
QVector<QVector3D> vertices; QVector<QVector3D> vertices;
QVector<QVector3D> normals; QVector<QVector3D> normals;
int vertexAttr; int vertexAttr;
@ -95,19 +95,13 @@ private:
QOpenGLContext *m_context; QOpenGLContext *m_context;
QOpenGLShaderProgram *m_program; QOpenGLShaderProgram *m_program;
QOpenGLBuffer m_vbo; QOpenGLBuffer m_vbo;
QList<HelloWindow *> m_windows;
int m_currentWindow;
QMutex m_windowLock;
QColor m_backgroundColor; QColor m_backgroundColor;
}; };
class HelloWindow : public QWindow class HelloWindow : public QWindow
{ {
public: public:
explicit HelloWindow(const QSharedPointer<Renderer> &renderer, QScreen *screen = 0); explicit HelloWindow(const QSharedPointer<Renderer> &renderer, QScreen *screen = nullptr);
QColor color() const; QColor color() const;
void updateColor(); void updateColor();
@ -116,10 +110,10 @@ protected:
bool event(QEvent *ev) override; bool event(QEvent *ev) override;
void exposeEvent(QExposeEvent *event) override; void exposeEvent(QExposeEvent *event) override;
void mousePressEvent(QMouseEvent *) override; void mousePressEvent(QMouseEvent *) override;
void render();
private: private:
int m_colorIndex; int m_colorIndex;
QColor m_color; QColor m_color;
const QSharedPointer<Renderer> m_renderer; const QSharedPointer<Renderer> m_renderer;
mutable QMutex m_colorLock;
}; };