WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
230766
Canvas drawImage is very slow when used with video as source
https://bugs.webkit.org/show_bug.cgi?id=230766
Summary
Canvas drawImage is very slow when used with video as source
Patryk Rogalski
Reported
2021-09-24 12:01:45 PDT
Created
attachment 439181
[details]
comparison between Chrome and Safari I'm running the latest Safari and Safari Technology Preview and I've run into a performance issue in Safari. I have a video that is encoded in H264 2176x1088. The video itself plays smoothly however I have to cut the content of it into 8 different canvas elements. I have a working demo of it working however the performance I'm getting is abysmal. I've ran the same code in Google Chrome 94 and it's perfect. Here is the comparison: Chrome takes about 0.5-2ms to draw Safari takes 150-330ms to draw Firefox takes 100-150ms And it has to run at 30 fps... which is completely impossible right now. Here is a demo to showcase the issue:
https://cdn.zu.casa/dev/apple/index.html
If open developer console it'll print out to the console the time it took to render.
Attachments
comparison between Chrome and Safari
(41.09 MB, video/quicktime)
2021-09-24 12:01 PDT
,
Patryk Rogalski
no flags
Details
Patch for EWS
(2.21 KB, patch)
2021-10-24 18:49 PDT
,
Cameron McCormack (:heycam)
no flags
Details
Formatted Diff
Diff
Patch
(2.76 KB, patch)
2021-10-27 16:25 PDT
,
Cameron McCormack (:heycam)
no flags
Details
Formatted Diff
Diff
Patch
(4.78 KB, patch)
2021-10-28 23:28 PDT
,
Cameron McCormack (:heycam)
no flags
Details
Formatted Diff
Diff
Patch for landing
(2.72 KB, patch)
2021-11-04 20:35 PDT
,
Cameron McCormack (:heycam)
no flags
Details
Formatted Diff
Diff
Show Obsolete
(3)
View All
Add attachment
proposed patch, testcase, etc.
Patryk Rogalski
Comment 1
2021-09-24 12:12:14 PDT
I had an older version of Safari on my iMac and it ran super fast (1.5-4ms) - as fast as in Google Chrome. After updating to the latest version it's terrible (200-350ms).
Sam Sneddon [:gsnedders]
Comment 2
2021-09-27 01:22:01 PDT
Quick look at a sample suggests we're blocking on cross-thread/process communication a bunch. Probably a regression caused by moving more things out-of-process?
Radar WebKit Bug Importer
Comment 3
2021-09-27 09:12:51 PDT
<
rdar://problem/83576009
>
Cameron McCormack (:heycam)
Comment 4
2021-10-24 16:51:44 PDT
Thanks for the bug report. Sam is right: this is because with GPU process canvas rendering enabled, we end up doing some copies of the HTMLVideoElement frame data (which lives in the GPU process) to share it (synchronously) to the Web process, only to ship it back to the GPU process again for the drawImage() call. We should be able to avoid any of this copying.
Cameron McCormack (:heycam)
Comment 5
2021-10-24 18:49:46 PDT
Created
attachment 442334
[details]
Patch for EWS
Cameron McCormack (:heycam)
Comment 6
2021-10-27 16:25:38 PDT
Created
attachment 442649
[details]
Patch
Cameron McCormack (:heycam)
Comment 7
2021-10-27 17:16:28 PDT
Simon pointed out to me there's another call to nativeImageForCurrentTime(), in createPattern(). But patterns currently can't avoid copying the pattern source image data from the GPU process, so I'll leave that be for now. And filed
https://bugs.webkit.org/show_bug.cgi?id=232411
for the more general problem.
Cameron McCormack (:heycam)
Comment 8
2021-10-28 23:28:38 PDT
Created
attachment 442787
[details]
Patch
EWS
Comment 9
2021-10-29 14:45:47 PDT
Committed
r285055
(
243698@main
): <
https://commits.webkit.org/243698@main
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 442787
[details]
.
ayumi_kojima
Comment 10
2021-11-01 09:28:08 PDT
Reverted
r285055
for reason: Reverting because this commit may have caused webgl/1.0.x/conformance/textures/misc/texture-corner-case-videos.html and webgl/2.0.y/conformance/textures/misc/texture-corner-case-videos.html to time out Committed
r285110
(
243751@main
): <
https://commits.webkit.org/243751@main
>
Said Abou-Hallawa
Comment 11
2021-11-01 11:13:48 PDT
Comment on
attachment 442787
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=442787&action=review
> Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp:1680 > + if (!canvasBase().buffer()->isRemote()) {
We have been trying to avoid adding this condition in WebCore. Can't we do this by checking whether 'c', which is the GraphicsContext of canvasBase().buffer(), is a recording GraphicsContext or not? I think you can replace this condition by if (c->hasPlatformContext()) { ... return { }; } This function has been used for this purpose in WebCore in a few places. Just search for it.
> Source/WebCore/platform/graphics/ImageBuffer.h:74 > + virtual bool isRemote() const { return false; }
Please avoid adding such check in WebCore.
> Source/WebKit/WebProcess/GPU/graphics/RemoteImageBufferProxy.h:98 > + bool isRemote() const final { return true; }
This method can be private.
Cameron McCormack (:heycam)
Comment 12
2021-11-01 14:48:10 PDT
(In reply to Said Abou-Hallawa from
comment #11
)
> > Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp:1680 > > + if (!canvasBase().buffer()->isRemote()) { > > We have been trying to avoid adding this condition in WebCore. Can't we do > this by checking whether 'c', which is the GraphicsContext of > canvasBase().buffer(), is a recording GraphicsContext or not? > > I think you can replace this condition by > > if (c->hasPlatformContext()) { > ... > return { }; > }
I had that in my original patch but Simon was not sure about it, so I changed it to this more direct check on the ImageBuffer. I can change it back.
Wenson Hsieh
Comment 13
2021-11-01 16:16:22 PDT
(In reply to Cameron McCormack (:heycam) from
comment #12
)
> (In reply to Said Abou-Hallawa from
comment #11
) > > > Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp:1680 > > > + if (!canvasBase().buffer()->isRemote()) { > > > > We have been trying to avoid adding this condition in WebCore. Can't we do > > this by checking whether 'c', which is the GraphicsContext of > > canvasBase().buffer(), is a recording GraphicsContext or not? > > > > I think you can replace this condition by > > > > if (c->hasPlatformContext()) { > > ... > > return { }; > > } > > I had that in my original patch but Simon was not sure about it, so I > changed it to this more direct check on the ImageBuffer. I can change it > back.
Generally speaking, methods that explicitly reference the WebKit process model (e.g. the notion of "remote" or "proxy" objects) normally exist in the WebKit2 layer, with client layer hooks (on WebChromeClient, for instance) that WebCore code may use in order to delegate decision-making to things that know about the process model. That said, there are some exceptions to this. But in general, ImageBuffer and its subclasses/backends have preserved this separation — it's also how we've (previously) avoided adding a method like `isRemote()` to image buffer.
Cameron McCormack (:heycam)
Comment 14
2021-11-04 20:35:42 PDT
Created
attachment 443372
[details]
Patch for landing
EWS
Comment 15
2021-11-04 21:06:19 PDT
Committed
r285333
(
243896@main
): <
https://commits.webkit.org/243896@main
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 443372
[details]
.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug