summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-08-13 16:33:27 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2014-08-15 18:28:37 +0200
commit258d35ceb3142d654d02799516c433ccf7094313 (patch)
treeb8e87dc4fc1591759988d61cea015716c7ccb60a /src
parentc8e7fe7f3583f03cc0af680aea2b25c25249ee6e (diff)
Add support for accelerated glyph rendering in the directfb plugin
Change-Id: I44ae087c900e5cffdada45845cb7f34aab89b8ab Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/gui/painting/qblittable_p.h14
-rw-r--r--src/gui/painting/qpaintengine_blitter.cpp35
-rw-r--r--src/gui/painting/qpaintengine_blitter_p.h1
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.cpp124
-rw-r--r--src/plugins/platforms/directfb/qdirectfbblitter.h16
5 files changed, 189 insertions, 1 deletions
diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h
index f65549d63c..0f846741b3 100644
--- a/src/gui/painting/qblittable_p.h
+++ b/src/gui/painting/qblittable_p.h
@@ -64,6 +64,9 @@ public:
SourceOverScaledPixmapCapability = 0x0008,
AlphaFillRectCapability = 0x0010,
OpacityPixmapCapability = 0x0020,
+ DrawScaledCachedGlyphsCapability = 0x0040,
+ SubPixelGlyphsCapability = 0x0080,
+ ComplexClipCapability = 0x0100,
// Internal ones
OutlineCapability = 0x0001000
@@ -92,6 +95,17 @@ public:
Q_UNUSED(opacity);
qWarning("Please implement drawPixmapOpacity function in your platform or remove OpacityPixmapCapability from it");
}
+ virtual bool drawCachedGlyphs(const QPaintEngineState *state, QFontEngine::GlyphFormat glyphFormat, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine) {
+ Q_UNUSED(state);
+ Q_UNUSED(glyphFormat);
+ Q_UNUSED(numGlyphs);
+ Q_UNUSED(glyphs);
+ Q_UNUSED(positions);
+ Q_UNUSED(fontEngine);
+ qWarning("Please implement drawCachedGlyphs function in your platform or remove DrawCachedGlyphsCapability from it");
+ return true;
+ }
+
QImage *lock();
void unlock();
diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp
index 67a692e2db..9a3b8f421b 100644
--- a/src/gui/painting/qpaintengine_blitter.cpp
+++ b/src/gui/painting/qpaintengine_blitter.cpp
@@ -132,6 +132,19 @@ public:
return checkStateAgainstMask(capabillitiesState, opacityPixmapMask);
}
+ bool canBlitterDrawCachedGlyphs(const QTransform &transform, QFontEngine::GlyphFormat requestedGlyphFormat, bool complexClip) const
+ {
+ if (transform.type() > QTransform::TxScale)
+ return false;
+ if (!(m_capabilities & QBlittable::DrawScaledCachedGlyphsCapability))
+ return false;
+ if (requestedGlyphFormat == QFontEngine::Format_ARGB && !(m_capabilities & QBlittable::SubPixelGlyphsCapability))
+ return false;
+ if (complexClip && !(m_capabilities & QBlittable::ComplexClipCapability))
+ return false;
+ return true;
+ }
+
inline void updateState(uint mask, bool on) {
updateStateBits(&capabillitiesState, mask, on);
}
@@ -798,6 +811,28 @@ void QBlitterPaintEngine::drawStaticTextItem(QStaticTextItem *sti)
#endif
}
+bool QBlitterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine)
+{
+ Q_D(QBlitterPaintEngine);
+ QFontEngine::GlyphFormat glyphFormat = d->glyphCacheFormat;
+ if (fontEngine->glyphFormat != QFontEngine::Format_None)
+ glyphFormat = fontEngine->glyphFormat;
+
+ const QClipData *clipData = d->clip();
+ const bool complexClip = clipData && !clipData->hasRectClip;
+
+ const QPainterState *s = state();
+ if (d->caps.canBlitterDrawCachedGlyphs(s->transform(), glyphFormat, complexClip)) {
+ d->unlock();
+ const bool result = d->pmData->blittable()->drawCachedGlyphs(s, glyphFormat, numGlyphs, glyphs, positions, fontEngine);
+ // Lock again as the raster paint engine might draw decorations now.
+ d->lock();
+ return result;
+ } else {
+ return QRasterPaintEngine::drawCachedGlyphs(numGlyphs, glyphs, positions, fontEngine);
+ }
+}
+
QT_END_NAMESPACE
#endif //QT_NO_BLITTABLE
diff --git a/src/gui/painting/qpaintengine_blitter_p.h b/src/gui/painting/qpaintengine_blitter_p.h
index b70ee5fc5c..56661a7d90 100644
--- a/src/gui/painting/qpaintengine_blitter_p.h
+++ b/src/gui/painting/qpaintengine_blitter_p.h
@@ -96,6 +96,7 @@ public:
void drawPoints(const QPoint *points, int pointCount);
void stroke(const QVectorPath &path, const QPen &pen);
void drawStaticTextItem(QStaticTextItem *);
+ bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp
index 46f811f816..bc6e4d70e9 100644
--- a/src/plugins/platforms/directfb/qdirectfbblitter.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp
@@ -58,7 +58,9 @@ static QBlittable::Capabilities dfb_blitter_capabilities()
|QBlittable::SourceOverPixmapCapability
|QBlittable::SourceOverScaledPixmapCapability
|QBlittable::AlphaFillRectCapability
- |QBlittable::OpacityPixmapCapability);
+ |QBlittable::OpacityPixmapCapability
+ |QBlittable::DrawScaledCachedGlyphsCapability
+ );
}
QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface)
@@ -210,6 +212,86 @@ void QDirectFbBlitter::drawPixmapOpacity(const QRectF &rect, const QPixmap &pixm
DirectFBError("QDirectFBBlitter::drawPixmapExtended()", result);
}
+bool QDirectFbBlitter::drawCachedGlyphs(const QPaintEngineState *state, QFontEngine::GlyphFormat glyphFormat, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine)
+{
+ void *cacheKey = QDirectFbConvenience::dfbInterface();
+
+ QDirectFbTextureGlyphCache *cache =
+ static_cast<QDirectFbTextureGlyphCache *>(fontEngine->glyphCache(cacheKey, glyphFormat, state->transform()));
+ if (!cache) {
+ cache = new QDirectFbTextureGlyphCache(glyphFormat, state->transform());
+ fontEngine->setGlyphCache(cacheKey, cache);
+ }
+
+ cache->populate(fontEngine, numGlyphs, glyphs, positions);
+ cache->fillInPendingGlyphs();
+
+ if (cache->image().width() == 0 || cache->image().height() == 0)
+ return false;
+
+ const int margin = fontEngine->glyphMargin(glyphFormat);
+
+ QVarLengthArray<DFBRectangle, 64> sourceRects(numGlyphs);
+ QVarLengthArray<DFBPoint, 64> destPoints(numGlyphs);
+ int nGlyphs = 0;
+
+ for (int i=0; i<numGlyphs; ++i) {
+
+ QFixed subPixelPosition = fontEngine->subPixelPositionForX(positions[i].x);
+ QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
+ const QTextureGlyphCache::Coord &c = cache->coords[glyph];
+ if (c.isNull())
+ continue;
+
+ int x = qFloor(positions[i].x) + c.baseLineX - margin;
+ int y = qRound(positions[i].y) - c.baseLineY - margin;
+
+ // printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
+ // c.x, c.y,
+ // c.w, c.h,
+ // c.baseLineX, c.baseLineY,
+ // glyphs[i],
+ // x, y,
+ // positions[i].x.toInt(), positions[i].y.toInt());
+
+ sourceRects[nGlyphs].x = c.x;
+ sourceRects[nGlyphs].y = c.y;
+ sourceRects[nGlyphs].w = c.w;
+ sourceRects[nGlyphs].h = c.h;
+ destPoints[nGlyphs].x = x;
+ destPoints[nGlyphs].y = y;
+ ++nGlyphs;
+ }
+
+ const QColor color = state->pen().color();
+ m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), color.alpha());
+
+ m_surface->SetSrcBlendFunction(m_surface.data(), DSBF_SRCALPHA);
+ m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
+
+ int flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
+ if (color.alpha() != 0xff)
+ flags |= DSBLIT_BLEND_COLORALPHA;
+ m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(flags));
+
+ const QRasterPaintEngineState *rs = static_cast<const QRasterPaintEngineState*>(state);
+ if (rs->clip && rs->clip->enabled) {
+ Q_ASSERT(rs->clip->hasRectClip);
+ DFBRegion dfbClip;
+ dfbClip.x1 = rs->clip->clipRect.x();
+ dfbClip.y1 = rs->clip->clipRect.y();
+ dfbClip.x2 = rs->clip->clipRect.right();
+ dfbClip.y2 = rs->clip->clipRect.bottom();
+ m_surface->SetClip(m_surface.data(), &dfbClip);
+ }
+
+ m_surface->BatchBlit(m_surface.data(), cache->sourceSurface(), sourceRects.constData(), destPoints.constData(), nGlyphs);
+
+ if (rs->clip && rs->clip->enabled)
+ m_surface->SetClip(m_surface.data(), 0);
+ return true;
+}
+
QImage *QDirectFbBlitter::doLock()
{
Q_ASSERT(m_surface);
@@ -321,4 +403,44 @@ void QDirectFbBlitter::doUnlock()
m_surface->Unlock(m_surface.data());
}
+void QDirectFbTextureGlyphCache::resizeTextureData(int width, int height)
+{
+ m_surface.reset();;
+ QImageTextureGlyphCache::resizeTextureData(width, height);
+}
+
+IDirectFBSurface *QDirectFbTextureGlyphCache::sourceSurface()
+{
+ if (m_surface.isNull()) {
+ const QImage &source = image();
+ DFBSurfaceDescription desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED | DSDESC_CAPS);
+ desc.width = source.width();
+ desc.height = source.height();
+ desc.caps = DSCAPS_SYSTEMONLY;
+
+ switch (source.format()) {
+ case QImage::Format_Mono:
+ desc.pixelformat = DSPF_A1;
+ break;
+ case QImage::Format_Indexed8:
+ desc.pixelformat = DSPF_A8;
+ break;
+ default:
+ qFatal("QDirectFBTextureGlyphCache: Unsupported source texture image format.");
+ break;
+ }
+
+ desc.preallocated[0].data = const_cast<void*>(static_cast<const void*>(source.bits()));
+ desc.preallocated[0].pitch = source.bytesPerLine();
+ desc.preallocated[1].data = 0;
+ desc.preallocated[1].pitch = 0;
+
+ IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
+ dfb->CreateSurface(dfb , &desc, m_surface.outPtr());
+ }
+ return m_surface.data();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.h b/src/plugins/platforms/directfb/qdirectfbblitter.h
index 0255040729..c60f0fac25 100644
--- a/src/plugins/platforms/directfb/qdirectfbblitter.h
+++ b/src/plugins/platforms/directfb/qdirectfbblitter.h
@@ -61,6 +61,7 @@ public:
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);
+ virtual bool drawCachedGlyphs(const QPaintEngineState *state, QFontEngine::GlyphFormat glyphFormat, int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine);
IDirectFBSurface *dfbSurface() const;
@@ -110,6 +111,21 @@ inline IDirectFBSurface *QDirectFbBlitter::dfbSurface() const
return m_surface.data();
}
+class QDirectFbTextureGlyphCache : public QImageTextureGlyphCache
+{
+public:
+ QDirectFbTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
+ : QImageTextureGlyphCache(format, matrix)
+ {}
+
+ virtual void resizeTextureData(int width, int height);
+
+ IDirectFBSurface *sourceSurface();
+
+private:
+ QDirectFBPointer<IDirectFBSurface> m_surface;
+};
+
QT_END_NAMESPACE
#endif // QDIRECTFBBLITTER_H