RESOLVED FIXED 290042
`fillText` after `transferControlToScreen` for canvas doesn't draw
https://bugs.webkit.org/show_bug.cgi?id=290042
Summary `fillText` after `transferControlToScreen` for canvas doesn't draw
Deleted User
Reported 2025-03-19 06:05:38 PDT
Created attachment 474628 [details] File of the WPT opened with MiniBrowser. Observe the missing text "T" at the beginning. The text appears after refreshing the window. https://github.com/WebKit/WebKit/pull/42688 contains a WPT for that. Of the corresponding EWS run https://ews-build.s3-us-west-2.amazonaws.com/macOS-Sonoma-Release-WK1-Tests-EWS/05f6b14c-4260-stress-mode/results.html failed. That's a WK1 run but locally the problem could sporadically be reproduced with GTK's MiniBrowser. See the attached video.
Attachments
File of the WPT opened with MiniBrowser. Observe the missing text "T" at the beginning. The text appears after refreshing the window. (555.42 KB, video/mp4)
2025-03-19 06:05 PDT, Deleted User
no flags
Deleted User
Comment 1 2025-03-19 08:02:42 PDT
Analysis revealed: `CanvasRenderingContext2DBase::didDraw` (https://searchfox.org/wubkat/rev/b602c49c2b9f3a896acd327d0f0a13afb2e3c7db/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp#2313) is called in both cases: when the text is visible and when it's invisible. In both cases it calls `canvasBase().didDraw` (https://searchfox.org/wubkat/rev/b602c49c2b9f3a896acd327d0f0a13afb2e3c7db/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp#2364).
Deleted User
Comment 2 2025-03-20 03:58:44 PDT
When the text is invisible, it becomes visible after hiding and showing the browser window (e.g. via twice alt-tab).
Deleted User
Comment 3 2025-03-20 04:01:58 PDT
When opening the file in the MiniBrowser, the issue seems more likely to reproduce when the cursor is besides the browser window.
Deleted User
Comment 4 2025-03-20 04:15:41 PDT
`HTMLCanvasElement::setImageBufferAndMarkDirty` (https://searchfox.org/wubkat/rev/b602c49c2b9f3a896acd327d0f0a13afb2e3c7db/Source/WebCore/html/HTMLCanvasElement.cpp#900) is also called when the text is invisible.
Deleted User
Comment 5 2025-03-20 04:18:10 PDT
Moving the mouse above the content window does not call `HTMLCanvasElement::setImageBufferAndMarkDirty` again, but the text becomes visible.
Deleted User
Comment 6 2025-03-20 07:03:08 PDT
`WebPage::finalizeRenderingUpdate` (https://searchfox.org/wubkat/rev/b602c49c2b9f3a896acd327d0f0a13afb2e3c7db/Source/WebKit/WebProcess/WebPage/WebPage.cpp#5147) is called when the text is invisible and when its visible.
Deleted User
Comment 7 2025-03-24 03:01:43 PDT
When the text is invisible `LayerTreeHost::commitSceneState` (https://searchfox.org/wubkat/rev/b2323ec6eaf613835bbaf8964d6e6d53b5310653/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp#527) is only called before `HTMLCanvasElement::setImageBufferAndMarkDirty` is called. When the text becomes visible, `LayerTreeHost::commitSceneState` is called again.
Deleted User
Comment 8 2025-03-24 04:02:35 PDT
`CanvasBase::notifyObserversCanvasChanged` (https://searchfox.org/wubkat/rev/b2323ec6eaf613835bbaf8964d6e6d53b5310653/Source/WebCore/html/CanvasBase.cpp#157) is called from `HTMLCanvasElement::setImageBufferAndMarkDirty`.
Deleted User
Comment 9 2025-03-24 06:25:03 PDT
`CanvasBase::addCanvasNeedingPreparationForDisplayOrFlush` (https://searchfox.org/wubkat/rev/b2323ec6eaf613835bbaf8964d6e6d53b5310653/Source/WebCore/html/CanvasBase.cpp#340) calls `Document::addCanvasNeedingPreparationForDisplayOrFlush` (https://searchfox.org/wubkat/rev/b2323ec6eaf613835bbaf8964d6e6d53b5310653/Source/WebCore/dom/Document.cpp#10998). The latter does not call `scheduleRenderingUpdate(RenderingUpdateStep::PrepareCanvasesForDisplayOrFlush);`.
Deleted User
Comment 10 2025-03-24 06:30:10 PDT
This seems to be fixable by forcing `Document::addCanvasNeedingPreparationForDisplayOrFlush` to call `scheduleRenderingUpdate(RenderingUpdateStep::PrepareCanvasesForDisplayOrFlush);`.
Deleted User
Comment 12 2025-03-25 06:24:36 PDT
Radar WebKit Bug Importer
Comment 13 2025-03-26 06:06:17 PDT
Deleted User
Comment 14 2025-04-03 06:33:23 PDT
`fillText` after loading a FontFace and after `transferControllToOffscreen()` failed reliably: https://github.com/WebKit/WebKit/pull/42688/files#diff-569aa52dd7b76b7c6aa31cc120f8ec75356e60777ab397ea10aca371cde4b597.
Deleted User
Comment 16 2025-04-09 01:32:46 PDT
Deleted User
Comment 18 2025-04-10 04:04:43 PDT
Deleted User
Comment 19 2025-04-10 05:25:16 PDT
`CanvasBase::buffer()` (https://searchfox.org/wubkat/rev/95b8a67e3715e5f442cadaf3532e007c8c7d2603/Source/WebCore/html/CanvasBase.cpp#83) which returns the image buffer, is not called after `HTMLCanvasElement::setImageBufferAndMarkDirty` was called.
Deleted User
Comment 20 2025-04-10 05:27:27 PDT
Deleted User
Comment 22 2025-04-21 01:55:32 PDT
Continuing checking the working hypothesis of https://bugs.webkit.org/show_bug.cgi?id=290042#c21: when the text is invisible, there's the following call-sequence: `CanvasRenderingContext2DBase::drawTextUnchecked` (https://searchfox.org/wubkat/rev/77741e95522d501f4c337a6aa525583001c29456/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp#2853) `GraphicsContext::drawBidiText` `FontCascade::drawText` `FontCascade::drawGlyphBuffer` `GraphicsContext::drawGlyphs` `GraphicsContextSkia::drawSkiaText` `SkCanvas::drawTextBlob` (https://searchfox.org/wubkat/rev/77741e95522d501f4c337a6aa525583001c29456/Source/ThirdParty/skia/include/core/SkCanvas.h#19960
Deleted User
Comment 23 2025-04-21 02:59:14 PDT
Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c22: the `SkGlyphID` and `SkScalar` set in `FontCascade::drawGlyphs` (https://searchfox.org/wubkat/rev/77741e95522d501f4c337a6aa525583001c29456/Source/WebCore/platform/graphics/skia/FontCascadeSkia.cpp#80,87) contain the same values (55 and 0) when the text is visible and when it's invisible.
Deleted User
Comment 25 2025-04-21 05:50:47 PDT
Returning to `canvas.2d.fillText.html`: with the mouse arrow next to the browser window, the call sequence is the same as in https://bugs.webkit.org/show_bug.cgi?id=290042#c22. After moving the mouse arrow over the content window and clicking, the text becomes visible, without `GraphicsContext::drawBidiText` being invoked again.
Deleted User
Comment 26 2025-04-22 01:45:28 PDT
Returning to `canvas.2d.fillText-FontFace.html`: `HTMLCanvasElement::paint`(https://searchfox.org/wubkat/rev/d767e232791f782fdcd8f0d72fd04c836716246f/Source/WebCore/html/HTMLCanvasElement.cpp#639) is only called before `OffscreenCanvasRenderingContext2D::fillText` is called.
Deleted User
Comment 27 2025-04-22 02:24:28 PDT
Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c26: Removing the size comparison in `HTMLCanvasElement::setImageBufferAndMarkDirty` (https://searchfox.org/wubkat/rev/d767e232791f782fdcd8f0d72fd04c836716246f/Source/WebCore/html/HTMLCanvasElement.cpp#905) still lets `canvas.2d.fillText-FontFace.html` fail.
Deleted User
Comment 28 2025-04-22 02:54:39 PDT
Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c27: forcing a repaint in `HTMLCanvasElement::setImageBufferAndMarkDirty` (https://searchfox.org/wubkat/rev/d767e232791f782fdcd8f0d72fd04c836716246f/Source/WebCore/html/HTMLCanvasElement.cpp#620) via `canvasRenderer->repaint(RenderHTMLCanvas::ForceRepaint::Yes);` still lets the test fail.
Simon Fraser (smfr)
Comment 29 2025-04-22 11:50:30 PDT
Do we know if this bug affects Apple platforms, or just Skia-based ones?
Deleted User
Comment 30 2025-04-22 23:21:00 PDT
(In reply to Simon Fraser (smfr) from comment #29) > Do we know if this bug affects Apple platforms, or just Skia-based ones? It affects Apple platforms too. See e.g. https://ews-build.s3-us-west-2.amazonaws.com/macOS-Sonoma-Release-WK2-Tests-EWS/995fd46a-6647-stress-mode/results.html.
Deleted User
Comment 31 2025-04-23 01:01:01 PDT
Deleted User
Comment 32 2025-04-23 01:52:49 PDT
For `canvas.2d.fillText-FontFace.html`: `PlaceholderRenderingContextSource::setPlaceholderBuffer` has no `m_delegate`: https://searchfox.org/wubkat/rev/cfa4aa1a28ba4bf125f016ca98668f3bee093d28/Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp#54.
Deleted User
Comment 33 2025-04-23 06:06:45 PDT
Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c32: The virtual method `CanvasRenderingContext::setContentsToLayer` is only called from `RenderLayerBacking::updateConfiguration`: https://searchfox.org/wubkat/query/default?q=calls-to%3A%27WebCore%3A%3ACanvasRenderingContext%3A%3AsetContentsToLayer%27+depth%3A3.
Deleted User
Comment 34 2025-04-23 07:43:28 PDT
Deleted User
Comment 35 2025-04-24 01:32:01 PDT
Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c34: the `RenderLayer` (https://searchfox.org/wubkat/rev/3fce852ff4e4172ed7e8b19f7f06f0e44b95f962/Source/WebCore/rendering/RenderLayer.cpp#313) for `RenderHTMLCanvas` is constructed after `CanvasRenderingContext2DBase::didDraw` and before `OffscreenCanvas::commitToPlaceholderCanvas`.
Deleted User
Comment 36 2025-04-24 06:52:10 PDT
(In reply to Mirko Brodesser from comment #35) > Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c34: > > the `RenderLayer` > (https://searchfox.org/wubkat/rev/3fce852ff4e4172ed7e8b19f7f06f0e44b95f962/ > Source/WebCore/rendering/RenderLayer.cpp#313) > for `RenderHTMLCanvas` is constructed after > `CanvasRenderingContext2DBase::didDraw` > and before `OffscreenCanvas::commitToPlaceholderCanvas`. Correction: at least sometimes, the `RenderLayer` is constructed after `OffscreenCanvas::commitToPlaceholderCanvas`.
Matt Woodrow
Comment 37 2025-04-27 14:20:18 PDT
What I would expect to happen: `setImageBufferAndMarkDirty` calls `CanvasBase::didDraw`, which would then call `contentChanged(ContentChangeType::CanvasPixels);` (for an HTML canvas using a placeholder rendering context). That should call through to `RenderLayerBacking::contentChanged` and then into `GraphicsLayer::setContentsNeedDisplay`. The `GraphicsLayer` should then call `notifyFlushRequired` on its client (which is `RenderLayerBacking` again). That should result in `Page::scheduleRenderingUpdate(RenderingUpdateStep::LayerFlush)` being called, which triggers the actual rendering update to happen (including `updateCompositingLayers`). That seems like it'd have the same effect as your current PR (which is returning true for `hasDeferredOperations()`, but I believe works because it results in a call to `Page::scheduleRenderingUpdate(RenderingUpdateStep::PrepareCanvasesForDisplayOrFlush)`). Is part of that not working?
Deleted User
Comment 38 2025-04-28 05:30:46 PDT
(In reply to Matt Woodrow from comment #37) > What I would expect to happen: > > `setImageBufferAndMarkDirty` calls `CanvasBase::didDraw`, which would then > call `contentChanged(ContentChangeType::CanvasPixels);` (for an HTML canvas > using a placeholder rendering context). > > That should call through to `RenderLayerBacking::contentChanged` and then > into `GraphicsLayer::setContentsNeedDisplay`. > > The `GraphicsLayer` should then call `notifyFlushRequired` on its client > (which is `RenderLayerBacking` again). That should result in > `Page::scheduleRenderingUpdate(RenderingUpdateStep::LayerFlush)` being > called, which triggers the actual rendering update to happen (including > `updateCompositingLayers`). > > That seems like it'd have the same effect as your current PR (which is > returning true for `hasDeferredOperations()`, but I believe works because it > results in a call to > `Page::scheduleRenderingUpdate(RenderingUpdateStep:: > PrepareCanvasesForDisplayOrFlush)`). > > Is part of that not working? Thanks for sharing the thoughts. Until `GraphicsLayer::setContentsNeedsDisplay` (https://searchfox.org/wubkat/rev/91adeac8b28caf815007f457c1eb67b531854aae/Source/WebCore/platform/graphics/GraphicsLayer.h#506) it's working. The overload of that method is invoked: `GraphicsLayerCoordinated::setContentsNeedsDisplay` (https://searchfox.org/wubkat/rev/91adeac8b28caf815007f457c1eb67b531854aae/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#330). Its `m_contentsDisplayDelegate` (https://searchfox.org/wubkat/rev/91adeac8b28caf815007f457c1eb67b531854aae/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#332) is null.
Deleted User
Comment 39 2025-04-28 07:49:35 PDT
`m_contentsDisplayDelegate` is set in `GraphicsLayerCoordinated::setContentsDisplayDelegate` (https://searchfox.org/wubkat/rev/cdeb683588e6b419a58d9735e7d98fc52dc2a094/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#355,360) after `GraphicsLayerCoordinated::setContentsNeedsDisplay` is called.
Deleted User
Comment 40 2025-04-29 00:57:22 PDT
`GraphicsLayerCoordinated::setContentsNeedsDisplay` has the following call stack: ``` Thread 1 "WebKitWebProces" hit Breakpoint 1, WebCore::GraphicsLayerCoordinated::setContentsDisplayDelegate (this=0x76236e0aa800, delegate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp:362 362 { (gdb) bt #0 WebCore::GraphicsLayerCoordinated::setContentsDisplayDelegate (this=0x76236e0aa800, delegate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp:362 #1 0x00007624101be7e7 in WebCore::GraphicsLayerAsyncContentsDisplayDelegateCoordinated::GraphicsLayerAsyncContentsDisplayDelegateCoordinated (this=0x7623de2c3d00, layer=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerAsyncContentsDisplayDelegateCoordinated.cpp:47 #2 0x00007624101c0656 in WebCore::GraphicsLayerAsyncContentsDisplayDelegateCoordinated::create (layer=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerAsyncContentsDisplayDelegateCoordinated.h:39 #3 0x00007624101c234b in WebCore::GraphicsLayerCoordinated::createAsyncContentsDisplayDelegate (this=0x76236e0aa800, existing=0x0) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp:388 #4 0x00007624144ddf38 in WebCore::PlaceholderRenderingContextSource::setContentsToLayer (this=0x7623de1734b0, layer=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp:80 #5 0x00007624144de16d in WebCore::PlaceholderRenderingContext::setContentsToLayer (this=0x76234e009700, layer=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp:109 #6 0x0000762415b9460b in WebCore::RenderLayerBacking::updateConfiguration (this=0x7623de102060, compositingAncestor=0x76234e000e30) at /host/home/mirko/work/code/WebKit/Source/WebCore/rendering/RenderLayerBacking.cpp:1305 #7 0x0000762415bb0459 in WebCore::RenderLayerCompositor::updateBackingAndHierarchy (this=0x7623de165290, layer=..., childLayersOfEnclosingLayer=..., traversalState=..., scrollingTreeState=..., updateLevel=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1722 #8 0x0000762415bb0976 in WebCore::RenderLayerCompositor::updateBackingAndHierarchy (this=0x7623de165290, layer=..., childLayersOfEnclosingLayer=..., traversalState=..., scrollingTreeState=..., updateLevel=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1795 #9 0x0000762415bb0a23 in WebCore::RenderLayerCompositor::updateBackingAndHierarchy (this=0x7623de165290, layer=..., childLayersOfEnclosingLayer=..., traversalState=..., scrollingTreeState=..., updateLevel=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1798 #10 0x0000762415bac5e5 in WebCore::RenderLayerCompositor::updateCompositingLayers (this=0x7623de165290, updateType=WebCore::CompositingUpdateType::AfterLayout, updateRoot=0x76234e000e30) at /host/home/mirko/work/code/WebKit/Source/WebCore/rendering/RenderLayerCompositor.cpp:1152 #11 0x0000762414d74b73 in WebCore::LocalFrameViewLayoutContext::updateCompositingLayersAfterLayout (this=0x76234e006c70) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/LocalFrameViewLayoutContext.cpp:398 #12 0x0000762414d74baf in WebCore::LocalFrameViewLayoutContext::updateCompositingLayersAfterLayoutIfNeeded (this=0x76234e006c70) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/LocalFrameViewLayoutContext.cpp:405 #13 0x0000762413ce3a0e in WebCore::Document::updateLayout (this=0x76236e101200, layoutOptions=..., context=0x0) at /host/home/mirko/work/code/WebKit/Source/WebCore/dom/Document.cpp:3062 #14 0x0000762414d6b498 in WebCore::LocalFrameView::updateLayoutAndStyleIfNeededRecursive (this=0x76234e006b10, layoutOptions=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/LocalFrameView.cpp:5290 #15 0x0000762414ddafa5 in WebCore::Page::layoutIfNeeded (this=0x7623de0f8100, layoutOptions=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/Page.cpp:2015 #16 0x0000762414fdacdf in WebCore::ThreadedScrollingCoordinator::willStartRenderingUpdate (this=0x7623de012200) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/scrolling/ThreadedScrollingCoordinator.cpp:120 #17 0x0000762414ddbfb0 in WebCore::Page::updateRendering (this=0x7623de0f8100) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/Page.cpp:2126 #18 0x000076240fd450a4 in WebKit::WebPage::updateRendering (this=0x7623de008d80) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebPage/WebPage.cpp:5026 #19 0x000076240fdef734 in WebKit::LayerTreeHost::flushLayers (this=0x7623de0b05d0) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:184 #20 0x000076240fdefb9b in WebKit::LayerTreeHost::layerFlushTimerFired (this=0x7623de0b05d0) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:255 #21 0x000076240fdf76b5 in WTF::RunLoop::Timer::Timer<WebKit::LayerTreeHost>(WTF::Ref<WTF::RunLoop, WTF::RawPtrTraits<WTF::RunLoop>, WTF::DefaultRefDerefTraits<WTF::RunLoop> >&&, WebKit::Laye--Type <RET> for more, q to quit, c to continue without paging-- rTreeHost*, void (WebKit::LayerTreeHost::*)())::{lambda()#1}::operator()() const (__closure=0x7623de113448) at /host/home/mirko/work/code/WebKit/WebKitBuild/GTK/Debug/WTF/Headers/wtf/RunLoop.h:199 ```
Deleted User
Comment 41 2025-04-29 23:56:33 PDT
Correction of https://bugs.webkit.org/show_bug.cgi?id=290042#c40: that comment shows the call stack of `GraphicsLayerCoordinated::setContentsDisplayDelegate`.
Deleted User
Comment 43 2025-04-30 00:57:57 PDT
`LayerTreeHost::scheduleLayerFlush` is called after `OffscreenCanvasRenderingContext2D::fillText` and before `OffscreenCanvas::commitToPlaceholderCanvas` with the following call stack: ``` #0 WebKit::LayerTreeHost::scheduleLayerFlush (this=0x7f39ed0a85d0) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:153 #1 0x00007f3a1edec87e in WebKit::DrawingAreaCoordinatedGraphics::triggerRenderingUpdate (this=0x7f39ed0f0110) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:322 #2 0x00007f3a1ebca664 in WebKit::WebChromeClient::triggerRenderingUpdate (this=0x7f39ed0e7900) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp:1147 #3 0x00007f3a23eac06c in WebCore::RenderingUpdateScheduler::triggerRenderingUpdate (this=0x7f39ed19cd00) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/RenderingUpdateScheduler.cpp:146 #4 0x00007f3a23eabff0 in WebCore::RenderingUpdateScheduler::displayRefreshFired (this=0x7f39ed19cd00) at /host/home/mirko/work/code/WebKit/Source/WebCore/page/RenderingUpdateScheduler.cpp:136 #5 0x00007f3a242ad228 in WebCore::DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded (this=0x7f39ed19cd00, displayUpdate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp:62 #6 0x00007f3a242acfec in WebCore::DisplayRefreshMonitor::displayDidRefresh (this=0x7f39ed00ed60, displayUpdate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp:205 #7 0x00007f3a242acdb4 in WebCore::DisplayRefreshMonitor::dispatchDisplayDidRefresh (this=0x7f39ed00ed60, displayUpdate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp:185 #8 0x00007f3a242acd03 in WebCore::DisplayRefreshMonitor::displayLinkFired (this=0x7f39ed00ed60, displayUpdate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp:179 #9 0x00007f3a242bf371 in WebCore::DisplayRefreshMonitorManager::displayDidRefresh (this=0x7f3a270cd0b0 <WebCore::DisplayRefreshMonitorManager::sharedManager()::manager>, displayID=1, displayUpdate=...) at /host/home/mirko/work/code/WebKit/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp:115 #10 0x00007f3a1e5c364d in WebKit::WebProcess::displayDidRefresh (this=0x7f39ed038100, displayID=1, displayUpdate=...) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/WebProcess.cpp:2300 #11 0x00007f3a1cd5fb09 in IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}::operator()<unsigned int, WebCore::DisplayUpdate>(unsigned int&&, WebCore::DisplayUpdate&&) const (__closure=0x7fff6c108e10) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:135 #12 0x00007f3a1cd6fa0c in std::__invoke_impl<void, IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}, unsigned int, WebCore::DisplayUpdate>(std::__invoke_other, IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}&&, unsigned int&&, WebCore::DisplayUpdate&&) (__f=...) at /usr/include/c++/13/bits/invoke.h:61 #13 0x00007f3a1cd67c6a in std::__invoke<IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}, unsigned int, WebCore::DisplayUpdate>(IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}&&, unsigned int&&, WebCore::DisplayUpdate&&) (__fn=...) at /usr/include/c++/13/bits/invoke.h:96 #14 0x00007f3a1cd5fb74 in std::__apply_impl<IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}, std::tuple<unsigned int, WebCore::DisplayUpdate>, 0ul, 1ul>(IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}&&, std::tuple<unsigned int, WebCore::DisplayUpdate>&&, std::integer_sequence<unsigned long, 0ul, 1ul>) (__f=..., __t=...) at /usr/include/c++/13/tuple:2302 #15 0x00007f3a1cd5fbb9 in std::apply<IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::Dis--Type <RET> for more, q to quit, c to continue without paging-- playUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}, std::tuple<unsigned int, WebCore::DisplayUpdate> >(IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&)::{lambda((auto:1&&)...)#1}&&, std::tuple<unsigned int, WebCore::DisplayUpdate>&&) (__f=..., __t=...) at /usr/include/c++/13/tuple:2313 #16 0x00007f3a1cd5fc22 in IPC::callMemberFunction<WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate> >(WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&), std::tuple<unsigned int, WebCore::DisplayUpdate>&&) (object=0x7f39ed038100, function=(void (WebKit::WebProcess::*)(WebKit::WebProcess * const, unsigned int, const WebCore::DisplayUpdate &)) 0x7f3a1e5c3564 <WebKit::WebProcess::displayDidRefresh(unsigned int, WebCore::DisplayUpdate const&)>, tuple=...) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:132 #17 0x00007f3a1cd578d6 in IPC::handleMessage<Messages::WebProcess::DisplayDidRefresh, IPC::Connection, WebKit::WebProcess, WebKit::WebProcess, void (unsigned int, WebCore::DisplayUpdate const&)>(IPC::Connection&, IPC::Decoder&, WebKit::WebProcess*, void (WebKit::WebProcess::*)(unsigned int, WebCore::DisplayUpdate const&)) (connection=..., decoder=..., object=0x7f39ed038100, function=(void (WebKit::WebProcess::*)(WebKit::WebProcess * const, unsigned int, const WebCore::DisplayUpdate &)) 0x7f3a1e5c3564 <WebKit::WebProcess::displayDidRefresh(unsigned int, WebCore::DisplayUpdate const&)>) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/HandleMessage.h:337 #18 0x00007f3a1cd51164 in WebKit::WebProcess::didReceiveMessage (this=0x7f39ed038100, connection=..., decoder=...) at /host/home/mirko/work/code/WebKit/WebKitBuild/GTK/Debug/DerivedSources/WebKit/WebProcessMessageReceiver.cpp:352 #19 0x00007f3a1dcde04b in IPC::Connection::dispatchMessage (this=0x7f39ed060210, decoder=...) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1395 #20 0x00007f3a1dcde2bc in IPC::Connection::dispatchMessage (this=0x7f39ed060210, message=...) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1445 #21 0x00007f3a1dcde94b in IPC::Connection::dispatchOneIncomingMessage (this=0x7f39ed060210) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1524 #22 0x00007f3a1dcddcc0 in operator() (__closure=0x7f39ed064268) at /host/home/mirko/work/code/WebKit/Source/WebKit/Platform/IPC/Connection.cpp:1357 #23 0x00007f3a1dd0c9f2 in WTF::Detail::CallableWrapper<IPC::Connection::enqueueIncomingMessage(WTF::UniqueRef<IPC::Decoder>)::<lambda()>, void>::call(void) (this=0x7f39ed064260) at /host/home/mirko/work/code/WebKit/WebKitBuild/GTK/Debug/WTF/Headers/wtf/Function.h:53 #24 0x00007f3a0d03403b in WTF::Function<void ()>::operator()() const (this=0x7fff6c109610) at /host/home/mirko/work/code/WebKit/WebKitBuild/GTK/Debug/WTF/Headers/wtf/Function.h:82 #25 0x00007f3a0eafcdef in WTF::RunLoop::performWork (this=0x7f39ed01c180) at /host/home/mirko/work/code/WebKit/Source/WTF/wtf/RunLoop.cpp:147 #26 0x00007f3a0ecb48c2 in operator() (__closure=0x0, userData=0x7f39ed01c180) at /host/home/mirko/work/code/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:80 #27 0x00007f3a0ecb48ea in _FUN () at /host/home/mirko/work/code/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:82 #28 0x00007f3a0ecb4811 in operator() (__closure=0x0, source=0x6553d84c88d0, callback=0x7f3a0ecb48c9 <_FUN(gpointer)>, userData=0x7f39ed01c180) at /host/home/mirko/work/code/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:53 #29 0x00007f3a0ecb4863 in _FUN () at /host/home/mirko/work/code/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:56 #30 0x00007f3a05f2148e in g_main_dispatch (context=0x6553d83fcea0) at ../../../glib/gmain.c:3344 #31 0x00007f3a05f80717 in g_main_context_dispatch_unlocked (context=0x6553d83fcea0) at ../../../glib/gmain.c:4152 #32 g_main_context_iterate_unlocked.isra.0 (context=0x6553d83fcea0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4217 #33 0x00007f3a05f21f77 in g_main_loop_run (loop=0x6553d84d2d10) at ../../../glib/gmain.c:4419 #34 0x00007f3a0ecb4f5a in WTF::RunLoop::run () at /host/home/mirko/work/code/WebKit/Source/WTF/wtf/glib/RunLoopGLib.cpp:108 #35 0x00007f3a1ee3391a in WebKit::AuxiliaryProcessMainBase<WebKit::WebProcess, true>::run (this=0x7fff6c1098d0, argc=4, argv=0x7fff6c109a98) at /host/home/mirko/work/code/WebKit/Source/WebKit/Shared/AuxiliaryProcessMain.h:77 #36 0x00007f3a1ee33183 in WebKit::AuxiliaryProcessMain<WebKit::WebProcessMainGtk> (argc=4, argv=0x7fff6c109a98) at /host/home/mirko/work/code/WebKit/Source/WebKit/Shared/AuxiliaryProcessMain.h:103 #37 0x00007f3a1ee32b63 in WebKit::WebProcessMain (argc=4, argv=0x7fff6c109a98) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/gtk/WebProcessMainGtk.cpp:114 #38 0x00006553b1ea37fd in main (argc=4, argv=0x7fff6c109a98) at /host/home/mirko/work/code/WebKit/Source/WebKit/WebProcess/EntryPoint/unix/WebProcessMain.cpp:31 ```
Deleted User
Comment 44 2025-04-30 01:30:01 PDT
Extending https://bugs.webkit.org/show_bug.cgi?id=290042#c43: After `OffscreenCanvasRenderingContext2D::fillText`, `LayerTreeHost::scheduleLayerFlush` is sometimes first called after `GraphicsLayerCoordinated::setContentsNeedsDisplay`.
Deleted User
Comment 45 2025-04-30 05:12:47 PDT
(In reply to Mirko Brodesser from comment #38) > (In reply to Matt Woodrow from comment #37) > > What I would expect to happen: > > > > `setImageBufferAndMarkDirty` calls `CanvasBase::didDraw`, which would then > > call `contentChanged(ContentChangeType::CanvasPixels);` (for an HTML canvas > > using a placeholder rendering context). > > > > That should call through to `RenderLayerBacking::contentChanged` and then > > into `GraphicsLayer::setContentsNeedDisplay`. > > > > The `GraphicsLayer` should then call `notifyFlushRequired` on its client > > (which is `RenderLayerBacking` again). That should result in > > `Page::scheduleRenderingUpdate(RenderingUpdateStep::LayerFlush)` being > > called, which triggers the actual rendering update to happen (including > > `updateCompositingLayers`). > > > > That seems like it'd have the same effect as your current PR (which is > > returning true for `hasDeferredOperations()`, but I believe works because it > > results in a call to > > `Page::scheduleRenderingUpdate(RenderingUpdateStep:: > > PrepareCanvasesForDisplayOrFlush)`). > > > > Is part of that not working? > > Thanks for sharing the thoughts. > > Until `GraphicsLayer::setContentsNeedsDisplay` > (https://searchfox.org/wubkat/rev/91adeac8b28caf815007f457c1eb67b531854aae/ > Source/WebCore/platform/graphics/GraphicsLayer.h#506) it's working. > The overload of that method is invoked: > `GraphicsLayerCoordinated::setContentsNeedsDisplay` > (https://searchfox.org/wubkat/rev/91adeac8b28caf815007f457c1eb67b531854aae/ > Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated. > cpp#330). > Its `m_contentsDisplayDelegate` > (https://searchfox.org/wubkat/rev/91adeac8b28caf815007f457c1eb67b531854aae/ > Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated. > cpp#332) is null. When `m_contentsDisplayDelegate` is set in `GraphicsLayerCoordinated::setContentsDisplayDelegate` it calls `GraphicsLayerCoordinated::noteLayerPropertyChanged` with at least `Change::ContentsBufferNeedsDisplay` (https://searchfox.org/wubkat/rev/d17a7c5952dbe4c9affb61ad7249c4cd6d1deb61/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#355,360,363,368,370). `GraphicsLayerCoordinated::setContentsNeedsDisplay` called `noteLayerPropertyChanged` with `Change::ContentsBufferNeedsDisplay`.
Matt Woodrow
Comment 46 2025-04-30 20:11:09 PDT
That much seems correct to me. If the `setImageBufferAndMarkDirty` call happens before the first rendering update, there won't be a delegate, but there should already be a scheduled rendering update which will install the delegate and mark the layer as needing display. If the call happens after, then we should just mark as needing display, and schedule a second rendering update for that to become visible.
Deleted User
Comment 47 2025-05-01 05:47:46 PDT
(In reply to Matt Woodrow from comment #46) > That much seems correct to me. When `GraphicsLayerCoordinated::setContentsNeedsDisplay` is called before `GraphicsLayerCoordinated::setContentsDisplayDelegate`, some calls to `GraphicsLayerCoordinated::commitLayerChanges` (https://searchfox.org/wubkat/rev/6696af1b6d5aeff18a62101163a33395dc0c08ea/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#971) follow. The last of those calls clears `m_pendingChanges` and adds `Change::ContentsBufferNeedsDisplay` to it (https://searchfox.org/wubkat/rev/6696af1b6d5aeff18a62101163a33395dc0c08ea/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#1096-1097).
Deleted User
Comment 48 2025-05-01 07:01:53 PDT
Continuing https://bugs.webkit.org/show_bug.cgi?id=290042#c47: after `child.recursiveCommitChanges` in `GraphicsLayerCoordinated::recursiveCommitChanges` (https://searchfox.org/wubkat/rev/6696af1b6d5aeff18a62101163a33395dc0c08ea/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#1158) it may have pending changes. That is, adding the assertion `ASSERT(child.m_pendingChanges.isEmpty());` after `child.recursiveCommitChanges` results in a violation of the assertion.
Deleted User
Comment 49 2025-05-14 04:52:37 PDT
The patch which introduced adding an element to `m_pendingChanges` at the end of `GraphicsLayerCoordinated::commitLayerChanges` (https://searchfox.org/wubkat/rev/87ffa9eb985d4367ea42c6c953d37b077404a7eb/Source/WebCore/platform/graphics/texmap/coordinated/GraphicsLayerCoordinated.cpp#1096-1097) was introduced in https://commits.webkit.org/289418@main. I've tested this this issue with `canvas.2d.fillText-FontFace.html` with the commit before the above mentioned one. It already occurred with it. That is, it's not a regression of https://commits.webkit.org/289418@main.
EWS
Comment 50 2025-05-22 00:24:33 PDT
Committed 295259@main (153da00a2526): <https://commits.webkit.org/295259@main> Reviewed commits have been landed. Closing PR #42688 and removing active labels.
Darin Adler
Comment 51 2025-06-22 19:52:36 PDT
Reopening this because I reverted the fix since a thread-safety assertion was triggered.
Matt Woodrow
Comment 52 2025-06-23 00:54:12 PDT
Kimmo Kinnunen
Comment 53 2025-06-26 05:21:05 PDT
EWS
Comment 54 2025-06-27 04:09:24 PDT
Committed 296714@main (323a59370e03): <https://commits.webkit.org/296714@main> Reviewed commits have been landed. Closing PR #47233 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.