Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: set window contents as opaque to decrease DWM GPU usage #39895

Merged

Conversation

brhenrique
Copy link
Contributor

@brhenrique brhenrique commented Sep 18, 2023

Description of Change

The window contents of Electron windows are marked as transparent even though neither transparent nor opacity settings are set in the BrowserWindow options.

Debugging DirectComposition redraws

Chromium 118 has a new flag called DCompDebugVisualization that uses EnableDrawRegions to display on the screen sections of a window that are redrawn by DirectComposition.

The problem

With DCompDebugVisualization, we can notice a difference in the frequency of redraws of <video> elements in Chromium compared to a regular non-transparent window in Electron.

While a video stream is rendered on screen, almost no redraws are displayed in Chromium. On Electron, a redraw is displayed for every video frame rendered.

Electron Fiddle gist: https://gist.github.com/brhenrique/100fc28409508d1730fb4216268cf04a

Why it happens?

When the contents of the window are set to be transparent, DirectCompositionChildSurfaceWin::SetDrawRectangle will use DXGI_ALPHA_MODE_PREMULTIPLIED instead of DXGI_ALPHA_MODE_IGNORE. This will trigger the DC redraw for every video frame.

Solution

If neither transparent nor opacity settings are used with a BrowserWindow, it seems safe to assume the contents of the BrowserWindow won't need alpha blending with other windows. So in this PR we override ShouldWindowContentsBeTransparent to take into account the transparency and opacity settings of the native window.

Results

Rendering 4 480p video elements in a blank opaque non-fullscreen Electron window on a 2160p display

Before: DWM uses 16-18% GPU
After: DWM uses less than 1%

Rendering 4 480p video elements in a blank opaque non-fullscreen Electron window on a 1080p display

Before: DWM uses 6-8% GPU
After: DWM uses less than 1%

Checklist

Release Notes

Notes: prevent DWM from redrawing video frames rendered on opaque windows

@electron-cation electron-cation bot added the new-pr 🌱 PR opened in the last 24 hours label Sep 18, 2023
@deepak1556
Copy link
Member

Thanks for the detailed analysis!

In case of Electron the title bar are system drawn unlike Chrome, so we get the default behavior defined in https://source.chromium.org/chromium/chromium/src/+/main:ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc;l=533-538. Do we regress with undrawn regions in the titlebar with this change ?

@brhenrique
Copy link
Contributor Author

Thanks for the detailed analysis!

In case of Electron the title bar are system drawn unlike Chrome, so we get the default behavior defined in https://source.chromium.org/chromium/chromium/src/+/main:ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc;l=533-538. Do we regress with undrawn regions in the titlebar with this change ?

Yeah I got a bit confused by that comment because I couldn't remember of any app that draws underneath the title bar. Looking further back the commit history, this setting seems to originally come from a requirement from Aero Glass (removed on W8+)

https://codereview.chromium.org/2487893002/diff/1/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc

Maybe this could be an issue if there was some code using DwmExtendFrameIntoClientArea to extend the client area to invade the title bar (never tried that so not sure if it's possible), but I couldn't find any place where this function is used that way in Electron.

Tried this PR with backgroundMaterial: acrylic, no issues there as well. titleBarStyle: hidden and titleBarOverlay: true also seem to work fine.

@zcbenz zcbenz changed the title set window contents as opaque to decrease DWM GPU usage fix: set window contents as opaque to decrease DWM GPU usage Sep 25, 2023
@zcbenz zcbenz added semver/patch backwards-compatible bug fixes no-backport labels Sep 25, 2023
@electron-cation electron-cation bot removed the new-pr 🌱 PR opened in the last 24 hours label Sep 25, 2023
@zcbenz zcbenz added target/27-x-y PR should also be added to the "27-x-y" branch. and removed no-backport labels Sep 25, 2023
@MarshallOfSound
Copy link
Member

@brhenrique can you rebase on latest main to pull in the depot_tools CI fixes

@brhenrique brhenrique force-pushed the disable-dxgi-alpha-on-opaque-windows branch from 50aa344 to 3f40d82 Compare September 26, 2023 12:39
@brhenrique
Copy link
Contributor Author

@brhenrique can you rebase on latest main to pull in the depot_tools CI fixes

@MarshallOfSound sure, done. Now appveyor: win-woa-testing failed but I couldn't find in the CI logs which test failed 🤔

@jkleinsc jkleinsc merged commit f943b8c into electron:main Sep 27, 2023
15 checks passed
@release-clerk
Copy link

release-clerk bot commented Sep 27, 2023

Release Notes Persisted

Fixed opaque window performance regression on DWM

@trop
Copy link
Contributor

trop bot commented Sep 27, 2023

I have automatically backported this PR to "27-x-y", please check out #40003

MrHuangJser pushed a commit to MrHuangJser/electron that referenced this pull request Dec 11, 2023
…n#39895)

* set window contents as opaque to decrease DWM GPU usage

* chore: add more context to ShouldWindowContentsBeTransparent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged/27-x-y PR was merged to the "27-x-y" branch. semver/patch backwards-compatible bug fixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants