aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick')
-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