Skip to content

Commit 61cfd4f

Browse files
committed
[PageLifecycle] Render single frame when launching hidden and resuming.
1 parent db503ac commit 61cfd4f

9 files changed

Lines changed: 70 additions & 0 deletions

File tree

Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,19 @@ void ThreadedCompositor::resume()
181181
m_compositingRunLoop->scheduleUpdate();
182182
}
183183

184+
void ThreadedCompositor::renderSingleFrame()
185+
{
186+
m_compositingRunLoop->performTaskSync([this, protectedThis = Ref { *this }] {
187+
// This must be called with the RunLoop suspended.
188+
if (m_suspendedCount <= 0)
189+
return;
190+
191+
m_scene->setActive(true);
192+
renderLayerTree();
193+
m_scene->setActive(false);
194+
});
195+
}
196+
184197
void ThreadedCompositor::setScaleFactor(float scale)
185198
{
186199
Locker locker { m_attributes.lock };

Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class ThreadedCompositor : public CoordinatedGraphicsSceneClient, public ThreadS
8181
void suspend();
8282
void suspendToTransparent();
8383
void resume();
84+
void renderSingleFrame();
8485

8586
private:
8687
ThreadedCompositor(Client&, ThreadedDisplayRefreshMonitor::Client&, WebCore::PlatformDisplayID, const WebCore::IntSize&, float scaleFactor, WebCore::TextureMapper::PaintFlags, bool);

Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ DrawingAreaCoordinatedGraphics::DrawingAreaCoordinatedGraphics(WebPage& webPage,
8282
m_webPage.corePage()->suspendActiveDOMObjectsAndAnimations();
8383
m_isViewSuspended = true;
8484
}
85+
86+
// Launch on hidden state situation.
87+
if (m_usingPageLifecycle && !parameters.activityState.contains(ActivityState::IsVisible))
88+
suspendPainting();
8589
}
8690

8791
DrawingAreaCoordinatedGraphics::~DrawingAreaCoordinatedGraphics() = default;
@@ -935,4 +939,12 @@ uint64_t DrawingAreaCoordinatedGraphics::nativeWindowID() const
935939
return m_layerTreeHost ? m_layerTreeHost->nativeWindowID() : 0;
936940
}
937941

