aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCharles Yin <charles.yin@nokia.com>2012-06-04 16:34:17 +1000
committerQt by Nokia <qt-info@nokia.com>2012-06-05 12:32:58 +0200
commit1dcfa8aa2ae6460f26d9843c197532024447e43b (patch)
tree10b5243607d603443a4abe9f89e2a453757ffaeb /src
parent332fe582d1bd590b59618cc7b732be9bf7f9f475 (diff)
Introduce QQuickCanvasPixmap
1. QQuickPixmap now only store textures instead of QImage data, however context2d still need to access the QImage in some places, so cache the loaded images to avoid the expensive GL readback operations. 2. Use texture directly if the render target is FBO. Change-Id: I6228011e5698fa00f2e3420a3a4a305995b8a238 Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp109
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h37
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp67
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h3
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp121
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h40
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp2
7 files changed, 271 insertions, 108 deletions
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 7d2a85cb35..9b2bc43db5 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -53,6 +53,73 @@
QT_BEGIN_NAMESPACE
+QQuickCanvasPixmap::QQuickCanvasPixmap(const QImage& image, QQuickCanvas *canvas)
+ : m_pixmap(0)
+ , m_image(image)
+ , m_texture(0)
+ , m_canvas(canvas)
+{
+
+}
+
+QQuickCanvasPixmap::QQuickCanvasPixmap(QQuickPixmap *pixmap, QQuickCanvas *canvas)
+ : m_pixmap(pixmap)
+ , m_texture(0)
+ , m_canvas(canvas)
+{
+
+}
+
+QQuickCanvasPixmap::~QQuickCanvasPixmap()
+{
+ delete m_pixmap;
+ if (m_texture)
+ m_texture->deleteLater();
+}
+
+qreal QQuickCanvasPixmap::width() const
+{
+ if (m_pixmap)
+ return m_pixmap->width();
+
+ return m_image.width();
+}
+
+qreal QQuickCanvasPixmap::height() const
+{
+ if (m_pixmap)
+ return m_pixmap->height();
+
+ return m_image.height();
+}
+
+bool QQuickCanvasPixmap::isValid() const
+{
+ if (m_pixmap)
+ return m_pixmap->isReady();
+ return !m_image.isNull();
+}
+
+QSGTexture *QQuickCanvasPixmap::texture()
+{
+ if (!m_texture) {
+ if (m_pixmap) {
+ Q_ASSERT(m_pixmap->textureFactory());
+ m_texture = m_pixmap->textureFactory()->createTexture(m_canvas);
+ } else {
+ m_texture = QQuickCanvasPrivate::get(m_canvas)->context->createTexture(m_image);
+ }
+ }
+ return m_texture;
+}
+QImage QQuickCanvasPixmap::image()
+{
+ if (m_image.isNull() && m_pixmap)
+ m_image = m_pixmap->image();
+
+ return m_image;
+}
+
QHash<QQmlEngine *,QQuickContext2DRenderThread*> QQuickContext2DRenderThread::renderThreads;
QMutex QQuickContext2DRenderThread::renderThreadsMutex;
@@ -95,7 +162,7 @@ class QQuickCanvasItemPrivate : public QQuickItemPrivate
public:
QQuickCanvasItemPrivate();
~QQuickCanvasItemPrivate();
- QQuickCanvasContext* context;
+ QQuickCanvasContext *context;
QSizeF canvasSize;
QSize tileSize;
QRectF canvasWindow;
@@ -108,7 +175,7 @@ public:
QQuickCanvasItem::RenderTarget renderTarget;
QQuickCanvasItem::RenderStrategy renderStrategy;
QString contextType;
- QHash<QUrl, QQuickPixmap*> images;
+ QHash<QUrl, QQmlRefPointer<QQuickCanvasPixmap> > pixmaps;
QUrl baseUrl;
QMap<int, v8::Persistent<v8::Function> > animationCallbacks;
};
@@ -130,7 +197,7 @@ QQuickCanvasItemPrivate::QQuickCanvasItemPrivate()
QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
{
- qDeleteAll(images);
+ pixmaps.clear();
}
@@ -785,18 +852,14 @@ bool QQuickCanvasItem::save(const QString &filename) const
return toImage().save(url.toLocalFile());
}
-QImage QQuickCanvasItem::loadedImage(const QUrl& url)
+QQmlRefPointer<QQuickCanvasPixmap> QQuickCanvasItem::loadedPixmap(const QUrl& url)
{
Q_D(QQuickCanvasItem);
QUrl fullPathUrl = d->baseUrl.resolved(url);
- if (!d->images.contains(fullPathUrl)) {
+ if (!d->pixmaps.contains(fullPathUrl)) {
loadImage(url);
}
- QQuickPixmap* pix = d->images.value(fullPathUrl);
- if (pix->isLoading() || pix->isError()) {
- return QImage();
- }
- return pix->image();
+ return d->pixmaps.value(fullPathUrl);
}
/*!
@@ -814,9 +877,11 @@ void QQuickCanvasItem::loadImage(const QUrl& url)
{
Q_D(QQuickCanvasItem);
QUrl fullPathUrl = d->baseUrl.resolved(url);
- if (!d->images.contains(fullPathUrl)) {
+ if (!d->pixmaps.contains(fullPathUrl)) {
QQuickPixmap* pix = new QQuickPixmap();
- d->images.insert(fullPathUrl, pix);
+ QQmlRefPointer<QQuickCanvasPixmap> canvasPix;
+ canvasPix.take(new QQuickCanvasPixmap(pix, d->canvas));
+ d->pixmaps.insert(fullPathUrl, canvasPix);
pix->load(qmlEngine(this)
, fullPathUrl
@@ -838,11 +903,7 @@ void QQuickCanvasItem::loadImage(const QUrl& url)
void QQuickCanvasItem::unloadImage(const QUrl& url)
{
Q_D(QQuickCanvasItem);
- QUrl removeThis = d->baseUrl.resolved(url);
- if (d->images.contains(removeThis)) {
- delete d->images.value(removeThis);
- d->images.remove(removeThis);
- }
+ d->pixmaps.remove(d->baseUrl.resolved(url));
}
/*!
@@ -855,8 +916,8 @@ bool QQuickCanvasItem::isImageError(const QUrl& url) const
{
Q_D(const QQuickCanvasItem);
QUrl fullPathUrl = d->baseUrl.resolved(url);
- return d->images.contains(fullPathUrl)
- && d->images.value(fullPathUrl)->isError();
+ return d->pixmaps.contains(fullPathUrl)
+ && d->pixmaps.value(fullPathUrl)->pixmap()->isError();
}
/*!
@@ -869,8 +930,8 @@ bool QQuickCanvasItem::isImageLoading(const QUrl& url) const
{
Q_D(const QQuickCanvasItem);
QUrl fullPathUrl = d->baseUrl.resolved(url);
- return d->images.contains(fullPathUrl)
- && d->images.value(fullPathUrl)->isLoading();
+ return d->pixmaps.contains(fullPathUrl)
+ && d->pixmaps.value(fullPathUrl)->pixmap()->isLoading();
}
/*!
\qmlmethod void QtQuick2::Canvas::isImageLoaded(url image)
@@ -882,8 +943,8 @@ bool QQuickCanvasItem::isImageLoaded(const QUrl& url) const
{
Q_D(const QQuickCanvasItem);
QUrl fullPathUrl = d->baseUrl.resolved(url);
- return d->images.contains(fullPathUrl)
- && d->images.value(fullPathUrl)->isReady();
+ return d->pixmaps.contains(fullPathUrl)
+ && d->pixmaps.value(fullPathUrl)->pixmap()->isReady();
}
QImage QQuickCanvasItem::toImage(const QRectF& rect) const
@@ -1013,4 +1074,4 @@ QRect QQuickCanvasItem::tiledRect(const QRectF &window, const QSize &tileSize)
the Canvas has been rendered.
*/
-QT_END_NAMESPACE
+QT_END_NAMESPACE \ No newline at end of file
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index 8e7b992387..090c763e46 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -45,6 +45,7 @@
#include <QtQuick/qquickitem.h>
#include <private/qv8engine_p.h>
#include <QtCore/QThread>
+#include <QtGui/QImage>
QT_BEGIN_HEADER
@@ -53,15 +54,40 @@ QT_BEGIN_NAMESPACE
class QQuickCanvasContext;
class QQuickCanvasItemPrivate;
+class QSGTexture;
+class QQuickPixmap;
+
+class QQuickCanvasPixmap : public QQmlRefCount
+{
+public:
+ QQuickCanvasPixmap(const QImage& image, QQuickCanvas *canvas);
+ QQuickCanvasPixmap(QQuickPixmap *pixmap, QQuickCanvas *canvas);
+ ~QQuickCanvasPixmap();
+
+ QSGTexture *texture();
+ QImage image();
+
+ qreal width() const;
+ qreal height() const;
+ bool isValid() const;
+ QQuickPixmap *pixmap() const { return m_pixmap;}
+
+private:
+ QQuickPixmap *m_pixmap;
+ QImage m_image;
+ QSGTexture *m_texture;
+ QQuickCanvas *m_canvas;
+};
+
class QQuickCanvasItem : public QQuickItem
{
Q_OBJECT
Q_ENUMS(RenderTarget)
Q_ENUMS(RenderStrategy)
- Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged);
+ Q_PROPERTY(bool available READ isAvailable NOTIFY availableChanged)
Q_PROPERTY(QString contextType READ contextType WRITE setContextType NOTIFY contextTypeChanged)
- Q_PROPERTY(QQmlV8Handle context READ context NOTIFY contextChanged);
+ Q_PROPERTY(QQmlV8Handle context READ context NOTIFY contextChanged)
Q_PROPERTY(QSizeF canvasSize READ canvasSize WRITE setCanvasSize NOTIFY canvasSizeChanged)
Q_PROPERTY(QSize tileSize READ tileSize WRITE setTileSize NOTIFY tileSizeChanged)
Q_PROPERTY(QRectF canvasWindow READ canvasWindow WRITE setCanvasWindow NOTIFY canvasWindowChanged)
@@ -105,7 +131,7 @@ public:
RenderStrategy renderStrategy() const;
void setRenderStrategy(RenderStrategy strategy);
- QQuickCanvasContext* rawContext() const;
+ QQuickCanvasContext *rawContext() const;
QImage toImage(const QRectF& rect = QRectF()) const;
@@ -119,7 +145,7 @@ public:
Q_INVOKABLE bool save(const QString &filename) const;
Q_INVOKABLE QString toDataURL(const QString& type = QLatin1String("image/png")) const;
- QImage loadedImage(const QUrl& url);
+ QQmlRefPointer<QQuickCanvasPixmap> loadedPixmap(const QUrl& url);
Q_SIGNALS:
void paint(const QRect &region);
@@ -154,7 +180,6 @@ protected:
private:
Q_DECLARE_PRIVATE(QQuickCanvasItem)
-
Q_INVOKABLE void delayedCreate();
bool createContext(const QString &contextType);
void initializeContext(QQuickCanvasContext *context, const QVariantMap &args = QVariantMap());
@@ -184,4 +209,4 @@ QML_DECLARE_TYPE(QQuickCanvasItem)
QT_END_HEADER
-#endif //QQUICKCANVASITEM_P_H
+#endif //QQUICKCANVASITEM_P_H \ No newline at end of file
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 637377bab8..c171bab50b 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -1204,7 +1204,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()) {
@@ -1983,16 +1983,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
@@ -2309,44 +2315,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()->canvas()));
} 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->canvas()));
} 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();
@@ -2374,16 +2387,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();
}
@@ -2551,7 +2566,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) {
@@ -2673,7 +2688,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();
}
@@ -2897,7 +2912,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)
@@ -2908,7 +2923,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)
@@ -2919,7 +2934,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)
@@ -3245,9 +3260,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)
@@ -3649,7 +3664,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)
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 22addf33a8..e2952ca580 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -109,6 +109,7 @@ public:
FillText,
StrokeText,
DrawImage,
+ DrawPixmap,
GetImageData
};
@@ -223,7 +224,7 @@ public:
bool isPointInPath(qreal x, qreal y) const;
QPainterPath createTextGlyphs(qreal x, qreal y, const QString& text);
- QImage createImage(const QUrl& url);
+ QQmlRefPointer<QQuickCanvasPixmap> createPixmap(const QUrl& url);
QOpenGLContext *glContext() { return m_glContext; }
QSurface *surface() { return m_surface; }
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 6f20b699c9..d231609151 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -43,6 +43,10 @@
#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)
@@ -383,37 +425,49 @@ 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();
+ QOpenGL2PaintEngineEx *engine = dynamic_cast<QOpenGL2PaintEngineEx *>(p->paintEngine());
+ engine->drawTexture(dr, tex->textureId(), tex->textureSize(), sr);
}
-
- //Strange OpenGL painting behavior here, without beginNativePainting/endNativePainting, only the first image is painted.
- p->beginNativePainting();
- p->drawImage(dx, dy, image);
- p->endNativePainting();
}
break;
}
@@ -435,11 +489,13 @@ QQuickContext2DCommandBuffer::QQuickContext2DCommandBuffer()
, intIdx(0)
, boolIdx(0)
, realIdx(0)
+ , rectIdx(0)
, colorIdx(0)
, matrixIdx(0)
, brushIdx(0)
, pathIdx(0)
, imageIdx(0)
+ , pixmapIdx(0)
{
}
@@ -454,11 +510,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();
}
@@ -468,12 +526,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
-
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index f33c43a936..ddf5ba14e4 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -44,8 +44,6 @@
#include <QtCore/qmutex.h>
#include "qquickcontext2d_p.h"
-#include <QtQuick/private/qquickpixmapcache_p.h>
-
QT_BEGIN_HEADER
@@ -98,11 +96,18 @@ public:
bools << repeatX << repeatY;
}
- inline void drawImage(const QImage& image, qreal sx, qreal sy, qreal sw, qreal sh, qreal dx, qreal dy, qreal dw, qreal dh)
+ inline void drawImage(const QImage& image, const QRectF& sr, const QRectF& dr)
{
commands << QQuickContext2D::DrawImage;
images << image;
- reals << sx << sy << sw << sh << dx << dy << dw << dh;
+ rects << sr << dr;
+ }
+
+ inline void drawPixmap(QQmlRefPointer<QQuickCanvasPixmap> pixmap, const QRectF& sr, const QRectF& dr)
+ {
+ commands << QQuickContext2D::DrawPixmap;
+ pixmaps << pixmap;
+ rects << sr << dr;
}
inline qreal takeShadowOffsetX() { return takeReal(); }
@@ -117,22 +122,22 @@ public:
matrixes << matrix;
}
- inline void clearRect(qreal x, qreal y, qreal w, qreal h)
+ inline void clearRect(const QRectF& r)
{
commands << QQuickContext2D::ClearRect;
- reals << x << y << w << h;
+ rects << r;
}
- inline void fillRect(qreal x, qreal y, qreal w, qreal h)
+ inline void fillRect(const QRectF& r)
{
commands << QQuickContext2D::FillRect;
- reals << x << y << w << h;
+ rects << r;
}
- inline void strokeRect(qreal x, qreal y, qreal w, qreal h)
+ inline void strokeRect(const QRectF& r)
{
QPainterPath p;
- p.addRect(x, y, w, h);
+ p.addRect(r);
commands << QQuickContext2D::Stroke;
pathes << p;
@@ -218,19 +223,12 @@ public:
inline QTransform takeMatrix() { return matrixes[matrixIdx++]; }
- // rects
- inline QRectF takeRect() {
- qreal x, y, w, h;
- x = takeReal();
- y = takeReal();
- w = takeReal();
- h = takeReal();
- return QRectF(x, y, w ,h);
- }
+ inline QRectF takeRect() { return rects[rectIdx++]; }
inline QPainterPath takePath() { return pathes[pathIdx++]; }
inline const QImage& takeImage() { return images[imageIdx++]; }
+ inline QQmlRefPointer<QQuickCanvasPixmap> takePixmap() { return pixmaps[pixmapIdx++]; }
inline int takeInt() { return ints[intIdx++]; }
inline bool takeBool() {return bools[boolIdx++]; }
@@ -246,21 +244,25 @@ private:
int intIdx;
int boolIdx;
int realIdx;
+ int rectIdx;
int colorIdx;
int matrixIdx;
int brushIdx;
int pathIdx;
int imageIdx;
+ int pixmapIdx;
QVector<QQuickContext2D::PaintCommand> commands;
QVector<int> ints;
QVector<bool> bools;
QVector<qreal> reals;
+ QVector<QRectF> rects;
QVector<QColor> colors;
QVector<QTransform> matrixes;
QVector<QBrush> brushes;
QVector<QPainterPath> pathes;
QVector<QImage> images;
+ QVector<QQmlRefPointer<QQuickCanvasPixmap> > pixmaps;
QMutex queueLock;
};
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index 7778a64962..2cb183d715 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -50,7 +50,7 @@
#include <QOpenGLFramebufferObject>
#include <QOpenGLFramebufferObjectFormat>
#include <QtCore/QThread>
-
+#include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE