QQuickCanvas renames
[profile/ivi/qtdeclarative.git] / src / quick / items / context2d / qquickcontext2d.cpp
index 11bc8ea..2a99a2e 100644 (file)
 #include <qqmlengine.h>
 #include <private/qv8domerrors_p.h>
 #include <QtCore/qnumeric.h>
+#include <private/qquickwindow_p.h>
+#include <private/qquickwindowmanager_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
 
 #ifdef Q_OS_QNX
 #include <ctype.h>
@@ -70,6 +74,7 @@ QT_BEGIN_NAMESPACE
 /*!
     \qmlclass Context2D QQuickContext2D
     \inqmlmodule QtQuick 2
+    \ingroup qtquick-canvas
     \since QtQuick 2.0
     \brief Provides 2D context for shapes on a Canvas item
 
@@ -1200,7 +1205,7 @@ static v8::Handle<v8::Value> ctx2d_createPattern(const v8::Arguments &args)
                     patternTexture = pixelData->image;
                 }
             } else {
-                patternTexture = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
+                patternTexture = r->context->createPixmap(QUrl(engine->toString(args[0]->ToString())))->image();
             }
 
             if (!patternTexture.isNull()) {
@@ -1979,16 +1984,22 @@ static v8::Handle<v8::Value> ctx2d_isPointInPath(const v8::Arguments &args)
 
 static v8::Handle<v8::Value> ctx2d_drawFocusRing(const v8::Arguments &args)
 {
+    Q_UNUSED(args);
+
     V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
 }
 
 static v8::Handle<v8::Value> ctx2d_setCaretSelectionRect(const v8::Arguments &args)
 {
+    Q_UNUSED(args);
+
     V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
 }
 
 static v8::Handle<v8::Value> ctx2d_caretBlinkRate(const v8::Arguments &args)
 {
+    Q_UNUSED(args);
+
     V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::caretBlinkRate is not supported");
 }
 // text
@@ -2195,6 +2206,7 @@ static v8::Handle<v8::Value> ctx2d_strokeText(const v8::Arguments &args)
   \qmlclass TextMetrics
     \inqmlmodule QtQuick 2
     \since QtQuick 2.0
+    \ingroup qtquick-canvas
     \brief Provides a Context2D TextMetrics interface
 
     The TextMetrics object can be created by QtQuick2::Context2D::measureText method.
@@ -2272,7 +2284,7 @@ static v8::Handle<v8::Value> ctx2d_measureText(const v8::Arguments &args)
 /*!
   \qmlmethod QtQuick2::Context2D::drawImage(variant image, real sx, real sy, real sw, sh, real dx, real dy, real dw, dh)
   This is an overloaded function.
-  Draws the given item as \a image from source point (\a sx, \a sy) and source width \sw, source height \sh
+  Draws the given item as \a image from source point (\a sx, \a sy) and source width \a sw, source height \a sh
   onto the canvas at point (\a dx, \a dy) and with width \a dw, height \a dh.
 
 
@@ -2305,44 +2317,51 @@ static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args)
     if (!r->context->state.invertibleCTM)
         return args.This();
 
-    QImage image;
+    QQmlRefPointer<QQuickCanvasPixmap> pixmap;
+
     if (args[0]->IsString()) {
         QUrl url(engine->toString(args[0]->ToString()));
         if (!url.isValid())
             V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
 
-        image = r->context->createImage(url);
+        pixmap = r->context->createPixmap(url);
     } else if (args[0]->IsObject()) {
         QQuickImage *imageItem = qobject_cast<QQuickImage*>(engine->toQObject(args[0]->ToObject()));
         QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(engine->toQObject(args[0]->ToObject()));
 
         QV8Context2DPixelArrayResource *pix = v8_resource_cast<QV8Context2DPixelArrayResource>(args[0]->ToObject()->GetInternalField(0)->ToObject());
-        if (pix) {
-            image = pix->image;
+        if (pix && !pix->image.isNull()) {
+            pixmap.take(new QQuickCanvasPixmap(pix->image, r->context->canvas()->window()));
         } else if (imageItem) {
-            image = imageItem->image();
+            pixmap.take(r->context->createPixmap(imageItem->source()));
         } else if (canvas) {
-            image = canvas->toImage();
+            QImage img = canvas->toImage();
+            if (!img.isNull())
+                pixmap.take(new QQuickCanvasPixmap(img, canvas->window()));
         } else {
             V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
         }
     } else {
         V8THROW_DOM(DOMEXCEPTION_TYPE_MISMATCH_ERR, "drawImage(), type mismatch");
     }
+
+    if (pixmap.isNull() || !pixmap->isValid())
+        return args.This();
+
     if (args.Length() == 3) {
         dx = args[1]->NumberValue();
         dy = args[2]->NumberValue();
         sx = 0;
         sy = 0;
-        sw = image.width();
-        sh = image.height();
+        sw = pixmap->width();
+        sh = pixmap->height();
         dw = sw;
         dh = sh;
     } else if (args.Length() == 5) {
         sx = 0;
         sy = 0;
-        sw = image.width();
-        sh = image.height();
+        sw = pixmap->width();
+        sh = pixmap->height();
         dx = args[1]->NumberValue();
         dy = args[2]->NumberValue();
         dw = args[3]->NumberValue();
@@ -2370,16 +2389,18 @@ static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args)
      || !qIsFinite(dh))
         return args.This();
 
-    if (!image.isNull()) {
-        if (sx < 0 || sy < 0 || sw == 0 || sh == 0
-         || sx + sw > image.width() || sy + sh > image.height()
-         || sx + sw < 0 || sy + sh < 0) {
+    if (sx < 0
+    || sy < 0
+    || sw == 0
+    || sh == 0
+    || sx + sw > pixmap->width()
+    || sy + sh > pixmap->height()
+    || sx + sw < 0 || sy + sh < 0) {
             V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "drawImage(), index size error");
-        }
-
-        r->context->buffer()->drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
     }
 
+    r->context->buffer()->drawPixmap(pixmap, QRectF(sx, sy, sw, sh), QRectF(dx, dy, dw, dh));
+
     return args.This();
 }
 
@@ -2387,6 +2408,7 @@ static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args)
 /*!
     \qmlclass CanvasImageData
     \inqmlmodule QtQuick 2
+    \ingroup qtquick-canvas
     \brief Contains image pixel data in RGBA order
 
      The \a QtQuick2::CanvasImageData object holds the image pixel data.
@@ -2439,6 +2461,7 @@ v8::Handle<v8::Value> ctx2d_imageData_data(v8::Local<v8::String>, const v8::Acce
 /*!
     \qmlclass CanvasPixelArray
     \inqmlmodule QtQuick 2
+    \ingroup qtquick-canvas
     \brief Provides ordered and indexed access to the components of each pixel in image data
 
   The CanvasPixelArray object provides ordered, indexed access to the color components of each pixel of the image data.
@@ -2547,7 +2570,7 @@ static v8::Handle<v8::Value> ctx2d_createImageData(const v8::Arguments &args)
                 return qt_create_image_data(w, h, engine, QImage());
             }
         } else if (args[0]->IsString()) {
-            QImage image = r->context->createImage(QUrl(engine->toString(args[0]->ToString())));
+            QImage image = r->context->createPixmap(QUrl(engine->toString(args[0]->ToString())))->image();
             return qt_create_image_data(image.width(), image.height(), engine, image);
         }
     } else if (args.Length() == 2) {
@@ -2669,7 +2692,7 @@ static v8::Handle<v8::Value> ctx2d_putImageData(const v8::Arguments &args)
         }
 
         QImage image = pixelArray->image.copy(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
-        r->context->buffer()->drawImage(image, dirtyX, dirtyY, dirtyWidth, dirtyHeight, dx, dy, dirtyWidth, dirtyHeight);
+        r->context->buffer()->drawImage(image, QRectF(dirtyX, dirtyY, dirtyWidth, dirtyHeight), QRectF(dx, dy, dirtyWidth, dirtyHeight));
     }
     return args.This();
 }
@@ -2678,6 +2701,7 @@ static v8::Handle<v8::Value> ctx2d_putImageData(const v8::Arguments &args)
     \qmlclass CanvasGradient
     \inqmlmodule QtQuick 2
     \since QtQuick 2.0
+    \ingroup qtquick-canvas
     \brief Provides an opaque CanvasGradient interface
   */
 
