diff options
author | Charles Yin <charles.yin@nokia.com> | 2012-06-04 16:34:17 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-05 12:32:58 +0200 |
commit | 1dcfa8aa2ae6460f26d9843c197532024447e43b (patch) | |
tree | 10b5243607d603443a4abe9f89e2a453757ffaeb /src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp | |
parent | 332fe582d1bd590b59618cc7b732be9bf7f9f475 (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/quick/items/context2d/qquickcontext2dcommandbuffer.cpp')
-rw-r--r-- | src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp | 121 |
1 files changed, 90 insertions, 31 deletions
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 - |