+2014-05-08 Tim Horton <timothy_horton@apple.com>
+
+ [iOS WebKit2] Flush RemoteLayerBackingStore contexts on a secondary queue
+ https://bugs.webkit.org/show_bug.cgi?id=132667
+ <rdar://problem/15349483>
+
+ Reviewed by Darin Adler.
+
+ * Shared/mac/RemoteLayerBackingStore.h:
+ * Shared/mac/RemoteLayerBackingStore.mm:
+ (WebKit::RemoteLayerBackingStore::takeFrontContextPendingFlush):
+ (WebKit::RemoteLayerBackingStore::flush): Deleted.
+ Add takeFrontContextPendingFlush, which returns the painted-but-not-yet-flushed front context,
+ and drops our reference to it. This needs to be called on all backing store between paints.
+
+ * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+ (WebKit::RemoteLayerTreeDrawingArea::BackingStoreFlusher::hasFlushed):
+ * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+ (WebKit::RemoteLayerTreeDrawingArea::RemoteLayerTreeDrawingArea):
+ (WebKit::RemoteLayerTreeDrawingArea::~RemoteLayerTreeDrawingArea):
+ (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
+ (WebKit::RemoteLayerTreeDrawingArea::BackingStoreFlusher::create):
+ (WebKit::RemoteLayerTreeDrawingArea::BackingStoreFlusher::BackingStoreFlusher):
+ (WebKit::RemoteLayerTreeDrawingArea::BackingStoreFlusher::flush):
+ (WebKit::flushBackingStoreChangesInTransaction): Deleted.
+ Flush backing store and send the layer tree commit to the UI process from a dispatch queue.
+ We will only ever have a single commit in flight at a time, and there's a new
+ RELEASE_ASSERT to ensure that is the case.
+ We package up the commit on the main thread; the queue calls CGContextFlush
+ on all of the newly painted contexts and then tosses the commit over to the UI process.
+ This is a win in many cases because the Web process main thread can go ahead
+ and do other non-painting tasks while the queue is blocked on painting.
+
2014-05-08 Tim Horton <timothy_horton@apple.com>
[wk2] Don't use the XPC-based plugin process for Adobe Reader
#include "GraphicsLayerCARemote.h"
#include <WebCore/GraphicsLayerClient.h>
#include <WebCore/Timer.h>
+#include <atomic>
+#include <dispatch/dispatch.h>
#include <wtf/HashMap.h>
namespace WebCore {
class PlatformCALayer;
}
+namespace IPC {
+class MessageEncoder;
+}
+
namespace WebKit {
class RemoteLayerTreeContext;
WebCore::TiledBacking* mainFrameTiledBacking() const;
+ class BackingStoreFlusher : public ThreadSafeRefCounted<BackingStoreFlusher> {
+ public:
+ static PassRefPtr<BackingStoreFlusher> create(IPC::Connection*, std::unique_ptr<IPC::MessageEncoder>, Vector<RetainPtr<CGContextRef>>);
+
+ void flush();
+ bool hasFlushed() const { return m_hasFlushed; }
+
+ private:
+ BackingStoreFlusher(IPC::Connection*, std::unique_ptr<IPC::MessageEncoder>, Vector<RetainPtr<CGContextRef>>);
+
+ RefPtr<IPC::Connection> m_connection;
+ std::unique_ptr<IPC::MessageEncoder> m_commitEncoder;
+ Vector<RetainPtr<CGContextRef>> m_contextsToFlush;
+
+ std::atomic<bool> m_hasFlushed;
+ };
+
std::unique_ptr<RemoteLayerTreeContext> m_remoteLayerTreeContext;
std::unique_ptr<WebCore::GraphicsLayer> m_rootLayer;
bool m_waitingForBackingStoreSwap;
bool m_hadFlushDeferredWhileWaitingForBackingStoreSwap;
+
+ dispatch_queue_t m_commitQueue;
+ RefPtr<BackingStoreFlusher> m_pendingBackingStoreFlusher;
};
DRAWING_AREA_TYPE_CASTS(RemoteLayerTreeDrawingArea, type() == DrawingAreaTypeRemoteLayerTree);
#import "RemoteScrollingCoordinator.h"
#import "RemoteScrollingCoordinatorTransaction.h"
#import "WebPage.h"
+#import "WebProcess.h"
#import <WebCore/Frame.h>
#import <WebCore/FrameView.h>
#import <WebCore/MainFrame.h>
#if PLATFORM(IOS)
webPage->corePage()->settings().setDelegatesPageScaling(true);
#endif
+
+ m_commitQueue = dispatch_queue_create("com.apple.WebKit.WebContent.RemoteLayerTreeDrawingArea.CommitQueue", nullptr);
}
RemoteLayerTreeDrawingArea::~RemoteLayerTreeDrawingArea()
{
+ dispatch_release(m_commitQueue);
}
void RemoteLayerTreeDrawingArea::setNeedsDisplay()
flushLayers();
}
-static void flushBackingStoreChangesInTransaction(RemoteLayerTreeTransaction& transaction)
-{
- for (RefPtr<PlatformCALayerRemote> layer : transaction.changedLayers()) {
- if (!layer->properties().changedProperties & RemoteLayerTreeTransaction::BackingStoreChanged)
- return;
-
- if (RemoteLayerBackingStore* backingStore = layer->properties().backingStore.get())
- backingStore->flush();
- }
-}
-
void RemoteLayerTreeDrawingArea::flushLayers()
{
if (!m_rootLayer)
return;
}
+ RELEASE_ASSERT(!m_pendingBackingStoreFlusher || m_pendingBackingStoreFlusher->hasFlushed());
+
m_webPage->layoutIfNeeded();
FloatRect visibleRect(FloatPoint(), m_viewSize);
toRemoteScrollingCoordinator(m_webPage->scrollingCoordinator())->buildTransaction(scrollingTransaction);
#endif
- // FIXME: Move flushing backing store and sending CommitLayerTree onto a background thread.
- flushBackingStoreChangesInTransaction(layerTransaction);
-
m_waitingForBackingStoreSwap = true;
- m_webPage->send(Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree(layerTransaction, scrollingTransaction));
+
+ Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree message(layerTransaction, scrollingTransaction);
+ auto commitEncoder = std::make_unique<IPC::MessageEncoder>(Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree::receiverName(), Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree::name(), m_webPage->pageID());
+ commitEncoder->encode(message.arguments());
bool hadAnyChangedBackingStore = false;
+ Vector<RetainPtr<CGContextRef>> contextsToFlush;
for (auto& layer : layerTransaction.changedLayers()) {
- if (layer->properties().changedProperties & RemoteLayerTreeTransaction::LayerChanges::BackingStoreChanged)
+ if (layer->properties().changedProperties & RemoteLayerTreeTransaction::LayerChanges::BackingStoreChanged) {
hadAnyChangedBackingStore = true;
+ if (auto contextPendingFlush = layer->properties().backingStore->takeFrontContextPendingFlush())
+ contextsToFlush.append(contextPendingFlush);
+ }
+
layer->didCommit();
}
if (hadAnyChangedBackingStore)
m_remoteLayerTreeContext->backingStoreCollection().schedulePurgeabilityTimer();
+
+ RefPtr<BackingStoreFlusher> backingStoreFlusher = BackingStoreFlusher::create(WebProcess::shared().parentProcessConnection(), std::move(commitEncoder), std::move(contextsToFlush));
+ m_pendingBackingStoreFlusher = backingStoreFlusher;
+
+ dispatch_async(m_commitQueue, [backingStoreFlusher]{
+ backingStoreFlusher->flush();
+ });
}
void RemoteLayerTreeDrawingArea::didUpdate()
m_webPage->pageOverlayController().didChangeDocumentSize();
}
+PassRefPtr<RemoteLayerTreeDrawingArea::BackingStoreFlusher> RemoteLayerTreeDrawingArea::BackingStoreFlusher::create(IPC::Connection* connection, std::unique_ptr<IPC::MessageEncoder> encoder, Vector<RetainPtr<CGContextRef>> contextsToFlush)
+{
+ return adoptRef(new RemoteLayerTreeDrawingArea::BackingStoreFlusher(connection, std::move(encoder), contextsToFlush));
+}
+
+RemoteLayerTreeDrawingArea::BackingStoreFlusher::BackingStoreFlusher(IPC::Connection* connection, std::unique_ptr<IPC::MessageEncoder> encoder, Vector<RetainPtr<CGContextRef>> contextsToFlush)
+ : m_connection(connection)
+ , m_commitEncoder(std::move(encoder))
+ , m_contextsToFlush(std::move(contextsToFlush))
+ , m_hasFlushed(false)
+{
+}
+
+void RemoteLayerTreeDrawingArea::BackingStoreFlusher::flush()
+{
+ ASSERT(!m_hasFlushed);
+
+ for (auto& context : m_contextsToFlush)
+ CGContextFlush(context.get());
+
+ m_connection->sendMessage(std::move(m_commitEncoder));
+ m_hasFlushed = true;
+}
+
} // namespace WebKit