From 4ae829c1dbd0e8a72b82ab4c6cddb0a4ffe009f6 Mon Sep 17 00:00:00 2001 From: Julien Brianceau Date: Tue, 11 Sep 2012 17:20:30 +0200 Subject: [PATCH] qpa: extend drawPixmap capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Extend drawPixmap capabilities for qpa through new ExtendedPixmapCapability QBlittable flag and add related implementation in DirectFB platform. Change-Id: If5436e16bfb37bf081bf864cad73a5e97394df8c Reviewed-by: Qt Doc Bot Reviewed-by: Jørgen Lind --- src/gui/painting/qblittable_p.h | 9 +++ src/gui/painting/qpaintengine_blitter.cpp | 56 ++++++++++++--- .../platforms/directfb/qdirectfbblitter.cpp | 80 +++++++++++++--------- src/plugins/platforms/directfb/qdirectfbblitter.h | 1 + 4 files changed, 104 insertions(+), 42 deletions(-) diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h index 654a0a0..1f404a3 100644 --- a/src/gui/painting/qblittable_p.h +++ b/src/gui/painting/qblittable_p.h @@ -63,6 +63,7 @@ public: SourceOverPixmapCapability = 0x0004, SourceOverScaledPixmapCapability = 0x0008, AlphaFillRectCapability = 0x0010, + OpacityPixmapCapability = 0x0020, // Internal ones OutlineCapability = 0x0001000 @@ -83,6 +84,14 @@ public: Q_UNUSED(cmode); qWarning("Please implement alphaFillRect function in your platform or remove AlphaFillRectCapability from it"); } + virtual void drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity) { + Q_UNUSED(rect); + Q_UNUSED(pixmap); + Q_UNUSED(subrect); + Q_UNUSED(cmode); + Q_UNUSED(opacity); + qWarning("Please implement drawPixmapOpacity function in your platform or remove OpacityPixmapCapability from it"); + } QImage *lock(); void unlock(); diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp index 20dd98b..f8ebaf7 100644 --- a/src/gui/painting/qpaintengine_blitter.cpp +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -74,6 +74,7 @@ public: , drawRectMask(0) , drawPixmapMask(0) , alphaFillRectMask(0) + , opacityPixmapMask(0) , capabillitiesState(0) { if (capabilities & QBlittable::SolidRectCapability) @@ -86,6 +87,8 @@ public: setSourceOverScaledPixmapMask(); if (capabilities & QBlittable::AlphaFillRectCapability) setAlphaFillRectMask(); + if (capabilities & QBlittable::OpacityPixmapCapability) + setOpacityPixmapMask(); } inline bool canBlitterFillRect() const @@ -121,6 +124,14 @@ public: return false; } + bool canBlitterDrawPixmapOpacity(const QPixmap &pm) const + { + if (pm.handle()->classId() != QPlatformPixmap::BlitterClass) + return false; + + return checkStateAgainstMask(capabillitiesState, opacityPixmapMask); + } + inline void updateState(uint mask, bool on) { updateStateBits(&capabillitiesState, mask, on); } @@ -199,11 +210,29 @@ private: updateStateBits(&drawRectMask, STATE_XFORM_SCALE, true); } + void setOpacityPixmapMask() { + updateStateBits(&opacityPixmapMask, STATE_XFORM_SCALE, true); + updateStateBits(&opacityPixmapMask, STATE_XFORM_COMPLEX, false); + + updateStateBits(&opacityPixmapMask, STATE_BRUSH_PATTERN, true); + updateStateBits(&opacityPixmapMask, STATE_BRUSH_ALPHA, true); + + updateStateBits(&opacityPixmapMask, STATE_PEN_ENABLED, true); + + updateStateBits(&opacityPixmapMask, STATE_ANTIALIASING, true); + updateStateBits(&opacityPixmapMask, STATE_ALPHA, true); + updateStateBits(&opacityPixmapMask, STATE_BLENDING_COMPLEX, false); + + updateStateBits(&opacityPixmapMask, STATE_CLIPSYS_COMPLEX, false); + updateStateBits(&opacityPixmapMask, STATE_CLIP_COMPLEX, false); + } + QBlittable::Capabilities m_capabilities; uint fillRectMask; uint drawRectMask; uint drawPixmapMask; uint alphaFillRectMask; + uint opacityPixmapMask; uint capabillitiesState; }; @@ -222,7 +251,7 @@ public: void lock(); void unlock(); void fillRect(const QRectF &rect, const QColor &color, bool alpha); - void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr); + void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr, bool opacity); void updateCompleteState(QPainterState *s); @@ -365,8 +394,10 @@ void QBlitterPaintEnginePrivate::fillRect(const QRectF &rect, const QColor &colo void QBlitterPaintEnginePrivate::clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, - const QRectF &sr) + const QRectF &sr, + bool opacity) { + Q_Q(QBlitterPaintEngine); QRectF intersectedRect = clip.intersected(target); if (intersectedRect.isEmpty()) return; @@ -391,7 +422,10 @@ void QBlitterPaintEnginePrivate::clipAndDrawPixmap(const QRectF &clip, } } pmData->unmarkRasterOverlay(intersectedRect); - pmData->blittable()->drawPixmap(intersectedRect, pm, source); + if (opacity) + pmData->blittable()->drawPixmapOpacity(intersectedRect, pm, source, q->state()->compositionMode(), q->state()->opacity); + else + pmData->blittable()->drawPixmap(intersectedRect, pm, source); } QBlitterPaintEngine::QBlitterPaintEngine(QBlittablePlatformPixmap *p) @@ -524,8 +558,9 @@ void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) && qbrush_color(brush).alpha() == 0xff && d->caps.canBlitterFillRect()) { d->fillRect(rect, qbrush_color(brush), false); - } else if (brush.style() == Qt::TexturePattern - && d->caps.canBlitterDrawPixmap(rect, brush.texture(), rect)) { + } else if (brush.style() == Qt::TexturePattern && + ((d->caps.canBlitterDrawPixmapOpacity(brush.texture())) || + (d->caps.canBlitterDrawPixmap(rect, brush.texture(), rect)))) { bool rectIsFilled = false; QRectF transformedRect = state()->matrix.mapRect(rect); qreal x = transformedRect.x(); @@ -621,7 +656,10 @@ void QBlitterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm) void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) { Q_D(QBlitterPaintEngine); - if (d->caps.canBlitterDrawPixmap(r, pm, sr)) { + bool canDrawOpacity; + + canDrawOpacity = d->caps.canBlitterDrawPixmapOpacity(pm); + if (canDrawOpacity || (d->caps.canBlitterDrawPixmap(r, pm, sr))) { d->unlock(); QRectF targetRect = r; @@ -630,15 +668,15 @@ void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const Q const QClipData *clipData = d->clip(); if (clipData) { if (clipData->hasRectClip) { - d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr); + d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr, canDrawOpacity); } else if (clipData->hasRegionClip) { QVectorrects = clipData->clipRegion.rects(); for (int i = 0; iclipAndDrawPixmap(rects.at(i), targetRect, pm, sr); + d->clipAndDrawPixmap(rects.at(i), targetRect, pm, sr, canDrawOpacity); } } else { QRectF deviceRect(0, 0, paintDevice()->width(), paintDevice()->height()); - d->clipAndDrawPixmap(deviceRect, targetRect, pm, sr); + d->clipAndDrawPixmap(deviceRect, targetRect, pm, sr, canDrawOpacity); } }else { d->lock(); diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp index 889f1cc..deca258 100644 --- a/src/plugins/platforms/directfb/qdirectfbblitter.cpp +++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp @@ -57,7 +57,8 @@ static QBlittable::Capabilities dfb_blitter_capabilities() |QBlittable::SourcePixmapCapability |QBlittable::SourceOverPixmapCapability |QBlittable::SourceOverScaledPixmapCapability - |QBlittable::AlphaFillRectCapability); + |QBlittable::AlphaFillRectCapability + |QBlittable::OpacityPixmapCapability); } QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface) @@ -79,7 +80,7 @@ QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha) surfaceDesc.width = rect.width(); surfaceDesc.height = rect.height(); - // force alpha format for AlphaFillRectCapability support + // force alpha format to get AlphaFillRectCapability and ExtendedPixmapCapability support alpha = true; if (alpha) { @@ -124,37 +125,7 @@ void QDirectFbBlitter::fillRect(const QRectF &rect, const QColor &color) void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &srcRect) { - QPlatformPixmap *data = pixmap.handle(); - Q_ASSERT(data->width() && data->height()); - Q_ASSERT(data->classId() == QPlatformPixmap::BlitterClass); - QBlittablePlatformPixmap *blitPm = static_cast(data); - QDirectFbBlitter *dfbBlitter = static_cast(blitPm->blittable()); - dfbBlitter->unlock(); - - IDirectFBSurface *s = dfbBlitter->m_surface.data(); - - DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; - DFBSurfacePorterDuffRule porterDuff = DSPD_SRC; - if (pixmap.hasAlpha()) { - blittingFlags = DSBLIT_BLEND_ALPHACHANNEL; - porterDuff = DSPD_SRC_OVER; - } - - m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(blittingFlags)); - m_surface->SetPorterDuff(m_surface.data(), porterDuff); - m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA); - - const DFBRectangle sRect = { int(srcRect.x()), int(srcRect.y()), int(srcRect.width()), int(srcRect.height()) }; - - DFBResult result; - if (rect.width() == srcRect.width() && rect.height() == srcRect.height()) - result = m_surface->Blit(m_surface.data(), s, &sRect, rect.x(), rect.y()); - else { - const DFBRectangle dRect = { int(rect.x()), int(rect.y()), int(rect.width()), int(rect.height()) }; - result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect); - } - if (result != DFB_OK) - DirectFBError("QDirectFBBlitter::drawPixmap()", result); + drawPixmapOpacity(rect, pixmap, srcRect, QPainter::CompositionMode_SourceOver, 1.0); } void QDirectFbBlitter::alphaFillRect(const QRectF &rect, const QColor &color, QPainter::CompositionMode cmode) @@ -194,6 +165,49 @@ void QDirectFbBlitter::alphaFillRect(const QRectF &rect, const QColor &color, QP DirectFBError("QDirectFBBlitter::alphaFillRect()", result); } +void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity) +{ + QRect sQRect = subrect.toRect(); + QRect dQRect = rect.toRect(); + DFBRectangle sRect = { sQRect.x(), sQRect.y(), sQRect.width(), sQRect.height() }; + DFBRectangle dRect = { dQRect.x(), dQRect.y(), dQRect.width(), dQRect.height() }; + DFBResult result; + + // skip if dst too small + if ((dRect.w <= 0) || (dRect.h <= 0)) return; + + // correct roundings if needed + if (sRect.w <= 0) sRect.w = 1; + if (sRect.h <= 0) sRect.h = 1; + + QDirectFbBlitterPlatformPixmap *blitPm = static_cast(pixmap.handle()); + QDirectFbBlitter *dfbBlitter = static_cast(blitPm->blittable()); + dfbBlitter->unlock(); + + IDirectFBSurface *s = dfbBlitter->m_surface.data(); + + DFBSurfaceBlittingFlags blittingFlags = DFBSurfaceBlittingFlags(DSBLIT_BLEND_ALPHACHANNEL); + DFBSurfacePorterDuffRule porterDuff = (cmode == QPainter::CompositionMode_SourceOver) ? DSPD_SRC_OVER : DSPD_SRC; + + if (opacity != 1.0) + { + blittingFlags = DFBSurfaceBlittingFlags(blittingFlags | DSBLIT_BLEND_COLORALPHA | (m_premult ? DSBLIT_SRC_PREMULTCOLOR : 0)); + m_surface->SetColor(m_surface.data(), 0xff, 0xff, 0xff, (u8) (opacity * 255.0)); + } + + m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(blittingFlags)); + m_surface->SetPorterDuff(m_surface.data(), porterDuff); + m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA); + + if ((sRect.w == dRect.w) && (sRect.h == dRect.h)) + result = m_surface->Blit(m_surface.data(), s, &sRect, dRect.x, dRect.y); + else + result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect); + + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawPixmapExtended()", result); +} + QImage *QDirectFbBlitter::doLock() { Q_ASSERT(m_surface); diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.h b/src/plugins/platforms/directfb/qdirectfbblitter.h index 6da5fcb..950ffe7 100644 --- a/src/plugins/platforms/directfb/qdirectfbblitter.h +++ b/src/plugins/platforms/directfb/qdirectfbblitter.h @@ -60,6 +60,7 @@ public: virtual void fillRect(const QRectF &rect, const QColor &color); virtual void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect); void alphaFillRect(const QRectF &rect, const QColor &color, QPainter::CompositionMode cmode); + void drawPixmapOpacity(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect, QPainter::CompositionMode cmode, qreal opacity); IDirectFBSurface *dfbSurface() const; -- 2.7.4