Add support for accelerated glyph rendering in the directfb plugin
Change-Id: I44ae087c900e5cffdada45845cb7f34aab89b8ab Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
c8e7fe7f35
commit
258d35ceb3
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user