Changeset 54541 in webkit


Ignore:
Timestamp:
Feb 9, 2010 2:07:58 AM (14 years ago)
Author:
eric@webkit.org
Message:

2010-02-09 Noam Rosenthal <noam.rosenthal@nokia.com>

Reviewed by Kenneth Rohde Christiansen.

[Qt] the above website does not render properly when in compositing mode
https://bugs.webkit.org/show_bug.cgi?id=34681

http://media.24ways.org/2009/15/spinner-alt.html now renders correctly

  • platform/graphics/qt/GraphicsLayerQt.cpp: (WebCore::MaskEffectQt::MaskEffectQt): implement mask as QGraphicsEffect (WebCore::MaskEffectQt::draw): reimp (WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): init the effect (WebCore::GraphicsLayerQtImpl::paint): no need for drawContents (WebCore::GraphicsLayerQtImpl::flushChanges): make sure to update the mask layer, not just the actual children
Location:
trunk/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r54537 r54541  
     12010-02-09  Noam Rosenthal  <noam.rosenthal@nokia.com>
     2
     3        Reviewed by Kenneth Rohde Christiansen.
     4
     5        [Qt] the above website does not render properly when in compositing mode
     6        https://bugs.webkit.org/show_bug.cgi?id=34681
     7
     8        http://media.24ways.org/2009/15/spinner-alt.html now renders correctly
     9
     10        * platform/graphics/qt/GraphicsLayerQt.cpp:
     11        (WebCore::MaskEffectQt::MaskEffectQt): implement mask as
     12        QGraphicsEffect
     13        (WebCore::MaskEffectQt::draw): reimp
     14        (WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): init the effect
     15        (WebCore::GraphicsLayerQtImpl::paint): no need for drawContents
     16        (WebCore::GraphicsLayerQtImpl::flushChanges): make sure to update the
     17        mask layer, not just the actual children
     18
    1192010-02-09  Kwang Yul Seo  <skyul@company100.net>
    220
  • trunk/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp

    r54344 r54541  
    4444
    4545namespace WebCore {
     46
     47class MaskEffectQt : public QGraphicsEffect {
     48public:
     49    MaskEffectQt(QObject* parent, QGraphicsItem* maskLayer)
     50            : QGraphicsEffect(parent)
     51            , m_maskLayer(maskLayer)
     52    {
     53    }
     54
     55    void draw(QPainter* painter)
     56    {
     57        // this is a modified clone of QGraphicsOpacityEffect.
     58        // It's more efficient to do it this way because
     59        // (a) we don't need the QBrush abstraction - we always end up using QGraphicsItem::paint from the mask layer
     60        // (b) QGraphicsOpacityEffect detaches the pixmap, which is inefficient on OpenGL.
     61        QPixmap maskPixmap(sourceBoundingRect().toAlignedRect().size());
     62
     63        // we need to do this so the pixmap would have hasAlpha()
     64        maskPixmap.fill(Qt::transparent);
     65        QPainter maskPainter(&maskPixmap);
     66        QStyleOptionGraphicsItem option;
     67        option.exposedRect = option.rect = maskPixmap.rect();
     68        maskPainter.setRenderHints(painter->renderHints(), true);
     69        m_maskLayer->paint(&maskPainter, &option, 0);
     70        maskPainter.end();
     71        QPoint offset;
     72        QPixmap srcPixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, QGraphicsEffect::NoPad);
     73
     74        // we have to use another intermediate pixmap, to make sure the mask applies only to this item
     75        // and doesn't modify pixels already painted into this paint-device
     76        QPixmap pixmap(srcPixmap.size());
     77        pixmap.fill(Qt::transparent);
     78
     79        if (pixmap.isNull())
     80            return;
     81
     82        QPainter pixmapPainter(&pixmap);
     83        pixmapPainter.setRenderHints(painter->renderHints());
     84        pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
     85        // We use drawPixmap rather than detaching, because it's more efficient on OpenGL
     86        pixmapPainter.drawPixmap(0, 0, srcPixmap);
     87        pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
     88        pixmapPainter.drawPixmap(0, 0, maskPixmap);
     89        pixmapPainter.end();
     90        painter->drawPixmap(offset, pixmap);
     91    }
     92
     93    QGraphicsItem* m_maskLayer;
     94};
    4695
    4796class GraphicsLayerQtImpl : public QGraphicsObject {
     
    89138    // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt
    90139    void setBaseTransform(const QTransform&);
    91     void drawContents(QPainter*, const QRectF&, bool mask = false);
    92140
    93141    // let the compositor-API tell us which properties were changed
     
    122170    bool m_transformAnimationRunning;
    123171    bool m_opacityAnimationRunning;
     172    QWeakPointer<MaskEffectQt> m_maskEffect;
    124173
    125174    struct ContentData {
     
    184233    , m_layer(newLayer)
    185234    , m_transformAnimationRunning(false)
     235    , m_opacityAnimationRunning(false)
    186236    , m_changeMask(NoChanges)
    187237{
     
    278328void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
    279329{
    280     if (m_state.maskLayer && m_state.maskLayer->platformLayer()) {
    281         // FIXME: see if this is better done somewhere else
    282         GraphicsLayerQtImpl* otherMask = static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer());
    283         otherMask->flushChanges(true);
    284        
    285         // CSS3 mask and QGraphicsOpacityEffect are the same thing! we just need to convert...
    286         // The conversion is as fast as we can make it - we render the layer once and send it to the QGraphicsOpacityEffect
    287         if (!graphicsEffect()) {
    288             QPixmap mask(QSize(m_state.maskLayer->size().width(), m_state.maskLayer->size().height()));
    289             mask.fill(Qt::transparent);
    290             {
    291                 QPainter p(&mask);
    292                 p.setRenderHints(painter->renderHints(), true);
    293                 p.setCompositionMode(QPainter::CompositionMode_Source);
    294                 static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer())->drawContents(&p, option->exposedRect, true);
    295             }
    296             QGraphicsOpacityEffect* opacityEffect = new QGraphicsOpacityEffect(this);
    297             opacityEffect->setOpacity(1);
    298             opacityEffect->setOpacityMask(QBrush(mask));
    299             setGraphicsEffect(opacityEffect);
    300         }
    301     }
    302     drawContents(painter, option->exposedRect);
    303 }
    304 
    305 void GraphicsLayerQtImpl::drawContents(QPainter* painter, const QRectF& exposedRect, bool mask)
    306 {
    307330    if (m_currentContent.backgroundColor.isValid())
    308         painter->fillRect(exposedRect, QColor(m_currentContent.backgroundColor));
     331        painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor));
    309332
    310333    switch (m_currentContent.contentType) {
     334    case HTMLContentType:
     335        if (m_state.drawsContent) {
     336            // this is the expensive bit. we try to minimize calls to this area by proper caching
     337            GraphicsContext gc(painter);
     338            m_layer->paintGraphicsLayerContents(gc, option->exposedRect.toAlignedRect());
     339        }
     340        break;
    311341    case PixmapContentType:
    312342        painter->drawPixmap(m_state.contentsRect, m_currentContent.pixmap);
     
    314344    case ColorContentType:
    315345        painter->fillRect(m_state.contentsRect, m_currentContent.contentsBackgroundColor);
    316         break;
    317     default:
    318         if (m_state.drawsContent) {
    319             // this is the "expensive" bit. we try to minimize calls to this neck of the woods by proper caching
    320             GraphicsContext gc(painter);
    321             m_layer->paintGraphicsLayerContents(gc, exposedRect.toAlignedRect());
    322         }
    323346        break;
    324347    }
     
    382405        // we can't paint here, because we don't know if the mask layer
    383406        // itself is ready... we'll have to wait till this layer tries to paint
     407        setFlag(ItemClipsChildrenToShape, m_layer->maskLayer() || m_layer->masksToBounds());
    384408        setGraphicsEffect(0);
    385         if (m_layer->maskLayer())
    386             setFlag(ItemClipsChildrenToShape, true);
    387         else
    388             setFlag(ItemClipsChildrenToShape, m_layer->masksToBounds());
    389         update();
     409        if (m_layer->maskLayer()) {
     410            if (GraphicsLayerQtImpl* mask = qobject_cast<GraphicsLayerQtImpl*>(m_layer->maskLayer()->platformLayer()->toGraphicsObject())) {
     411                mask->m_maskEffect = new MaskEffectQt(this, mask);
     412                mask->setCacheMode(NoCache);
     413                setGraphicsEffect(mask->m_maskEffect.data());
     414            }
     415        }
    390416    }
    391417
     
    408434    }
    409435
    410     if (m_changeMask & (ContentChange | DrawsContentChange)) {
     436    if (m_changeMask & (ContentChange | DrawsContentChange | MaskLayerChange)) {
    411437        switch (m_pendingContent.contentType) {
    412438        case PixmapContentType:
     
    420446        case ColorContentType:
    421447            // no point in caching a solid-color rectangle
    422             setCacheMode(QGraphicsItem::NoCache);
     448            setCacheMode(m_layer->maskLayer() ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
    423449            if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor)
    424450                update();
     
    435461            if (!m_state.drawsContent && m_layer->drawsContent())
    436462                update();
    437                 if (m_layer->drawsContent()) {
     463                if (m_layer->drawsContent() && !m_maskEffect) {
    438464                    const QGraphicsItem::CacheMode mewCacheMode = isTransformAnimationRunning() ? ItemCoordinateCache : DeviceCoordinateCache;
    439465
     
    474500        prepareGeometryChange();
    475501
    476     if (m_changeMask & DisplayChange)
     502    if (m_maskEffect)
     503        m_maskEffect.data()->update();
     504    else if (m_changeMask & DisplayChange)
    477505        update(m_pendingContent.regionToUpdate.boundingRect());
    478506
     
    510538        return;   
    511539
    512     const QList<QGraphicsItem*> children = childItems();
     540    QList<QGraphicsItem*> children = childItems();
     541    if (m_state.maskLayer)
     542        children.append(m_state.maskLayer->platformLayer());
    513543
    514544    for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) {
Note: See TracChangeset for help on using the changeset viewer.