summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/painting/qblittable_p.h9
-rw-r--r--src/gui/painting/qpaintengine_blitter.cpp56
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.cpp80
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.h1
4 files changed, 104 insertions, 42 deletions
diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h
index 654a0a0533..1f404a3b55 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 20dd98b9bf..f8ebaf7b2e 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) {
QVector<QRect>rects = clipData->clipRegion.rects();
for (int i = 0; i<rects.size(); ++i)
- d->clipAndDrawPixmap(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 889f1cc071..deca258b04 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<QBlittablePlatformPixmap*>(data);
- QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(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<QDirectFbBlitterPlatformPixmap *>(pixmap.handle());
+ QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(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 6da5fcbb37..950ffe708b 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;