diff options
author | Andy Nichols <andy.nichols@digia.com> | 2014-09-01 16:49:58 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2014-09-02 13:45:44 +0300 |
commit | ba0d8e93d8525bb459e9b6cb384f2fe0701d5a02 (patch) | |
tree | 8239423e74a36f24e00c9624d289c143b6824489 /softwarecontext | |
parent | f013631527b3cc569527e9541c11b0f12c420473 (diff) |
Reformat project to be a Qt Module
Change-Id: I2fe8df530a687247a9cd7ea12c1d8de79fef506e
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'softwarecontext')
26 files changed, 0 insertions, 3986 deletions
diff --git a/softwarecontext/context.cpp b/softwarecontext/context.cpp deleted file mode 100644 index 33dc7e87e4..0000000000 --- a/softwarecontext/context.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "context.h" - -#include "rectanglenode.h" -#include "imagenode.h" -#include "painternode.h" -#include "pixmaptexture.h" -#include "glyphnode.h" -#include "ninepatchnode.h" -#include "renderingvisitor.h" -#include "softwarelayer.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QElapsedTimer> - -#include <QtGui/QWindow> - -#include <QtQuick/QSGFlatColorMaterial> -#include <QtQuick/QSGVertexColorMaterial> -#include <QtQuick/QSGOpaqueTextureMaterial> -#include <QtQuick/QSGTextureMaterial> -#include <private/qsgdefaultimagenode_p.h> -#include <private/qsgdefaultrectanglenode_p.h> -#include <private/qsgdistancefieldglyphnode_p_p.h> -#include <private/qsgdefaultglyphnode_p.h> - -#ifndef QSG_NO_RENDERER_TIMING -static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty(); -#endif - -namespace SoftwareContext -{ - -Renderer::Renderer(QSGRenderContext *context) - : QSGRenderer(context) -{ -} - -void Renderer::renderScene(GLuint fboId) -{ - class B : public QSGBindable - { - public: - void bind() const { } - } bindable; - QSGRenderer::renderScene(bindable); -} - -void Renderer::render() -{ - QWindow *currentWindow = static_cast<RenderContext*>(m_context)->currentWindow; - if (!m_backingStore) - m_backingStore.reset(new QBackingStore(currentWindow)); - - if (m_backingStore->size() != currentWindow->size()) - m_backingStore->resize(currentWindow->size()); - - const QRect rect(0, 0, currentWindow->width(), currentWindow->height()); - m_backingStore->beginPaint(rect); - - QPaintDevice *device = m_backingStore->paintDevice(); - QPainter painter(device); - painter.setRenderHint(QPainter::Antialiasing); - - painter.fillRect(rect, clearColor()); - RenderingVisitor(&painter).visitChildren(rootNode()); - - m_backingStore->endPaint(); - m_backingStore->flush(rect); -} - -void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) -{ - - QSGRenderer::nodeChanged(node, state); -} - -PixmapRenderer::PixmapRenderer(QSGRenderContext *context) - : QSGRenderer(context) -{ - -} - -void PixmapRenderer::renderScene(GLuint) -{ - Q_UNREACHABLE(); -} - -void PixmapRenderer::render() -{ - Q_UNREACHABLE(); -} - -void PixmapRenderer::render(QPixmap *target) -{ - const QRect rect(0, 0, target->width(), target->height()); - target->fill(clearColor()); - QPainter painter(target); - painter.setRenderHint(QPainter::Antialiasing); - - RenderingVisitor(&painter).visitChildren(rootNode()); -} - -RenderContext::RenderContext(QSGContext *ctx) - : QSGRenderContext(ctx) - , currentWindow(0) - , m_initialized(false) -{ -} -Context::Context(QObject *parent) - : QSGContext(parent) -{ - setDistanceFieldEnabled(false); -} - -QSGRectangleNode *Context::createRectangleNode() -{ - return new RectangleNode(); -} - -QSGImageNode *Context::createImageNode() -{ - return new ImageNode(); -} - -QSGPainterNode *Context::createPainterNode(QQuickPaintedItem *item) -{ - return new PainterNode(item); -} - -QSGGlyphNode *Context::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) -{ - Q_UNUSED(rc); - Q_UNUSED(preferNativeGlyphNode); - return new GlyphNode(); -} - -QSGNinePatchNode *Context::createNinePatchNode() -{ - return new NinePatchNode(); -} - -QSGLayer *Context::createLayer(QSGRenderContext *renderContext) -{ - return new SoftwareLayer(renderContext); -} - -QSurfaceFormat Context::defaultSurfaceFormat() const -{ - QSurfaceFormat format = QSurfaceFormat::defaultFormat(); - format.setRenderableType(QSurfaceFormat::DefaultRenderableType); - format.setMajorVersion(0); - format.setMinorVersion(0); - return format; -} - -void RenderContext::initialize(QOpenGLContext *context) -{ - Q_UNUSED(context) - Q_UNREACHABLE(); -} - -void RenderContext::initializeIfNeeded() -{ - if (m_initialized) - return; - m_initialized = true; - emit initialized(); -} - -void RenderContext::invalidate() -{ - QSGRenderContext::invalidate(); -} - -QSGTexture *RenderContext::createTexture(const QImage &image) const -{ - return new PixmapTexture(image); -} - -QSGTexture *RenderContext::createTextureNoAtlas(const QImage &image) const -{ - return new PixmapTexture(image); -} - -QSGRenderer *RenderContext::createRenderer() -{ - return new Renderer(this); -} - - -void RenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fbo) -{ - QSGRenderContext::renderNextFrame(renderer, fbo); -} - -} // namespace diff --git a/softwarecontext/context.h b/softwarecontext/context.h deleted file mode 100644 index 88fe4e447f..0000000000 --- a/softwarecontext/context.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef CONTEXT_H -#define CONTEXT_H - -#include <private/qsgcontext_p.h> -#include <private/qsgrenderer_p.h> -#include <private/qsgadaptationlayer_p.h> -#include <QtCore/QElapsedTimer> -#include <QtGui/QOpenGLShaderProgram> -#include <QtGui/QBackingStore> - -namespace SoftwareContext -{ - -class Renderer : public QSGRenderer -{ -public: - Renderer(QSGRenderContext *context); - - virtual void renderScene(GLuint fboId = 0); - - virtual void render(); - - void nodeChanged(QSGNode *node, QSGNode::DirtyState state); - - QBackingStore *backingStore() const { return m_backingStore.data(); } - -private: - QScopedPointer<QBackingStore> m_backingStore; - QRect m_dirtyRect; -}; - -class PixmapRenderer : public QSGRenderer -{ -public: - PixmapRenderer(QSGRenderContext *context); - - virtual void renderScene(GLuint fboId = 0); - - virtual void render(); - - void render(QPixmap *target); -}; - -class RenderContext : public QSGRenderContext -{ -public: - RenderContext(QSGContext *ctx); - void initialize(QOpenGLContext *context); - void initializeIfNeeded(); - void invalidate(); - void renderNextFrame(QSGRenderer *renderer, GLuint fbo); - QSGTexture *createTexture(const QImage &image) const; - QSGTexture *createTextureNoAtlas(const QImage &image) const; - QSGRenderer *createRenderer(); - - QWindow *currentWindow; - bool m_initialized; -}; - -class Context : public QSGContext -{ - Q_OBJECT -public: - explicit Context(QObject *parent = 0); - - QSGRenderContext *createRenderContext() { return new RenderContext(this); } - - virtual QSGRectangleNode *createRectangleNode(); - virtual QSGImageNode *createImageNode(); - virtual QSGPainterNode *createPainterNode(QQuickPaintedItem *item); - virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode); - virtual QSGNinePatchNode *createNinePatchNode(); - virtual QSGLayer *createLayer(QSGRenderContext *renderContext); - virtual QSurfaceFormat defaultSurfaceFormat() const; -}; - -} // namespace - -#endif // CONTEXT_H diff --git a/softwarecontext/glyphnode.cpp b/softwarecontext/glyphnode.cpp deleted file mode 100644 index eae8b626cb..0000000000 --- a/softwarecontext/glyphnode.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "glyphnode.h" - -GlyphNode::GlyphNode() - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0) - , m_style(QQuickText::Normal) -{ - setMaterial((QSGMaterial*)1); - setGeometry(&m_geometry); -} - - -void GlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs) -{ - m_position = position; - m_glyphRun = glyphs; -} - -void GlyphNode::setColor(const QColor &color) -{ - m_color = color; -} - -void GlyphNode::setStyle(QQuickText::TextStyle style) -{ - m_style = style; -} - -void GlyphNode::setStyleColor(const QColor &color) -{ - m_styleColor = color; -} - -QPointF GlyphNode::baseLine() const -{ - return QPointF(); -} - -void GlyphNode::setPreferredAntialiasingMode(QSGGlyphNode::AntialiasingMode) -{ -} - -void GlyphNode::update() -{ -} - -void GlyphNode::paint(QPainter *painter) -{ - painter->setBrush(QBrush()); - QPointF pos = m_position - QPointF(0, m_glyphRun.rawFont().ascent()); - - switch (m_style) { - case QQuickText::Normal: break; - case QQuickText::Outline: - painter->setPen(m_styleColor); - painter->drawGlyphRun(pos + QPointF(0, 1), m_glyphRun); - painter->drawGlyphRun(pos + QPointF(0, -1), m_glyphRun); - painter->drawGlyphRun(pos + QPointF(1, 0), m_glyphRun); - painter->drawGlyphRun(pos + QPointF(-1, 0), m_glyphRun); - break; - case QQuickText::Raised: - painter->setPen(m_styleColor); - painter->drawGlyphRun(pos + QPointF(0, 1), m_glyphRun); - break; - case QQuickText::Sunken: - painter->setPen(m_styleColor); - painter->drawGlyphRun(pos + QPointF(0, -1), m_glyphRun); - break; - } - - painter->setPen(m_color); - painter->drawGlyphRun(pos, m_glyphRun); -} diff --git a/softwarecontext/glyphnode.h b/softwarecontext/glyphnode.h deleted file mode 100644 index d34013be5b..0000000000 --- a/softwarecontext/glyphnode.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef GLYPHNODE_H -#define GLYPHNODE_H - -#include <private/qsgadaptationlayer_p.h> - -class GlyphNode : public QSGGlyphNode -{ -public: - GlyphNode(); - - virtual void setGlyphs(const QPointF &position, const QGlyphRun &glyphs); - virtual void setColor(const QColor &color); - virtual void setStyle(QQuickText::TextStyle style); - virtual void setStyleColor(const QColor &color); - virtual QPointF baseLine() const; - virtual void setPreferredAntialiasingMode(AntialiasingMode); - virtual void update(); - - void paint(QPainter *painter); - -private: - QPointF m_position; - QGlyphRun m_glyphRun; - QColor m_color; - QSGGeometry m_geometry; - QQuickText::TextStyle m_style; - QColor m_styleColor; -}; - -#endif // GLYPHNODE_H diff --git a/softwarecontext/imagenode.cpp b/softwarecontext/imagenode.cpp deleted file mode 100644 index 7718831b65..0000000000 --- a/softwarecontext/imagenode.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "imagenode.h" - -#include "pixmaptexture.h" -#include "softwarelayer.h" -#include <QPainter> -#include <qmath.h> - -// Helper from widgets/styles/qdrawutil.cpp - -namespace SoftwareContext { - -void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, - const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, - const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints) -{ - QPainter::PixmapFragment d; - d.opacity = 1.0; - d.rotation = 0.0; - - QPixmapFragmentsArray opaqueData; - QPixmapFragmentsArray translucentData; - - // source center - const int sourceCenterTop = sourceRect.top() + sourceMargins.top(); - const int sourceCenterLeft = sourceRect.left() + sourceMargins.left(); - const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom() + 1; - const int sourceCenterRight = sourceRect.right() - sourceMargins.right() + 1; - const int sourceCenterWidth = sourceCenterRight - sourceCenterLeft; - const int sourceCenterHeight = sourceCenterBottom - sourceCenterTop; - // target center - const int targetCenterTop = targetRect.top() + targetMargins.top(); - const int targetCenterLeft = targetRect.left() + targetMargins.left(); - const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom() + 1; - const int targetCenterRight = targetRect.right() - targetMargins.right() + 1; - const int targetCenterWidth = targetCenterRight - targetCenterLeft; - const int targetCenterHeight = targetCenterBottom - targetCenterTop; - - QVarLengthArray<qreal, 16> xTarget; // x-coordinates of target rectangles - QVarLengthArray<qreal, 16> yTarget; // y-coordinates of target rectangles - - int columns = 3; - int rows = 3; - if (rules.horizontal != Qt::StretchTile && sourceCenterWidth != 0) - columns = qMax(3, 2 + qCeil(targetCenterWidth / qreal(sourceCenterWidth))); - if (rules.vertical != Qt::StretchTile && sourceCenterHeight != 0) - rows = qMax(3, 2 + qCeil(targetCenterHeight / qreal(sourceCenterHeight))); - - xTarget.resize(columns + 1); - yTarget.resize(rows + 1); - - bool oldAA = painter->testRenderHint(QPainter::Antialiasing); - if (painter->paintEngine()->type() != QPaintEngine::OpenGL - && painter->paintEngine()->type() != QPaintEngine::OpenGL2 - && oldAA && painter->combinedTransform().type() != QTransform::TxNone) { - painter->setRenderHint(QPainter::Antialiasing, false); - } - - xTarget[0] = targetRect.left(); - xTarget[1] = targetCenterLeft; - xTarget[columns - 1] = targetCenterRight; - xTarget[columns] = targetRect.left() + targetRect.width(); - - yTarget[0] = targetRect.top(); - yTarget[1] = targetCenterTop; - yTarget[rows - 1] = targetCenterBottom; - yTarget[rows] = targetRect.top() + targetRect.height(); - - qreal dx = targetCenterWidth; - qreal dy = targetCenterHeight; - - switch (rules.horizontal) { - case Qt::StretchTile: - dx = targetCenterWidth; - break; - case Qt::RepeatTile: - dx = sourceCenterWidth; - break; - case Qt::RoundTile: - dx = targetCenterWidth / qreal(columns - 2); - break; - } - - for (int i = 2; i < columns - 1; ++i) - xTarget[i] = xTarget[i - 1] + dx; - - switch (rules.vertical) { - case Qt::StretchTile: - dy = targetCenterHeight; - break; - case Qt::RepeatTile: - dy = sourceCenterHeight; - break; - case Qt::RoundTile: - dy = targetCenterHeight / qreal(rows - 2); - break; - } - - for (int i = 2; i < rows - 1; ++i) - yTarget[i] = yTarget[i - 1] + dy; - - // corners - if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left - d.x = (0.5 * (xTarget[1] + xTarget[0])); - d.y = (0.5 * (yTarget[1] + yTarget[0])); - d.sourceLeft = sourceRect.left(); - d.sourceTop = sourceRect.top(); - d.width = sourceMargins.left(); - d.height = sourceMargins.top(); - d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; - d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueTopLeft) - opaqueData.append(d); - else - translucentData.append(d); - } - if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right - d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); - d.y = (0.5 * (yTarget[1] + yTarget[0])); - d.sourceLeft = sourceCenterRight; - d.sourceTop = sourceRect.top(); - d.width = sourceMargins.right(); - d.height = sourceMargins.top(); - d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; - d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueTopRight) - opaqueData.append(d); - else - translucentData.append(d); - } - if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left - d.x = (0.5 * (xTarget[1] + xTarget[0])); - d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1])); - d.sourceLeft = sourceRect.left(); - d.sourceTop = sourceCenterBottom; - d.width = sourceMargins.left(); - d.height = sourceMargins.bottom(); - d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; - d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueBottomLeft) - opaqueData.append(d); - else - translucentData.append(d); - } - if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right - d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); - d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); - d.sourceLeft = sourceCenterRight; - d.sourceTop = sourceCenterBottom; - d.width = sourceMargins.right(); - d.height = sourceMargins.bottom(); - d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; - d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; - if (hints & QDrawBorderPixmap::OpaqueBottomRight) - opaqueData.append(d); - else - translucentData.append(d); - } - - // horizontal edges - if (targetCenterWidth > 0 && sourceCenterWidth > 0) { - if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData; - d.sourceLeft = sourceCenterLeft; - d.sourceTop = sourceRect.top(); - d.width = sourceCenterWidth; - d.height = sourceMargins.top(); - d.y = (0.5 * (yTarget[1] + yTarget[0])); - d.scaleX = dx / d.width; - d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height; - for (int i = 1; i < columns - 1; ++i) { - d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); - data.append(d); - } - if (rules.horizontal == Qt::RepeatTile) - data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); - } - if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData; - d.sourceLeft = sourceCenterLeft; - d.sourceTop = sourceCenterBottom; - d.width = sourceCenterWidth; - d.height = sourceMargins.bottom(); - d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1])); - d.scaleX = dx / d.width; - d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height; - for (int i = 1; i < columns - 1; ++i) { - d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); - data.append(d); - } - if (rules.horizontal == Qt::RepeatTile) - data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX); - } - } - - // vertical edges - if (targetCenterHeight > 0 && sourceCenterHeight > 0) { - if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData; - d.sourceLeft = sourceRect.left(); - d.sourceTop = sourceCenterTop; - d.width = sourceMargins.left(); - d.height = sourceCenterHeight; - d.x = (0.5 * (xTarget[1] + xTarget[0])); - d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width; - d.scaleY = dy / d.height; - for (int i = 1; i < rows - 1; ++i) { - d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); - data.append(d); - } - if (rules.vertical == Qt::RepeatTile) - data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); - } - if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData; - d.sourceLeft = sourceCenterRight; - d.sourceTop = sourceCenterTop; - d.width = sourceMargins.right(); - d.height = sourceCenterHeight; - d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1])); - d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width; - d.scaleY = dy / d.height; - for (int i = 1; i < rows - 1; ++i) { - d.y = (0.5 * (yTarget[i + 1] + yTarget[i])); - data.append(d); - } - if (rules.vertical == Qt::RepeatTile) - data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY); - } - } - - // center - if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) { - QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData; - d.sourceLeft = sourceCenterLeft; - d.sourceTop = sourceCenterTop; - d.width = sourceCenterWidth; - d.height = sourceCenterHeight; - d.scaleX = dx / d.width; - d.scaleY = dy / d.height; - - qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX; - qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY; - - for (int j = 1; j < rows - 1; ++j) { - d.y = (0.5 * (yTarget[j + 1] + yTarget[j])); - for (int i = 1; i < columns - 1; ++i) { - d.x = (0.5 * (xTarget[i + 1] + xTarget[i])); - data.append(d); - } - if (rules.horizontal == Qt::RepeatTile) - data[data.size() - 1].width = repeatWidth; - } - if (rules.vertical == Qt::RepeatTile) { - for (int i = 1; i < columns - 1; ++i) - data[data.size() - i].height = repeatHeight; - } - } - - if (opaqueData.size()) - painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint); - if (translucentData.size()) - painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap); - - if (oldAA) - painter->setRenderHint(QPainter::Antialiasing, true); -} - -} - -ImageNode::ImageNode() - : m_innerSourceRect(0, 0, 1, 1) - , m_subSourceRect(0, 0, 1, 1) - , m_texture(0) - , m_mirror(false) - , m_smooth(true) - , m_tileHorizontal(false) - , m_tileVertical(false) -{ - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - - -void ImageNode::setTargetRect(const QRectF &rect) -{ - m_targetRect = rect; -} - -void ImageNode::setInnerTargetRect(const QRectF &rect) -{ - m_innerTargetRect = rect; -} - -void ImageNode::setInnerSourceRect(const QRectF &rect) -{ - m_innerSourceRect = rect; -} - -void ImageNode::setSubSourceRect(const QRectF &rect) -{ - m_subSourceRect = rect; -} - -void ImageNode::setTexture(QSGTexture *texture) -{ - m_texture = texture; -} - -void ImageNode::setMirror(bool mirror) -{ - // ### implement support for mirrored pixmaps - m_mirror = mirror; -} - -void ImageNode::setMipmapFiltering(QSGTexture::Filtering /*filtering*/) -{ -} - -void ImageNode::setFiltering(QSGTexture::Filtering filtering) -{ - m_smooth = (filtering == QSGTexture::Nearest); -} - -void ImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) -{ - m_tileHorizontal = (wrapMode == QSGTexture::Repeat); -} - -void ImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) -{ - m_tileVertical = (wrapMode == QSGTexture::Repeat); -} - -void ImageNode::update() -{ -} - -void ImageNode::preprocess() -{ - bool doDirty = false; - QSGLayer *t = qobject_cast<QSGLayer *>(m_texture); - if (t) { - doDirty = t->updateTexture(); - markDirty(DirtyGeometry); - } - if (doDirty) - markDirty(DirtyMaterial); -} - -static Qt::TileRule getTileRule(qreal factor) -{ - int ifactor = qRound(factor); - if (qFuzzyCompare(factor, ifactor )) { - if (ifactor == 1 || ifactor == 0) - return Qt::StretchTile; - return Qt::RoundTile; - } - return Qt::RepeatTile; -} - - -void ImageNode::paint(QPainter *painter) -{ - painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth); - - const QPixmap &pm = pixmap(); - - if (m_innerTargetRect != m_targetRect) { - // border image - QMargins margins(m_innerTargetRect.left() - m_targetRect.left(), m_innerTargetRect.top() - m_targetRect.top(), - m_targetRect.right() - m_innerTargetRect.right(), m_targetRect.bottom() - m_innerTargetRect.bottom()); - QTileRules tilerules(getTileRule(m_subSourceRect.width()), getTileRule(m_subSourceRect.height())); - SoftwareContext::qDrawBorderPixmap(painter, m_targetRect.toRect(), margins, pm, QRect(0, 0, pm.width(), pm.height()), - margins, tilerules, QDrawBorderPixmap::DrawingHints(0)); - return; - } - - if (m_tileHorizontal || m_tileVertical) { - painter->save(); - qreal sx = m_targetRect.width()/(m_subSourceRect.width()*pm.width()); - qreal sy = m_targetRect.height()/(m_subSourceRect.height()*pm.height()); - QMatrix transform(sx, 0, 0, sy, 0, 0); - painter->setMatrix(transform, true); - painter->drawTiledPixmap(QRectF(m_targetRect.x()/sx, m_targetRect.y()/sy, m_targetRect.width()/sx, m_targetRect.height()/sy), - pm, - QPointF(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height())); - painter->restore(); - } else { - QRectF sr(m_subSourceRect.left()*pm.width(), m_subSourceRect.top()*pm.height(), - m_subSourceRect.width()*pm.width(), m_subSourceRect.height()*pm.height()); - painter->drawPixmap(m_targetRect, pm, sr); - } -} - -const QPixmap &ImageNode::pixmap() const -{ - if (PixmapTexture *pt = qobject_cast<PixmapTexture*>(m_texture)) { - return pt->pixmap(); - } else if (SoftwareLayer *layer = qobject_cast<SoftwareLayer*>(m_texture)) { - return layer->pixmap(); - } else { - qFatal("Image used with invalid texture format."); - } -} diff --git a/softwarecontext/imagenode.h b/softwarecontext/imagenode.h deleted file mode 100644 index a0c059a889..0000000000 --- a/softwarecontext/imagenode.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef IMAGENODE_H -#define IMAGENODE_H - -#include <private/qsgadaptationlayer_p.h> -#include <private/qsgtexturematerial_p.h> - -typedef QVarLengthArray<QPainter::PixmapFragment, 16> QPixmapFragmentsArray; - -struct QTileRules -{ - inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule) - : horizontal(horizontalRule), vertical(verticalRule) {} - inline QTileRules(Qt::TileRule rule = Qt::StretchTile) - : horizontal(rule), vertical(rule) {} - Qt::TileRule horizontal; - Qt::TileRule vertical; -}; - -#ifndef Q_QDOC -// For internal use only. -namespace QDrawBorderPixmap -{ - enum DrawingHint - { - OpaqueTopLeft = 0x0001, - OpaqueTop = 0x0002, - OpaqueTopRight = 0x0004, - OpaqueLeft = 0x0008, - OpaqueCenter = 0x0010, - OpaqueRight = 0x0020, - OpaqueBottomLeft = 0x0040, - OpaqueBottom = 0x0080, - OpaqueBottomRight = 0x0100, - OpaqueCorners = OpaqueTopLeft | OpaqueTopRight | OpaqueBottomLeft | OpaqueBottomRight, - OpaqueEdges = OpaqueTop | OpaqueLeft | OpaqueRight | OpaqueBottom, - OpaqueFrame = OpaqueCorners | OpaqueEdges, - OpaqueAll = OpaqueCenter | OpaqueFrame - }; - - Q_DECLARE_FLAGS(DrawingHints, DrawingHint) -} -#endif - -namespace SoftwareContext { - -void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, - const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins, - const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints); - -} - -class ImageNode : public QSGImageNode -{ -public: - ImageNode(); - - virtual void setTargetRect(const QRectF &rect); - virtual void setInnerTargetRect(const QRectF &rect); - virtual void setInnerSourceRect(const QRectF &rect); - virtual void setSubSourceRect(const QRectF &rect); - virtual void setTexture(QSGTexture *texture); - virtual void setMirror(bool mirror); - virtual void setMipmapFiltering(QSGTexture::Filtering filtering); - virtual void setFiltering(QSGTexture::Filtering filtering); - virtual void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode); - virtual void setVerticalWrapMode(QSGTexture::WrapMode wrapMode); - virtual void update(); - - virtual void preprocess(); - - void paint(QPainter *painter); - -private: - const QPixmap &pixmap() const; - - QRectF m_targetRect; - QRectF m_innerTargetRect; - QRectF m_innerSourceRect; - QRectF m_subSourceRect; - - QSGTexture *m_texture; - - bool m_mirror; - bool m_smooth; - bool m_tileHorizontal; - bool m_tileVertical; -}; - -#endif // IMAGENODE_H diff --git a/softwarecontext/ninepatchnode.cpp b/softwarecontext/ninepatchnode.cpp deleted file mode 100644 index ab503b7af5..0000000000 --- a/softwarecontext/ninepatchnode.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "ninepatchnode.h" -#include "pixmaptexture.h" -#include "imagenode.h" - -NinePatchNode::NinePatchNode() -{ - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - -void NinePatchNode::setTexture(QSGTexture *texture) -{ - PixmapTexture *pt = qobject_cast<PixmapTexture*>(texture); - if (!pt) { - qWarning() << "Image used with invalid texture format."; - return; - } - m_pixmap = pt->pixmap(); -} - -void NinePatchNode::setBounds(const QRectF &bounds) -{ - m_bounds = bounds; -} - -void NinePatchNode::setDevicePixelRatio(qreal ratio) -{ - m_pixelRatio = ratio; -} - -void NinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) -{ - m_margins = QMargins(qRound(left), qRound(top), qRound(right), qRound(bottom)); -} - -void NinePatchNode::update() -{ -} - -void NinePatchNode::paint(QPainter *painter) -{ - if (m_margins.isNull()) - painter->drawPixmap(m_bounds, m_pixmap, QRectF(0, 0, m_pixmap.width(), m_pixmap.height())); - else - SoftwareContext::qDrawBorderPixmap(painter, m_bounds.toRect(), m_margins, m_pixmap, QRect(0, 0, m_pixmap.width(), m_pixmap.height()), - m_margins, Qt::StretchTile, QDrawBorderPixmap::DrawingHints(0)); -} diff --git a/softwarecontext/ninepatchnode.h b/softwarecontext/ninepatchnode.h deleted file mode 100644 index 2bcd1214e3..0000000000 --- a/softwarecontext/ninepatchnode.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef NINEPATCHNODE_H -#define NINEPATCHNODE_H - -#include <private/qsgadaptationlayer_p.h> - -class NinePatchNode : public QSGNinePatchNode -{ -public: - NinePatchNode(); - - virtual void setTexture(QSGTexture *texture); - virtual void setBounds(const QRectF &bounds); - virtual void setDevicePixelRatio(qreal ratio); - virtual void setPadding(qreal left, qreal top, qreal right, qreal bottom); - virtual void update(); - - void paint(QPainter *painter); - -private: - QPixmap m_pixmap; - QRectF m_bounds; - qreal m_pixelRatio; - QMargins m_margins; -}; - -#endif // NINEPATCHNODE_H diff --git a/softwarecontext/painternode.cpp b/softwarecontext/painternode.cpp deleted file mode 100644 index bf5ec5f202..0000000000 --- a/softwarecontext/painternode.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "painternode.h" -#include "pixmaptexture.h" -#include <qmath.h> - -PainterNode::PainterNode(QQuickPaintedItem *item) - : QSGPainterNode() - , m_preferredRenderTarget(QQuickPaintedItem::Image) - , m_actualRenderTarget(QQuickPaintedItem::Image) - , m_item(item) - , m_texture(0) - , m_dirtyContents(false) - , m_opaquePainting(false) - , m_linear_filtering(false) - , m_mipmapping(false) - , m_smoothPainting(false) - , m_extensionsChecked(false) - , m_multisamplingSupported(false) - , m_fastFBOResizing(false) - , m_fillColor(Qt::transparent) - , m_contentsScale(1.0) - , m_dirtyGeometry(false) -{ - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - -PainterNode::~PainterNode() -{ - delete m_texture; -} - -void PainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) -{ - if (m_preferredRenderTarget == target) - return; - - m_preferredRenderTarget = target; -} - -void PainterNode::setSize(const QSize &size) -{ - if (size == m_size) - return; - - m_size = size; - - m_dirtyGeometry = true; -} - -void PainterNode::setDirty(const QRect &dirtyRect) -{ - m_dirtyContents = true; - m_dirtyRect = dirtyRect; - markDirty(DirtyMaterial); -} - -void PainterNode::setOpaquePainting(bool opaque) -{ - if (opaque == m_opaquePainting) - return; - - m_opaquePainting = opaque; -} - -void PainterNode::setLinearFiltering(bool linearFiltering) -{ - if (linearFiltering == m_linear_filtering) - return; - - m_linear_filtering = linearFiltering; -} - -void PainterNode::setMipmapping(bool mipmapping) -{ - if (mipmapping == m_mipmapping) - return; - - m_mipmapping = mipmapping; -} - -void PainterNode::setSmoothPainting(bool s) -{ - if (s == m_smoothPainting) - return; - - m_smoothPainting = s; -} - -void PainterNode::setFillColor(const QColor &c) -{ - if (c == m_fillColor) - return; - - m_fillColor = c; - markDirty(DirtyMaterial); -} - -void PainterNode::setContentsScale(qreal s) -{ - if (s == m_contentsScale) - return; - - m_contentsScale = s; - markDirty(DirtyMaterial); -} - -void PainterNode::setFastFBOResizing(bool dynamic) -{ - m_fastFBOResizing = dynamic; -} - -QImage PainterNode::toImage() const -{ - return m_pixmap.toImage(); -} - -void PainterNode::update() -{ - if (m_dirtyGeometry) { - m_pixmap = QPixmap(m_size); - if (!m_opaquePainting) - m_pixmap.fill(Qt::transparent); - - if (m_texture) - delete m_texture; - m_texture = new PixmapTexture(m_pixmap); - } - - if (m_dirtyContents) - paint(); - - m_dirtyGeometry = false; - m_dirtyContents = false; -} - -void PainterNode::paint(QPainter *painter) -{ - painter->drawPixmap(0, 0, m_size.width(), m_size.height(), m_pixmap); -} - -void PainterNode::paint() -{ - QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect; - - QPainter painter; - - painter.begin(&m_pixmap); - if (m_smoothPainting) { - painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); - } - - painter.scale(m_contentsScale, m_contentsScale); - - QRect sclip(qFloor(dirtyRect.x()/m_contentsScale), - qFloor(dirtyRect.y()/m_contentsScale), - qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)), - qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale))); - - if (!m_dirtyRect.isNull()) - painter.setClipRect(sclip); - - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(sclip, m_fillColor); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - - m_item->paint(&painter); - painter.end(); - - m_dirtyRect = QRect(); -} diff --git a/softwarecontext/painternode.h b/softwarecontext/painternode.h deleted file mode 100644 index db0d03e28a..0000000000 --- a/softwarecontext/painternode.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef PAINTERNODE_H -#define PAINTERNODE_H - -#include <private/qsgadaptationlayer_p.h> -#include <QtQuick/qquickpainteditem.h> - -#include <QtGui/QPixmap> - -class PainterNode : public QSGPainterNode -{ -public: - PainterNode(QQuickPaintedItem *item); - ~PainterNode(); - - void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target); - - void setSize(const QSize &size); - QSize size() const { return m_size; } - - void setDirty(const QRect &dirtyRect = QRect()); - - void setOpaquePainting(bool opaque); - bool opaquePainting() const { return m_opaquePainting; } - - void setLinearFiltering(bool linearFiltering); - bool linearFiltering() const { return m_linear_filtering; } - - void setMipmapping(bool mipmapping); - bool mipmapping() const { return m_mipmapping; } - - void setSmoothPainting(bool s); - bool smoothPainting() const { return m_smoothPainting; } - - void setFillColor(const QColor &c); - QColor fillColor() const { return m_fillColor; } - - void setContentsScale(qreal s); - qreal contentsScale() const { return m_contentsScale; } - - void setFastFBOResizing(bool dynamic); - bool fastFBOResizing() const { return m_fastFBOResizing; } - - QImage toImage() const; - void update(); - QSGTexture *texture() const { return m_texture; } - - void paint(QPainter *painter); - - void paint(); - -private: - - QQuickPaintedItem::RenderTarget m_preferredRenderTarget; - QQuickPaintedItem::RenderTarget m_actualRenderTarget; - - QQuickPaintedItem *m_item; - - QPixmap m_pixmap; - QSGTexture *m_texture; - - QSize m_size; - bool m_dirtyContents; - QRect m_dirtyRect; - bool m_opaquePainting; - bool m_linear_filtering; - bool m_mipmapping; - bool m_smoothPainting; - bool m_extensionsChecked; - bool m_multisamplingSupported; - bool m_fastFBOResizing; - QColor m_fillColor; - qreal m_contentsScale; - - bool m_dirtyGeometry; -}; - -#endif // PAINTERNODE_H diff --git a/softwarecontext/pixmaptexture.cpp b/softwarecontext/pixmaptexture.cpp deleted file mode 100644 index d3dd747a9e..0000000000 --- a/softwarecontext/pixmaptexture.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "pixmaptexture.h" - -PixmapTexture::PixmapTexture(const QImage &image) - : m_pixmap(QPixmap::fromImage(image)) -{ -} - -PixmapTexture::PixmapTexture(const QPixmap &pixmap) - : m_pixmap(pixmap) -{ -} - - -int PixmapTexture::textureId() const -{ - return 0; -} - -QSize PixmapTexture::textureSize() const -{ - return m_pixmap.size(); -} - -bool PixmapTexture::hasAlphaChannel() const -{ - return m_pixmap.hasAlphaChannel(); -} - -bool PixmapTexture::hasMipmaps() const -{ - return false; -} - -void PixmapTexture::bind() -{ - Q_UNREACHABLE(); -} diff --git a/softwarecontext/pixmaptexture.h b/softwarecontext/pixmaptexture.h deleted file mode 100644 index c3ee09dfe1..0000000000 --- a/softwarecontext/pixmaptexture.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef PIXMAPTEXTURE_H -#define PIXMAPTEXTURE_H - -#include <private/qsgtexture_p.h> - -class PixmapTexture : public QSGTexture -{ - Q_OBJECT -public: - PixmapTexture(const QImage &image); - PixmapTexture(const QPixmap &pixmap); - - virtual int textureId() const; - virtual QSize textureSize() const; - virtual bool hasAlphaChannel() const; - virtual bool hasMipmaps() const; - virtual void bind(); - - const QPixmap &pixmap() const { return m_pixmap; } - -private: - QPixmap m_pixmap; -}; - -#endif // PIXMAPTEXTURE_H diff --git a/softwarecontext/pluginmain.cpp b/softwarecontext/pluginmain.cpp deleted file mode 100644 index afb91a8ea2..0000000000 --- a/softwarecontext/pluginmain.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "pluginmain.h" -#include "context.h" -#include "renderloop.h" -#include "threadedrenderloop.h" - -ContextPlugin::ContextPlugin(QObject *parent) - : QSGContextPlugin(parent) -{ -} - -QStringList ContextPlugin::keys() const -{ - return QStringList() << QLatin1String("softwarecontext"); -} - -QSGContext *ContextPlugin::create(const QString &) const -{ - if (!instance) - instance = new SoftwareContext::Context(); - return instance; -} - -QSGRenderLoop *ContextPlugin::createWindowManager() -{ - if (qgetenv("QSG_RENDER_LOOP") == QByteArrayLiteral("basic")) - return new RenderLoop(); - return new ThreadedRenderLoop(); -} - -SoftwareContext::Context *ContextPlugin::instance = 0; - - - diff --git a/softwarecontext/pluginmain.h b/softwarecontext/pluginmain.h deleted file mode 100644 index fd90823322..0000000000 --- a/softwarecontext/pluginmain.h +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PLUGINMAIN_H -#define PLUGINMAIN_H - -#include <private/qsgcontext_p.h> -#include <private/qsgcontextplugin_p.h> - -#include <qplugin.h> - -#include "context.h" - -class ContextPlugin : public QSGContextPlugin -{ - Q_OBJECT - - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSGContextFactoryInterface" FILE "softwarecontext.json") - -public: - ContextPlugin(QObject *parent = 0); - - QStringList keys() const; - QSGContext *create(const QString &key) const; - QSGRenderLoop *createWindowManager(); - - static SoftwareContext::Context *instance; -}; - -#endif // PLUGINMAIN_H diff --git a/softwarecontext/rectanglenode.cpp b/softwarecontext/rectanglenode.cpp deleted file mode 100644 index 054ffd3ecf..0000000000 --- a/softwarecontext/rectanglenode.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "rectanglenode.h" -#include <qmath.h> - -#include <QtGui/QPainter> - - -RectangleNode::RectangleNode() - : m_penWidth(0) - , m_radius(0) - , m_cornerPixmapIsDirty(true) -{ - setMaterial((QSGMaterial*)1); - setGeometry((QSGGeometry*)1); -} - -void RectangleNode::setRect(const QRectF &rect) -{ - if (m_rect != rect) { - m_rect = rect; - } -} - -void RectangleNode::setColor(const QColor &color) -{ - if (m_color != color) { - m_color = color; - m_cornerPixmapIsDirty = true; - } -} - -void RectangleNode::setPenColor(const QColor &color) -{ - if (m_penColor != color) { - m_penColor = color; - m_cornerPixmapIsDirty = true; - } -} - -void RectangleNode::setPenWidth(qreal width) -{ - if (m_penWidth != width) { - m_penWidth = width; - m_cornerPixmapIsDirty = true; - } -} - -void RectangleNode::setGradientStops(const QGradientStops &stops) -{ - m_stops = stops; - m_cornerPixmapIsDirty = true; -} - -void RectangleNode::setRadius(qreal radius) -{ - if (m_radius != radius) { - m_radius = radius; - m_cornerPixmapIsDirty = true; - } -} - -void RectangleNode::setAligned(bool /*aligned*/) -{ -} - -void RectangleNode::update() -{ - if (!m_penWidth || m_penColor == Qt::transparent) { - m_pen = Qt::NoPen; - } else { - m_pen = QPen(m_penColor); - m_pen.setWidthF(m_penWidth); - } - - if (!m_stops.isEmpty()) { - QLinearGradient gradient(QPoint(0,0), QPoint(0,1)); - gradient.setStops(m_stops); - gradient.setCoordinateMode(QGradient::ObjectBoundingMode); - m_brush = QBrush(gradient); - } else { - m_brush = QBrush(m_color); - } - - if (m_cornerPixmapIsDirty) { - //Generate new corner Pixmap - int radius = qRound(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5f, m_radius)); - - m_cornerPixmap = QPixmap(radius * 2, radius * 2); - m_cornerPixmap.fill(Qt::transparent); - - if (radius > 0) { - QPainter cornerPainter(&m_cornerPixmap); - cornerPainter.setRenderHint(QPainter::Antialiasing); - cornerPainter.setCompositionMode(QPainter::CompositionMode_Source); - - //Paint outer cicle - if (m_penWidth > 0) { - cornerPainter.setPen(Qt::NoPen); - cornerPainter.setBrush(m_penColor); - cornerPainter.drawRoundedRect(QRectF(0, 0, radius * 2, radius *2), radius, radius); - } - - //Paint inner circle - if (radius > m_penWidth) { - cornerPainter.setPen(Qt::NoPen); - if (m_stops.isEmpty()) - cornerPainter.setBrush(m_brush); - else - cornerPainter.setBrush(Qt::transparent); - - QMarginsF adjustmentMargins(m_penWidth, m_penWidth, m_penWidth, m_penWidth); - QRectF cornerCircleRect = QRectF(0, 0, radius * 2, radius * 2).marginsRemoved(adjustmentMargins); - cornerPainter.drawRoundedRect(cornerCircleRect, radius, radius); - } - cornerPainter.end(); - } - m_cornerPixmapIsDirty = false; - } -} - -void RectangleNode::paint(QPainter *painter) -{ - //Radius should never exceeds half of the width or half of the height - int radius = qRound(qMin(qMin(m_rect.width(), m_rect.height()) * 0.5, m_radius)); - - QPainter::RenderHints previousRenderHints = painter->renderHints(); - painter->setRenderHint(QPainter::Antialiasing, false); - - if (m_penWidth > 0) { - //Borders can not be more than half the height/width of a rect - double borderWidth = qMin(m_penWidth, m_rect.width() * 0.5); - double borderHeight = qMin(m_penWidth, m_rect.height() * 0.5); - - //Fill 4 border Rects - QRectF borderTop(QPointF(m_rect.x() + radius, m_rect.y()), - QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + borderHeight)); - painter->fillRect(borderTop, m_penColor); - QRectF borderBottom(QPointF(m_rect.x() + radius, m_rect.y() + m_rect.height() - borderHeight), - QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + m_rect.height())); - painter->fillRect(borderBottom, m_penColor); - QRectF borderLeft(QPointF(m_rect.x(), m_rect.y() + radius), - QPointF(m_rect.x() + borderWidth, m_rect.y() + m_rect.height() - radius)); - painter->fillRect(borderLeft, m_penColor); - QRectF borderRight(QPointF(m_rect.x() + m_rect.width() - borderWidth, m_rect.y() + radius), - QPointF(m_rect.x() + m_rect.width(), m_rect.y() + m_rect.height() - radius)); - painter->fillRect(borderRight, m_penColor); - } - - if (radius > 0) { - //blit 4 corners to border - QRectF topLeftCorner(QPointF(m_rect.x(), m_rect.y()), - QPointF(m_rect.x() + radius, m_rect.y() + radius)); - painter->drawPixmap(topLeftCorner, m_cornerPixmap, QRectF(0, 0, radius, radius)); - QRectF topRightCorner(QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y()), - QPointF(m_rect.x() + m_rect.width(), m_rect.y() + radius)); - painter->drawPixmap(topRightCorner, m_cornerPixmap, QRectF(radius, 0, radius, radius)); - QRectF bottomLeftCorner(QPointF(m_rect.x(), m_rect.y() + m_rect.height() - radius), - QPointF(m_rect.x() + radius, m_rect.y() + m_rect.height())); - painter->drawPixmap(bottomLeftCorner, m_cornerPixmap, QRectF(0, radius, radius, radius)); - QRectF bottomRightCorner(QPointF(m_rect.x() + m_rect.width() - radius, m_rect.y() + m_rect.height() - radius), - QPointF(m_rect.x() + m_rect.width(), m_rect.y() + m_rect.height())); - painter->drawPixmap(bottomRightCorner, m_cornerPixmap, QRectF(radius, radius, radius, radius)); - - } - - QRectF brushRect = m_rect.marginsRemoved(QMarginsF(m_penWidth, m_penWidth, m_penWidth, m_penWidth)); - if (brushRect.width() < 0) - brushRect.setWidth(0); - if (brushRect.height() < 0) - brushRect.setHeight(0); - double innerRectRadius = qMax(0.0, radius - m_penWidth); - - //If not completely transparent or has a gradient - if (m_color.alpha() > 0 || !m_stops.empty()) { - if (innerRectRadius > 0) { - //Rounded Rect - if (m_stops.empty()) { - //Rounded Rects without gradient need 3 blits - QRectF centerRect(QPointF(brushRect.x() + innerRectRadius, brushRect.y()), - QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + brushRect.height())); - painter->fillRect(centerRect, m_color); - QRectF leftRect(QPointF(brushRect.x(), brushRect.y() + innerRectRadius), - QPointF(brushRect.x() + innerRectRadius, brushRect.y() + brushRect.height() - innerRectRadius)); - painter->fillRect(leftRect, m_color); - QRectF rightRect(QPointF(brushRect.x() + brushRect.width() - innerRectRadius, brushRect.y() + innerRectRadius), - QPointF(brushRect.x() + brushRect.width(), brushRect.y() + brushRect.height() - innerRectRadius)); - painter->fillRect(rightRect, m_color); - } else { - //Rounded Rect with gradient (slow) - painter->setPen(Qt::NoPen); - painter->setBrush(m_brush); - painter->drawRoundedRect(brushRect, innerRectRadius, innerRectRadius); - } - } else { - //non-rounded rects only need 1 blit - painter->fillRect(brushRect, m_brush); - } - } - - painter->setRenderHints(previousRenderHints); -} diff --git a/softwarecontext/rectanglenode.h b/softwarecontext/rectanglenode.h deleted file mode 100644 index 74c0971c82..0000000000 --- a/softwarecontext/rectanglenode.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef RECTANGLENODE_H -#define RECTANGLENODE_H - -#include <private/qsgadaptationlayer_p.h> - -#include <QPen> -#include <QBrush> -#include <QPixmap> - -class RectangleNode : public QSGRectangleNode -{ -public: - RectangleNode(); - - virtual void setRect(const QRectF &rect); - virtual void setColor(const QColor &color); - virtual void setPenColor(const QColor &color); - virtual void setPenWidth(qreal width); - virtual void setGradientStops(const QGradientStops &stops); - virtual void setRadius(qreal radius); - virtual void setAntialiasing(bool antialiasing) { Q_UNUSED(antialiasing) } - virtual void setAligned(bool aligned); - - virtual void update(); - - void paint(QPainter *); - -private: - QRectF m_rect; - QColor m_color; - QColor m_penColor; - double m_penWidth; - QGradientStops m_stops; - double m_radius; - QPen m_pen; - QBrush m_brush; - - bool m_cornerPixmapIsDirty; - QPixmap m_cornerPixmap; -}; - -#endif // RECTANGLENODE_H diff --git a/softwarecontext/renderingvisitor.cpp b/softwarecontext/renderingvisitor.cpp deleted file mode 100644 index 879c30eb4f..0000000000 --- a/softwarecontext/renderingvisitor.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "renderingvisitor.h" - -#include "imagenode.h" -#include "rectanglenode.h" -#include "glyphnode.h" -#include "ninepatchnode.h" -#include "painternode.h" -#include "pixmaptexture.h" - -#include <QtQuick/QSGSimpleRectNode> -#include <QtQuick/qsgsimpletexturenode.h> -#include <private/qsgtexture_p.h> -#include <private/qquickshadereffectnode_p.h> - -RenderingVisitor::RenderingVisitor(QPainter *painter) - : painter(painter) -{ - -} - -bool RenderingVisitor::visit(QSGTransformNode *node) -{ - painter->save(); - painter->setTransform(node->matrix().toTransform(), /*combine*/true); - return true; -} - -void RenderingVisitor::endVisit(QSGTransformNode *) -{ - painter->restore(); -} - -bool RenderingVisitor::visit(QSGClipNode *node) -{ - painter->save(); - painter->setClipRect(node->clipRect(), Qt::IntersectClip); - return true; -} - -void RenderingVisitor::endVisit(QSGClipNode *) -{ - painter->restore(); -} - -bool RenderingVisitor::visit(QSGGeometryNode *node) -{ - if (QSGSimpleRectNode *rectNode = dynamic_cast<QSGSimpleRectNode *>(node)) { - if (!rectNode->material()->flags() & QSGMaterial::Blending) - painter->setCompositionMode(QPainter::CompositionMode_Source); - painter->fillRect(rectNode->rect(), rectNode->color()); - painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - } else if (QSGSimpleTextureNode *tn = dynamic_cast<QSGSimpleTextureNode *>(node)) { - QSGTexture *texture = tn->texture(); - if (PixmapTexture *pt = dynamic_cast<PixmapTexture *>(texture)) { - const QPixmap &pm = pt->pixmap(); - painter->drawPixmap(tn->rect(), pm, QRectF(0, 0, pm.width(), pm.height())); - } else if (QSGPlainTexture *pt = dynamic_cast<QSGPlainTexture *>(texture)) { - const QImage &im = pt->image(); - painter->drawImage(tn->rect(), im, QRectF(0, 0, im.width(), im.height())); - } else { - Q_UNREACHABLE(); - } - } else if (QQuickShaderEffectNode *sn = dynamic_cast<QQuickShaderEffectNode *>(node)) { - Q_UNUSED(sn) - } else { - Q_UNREACHABLE(); - } - return true; -} - -void RenderingVisitor::endVisit(QSGGeometryNode *) -{ -} - -bool RenderingVisitor::visit(QSGOpacityNode *node) -{ - painter->save(); - - const qreal newOpacity = painter->opacity() * node->opacity(); - if (qFuzzyIsNull(newOpacity)) - return false; - - painter->setOpacity(newOpacity); - return true; -} - -void RenderingVisitor::endVisit(QSGOpacityNode *) -{ - painter->restore(); -} - -bool RenderingVisitor::visit(QSGImageNode *node) -{ - static_cast<ImageNode*>(node)->paint(painter); - return true; -} - -void RenderingVisitor::endVisit(QSGImageNode *) -{ -} - -bool RenderingVisitor::visit(QSGPainterNode *node) -{ - static_cast<PainterNode*>(node)->paint(painter); - return true; -} - -void RenderingVisitor::endVisit(QSGPainterNode *node) -{ - -} - -bool RenderingVisitor::visit(QSGRectangleNode *node) -{ - static_cast<RectangleNode*>(node)->paint(painter); - return true; -} - -void RenderingVisitor::endVisit(QSGRectangleNode *) -{ -} - -bool RenderingVisitor::visit(QSGGlyphNode *node) -{ - static_cast<GlyphNode*>(node)->paint(painter); - return true; -} - -void RenderingVisitor::endVisit(QSGGlyphNode *) -{ -} - -bool RenderingVisitor::visit(QSGNinePatchNode *node) -{ - static_cast<NinePatchNode*>(node)->paint(painter); - return true; -} - -void RenderingVisitor::endVisit(QSGNinePatchNode *) -{ -} - -bool RenderingVisitor::visit(QSGRootNode *) -{ - return true; -} - -void RenderingVisitor::endVisit(QSGRootNode *) -{ -} diff --git a/softwarecontext/renderingvisitor.h b/softwarecontext/renderingvisitor.h deleted file mode 100644 index d65faa4293..0000000000 --- a/softwarecontext/renderingvisitor.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef RENDERINGVISITOR_H -#define RENDERINGVISITOR_H - -#include <private/qsgadaptationlayer_p.h> - -class RenderingVisitor : public QSGNodeVisitorEx -{ -public: - RenderingVisitor(QPainter *painter); - - virtual bool visit(QSGTransformNode *node); - virtual void endVisit(QSGTransformNode *); - virtual bool visit(QSGClipNode *node); - virtual void endVisit(QSGClipNode *node); - virtual bool visit(QSGGeometryNode *node); - virtual void endVisit(QSGGeometryNode *node); - virtual bool visit(QSGOpacityNode *node); - virtual void endVisit(QSGOpacityNode *node); - virtual bool visit(QSGImageNode *node); - virtual void endVisit(QSGImageNode *node); - virtual bool visit(QSGPainterNode *node); - virtual void endVisit(QSGPainterNode *node); - virtual bool visit(QSGRectangleNode *node); - virtual void endVisit(QSGRectangleNode *node); - virtual bool visit(QSGGlyphNode *node); - virtual void endVisit(QSGGlyphNode *node); - virtual bool visit(QSGNinePatchNode *node); - virtual void endVisit(QSGNinePatchNode *); - virtual bool visit(QSGRootNode *); - virtual void endVisit(QSGRootNode *); - -private: - QPainter *painter; -}; - -#endif // RENDERINGVISITOR_H diff --git a/softwarecontext/renderloop.cpp b/softwarecontext/renderloop.cpp deleted file mode 100644 index 7dd20342bc..0000000000 --- a/softwarecontext/renderloop.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "renderloop.h" - -#include "context.h" -#include <private/qquickwindow_p.h> -#include <QElapsedTimer> -#include <private/qquickprofiler_p.h> - -// Used for very high-level info about the renderering and gl context -// Includes GL_VERSION, type of render loop, atlas size, etc. -Q_LOGGING_CATEGORY(QSG_LOG_INFO, "qt.scenegraph.info") - -// Used to debug the renderloop logic. Primarily useful for platform integrators -// and when investigating the render loop logic. -Q_LOGGING_CATEGORY(QSG_LOG_RENDERLOOP, "qt.scenegraph.renderloop") - - -// GLSL shader compilation -Q_LOGGING_CATEGORY(QSG_LOG_TIME_COMPILATION, "qt.scenegraph.time.compilation") - -// polish, animations, sync, render and swap in the render loop -Q_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERLOOP, "qt.scenegraph.time.renderloop") - -// Texture uploads and swizzling -Q_LOGGING_CATEGORY(QSG_LOG_TIME_TEXTURE, "qt.scenegraph.time.texture") - -// Glyph preparation (only for distance fields atm) -Q_LOGGING_CATEGORY(QSG_LOG_TIME_GLYPH, "qt.scenegraph.time.glyph") - -// Timing inside the renderer base class -Q_LOGGING_CATEGORY(QSG_LOG_TIME_RENDERER, "qt.scenegraph.time.renderer") - -RenderLoop::RenderLoop() - : eventPending(false) -{ - sg = QSGContext::createDefaultContext(); - rc = sg->createRenderContext(); -} - -RenderLoop::~RenderLoop() -{ - delete rc; - delete sg; -} - -void RenderLoop::show(QQuickWindow *window) -{ - WindowData data; - data.updatePending = false; - data.grabOnly = false; - m_windows[window] = data; - - maybeUpdate(window); -} - -void RenderLoop::hide(QQuickWindow *window) -{ - if (!m_windows.contains(window)) - return; - - m_windows.remove(window); - QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); - cd->fireAboutToStop(); - cd->cleanupNodesOnShutdown(); - - if (m_windows.size() == 0) { - if (!cd->persistentSceneGraph) { - rc->invalidate(); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - } - } -} - -void RenderLoop::windowDestroyed(QQuickWindow *window) -{ - hide(window); - if (m_windows.size() == 0) { - rc->invalidate(); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - } -} - -void RenderLoop::renderWindow(QQuickWindow *window) -{ - QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); - if (!cd->isRenderable() || !m_windows.contains(window)) - return; - - WindowData &data = const_cast<WindowData &>(m_windows[window]); - - // ### create QPainter and set up pointer to current window/painter - SoftwareContext::RenderContext *ctx = static_cast<SoftwareContext::RenderContext*>(cd->context); - ctx->currentWindow = window; - ctx->initializeIfNeeded(); - - bool alsoSwap = data.updatePending; - data.updatePending = false; - - if (!data.grabOnly) { - cd->flushDelayedTouchEvent(); - // Event delivery/processing triggered the window to be deleted or stop rendering. - if (!m_windows.contains(window)) - return; - } - QElapsedTimer renderTimer; - qint64 renderTime = 0, syncTime = 0, polishTime = 0; - bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::enabled; - if (profileFrames) - renderTimer.start(); - - cd->polishItems(); - - if (profileFrames) { - polishTime = renderTimer.nsecsElapsed(); - Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphPolishFrame, (polishTime)); - } - - emit window->afterAnimating(); - - cd->syncSceneGraph(); - - if (profileFrames) - syncTime = renderTimer.nsecsElapsed(); - - cd->renderSceneGraph(window->size()); - - if (profileFrames) - renderTime = renderTimer.nsecsElapsed(); - - if (data.grabOnly) { - // #### grabContent = qt_gl_read_framebuffer(window->size() * window->devicePixelRatio(), false, false); - data.grabOnly = false; - } - - if (alsoSwap && window->isVisible()) { -// ### gl->swapBuffers(window); - cd->fireFrameSwapped(); - } - - qint64 swapTime = 0; - if (profileFrames) - swapTime = renderTimer.nsecsElapsed(); - - if (QSG_LOG_TIME_RENDERLOOP().isDebugEnabled()) { - static QTime lastFrameTime = QTime::currentTime(); - qCDebug(QSG_LOG_TIME_RENDERLOOP, - "Frame rendered with 'basic' renderloop in %dms, polish=%d, sync=%d, render=%d, swap=%d, frameDelta=%d", - int(swapTime / 1000000), - int(polishTime / 1000000), - int((syncTime - polishTime) / 1000000), - int((renderTime - syncTime) / 1000000), - int((swapTime - renderTime) / 10000000), - int(lastFrameTime.msecsTo(QTime::currentTime()))); - lastFrameTime = QTime::currentTime(); - } - - Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRenderLoopFrame, ( - syncTime - polishTime, - renderTime - syncTime, - swapTime - renderTime)); - - // Might have been set during syncSceneGraph() - if (data.updatePending) - maybeUpdate(window); -} - -void RenderLoop::exposureChanged(QQuickWindow *window) -{ - if (window->isExposed()) { - m_windows[window].updatePending = true; - renderWindow(window); - } -} - -QImage RenderLoop::grab(QQuickWindow *window) -{ - if (!m_windows.contains(window)) - return QImage(); - - m_windows[window].grabOnly = true; - - renderWindow(window); - - QImage grabbed = grabContent; - grabContent = QImage(); - return grabbed; -} - - - -void RenderLoop::maybeUpdate(QQuickWindow *window) -{ - if (!m_windows.contains(window)) - return; - - m_windows[window].updatePending = true; - - if (!eventPending) { - const int exhaust_delay = 5; - m_update_timer = startTimer(exhaust_delay, Qt::PreciseTimer); - eventPending = true; - } -} - -QSurface::SurfaceType RenderLoop::windowSurfaceType() const -{ - return QSurface::RasterSurface; -} - - - -QSGContext *RenderLoop::sceneGraphContext() const -{ - return sg; -} - - -bool RenderLoop::event(QEvent *e) -{ - if (e->type() == QEvent::Timer) { - eventPending = false; - killTimer(m_update_timer); - m_update_timer = 0; - for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin(); - it != m_windows.constEnd(); ++it) { - const WindowData &data = it.value(); - if (data.updatePending) - renderWindow(it.key()); - } - return true; - } - return QObject::event(e); -} diff --git a/softwarecontext/renderloop.h b/softwarecontext/renderloop.h deleted file mode 100644 index b6993a830a..0000000000 --- a/softwarecontext/renderloop.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef RENDERLOOP_H -#define RENDERLOOP_H - -#include <private/qsgrenderloop_p.h> - -class RenderLoop : public QSGRenderLoop -{ - Q_OBJECT -public: - RenderLoop(); - ~RenderLoop(); - - void show(QQuickWindow *window); - void hide(QQuickWindow *window); - - void windowDestroyed(QQuickWindow *window); - - void renderWindow(QQuickWindow *window); - void exposureChanged(QQuickWindow *window); - QImage grab(QQuickWindow *window); - - void maybeUpdate(QQuickWindow *window); - void update(QQuickWindow *window) { maybeUpdate(window); } // identical for this implementation. - - void releaseResources(QQuickWindow *) { } - - virtual QSurface::SurfaceType windowSurfaceType() const; - - QAnimationDriver *animationDriver() const { return 0; } - - QSGContext *sceneGraphContext() const; - QSGRenderContext *createRenderContext(QSGContext *) const { return rc; } - - bool event(QEvent *); - - struct WindowData { - bool updatePending : 1; - bool grabOnly : 1; - }; - - QHash<QQuickWindow *, WindowData> m_windows; - - QSGContext *sg; - QSGRenderContext *rc; - - QImage grabContent; - int m_update_timer; - - bool eventPending; - -}; - -#endif // RENDERLOOP_H diff --git a/softwarecontext/softwarecontext.json b/softwarecontext/softwarecontext.json deleted file mode 100644 index ca87c6c38a..0000000000 --- a/softwarecontext/softwarecontext.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Keys": ["softwarecontext"] -} diff --git a/softwarecontext/softwarecontext.pro b/softwarecontext/softwarecontext.pro deleted file mode 100644 index d60260c1eb..0000000000 --- a/softwarecontext/softwarecontext.pro +++ /dev/null @@ -1,43 +0,0 @@ -TEMPLATE=lib -TARGET=softwarecontext - -CONFIG += plugin - -QT += gui-private core-private quick-private qml-private - -SOURCES += \ - context.cpp \ - pluginmain.cpp \ - renderloop.cpp \ - rectanglenode.cpp \ - imagenode.cpp \ - pixmaptexture.cpp \ - glyphnode.cpp \ - renderingvisitor.cpp \ - ninepatchnode.cpp \ - softwarelayer.cpp \ - threadedrenderloop.cpp \ - painternode.cpp - -HEADERS += \ - context.h \ - pluginmain.h \ - renderloop.h \ - rectanglenode.h \ - imagenode.h \ - pixmaptexture.h \ - glyphnode.h \ - renderingvisitor.h \ - ninepatchnode.h \ - softwarelayer.h \ - threadedrenderloop.h \ - painternode.h - -OTHER_FILES += softwarecontext.json - -target.path += $$[QT_INSTALL_PLUGINS]/scenegraph - -files.path += $$[QT_INSTALL_PLUGINS]/scenegraph - -INSTALLS += target files - diff --git a/softwarecontext/softwarelayer.cpp b/softwarecontext/softwarelayer.cpp deleted file mode 100644 index 70cb73fdaa..0000000000 --- a/softwarecontext/softwarelayer.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "softwarelayer.h" - -#include "context.h" - -SoftwareLayer::SoftwareLayer(QSGRenderContext *renderContext) - : m_item(0) - , m_shaderSourceNode(0) - , m_context(renderContext) - , m_renderer(0) - , m_device_pixel_ratio(1) - , m_live(true) - , m_grab(true) - , m_recursive(false) - , m_dirtyTexture(true) -{ - -} - -SoftwareLayer::~SoftwareLayer() -{ - invalidated(); -} - -int SoftwareLayer::textureId() const -{ - return 0; -} - -QSize SoftwareLayer::textureSize() const -{ - return m_pixmap.size(); -} - -bool SoftwareLayer::hasAlphaChannel() const -{ - return m_pixmap.hasAlphaChannel(); -} - -bool SoftwareLayer::hasMipmaps() const -{ - return false; -} - -void SoftwareLayer::bind() -{ -} - -bool SoftwareLayer::updateTexture() -{ - bool doGrab = (m_live || m_grab) && m_dirtyTexture; - if (doGrab) - grab(); - if (m_grab) - emit scheduledUpdateCompleted(); - m_grab = false; - return doGrab; -} - -void SoftwareLayer::setItem(QSGNode *item) -{ - if (item == m_item) - return; - m_item = item; - - if (m_live && !m_item) - m_pixmap = QPixmap(); - - markDirtyTexture(); -} - -void SoftwareLayer::setShaderSourceNode(QSGNode *node) -{ - m_shaderSourceNode = node; -} - -void SoftwareLayer::setRect(const QRectF &rect) -{ - if (rect == m_rect) - return; - m_rect = rect; - markDirtyTexture(); -} - -void SoftwareLayer::setSize(const QSize &size) -{ - if (size == m_size) - return; - m_size = size; - - if (m_live && m_size.isNull()) - m_pixmap = QPixmap(); - - markDirtyTexture(); -} - -void SoftwareLayer::scheduleUpdate() -{ - if (m_grab) - return; - m_grab = true; - if (m_dirtyTexture) { - emit updateRequested(); - if (m_shaderSourceNode) - m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial); - } -} - -QImage SoftwareLayer::toImage() const -{ - return m_pixmap.toImage(); -} - -void SoftwareLayer::setLive(bool live) -{ - if (live == m_live) - return; - m_live = live; - - if (m_live && (!m_item || m_size.isNull())) - m_pixmap = QPixmap(); - - markDirtyTexture(); -} - -void SoftwareLayer::setRecursive(bool recursive) -{ - m_recursive = recursive; -} - -void SoftwareLayer::setFormat(GLenum) -{ -} - -void SoftwareLayer::setHasMipmaps(bool) -{ -} - -void SoftwareLayer::setDevicePixelRatio(qreal ratio) -{ - m_device_pixel_ratio = ratio; -} - -void SoftwareLayer::markDirtyTexture() -{ - m_dirtyTexture = true; - if (m_live || m_grab) { - emit updateRequested(); - if (m_shaderSourceNode) - m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial); - } -} - -void SoftwareLayer::invalidated() -{ - delete m_renderer; - m_renderer = 0; -} - -void SoftwareLayer::grab() -{ - if (!m_item || m_size.isNull()) { - m_pixmap = QPixmap(); - m_dirtyTexture = false; - return; - } - QSGNode *root = m_item; - while (root->firstChild() && root->type() != QSGNode::RootNodeType) - root = root->firstChild(); - if (root->type() != QSGNode::RootNodeType) - return; - - if (!m_renderer) { - m_renderer = new SoftwareContext::PixmapRenderer(m_context); - connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture())); - } - m_renderer->setDevicePixelRatio(m_device_pixel_ratio); - m_renderer->setRootNode(static_cast<QSGRootNode *>(root)); - - if (m_pixmap.size() != m_size) - m_pixmap = QPixmap(m_size); - - // Render texture. - root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update. - m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update. - - m_dirtyTexture = false; - - m_renderer->setDeviceRect(m_size); - m_renderer->setViewportRect(m_size); - QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height()); - m_renderer->setProjectionMatrixToRect(mirrored); - m_renderer->setClearColor(Qt::transparent); - - m_renderer->render(&m_pixmap); - - root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update. - - if (m_recursive) - markDirtyTexture(); // Continuously update if 'live' and 'recursive'. -} diff --git a/softwarecontext/softwarelayer.h b/softwarecontext/softwarelayer.h deleted file mode 100644 index 3352e6085e..0000000000 --- a/softwarecontext/softwarelayer.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef SOFTWARELAYER_H -#define SOFTWARELAYER_H - -#include <private/qsgadaptationlayer_p.h> -#include <private/qsgcontext_p.h> - -namespace SoftwareContext { -class PixmapRenderer; -} - -class SoftwareLayer : public QSGLayer -{ - Q_OBJECT -public: - SoftwareLayer(QSGRenderContext *renderContext); - ~SoftwareLayer(); - - const QPixmap &pixmap() const { return m_pixmap; } - - // QSGTexture interface -public: - virtual int textureId() const; - virtual QSize textureSize() const; - virtual bool hasAlphaChannel() const; - virtual bool hasMipmaps() const; - virtual void bind(); - - // QSGDynamicTexture interface -public: - virtual bool updateTexture(); - - // QSGLayer interface -public: - virtual void setItem(QSGNode *item); - virtual void setShaderSourceNode(QSGNode *node); - virtual void setRect(const QRectF &rect); - virtual void setSize(const QSize &size); - virtual void scheduleUpdate(); - virtual QImage toImage() const; - virtual void setLive(bool live); - virtual void setRecursive(bool recursive); - virtual void setFormat(GLenum); - virtual void setHasMipmaps(bool); - virtual void setDevicePixelRatio(qreal ratio); - -public slots: - virtual void markDirtyTexture(); - virtual void invalidated(); - -private: - void grab(); - - QSGNode *m_item; - QSGNode *m_shaderSourceNode; - QSGRenderContext *m_context; - SoftwareContext::PixmapRenderer *m_renderer; - QRectF m_rect; - QSize m_size; - QPixmap m_pixmap; - qreal m_device_pixel_ratio; - bool m_live; - bool m_grab; - bool m_recursive; - bool m_dirtyTexture; -}; - -#endif // SOFTWARELAYER_H diff --git a/softwarecontext/threadedrenderloop.cpp b/softwarecontext/threadedrenderloop.cpp deleted file mode 100644 index 6b8991552d..0000000000 --- a/softwarecontext/threadedrenderloop.cpp +++ /dev/null @@ -1,1129 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com> -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "threadedrenderloop.h" - -#include <QtCore/QMutex> -#include <QtCore/QWaitCondition> -#include <QtCore/QAnimationDriver> -#include <QtCore/QQueue> -#include <QtCore/QTime> - -#include <QtGui/QGuiApplication> -#include <QtGui/QScreen> -#include <QtGui/QOffscreenSurface> - -#include <qpa/qwindowsysteminterface.h> -#include <qpa/qplatformbackingstore.h> - -#include <QtQuick/QQuickWindow> -#include <private/qquickwindow_p.h> - -#include <QtQuick/private/qsgrenderer_p.h> - -#include <private/qquickanimatorcontroller_p.h> - -#include <private/qquickprofiler_p.h> -#include <private/qqmldebugservice_p.h> -#include "context.h" - -/* - Overall design: - - There are two classes here. ThreadedRenderLoop and - RenderThread. All communication between the two is based on - event passing and we have a number of custom events. - - In this implementation, the render thread is never blocked and the - GUI thread will initiate a polishAndSync which will block and wait - for the render thread to pick it up and release the block only - after the render thread is done syncing. The reason for this - is: - - 1. Clear blocking paradigm. We only have one real "block" point - (polishAndSync()) and all blocking is initiated by GUI and picked - up by Render at specific times based on events. This makes the - execution deterministic. - - 2. Render does not have to interact with GUI. This is done so that - the render thread can run its own animation system which stays - alive even when the GUI thread is blocked doing i/o, object - instantiation, QPainter-painting or any other non-trivial task. - - --- - - There is one thread per window and one opengl context per thread. - - --- - - The render thread has affinity to the GUI thread until a window - is shown. From that moment and until the window is destroyed, it - will have affinity to the render thread. (moved back at the end - of run for cleanup). - - --- - - The render loop is active while any window is exposed. All visible - windows are tracked, but only exposed windows are actually added to - the render thread and rendered. That means that if all windows are - obscured, we might end up cleaning up the SG and GL context (if all - windows have disabled persistency). Especially for multiprocess, - low-end systems, this should be quite important. - - */ - -QT_BEGIN_NAMESPACE - -#define QSG_RT_PAD " (RT)" - -static int get_env_int(const char *name, int defaultValue) -{ - QByteArray content = qgetenv(name); - - bool ok = false; - int value = content.toInt(&ok); - return ok ? value : defaultValue; -} - - -static inline int qsgrl_animation_interval() { - qreal refreshRate = QGuiApplication::primaryScreen()->refreshRate(); - // To work around that some platforms wrongfully return 0 or something - // bogus for refreshrate - if (refreshRate < 1) - return 16; - return int(1000 / refreshRate); -} - - -static QElapsedTimer threadTimer; -static qint64 syncTime; -static qint64 renderTime; -static qint64 sinceLastTime; - -extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); - -// RL: Render Loop -// RT: Render Thread - -// Passed from the RL to the RT when a window is removed obscured and -// should be removed from the render loop. -const QEvent::Type WM_Obscure = QEvent::Type(QEvent::User + 1); - -// Passed from the RL to RT when GUI has been locked, waiting for sync -// (updatePaintNode()) -const QEvent::Type WM_RequestSync = QEvent::Type(QEvent::User + 2); - -// Passed by the RT to itself to trigger another render pass. This is -// typically a result of QQuickWindow::update(). -const QEvent::Type WM_RequestRepaint = QEvent::Type(QEvent::User + 3); - -// Passed by the RL to the RT to free up maybe release SG and GL contexts -// if no windows are rendering. -const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4); - -// Passed by the RL to the RT when a QQuickWindow::grabWindow() is -// called. -const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5); - -template <typename T> T *windowFor(const QList<T> list, QQuickWindow *window) -{ - for (int i=0; i<list.size(); ++i) { - const T &t = list.at(i); - if (t.window == window) - return const_cast<T *>(&t); - } - return 0; -} - - -class WMWindowEvent : public QEvent -{ -public: - WMWindowEvent(QQuickWindow *c, QEvent::Type type) : QEvent(type), window(c) { } - QQuickWindow *window; -}; - -class WMTryReleaseEvent : public WMWindowEvent -{ -public: - WMTryReleaseEvent(QQuickWindow *win, bool destroy, QOffscreenSurface *fallback) - : WMWindowEvent(win, WM_TryRelease) - , inDestructor(destroy) - , fallbackSurface(fallback) - {} - - bool inDestructor; - QOffscreenSurface *fallbackSurface; -}; - -class WMSyncEvent : public WMWindowEvent -{ -public: - WMSyncEvent(QQuickWindow *c, bool inExpose) : WMWindowEvent(c, WM_RequestSync), size(c->size()), syncInExpose(inExpose) { } - QSize size; - bool syncInExpose; -}; - - -class WMGrabEvent : public WMWindowEvent -{ -public: - WMGrabEvent(QQuickWindow *c, QImage *result) : WMWindowEvent(c, WM_Grab), image(result) {} - QImage *image; -}; - - -class RenderThreadEventQueue : public QQueue<QEvent *> -{ -public: - RenderThreadEventQueue() - : waiting(false) - { - } - - void addEvent(QEvent *e) { - mutex.lock(); - enqueue(e); - if (waiting) - condition.wakeOne(); - mutex.unlock(); - } - - QEvent *takeEvent(bool wait) { - mutex.lock(); - if (size() == 0 && wait) { - waiting = true; - condition.wait(&mutex); - waiting = false; - } - QEvent *e = dequeue(); - mutex.unlock(); - return e; - } - - bool hasMoreEvents() { - mutex.lock(); - bool has = !isEmpty(); - mutex.unlock(); - return has; - } - -private: - QMutex mutex; - QWaitCondition condition; - bool waiting; -}; - - -class RenderThread : public QThread -{ - Q_OBJECT -public: - RenderThread(ThreadedRenderLoop *w, QSGRenderContext *renderContext) - : wm(w) - , sgrc(renderContext) - , animatorDriver(0) - , pendingUpdate(0) - , sleeping(false) - , syncResultedInChanges(false) - , active(false) - , window(0) - , stopEventProcessing(false) - { -#if defined(Q_OS_QNX) && !defined(Q_OS_BLACKBERRY) && defined(Q_PROCESSOR_X86) - // The SDP 6.6.0 x86 MESA driver requires a larger stack than the default. - setStackSize(1024 * 1024); -#endif - vsyncDelta = qsgrl_animation_interval(); - } - - ~RenderThread() - { - delete sgrc; - } - - bool event(QEvent *); - void run(); - - void syncAndRender(); - void sync(bool inExpose); - - void requestRepaint() - { - if (sleeping) - stopEventProcessing = true; - if (window) - pendingUpdate |= RepaintRequest; - } - - void processEventsAndWaitForMore(); - void processEvents(); - void postEvent(QEvent *e); - -public slots: - void sceneGraphChanged() { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "sceneGraphChanged"; - syncResultedInChanges = true; - } - -public: - enum UpdateRequest { - SyncRequest = 0x01, - RepaintRequest = 0x02, - ExposeRequest = 0x04 | RepaintRequest | SyncRequest - }; - - ThreadedRenderLoop *wm; - QSGRenderContext *sgrc; - - QAnimationDriver *animatorDriver; - - uint pendingUpdate; - bool sleeping; - bool syncResultedInChanges; - - volatile bool active; - - float vsyncDelta; - - QMutex mutex; - QWaitCondition waitCondition; - - QElapsedTimer m_timer; - - QQuickWindow *window; // Will be 0 when window is not exposed - QSize windowSize; - - // Local event queue stuff... - bool stopEventProcessing; - RenderThreadEventQueue eventQueue; -}; - -bool RenderThread::event(QEvent *e) -{ - switch ((int) e->type()) { - - case WM_Obscure: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Obscure"; - - Q_ASSERT(!window || window == static_cast<WMWindowEvent *>(e)->window); - - mutex.lock(); - if (window) { - QQuickWindowPrivate::get(window)->fireAboutToStop(); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window removed"; - window = 0; - } - waitCondition.wakeOne(); - mutex.unlock(); - - return true; } - - case WM_RequestSync: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestSync"; - WMSyncEvent *se = static_cast<WMSyncEvent *>(e); - if (sleeping) - stopEventProcessing = true; - window = se->window; - windowSize = se->size; - - pendingUpdate |= SyncRequest; - if (se->syncInExpose) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- triggered from expose"; - pendingUpdate |= ExposeRequest; - } - return true; } - - case WM_TryRelease: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_TryRelease"; - mutex.lock(); - wm->m_lockedForSync = true; - WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e); - if (!window || wme->inDestructor) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- setting exit flag and invalidating OpenGL"; - active = false; - Q_ASSERT_X(!wme->inDestructor || !active, "RenderThread::invalidateOpenGL()", "Thread's active state is not set to false when shutting down"); - if (sleeping) - stopEventProcessing = true; - } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- not releasing because window is still active"; - } - waitCondition.wakeOne(); - wm->m_lockedForSync = false; - mutex.unlock(); - return true; - } - - case WM_Grab: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Grab"; - WMGrabEvent *ce = static_cast<WMGrabEvent *>(e); - Q_ASSERT(ce->window == window); - mutex.lock(); - if (window) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync scene graph"; - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - static_cast<SoftwareContext::RenderContext*>(d->context)->currentWindow = window; - d->syncSceneGraph(); - - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering scene graph"; - QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize); - - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- grabbing result"; - *ce->image = static_cast<SoftwareContext::Renderer*>(d->renderer)->backingStore()->handle()->toImage(); - } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- waking gui to handle result"; - waitCondition.wakeOne(); - mutex.unlock(); - return true; - } - - case WM_RequestRepaint: - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint"; - // When GUI posts this event, it is followed by a polishAndSync, so we mustn't - // exit the event loop yet. - pendingUpdate |= RepaintRequest; - break; - - default: - break; - } - return QThread::event(e); -} - -/*! - Enters the mutex lock to make sure GUI is blocking and performs - sync, then wakes GUI. - */ -void RenderThread::sync(bool inExpose) -{ - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "sync()"; - mutex.lock(); - - Q_ASSERT_X(wm->m_lockedForSync, "RenderThread::sync()", "sync triggered on bad terms as gui is not already locked..."); - - bool current = false; - if (windowSize.width() > 0 && windowSize.height() > 0) - current = true; - if (current) { - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - static_cast<SoftwareContext::RenderContext*>(d->context)->currentWindow = window; - bool hadRenderer = d->renderer != 0; - // If the scene graph was touched since the last sync() make sure it sends the - // changed signal. - if (d->renderer) - d->renderer->clearChangedFlag(); - d->syncSceneGraph(); - if (!hadRenderer && d->renderer) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- renderer was created"; - syncResultedInChanges = true; - connect(d->renderer, SIGNAL(sceneGraphChanged()), this, SLOT(sceneGraphChanged()), Qt::DirectConnection); - } - - // Process deferred deletes now, directly after the sync as - // deleteLater on the GUI must now also have resulted in SG changes - // and the delete is a safe operation. - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); - } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window has bad size, sync aborted"; - } - - if (!inExpose) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync complete, waking Gui"; - waitCondition.wakeOne(); - mutex.unlock(); - } -} - -void RenderThread::syncAndRender() -{ - bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::enabled; - if (profileFrames) { - sinceLastTime = threadTimer.nsecsElapsed(); - threadTimer.start(); - } - - QElapsedTimer waitTimer; - waitTimer.start(); - - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "syncAndRender()"; - - syncResultedInChanges = false; - - uint pending = pendingUpdate; - pendingUpdate = 0; - - if (pending & SyncRequest) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- updatePending, doing sync"; - sync(pending == ExposeRequest); - } - - if (!syncResultedInChanges && ((pending & RepaintRequest) == 0)) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted"; - int waitTime = vsyncDelta - (int) waitTimer.elapsed(); - if (waitTime > 0) - msleep(waitTime); - return; - } - - if (profileFrames) - syncTime = threadTimer.nsecsElapsed(); - - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering started"; - - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - - if (animatorDriver->isRunning()) { - d->animationController->lock(); - animatorDriver->advance(); - d->animationController->unlock(); - } - - bool current = false; - if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0) - current = true; - if (current) { - static_cast<SoftwareContext::RenderContext*>(d->context)->currentWindow = window; - d->renderSceneGraph(windowSize); - if (profileFrames) - renderTime = threadTimer.nsecsElapsed(); - // ### used to be swappBuffers here - d->fireFrameSwapped(); - } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window not ready, skipping render"; - } - - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering done"; - - // Though it would be more correct to put this block directly after - // fireFrameSwapped in the if (current) branch above, we don't do - // that to avoid blocking the GUI thread in the case where it - // has started rendering with a bad window, causing makeCurrent to - // fail or if the window has a bad size. - if (pending == ExposeRequest) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- wake Gui after initial expose"; - waitCondition.wakeOne(); - mutex.unlock(); - } - - qCDebug(QSG_LOG_TIME_RENDERLOOP, - "Frame rendered with 'threaded' renderloop in %dms, sync=%d, render=%d, swap=%d - (on render thread)", - int(threadTimer.elapsed()), - int((syncTime/1000000)), - int((renderTime - syncTime) / 1000000), - int(threadTimer.elapsed() - renderTime / 1000000)); - - - Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRenderLoopFrame, ( - syncTime, - renderTime - syncTime, - threadTimer.nsecsElapsed() - renderTime)); -} - - - -void RenderThread::postEvent(QEvent *e) -{ - eventQueue.addEvent(e); -} - - - -void RenderThread::processEvents() -{ - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- begin processEvents()"; - while (eventQueue.hasMoreEvents()) { - QEvent *e = eventQueue.takeEvent(false); - event(e); - delete e; - } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- done processEvents()"; -} - -void RenderThread::processEventsAndWaitForMore() -{ - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- begin processEventsAndWaitForMore()"; - stopEventProcessing = false; - while (!stopEventProcessing) { - QEvent *e = eventQueue.takeEvent(true); - event(e); - delete e; - } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- done processEventsAndWaitForMore()"; -} - -void RenderThread::run() -{ - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run()"; - animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0); - animatorDriver->install(); - QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming()); - if (QQmlDebugService::isDebuggingEnabled()) - QQuickProfiler::registerAnimationCallback(); - - while (active) { - - if (window) { - static_cast<SoftwareContext::RenderContext*>(sgrc)->initializeIfNeeded(); - syncAndRender(); - } - - processEvents(); - QCoreApplication::processEvents(); - - if (active && (pendingUpdate == 0 || !window)) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "done drawing, sleep..."; - sleeping = true; - processEventsAndWaitForMore(); - sleeping = false; - } - } - - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run() completed"; - - delete animatorDriver; - animatorDriver = 0; - - sgrc->moveToThread(wm->thread()); - moveToThread(wm->thread()); -} - -ThreadedRenderLoop::ThreadedRenderLoop() - : sg(QSGContext::createDefaultContext()) - , m_animation_timer(0) -{ -#if defined(QSG_RENDER_LOOP_DEBUG) - qsgrl_timer.start(); -#endif - - m_animation_driver = sg->createAnimationDriver(this); - - m_exhaust_delay = get_env_int("QML_EXHAUST_DELAY", 5); - - connect(m_animation_driver, SIGNAL(started()), this, SLOT(animationStarted())); - connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped())); - - m_animation_driver->install(); -} - -QSGRenderContext *ThreadedRenderLoop::createRenderContext(QSGContext *sg) const -{ - return sg->createRenderContext(); -} - -void ThreadedRenderLoop::maybePostPolishRequest(Window *w) -{ - if (w->timerId == 0) { - qCDebug(QSG_LOG_RENDERLOOP) << "- posting update"; - w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer); - } -} - -QAnimationDriver *ThreadedRenderLoop::animationDriver() const -{ - return m_animation_driver; -} - -QSGContext *ThreadedRenderLoop::sceneGraphContext() const -{ - return sg; -} - -bool ThreadedRenderLoop::anyoneShowing() const -{ - for (int i=0; i<m_windows.size(); ++i) { - QQuickWindow *c = m_windows.at(i).window; - if (c->isVisible() && c->isExposed()) - return true; - } - return false; -} - -bool ThreadedRenderLoop::interleaveIncubation() const -{ - return m_animation_driver->isRunning() && anyoneShowing(); -} - -void ThreadedRenderLoop::animationStarted() -{ - qCDebug(QSG_LOG_RENDERLOOP) << "- animationStarted()"; - startOrStopAnimationTimer(); - - for (int i=0; i<m_windows.size(); ++i) - maybePostPolishRequest(const_cast<Window *>(&m_windows.at(i))); -} - -void ThreadedRenderLoop::animationStopped() -{ - qCDebug(QSG_LOG_RENDERLOOP) << "- animationStopped()"; - startOrStopAnimationTimer(); -} - - -void ThreadedRenderLoop::startOrStopAnimationTimer() -{ - int exposedWindows = 0; - Window *theOne = 0; - for (int i=0; i<m_windows.size(); ++i) { - Window &w = m_windows[i]; - if (w.window->isVisible() && w.window->isExposed()) { - ++exposedWindows; - theOne = &w; - } - } - - if (m_animation_timer != 0 && (exposedWindows == 1 || !m_animation_driver->isRunning())) { - killTimer(m_animation_timer); - m_animation_timer = 0; - // If animations are running, make sure we keep on animating - if (m_animation_driver->isRunning()) - maybePostPolishRequest(theOne); - - } else if (m_animation_timer == 0 && exposedWindows != 1 && m_animation_driver->isRunning()) { - m_animation_timer = startTimer(qsgrl_animation_interval()); - } -} - -/* - Removes this window from the list of tracked windowes in this - window manager. hide() will trigger obscure, which in turn will - stop rendering. - - This function will be called during QWindow::close() which will - also destroy the QPlatformWindow so it is important that this - triggers handleObscurity() and that rendering for that window - is fully done and over with by the time this function exits. - */ - -void ThreadedRenderLoop::hide(QQuickWindow *window) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "hide()" << window; - - if (window->isExposed()) - handleObscurity(windowFor(m_windows, window)); - - releaseResources(window); -} - - -/*! - If the window is first hide it, then perform a complete cleanup - with releaseResources which will take down the GL context and - exit the rendering thread. - */ -void ThreadedRenderLoop::windowDestroyed(QQuickWindow *window) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "begin windowDestroyed()" << window; - - Window *w = windowFor(m_windows, window); - if (!w) - return; - - handleObscurity(w); - releaseResources(w, true); - - RenderThread *thread = w->thread; - while (thread->isRunning()) - QThread::yieldCurrentThread(); - Q_ASSERT(thread->thread() == QThread::currentThread()); - delete thread; - - for (int i=0; i<m_windows.size(); ++i) { - if (m_windows.at(i).window == window) { - m_windows.removeAt(i); - break; - } - } - - qCDebug(QSG_LOG_RENDERLOOP) << "done windowDestroyed()" << window; -} - - -void ThreadedRenderLoop::exposureChanged(QQuickWindow *window) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "exposureChanged()" << window; - if (window->isExposed()) { - handleExposure(window); - } else { - Window *w = windowFor(m_windows, window); - if (w) - handleObscurity(w); - } -} - -/*! - Will post an event to the render thread that this window should - start to render. - */ -void ThreadedRenderLoop::handleExposure(QQuickWindow *window) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "handleExposure()" << window; - - Window *w = windowFor(m_windows, window); - if (!w) { - qCDebug(QSG_LOG_RENDERLOOP) << "- adding window to list"; - Window win; - win.window = window; - win.actualWindowFormat = window->format(); - win.thread = new RenderThread(this, QQuickWindowPrivate::get(window)->context); - win.timerId = 0; - win.updateDuringSync = false; - m_windows << win; - w = &m_windows.last(); - } - - // set this early as we'll be rendering shortly anyway and this avoids - // specialcasing exposure in polishAndSync. - w->thread->window = window; - - if (w->window->width() <= 0 || w->window->height() <= 0 - || !w->window->geometry().intersects(w->window->screen()->availableGeometry())) { -#ifndef QT_NO_DEBUG - qWarning("ThreadedRenderLoop: expose event received for window with invalid geometry."); -#endif - } - - // Because we are going to bind a GL context to it, make sure it - // is created. - if (!w->window->handle()) - w->window->create(); - - // Start render thread if it is not running - if (!w->thread->isRunning()) { - - qCDebug(QSG_LOG_RENDERLOOP) << "- starting render thread"; - - QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController; - if (controller->thread() != w->thread) - controller->moveToThread(w->thread); - - w->thread->active = true; - if (w->thread->thread() == QThread::currentThread()) { - w->thread->sgrc->moveToThread(w->thread); - w->thread->moveToThread(w->thread); - } - w->thread->start(); - - } else { - qCDebug(QSG_LOG_RENDERLOOP) << "- render thread already running"; - } - - polishAndSync(w, true); - qCDebug(QSG_LOG_RENDERLOOP) << "- done with handleExposure()"; - - startOrStopAnimationTimer(); -} - -/*! - This function posts an event to the render thread to remove the window - from the list of windowses to render. - - It also starts up the non-vsync animation tick if no more windows - are showing. - */ -void ThreadedRenderLoop::handleObscurity(Window *w) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "handleObscurity()" << w->window; - if (w->thread->isRunning()) { - w->thread->mutex.lock(); - w->thread->postEvent(new WMWindowEvent(w->window, WM_Obscure)); - w->thread->waitCondition.wait(&w->thread->mutex); - w->thread->mutex.unlock(); - } - startOrStopAnimationTimer(); -} - - -void ThreadedRenderLoop::maybeUpdate(QQuickWindow *window) -{ - Window *w = windowFor(m_windows, window); - if (w) - maybeUpdate(w); -} - -/*! - Called whenever the QML scene has changed. Will post an event to - ourselves that a sync is needed. - */ -void ThreadedRenderLoop::maybeUpdate(Window *w) -{ - if (!QCoreApplication::instance()) - return; - - QThread *current = QThread::currentThread(); - if (current != QCoreApplication::instance()->thread() && (current != w->thread || !m_lockedForSync)) { - qWarning() << "Updates can only be scheduled from GUI thread or from QQuickItem::updatePaintNode()"; - return; - } - - if (!w || !w->thread->isRunning()) { - return; - } - qCDebug(QSG_LOG_RENDERLOOP) << "update from item" << w->window; - - // Call this function from the Gui thread later as startTimer cannot be - // called from the render thread. - if (QThread::currentThread() == w->thread) { - qCDebug(QSG_LOG_RENDERLOOP) << "- on render thread"; - w->updateDuringSync = true; - return; - } - - maybePostPolishRequest(w); -} - -/*! - Called when the QQuickWindow should be explicitly repainted. This function - can also be called on the render thread when the GUI thread is blocked to - keep render thread animations alive. - */ -void ThreadedRenderLoop::update(QQuickWindow *window) -{ - Window *w = windowFor(m_windows, window); - if (!w) - return; - - if (w->thread == QThread::currentThread()) { - qCDebug(QSG_LOG_RENDERLOOP) << "update on window - on render thread" << w->window; - w->thread->requestRepaint(); - return; - } - - qCDebug(QSG_LOG_RENDERLOOP) << "update on window" << w->window; - w->thread->postEvent(new QEvent(WM_RequestRepaint)); - maybeUpdate(w); -} - - -void ThreadedRenderLoop::releaseResources(QQuickWindow *window) -{ - Window *w = windowFor(m_windows, window); - if (w) - releaseResources(w, false); -} - -/*! - * Release resources will post an event to the render thread to - * free up the SG and GL resources and exists the render thread. - */ -void ThreadedRenderLoop::releaseResources(Window *w, bool inDestructor) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "releaseResources()" << (inDestructor ? "in destructor" : "in api-call") << w->window; - - w->thread->mutex.lock(); - if (w->thread->isRunning() && w->thread->active) { - QQuickWindow *window = w->window; - - // The platform window might have been destroyed before - // hide/release/windowDestroyed is called, so we need to have a - // fallback surface to perform the cleanup of the scene graph - // and the OpenGL resources. - // QOffscreenSurface must be created on the GUI thread, so we - // create it here and pass it on to RenderThread::invalidateGL() - QOffscreenSurface *fallback = 0; - if (!window->handle()) { - qCDebug(QSG_LOG_RENDERLOOP) << "- using fallback surface"; - fallback = new QOffscreenSurface(); - fallback->setFormat(w->actualWindowFormat); - fallback->create(); - } - - qCDebug(QSG_LOG_RENDERLOOP) << "- posting release request to render thread"; - w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, fallback)); - w->thread->waitCondition.wait(&w->thread->mutex); - delete fallback; - } - w->thread->mutex.unlock(); -} - - -/* Calls polish on all items, then requests synchronization with the render thread - * and blocks until that is complete. Returns false if it aborted; otherwise true. - */ -void ThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "polishAndSync" << (inExpose ? "(in expose)" : "(normal)") << w->window; - - QQuickWindow *window = w->window; - if (!w->thread || !w->thread->window) { - qCDebug(QSG_LOG_RENDERLOOP) << "- not exposed, abort"; - killTimer(w->timerId); - w->timerId = 0; - return; - } - - // Flush pending touch events. - QQuickWindowPrivate::get(window)->flushDelayedTouchEvent(); - // The delivery of the event might have caused the window to stop rendering - w = windowFor(m_windows, window); - if (!w || !w->thread || !w->thread->window) { - qCDebug(QSG_LOG_RENDERLOOP) << "- removed after event flushing, abort"; - killTimer(w->timerId); - w->timerId = 0; - return; - } - - - QElapsedTimer timer; - qint64 polishTime = 0; - qint64 waitTime = 0; - qint64 syncTime = 0; - bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::enabled; - if (profileFrames) - timer.start(); - - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - d->polishItems(); - - if (profileFrames) - polishTime = timer.nsecsElapsed(); - - w->updateDuringSync = false; - - emit window->afterAnimating(); - - qCDebug(QSG_LOG_RENDERLOOP) << "- lock for sync"; - w->thread->mutex.lock(); - m_lockedForSync = true; - w->thread->postEvent(new WMSyncEvent(window, inExpose)); - - qCDebug(QSG_LOG_RENDERLOOP) << "- wait for sync"; - if (profileFrames) - waitTime = timer.nsecsElapsed(); - w->thread->waitCondition.wait(&w->thread->mutex); - m_lockedForSync = false; - w->thread->mutex.unlock(); - qCDebug(QSG_LOG_RENDERLOOP) << "- unlock after sync"; - - if (profileFrames) - syncTime = timer.nsecsElapsed(); - - killTimer(w->timerId); - w->timerId = 0; - - if (m_animation_timer == 0 && m_animation_driver->isRunning()) { - qCDebug(QSG_LOG_RENDERLOOP) << "- advancing animations"; - m_animation_driver->advance(); - qCDebug(QSG_LOG_RENDERLOOP) << "- animations done.."; - // We need to trigger another sync to keep animations running... - maybePostPolishRequest(w); - emit timeToIncubate(); - } else if (w->updateDuringSync) { - maybePostPolishRequest(w); - } - - qCDebug(QSG_LOG_TIME_RENDERLOOP()).nospace() - << "Frame prepared with 'threaded' renderloop" - << ", polish=" << (polishTime / 1000000) - << ", lock=" << (waitTime - polishTime) / 1000000 - << ", blockedForSync=" << (syncTime - waitTime) / 1000000 - << ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000 - << " - (on Gui thread) " << window; - - Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphPolishAndSync, ( - polishTime, - waitTime - polishTime, - syncTime - waitTime, - timer.nsecsElapsed() - syncTime)); -} - -ThreadedRenderLoop::Window *ThreadedRenderLoop::windowForTimer(int timerId) const -{ - for (int i=0; i<m_windows.size(); ++i) { - if (m_windows.at(i).timerId == timerId) { - return const_cast<Window *>(&m_windows.at(i)); - break; - } - } - return 0; -} - -bool ThreadedRenderLoop::event(QEvent *e) -{ - switch ((int) e->type()) { - - case QEvent::Timer: { - QTimerEvent *te = static_cast<QTimerEvent *>(e); - if (te->timerId() == m_animation_timer) { - qCDebug(QSG_LOG_RENDERLOOP) << "- ticking non-visual timer"; - m_animation_driver->advance(); - emit timeToIncubate(); - } else { - qCDebug(QSG_LOG_RENDERLOOP) << "- polish and sync timer"; - Window *w = windowForTimer(te->timerId()); - if (w) - polishAndSync(w); - else - killTimer(te->timerId()); - } - return true; - } - - default: - break; - } - - return QObject::event(e); -} - - - -/* - Locks down GUI and performs a grab the scene graph, then returns the result. - - Since the QML scene could have changed since the last time it was rendered, - we need to polish and sync the scene graph. This might seem superfluous, but - - QML changes could have triggered deleteLater() which could have removed - textures or other objects from the scene graph, causing render to crash. - - Autotests rely on grab(), setProperty(), grab(), compare behavior. - */ - -QImage ThreadedRenderLoop::grab(QQuickWindow *window) -{ - qCDebug(QSG_LOG_RENDERLOOP) << "grab()" << window; - - Window *w = windowFor(m_windows, window); - Q_ASSERT(w); - - if (!w->thread->isRunning()) - return QImage(); - - if (!window->handle()) - window->create(); - - qCDebug(QSG_LOG_RENDERLOOP) << "- polishing items"; - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - d->polishItems(); - - QImage result; - w->thread->mutex.lock(); - m_lockedForSync = true; - qCDebug(QSG_LOG_RENDERLOOP) << "- posting grab event"; - w->thread->postEvent(new WMGrabEvent(window, &result)); - w->thread->waitCondition.wait(&w->thread->mutex); - m_lockedForSync = false; - w->thread->mutex.unlock(); - - qCDebug(QSG_LOG_RENDERLOOP) << "- grab complete"; - - return result; -} - -#include "threadedrenderloop.moc" diff --git a/softwarecontext/threadedrenderloop.h b/softwarecontext/threadedrenderloop.h deleted file mode 100644 index 7e3bcb2d79..0000000000 --- a/softwarecontext/threadedrenderloop.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com> -** All rights reserved. -** For any questions to Digia, please use contact form at http://qt.digia.com -** -** This file is part of the Qt SceneGraph Raster Add-on. -** -** $QT_BEGIN_LICENSE$ -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** contact form at http://qt.digia.com -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef THREADEDRENDERLOOP_H -#define THREADEDRENDERLOOP_H - -#include <private/qsgrenderloop_p.h> - -class RenderThread; - -class ThreadedRenderLoop : public QSGRenderLoop -{ - Q_OBJECT -public: - ThreadedRenderLoop(); - - void show(QQuickWindow *) {} - void hide(QQuickWindow *); - - void windowDestroyed(QQuickWindow *window); - void exposureChanged(QQuickWindow *window); - - QImage grab(QQuickWindow *); - - void update(QQuickWindow *window); - void maybeUpdate(QQuickWindow *window); - QSGContext *sceneGraphContext() const; - QSGRenderContext *createRenderContext(QSGContext *) const; - - QAnimationDriver *animationDriver() const; - - void releaseResources(QQuickWindow *window); - - bool event(QEvent *); - - bool interleaveIncubation() const; - -public Q_SLOTS: - void animationStarted(); - void animationStopped(); - -private: - struct Window { - QQuickWindow *window; - RenderThread *thread; - QSurfaceFormat actualWindowFormat; - int timerId; - uint updateDuringSync : 1; - }; - - friend class RenderThread; - - void releaseResources(Window *window, bool inDestructor); - bool checkAndResetForceUpdate(QQuickWindow *window); - Window *windowForTimer(int timerId) const; - - bool anyoneShowing() const; - void initialize(); - - void startOrStopAnimationTimer(); - void maybePostPolishRequest(Window *w); - void waitForReleaseComplete(); - void polishAndSync(Window *w, bool inExpose = false); - void maybeUpdate(Window *window); - - void handleExposure(QQuickWindow *w); - void handleObscurity(Window *w); - - - QSGContext *sg; - QAnimationDriver *m_animation_driver; - QList<Window> m_windows; - - int m_animation_timer; - int m_exhaust_delay; - - bool m_lockedForSync; -}; - -#endif // THREADEDRENDERLOOP_H |