diff options
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/context2d/qquickcanvasitem.cpp | 109 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcanvasitem_p.h | 37 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2d.cpp | 67 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2d_p.h | 3 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp | 121 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h | 40 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2dtexture.cpp | 2 |
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 ®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 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 |