Changeset 170974 in webkit


Ignore:
Timestamp:
Jul 10, 2014 1:33:05 PM (10 years ago)
Author:
timothy_horton@apple.com
Message:

Store ViewSnapshots directly on the WebBackForwardListItem
https://bugs.webkit.org/show_bug.cgi?id=134667
<rdar://problem/17082639>

Reviewed by Dan Bernstein.

Make ViewSnapshot a refcounted class. Store it directly on the back-forward item
instead of in a side map referenced by UUID. Switch to a very simple LRU eviction model for now.
This fixes a ton of snapshot management bugs; for example, we would start throwing out snapshots
in the page that was actively being interacted with *first* when evicting snapshots, instead of
preferring older snapshots. Additionally, we would not throw away snapshots when back forward items
became unreachable.

There is definitely room for improvement of the eviction mechanism, but this is closer to a time-tested implementation.

  • Shared/SessionState.h:

Keep a ViewSnapshot instead of a UUID on the BackForwardListItemState.

  • Shared/WebBackForwardListItem.h:

Fix some indented namespace contents.

(WebKit::WebBackForwardListItem::snapshot):
(WebKit::WebBackForwardListItem::setSnapshot):
(WebKit::WebBackForwardListItem::setSnapshotUUID): Deleted.
(WebKit::WebBackForwardListItem::snapshotUUID): Deleted.
Switch the snapshot getter/setter to operate on ViewSnapshots instead of UUIDs.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _takeViewSnapshot]):

  • UIProcess/API/Cocoa/WKWebViewInternal.h:
  • UIProcess/API/mac/WKView.mm:

(-[WKView _takeViewSnapshot]):

  • UIProcess/API/mac/WKViewInternal.h:
  • UIProcess/PageClient.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::takeViewSnapshot):

  • UIProcess/WebPageProxy.h:
  • UIProcess/ios/PageClientImplIOS.h:
  • UIProcess/ios/PageClientImplIOS.mm:

(WebKit::PageClientImpl::takeViewSnapshot):

  • UIProcess/mac/PageClientImpl.h:
  • UIProcess/mac/PageClientImpl.mm:

(WebKit::PageClientImpl::takeViewSnapshot):
Adopt ViewSnapshot::create, return a PassRefPtr, and class-ify ViewSnapshot.

  • UIProcess/ios/ViewGestureControllerIOS.mm:

(WebKit::ViewGestureController::beginSwipeGesture):
(WebKit::ViewGestureController::endSwipeGesture):

  • UIProcess/mac/ViewGestureController.h:
  • UIProcess/mac/ViewGestureControllerMac.mm:

(WebKit::ViewGestureController::shouldUseSnapshotForSize):
(WebKit::ViewGestureController::beginSwipeGesture):
(WebKit::ViewGestureController::endSwipeGesture):
Grab the ViewSnapshot directly from the WebBackForwardListItem, and adopt the new functions.

  • UIProcess/ios/WebMemoryPressureHandlerIOS.mm:

(WebKit::WebMemoryPressureHandler::WebMemoryPressureHandler):
Rename discardSnapshots to discardSnapshotImages, because we're really only discarding
the images; the render tree size/background color "snapshot" remains and is useful.

  • UIProcess/mac/ViewSnapshotStore.h:

(WebKit::ViewSnapshot::setRenderTreeSize):
(WebKit::ViewSnapshot::renderTreeSize):
(WebKit::ViewSnapshot::setBackgroundColor):
(WebKit::ViewSnapshot::backgroundColor):
(WebKit::ViewSnapshot::setDeviceScaleFactor):
(WebKit::ViewSnapshot::deviceScaleFactor):
(WebKit::ViewSnapshot::imageSizeInBytes):
(WebKit::ViewSnapshot::surface):
(WebKit::ViewSnapshot::size):
(WebKit::ViewSnapshot::creationTime):
Make ViewSnapshot a refcounted class.
Add create functions which take an image (or slot ID), and relevant sizes.
It is expected that a ViewSnapshot is created with an image, and it is only possible
to remove that image, never to replace it. A new ViewSnapshot is required in that case.
Add setters for things that ViewSnapshotStore sets on the snapshot after the PageClient
retrieves it from the view. Add getters for things that the ViewGestureControllers need.

Remove removeSnapshotImage, getSnapshot, and the snapshot map.

  • UIProcess/mac/ViewSnapshotStore.mm:

(WebKit::ViewSnapshotStore::~ViewSnapshotStore):
(WebKit::ViewSnapshotStore::didAddImageToSnapshot):
(WebKit::ViewSnapshotStore::willRemoveImageFromSnapshot):
Manage m_snapshotCacheSize and m_snapshotsWithImages via didAddImageToSnapshot and willRemoveImageFromSnapshot.
willRemoveImageFromSnapshot will -always- be called before the ViewSnapshot is destroyed.

(WebKit::ViewSnapshotStore::pruneSnapshots):
Switch to a simple LRU eviction model. As previously mentioned, it's possible to do better, but
this is much less broken than the previous implementation.

(WebKit::ViewSnapshotStore::recordSnapshot):
(WebKit::ViewSnapshotStore::discardSnapshotImages):
(WebKit::ViewSnapshot::create):
(WebKit::ViewSnapshot::ViewSnapshot):
(WebKit::ViewSnapshot::~ViewSnapshot):
(WebKit::ViewSnapshot::hasImage):
(WebKit::ViewSnapshot::clearImage):
(WebKit::ViewSnapshot::asLayerContents):
If a surface is Empty when it comes back from being volatile, throw away the surface
and notify the Store to remove it from m_snapshotCacheSize (via clearImage()).

