diff options
author | Steve Block <steveblock@google.com> | 2010-07-08 12:51:48 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-07-09 15:33:40 +0100 |
commit | ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24 (patch) | |
tree | bb45155550ec013adc0ad10f4d7d354c6469b022 /WebCore/platform/graphics/qt/GraphicsLayerQt.cpp | |
parent | d4b24d9a829ed7de70381c8b99fb75a07ab40466 (diff) | |
download | external_webkit-ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24.zip external_webkit-ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24.tar.gz external_webkit-ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24.tar.bz2 |
Merge WebKit at r62496: Initial merge by git
Change-Id: Ie3da0770eca22a70a632e3571f31cfabc80facb2
Diffstat (limited to 'WebCore/platform/graphics/qt/GraphicsLayerQt.cpp')
-rw-r--r-- | WebCore/platform/graphics/qt/GraphicsLayerQt.cpp | 135 |
1 files changed, 107 insertions, 28 deletions
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 8ed0d89..226f1fb 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -41,6 +41,10 @@ #include <QtGui/qpixmapcache.h> #include <QtGui/qstyleoption.h> + +#define QT_DEBUG_RECACHE 0 +#define QT_DEBUG_CACHEDUMP 0 + namespace WebCore { #ifndef QT_NO_GRAPHICSEFFECT @@ -225,7 +229,10 @@ public: int m_changeMask; QSizeF m_size; - QPixmapCache::Key m_backingStoreKey; + struct { + QPixmapCache::Key key; + QSizeF size; + } m_backingStore; #ifndef QT_NO_ANIMATION QList<QWeakPointer<QAbstractAnimation> > m_animations; #endif @@ -283,7 +290,6 @@ inline GraphicsLayerQtImpl* toGraphicsLayerQtImpl(QGraphicsItem* item) inline GraphicsLayerQtImpl* toGraphicsLayerQtImpl(QGraphicsObject* item) { - ASSERT(item); return qobject_cast<GraphicsLayerQtImpl*>(item); } @@ -339,36 +345,109 @@ const GraphicsLayerQtImpl* GraphicsLayerQtImpl::rootLayer() const QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) { - if (!m_layer->drawsContent() || m_size.isEmpty() ||!m_size.isValid()) + if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid()) return QPixmap(); - QRegion region = regionToUpdate; QPixmap pixmap; + QRegion region = regionToUpdate; + if (QPixmapCache::find(m_backingStore.key, &pixmap)) { + if (region.isEmpty()) + return pixmap; + QPixmapCache::remove(m_backingStore.key); // Remove the reference to the pixmap in the cache to avoid a detach. + } - // We might be drawing into an existing cache. - if (!QPixmapCache::find(m_backingStoreKey, &pixmap)) - region = QRegion(QRect(0, 0, m_size.width(), m_size.height())); + { + bool erased = false; - if (m_size != pixmap.size()) { - pixmap = QPixmap(m_size.toSize()); - if (!m_layer->contentsOpaque()) - pixmap.fill(Qt::transparent); - m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), m_size.toSize())); - } + // If the pixmap is not in the cache or the view has grown since last cached. + if (pixmap.isNull() || m_size != m_backingStore.size) { +#if QT_DEBUG_RECACHE + if (pixmap.isNull()) + qDebug() << "CacheMiss" << this << m_size; +#endif + bool fill = true; + QRegion newRegion; + QPixmap oldPixmap = pixmap; + + // If the pixmap is two small to hold the view contents we enlarge, otherwise just use the old (large) pixmap. + if (pixmap.width() < m_size.width() || pixmap.height() < m_size.height()) { +#if QT_DEBUG_RECACHE + qDebug() << "CacheGrow" << this << m_size; +#endif + pixmap = QPixmap(m_size.toSize()); + pixmap.fill(Qt::transparent); + newRegion = QRegion(0, 0, m_size.width(), m_size.height()); + } + +#if 1 + // Blit the contents of oldPixmap back into the cached pixmap as we are just adding new pixels. + if (!oldPixmap.isNull()) { + const QRegion cleanRegion = (QRegion(0, 0, m_size.width(), m_size.height()) + & QRegion(0, 0, m_backingStore.size.width(), m_backingStore.size.height())) - regionToUpdate; + if (!cleanRegion.isEmpty()) { +#if QT_DEBUG_RECACHE + qDebug() << "CacheBlit" << this << cleanRegion; +#endif + const QRect cleanBounds(cleanRegion.boundingRect()); + QPainter painter(&pixmap); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.drawPixmap(cleanBounds.topLeft(), oldPixmap, cleanBounds); + newRegion -= cleanRegion; + fill = false; // We cannot just fill the pixmap. + } + oldPixmap = QPixmap(); + } +#endif + region += newRegion; + if (fill && !region.isEmpty()) { // Clear the entire pixmap with the background. +#if QT_DEBUG_RECACHE + qDebug() << "CacheErase" << this << m_size << background; +#endif + erased = true; + pixmap.fill(Qt::transparent); + } + } + region &= QRegion(0, 0, m_size.width(), m_size.height()); + + // If we have something to draw its time to erase it and render the contents. + if (!region.isEmpty()) { +#if QT_DEBUG_CACHEDUMP + static int recacheCount = 0; + ++recacheCount; + qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; + pixmap.save(QString().sprintf("/tmp/%05d_A.png", recacheCount), "PNG"); +#endif + + QPainter painter(&pixmap); + GraphicsContext gc(&painter); - QPainter painter(&pixmap); - GraphicsContext gc(&painter); + painter.setClipRegion(region); - // Clear the area in cache that we're drawing into - painter.setCompositionMode(QPainter::CompositionMode_Clear); - painter.fillRect(region.boundingRect(), Qt::transparent); + if (!erased) { // Erase the area in cache that we're drawing into. + painter.setCompositionMode(QPainter::CompositionMode_Clear); + painter.fillRect(region.boundingRect(), Qt::transparent); - // Render the actual contents into the cache - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); - painter.end(); +#if QT_DEBUG_CACHEDUMP + qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; + pixmap.save(QString().sprintf("/tmp/%05d_B.png", recacheCount), "PNG"); +#endif + } - m_backingStoreKey = QPixmapCache::insert(pixmap); + // Render the actual contents into the cache. + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); + painter.end(); + +#if QT_DEBUG_CACHEDUMP + qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; + pixmap.save(QString().sprintf("/tmp/%05d_C.png", recacheCount), "PNG"); +#endif + } + m_backingStore.size = m_size; // Store the used size of the pixmap. + } + + // Finally insert into the cache and allow a reference there. + m_backingStore.key = QPixmapCache::insert(pixmap); return pixmap; } @@ -487,8 +566,9 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte if (m_state.drawsContent) { QPixmap backingStore; // We might need to recache, in case we try to paint and the cache was purged (e.g. if it was full). - if (!QPixmapCache::find(m_backingStoreKey, &backingStore) || backingStore.size() != m_size.toSize()) + if (!QPixmapCache::find(m_backingStore.key, &backingStore) || backingStore.size() != m_size.toSize()) backingStore = recache(QRegion(m_state.contentsRect)); + const QRectF bounds(0, 0, m_backingStore.size.width(), m_backingStore.size.height()); painter->drawPixmap(0, 0, backingStore); } break; @@ -674,11 +754,13 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform else #endif if (m_changeMask & DisplayChange) { +#ifndef QT_GRAPHICS_LAYER_NO_RECACHE_ON_DISPLAY_CHANGE // Recache now: all the content is ready and we don't want to wait until the paint event. // We only need to do this for HTML content, there's no point in caching directly composited // content like images or solid rectangles. if (m_pendingContent.contentType == HTMLContentType) recache(m_pendingContent.regionToUpdate); +#endif update(m_pendingContent.regionToUpdate.boundingRect()); m_pendingContent.regionToUpdate = QRegion(); } @@ -1441,10 +1523,7 @@ bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSiz if (anim->fillsBackwards()) newAnim->setCurrentTime(0); - if (anim->delay()) - QTimer::singleShot(anim->delay() * 1000, newAnim, SLOT(start())); - else - newAnim->start(); + newAnim->start(); // We synchronize the animation's clock to WebCore's timeOffset. newAnim->setCurrentTime(timeOffset * 1000); |