summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp')
-rw-r--r--Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp192
1 files changed, 179 insertions, 13 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
index 2063bd6..6d65fae 100644
--- a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
@@ -23,9 +23,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "DrawingAreaImpl.h"
#include "DrawingAreaProxyMessages.h"
+#include "LayerTreeContext.h"
#include "ShareableBitmap.h"
#include "UpdateInfo.h"
#include "WebPage.h"
@@ -33,7 +35,7 @@
#include "WebProcess.h"
#include <WebCore/GraphicsContext.h>
-#ifndef __APPLE__
+#if !PLATFORM(MAC) && !PLATFORM(WIN)
#error "This drawing area is not ready for use by other ports yet."
#endif
@@ -41,6 +43,12 @@ using namespace WebCore;
namespace WebKit {
+static uint64_t generateSequenceNumber()
+{
+ static uint64_t sequenceNumber;
+ return ++sequenceNumber;
+}
+
PassRefPtr<DrawingAreaImpl> DrawingAreaImpl::create(WebPage* webPage, const WebPageCreationParameters& parameters)
{
return adoptRef(new DrawingAreaImpl(webPage, parameters));
@@ -48,27 +56,50 @@ PassRefPtr<DrawingAreaImpl> DrawingAreaImpl::create(WebPage* webPage, const WebP
DrawingAreaImpl::~DrawingAreaImpl()
{
+ if (m_layerTreeHost)
+ m_layerTreeHost->invalidate();
}
DrawingAreaImpl::DrawingAreaImpl(WebPage* webPage, const WebPageCreationParameters& parameters)
: DrawingArea(DrawingAreaInfo::Impl, parameters.drawingAreaInfo.identifier, webPage)
+ , m_inSetSize(false)
, m_isWaitingForDidUpdate(false)
, m_isPaintingSuspended(!parameters.isVisible)
, m_displayTimer(WebProcess::shared().runLoop(), this, &DrawingAreaImpl::display)
+ , m_exitCompositingTimer(WebProcess::shared().runLoop(), this, &DrawingAreaImpl::exitAcceleratedCompositingMode)
{
}
void DrawingAreaImpl::setNeedsDisplay(const IntRect& rect)
{
- if (rect.isEmpty())
+ IntRect dirtyRect = rect;
+ dirtyRect.intersect(m_webPage->bounds());
+
+ if (dirtyRect.isEmpty())
return;
- m_dirtyRegion.unite(rect);
+ if (m_layerTreeHost) {
+ ASSERT(m_dirtyRegion.isEmpty());
+
+ m_layerTreeHost->setNonCompositedContentsNeedDisplay(dirtyRect);
+ return;
+ }
+
+ m_dirtyRegion.unite(dirtyRect);
scheduleDisplay();
}
void DrawingAreaImpl::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
{
+ if (m_layerTreeHost) {
+ ASSERT(m_scrollRect.isEmpty());
+ ASSERT(m_scrollOffset.isEmpty());
+ ASSERT(m_dirtyRegion.isEmpty());
+
+ m_layerTreeHost->scrollNonCompositedContents(scrollRect, scrollOffset);
+ return;
+ }
+
if (!m_scrollRect.isEmpty() && scrollRect != m_scrollRect) {
unsigned scrollArea = scrollRect.width() * scrollRect.height();
unsigned currentScrollArea = m_scrollRect.width() * m_scrollRect.height();
@@ -109,6 +140,36 @@ void DrawingAreaImpl::scroll(const IntRect& scrollRect, const IntSize& scrollOff
m_scrollOffset += scrollOffset;
}
+void DrawingAreaImpl::forceRepaint()
+{
+ m_isWaitingForDidUpdate = false;
+ display();
+}
+
+void DrawingAreaImpl::didInstallPageOverlay()
+{
+ if (m_layerTreeHost)
+ m_layerTreeHost->didInstallPageOverlay();
+}
+
+void DrawingAreaImpl::didUninstallPageOverlay()
+{
+ if (m_layerTreeHost)
+ m_layerTreeHost->didUninstallPageOverlay();
+
+ setNeedsDisplay(m_webPage->bounds());
+}
+
+void DrawingAreaImpl::setPageOverlayNeedsDisplay(const IntRect& rect)
+{
+ if (m_layerTreeHost) {
+ m_layerTreeHost->setPageOverlayNeedsDisplay(rect);
+ return;
+ }
+
+ setNeedsDisplay(rect);
+}
+
void DrawingAreaImpl::attachCompositingContext()
{
}
@@ -117,12 +178,31 @@ void DrawingAreaImpl::detachCompositingContext()
{
}
-void DrawingAreaImpl::setRootCompositingLayer(WebCore::GraphicsLayer*)
+void DrawingAreaImpl::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
{
+ if (graphicsLayer) {
+ if (!m_layerTreeHost) {
+ // We're actually entering accelerated compositing mode.
+ enterAcceleratedCompositingMode(graphicsLayer);
+ } else {
+ m_exitCompositingTimer.stop();
+ // We're already in accelerated compositing mode, but the root compositing layer changed.
+ m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
+ }
+ } else {
+ if (m_layerTreeHost) {
+ // We'll exit accelerated compositing mode on a timer, to avoid re-entering
+ // compositing code via display() and layout.
+ exitAcceleratedCompositingModeSoon();
+ }
+ }
}
void DrawingAreaImpl::scheduleCompositingLayerSync()
{
+ if (!m_layerTreeHost)
+ return;
+ m_layerTreeHost->scheduleLayerFlush();
}
void DrawingAreaImpl::syncCompositingLayers()
@@ -133,27 +213,48 @@ void DrawingAreaImpl::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID
{
}
-void DrawingAreaImpl::setSize(const IntSize& size)
+void DrawingAreaImpl::setSize(const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset)
{
+ ASSERT(!m_inSetSize);
+ m_inSetSize = true;
+
// Set this to false since we're about to call display().
m_isWaitingForDidUpdate = false;
m_webPage->setSize(size);
m_webPage->layoutIfNeeded();
+ m_webPage->scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
UpdateInfo updateInfo;
+ LayerTreeContext layerTreeContext;
- if (m_isPaintingSuspended) {
- updateInfo.timestamp = currentTime();
+ if (m_layerTreeHost) {
+ m_layerTreeHost->sizeDidChange(size);
+ layerTreeContext = m_layerTreeHost->layerTreeContext();
+ }
+
+ if (m_isPaintingSuspended || m_layerTreeHost)
updateInfo.viewSize = m_webPage->size();
- } else
+ else {
+ m_dirtyRegion.unite(m_webPage->bounds());
+
+ // The display here should not cause layout to happen, so we can't enter accelerated compositing mode here.
display(updateInfo);
+ ASSERT(!m_layerTreeHost);
+ }
- m_webPage->send(Messages::DrawingAreaProxy::DidSetSize(updateInfo));
+ m_webPage->send(Messages::DrawingAreaProxy::DidSetSize(generateSequenceNumber(), updateInfo, layerTreeContext));
+
+ m_inSetSize = false;
}
void DrawingAreaImpl::didUpdate()
{
+ // We might get didUpdate messages from the UI process even after we've
+ // entered accelerated compositing mode. Ignore them.
+ if (m_layerTreeHost)
+ return;
+
m_isWaitingForDidUpdate = false;
// Display if needed.
@@ -174,7 +275,62 @@ void DrawingAreaImpl::resumePainting()
m_isPaintingSuspended = false;
- // FIXME: Repaint if needed.
+ // FIXME: We shouldn't always repaint everything here.
+ setNeedsDisplay(m_webPage->bounds());
+}
+
+void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLayer)
+{
+ m_exitCompositingTimer.stop();
+
+ ASSERT(!m_layerTreeHost);
+
+ m_layerTreeHost = LayerTreeHost::create(m_webPage);
+ m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
+
+ // Non-composited content will now be handled exclusively by the layer tree host.
+ m_dirtyRegion = Region();
+ m_scrollRect = IntRect();
+ m_scrollOffset = IntSize();
+ m_displayTimer.stop();
+ m_isWaitingForDidUpdate = false;
+
+ if (!m_inSetSize)
+ m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(generateSequenceNumber(), m_layerTreeHost->layerTreeContext()));
+}
+
+void DrawingAreaImpl::exitAcceleratedCompositingMode()
+{
+ m_exitCompositingTimer.stop();
+
+ ASSERT(m_layerTreeHost);
+
+ m_layerTreeHost->invalidate();
+ m_layerTreeHost = nullptr;
+
+ if (m_inSetSize)
+ return;
+
+ UpdateInfo updateInfo;
+ if (m_isPaintingSuspended)
+ updateInfo.viewSize = m_webPage->size();
+ else {
+ m_dirtyRegion = m_webPage->bounds();
+ display(updateInfo);
+ }
+
+ // Send along a complete update of the page so we can paint the contents right after we exit the
+ // accelerated compositing mode, eliminiating flicker.
+ if (!m_inSetSize)
+ m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(generateSequenceNumber(), updateInfo));
+}
+
+void DrawingAreaImpl::exitAcceleratedCompositingModeSoon()
+{
+ if (m_exitCompositingTimer.isActive())
+ return;
+
+ m_exitCompositingTimer.startOneShot(0);
}
void DrawingAreaImpl::scheduleDisplay()
@@ -196,6 +352,7 @@ void DrawingAreaImpl::scheduleDisplay()
void DrawingAreaImpl::display()
{
+ ASSERT(!m_layerTreeHost);
ASSERT(!m_isWaitingForDidUpdate);
if (m_isPaintingSuspended)
@@ -207,7 +364,13 @@ void DrawingAreaImpl::display()
UpdateInfo updateInfo;
display(updateInfo);
- m_webPage->send(Messages::DrawingAreaProxy::Update(updateInfo));
+ if (m_layerTreeHost) {
+ // The call to update caused layout which turned on accelerated compositing.
+ // Don't send an Update message in this case.
+ return;
+ }
+
+ m_webPage->send(Messages::DrawingAreaProxy::Update(generateSequenceNumber(), updateInfo));
m_isWaitingForDidUpdate = true;
}
@@ -235,6 +398,8 @@ static bool shouldPaintBoundsRect(const IntRect& bounds, const Vector<IntRect>&
void DrawingAreaImpl::display(UpdateInfo& updateInfo)
{
ASSERT(!m_isPaintingSuspended);
+ ASSERT(!m_layerTreeHost);
+ ASSERT(!m_webPage->size().isEmpty());
// FIXME: It would be better if we could avoid painting altogether when there is a custom representation.
if (m_webPage->mainFrameHasCustomRepresentation())
@@ -263,7 +428,6 @@ void DrawingAreaImpl::display(UpdateInfo& updateInfo)
m_webPage->layoutIfNeeded();
- updateInfo.timestamp = currentTime();
updateInfo.viewSize = m_webPage->size();
updateInfo.updateRectBounds = bounds;
@@ -271,9 +435,11 @@ void DrawingAreaImpl::display(UpdateInfo& updateInfo)
for (size_t i = 0; i < rects.size(); ++i) {
m_webPage->drawRect(*graphicsContext, rects[i]);
+ if (m_webPage->hasPageOverlay())
+ m_webPage->drawPageOverlay(*graphicsContext, rects[i]);
updateInfo.updateRects.append(rects[i]);
}
-
+
// Layout can trigger more calls to setNeedsDisplay and we don't want to process them
// until the UI process has painted the update, so we stop the timer here.
m_displayTimer.stop();