qpa: extend drawPixmap capabilities
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 <qt_docbot@qt-project.org> Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>bb10
parent
287255c03a
commit
4ae829c1db
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue