From: Charles Yin Date: Mon, 4 Jun 2012 06:34:17 +0000 (+1000) Subject: Introduce QQuickCanvasPixmap X-Git-Tag: upstream/5.2.1~1696 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1dcfa8aa2ae6460f26d9843c197532024447e43b;p=platform%2Fupstream%2Fqtdeclarative.git 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 --- diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 7d2a85c..9b2bc43 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 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 images; + QHash > pixmaps; QUrl baseUrl; QMap > 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 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 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 8e7b992..090c763 100644 --- a/src/quick/items/context2d/qquickcanvasitem_p.h +++ b/src/quick/items/context2d/qquickcanvasitem_p.h @@ -45,6 +45,7 @@ #include #include #include +#include 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 loadedPixmap(const QUrl& url); Q_SIGNALS: void paint(const QRect ®ion); @@ -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 637377b..c171bab 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -1204,7 +1204,7 @@ static v8::Handle 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 ctx2d_isPointInPath(const v8::Arguments &args) static v8::Handle ctx2d_drawFocusRing(const v8::Arguments &args) { + Q_UNUSED(args); + V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported"); } static v8::Handle ctx2d_setCaretSelectionRect(const v8::Arguments &args) { + Q_UNUSED(args); + V8THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported"); } static v8::Handle 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 ctx2d_drawImage(const v8::Arguments &args) if (!r->context->state.invertibleCTM) return args.This(); - QImage image; + QQmlRefPointer 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(engine->toQObject(args[0]->ToObject())); QQuickCanvasItem *canvas = qobject_cast(engine->toQObject(args[0]->ToObject())); QV8Context2DPixelArrayResource *pix = v8_resource_cast(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 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 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 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 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 22addf3..e2952ca 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 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 6f20b69..d231609 100644 --- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp +++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp @@ -43,6 +43,10 @@ #include "qquickcanvasitem_p.h" #include #include +#include +#include +#include +#include #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 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(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(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 f33c43a..ddf5ba1 100644 --- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h +++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h @@ -44,8 +44,6 @@ #include #include "qquickcontext2d_p.h" -#include - 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 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 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 commands; QVector ints; QVector bools; QVector reals; + QVector rects; QVector colors; QVector matrixes; QVector brushes; QVector pathes; QVector images; + QVector > pixmaps; QMutex queueLock; }; diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp index 7778a64..2cb183d 100644 --- a/src/quick/items/context2d/qquickcontext2dtexture.cpp +++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp @@ -50,7 +50,7 @@ #include #include #include - +#include QT_BEGIN_NAMESPACE