[iOS][WebKit2] Mark layer contents as being opaque if they are
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 01:51:56 +0000 (01:51 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 01:51:56 +0000 (01:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=130427
<rdar://problem/15540434>

Reviewed by Simon Fraser.

* Shared/mac/RemoteLayerBackingStore.h:
(WebKit::RemoteLayerBackingStore::isOpaque):
* Shared/mac/RemoteLayerBackingStore.mm:
(RemoteLayerBackingStore::RemoteLayerBackingStore):
(RemoteLayerBackingStore::ensureBackingStore):
(RemoteLayerBackingStore::encode):
(RemoteLayerBackingStore::decode):
(RemoteLayerBackingStore::display):
(RemoteLayerBackingStore::applyBackingStoreToLayer):
Move the code to set a RemoteLayerBackingStore as a CALayer's contents
from RemoteLayerTreePropertyApplier to RemoteLayerBackingStore (mostly
as a way to keep the USE(IOSURFACE) #ifs in one place).
Remove the surface() getter, because it's no longer needed, and make
image() private as it can be now (and rename it to createImageForFrontBuffer
for clarity's sake).

Add an isOpaque argument to ensureBackingStore, encode/decode it, and
add a getter. If isOpaque is true when applying backing store to the
CALayer on the UI process side, set CALayer.contentsOpaque to let CA know.

Make opaque bitmaps if not using accelerated drawing. For the IOSurface
case, we can't make opaque IOSurfaces, but telling CA that we have filled
the whole bitmap still enables similar optimizations.

* Shared/mac/RemoteLayerTreePropertyApplier.mm:
(WebKit::applyPropertiesToLayer):
Reset contentsOpaque if the layer loses its backing store.

* Shared/mac/RemoteLayerTreeTransaction.mm:
(WebKit::RemoteLayerTreeTextStream::operator<<):
(WebKit::dumpChangedLayers):
Add a bit more logging about RemoteLayerBackingStore's opaqueness
and acceleratedness.

* WebProcess/WebPage/mac/PlatformCALayerRemote.cpp:
(PlatformCALayerRemote::updateBackingStore):
(PlatformCALayerRemote::setOpaque):
Invalidate the RemoteLayerBackingStore if layer opaqueness changes.

* platform/graphics/GraphicsLayerClient.h:
(WebCore::GraphicsLayerClient::paintsOpaquelyAtNonIntegralScales):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::updateContentsOpaque):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::paintsOpaquelyAtNonIntegralScales):
* rendering/RenderLayerBacking.h:
r159463 stopped us from setting layers opaque if they were being painted
at non-integral scale. This makes sense for compositing layers, which
are painted by arbitrary elements, but the main frame's RenderView
will always paint its entire contents. To restore the opaque contents
optimization to the main frame's tiles, don't de-opaquify layers
belonging to the main frame's RenderView.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@165863 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsLayerClient.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/mac/RemoteLayerBackingStore.h
Source/WebKit2/Shared/mac/RemoteLayerBackingStore.mm
Source/WebKit2/Shared/mac/RemoteLayerTreePropertyApplier.mm
Source/WebKit2/Shared/mac/RemoteLayerTreeTransaction.mm
Source/WebKit2/WebProcess/WebPage/mac/PlatformCALayerRemote.cpp

index 6ac444e..496b0bc 100644 (file)
@@ -1,3 +1,25 @@
+2014-03-18  Tim Horton  <timothy_horton@apple.com>
+
+        [iOS][WebKit2] Mark layer contents as being opaque if they are
+        https://bugs.webkit.org/show_bug.cgi?id=130427
+        <rdar://problem/15540434>
+
+        Reviewed by Simon Fraser.
+
+        * platform/graphics/GraphicsLayerClient.h:
+        (WebCore::GraphicsLayerClient::paintsOpaquelyAtNonIntegralScales):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::updateContentsOpaque):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::paintsOpaquelyAtNonIntegralScales):
+        * rendering/RenderLayerBacking.h:
+        r159463 stopped us from setting layers opaque if they were being painted
+        at non-integral scale. This makes sense for compositing layers, which
+        are painted by arbitrary elements, but the main frame's RenderView
+        will always paint its entire contents. To restore the opaque contents
+        optimization to the main frame's tiles, don't de-opaquify layers
+        belonging to the main frame's RenderView.
+
 2014-03-18  Jeffrey Pfau  <jpfau@apple.com>
 
         Unify <media> element callback registration and unregistration
