Changeset 159463 in webkit


Ignore:
Timestamp:
Nov 18, 2013 3:33:04 PM (10 years ago)
Author:
Simon Fraser
Message:

At some scales, opaque compositing layers have garbage pixels around the edges
https://bugs.webkit.org/show_bug.cgi?id=124541

Reviewed by Dean Jackson.

Layers get marked as having opaque contents when their background is
known to paint the entire layer. However, this failed to take into
account two reasons why every pixel may not get painted.

First, subpixel layout can result in non-integral RenderLayer
bounds, which will get rounded up to an integral GraphicsLayer
size. When this happens we may not paint edge pixels.

Second, at non-integral scale factors, graphics context scaling
may cause us to not paint edge pixels.

Fix by only marking PlatformCALayers as having opaque contents
when the contentsScale of the layer is integral.

Not testable, because we can't guarantee to get garbage pixels
in a ref test, and layer dumps show GraphicsLayer's notion of
content opaqueness, not the one we set on the PlatformCALayer.

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::isIntegral):
(WebCore::clampedContentsScaleForScale):
(WebCore::GraphicsLayerCA::updateRootRelativeScale):
(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
(WebCore::GraphicsLayerCA::updateContentsOpaque):
(WebCore::GraphicsLayerCA::getTransformFromAnimationsWithMaxScaleImpact):
Drive-by typo fix.
(WebCore::GraphicsLayerCA::noteChangesForScaleSensitiveProperties):

  • platform/graphics/ca/GraphicsLayerCA.h:
  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r159460 r159463  
     12013-11-18  Simon Fraser  <simon.fraser@apple.com>
     2
     3        At some scales, opaque compositing layers have garbage pixels around the edges
     4        https://bugs.webkit.org/show_bug.cgi?id=124541
     5
     6        Reviewed by Dean Jackson.
     7       
     8        Layers get marked as having opaque contents when their background is
     9        known to paint the entire layer. However, this failed to take into
     10        account two reasons why every pixel may not get painted.
     11       
     12        First, subpixel layout can result in non-integral RenderLayer
     13        bounds, which will get rounded up to an integral GraphicsLayer
     14        size. When this happens we may not paint edge pixels.
     15       
     16        Second, at non-integral scale factors, graphics context scaling
     17        may cause us to not paint edge pixels.
     18       
     19        Fix by only marking PlatformCALayers as having opaque contents
     20        when the contentsScale of the layer is integral.
     21
     22        Not testable, because we can't guarantee to get garbage pixels
     23        in a ref test, and layer dumps show GraphicsLayer's notion of
     24        content opaqueness, not the one we set on the PlatformCALayer.
     25
     26        * platform/graphics/ca/GraphicsLayerCA.cpp:
     27        (WebCore::isIntegral):
     28        (WebCore::clampedContentsScaleForScale):
     29        (WebCore::GraphicsLayerCA::updateRootRelativeScale):
     30        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers):
     31        (WebCore::GraphicsLayerCA::updateContentsOpaque):
     32        (WebCore::GraphicsLayerCA::getTransformFromAnimationsWithMaxScaleImpact):
     33        Drive-by typo fix.
     34        (WebCore::GraphicsLayerCA::noteChangesForScaleSensitiveProperties):
     35        * platform/graphics/ca/GraphicsLayerCA.h:
     36        * rendering/RenderLayerBacking.cpp:
     37        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
     38
    1392013-11-18  David Hyatt  <hyatt@apple.com>
    240
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r159027 r159463  
    7070// of 250ms. So send a very small value instead.
    7171static const float cAnimationAlmostZeroDuration = 1e-3f;
     72
     73static inline bool isIntegral(float value)
     74{
     75    return static_cast<int>(value) == value;
     76}
     77
     78static float clampedContentsScaleForScale(float scale)
     79{
     80    // Define some limits as a sanity check for the incoming scale value
     81    // those too small to see.
     82    const float maxScale = 10.0f;
     83    const float minScale = 0.01f;
     84    return std::max(minScale, std::min(scale, maxScale));
     85}
    7286
    7387static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
     
    11191133    if (rootRelativeScaleFactor != m_rootRelativeScaleFactor) {
    11201134        m_rootRelativeScaleFactor = rootRelativeScaleFactor;
    1121         m_uncommittedChanges |= ContentsScaleChanged;
     1135        m_uncommittedChanges |= ContentsScaleChanged | ContentsOpaqueChanged;
    11221136    }
    11231137}
     
    13021316        updateContentsVisibility();
    13031317
     1318    // Note that contentsScale can affect whether the layer can be opaque.
    13041319    if (m_uncommittedChanges & ContentsOpaqueChanged)
    1305         updateContentsOpaque();
     1320        updateContentsOpaque(pageScaleFactor);
    13061321
    13071322    if (m_uncommittedChanges & BackfaceVisibilityChanged)
     
    15661581}
    15671582
    1568 void GraphicsLayerCA::updateContentsOpaque()
    1569 {
    1570     m_layer->setOpaque(m_contentsOpaque);
     1583void GraphicsLayerCA::updateContentsOpaque(float pageScaleFactor)
     1584{
     1585    bool contentsOpaque = m_contentsOpaque;
     1586    if (contentsOpaque) {
     1587        float contentsScale = clampedContentsScaleForScale(m_rootRelativeScaleFactor * pageScaleFactor * deviceScaleFactor());
     1588        if (!isIntegral(contentsScale))
     1589            contentsOpaque = false;
     1590    }
     1591   
     1592    m_layer->setOpaque(contentsOpaque);
    15711593
    15721594    if (LayerMap* layerCloneMap = m_layerClones.get()) {
    15731595        LayerMap::const_iterator end = layerCloneMap->end();
    15741596        for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
    1575             it->value->setOpaque(m_contentsOpaque);
     1597            it->value->setOpaque(contentsOpaque);
    15761598    }
    15771599}
     
    23042326               
    23052327                for (size_t i = 0; i < matrices.size(); ++i) {
    2306                     TransformationMatrix roootRelativeTransformWithAnimation = parentTransformFromRoot;
     2328                    TransformationMatrix rootRelativeTransformWithAnimation = parentTransformFromRoot;
    23072329                    TransformationMatrix layerTransformWithAnimation = layerTransform(m_position, &matrices[i]);
    23082330
    2309                     roootRelativeTransformWithAnimation.multiply(layerTransformWithAnimation);
     2331                    rootRelativeTransformWithAnimation.multiply(layerTransformWithAnimation);
    23102332                   
    2311                     float rootRelativeScale = maxScaleFromTransform(roootRelativeTransformWithAnimation);
     2333                    float rootRelativeScale = maxScaleFromTransform(rootRelativeTransformWithAnimation);
    23122334                    if (rootRelativeScale > maxScale) {
    23132335                        maxScale = rootRelativeScale;
     
    28142836}
    28152837
    2816 static float clampedContentsScaleForScale(float scale)
    2817 {
    2818     // Define some limits as a sanity check for the incoming scale value
    2819     // those too small to see.
    2820     const float maxScale = 10.0f;
    2821     const float minScale = 0.01f;
    2822     return std::max(minScale, std::min(scale, maxScale));
    2823 }
    2824 
    28252838void GraphicsLayerCA::updateContentsScale(float pageScaleFactor)
    28262839{
     
    32733286void GraphicsLayerCA::noteChangesForScaleSensitiveProperties()
    32743287{
    3275     noteLayerPropertyChanged(GeometryChanged | ContentsScaleChanged);
    3276 }
    3277 
    3278 static inline bool isIntegral(float value)
    3279 {
    3280     return static_cast<int>(value) == value;
     3288    noteLayerPropertyChanged(GeometryChanged | ContentsScaleChanged | ContentsOpaqueChanged);
    32813289}
    32823290
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h

    r158859 r159463  
    346346    void updateMasksToBounds();
    347347    void updateContentsVisibility();
    348     void updateContentsOpaque();
     348    void updateContentsOpaque(float pageScaleFactor);
    349349    void updateBackfaceVisibility();
    350350    void updateStructuralLayer();
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r159082 r159463  
    707707        // For non-root layers, background is always painted by the primary graphics layer.
    708708        ASSERT(!m_backgroundLayer);
    709         m_graphicsLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(localCompositingBounds));
     709        bool hadSubpixelRounding = LayoutSize(relativeCompositingBounds.size()) != localRawCompositingBounds.size();
     710        m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(localCompositingBounds));
    710711    }
    711712
Note: See TracChangeset for help on using the changeset viewer.