@@ -2893,7 +2917,7 @@ void QQuickContext2D::fillRect(qreal x, qreal y, qreal w, qreal h)
     if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
         return;
 
-    buffer()->fillRect(x, y, w, h);
+    buffer()->fillRect(QRectF(x, y, w, h));
 }
 
 void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
@@ -2904,7 +2928,7 @@ void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
     if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
         return;
 
-    buffer()->strokeRect(x, y, w, h);
+    buffer()->strokeRect(QRectF(x, y, w, h));
 }
 
 void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h)
@@ -2915,7 +2939,7 @@ void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h)
     if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
         return;
 
-    buffer()->clearRect(x, y, w, h);
+    buffer()->clearRect(QRectF(x, y, w, h));
 }
 
 void QQuickContext2D::drawText(const QString& text, qreal x, qreal y, bool fill)
@@ -3241,9 +3265,9 @@ static int textAlignOffset(QQuickContext2D::TextAlignType value, const QFontMetr
 }
 
 
-QImage QQuickContext2D::createImage(const QUrl& url)
+QQmlRefPointer<QQuickCanvasPixmap> QQuickContext2D::createPixmap(const QUrl& url)
 {
-    return m_canvas->loadedImage(url);
+    return m_canvas->loadedPixmap(url);
 }
 
 QPainterPath QQuickContext2D::createTextGlyphs(qreal x, qreal y, const QString& text)