(WebKit::ViewSnapshotStore::removeSnapshotImage): Deleted.
(WebKit::ViewSnapshotStore::getSnapshot): Deleted.
(WebKit::ViewSnapshotStore::discardSnapshots): Deleted.

Location:
trunk/Source/WebKit2
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r170972 r170974  
     12014-07-10  Tim Horton  <timothy_horton@apple.com>
     2
     3        Store ViewSnapshots directly on the WebBackForwardListItem
     4        https://bugs.webkit.org/show_bug.cgi?id=134667
     5        <rdar://problem/17082639>
     6
     7        Reviewed by Dan Bernstein.
     8
     9        Make ViewSnapshot a refcounted class. Store it directly on the back-forward item
     10        instead of in a side map referenced by UUID. Switch to a very simple LRU eviction model for now.
     11        This fixes a ton of snapshot management bugs; for example, we would start throwing out snapshots
     12        in the page that was actively being interacted with *first* when evicting snapshots, instead of
     13        preferring older snapshots. Additionally, we would not throw away snapshots when back forward items
     14        became unreachable.
     15
     16        There is definitely room for improvement of the eviction mechanism, but this is closer to a time-tested implementation.
     17
     18        * Shared/SessionState.h:
     19        Keep a ViewSnapshot instead of a UUID on the BackForwardListItemState.
     20
     21        * Shared/WebBackForwardListItem.h:
     22        Fix some indented namespace contents.
     23
     24        (WebKit::WebBackForwardListItem::snapshot):
     25        (WebKit::WebBackForwardListItem::setSnapshot):
     26        (WebKit::WebBackForwardListItem::setSnapshotUUID): Deleted.
     27        (WebKit::WebBackForwardListItem::snapshotUUID): Deleted.
     28        Switch the snapshot getter/setter to operate on ViewSnapshots instead of UUIDs.
     29
     30        * UIProcess/API/Cocoa/WKWebView.mm:
     31        (-[WKWebView _takeViewSnapshot]):
     32        * UIProcess/API/Cocoa/WKWebViewInternal.h:
     33        * UIProcess/API/mac/WKView.mm:
     34        (-[WKView _takeViewSnapshot]):
     35        * UIProcess/API/mac/WKViewInternal.h:
     36        * UIProcess/PageClient.h:
     37        * UIProcess/WebPageProxy.cpp:
     38        (WebKit::WebPageProxy::takeViewSnapshot):
     39        * UIProcess/WebPageProxy.h:
     40        * UIProcess/ios/PageClientImplIOS.h:
     41        * UIProcess/ios/PageClientImplIOS.mm:
     42        (WebKit::PageClientImpl::takeViewSnapshot):
     43        * UIProcess/mac/PageClientImpl.h:
     44        * UIProcess/mac/PageClientImpl.mm:
     45        (WebKit::PageClientImpl::takeViewSnapshot):
     46        Adopt ViewSnapshot::create, return a PassRefPtr, and class-ify ViewSnapshot.
     47
     48        * UIProcess/ios/ViewGestureControllerIOS.mm:
     49        (WebKit::ViewGestureController::beginSwipeGesture):
     50        (WebKit::ViewGestureController::endSwipeGesture):
     51        * UIProcess/mac/ViewGestureController.h:
     52        * UIProcess/mac/ViewGestureControllerMac.mm:
     53        (WebKit::ViewGestureController::shouldUseSnapshotForSize):
     54        (WebKit::ViewGestureController::beginSwipeGesture):
     55        (WebKit::ViewGestureController::endSwipeGesture):
     56        Grab the ViewSnapshot directly from the WebBackForwardListItem, and adopt the new functions.
     57
     58        * UIProcess/ios/WebMemoryPressureHandlerIOS.mm:
     59        (WebKit::WebMemoryPressureHandler::WebMemoryPressureHandler):
     60        Rename discardSnapshots to discardSnapshotImages, because we're really only discarding
     61        the images; the render tree size/background color "snapshot" remains and is useful.
     62
     63        * UIProcess/mac/ViewSnapshotStore.h:
     64        (WebKit::ViewSnapshot::setRenderTreeSize):
     65        (WebKit::ViewSnapshot::renderTreeSize):
     66        (WebKit::ViewSnapshot::setBackgroundColor):
     67        (WebKit::ViewSnapshot::backgroundColor):
     68        (WebKit::ViewSnapshot::setDeviceScaleFactor):
     69        (WebKit::ViewSnapshot::deviceScaleFactor):
     70        (WebKit::ViewSnapshot::imageSizeInBytes):
     71        (WebKit::ViewSnapshot::surface):
     72        (WebKit::ViewSnapshot::size):
     73        (WebKit::ViewSnapshot::creationTime):
     74        Make ViewSnapshot a refcounted class.
     75        Add create functions which take an image (or slot ID), and relevant sizes.
     76        It is expected that a ViewSnapshot is created with an image, and it is only possible
     77        to remove that image, never to replace it. A new ViewSnapshot is required in that case.
     78        Add setters for things that ViewSnapshotStore sets on the snapshot after the PageClient
     79        retrieves it from the view. Add getters for things that the ViewGestureControllers need.
     80
     81        Remove removeSnapshotImage, getSnapshot, and the snapshot map.
     82
     83        * UIProcess/mac/ViewSnapshotStore.mm:
     84        (WebKit::ViewSnapshotStore::~ViewSnapshotStore):
     85        (WebKit::ViewSnapshotStore::didAddImageToSnapshot):
     86        (WebKit::ViewSnapshotStore::willRemoveImageFromSnapshot):
     87        Manage m_snapshotCacheSize and m_snapshotsWithImages via didAddImageToSnapshot and willRemoveImageFromSnapshot.
     88        willRemoveImageFromSnapshot will -always- be called before the ViewSnapshot is destroyed.
     89
     90        (WebKit::ViewSnapshotStore::pruneSnapshots):
     91        Switch to a simple LRU eviction model. As previously mentioned, it's possible to do better, but
     92        this is much less broken than the previous implementation.
     93
     94        (WebKit::ViewSnapshotStore::recordSnapshot):
     95        (WebKit::ViewSnapshotStore::discardSnapshotImages):
     96        (WebKit::ViewSnapshot::create):
     97        (WebKit::ViewSnapshot::ViewSnapshot):
     98        (WebKit::ViewSnapshot::~ViewSnapshot):
     99        (WebKit::ViewSnapshot::hasImage):
     100        (WebKit::ViewSnapshot::clearImage):
     101        (WebKit::ViewSnapshot::asLayerContents):
     102        If a surface is Empty when it comes back from being volatile, throw away the surface
     103        and notify the Store to remove it from m_snapshotCacheSize (via clearImage()).
     104
     105        (WebKit::ViewSnapshotStore::removeSnapshotImage): Deleted.
     106        (WebKit::ViewSnapshotStore::getSnapshot): Deleted.
     107        (WebKit::ViewSnapshotStore::discardSnapshots): Deleted.
     108
    11092014-07-10  Beth Dakin  <bdakin@apple.com>
    2110
  • trunk/Source/WebKit2/Shared/SessionState.h

    r170722 r170974  
    2727#define SessionState_h
    2828
     29#include "ViewSnapshotStore.h"
    2930#include <WebCore/FloatRect.h>
    3031#include <WebCore/IntRect.h>
     
    121122
    122123    PageState pageState;
    123     // FIXME: This should hold the snapshot itself, not its UUID.
    124     String snapshotUUID;
     124    RefPtr<ViewSnapshot> snapshot;
    125125};
    126126
  • trunk/Source/WebKit2/Shared/WebBackForwardListItem.h

    r170902 r170974  
    3737
    3838namespace IPC {
    39     class ArgumentDecoder;
    40     class ArgumentEncoder;
     39class ArgumentDecoder;
     40class ArgumentEncoder;
    4141}
    4242
     
    5757    const String& url() const { return m_itemState.pageState.mainFrameState.urlString; }
    5858    const String& title() const { return m_itemState.pageState.title; }
    59    
    60     void setSnapshotUUID(const String& uuid) { m_itemState.snapshotUUID = uuid; }
    61     const String& snapshotUUID() const { return m_itemState.snapshotUUID; }
     59
     60    ViewSnapshot* snapshot() const { return m_itemState.snapshot.get(); }
     61    void setSnapshot(PassRefPtr<ViewSnapshot> snapshot) { m_itemState.snapshot = snapshot; }
    6262
    6363    static uint64_t highedUsedItemID();
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r170945 r170974  
    900900}
    901901
    902 - (WebKit::ViewSnapshot)_takeViewSnapshot
     902- (PassRefPtr<WebKit::ViewSnapshot>)_takeViewSnapshot
    903903{
    904904    float deviceScale = WKGetScreenScaleFactor();
     
    907907    snapshotSize.height *= deviceScale;
    908908
    909     WebKit::ViewSnapshot snapshot;
    910     snapshot.slotID = [WebKit::ViewSnapshotStore::snapshottingContext() createImageSlot:snapshotSize hasAlpha:YES];
     909    uint32_t slotID = [WebKit::ViewSnapshotStore::snapshottingContext() createImageSlot:snapshotSize hasAlpha:YES];
     910
     911    if (!slotID)
     912        return nullptr;
    911913
    912914    CATransform3D transform = CATransform3DMakeScale(deviceScale, deviceScale, 1);
    913     CARenderServerCaptureLayerWithTransform(MACH_PORT_NULL, self.layer.context.contextId, (uint64_t)self.layer, snapshot.slotID, 0, 0, &transform);
    914 
    915     snapshot.size = WebCore::expandedIntSize(WebCore::FloatSize(snapshotSize));
    916     snapshot.imageSizeInBytes = snapshotSize.width * snapshotSize.height * 4;
    917     snapshot.backgroundColor = _page->pageExtendedBackgroundColor();
    918 
    919     return snapshot;
     915    CARenderServerCaptureLayerWithTransform(MACH_PORT_NULL, self.layer.context.contextId, (uint64_t)self.layer, slotID, 0, 0, &transform);
     916
     917    WebCore::IntSize imageSize = WebCore::expandedIntSize(WebCore::FloatSize(snapshotSize));
     918    return WebKit::ViewSnapshot::create(slotID, imageSize, imageSize.width() * imageSize.height() * 4);
    920919}
    921920
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h

    r170445 r170974  
    5151
    5252namespace WebKit {
     53class ViewSnapshot;
    5354class WebPageProxy;
    5455struct PrintInfo;
    55 struct ViewSnapshot;
    5656}
    5757
     
    7979- (void)_restorePageStateToUnobscuredCenter:(WebCore::FloatPoint)center scale:(double)scale;
    8080
    81 - (WebKit::ViewSnapshot)_takeViewSnapshot;
     81- (PassRefPtr<WebKit::ViewSnapshot>)_takeViewSnapshot;
    8282
    8383- (void)_scrollToContentOffset:(WebCore::FloatPoint)contentOffset;
  • trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm

    r170963 r170974  
    31023102}
    31033103
    3104 - (ViewSnapshot)_takeViewSnapshot
     3104- (PassRefPtr<ViewSnapshot>)_takeViewSnapshot
    31053105{
    31063106    NSWindow *window = self.window;
    3107 
    3108     ViewSnapshot snapshot;
    31093107
    31103108    CGSWindowID windowID = (CGSWindowID)[window windowNumber];
    31113109    if (!windowID || ![window isVisible])
    3112         return snapshot;
     3110        return nullptr;
    31133111
    31143112    RetainPtr<CGImageRef> windowSnapshotImage = adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque));
     
    31423140    auto croppedSnapshotImage = adoptCF(CGImageCreateWithImageInRect(windowSnapshotImage.get(), NSRectToCGRect([window convertRectToBacking:croppedImageRect])));
    31433141
    3144     snapshot.surface = IOSurface::createFromImage(croppedSnapshotImage.get());
    3145     snapshot.surface->setIsVolatile(true);
    3146 
    3147     IntSize imageSize(CGImageGetWidth(croppedSnapshotImage.get()), CGImageGetHeight(croppedSnapshotImage.get()));
    3148     snapshot.size = imageSize;
    3149     snapshot.imageSizeInBytes = imageSize.width() * imageSize.height() * 4;
    3150     snapshot.backgroundColor = _data->_page->pageExtendedBackgroundColor();
    3151 
    3152     return snapshot;
     3142    auto surface = IOSurface::createFromImage(croppedSnapshotImage.get());
     3143    if (!surface)
     3144        return nullptr;
     3145    surface->setIsVolatile(true);
     3146
     3147    return ViewSnapshot::create(surface.get(), surface->size(), surface->totalBytes());
    31533148}
    31543149
  • trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h

    r168260 r170974  
    4848class FindIndicator;
    4949class LayerTreeContext;
     50class ViewSnapshot;
    5051class WebContext;
    5152struct ColorSpaceData;
    5253struct EditorState;
    53 struct ViewSnapshot;
    5454struct WebPageConfiguration;
    5555}
     
    8484- (CALayer *)_acceleratedCompositingModeRootLayer;
    8585
    86 - (WebKit::ViewSnapshot)_takeViewSnapshot;
     86- (PassRefPtr<WebKit::ViewSnapshot>)_takeViewSnapshot;
    8787- (void)_wheelEventWasNotHandledByWebCore:(NSEvent *)event;
    8888
  • trunk/Source/WebKit2/UIProcess/PageClient.h

    r170858 r170974  
    5858class NativeWebKeyboardEvent;
    5959class RemoteLayerTreeTransaction;
     60class ViewSnapshot;
    6061class WebContextMenuProxy;
    6162class WebEditCommandProxy;
    6263class WebPopupMenuProxy;
    63 struct ViewSnapshot;
    6464
    6565#if ENABLE(TOUCH_EVENTS)
     
    181181    virtual void setAcceleratedCompositingRootLayer(LayerOrView *) = 0;
    182182    virtual LayerOrView *acceleratedCompositingRootLayer() const = 0;
    183     virtual ViewSnapshot takeViewSnapshot() = 0;
     183    virtual PassRefPtr<ViewSnapshot> takeViewSnapshot() = 0;
    184184    virtual void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) = 0;
    185185    virtual void clearCustomSwipeViews() = 0;
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r170943 r170974  
    49454945
    49464946#if PLATFORM(COCOA)
    4947 ViewSnapshot WebPageProxy::takeViewSnapshot()
     4947PassRefPtr<ViewSnapshot> WebPageProxy::takeViewSnapshot()
    49484948{
    49494949    return m_pageClient.takeViewSnapshot();
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r170943 r170974  
    153153class RemoteScrollingCoordinatorProxy;
    154154class StringPairVector;
     155class ViewSnapshot;
    155156class VisitedLinkProvider;
    156157class WebBackForwardList;
     
    174175struct PlatformPopupMenuData;
    175176struct PrintInfo;
    176 struct ViewSnapshot;
    177177struct WebPopupItem;
    178178
     
    885885
    886886#if PLATFORM(COCOA)
    887     ViewSnapshot takeViewSnapshot();
     887    PassRefPtr<ViewSnapshot> takeViewSnapshot();
    888888#endif
    889889
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h

    r170858 r170974  
    106106    virtual LayerHostingMode viewLayerHostingMode() override { return LayerHostingMode::OutOfProcess; }
    107107
    108     virtual ViewSnapshot takeViewSnapshot() override;
     108    virtual PassRefPtr<ViewSnapshot> takeViewSnapshot() override;
    109109    virtual void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override;
    110110    virtual void clearCustomSwipeViews() override;
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm

    r170858 r170974  
    471471}
    472472
    473 ViewSnapshot PageClientImpl::takeViewSnapshot()
     473PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
    474474{
    475475    return [m_webView _takeViewSnapshot];
  • trunk/Source/WebKit2/UIProcess/ios/ViewGestureControllerIOS.mm

    r170761 r170974  
    169169
    170170    RetainPtr<UIColor> backgroundColor = [UIColor whiteColor];
    171     ViewSnapshot snapshot;
    172     if (ViewSnapshotStore::shared().getSnapshot(targetItem, snapshot)) {
     171    if (ViewSnapshot* snapshot = targetItem->snapshot()) {
    173172        float deviceScaleFactor = m_webPageProxy.deviceScaleFactor();
    174173        FloatSize swipeLayerSizeInDeviceCoordinates(liveSwipeViewFrame.size);
    175174        swipeLayerSizeInDeviceCoordinates.scale(deviceScaleFactor);
    176         if (snapshot.hasImage() && snapshot.size == swipeLayerSizeInDeviceCoordinates && deviceScaleFactor == snapshot.deviceScaleFactor)
    177             [m_snapshotView layer].contents = snapshot.asLayerContents();
    178         Color coreColor = snapshot.backgroundColor;
     175        if (snapshot->hasImage() && snapshot->size() == swipeLayerSizeInDeviceCoordinates && deviceScaleFactor == snapshot->deviceScaleFactor())
     176            [m_snapshotView layer].contents = snapshot->asLayerContents();
     177        Color coreColor = snapshot->backgroundColor();
    179178        if (coreColor.isValid())
    180179            backgroundColor = adoptNS([[UIColor alloc] initWithCGColor:cachedCGColor(coreColor, ColorSpaceDeviceRGB)]);
     
    245244    }
    246245
    247     ViewSnapshot snapshot;
    248246    m_snapshotRemovalTargetRenderTreeSize = 0;
    249     if (ViewSnapshotStore::shared().getSnapshot(targetItem, snapshot))
    250         m_snapshotRemovalTargetRenderTreeSize = snapshot.renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction;
     247    if (ViewSnapshot* snapshot = targetItem->snapshot())
     248        m_snapshotRemovalTargetRenderTreeSize = snapshot->renderTreeSize() * swipeSnapshotRemovalRenderTreeSizeTargetFraction;
    251249
    252250    // We don't want to replace the current back-forward item's snapshot
  • trunk/Source/WebKit2/UIProcess/ios/WebMemoryPressureHandlerIOS.mm

    r168739 r170974  
    4949    dispatch_set_context(source, this);
    5050    dispatch_source_set_event_handler(source, ^{
    51         ViewSnapshotStore::shared().discardSnapshots();
     51        ViewSnapshotStore::shared().discardSnapshotImages();
    5252    });
    5353    dispatch_resume(source);
  • trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.h

    r170447 r170974  
    125125    virtual void updateAcceleratedCompositingMode(const LayerTreeContext&);
    126126
    127     virtual ViewSnapshot takeViewSnapshot() override;
     127    virtual PassRefPtr<ViewSnapshot> takeViewSnapshot() override;
    128128    virtual void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override;
    129129    virtual void clearCustomSwipeViews() override;
  • trunk/Source/WebKit2/UIProcess/mac/PageClientImpl.mm

    r170447 r170974  
    508508}
    509509
    510 ViewSnapshot PageClientImpl::takeViewSnapshot()
     510PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
    511511{
    512512    return [m_wkView _takeViewSnapshot];
  • trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h

    r170774 r170974  
    5151namespace WebKit {
    5252
    53 struct ViewSnapshot;
     53class ViewSnapshot;
    5454class WebBackForwardListItem;
    5555class WebPageProxy;
  • trunk/Source/WebKit2/UIProcess/mac/ViewGestureControllerMac.mm

    r170335 r170974  
    455455{
    456456    float deviceScaleFactor = m_webPageProxy.deviceScaleFactor();
    457     if (snapshot.deviceScaleFactor != deviceScaleFactor)
     457    if (snapshot.deviceScaleFactor() != deviceScaleFactor)
    458458        return false;
    459459
    460460    FloatSize unobscuredSwipeLayerSizeInDeviceCoordinates = swipeLayerSize - FloatSize(0, topContentInset);
    461461    unobscuredSwipeLayerSizeInDeviceCoordinates.scale(deviceScaleFactor);
    462     if (snapshot.size != unobscuredSwipeLayerSizeInDeviceCoordinates)
     462    if (snapshot.size() != unobscuredSwipeLayerSizeInDeviceCoordinates)
    463463        return false;
    464464
     
    527527
    528528    RetainPtr<CGColorRef> backgroundColor = CGColorGetConstantColor(kCGColorWhite);
    529     ViewSnapshot snapshot;
    530     if (ViewSnapshotStore::shared().getSnapshot(targetItem, snapshot)) {
    531         if (shouldUseSnapshotForSize(snapshot, swipeArea.size(), topContentInset))
    532             [m_swipeSnapshotLayer setContents:snapshot.asLayerContents()];
    533 
    534         Color coreColor = snapshot.backgroundColor;
     529    if (ViewSnapshot* snapshot = targetItem->snapshot()) {
     530        if (shouldUseSnapshotForSize(*snapshot, swipeArea.size(), topContentInset))
     531            [m_swipeSnapshotLayer setContents:snapshot->asLayerContents()];
     532
     533        Color coreColor = snapshot->backgroundColor();
    535534        if (coreColor.isValid())
    536535            backgroundColor = cachedCGColor(coreColor, ColorSpaceDeviceRGB);
    537536#if USE_IOSURFACE_VIEW_SNAPSHOTS
    538         m_currentSwipeSnapshotSurface = snapshot.surface;
     537        m_currentSwipeSnapshotSurface = snapshot->surface();
    539538#endif
    540539    }
     
    631630    }
    632631
    633     ViewSnapshot snapshot;
    634632    uint64_t renderTreeSize = 0;
    635     if (ViewSnapshotStore::shared().getSnapshot(targetItem, snapshot))
    636         renderTreeSize = snapshot.renderTreeSize;
     633    if (ViewSnapshot* snapshot = targetItem->snapshot())
     634        renderTreeSize = snapshot->renderTreeSize();
    637635
    638636    m_webPageProxy.process().send(Messages::ViewGestureGeometryCollector::SetRenderTreeSizeNotificationThreshold(renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction), m_webPageProxy.pageID());
  • trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.h

    r170925 r170974  
    3030#include <WebCore/IntSize.h>
    3131#include <WebCore/IOSurface.h>
    32 #include <chrono>
    33 #include <wtf/HashMap.h>
     32#include <wtf/ListHashSet.h>
    3433#include <wtf/Noncopyable.h>
     34#include <wtf/RefCounted.h>
    3535#include <wtf/RetainPtr.h>
    3636#include <wtf/text/WTFString.h>
     
    3939
    4040#if PLATFORM(MAC)
    41 #define USE_IOSURFACE_VIEW_SNAPSHOTS true
    42 #define USE_RENDER_SERVER_VIEW_SNAPSHOTS false
     41#define USE_IOSURFACE_VIEW_SNAPSHOTS 1
     42#define USE_RENDER_SERVER_VIEW_SNAPSHOTS 0
    4343#else
    44 #define USE_IOSURFACE_VIEW_SNAPSHOTS false
    45 #define USE_RENDER_SERVER_VIEW_SNAPSHOTS true
     44#define USE_IOSURFACE_VIEW_SNAPSHOTS 0
     45#define USE_RENDER_SERVER_VIEW_SNAPSHOTS 1
    4646#endif
     47
     48namespace WebCore {
     49class IOSurface;
     50}
    4751
    4852namespace WebKit {
    4953
     54class ViewSnapshotStore;
    5055class WebBackForwardListItem;
    5156class WebPageProxy;
    5257
    53 struct ViewSnapshot {
     58class ViewSnapshot : public RefCounted<ViewSnapshot> {
     59public:
    5460#if USE_IOSURFACE_VIEW_SNAPSHOTS
    55     RefPtr<WebCore::IOSurface> surface;
    56 #endif
    57 #if USE_RENDER_SERVER_VIEW_SNAPSHOTS
    58     uint32_t slotID = 0;
     61    static PassRefPtr<ViewSnapshot> create(WebCore::IOSurface*, WebCore::IntSize, size_t imageSizeInBytes);
     62#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     63    static PassRefPtr<ViewSnapshot> create(uint32_t slotID, WebCore::IntSize, size_t imageSizeInBytes);
    5964#endif
    6065
    61     std::chrono::steady_clock::time_point creationTime;
    62     uint64_t renderTreeSize;
    63     float deviceScaleFactor;
    64     WebCore::IntSize size;
    65     size_t imageSizeInBytes = 0;
    66     WebCore::Color backgroundColor;
     66    ~ViewSnapshot();
    6767
    6868    void clearImage();
    6969    bool hasImage() const;
    7070    id asLayerContents();
     71
     72    void setRenderTreeSize(uint64_t renderTreeSize) { m_renderTreeSize = renderTreeSize; }
     73    uint64_t renderTreeSize() const { return m_renderTreeSize; }
     74
     75    void setBackgroundColor(WebCore::Color color) { m_backgroundColor = color; }
     76    WebCore::Color backgroundColor() const { return m_backgroundColor; }
     77
     78    void setDeviceScaleFactor(float deviceScaleFactor) { m_deviceScaleFactor = deviceScaleFactor; }
     79    float deviceScaleFactor() const { return m_deviceScaleFactor; }
     80
     81    size_t imageSizeInBytes() const { return m_imageSizeInBytes; }
     82#if USE_IOSURFACE_VIEW_SNAPSHOTS
     83    WebCore::IOSurface* surface() const { return m_surface.get(); }
     84#endif
     85    WebCore::IntSize size() const { return m_size; }
     86
     87private:
     88#if USE_IOSURFACE_VIEW_SNAPSHOTS
     89    explicit ViewSnapshot(WebCore::IOSurface*, WebCore::IntSize, size_t imageSizeInBytes);
     90#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     91    explicit ViewSnapshot(uint32_t slotID, WebCore::IntSize, size_t imageSizeInBytes);
     92#endif
     93
     94#if USE_IOSURFACE_VIEW_SNAPSHOTS
     95    RefPtr<WebCore::IOSurface> m_surface;
     96#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     97    uint32_t m_slotID;
     98#endif
     99
     100    size_t m_imageSizeInBytes;
     101    uint64_t m_renderTreeSize;
     102    float m_deviceScaleFactor;
     103    WebCore::IntSize m_size;
     104    WebCore::Color m_backgroundColor;
    71105};
    72106
    73107class ViewSnapshotStore {
    74108    WTF_MAKE_NONCOPYABLE(ViewSnapshotStore);
     109    friend class ViewSnapshot;
    75110public:
    76111    ViewSnapshotStore();
     
    80115
    81116    void recordSnapshot(WebPageProxy&);
    82     bool getSnapshot(WebBackForwardListItem*, ViewSnapshot&);
    83117
    84118    void disableSnapshotting() { m_enabled = false; }
    85119    void enableSnapshotting() { m_enabled = true; }
    86120
    87     void discardSnapshots();
     121    void discardSnapshotImages();
    88122
    89 #if PLATFORM(IOS)
     123#if USE_RENDER_SERVER_VIEW_SNAPSHOTS
    90124    static CAContext *snapshottingContext();
    91125#endif
    92126
    93127private:
     128    void didAddImageToSnapshot(ViewSnapshot&);
     129    void willRemoveImageFromSnapshot(ViewSnapshot&);
    94130    void pruneSnapshots(WebPageProxy&);
    95     void removeSnapshotImage(ViewSnapshot&);
    96 
    97     HashMap<String, ViewSnapshot> m_snapshotMap;
    98131
    99132    bool m_enabled;
    100133    size_t m_snapshotCacheSize;
     134
     135    ListHashSet<ViewSnapshot*> m_snapshotsWithImages;
    101136};
    102137
  • trunk/Source/WebKit2/UIProcess/mac/ViewSnapshotStore.mm

    r170925 r170974  
    3131#import <CoreGraphics/CoreGraphics.h>
    3232#import <WebCore/IOSurface.h>
    33 #import <WebCore/UUID.h>
    3433
    3534#if PLATFORM(IOS)
     
    5655ViewSnapshotStore::~ViewSnapshotStore()
    5756{
    58     discardSnapshots();
     57    discardSnapshotImages();
    5958}
    6059
     
    6564}
    6665
    67 #if PLATFORM(IOS)
     66#if USE_RENDER_SERVER_VIEW_SNAPSHOTS
    6867CAContext *ViewSnapshotStore::snapshottingContext()
    6968{
     
    8382#endif
    8483
    85 void ViewSnapshotStore::removeSnapshotImage(ViewSnapshot& snapshot)
    86 {
    87     if (!snapshot.hasImage())
    88         return;
    89 
    90     m_snapshotCacheSize -= snapshot.imageSizeInBytes;
    91     snapshot.clearImage();
     84void ViewSnapshotStore::didAddImageToSnapshot(ViewSnapshot& snapshot)
     85{
     86    bool isNewEntry = m_snapshotsWithImages.add(&snapshot).isNewEntry;
     87    ASSERT_UNUSED(isNewEntry, isNewEntry);
     88    m_snapshotCacheSize += snapshot.imageSizeInBytes();
     89}
     90
     91void ViewSnapshotStore::willRemoveImageFromSnapshot(ViewSnapshot& snapshot)
     92{
     93    bool removed = m_snapshotsWithImages.remove(&snapshot);
     94    ASSERT_UNUSED(removed, removed);
     95    m_snapshotCacheSize -= snapshot.imageSizeInBytes();
    9296}
    9397
     
    97101        return;
    98102
    99     uint32_t currentIndex = webPageProxy.backForwardList().currentIndex();
    100     uint32_t maxDistance = 0;
    101     auto mostDistantSnapshotIter = m_snapshotMap.end();
    102     auto backForwardEntries = webPageProxy.backForwardList().entries();
    103 
    104     // First, try to evict the snapshot for the page farthest from the current back-forward item.
    105     for (uint32_t i = 0, entryCount = webPageProxy.backForwardList().entries().size(); i < entryCount; i++) {
    106         uint32_t distance = std::max(currentIndex, i) - std::min(currentIndex, i);
    107 
    108         if (i == currentIndex || distance < maxDistance)
    109             continue;
    110 
    111         WebBackForwardListItem* item = backForwardEntries[i].get();
    112         String snapshotUUID = item->snapshotUUID();
    113         if (snapshotUUID.isEmpty())
    114             continue;
    115 
    116         const auto& snapshotIter = m_snapshotMap.find(snapshotUUID);
    117         if (snapshotIter == m_snapshotMap.end())
    118             continue;
    119 
    120         // We're only interested in evicting snapshots that still have images.
    121         if (!snapshotIter->value.hasImage())
    122             continue;
    123 
    124         mostDistantSnapshotIter = snapshotIter;
    125         maxDistance = distance;
     103    ASSERT(!m_snapshotsWithImages.isEmpty());
     104
     105    // FIXME: We have enough information to do smarter-than-LRU eviction (making use of the back-forward lists, etc.)
     106
     107    m_snapshotsWithImages.first()->clearImage();
     108}
     109
     110void ViewSnapshotStore::recordSnapshot(WebPageProxy& webPageProxy)
     111{
     112    WebBackForwardListItem* item = webPageProxy.backForwardList().currentItem();
     113
     114    if (!m_enabled)
     115        return;
     116
     117    if (!item)
     118        return;
     119
     120    pruneSnapshots(webPageProxy);
     121
     122    RefPtr<ViewSnapshot> snapshot = webPageProxy.takeViewSnapshot();
     123    if (!snapshot || !snapshot->hasImage())
     124        return;
     125
     126    snapshot->setRenderTreeSize(webPageProxy.renderTreeSize());
     127    snapshot->setDeviceScaleFactor(webPageProxy.deviceScaleFactor());
     128    snapshot->setBackgroundColor(webPageProxy.pageExtendedBackgroundColor());
     129
     130    item->setSnapshot(snapshot.release());
     131}
     132
     133void ViewSnapshotStore::discardSnapshotImages()
     134{
     135    while (!m_snapshotsWithImages.isEmpty())
     136        m_snapshotsWithImages.first()->clearImage();
     137}
     138
     139
     140#if USE_IOSURFACE_VIEW_SNAPSHOTS
     141PassRefPtr<ViewSnapshot> ViewSnapshot::create(IOSurface* surface, IntSize size, size_t imageSizeInBytes)
     142{
     143    return adoptRef(new ViewSnapshot(surface, size, imageSizeInBytes));
     144}
     145#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     146PassRefPtr<ViewSnapshot> ViewSnapshot::create(uint32_t slotID, IntSize size, size_t imageSizeInBytes)
     147{
     148    return adoptRef(new ViewSnapshot(slotID, size, imageSizeInBytes));
     149}
     150#endif
     151
     152#if USE_IOSURFACE_VIEW_SNAPSHOTS
     153ViewSnapshot::ViewSnapshot(IOSurface* surface, IntSize size, size_t imageSizeInBytes)
     154    : m_surface(surface)
     155#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     156ViewSnapshot::ViewSnapshot(uint32_t slotID, IntSize size, size_t imageSizeInBytes)
     157    : m_slotID(slotID)
     158#endif
     159    , m_imageSizeInBytes(imageSizeInBytes)
     160    , m_size(size)
     161{
     162    if (hasImage())
     163        ViewSnapshotStore::shared().didAddImageToSnapshot(*this);
     164}
     165
     166ViewSnapshot::~ViewSnapshot()
     167{
     168    clearImage();
     169}
     170
     171bool ViewSnapshot::hasImage() const
     172{
     173#if USE_IOSURFACE_VIEW_SNAPSHOTS
     174    return m_surface;
     175#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     176    return m_slotID;
     177#endif
     178}
     179
     180void ViewSnapshot::clearImage()
     181{
     182    if (!hasImage())
     183        return;
     184
     185    ViewSnapshotStore::shared().willRemoveImageFromSnapshot(*this);
     186
     187#if USE_IOSURFACE_VIEW_SNAPSHOTS
     188    m_surface = nullptr;
     189#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     190    [ViewSnapshotStore::snapshottingContext() deleteSlot:m_slotID];
     191    m_slotID = 0;
     192#endif
     193    m_imageSizeInBytes = 0;
     194}
     195
     196id ViewSnapshot::asLayerContents()
     197{
     198#if USE_IOSURFACE_VIEW_SNAPSHOTS
     199    if (!m_surface)
     200        return nullptr;
     201
     202    if (m_surface->setIsVolatile(false) != IOSurface::SurfaceState::Valid) {
     203        clearImage();
     204        return nullptr;
    126205    }
    127206
    128     if (mostDistantSnapshotIter != m_snapshotMap.end()) {
    129         removeSnapshotImage(mostDistantSnapshotIter->value);
    130         return;
    131     }
    132 
    133     // If we can't find a most distant item (perhaps because all the snapshots are from
    134     // a different WebPageProxy's back-forward list), we should evict the the oldest item.
    135     std::chrono::steady_clock::time_point oldestSnapshotTime = std::chrono::steady_clock::time_point::max();
    136     String oldestSnapshotUUID;
    137 
    138     for (const auto& uuidAndSnapshot : m_snapshotMap) {
    139         if (uuidAndSnapshot.value.creationTime < oldestSnapshotTime && uuidAndSnapshot.value.hasImage()) {
    140             oldestSnapshotTime = uuidAndSnapshot.value.creationTime;
    141             oldestSnapshotUUID = uuidAndSnapshot.key;
    142         }
    143     }
    144 
    145     const auto& snapshotIter = m_snapshotMap.find(oldestSnapshotUUID);
    146     removeSnapshotImage(snapshotIter->value);
    147 }
    148 
    149 void ViewSnapshotStore::recordSnapshot(WebPageProxy& webPageProxy)
    150 {
    151     WebBackForwardListItem* item = webPageProxy.backForwardList().currentItem();
    152 
    153     if (!m_enabled)
    154         return;
    155 
    156     if (!item)
    157         return;
    158 
    159     pruneSnapshots(webPageProxy);
    160 
    161     ViewSnapshot snapshot = webPageProxy.takeViewSnapshot();
    162     if (!snapshot.hasImage())
    163         return;
    164 
    165     String oldSnapshotUUID = item->snapshotUUID();
    166     if (!oldSnapshotUUID.isEmpty()) {
    167         const auto& oldSnapshotIter = m_snapshotMap.find(oldSnapshotUUID);
    168         if (oldSnapshotIter != m_snapshotMap.end()) {
    169             removeSnapshotImage(oldSnapshotIter->value);
    170             m_snapshotMap.remove(oldSnapshotIter);
    171         }
    172     }
    173 
    174     snapshot.creationTime = std::chrono::steady_clock::now();
    175     snapshot.renderTreeSize = webPageProxy.renderTreeSize();
    176     snapshot.deviceScaleFactor = webPageProxy.deviceScaleFactor();
    177 
    178     item->setSnapshotUUID(createCanonicalUUIDString());
    179 
    180     m_snapshotMap.add(item->snapshotUUID(), snapshot);
    181     m_snapshotCacheSize += snapshot.imageSizeInBytes;
    182 }
    183 
    184 bool ViewSnapshotStore::getSnapshot(WebBackForwardListItem* item, ViewSnapshot& snapshot)
    185 {
    186     if (item->snapshotUUID().isEmpty())
    187         return false;
    188 
    189     const auto& snapshotIterator = m_snapshotMap.find(item->snapshotUUID());
    190     if (snapshotIterator == m_snapshotMap.end())
    191         return false;
    192     snapshot = snapshotIterator->value;
    193     return true;
    194 }
    195 
    196 void ViewSnapshotStore::discardSnapshots()
    197 {
    198     for (auto& snapshot : m_snapshotMap.values())
    199         removeSnapshotImage(snapshot);
    200 }
    201 
    202 bool ViewSnapshot::hasImage() const
    203 {
    204     return imageSizeInBytes;
    205 }
    206 
    207 void ViewSnapshot::clearImage()
    208 {
    209 #if USE_IOSURFACE_VIEW_SNAPSHOTS
    210     surface = nullptr;
    211 #elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
    212     if (slotID)
    213         [ViewSnapshotStore::snapshottingContext() deleteSlot:slotID];
    214     slotID = 0;
    215 #endif
    216     imageSizeInBytes = 0;
    217 }
    218 
    219 id ViewSnapshot::asLayerContents()
    220 {
    221 #if USE_IOSURFACE_VIEW_SNAPSHOTS
    222     if (!surface)
    223         return nullptr;
    224 
    225     // FIXME: This should destroy the surface and inform the ViewSnapshotStore to reduce m_snapshotCacheSize.
    226     if (surface->setIsVolatile(false) != IOSurface::SurfaceState::Valid)
    227         return nullptr;
    228 
    229     return (id)surface->surface();
    230 #elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
    231     return [CAContext objectForSlot:slotID];
     207    return (id)m_surface->surface();
     208#elif USE_RENDER_SERVER_VIEW_SNAPSHOTS
     209    return [CAContext objectForSlot:m_slotID];
    232210#endif
    233211}
Note: See TracChangeset for help on using the changeset viewer.