index 1a57aae..3d24224 100644 (file)
@@ -88,6 +88,7 @@ public:
     virtual float pageScaleFactor() const { return 1; }
 
     virtual float contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const { return 1; }
+    virtual bool paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const { return false; }
 
     virtual bool isTrackingRepaints() const { return false; }
 
index 5100f55..b2d92e1 100644 (file)
@@ -1655,7 +1655,7 @@ void GraphicsLayerCA::updateContentsOpaque(float pageScaleFactor)
     bool contentsOpaque = m_contentsOpaque;
     if (contentsOpaque) {
         float contentsScale = clampedContentsScaleForScale(m_rootRelativeScaleFactor * pageScaleFactor * deviceScaleFactor());
-        if (!isIntegral(contentsScale))
+        if (!isIntegral(contentsScale) && !m_client->paintsOpaquelyAtNonIntegralScales(this))
             contentsOpaque = false;
     }
     
index a8ac1ad..7a830e1 100644 (file)
@@ -2257,6 +2257,11 @@ float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer
     return compositor().contentsScaleMultiplierForNewTiles(layer);
 }
 
+bool RenderLayerBacking::paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const
+{
+    return m_isMainFrameRenderViewLayer;
+}
+
 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
 {
     compositor().didFlushChangesForLayer(m_owningLayer, layer);
index 7bf54af..bf41482 100644 (file)
@@ -177,6 +177,8 @@ public:
     virtual float deviceScaleFactor() const override;
     virtual float contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const override;
 
+    virtual bool paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const override;
+
     virtual float pageScaleFactor() const override;
     virtual void didCommitChangesForLayer(const GraphicsLayer*) const override;
     virtual bool getCurrentTransform(const GraphicsLayer*, TransformationMatrix&) const override;
index 2d56c59..15bd715 100644 (file)
@@ -1,3 +1,50 @@
+2014-03-18  Tim Horton  <timothy_horton@apple.com>
+
+        [iOS][WebKit2] Mark layer contents as being opaque if they are
+        https://bugs.webkit.org/show_bug.cgi?id=130427
+        <rdar://problem/15540434>
+
+        Reviewed by Simon Fraser.
+
+        * Shared/mac/RemoteLayerBackingStore.h:
+        (WebKit::RemoteLayerBackingStore::isOpaque):
+        * Shared/mac/RemoteLayerBackingStore.mm:
+        (RemoteLayerBackingStore::RemoteLayerBackingStore):
+        (RemoteLayerBackingStore::ensureBackingStore):
+        (RemoteLayerBackingStore::encode):
+        (RemoteLayerBackingStore::decode):
+        (RemoteLayerBackingStore::display):
+        (RemoteLayerBackingStore::applyBackingStoreToLayer):
+        Move the code to set a RemoteLayerBackingStore as a CALayer's contents
+        from RemoteLayerTreePropertyApplier to RemoteLayerBackingStore (mostly
+        as a way to keep the USE(IOSURFACE) #ifs in one place).
+        Remove the surface() getter, because it's no longer needed, and make
+        image() private as it can be now (and rename it to createImageForFrontBuffer
+        for clarity's sake).
+
+        Add an isOpaque argument to ensureBackingStore, encode/decode it, and
+        add a getter. If isOpaque is true when applying backing store to the
+        CALayer on the UI process side, set CALayer.contentsOpaque to let CA know.
+
+        Make opaque bitmaps if not using accelerated drawing. For the IOSurface
+        case, we can't make opaque IOSurfaces, but telling CA that we have filled
+        the whole bitmap still enables similar optimizations.
+
+        * Shared/mac/RemoteLayerTreePropertyApplier.mm:
+        (WebKit::applyPropertiesToLayer):
+        Reset contentsOpaque if the layer loses its backing store.
+
+        * Shared/mac/RemoteLayerTreeTransaction.mm:
+        (WebKit::RemoteLayerTreeTextStream::operator<<):
+        (WebKit::dumpChangedLayers):
+        Add a bit more logging about RemoteLayerBackingStore's opaqueness
+        and acceleratedness.
+
+        * WebProcess/WebPage/mac/PlatformCALayerRemote.cpp:
+        (PlatformCALayerRemote::updateBackingStore):
+        (PlatformCALayerRemote::setOpaque):
+        Invalidate the RemoteLayerBackingStore if layer opaqueness changes.
+
 2014-03-18  Brady Eidson  <beidson@apple.com>
 
         Make image controls menu work in WK2
index d1fcda4..245d858 100644 (file)
@@ -34,6 +34,8 @@
 #include <IOSurface/IOSurface.h>
 #endif
 
+OBJC_CLASS CALayer;
+
 // FIXME: Make PlatformCALayerRemote.cpp Objective-C so we can include WebLayer.h here and share the typedef.
 namespace WebCore {
 typedef Vector<WebCore::FloatRect, 5> RepaintRectList;
@@ -47,23 +49,22 @@ class RemoteLayerBackingStore {
 public:
     RemoteLayerBackingStore();
 
-    void ensureBackingStore(PlatformCALayerRemote*, WebCore::IntSize, float scale, bool acceleratesDrawing);
+    void ensureBackingStore(PlatformCALayerRemote*, WebCore::IntSize, float scale, bool acceleratesDrawing, bool isOpaque);
 
     void setNeedsDisplay(const WebCore::IntRect);
     void setNeedsDisplay();
 
     bool display();
 
-    RetainPtr<CGImageRef> image() const;
-#if USE(IOSURFACE)
-    RetainPtr<IOSurfaceRef> surface() const { return m_frontSurface; }
-#endif
     WebCore::IntSize size() const { return m_size; }
     float scale() const { return m_scale; }
     bool acceleratesDrawing() const { return m_acceleratesDrawing; }
+    bool isOpaque() const { return m_isOpaque; }
 
     PlatformCALayerRemote* layer() const { return m_layer; }
 
+    void applyBackingStoreToLayer(CALayer *);
+
     void encode(IPC::ArgumentEncoder&) const;
     static bool decode(IPC::ArgumentDecoder&, RemoteLayerBackingStore&);
 
@@ -78,13 +79,15 @@ public:
         return !!m_frontBuffer;
     }
 private:
-
     void drawInContext(WebCore::GraphicsContext&, CGImageRef frontImage);
 
+    RetainPtr<CGImageRef> createImageForFrontBuffer() const;
+
     PlatformCALayerRemote* m_layer;
 
     WebCore::IntSize m_size;
     float m_scale;
+    bool m_isOpaque;
 
     WebCore::Region m_dirtyRegion;
 
index deb8634..d517eb6 100644 (file)
@@ -31,6 +31,7 @@
 #import "PlatformCALayerRemote.h"
 #import "ShareableBitmap.h"
 #import "WebCoreArgumentCoders.h"
+#import <QuartzCore/QuartzCore.h>
 #import <WebCore/GraphicsContextCG.h>
 #import <WebCore/WebLayer.h>
 
@@ -38,7 +39,7 @@
 #import <mach/mach_port.h>
 #endif
 
-#if defined(__has_include) && __has_include(<ApplicationServices/ApplicationServicesPriv.h>)
+#if __has_include(<ApplicationServices/ApplicationServicesPriv.h>)
 #import <ApplicationServices/ApplicationServicesPriv.h>
 #endif
 
@@ -49,23 +50,33 @@ CGContextRef CGIOSurfaceContextCreate(IOSurfaceRef, size_t, size_t, size_t, size
 CGImageRef CGIOSurfaceContextCreateImage(CGContextRef);
 }
 
+#if __has_include(<QuartzCore/CALayerPrivate.h>)
+#import <QuartzCore/CALayerPrivate.h>
+#endif
+
+@interface CALayer (Details)
+@property BOOL contentsOpaque;
+@end
+
 using namespace WebCore;
 using namespace WebKit;
 
 RemoteLayerBackingStore::RemoteLayerBackingStore()
     : m_layer(nullptr)
+    , m_isOpaque(false)
 {
 }
 
-void RemoteLayerBackingStore::ensureBackingStore(PlatformCALayerRemote* layer, IntSize size, float scale, bool acceleratesDrawing)
+void RemoteLayerBackingStore::ensureBackingStore(PlatformCALayerRemote* layer, IntSize size, float scale, bool acceleratesDrawing, bool isOpaque)
 {
-    if (m_layer == layer && m_size == size && m_scale == scale && m_acceleratesDrawing == acceleratesDrawing)
+    if (m_layer == layer && m_size == size && m_scale == scale && m_acceleratesDrawing == acceleratesDrawing && m_isOpaque == isOpaque)
         return;
 
     m_layer = layer;
     m_size = size;
     m_scale = scale;
     m_acceleratesDrawing = acceleratesDrawing;
+    m_isOpaque = isOpaque;
 
 #if USE(IOSURFACE)
     m_frontSurface = nullptr;
@@ -78,6 +89,7 @@ void RemoteLayerBackingStore::encode(IPC::ArgumentEncoder& encoder) const
     encoder << m_size;
     encoder << m_scale;
     encoder << m_acceleratesDrawing;
+    encoder << m_isOpaque;
 
 #if USE(IOSURFACE)
     if (m_acceleratesDrawing) {
@@ -105,6 +117,9 @@ bool RemoteLayerBackingStore::decode(IPC::ArgumentDecoder& decoder, RemoteLayerB
     if (!decoder.decode(result.m_acceleratesDrawing))
         return false;
 
+    if (!decoder.decode(result.m_isOpaque))
+        return false;
+
 #if USE(IOSURFACE)
     if (result.m_acceleratesDrawing) {
         IPC::MachPort machPort;
@@ -174,7 +189,7 @@ static RetainPtr<IOSurfaceRef> createIOSurface(IntSize size)
 }
 #endif // USE(IOSURFACE)
 
-RetainPtr<CGImageRef> RemoteLayerBackingStore::image() const
+RetainPtr<CGImageRef> RemoteLayerBackingStore::createImageForFrontBuffer() const
 {
     if (!m_frontBuffer || m_acceleratesDrawing)
         return nullptr;
@@ -249,8 +264,8 @@ bool RemoteLayerBackingStore::display()
     ASSERT(!m_acceleratesDrawing);
 #endif
 
-    RetainPtr<CGImageRef> frontImage = image();
-    m_frontBuffer = ShareableBitmap::createShareable(expandedScaledSize, ShareableBitmap::SupportsAlpha);
+    RetainPtr<CGImageRef> frontImage = createImageForFrontBuffer();
+    m_frontBuffer = ShareableBitmap::createShareable(expandedScaledSize, m_isOpaque ? ShareableBitmap::NoFlags : ShareableBitmap::SupportsAlpha);
     std::unique_ptr<GraphicsContext> context = m_frontBuffer->createGraphicsContext();
     drawInContext(*context, frontImage.get());
     
@@ -347,3 +362,18 @@ void RemoteLayerBackingStore::enumerateRectsBeingDrawn(CGContextRef context, voi
         block(rectToDraw);
     }
 }
+
+void RemoteLayerBackingStore::applyBackingStoreToLayer(CALayer *layer)
+{
+#if USE(IOSURFACE)
+    if (acceleratesDrawing())
+        layer.contents = (id)m_frontSurface.get();
+    else
+        layer.contents = (id)createImageForFrontBuffer().get();
+#else
+    ASSERT(!acceleratesDrawing());
+    layer.contents = (id)createImageForFrontBuffer().get();
+#endif
+
+    layer.contentsOpaque = m_isOpaque;
+}
index b362c75..dd2e722 100644 (file)
 #import <WebCore/BlockExceptions.h>
 #import <WebCore/PlatformCAFilters.h>
 #import <WebCore/ScrollbarThemeMac.h>
+
 #if PLATFORM(IOS)
 #import <UIKit/UIView.h>
 #endif
 
-using namespace WebCore;
+#if __has_include(<QuartzCore/CALayerPrivate.h>)
+#import <QuartzCore/CALayerPrivate.h>
+#endif
+
+@interface CALayer (Details)
+@property BOOL contentsOpaque;
+@end
 
 #if PLATFORM(IOS)
 @interface UIView (WKUIViewUtilities)
@@ -56,6 +63,8 @@ using namespace WebCore;
 @end
 #endif
 
+using namespace WebCore;
+
 namespace WebKit {
 
 static RetainPtr<CGColorRef> cgColorFromColor(Color color)
@@ -172,18 +181,12 @@ static void applyPropertiesToLayer(CALayer *layer, const RemoteLayerTreeTransact
         layer.timeOffset = properties.timeOffset;
 
     if (properties.changedProperties & RemoteLayerTreeTransaction::BackingStoreChanged) {
-        if (RemoteLayerBackingStore* backingStore = properties.backingStore.get()) {
-#if USE(IOSURFACE)
-            if (backingStore->acceleratesDrawing())
-                layer.contents = (id)backingStore->surface().get();
-            else
-                layer.contents = (id)backingStore->image().get();
-#else
-            ASSERT(!backingStore->acceleratesDrawing());
-            layer.contents = (id)backingStore->image().get();
-#endif
-        } else
+        if (RemoteLayerBackingStore* backingStore = properties.backingStore.get())
+            backingStore->applyBackingStoreToLayer(layer);
+        else {
             layer.contents = nil;
+            layer.contentsOpaque = NO;
+        }
     }
 
     if (properties.changedProperties & RemoteLayerTreeTransaction::FiltersChanged)
index e0cec3b..d3ca5ef 100644 (file)
@@ -534,6 +534,7 @@ public:
     RemoteLayerTreeTextStream& operator<<(FloatRect);
     RemoteLayerTreeTextStream& operator<<(const Vector<WebCore::GraphicsLayer::PlatformLayerID>& layers);
     RemoteLayerTreeTextStream& operator<<(const FilterOperations&);
+    RemoteLayerTreeTextStream& operator<<(const RemoteLayerBackingStore& backingStore);
 
     void increaseIndent() { ++m_indent; }
     void decreaseIndent() { --m_indent; ASSERT(m_indent >= 0); }
@@ -668,6 +669,18 @@ RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const Vector<Gr
     return ts;
 }
 
+RemoteLayerTreeTextStream& RemoteLayerTreeTextStream::operator<<(const RemoteLayerBackingStore& backingStore)
+{
+    RemoteLayerTreeTextStream& ts = *this;
+    ts << backingStore.size();
+    ts << " scale=" << backingStore.scale();
+    if (backingStore.isOpaque())
+        ts << " opaque";
+    if (backingStore.acceleratesDrawing())
+        ts << " accelerated";
+    return ts;
+}
+
 void RemoteLayerTreeTextStream::writeIndent()
 {
     for (int i = 0; i < m_indent; ++i)
@@ -776,8 +789,12 @@ static void dumpChangedLayers(RemoteLayerTreeTextStream& ts, const RemoteLayerTr
         if (layerProperties.changedProperties & RemoteLayerTreeTransaction::TimeOffsetChanged)
             dumpProperty<double>(ts, "timeOffset", layerProperties.timeOffset);
 
-        if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BackingStoreChanged)
-            dumpProperty<IntSize>(ts, "backingStore", layerProperties.backingStore ? layerProperties.backingStore->size() : IntSize());
+        if (layerProperties.changedProperties & RemoteLayerTreeTransaction::BackingStoreChanged) {
+            if (const RemoteLayerBackingStore* backingStore = layerProperties.backingStore.get())
+                dumpProperty<RemoteLayerBackingStore>(ts, "backingStore", *backingStore);
+            else
+                dumpProperty<String>(ts, "backingStore", "removed");
+        }
 
         if (layerProperties.changedProperties & RemoteLayerTreeTransaction::FiltersChanged)
             dumpProperty<FilterOperations>(ts, "filters", layerProperties.filters ? *layerProperties.filters : FilterOperations());
index a8cf207..49c64f8 100644 (file)
@@ -160,7 +160,7 @@ void PlatformCALayerRemote::updateBackingStore()
     if (!m_properties.backingStore)
         return;
 
-    m_properties.backingStore->ensureBackingStore(this, expandedIntSize(m_properties.size), m_properties.contentsScale, m_acceleratesDrawing);
+    m_properties.backingStore->ensureBackingStore(this, expandedIntSize(m_properties.size), m_properties.contentsScale, m_acceleratesDrawing, m_properties.opaque);
 }
 
 void PlatformCALayerRemote::setNeedsDisplay(const FloatRect* rect)
@@ -304,6 +304,8 @@ void PlatformCALayerRemote::setOpaque(bool value)
 {
     m_properties.opaque = value;
     m_properties.notePropertiesChanged(RemoteLayerTreeTransaction::OpaqueChanged);
+
+    updateBackingStore();
 }
 
 FloatRect PlatformCALayerRemote::bounds() const