diff options
author | Gunnar Sletta <gunnar.sletta@digia.com> | 2013-11-27 17:04:06 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-12-03 18:06:36 +0100 |
commit | 9ad9615d0003c9fb84255152f0cbb473ee2a7a70 (patch) | |
tree | c4aba681ddacd7eadb4defe7312e9020b43407c2 /src/quick/items/context2d/qquickcontext2dtexture_p.h | |
parent | 9e77d6c31b406e5941a2d287f3c8842954815db4 (diff) |
Improve the Canvas threading model
The canvas classes were mixing scene graph resources and GL
content across threads. This led to a number of potential crashes
in addition to that the FBO based rendering had significant
potential for stalling.
QQuickContext2DTexture is no longer a QSGTexture with ambiguous
ownership. Instead we use textureForNextFrame which is called
on the render thread while the GUI is locked to synchronize
state from the Context2D's "texture" into the actual QSGTexture.
This means that cleanup of the QQuickContext2DTexture and
the QSGTexture used for display is no longer in conflict.
QQuickPixmap no longer contains a QSGTexture either as these
are strictly for use on the scene graph thread. The Images are
anyway loaded explicitly as QImage files in QQuickContext2DContext
and uploaded again for every Canvas, so relying on the GL paint
engine to do the caching will give us the same with less code.
I also changed the default strategy to Immediate as that one
supports the full API (cooperative does not support readback)
and because cooperative is pretty bad for performance since the
rendering happens in the sync() step.
Task-number: QTBUG-34268
Task-number: QTBUG-31052
Task-number: QTBUG-21935
Task-number: QTBUG-30689
Task-number: QTBUG-29007
Change-Id: Ic540b22d5faa1188e21e56a3beee24191d13f423
Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src/quick/items/context2d/qquickcontext2dtexture_p.h')
-rw-r--r-- | src/quick/items/context2d/qquickcontext2dtexture_p.h | 70 |
1 files changed, 53 insertions, 17 deletions
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h index 2a5b7a318a..cf0e8e3fa9 100644 --- a/src/quick/items/context2d/qquickcontext2dtexture_p.h +++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h @@ -58,16 +58,44 @@ QT_BEGIN_NAMESPACE class QQuickContext2DTile; class QQuickContext2DCommandBuffer; -class QQuickContext2DTexture : public QSGDynamicTexture +class QQuickContext2DTexture : public QObject { Q_OBJECT public: + class PaintEvent : public QEvent { + public: + PaintEvent(QQuickContext2DCommandBuffer *b) : QEvent(QEvent::Type(QEvent::User + 1)), buffer(b) {} + QQuickContext2DCommandBuffer *buffer; + }; + + class CanvasChangeEvent : public QEvent { + public: + CanvasChangeEvent(const QSize &cSize, + const QSize &tSize, + const QRect &cWindow, + const QRect &dRect, + bool sm, + bool aa) + : QEvent(QEvent::Type(QEvent::User + 2)) + , canvasSize(cSize) + , tileSize(tSize) + , canvasWindow(cWindow) + , dirtyRect(dRect) + , smooth(sm) + , antialiasing(aa) + { + } + QSize canvasSize; + QSize tileSize; + QRect canvasWindow; + QRect dirtyRect; + bool smooth; + bool antialiasing; + }; + QQuickContext2DTexture(); ~QQuickContext2DTexture(); - virtual bool hasAlphaChannel() const {return true;} - virtual bool hasMipmaps() const {return false;} - virtual QSize textureSize() const; virtual QQuickCanvasItem::RenderTarget renderTarget() const = 0; static QRect tiledRect(const QRectF& window, const QSize& tileSize); @@ -78,15 +106,20 @@ public: void setAntialiasing(bool antialiasing); bool setDirtyRect(const QRect &dirtyRect); bool canvasDestroyed(); + void setOnCustomThread(bool is) { m_onCustomThread = is; } + + // Called during sync() on the scene graph thread while GUI is blocked. + virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame) = 0; + bool event(QEvent *e); Q_SIGNALS: void textureChanged(); public Q_SLOTS: - void markDirtyTexture(); - void setItem(QQuickCanvasItem* item); void canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing); void paint(QQuickContext2DCommandBuffer *ccb); + void markDirtyTexture(); + void setItem(QQuickCanvasItem* item); virtual void grabImage(const QRectF& region = QRectF()) = 0; protected: @@ -110,13 +143,16 @@ protected: QSize m_tileSize; QRect m_canvasWindow; - uint m_dirtyCanvas : 1; + QMutex m_mutex; + QWaitCondition m_condition; + uint m_canvasWindowChanged : 1; uint m_dirtyTexture : 1; uint m_smooth : 1; uint m_antialiasing : 1; uint m_tiledCanvas : 1; uint m_painting : 1; + uint m_onCustomThread : 1; // Not GUI and not SGRender }; class QQuickContext2DFBOTexture : public QQuickContext2DTexture @@ -126,17 +162,16 @@ class QQuickContext2DFBOTexture : public QQuickContext2DTexture public: QQuickContext2DFBOTexture(); ~QQuickContext2DFBOTexture(); - virtual int textureId() const; - virtual bool updateTexture(); virtual QQuickContext2DTile* createTile() const; virtual QPaintDevice* beginPainting(); virtual void endPainting(); QRectF normalizedTextureSubRect() const; virtual QQuickCanvasItem::RenderTarget renderTarget() const; virtual void compositeTile(QQuickContext2DTile* tile); - virtual void bind(); QSize adjustedTileSize(const QSize &ts); + QSGTexture *textureForNextFrame(QSGTexture *); + public Q_SLOTS: virtual void grabImage(const QRectF& region = QRectF()); @@ -144,10 +179,12 @@ private: bool doMultisampling() const; QOpenGLFramebufferObject *m_fbo; QOpenGLFramebufferObject *m_multisampledFbo; - QMutex m_mutex; - QWaitCondition m_condition; QSize m_fboSize; QPaintDevice *m_paint_device; + + + GLuint m_displayTextures[2]; + int m_displayTexture; }; class QSGPlainTexture; @@ -158,24 +195,23 @@ class QQuickContext2DImageTexture : public QQuickContext2DTexture public: QQuickContext2DImageTexture(); ~QQuickContext2DImageTexture(); - virtual int textureId() const; - virtual void bind(); virtual QQuickCanvasItem::RenderTarget renderTarget() const; - virtual bool updateTexture(); virtual QQuickContext2DTile* createTile() const; virtual QPaintDevice* beginPainting(); + virtual void endPainting(); virtual void compositeTile(QQuickContext2DTile* tile); + virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame); + public Q_SLOTS: virtual void grabImage(const QRectF& region = QRectF()); private: - QSGPlainTexture *imageTexture() const; QImage m_image; + QImage m_displayImage; QPainter m_painter; - QSGPlainTexture* m_texture; }; QT_END_NAMESPACE |