942+
void DrawingAreaCoordinatedGraphics::renderSingleFrameIfRenderingPaused()
943+
{
944+
if (!m_isPaintingSuspended || !m_usingPageLifecycle || !m_layerTreeHost)
945+
return;
946+
947+
m_layerTreeHost->renderSingleFrameWhilePaused();
948+
}
949+
938950
} // namespace WebKit

Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class DrawingAreaCoordinatedGraphics final : public DrawingArea {
109109

110110
uint64_t nativeWindowID() const final;
111111

112+
void renderSingleFrameIfRenderingPaused() final;
113+
112114
uint64_t m_backingStoreStateID { 0 };
113115

114116
// Whether painting is enabled. If painting is disabled, any calls to setNeedsDisplay and scroll are ignored.

Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ LayerTreeHost::LayerTreeHost(WebPage& webPage)
5656
, m_viewportController(webPage.size())
5757
, m_layerFlushTimer(RunLoop::main(), this, &LayerTreeHost::layerFlushTimerFired)
5858
, m_coordinator(webPage, *this)
59+
, m_usingPageLifecycle(webPage.corePage()->settings().pageLifecycleAPIEnabled())
5960
{
6061
#if USE(GLIB_EVENT_LOOP)
6162
m_layerFlushTimer.setPriority(RunLoopSourcePriority::LayerFlushTimer);
@@ -273,6 +274,22 @@ void LayerTreeHost::resumeRendering()
273274
m_compositor->resume();
274275
}
275276

277+
void LayerTreeHost::renderSingleFrameWhilePaused()
278+
{
279+
// This allows painting a single frame while the rendering has been paused without
280+
// actually resuming it. This is only used on 2 cases when page lifecycle is enabled:
281+
// - When launching the application on hidden state.
282+
// - When resuming from suspension into hidden state.
283+
284+
if (!m_isSuspended || !m_usingPageLifecycle)
285+
return;
286+
287+
m_isSuspended = false;
288+
renderNextFrame(true);
289+
m_isSuspended = true;
290+
m_compositor->renderSingleFrame();
291+
}
292+
276293
GraphicsLayerFactory* LayerTreeHost::graphicsLayerFactory()
277294
{
278295
return &m_coordinator;

Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class LayerTreeHost
8585

8686
void pauseRendering(bool toTransparent = false);
8787
void resumeRendering();
88+
void renderSingleFrameWhilePaused();
8889

8990
WebCore::GraphicsLayerFactory* graphicsLayerFactory();
9091

@@ -220,6 +221,7 @@ class LayerTreeHost
220221
double m_transientZoomScale { 1 };
221222
WebCore::FloatPoint m_transientZoomOrigin;
222223
#endif
224+
bool m_usingPageLifecycle { false };
223225
};
224226

225227
#if !USE(COORDINATED_GRAPHICS)

Source/WebKit/WebProcess/WebPage/DrawingArea.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ class DrawingArea : public IPC::MessageReceiver, public WebCore::DisplayRefreshM
156156

157157
virtual uint64_t nativeWindowID() const = 0;
158158

159+
virtual void renderSingleFrameIfRenderingPaused() { };
160+
159161
protected:
160162
DrawingArea(DrawingAreaType, DrawingAreaIdentifier, WebPage&);
161163

Source/WebKit/WebProcess/WebPage/WebPage.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
583583
#if ENABLE(APP_HIGHLIGHTS)
584584
, m_appHighlightsVisible(parameters.appHighlightsVisible)
585585
#endif
586+
, m_renderSingleFrameIfRenderingPausedTimer(*this, &WebPage::renderSingleFrameIfRenderingPausedTimerFired)
586587
{
587588
ASSERT(m_identifier);
588589
WEBPAGE_RELEASE_LOG(Loading, "constructor:");
@@ -3844,6 +3845,9 @@ void WebPage::resume(CompletionHandler<void(bool)>&& completionHandler)
38443845
Ref<ResumeEventNotifier> notifier = adoptRef(*new ResumeEventNotifier());
38453846
notifier->setCompletionHandler([this, completionHandler = std::exchange(completionHandler, { })] () mutable {
38463847
m_isLifecycleSuspended = false;
3848+
// This is the last step of the resume before moving into hidden state, so we want to request
3849+
// a single frame here.
3850+
m_drawingArea->renderSingleFrameIfRenderingPaused();
38473851
completionHandler(true);
38483852
});
38493853

@@ -7259,6 +7263,15 @@ void WebPage::dispatchDidReachLayoutMilestone(OptionSet<WebCore::LayoutMilestone
72597263
updateIntrinsicContentSizeIfNeeded(mainFrameView()->autoSizingIntrinsicContentSize());
72607264
}
72617265

7266+
if (milestones.contains(DidFirstLayout) && m_page->settings().pageLifecycleAPIEnabled() && !m_isLifecycleSuspended) {
7267+
// The page finished its first layout. This can happen when the page is loaded for the first time or
7268+
// when the view is resuming. If m_isLifecycleSuspended is false it means that it's the first load
7269+
// so this is the point where we want to request a single frame if the view is hidden. We cannot try
7270+
// to render the frame directly because scripts are disallowed at this point, and we may need them when
7271+
// rendering, so request the frame with a timer.
7272+
m_renderSingleFrameIfRenderingPausedTimer.startOneShot(0_s);
7273+
}
7274+
72627275
send(Messages::WebPageProxy::DidReachLayoutMilestone(milestones));
72637276
}
72647277

@@ -8250,6 +8263,11 @@ void WebPage::clearNotificationPermissionState()
82508263
}
82518264
#endif
82528265

8266+
void WebPage::renderSingleFrameIfRenderingPausedTimerFired()
8267+
{
8268+
m_drawingArea->renderSingleFrameIfRenderingPaused();
8269+
}
8270+
82538271
} // namespace WebKit
82548272

82558273
#undef WEBPAGE_RELEASE_LOG

Source/WebKit/WebProcess/WebPage/WebPage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,6 +2031,8 @@ class WebPage : public API::ObjectImpl<API::Object::Type::BundlePage>, public IP
20312031
bool hasPendingEditorStateUpdate() const;
20322032
bool shouldAvoidComputingPostLayoutDataForEditorState() const;
20332033

2034+
void renderSingleFrameIfRenderingPausedTimerFired();
2035+
20342036
WebCore::PageIdentifier m_identifier;
20352037

20362038
std::unique_ptr<WebCore::Page> m_page;
@@ -2510,6 +2512,7 @@ class WebPage : public API::ObjectImpl<API::Object::Type::BundlePage>, public IP
25102512
#if ENABLE(IMAGE_ANALYSIS_ENHANCEMENTS)
25112513
WeakHashSet<WebCore::HTMLImageElement> m_elementsToExcludeFromRemoveBackground;
25122514
#endif
2515+
WebCore::Timer m_renderSingleFrameIfRenderingPausedTimer;
25132516
};
25142517

25152518
#if !PLATFORM(IOS_FAMILY)

0 commit comments

Comments
 (0)