From 508f241a6a56b0a31472ed99ad60eb3a22388c20 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Tue, 5 May 2009 15:18:17 -0700 Subject: Cleaned up code Move private functions to the bottom of the file to be more in line with how most qt cpp files are structured. Reviewed-by: TrustMe --- .../gfxdrivers/directfb/qdirectfbpaintengine.cpp | 1434 ++++++++++---------- 1 file changed, 719 insertions(+), 715 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 317f930..bc8efdd 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -291,948 +291,952 @@ private: QDirectFBPaintEngine *q; }; -QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) - : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), - matrixRotShear(false), scale(NoScale), lastLockedHeight(-1), - fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), - blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), - dfbHandledClip(false), dfbDevice(0), lockedMemory(0), q(p) +QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device) + : QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device) { - fb = QDirectFBScreen::instance()->dfb(); - ignoreSystemClip = QDirectFBScreen::instance()->directFBFlags() & QDirectFBScreen::IgnoreSystemClip; - surfaceCache = new SurfaceCache; } -QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate() +QDirectFBPaintEngine::~QDirectFBPaintEngine() { - delete surfaceCache; } -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const +bool QDirectFBPaintEngine::begin(QPaintDevice *device) { - // TODO: Check to see if DirectFB can handle the clip for the given rect - return dfbHandledClip; + Q_D(QDirectFBPaintEngine); + d->begin(device); + const bool status = QRasterPaintEngine::begin(device); + + // XXX: QRasterPaintEngine::begin() resets the capabilities + gccaps |= PorterDuff; + + return status; } -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const +bool QDirectFBPaintEngine::end() { - // TODO: Check to see if DirectFB can handle the clip for the given rect - return dfbHandledClip; + Q_D(QDirectFBPaintEngine); + d->end(); + return QRasterPaintEngine::end(); } -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const +void QDirectFBPaintEngine::clipEnabledChanged() { - return dfbHandledClip; + Q_D(QDirectFBPaintEngine); + d->setClipDirty(); + QRasterPaintEngine::clipEnabledChanged(); } -bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const +void QDirectFBPaintEngine::penChanged() { - return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); + Q_D(QDirectFBPaintEngine); + d->setPen(state()->pen); + + QRasterPaintEngine::penChanged(); } -void QDirectFBPaintEnginePrivate::setClipDirty() +void QDirectFBPaintEngine::opacityChanged() { - dirtyClip = true; + Q_D(QDirectFBPaintEngine); + d->setOpacity(quint8(state()->opacity * 255)); + QRasterPaintEngine::opacityChanged(); } -void QDirectFBPaintEnginePrivate::lock() +void QDirectFBPaintEngine::compositionModeChanged() { - // We will potentially get a new pointer to the buffer after a - // lock so we need to call the base implementation of prepare so - // it updates its rasterBuffer to point to the new buffer address. - Q_ASSERT(dfbDevice); - if (dfbDevice->lockFlags() != (DSLF_WRITE|DSLF_READ) - || dfbDevice->height() != lastLockedHeight - || dfbDevice->memory() != lockedMemory) { - prepare(dfbDevice); - lastLockedHeight = dfbDevice->height(); - lockedMemory = dfbDevice->memory(); - } + Q_D(QDirectFBPaintEngine); + d->setCompositionMode(state()->compositionMode()); + QRasterPaintEngine::compositionModeChanged(); } -void QDirectFBPaintEnginePrivate::unlock() +void QDirectFBPaintEngine::renderHintsChanged() { - Q_ASSERT(dfbDevice); - dfbDevice->unlockDirectFB(); - lockedMemory = 0; + Q_D(QDirectFBPaintEngine); + d->setRenderHints(state()->renderHints); + QRasterPaintEngine::renderHintsChanged(); } -void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m) +void QDirectFBPaintEngine::transformChanged() { - transform = m; - matrixRotShear = (transform.m12() != 0 || transform.m21() != 0); - if (qMin(transform.m11(), transform.m22()) < 0) { - scale = NegativeScale; - } else if (transform.m11() != 1 || transform.m22() != 1) { - scale = Scaled; - } else { - scale = NoScale; + Q_D(QDirectFBPaintEngine); + const QDirectFBPaintEnginePrivate::Scale old = d->scale; + d->setTransform(state()->transform()); + if (d->scale != old) { + d->setPen(state()->pen); } + QRasterPaintEngine::transformChanged(); } -void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) +void QDirectFBPaintEngine::setState(QPainterState *s) { - lastLockedHeight = -1; - if (device->devType() == QInternal::CustomRaster) - dfbDevice = static_cast(device); - else if (device->devType() == QInternal::Pixmap) { - QPixmapData *data = static_cast(device)->pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData* dfbPixmapData = static_cast(data); - dfbDevice = static_cast(dfbPixmapData); - } - - if (dfbDevice) - surface = dfbDevice->directFBSurface(); - - if (!surface) { - qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", - device->devType()); - } - lockedMemory = 0; - forceRasterPrimitives = dfbDevice->forceRasterPrimitives(); - - surface->GetSize(surface, &fbWidth, &fbHeight); - - setTransform(QTransform()); - antialiased = false; - opacity = 255; - setCompositionMode(q->state()->compositionMode()); - dirtyClip = true; - setPen(q->state()->pen); - setDFBColor(pen.color()); + Q_D(QDirectFBPaintEngine); + QRasterPaintEngine::setState(s); + d->setClipDirty(); + d->setPen(state()->pen); + d->setOpacity(quint8(state()->opacity * 255)); + d->setCompositionMode(state()->compositionMode()); + d->setTransform(state()->transform()); } -void QDirectFBPaintEnginePrivate::end() +void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) { - lockedMemory = 0; - dfbDevice = 0; - surface->ReleaseSource(surface); - surface->SetClip(surface, NULL); - surface = 0; + Q_D(QDirectFBPaintEngine); + d->setClipDirty(); + const QPoint bottom = d->transform.map(QPoint(0, path.controlPointRect().y2)); + if (bottom.y() >= d->lastLockedHeight) + d->lock(); + QRasterPaintEngine::clip(path, op); } -void QDirectFBPaintEnginePrivate::setPen(const QPen &p) +void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) { - pen = p; - simplePen = (pen.style() == Qt::NoPen) || - (pen.style() == Qt::SolidLine - && !antialiased - && (pen.brush().style() == Qt::SolidPattern) - && (pen.widthF() <= 1 && scale != NoScale)); + Q_D(QDirectFBPaintEngine); + d->setClipDirty(); + if (d->clip() && !d->clip()->hasRectClip && d->clip()->enabled) { + const QPoint bottom = d->transform.map(QPoint(0, rect.bottom())); + if (bottom.y() >= d->lastLockedHeight) + d->lock(); + } + + QRasterPaintEngine::clip(rect, op); } -void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) +void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount) { - blitFlagsFromCompositionMode = DSBLIT_NOFX; - drawFlagsFromCompositionMode = DSDRAW_NOFX; - - bool blend = true; - switch (mode) { - case QPainter::CompositionMode_SourceOver: - porterDuffRule = DSPD_SRC_OVER; - break; - case QPainter::CompositionMode_DestinationOver: - porterDuffRule = DSPD_DST_OVER; - break; - case QPainter::CompositionMode_Clear: - porterDuffRule = DSPD_CLEAR; - blend = false; - break; - case QPainter::CompositionMode_Source: - porterDuffRule = DSPD_SRC; - blend = false; - break; - case QPainter::CompositionMode_Destination: - porterDuffRule = DSPD_NONE; // ### need to double check this - blend = false; - return; - case QPainter::CompositionMode_SourceIn: - porterDuffRule = DSPD_SRC_IN; - break; - case QPainter::CompositionMode_DestinationIn: - porterDuffRule = DSPD_DST_IN; - break; - case QPainter::CompositionMode_SourceOut: - porterDuffRule = DSPD_SRC_OUT; - break; - case QPainter::CompositionMode_DestinationOut: - porterDuffRule = DSPD_DST_OUT; - break; - case QPainter::CompositionMode_Xor: - porterDuffRule = DSPD_XOR; - blitFlagsFromCompositionMode |= DSBLIT_XOR; - drawFlagsFromCompositionMode |= DSDRAW_XOR; - break; -// case QPainter::CompositionMode_Plus: // ??? -// porterDuffRule = DSPD_ADD; -// break; - default: - qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " - "mode %d not implemented", mode); + Q_D(QDirectFBPaintEngine); + d->updateClip(); + const QBrush &brush = state()->brush; + if (!d->dfbCanHandleClip() || d->matrixRotShear + || !d->simplePen || d->forceRasterPrimitives + || !d->isSimpleBrush(brush)) { + RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); + d->lock(); + QRasterPaintEngine::drawRects(rects, rectCount); return; } - // intentially not comparing with current porterDuffRule. surface might have changed. - if (blend) { - blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; - drawFlagsFromCompositionMode |= DSDRAW_BLEND; + + d->unlock(); + + if (brush != Qt::NoBrush) { + d->setDFBColor(brush.color()); + d->fillRects(rects, rectCount); } - if (opacity != 255) { - setOpacity(opacity); + if (d->pen != Qt::NoPen) { + d->setDFBColor(d->pen.color()); + d->drawRects(rects, rectCount); } } -void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) +void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount) { - opacity = op; - if (opacity == 255) { - blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; - } else { - blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; + Q_D(QDirectFBPaintEngine); + d->updateClip(); + const QBrush &brush = state()->brush; + if (!d->dfbCanHandleClip() || d->matrixRotShear + || !d->simplePen || d->forceRasterPrimitives + || !d->isSimpleBrush(brush)) { + RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); + d->lock(); + QRasterPaintEngine::drawRects(rects, rectCount); + return; } -} -void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) -{ - const bool old = antialiased; - antialiased = bool(hints & QPainter::Antialiasing); - if (old != antialiased) { - setPen(q->state()->pen); + d->unlock(); + + if (brush != Qt::NoBrush) { + d->setDFBColor(brush.color()); + d->fillRects(rects, rectCount); + } + if (d->pen != Qt::NoPen) { + d->setDFBColor(d->pen.color()); + d->drawRects(rects, rectCount); } } -void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) +void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount) { - quint32 blittingFlags = blitFlagsFromCompositionMode; - if (alpha) { - surface->SetPorterDuff(surface, - (blittingFlags & DSBLIT_BLEND_COLORALPHA) - ? DSPD_NONE - : porterDuffRule); - } else { - blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; - surface->SetPorterDuff(surface, DSPD_NONE); + Q_D(QDirectFBPaintEngine); + d->updateClip(); + if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) { + RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); + d->lock(); + QRasterPaintEngine::drawLines(lines, lineCount); + return; } - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); -} -void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) -{ - Q_ASSERT(surface); - const quint8 alpha = (opacity == 255 ? - color.alpha() : ALPHA_MUL(color.alpha(), opacity)); - surface->SetColor(surface, - color.red(), color.green(), color.blue(), alpha); - quint32 drawingFlags = drawFlagsFromCompositionMode; - if (alpha == 255) { - drawingFlags &= ~DSDRAW_BLEND; + if (d->pen != Qt::NoPen) { + d->unlock(); + d->setDFBColor(d->pen.color()); + d->drawLines(lines, lineCount); } - surface->SetPorterDuff(surface, DSPD_NONE); - // PorterDuff messes up alpha values for primitives - surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); } -void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) +void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount) { - for (int i = 0; i < n; ++i) { - const QLine l = transform.map(lines[i]); - surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + Q_D(QDirectFBPaintEngine); + d->updateClip(); + if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) { + RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); + d->lock(); + QRasterPaintEngine::drawLines(lines, lineCount); + return; } -} -void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) -{ - for (int i = 0; i < n; ++i) { - const QLine l = transform.map(lines[i]).toLine(); - surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + if (d->pen != Qt::NoPen) { + d->unlock(); + d->setDFBColor(d->pen.color()); + d->drawLines(lines, lineCount); } } -void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®ion) +void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, + const QRectF &sr, + Qt::ImageConversionFlags flags) { - Q_ASSERT(isSimpleBrush(q->state()->brush)); - setDFBColor(q->state()->brush.color()); - const QVector rects = region.rects(); - const int n = rects.size(); - fillRects(rects.constData(), n); -} + Q_D(QDirectFBPaintEngine); + Q_UNUSED(flags); -void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) -{ - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]); - surface->FillRectangle(surface, r.x(), r.y(), - r.width(), r.height()); + /* This is hard to read. The way it works is like this: + + - If you do not have support for preallocated surfaces and do not use an + image cache we always fall back to raster engine. + + - If it's rotated/sheared/mirrored (negative scale) or we can't + clip it we fall back to raster engine. + + - If we don't cache the image, but we do have support for + preallocated surfaces we fall back to the raster engine if the + image is in a format DirectFB can't handle. + + - If we do cache the image but don't have support for preallocated + images and the cost of caching the image (bytes used) is higher + than the max image cache size we fall back to raster engine. + */ + + d->updateClip(); +#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE + if (d->matrixRotShear + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale + || !d->dfbCanHandleClip(r) +#ifndef QT_DIRECTFB_IMAGECACHE + || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN +#elif defined QT_NO_DIRECTFB_PREALLOCATED + || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost() +#endif + ) +#endif + { + RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr); + d->lock(); + QRasterPaintEngine::drawImage(r, image, sr, flags); + return; + } +#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE + d->unlock(); + bool release; + IDirectFBSurface *imgSurface = d->getSurface(image, &release); + d->prepareForBlit(QDirectFBScreen::hasAlpha(imgSurface)); + d->blit(r, imgSurface, sr); + if (release) { + imgSurface->ReleaseSource(imgSurface); + imgSurface->Release(imgSurface); } +#endif } -void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) +void QDirectFBPaintEngine::drawImage(const QPointF &p, const QImage &img) { - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]).toRect(); - surface->FillRectangle(surface, r.x(), r.y(), - r.width(), r.height()); - } + drawImage(QRectF(p, img.size()), img, img.rect()); } -void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) +void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, + const QRectF &sr) { - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]); - surface->DrawRectangle(surface, r.x(), r.y(), - r.width() + 1, r.height() + 1); + Q_D(QDirectFBPaintEngine); + d->updateClip(); + + if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { + RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); + d->lock(); + QRasterPaintEngine::drawPixmap(r, pixmap, sr); + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { + RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); + const QImage *img = static_cast(pixmap.pixmapData())->buffer(DSLF_READ); + d->lock(); + QRasterPaintEngine::drawImage(r, *img, sr); + } else { + d->unlock(); + d->prepareForBlit(pixmap.hasAlphaChannel()); + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData *dfbData = static_cast(data); + IDirectFBSurface *s = dfbData->directFBSurface(); + d->blit(r, s, sr); } } -void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n) +void QDirectFBPaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) { - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]).toRect(); - surface->DrawRectangle(surface, r.x(), r.y(), - r.width() + 1, r.height() + 1); - } + drawPixmap(QRectF(p, pm.size()), pm, pm.rect()); } -IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release) +void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, + const QPixmap &pixmap, + const QPointF &sp) { -#ifndef QT_DIRECTFB_IMAGECACHE - *release = true; - return QDirectFBScreen::instance()->createDFBSurface(img, QDirectFBScreen::DontTrackSurface); -#else - const qint64 key = img.cacheKey(); - *release = false; - if (imageCache.contains(key)) { - return imageCache[key]->surface; - } - - const int cost = cacheCost(img); - const bool cache = cost <= imageCache.maxCost(); - QDirectFBScreen *screen = QDirectFBScreen::instance(); - const QImage::Format format = (img.format() == screen->alphaPixmapFormat() || QDirectFBPixmapData::hasAlphaChannel(img) - ? screen->alphaPixmapFormat() : screen->pixelFormat()); - - IDirectFBSurface *surface = screen->copyToDFBSurface(img, format, - cache - ? QDirectFBScreen::TrackSurface - : QDirectFBScreen::DontTrackSurface); - if (cache) { - CachedImage *cachedImage = new CachedImage; - const_cast(img).data_ptr()->is_cached = true; - cachedImage->surface = surface; - imageCache.insert(key, cachedImage, cost); + Q_D(QDirectFBPaintEngine); + d->updateClip(); + if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { + RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); + d->lock(); + QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull() + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { + RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); + const QImage *img = static_cast(pixmap.pixmapData())->buffer(DSLF_READ); + d->lock(); + QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); + data->fromImage(*img, Qt::AutoColor); + const QPixmap pix(data); + QRasterPaintEngine::drawTiledPixmap(r, pix, sp); } else { - *release = true; + d->unlock(); + d->drawTiledPixmap(r, pixmap); } - return surface; -#endif } -void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src) +void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen) { - const QRect sr = src.toRect(); - const QRect dr = transform.mapRect(dest).toRect(); - const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; - DFBResult result; + RASTERFALLBACK(STROKE_PATH, path, VOID_ARG(), VOID_ARG()); + Q_D(QDirectFBPaintEngine); + d->lock(); + QRasterPaintEngine::stroke(path, pen); +} - if (dr.size() == sr.size()) { - result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); - } else { - const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - } - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); +void QDirectFBPaintEngine::drawPath(const QPainterPath &path) +{ + RASTERFALLBACK(DRAW_PATH, path, VOID_ARG(), VOID_ARG()); + Q_D(QDirectFBPaintEngine); + d->lock(); + QRasterPaintEngine::drawPath(path); } -void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, - const QPixmap &pixmap) -{ - prepareForBlit(pixmap.hasAlphaChannel()); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - const QRect dr = transform.mapRect(dest).toRect(); - DFBResult result = DFB_OK; - - if (scale == NoScale && dr == QRect(0, 0, fbWidth, fbHeight)) { - result = surface->TileBlit(surface, s, 0, 0, 0); - } else if (scale == NoScale) { - const int dx = pixmap.width(); - const int dy = pixmap.height(); - const DFBRectangle rect = { 0, 0, dx, dy }; - QVarLengthArray rects; - QVarLengthArray points; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - rects.append(rect); - const DFBPoint point = { x, y }; - points.append(point); - } - } - result = surface->BatchBlit(surface, s, rects.constData(), - points.constData(), points.size()); - } else { - const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); - const int dx = sr.width(); - const int dy = sr.height(); - const DFBRectangle sRect = { 0, 0, dx, dy }; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - const DFBRectangle dRect = { x, y, dx, dy }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - if (result != DFB_OK) { - y = dr.bottom() + 1; - break; - } - } - } - } - - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); -} - -void QDirectFBPaintEnginePrivate::updateClip() -{ - if (!dirtyClip) - return; - - const QClipData *clipData = clip(); - if (!clipData || !clipData->enabled) { - surface->SetClip(surface, NULL); - dfbHandledClip = true; - } else if (clipData->hasRectClip) { - const DFBRegion r = { - clipData->clipRect.x(), - clipData->clipRect.y(), - clipData->clipRect.x() + clipData->clipRect.width(), - clipData->clipRect.y() + clipData->clipRect.height() - }; - surface->SetClip(surface, &r); - dfbHandledClip = true; - } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) { - dfbHandledClip = true; - } else { - dfbHandledClip = false; - } - - dirtyClip = false; -} - -void QDirectFBPaintEnginePrivate::systemStateChanged() -{ - setClipDirty(); - QRasterPaintEnginePrivate::systemStateChanged(); -} - -QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device) - : QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device) -{ -} - -QDirectFBPaintEngine::~QDirectFBPaintEngine() -{ -} - -bool QDirectFBPaintEngine::begin(QPaintDevice *device) +void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount) { + RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->begin(device); - const bool status = QRasterPaintEngine::begin(device); - - // XXX: QRasterPaintEngine::begin() resets the capabilities - gccaps |= PorterDuff; - - return status; + d->lock(); + QRasterPaintEngine::drawPoints(points, pointCount); } -bool QDirectFBPaintEngine::end() +void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount) { + RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->end(); - return QRasterPaintEngine::end(); + d->lock(); + QRasterPaintEngine::drawPoints(points, pointCount); } -void QDirectFBPaintEngine::clipEnabledChanged() +void QDirectFBPaintEngine::drawEllipse(const QRectF &rect) { + RASTERFALLBACK(DRAW_ELLIPSE, rect, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->setClipDirty(); - QRasterPaintEngine::clipEnabledChanged(); + d->lock(); + QRasterPaintEngine::drawEllipse(rect); } -void QDirectFBPaintEngine::penChanged() +void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount, + PolygonDrawMode mode) { + RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->setPen(state()->pen); - - QRasterPaintEngine::penChanged(); + d->lock(); + QRasterPaintEngine::drawPolygon(points, pointCount, mode); } -void QDirectFBPaintEngine::opacityChanged() +void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount, + PolygonDrawMode mode) { + RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->setOpacity(quint8(state()->opacity * 255)); - QRasterPaintEngine::opacityChanged(); + d->lock(); + QRasterPaintEngine::drawPolygon(points, pointCount, mode); } -void QDirectFBPaintEngine::compositionModeChanged() +void QDirectFBPaintEngine::drawTextItem(const QPointF &p, + const QTextItem &textItem) { + RASTERFALLBACK(DRAW_TEXT, p, textItem.text(), VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->setCompositionMode(state()->compositionMode()); - QRasterPaintEngine::compositionModeChanged(); + d->lock(); + QRasterPaintEngine::drawTextItem(p, textItem); } -void QDirectFBPaintEngine::renderHintsChanged() +void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) { + RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG()); Q_D(QDirectFBPaintEngine); - d->setRenderHints(state()->renderHints); - QRasterPaintEngine::renderHintsChanged(); + d->lock(); + QRasterPaintEngine::fill(path, brush); } -void QDirectFBPaintEngine::transformChanged() + +void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) { Q_D(QDirectFBPaintEngine); - const QDirectFBPaintEnginePrivate::Scale old = d->scale; - d->setTransform(state()->transform()); - if (d->scale != old) { - d->setPen(state()->pen); + d->updateClip(); + if (d->dfbCanHandleClip(rect) && !d->matrixRotShear) { + switch (brush.style()) { + case Qt::SolidPattern: { + if (d->forceRasterPrimitives) + break; + d->unlock(); + d->setDFBColor(brush.color()); + const QRect r = d->transform.mapRect(rect).toRect(); + d->surface->FillRectangle(d->surface, r.x(), r.y(), + r.width(), r.height()); + return; } + case Qt::TexturePattern: + if (state()->brushOrigin == QPointF() && brush.transform().isIdentity()) { + //could handle certain types of brush.transform() E.g. scale + d->unlock(); + d->drawTiledPixmap(rect, brush.texture()); + return; + } + break; + default: + break; + } } - QRasterPaintEngine::transformChanged(); + RASTERFALLBACK(FILL_RECT, rect, brush, VOID_ARG()); + d->lock(); + QRasterPaintEngine::fillRect(rect, brush); } -void QDirectFBPaintEngine::setState(QPainterState *s) +void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color) { Q_D(QDirectFBPaintEngine); - QRasterPaintEngine::setState(s); - d->setClipDirty(); - d->setPen(state()->pen); - d->setOpacity(quint8(state()->opacity * 255)); - d->setCompositionMode(state()->compositionMode()); - d->setTransform(state()->transform()); + d->updateClip(); + if (!d->dfbCanHandleClip() || d->matrixRotShear || d->forceRasterPrimitives) { + RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG()); + d->lock(); + QRasterPaintEngine::fillRect(rect, color); + } else { + d->unlock(); + d->setDFBColor(color); + const QRect r = d->transform.mapRect(rect).toRect(); + d->surface->FillRectangle(d->surface, r.x(), r.y(), + r.width(), r.height()); + } } -void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) +void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count, + uint color) { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); - const QPoint bottom = d->transform.map(QPoint(0, path.controlPointRect().y2)); - if (bottom.y() >= d->lastLockedHeight) + if (d->forceRasterPrimitives) { + RASTERFALLBACK(DRAW_COLORSPANS, count, color, VOID_ARG()); d->lock(); - QRasterPaintEngine::clip(path, op); -} + QRasterPaintEngine::drawColorSpans(spans, count, color); + } else { + color = INV_PREMUL(color); -void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) -{ - Q_D(QDirectFBPaintEngine); - d->setClipDirty(); - if (d->clip() && !d->clip()->hasRectClip && d->clip()->enabled) { - const QPoint bottom = d->transform.map(QPoint(0, rect.bottom())); - if (bottom.y() >= d->lastLockedHeight) - d->lock(); + QVarLengthArray lines(count); + int j = 0; + for (int i = 0; i < count; ++i) { + if (spans[i].coverage == 255) { + lines[j].x1 = spans[i].x; + lines[j].y1 = spans[i].y; + lines[j].x2 = spans[i].x + spans[i].len - 1; + lines[j].y2 = spans[i].y; + ++j; + } else { + DFBSpan span = { spans[i].x, spans[i].len }; + uint c = BYTE_MUL(color, spans[i].coverage); + // ### how does this play with setDFBColor + d->surface->SetColor(d->surface, + qRed(c), qGreen(c), qBlue(c), qAlpha(c)); + d->surface->FillSpans(d->surface, spans[i].y, &span, 1); + } + } + if (j > 0) { + d->surface->SetColor(d->surface, + qRed(color), qGreen(color), qBlue(color), + qAlpha(color)); + d->surface->DrawLines(d->surface, lines.data(), j); + } } - - QRasterPaintEngine::clip(rect, op); } -void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount) +void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize, + int x, int y, int length, + uint const_alpha) { Q_D(QDirectFBPaintEngine); - d->updateClip(); - const QBrush &brush = state()->brush; - if (!d->dfbCanHandleClip() || d->matrixRotShear - || !d->simplePen || d->forceRasterPrimitives - || !d->isSimpleBrush(brush)) { - RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); - d->lock(); - QRasterPaintEngine::drawRects(rects, rectCount); - return; - } + IDirectFBSurface *src = d->surfaceCache->getSurface(buffer, bufsize); + // ### how does this play with setDFBColor + src->SetColor(src, 0, 0, 0, const_alpha); + const DFBRectangle rect = { 0, 0, length, 1 }; + d->surface->Blit(d->surface, src, &rect, x, y); +} - d->unlock(); +#ifdef QT_DIRECTFB_IMAGECACHE +static void cachedImageCleanupHook(qint64 key) +{ + delete imageCache.take(key); +} +void QDirectFBPaintEngine::initImageCache(int size) +{ + Q_ASSERT(size >= 0); + imageCache.setMaxCost(size); + typedef void (*_qt_image_cleanup_hook_64)(qint64); + extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; + qt_image_cleanup_hook_64 = ::cachedImageCleanupHook; +} - if (brush != Qt::NoBrush) { - d->setDFBColor(brush.color()); - d->fillRects(rects, rectCount); - } - if (d->pen != Qt::NoPen) { - d->setDFBColor(d->pen.color()); - d->drawRects(rects, rectCount); - } +#endif // QT_DIRECTFB_IMAGECACHE + +// ---- QDirectFBPaintEnginePrivate ---- + + +QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) + : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), + matrixRotShear(false), scale(NoScale), lastLockedHeight(-1), + fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), + blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), + dfbHandledClip(false), dfbDevice(0), lockedMemory(0), q(p) +{ + fb = QDirectFBScreen::instance()->dfb(); + ignoreSystemClip = QDirectFBScreen::instance()->directFBFlags() & QDirectFBScreen::IgnoreSystemClip; + surfaceCache = new SurfaceCache; } -void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount) +QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate() { - Q_D(QDirectFBPaintEngine); - d->updateClip(); - const QBrush &brush = state()->brush; - if (!d->dfbCanHandleClip() || d->matrixRotShear - || !d->simplePen || d->forceRasterPrimitives - || !d->isSimpleBrush(brush)) { - RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); - d->lock(); - QRasterPaintEngine::drawRects(rects, rectCount); - return; - } + delete surfaceCache; +} - d->unlock(); +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const +{ + // TODO: Check to see if DirectFB can handle the clip for the given rect + return dfbHandledClip; +} - if (brush != Qt::NoBrush) { - d->setDFBColor(brush.color()); - d->fillRects(rects, rectCount); - } - if (d->pen != Qt::NoPen) { - d->setDFBColor(d->pen.color()); - d->drawRects(rects, rectCount); - } +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const +{ + // TODO: Check to see if DirectFB can handle the clip for the given rect + return dfbHandledClip; } -void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount) +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const { - Q_D(QDirectFBPaintEngine); - d->updateClip(); - if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) { - RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); - d->lock(); - QRasterPaintEngine::drawLines(lines, lineCount); - return; - } + return dfbHandledClip; +} - if (d->pen != Qt::NoPen) { - d->unlock(); - d->setDFBColor(d->pen.color()); - d->drawLines(lines, lineCount); - } +bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const +{ + return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); } -void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount) +void QDirectFBPaintEnginePrivate::setClipDirty() { - Q_D(QDirectFBPaintEngine); - d->updateClip(); - if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) { - RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); - d->lock(); - QRasterPaintEngine::drawLines(lines, lineCount); - return; - } + dirtyClip = true; +} - if (d->pen != Qt::NoPen) { - d->unlock(); - d->setDFBColor(d->pen.color()); - d->drawLines(lines, lineCount); +void QDirectFBPaintEnginePrivate::lock() +{ + // We will potentially get a new pointer to the buffer after a + // lock so we need to call the base implementation of prepare so + // it updates its rasterBuffer to point to the new buffer address. + Q_ASSERT(dfbDevice); + if (dfbDevice->lockFlags() != (DSLF_WRITE|DSLF_READ) + || dfbDevice->height() != lastLockedHeight + || dfbDevice->memory() != lockedMemory) { + prepare(dfbDevice); + lastLockedHeight = dfbDevice->height(); + lockedMemory = dfbDevice->memory(); } } -void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, - const QRectF &sr, - Qt::ImageConversionFlags flags) +void QDirectFBPaintEnginePrivate::unlock() { - Q_D(QDirectFBPaintEngine); - Q_UNUSED(flags); + Q_ASSERT(dfbDevice); + dfbDevice->unlockDirectFB(); + lockedMemory = 0; +} - /* This is hard to read. The way it works is like this: +void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m) +{ + transform = m; + matrixRotShear = (transform.m12() != 0 || transform.m21() != 0); + if (qMin(transform.m11(), transform.m22()) < 0) { + scale = NegativeScale; + } else if (transform.m11() != 1 || transform.m22() != 1) { + scale = Scaled; + } else { + scale = NoScale; + } +} - - If you do not have support for preallocated surfaces and do not use an - image cache we always fall back to raster engine. +void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) +{ + lastLockedHeight = -1; + if (device->devType() == QInternal::CustomRaster) + dfbDevice = static_cast(device); + else if (device->devType() == QInternal::Pixmap) { + QPixmapData *data = static_cast(device)->pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData* dfbPixmapData = static_cast(data); + dfbDevice = static_cast(dfbPixmapData); + } - - If it's rotated/sheared/mirrored (negative scale) or we can't - clip it we fall back to raster engine. + if (dfbDevice) + surface = dfbDevice->directFBSurface(); - - If we don't cache the image, but we do have support for - preallocated surfaces we fall back to the raster engine if the - image is in a format DirectFB can't handle. + if (!surface) { + qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", + device->devType()); + } + lockedMemory = 0; + forceRasterPrimitives = dfbDevice->forceRasterPrimitives(); - - If we do cache the image but don't have support for preallocated - images and the cost of caching the image (bytes used) is higher - than the max image cache size we fall back to raster engine. - */ + surface->GetSize(surface, &fbWidth, &fbHeight); - d->updateClip(); -#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE - if (d->matrixRotShear - || d->scale == QDirectFBPaintEnginePrivate::NegativeScale - || !d->dfbCanHandleClip(r) -#ifndef QT_DIRECTFB_IMAGECACHE - || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN -#elif defined QT_NO_DIRECTFB_PREALLOCATED - || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost() -#endif - ) -#endif - { - RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr); - d->lock(); - QRasterPaintEngine::drawImage(r, image, sr, flags); - return; - } -#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE - d->unlock(); - bool release; - IDirectFBSurface *imgSurface = d->getSurface(image, &release); - d->prepareForBlit(QDirectFBScreen::hasAlpha(imgSurface)); - d->blit(r, imgSurface, sr); - if (release) { - imgSurface->ReleaseSource(imgSurface); - imgSurface->Release(imgSurface); - } -#endif + setTransform(QTransform()); + antialiased = false; + opacity = 255; + setCompositionMode(q->state()->compositionMode()); + dirtyClip = true; + setPen(q->state()->pen); + setDFBColor(pen.color()); } -void QDirectFBPaintEngine::drawImage(const QPointF &p, const QImage &img) +void QDirectFBPaintEnginePrivate::end() { - drawImage(QRectF(p, img.size()), img, img.rect()); + lockedMemory = 0; + dfbDevice = 0; + surface->ReleaseSource(surface); + surface->SetClip(surface, NULL); + surface = 0; } -void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, - const QRectF &sr) +void QDirectFBPaintEnginePrivate::setPen(const QPen &p) { - Q_D(QDirectFBPaintEngine); - d->updateClip(); + pen = p; + simplePen = (pen.style() == Qt::NoPen) || + (pen.style() == Qt::SolidLine + && !antialiased + && (pen.brush().style() == Qt::SolidPattern) + && (pen.widthF() <= 1 && scale != NoScale)); +} - if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { - RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); - d->lock(); - QRasterPaintEngine::drawPixmap(r, pixmap, sr); - } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear - || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { - RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); - const QImage *img = static_cast(pixmap.pixmapData())->buffer(DSLF_READ); - d->lock(); - QRasterPaintEngine::drawImage(r, *img, sr); +void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) +{ + blitFlagsFromCompositionMode = DSBLIT_NOFX; + drawFlagsFromCompositionMode = DSDRAW_NOFX; + + bool blend = true; + switch (mode) { + case QPainter::CompositionMode_SourceOver: + porterDuffRule = DSPD_SRC_OVER; + break; + case QPainter::CompositionMode_DestinationOver: + porterDuffRule = DSPD_DST_OVER; + break; + case QPainter::CompositionMode_Clear: + porterDuffRule = DSPD_CLEAR; + blend = false; + break; + case QPainter::CompositionMode_Source: + porterDuffRule = DSPD_SRC; + blend = false; + break; + case QPainter::CompositionMode_Destination: + porterDuffRule = DSPD_NONE; // ### need to double check this + blend = false; + return; + case QPainter::CompositionMode_SourceIn: + porterDuffRule = DSPD_SRC_IN; + break; + case QPainter::CompositionMode_DestinationIn: + porterDuffRule = DSPD_DST_IN; + break; + case QPainter::CompositionMode_SourceOut: + porterDuffRule = DSPD_SRC_OUT; + break; + case QPainter::CompositionMode_DestinationOut: + porterDuffRule = DSPD_DST_OUT; + break; + case QPainter::CompositionMode_Xor: + porterDuffRule = DSPD_XOR; + blitFlagsFromCompositionMode |= DSBLIT_XOR; + drawFlagsFromCompositionMode |= DSDRAW_XOR; + break; +// case QPainter::CompositionMode_Plus: // ??? +// porterDuffRule = DSPD_ADD; +// break; + default: + qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " + "mode %d not implemented", mode); + return; + } + // intentially not comparing with current porterDuffRule. surface might have changed. + if (blend) { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; + drawFlagsFromCompositionMode |= DSDRAW_BLEND; + } + if (opacity != 255) { + setOpacity(opacity); + } +} + +void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) +{ + opacity = op; + if (opacity == 255) { + blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; } else { - d->unlock(); - d->prepareForBlit(pixmap.hasAlphaChannel()); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - d->blit(r, s, sr); + blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; } } -void QDirectFBPaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) +void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) { - drawPixmap(QRectF(p, pm.size()), pm, pm.rect()); + const bool old = antialiased; + antialiased = bool(hints & QPainter::Antialiasing); + if (old != antialiased) { + setPen(q->state()->pen); + } } -void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, - const QPixmap &pixmap, - const QPointF &sp) +void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) { - Q_D(QDirectFBPaintEngine); - d->updateClip(); - if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { - RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); - d->lock(); - QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); - } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull() - || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { - RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); - const QImage *img = static_cast(pixmap.pixmapData())->buffer(DSLF_READ); - d->lock(); - QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); - data->fromImage(*img, Qt::AutoColor); - const QPixmap pix(data); - QRasterPaintEngine::drawTiledPixmap(r, pix, sp); + quint32 blittingFlags = blitFlagsFromCompositionMode; + if (alpha) { + surface->SetPorterDuff(surface, + (blittingFlags & DSBLIT_BLEND_COLORALPHA) + ? DSPD_NONE + : porterDuffRule); } else { - d->unlock(); - d->drawTiledPixmap(r, pixmap); + blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; + surface->SetPorterDuff(surface, DSPD_NONE); } + surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); + surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); } - -void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen) +void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) { - RASTERFALLBACK(STROKE_PATH, path, VOID_ARG(), VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::stroke(path, pen); + Q_ASSERT(surface); + const quint8 alpha = (opacity == 255 ? + color.alpha() : ALPHA_MUL(color.alpha(), opacity)); + surface->SetColor(surface, + color.red(), color.green(), color.blue(), alpha); + quint32 drawingFlags = drawFlagsFromCompositionMode; + if (alpha == 255) { + drawingFlags &= ~DSDRAW_BLEND; + } + surface->SetPorterDuff(surface, DSPD_NONE); + // PorterDuff messes up alpha values for primitives + surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); } -void QDirectFBPaintEngine::drawPath(const QPainterPath &path) +void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) { - RASTERFALLBACK(DRAW_PATH, path, VOID_ARG(), VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawPath(path); + for (int i = 0; i < n; ++i) { + const QLine l = transform.map(lines[i]); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + } } -void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount) +void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) { - RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawPoints(points, pointCount); + for (int i = 0; i < n; ++i) { + const QLine l = transform.map(lines[i]).toLine(); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + } } -void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount) +void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®ion) { - RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawPoints(points, pointCount); + Q_ASSERT(isSimpleBrush(q->state()->brush)); + setDFBColor(q->state()->brush.color()); + const QVector rects = region.rects(); + const int n = rects.size(); + fillRects(rects.constData(), n); } -void QDirectFBPaintEngine::drawEllipse(const QRectF &rect) +void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) { - RASTERFALLBACK(DRAW_ELLIPSE, rect, VOID_ARG(), VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawEllipse(rect); + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]); + surface->FillRectangle(surface, r.x(), r.y(), + r.width(), r.height()); + } } -void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount, - PolygonDrawMode mode) +void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) { - RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawPolygon(points, pointCount, mode); + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]).toRect(); + surface->FillRectangle(surface, r.x(), r.y(), + r.width(), r.height()); + } } -void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount, - PolygonDrawMode mode) +void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) { - RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawPolygon(points, pointCount, mode); + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]); + surface->DrawRectangle(surface, r.x(), r.y(), + r.width() + 1, r.height() + 1); + } } -void QDirectFBPaintEngine::drawTextItem(const QPointF &p, - const QTextItem &textItem) +void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n) { - RASTERFALLBACK(DRAW_TEXT, p, textItem.text(), VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::drawTextItem(p, textItem); + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]).toRect(); + surface->DrawRectangle(surface, r.x(), r.y(), + r.width() + 1, r.height() + 1); + } } -void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) +IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release) { - RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG()); - Q_D(QDirectFBPaintEngine); - d->lock(); - QRasterPaintEngine::fill(path, brush); -} +#ifndef QT_DIRECTFB_IMAGECACHE + *release = true; + return QDirectFBScreen::instance()->createDFBSurface(img, QDirectFBScreen::DontTrackSurface); +#else + const qint64 key = img.cacheKey(); + *release = false; + if (imageCache.contains(key)) { + return imageCache[key]->surface; + } + const int cost = cacheCost(img); + const bool cache = cost <= imageCache.maxCost(); + QDirectFBScreen *screen = QDirectFBScreen::instance(); + const QImage::Format format = (img.format() == screen->alphaPixmapFormat() || QDirectFBPixmapData::hasAlphaChannel(img) + ? screen->alphaPixmapFormat() : screen->pixelFormat()); -void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) -{ - Q_D(QDirectFBPaintEngine); - d->updateClip(); - if (d->dfbCanHandleClip(rect) && !d->matrixRotShear) { - switch (brush.style()) { - case Qt::SolidPattern: { - if (d->forceRasterPrimitives) - break; - d->unlock(); - d->setDFBColor(brush.color()); - const QRect r = d->transform.mapRect(rect).toRect(); - d->surface->FillRectangle(d->surface, r.x(), r.y(), - r.width(), r.height()); - return; } - case Qt::TexturePattern: - if (state()->brushOrigin == QPointF() && brush.transform().isIdentity()) { - //could handle certain types of brush.transform() E.g. scale - d->unlock(); - d->drawTiledPixmap(rect, brush.texture()); - return; - } - break; - default: - break; - } + IDirectFBSurface *surface = screen->copyToDFBSurface(img, format, + cache + ? QDirectFBScreen::TrackSurface + : QDirectFBScreen::DontTrackSurface); + if (cache) { + CachedImage *cachedImage = new CachedImage; + const_cast(img).data_ptr()->is_cached = true; + cachedImage->surface = surface; + imageCache.insert(key, cachedImage, cost); + } else { + *release = true; } - RASTERFALLBACK(FILL_RECT, rect, brush, VOID_ARG()); - d->lock(); - QRasterPaintEngine::fillRect(rect, brush); + return surface; +#endif } -void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color) + +void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src) { - Q_D(QDirectFBPaintEngine); - d->updateClip(); - if (!d->dfbCanHandleClip() || d->matrixRotShear || d->forceRasterPrimitives) { - RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG()); - d->lock(); - QRasterPaintEngine::fillRect(rect, color); + const QRect sr = src.toRect(); + const QRect dr = transform.mapRect(dest).toRect(); + const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; + DFBResult result; + + if (dr.size() == sr.size()) { + result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); } else { - d->unlock(); - d->setDFBColor(color); - const QRect r = d->transform.mapRect(rect).toRect(); - d->surface->FillRectangle(d->surface, r.x(), r.y(), - r.width(), r.height()); + const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; + result = surface->StretchBlit(surface, s, &sRect, &dRect); } + if (result != DFB_OK) + DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); } -void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count, - uint color) +void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, + const QPixmap &pixmap) { - Q_D(QDirectFBPaintEngine); - if (d->forceRasterPrimitives) { - RASTERFALLBACK(DRAW_COLORSPANS, count, color, VOID_ARG()); - d->lock(); - QRasterPaintEngine::drawColorSpans(spans, count, color); - } else { - color = INV_PREMUL(color); + prepareForBlit(pixmap.hasAlphaChannel()); + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData *dfbData = static_cast(data); + IDirectFBSurface *s = dfbData->directFBSurface(); + const QRect dr = transform.mapRect(dest).toRect(); + DFBResult result = DFB_OK; - QVarLengthArray lines(count); - int j = 0; - for (int i = 0; i < count; ++i) { - if (spans[i].coverage == 255) { - lines[j].x1 = spans[i].x; - lines[j].y1 = spans[i].y; - lines[j].x2 = spans[i].x + spans[i].len - 1; - lines[j].y2 = spans[i].y; - ++j; - } else { - DFBSpan span = { spans[i].x, spans[i].len }; - uint c = BYTE_MUL(color, spans[i].coverage); - // ### how does this play with setDFBColor - d->surface->SetColor(d->surface, - qRed(c), qGreen(c), qBlue(c), qAlpha(c)); - d->surface->FillSpans(d->surface, spans[i].y, &span, 1); + if (scale == NoScale && dr == QRect(0, 0, fbWidth, fbHeight)) { + result = surface->TileBlit(surface, s, 0, 0, 0); + } else if (scale == NoScale) { + const int dx = pixmap.width(); + const int dy = pixmap.height(); + const DFBRectangle rect = { 0, 0, dx, dy }; + QVarLengthArray rects; + QVarLengthArray points; + + for (int y = dr.y(); y <= dr.bottom(); y += dy) { + for (int x = dr.x(); x <= dr.right(); x += dx) { + rects.append(rect); + const DFBPoint point = { x, y }; + points.append(point); } } - if (j > 0) { - d->surface->SetColor(d->surface, - qRed(color), qGreen(color), qBlue(color), - qAlpha(color)); - d->surface->DrawLines(d->surface, lines.data(), j); + result = surface->BatchBlit(surface, s, rects.constData(), + points.constData(), points.size()); + } else { + const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); + const int dx = sr.width(); + const int dy = sr.height(); + const DFBRectangle sRect = { 0, 0, dx, dy }; + + for (int y = dr.y(); y <= dr.bottom(); y += dy) { + for (int x = dr.x(); x <= dr.right(); x += dx) { + const DFBRectangle dRect = { x, y, dx, dy }; + result = surface->StretchBlit(surface, s, &sRect, &dRect); + if (result != DFB_OK) { + y = dr.bottom() + 1; + break; + } + } } } -} -void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize, - int x, int y, int length, - uint const_alpha) -{ - Q_D(QDirectFBPaintEngine); - IDirectFBSurface *src = d->surfaceCache->getSurface(buffer, bufsize); - // ### how does this play with setDFBColor - src->SetColor(src, 0, 0, 0, const_alpha); - const DFBRectangle rect = { 0, 0, length, 1 }; - d->surface->Blit(d->surface, src, &rect, x, y); + if (result != DFB_OK) + DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); } -#ifdef QT_DIRECTFB_IMAGECACHE -static void cachedImageCleanupHook(qint64 key) +void QDirectFBPaintEnginePrivate::updateClip() { - delete imageCache.take(key); + if (!dirtyClip) + return; + + const QClipData *clipData = clip(); + if (!clipData || !clipData->enabled) { + surface->SetClip(surface, NULL); + dfbHandledClip = true; + } else if (clipData->hasRectClip) { + const DFBRegion r = { + clipData->clipRect.x(), + clipData->clipRect.y(), + clipData->clipRect.x() + clipData->clipRect.width(), + clipData->clipRect.y() + clipData->clipRect.height() + }; + surface->SetClip(surface, &r); + dfbHandledClip = true; + } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) { + dfbHandledClip = true; + } else { + dfbHandledClip = false; + } + + dirtyClip = false; } -void QDirectFBPaintEngine::initImageCache(int size) + +void QDirectFBPaintEnginePrivate::systemStateChanged() { - Q_ASSERT(size >= 0); - imageCache.setMaxCost(size); - typedef void (*_qt_image_cleanup_hook_64)(qint64); - extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; - qt_image_cleanup_hook_64 = ::cachedImageCleanupHook; + setClipDirty(); + QRasterPaintEnginePrivate::systemStateChanged(); } -#endif // QT_DIRECTFB_IMAGECACHE #endif // QT_NO_DIRECTFB -- cgit v0.12