@@ -3319,6 +3343,9 @@ QQuickContext2D::QQuickContext2D(QObject *parent)
     : QQuickCanvasContext(parent)
     , m_buffer(new QQuickContext2DCommandBuffer)
     , m_v8engine(0)
+    , m_windowManager(0)
+    , m_surface(0)
+    , m_glContext(0)
 {
 }
 
@@ -3344,11 +3371,8 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
     m_canvas = canvasItem;
     m_renderTarget = canvasItem->renderTarget();
 
-    // For the FBO target we only (currently) support Cooperative
-    if (m_renderTarget == QQuickCanvasItem::FramebufferObject) {
-        canvasItem->setRenderStrategy(QQuickCanvasItem::Cooperative);
-    }
-
+    QQuickWindow *window = canvasItem->window();
+    m_windowManager =  QQuickWindowPrivate::get(window)->windowManager;
     m_renderStrategy = canvasItem->renderStrategy();
 
     switch (m_renderTarget) {
@@ -3356,7 +3380,12 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
         m_texture = new QQuickContext2DImageTexture(m_renderStrategy == QQuickCanvasItem::Threaded);
         break;
     case QQuickCanvasItem::FramebufferObject:
+    {
         m_texture = new QQuickContext2DFBOTexture;
+        // No BufferQueueingOpenGL, falls back to Cooperative mode
+        if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL))
+            m_renderStrategy = QQuickCanvasItem::Cooperative;
+    }
         break;
     }
 
@@ -3366,6 +3395,24 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
     m_texture->setCanvasSize(canvasItem->canvasSize().toSize());
     m_texture->setSmooth(canvasItem->smooth());
 
+    QThread *renderThread = QThread::currentThread();
+    QThread *sceneGraphThread = window->openglContext() ? window->openglContext()->thread() : 0;
+
+    if (m_renderStrategy == QQuickCanvasItem::Threaded)
+        renderThread = QQuickContext2DRenderThread::instance(qmlEngine(canvasItem));
+    else if (m_renderStrategy == QQuickCanvasItem::Cooperative)
+        renderThread = sceneGraphThread;
+
+    if (m_renderTarget == QQuickCanvasItem::FramebufferObject && renderThread != sceneGraphThread) {
+         QOpenGLContext *cc = QQuickWindowPrivate::get(window)->context->glContext();
+         m_surface = window;
+         m_glContext = new QOpenGLContext;
+         m_glContext->setFormat(cc->format());
+         m_glContext->setShareContext(cc);
+         if (renderThread != QThread::currentThread())
+             m_glContext->moveToThread(renderThread);
+    }
+
     connect(m_texture, SIGNAL(textureChanged()), SIGNAL(textureChanged()));
 
     reset();
@@ -3622,7 +3669,7 @@ void QQuickContext2D::reset()
     m_stateStack.clear();
     m_stateStack.push(newState);
     popState();
-    m_buffer->clearRect(0, 0, m_canvas->width(), m_canvas->height());
+    m_buffer->clearRect(QRectF(0, 0, m_canvas->width(), m_canvas->height()));
 }
 
 void QQuickContext2D::setV8Engine(QV8Engine *engine)