Changeset 61880 in webkit


Ignore:
Timestamp:
Jun 25, 2010 12:31:08 PM (14 years ago)
Author:
commit-queue@webkit.org
Message:

2010-06-25 Sam Magnuson <smagnuson@netflix.com>

Reviewed by Kenneth Rohde Christiansen.

[Qt] When any geometry change happens to a node it will resize the
backing cache
https://bugs.webkit.org/show_bug.cgi?id=40378

Continue to grow the cache, but never toss it. When the pixmap
cache gets too big it will be lost and created at the right size
next time.

No new tests: this is an optimization.

  • platform/graphics/qt/GraphicsLayerQt.cpp: (WebCore::GraphicsLayerQtImpl::recache): (WebCore::GraphicsLayerQtImpl::paint): (WebCore::GraphicsLayerQtImpl::flushChanges):
Location:
trunk/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r61877 r61880  
     12010-06-25  Sam Magnuson  <smagnuson@netflix.com>
     2
     3        Reviewed by Kenneth Rohde Christiansen.
     4
     5        [Qt] When any geometry change happens to a node it will resize the
     6        backing cache
     7        https://bugs.webkit.org/show_bug.cgi?id=40378
     8
     9        Continue to grow the cache, but never toss it. When the pixmap
     10        cache gets too big it will be lost and created at the right size
     11        next time.
     12
     13        No new tests: this is an optimization.
     14
     15        * platform/graphics/qt/GraphicsLayerQt.cpp:
     16        (WebCore::GraphicsLayerQtImpl::recache):
     17        (WebCore::GraphicsLayerQtImpl::paint):
     18        (WebCore::GraphicsLayerQtImpl::flushChanges):
     19
    1202010-06-25  Andreas Kling  <andreas.kling@nokia.com>
    221
  • trunk/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp

    r61086 r61880  
    4242#include <QtGui/qstyleoption.h>
    4343
     44
     45#define QT_DEBUG_RECACHE 0
     46#define QT_DEBUG_CACHEDUMP 0
     47
    4448namespace WebCore {
    4549
     
    226230
    227231    QSizeF m_size;
    228     QPixmapCache::Key m_backingStoreKey;
     232    struct {
     233        QPixmapCache::Key key;
     234        QSizeF size;
     235    } m_backingStore;
    229236#ifndef QT_NO_ANIMATION
    230237    QList<QWeakPointer<QAbstractAnimation> > m_animations;
     
    340347QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate)
    341348{
    342     if (!m_layer->drawsContent() || m_size.isEmpty() ||!m_size.isValid())
     349    if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid())
    343350        return QPixmap();
    344351
     352    QPixmap pixmap;
    345353    QRegion region = regionToUpdate;
    346     QPixmap pixmap;
    347 
    348     // We might be drawing into an existing cache.
    349     if (!QPixmapCache::find(m_backingStoreKey, &pixmap))
    350         region = QRegion(QRect(0, 0, m_size.width(), m_size.height()));
    351 
    352     if (m_size != pixmap.size()) {
    353         pixmap = QPixmap(m_size.toSize());
    354         if (!m_layer->contentsOpaque())
    355             pixmap.fill(Qt::transparent);
    356         m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), m_size.toSize()));
    357     }
    358 
    359     QPainter painter(&pixmap);
    360     GraphicsContext gc(&painter);
    361 
    362     // Clear the area in cache that we're drawing into
    363     painter.setCompositionMode(QPainter::CompositionMode_Clear);
    364     painter.fillRect(region.boundingRect(), Qt::transparent);
    365 
    366     // Render the actual contents into the cache
    367     painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
    368     m_layer->paintGraphicsLayerContents(gc, region.boundingRect());
    369     painter.end();
    370 
    371     m_backingStoreKey = QPixmapCache::insert(pixmap);
     354    if (QPixmapCache::find(m_backingStore.key, &pixmap)) {
     355        if (region.isEmpty())
     356            return pixmap;
     357        QPixmapCache::remove(m_backingStore.key); // Remove the reference to the pixmap in the cache to avoid a detach.
     358    }
     359
     360    {
     361        bool erased = false;
     362
     363        // If the pixmap is not in the cache or the view has grown since last cached.
     364        if (pixmap.isNull() || m_size != m_backingStore.size) {
     365#if QT_DEBUG_RECACHE
     366            if (pixmap.isNull())
     367                qDebug() << "CacheMiss" << this << m_size;
     368#endif
     369            bool fill = true;
     370            QRegion newRegion;
     371            QPixmap oldPixmap = pixmap;
     372
     373            // If the pixmap is two small to hold the view contents we enlarge, otherwise just use the old (large) pixmap.
     374            if (pixmap.width() < m_size.width() || pixmap.height() < m_size.height()) {
     375#if QT_DEBUG_RECACHE
     376                qDebug() << "CacheGrow" << this << m_size;
     377#endif
     378                pixmap = QPixmap(m_size.toSize());
     379                pixmap.fill(Qt::transparent);
     380                newRegion = QRegion(0, 0, m_size.width(), m_size.height());
     381            }
     382
     383#if 1
     384            // Blit the contents of oldPixmap back into the cached pixmap as we are just adding new pixels.
     385            if (!oldPixmap.isNull()) {
     386                const QRegion cleanRegion = (QRegion(0, 0, m_size.width(), m_size.height())
     387                                             & QRegion(0, 0, m_backingStore.size.width(), m_backingStore.size.height())) - regionToUpdate;
     388                if (!cleanRegion.isEmpty()) {
     389#if QT_DEBUG_RECACHE
     390                    qDebug() << "CacheBlit" << this << cleanRegion;
     391#endif
     392                    const QRect cleanBounds(cleanRegion.boundingRect());
     393                    QPainter painter(&pixmap);
     394                    painter.setCompositionMode(QPainter::CompositionMode_Source);
     395                    painter.drawPixmap(cleanBounds.topLeft(), oldPixmap, cleanBounds);
     396                    newRegion -= cleanRegion;
     397                    fill = false; // We cannot just fill the pixmap.
     398                }
     399                oldPixmap = QPixmap();
     400            }
     401#endif
     402            region += newRegion;
     403            if (fill && !region.isEmpty()) { // Clear the entire pixmap with the background.
     404#if QT_DEBUG_RECACHE
     405                qDebug() << "CacheErase" << this << m_size << background;
     406#endif
     407                erased = true;
     408                pixmap.fill(Qt::transparent);
     409            }
     410        }
     411        region &= QRegion(0, 0, m_size.width(), m_size.height());
     412
     413        // If we have something to draw its time to erase it and render the contents.
     414        if (!region.isEmpty()) {
     415#if QT_DEBUG_CACHEDUMP
     416            static int recacheCount = 0;
     417            ++recacheCount;
     418            qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size;
     419            pixmap.save(QString().sprintf("/tmp/%05d_A.png", recacheCount), "PNG");
     420#endif
     421
     422            QPainter painter(&pixmap);
     423            GraphicsContext gc(&painter);
     424
     425            painter.setClipRegion(region);
     426
     427            if (!erased) { // Erase the area in cache that we're drawing into.
     428                painter.setCompositionMode(QPainter::CompositionMode_Clear);
     429                painter.fillRect(region.boundingRect(), Qt::transparent);
     430
     431#if QT_DEBUG_CACHEDUMP
     432                qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size;
     433                pixmap.save(QString().sprintf("/tmp/%05d_B.png", recacheCount), "PNG");
     434#endif
     435            }
     436
     437            // Render the actual contents into the cache.
     438            painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
     439            m_layer->paintGraphicsLayerContents(gc, region.boundingRect());
     440            painter.end();
     441
     442#if QT_DEBUG_CACHEDUMP
     443            qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size;
     444            pixmap.save(QString().sprintf("/tmp/%05d_C.png", recacheCount), "PNG");
     445#endif
     446        }
     447        m_backingStore.size = m_size; // Store the used size of the pixmap.
     448    }
     449
     450    // Finally insert into the cache and allow a reference there.
     451    m_backingStore.key = QPixmapCache::insert(pixmap);
    372452    return pixmap;
    373453}
     
    488568            QPixmap backingStore;
    489569            // We might need to recache, in case we try to paint and the cache was purged (e.g. if it was full).
    490             if (!QPixmapCache::find(m_backingStoreKey, &backingStore) || backingStore.size() != m_size.toSize())
     570            if (!QPixmapCache::find(m_backingStore.key, &backingStore) || backingStore.size() != m_size.toSize())
    491571                backingStore = recache(QRegion(m_state.contentsRect));
     572            const QRectF bounds(0, 0, m_backingStore.size.width(), m_backingStore.size.height());
    492573            painter->drawPixmap(0, 0, backingStore);
    493574        }
     
    675756#endif
    676757    if (m_changeMask & DisplayChange) {
     758#ifndef QT_GRAPHICS_LAYER_NO_RECACHE_ON_DISPLAY_CHANGE
    677759        // Recache now: all the content is ready and we don't want to wait until the paint event.
    678760        // We only need to do this for HTML content, there's no point in caching directly composited
     
    680762        if (m_pendingContent.contentType == HTMLContentType)
    681763            recache(m_pendingContent.regionToUpdate);
     764#endif
    682765        update(m_pendingContent.regionToUpdate.boundingRect());
    683766        m_pendingContent.regionToUpdate = QRegion();
Note: See TracChangeset for help on using the changeset viewer.