Refactor context2d thread logic
[profile/ivi/qtdeclarative.git] / src / quick / items / context2d / qquickcontext2dcommandbuffer.cpp
index 591fc21..47f7e1a 100644 (file)
 #include "qquickcanvasitem_p.h"
 #include <qqml.h>
 #include <QtCore/QMutex>
+#include <QtQuick/qsgtexture.h>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QPaintEngine>
+#include <QtGui/private/qopenglpaintengine_p.h>
 
 #define HAS_SHADOW(offsetX, offsetY, blur, color) (color.isValid() && color.alpha() && (blur || offsetX || offsetY))
 
@@ -229,6 +233,44 @@ void QQuickContext2DCommandBuffer::setPainterState(QPainter* p, const QQuickCont
        p->setCompositionMode(state.globalCompositeOperation);
 }
 
+static void qt_drawImage(QPainter *p, QQuickContext2D::State& state, QImage image, const QRectF& sr, const QRectF& dr, bool shadow = false)
+{
+    Q_ASSERT(p);
+
+    if (image.isNull())
+        return;
+
+    qreal sx = sr.x();
+    qreal sy = sr.y();
+    qreal sw = sr.width();
+    qreal sh = sr.height();
+    qreal dx = dr.x();
+    qreal dy = dr.y();
+    qreal dw = dr.width();
+    qreal dh = dr.height();
+
+    if (sw == -1 || sh == -1) {
+        sw = image.width();
+        sh = image.height();
+    }
+    if (sx != 0 || sy != 0 || sw != image.width() || sh != image.height())
+        image = image.copy(sx, sy, sw, sh);
+
+    if (sw != dw || sh != dh)
+        image = image.scaled(dw, dh);
+
+    if (shadow) {
+        QImage shadow = makeShadowImage(image, state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor);
+        qreal shadow_dx = dx + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
+        qreal shadow_dy = dy + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
+        p->drawImage(shadow_dx, shadow_dy, shadow);
+    }
+    //Strange OpenGL painting behavior here, without beginNativePainting/endNativePainting, only the first image is painted.
+    p->beginNativePainting();
+    p->drawImage(dx, dy, image);
+    p->endNativePainting();
+}
+
 void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& state)
 {
     if (!p)
@@ -236,7 +278,7 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
 
     reset();
 
-    QTransform originMatrix = p->transform();
+    QTransform originMatrix = p->worldTransform();
 
     QPen pen = makePen(state);
     setPainterState(p, state, pen);
@@ -247,7 +289,7 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
         case QQuickContext2D::UpdateMatrix:
         {
             state.matrix = takeMatrix();
-            p->setTransform(state.matrix * originMatrix);
+            p->setWorldTransform(state.matrix * originMatrix);
             break;
         }
         case QQuickContext2D::ClearRect:
@@ -303,36 +345,42 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
             state.strokeStyle = takeStrokeStyle();
             state.strokePatternRepeatX = takeBool();
             state.strokePatternRepeatY = takeBool();
-            pen.setBrush(state.strokeStyle);
-            p->setPen(pen);
+            QPen nPen = p->pen();
+            nPen.setBrush(state.strokeStyle);
+            p->setPen(nPen);
             break;
         }
         case QQuickContext2D::LineWidth:
         {
             state.lineWidth = takeLineWidth();
-            pen.setWidth(state.lineWidth);
-            p->setPen(pen);
+            QPen nPen = p->pen();
+
+            nPen.setWidthF(state.lineWidth);
+            p->setPen(nPen);
             break;
         }
         case QQuickContext2D::LineCap:
         {
             state.lineCap = takeLineCap();
-            pen.setCapStyle(state.lineCap);
-            p->setPen(pen);
+            QPen nPen = p->pen();
+            nPen.setCapStyle(state.lineCap);
+            p->setPen(nPen);
             break;
         }
         case QQuickContext2D::LineJoin:
         {
             state.lineJoin = takeLineJoin();
-            pen.setJoinStyle(state.lineJoin);
-            p->setPen(pen);
+            QPen nPen = p->pen();
+            nPen.setJoinStyle(state.lineJoin);
+            p->setPen(nPen);
             break;
         }
         case QQuickContext2D::MiterLimit:
         {
             state.miterLimit = takeMiterLimit();
-            pen.setMiterLimit(state.miterLimit);
-            p->setPen(pen);
+            QPen nPen = p->pen();
+            nPen.setMiterLimit(state.miterLimit);
+            p->setPen(nPen);
             break;
         }
         case QQuickContext2D::TextAlign:
@@ -377,33 +425,51 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
         }
         case QQuickContext2D::DrawImage:
         {
-            qreal sx = takeReal();
-            qreal sy = takeReal();
-            qreal sw = takeReal();
-            qreal sh = takeReal();
-            qreal dx = takeReal();
-            qreal dy = takeReal();
-            qreal dw = takeReal();
-            qreal dh = takeReal();
-            QImage image = takeImage();
-
-            if (!image.isNull()) {
-                if (sw == -1 || sh == -1) {
-                    sw = image.width();
-                    sh = image.height();
-                }
-                if (sx != 0 || sy != 0 || sw != image.width() || sh != image.height())
-                    image = image.copy(sx, sy, sw, sh);
-
-                image = image.scaled(dw, dh);
-
-                if (HAS_SHADOW(state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor)) {
-                    QImage shadow = makeShadowImage(image, state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor);
-                    qreal shadow_dx = dx + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
-                    qreal shadow_dy = dy + (state.shadowOffsetX < 0? state.shadowOffsetY:0);
-                    p->drawImage(shadow_dx, shadow_dy, shadow);
+            QRectF sr = takeRect();
+            QRectF dr = takeRect();
+            qt_drawImage(p, state, takeImage(), sr, dr, HAS_SHADOW(state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor));
+            break;
+        }
+        case QQuickContext2D::DrawPixmap:
+        {
+            QRectF sr = takeRect();
+            QRectF dr = takeRect();
+
+            QQmlRefPointer<QQuickCanvasPixmap> pix = takePixmap();
+            Q_ASSERT(!pix.isNull());
+
+            const bool hasShadow = HAS_SHADOW(state.shadowOffsetX, state.shadowOffsetY, state.shadowBlur, state.shadowColor);
+            if (p->paintEngine()->type() != QPaintEngine::OpenGL2 || hasShadow){
+                //TODO: generate shadow blur with shaders
+                qt_drawImage(p, state, pix->image(), sr, dr, hasShadow);
+            } else if (pix->texture()){
+                QSGTexture *tex = pix->texture();
+                QSGDynamicTexture *dynamicTexture = qobject_cast<QSGDynamicTexture *>(tex);
+                if (dynamicTexture)
+                    dynamicTexture->updateTexture();
+
+                if (tex->textureId()) {
+
+                    if (sr.width() < 0)
+                        sr.setWidth(tex->textureSize().width());
+                    if (sr.height() < 0)
+                        sr.setHeight(tex->textureSize().height());
+
+                    if (dr.width() < 0)
+                        dr.setWidth(sr.width());
+                    if (dr.height() < 0)
+                        dr.setHeight(sr.height());
+
+                    qreal srBottom = sr.bottom();
+                    sr.setBottom(sr.top());
+                    sr.setTop(srBottom);
+
+                    tex->bind();
+                    if (p->paintEngine()->type() == QPaintEngine::OpenGL2) {
+                        QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx *>(p->paintEngine());
+                        engine->drawTexture(dr, tex->textureId(), tex->textureSize(), sr);
+                    }
                 }
-                p->drawImage(dx, dy, image);
             }
             break;
         }
@@ -425,12 +491,19 @@ QQuickContext2DCommandBuffer::QQuickContext2DCommandBuffer()
     , intIdx(0)
     , boolIdx(0)
     , realIdx(0)
+    , rectIdx(0)
     , colorIdx(0)
     , matrixIdx(0)
     , brushIdx(0)
     , pathIdx(0)
     , imageIdx(0)
+    , pixmapIdx(0)
 {
+    static bool registered = false;
+    if (!registered) {
+        qRegisterMetaType<QQuickContext2DCommandBuffer*>("QQuickContext2DCommandBuffer*");
+        registered = true;
+    }
 }
 
 
@@ -444,11 +517,13 @@ void QQuickContext2DCommandBuffer::clear()
     ints.clear();
     bools.clear();
     reals.clear();
+    rects.clear();
     colors.clear();
     matrixes.clear();
     brushes.clear();
     pathes.clear();
     images.clear();
+    pixmaps.clear();
     reset();
 }
 
@@ -458,12 +533,13 @@ void QQuickContext2DCommandBuffer::reset()
     intIdx = 0;
     boolIdx = 0;
     realIdx = 0;
+    rectIdx = 0;
     colorIdx = 0;
     matrixIdx = 0;
     brushIdx = 0;
     pathIdx = 0;
     imageIdx = 0;
+    pixmapIdx = 0;
 }
 
 QT_END_NAMESPACE
-