fix: offscreen rendering with correct screen info. (#48730)

fix: osr use correct screen info.
This commit is contained in:
reito
2026-01-23 03:58:54 +08:00
committed by GitHub
parent 1f8e4079cd
commit e3142865b2
12 changed files with 174 additions and 51 deletions

View File

@@ -826,6 +826,8 @@ WebContents::WebContents(v8::Isolate* isolate,
&offscreen_use_shared_texture_);
use_offscreen_dict.Get(options::kSharedTexturePixelFormat,
&offscreen_shared_texture_pixel_format_);
use_offscreen_dict.Get(options::kDeviceScaleFactor,
&offscreen_device_scale_factor_);
}
}
@@ -864,6 +866,7 @@ WebContents::WebContents(v8::Isolate* isolate,
auto* view = new OffScreenWebContentsView(
false, offscreen_use_shared_texture_,
offscreen_shared_texture_pixel_format_,
offscreen_device_scale_factor_,
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
params.view = view;
params.delegate_view = view;
@@ -885,7 +888,7 @@ WebContents::WebContents(v8::Isolate* isolate,
content::WebContents::CreateParams params(session->browser_context());
auto* view = new OffScreenWebContentsView(
transparent, offscreen_use_shared_texture_,
offscreen_shared_texture_pixel_format_,
offscreen_shared_texture_pixel_format_, offscreen_device_scale_factor_,
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
params.view = view;
params.delegate_view = view;
@@ -1249,6 +1252,7 @@ void WebContents::MaybeOverrideCreateParamsForNewWindow(
auto* view = new OffScreenWebContentsView(
false, offscreen_use_shared_texture_,
offscreen_shared_texture_pixel_format_,
offscreen_device_scale_factor_,
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
create_params->view = view;
create_params->delegate_view = view;

View File

@@ -820,6 +820,13 @@ class WebContents final : public ExclusiveAccessContext,
bool offscreen_use_shared_texture_ = false;
std::string offscreen_shared_texture_pixel_format_ = "argb";
// TODO(reito): 0.0f means the device scale factor is not set, it's a
// migration of the breaking change so that we can read the device scale
// factor from physical primary screen's info. In Electron 42, we need to set
// this to 1.0f so that the offscreen rendering use 1.0 as default when
// `deviceScaleFactor` is not specified in webPreferences.
float offscreen_device_scale_factor_ = 0.0f;
// Whether window is fullscreened by HTML5 api.
bool html_fullscreen_ = false;

View File

@@ -53,8 +53,6 @@ namespace electron {
namespace {
const float kDefaultScaleFactor = 1.0;
ui::MouseEvent UiMouseEventFromWebMouseEvent(blink::WebMouseEvent event) {
int button_flags = 0;
switch (event.button) {
@@ -96,6 +94,15 @@ ui::MouseWheelEvent UiMouseWheelEventFromWebMouseEvent(
base::ClampFloor<int>(event.delta_y)};
}
// TODO(reito): Remove this function and use default 1.0f when Electron 42.
float GetDefaultDeviceScaleFactorFromDisplayInfo() {
display::Display display =
display::Screen::Get()->GetDisplayNearestView(gfx::NativeView());
const float factor = display.device_scale_factor();
return factor > 0 ? factor : 1.0f;
}
} // namespace
class ElectronDelegatedFrameHostClient
@@ -155,6 +162,7 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
bool transparent,
bool offscreen_use_shared_texture,
const std::string& offscreen_shared_texture_pixel_format,
float offscreen_device_scale_factor,
bool painting,
int frame_rate,
const OnPaintCallback& callback,
@@ -168,6 +176,7 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
offscreen_use_shared_texture_(offscreen_use_shared_texture),
offscreen_shared_texture_pixel_format_(
offscreen_shared_texture_pixel_format),
offscreen_device_scale_factor_(offscreen_device_scale_factor),
callback_(callback),
frame_rate_(frame_rate),
size_(initial_size),
@@ -184,11 +193,11 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
DCHECK(render_widget_host_);
DCHECK(!render_widget_host_->GetView());
// Initialize a screen_infos_ struct as needed, to cache the scale factor.
if (screen_infos_.screen_infos.empty()) {
UpdateScreenInfo();
// TODO(reito): Remove this when Electron 42.
if (cc::MathUtil::IsWithinEpsilon(offscreen_device_scale_factor_, 0.0f)) {
offscreen_device_scale_factor_ =
GetDefaultDeviceScaleFactorFromDisplayInfo();
}
screen_infos_.mutable_current().device_scale_factor = kDefaultScaleFactor;
delegated_frame_host_allocator_.GenerateId();
delegated_frame_host_surface_id_ =
@@ -210,15 +219,6 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
compositor_->SetDelegate(this);
compositor_->SetRootLayer(root_layer_.get());
// For offscreen rendering with format rgbaf16, we need to set correct display
// color spaces to the compositor, otherwise it won't support hdr.
if (offscreen_use_shared_texture_ &&
offscreen_shared_texture_pixel_format_ == "rgbaf16") {
gfx::DisplayColorSpaces hdr_display_color_spaces(
gfx::ColorSpace::CreateSRGBLinear(), viz::SinglePlaneFormat::kRGBA_F16);
compositor_->SetDisplayColorSpaces(hdr_display_color_spaces);
}
ResizeRootLayer(false);
render_widget_host_->SetView(this);
@@ -504,19 +504,6 @@ void OffScreenRenderWidgetHostView::CopyFromSurface(
src_rect, output_size, base::TimeDelta(), std::move(callback));
}
display::ScreenInfo OffScreenRenderWidgetHostView::GetScreenInfo() const {
display::ScreenInfo screen_info;
screen_info.depth = 24;
screen_info.depth_per_component = 8;
screen_info.orientation_angle = 0;
screen_info.device_scale_factor = GetDeviceScaleFactor();
screen_info.orientation_type =
display::mojom::ScreenOrientation::kLandscapePrimary;
screen_info.rect = gfx::Rect(size_);
screen_info.available_rect = gfx::Rect(size_);
return screen_info;
}
gfx::Rect OffScreenRenderWidgetHostView::GetBoundsInRootWindow() {
return gfx::Rect(size_);
}
@@ -562,8 +549,8 @@ OffScreenRenderWidgetHostView::CreateViewForWidget(
return new OffScreenRenderWidgetHostView(
transparent_, offscreen_use_shared_texture_,
offscreen_shared_texture_pixel_format_, true,
embedder_host_view->frame_rate(), callback_, render_widget_host,
offscreen_shared_texture_pixel_format_, offscreen_device_scale_factor_,
true, embedder_host_view->frame_rate(), callback_, render_widget_host,
embedder_host_view, size());
}
@@ -971,35 +958,55 @@ void OffScreenRenderWidgetHostView::InvalidateBounds(const gfx::Rect& bounds) {
CompositeFrame(bounds);
}
display::ScreenInfos
OffScreenRenderWidgetHostView::GetNewScreenInfosForUpdate() {
display::ScreenInfo screen_info;
screen_info.depth = 24;
screen_info.depth_per_component = 8;
screen_info.orientation_angle = 0;
screen_info.orientation_type =
display::mojom::ScreenOrientation::kLandscapePrimary;
screen_info.rect = gfx::Rect(size_);
screen_info.available_rect = gfx::Rect(size_);
screen_info.device_scale_factor = offscreen_device_scale_factor_;
// When pixel format is 'rgbaf16', we need to set screen info to support HDR.
if (offscreen_use_shared_texture_ &&
offscreen_shared_texture_pixel_format_ == "rgbaf16") {
gfx::DisplayColorSpaces hdr_display_color_spaces{
gfx::ColorSpace::CreateSRGBLinear(), viz::SinglePlaneFormat::kRGBA_F16};
// The max luminance value doesn't matter so we set to a large value.
hdr_display_color_spaces.SetHDRMaxLuminanceRelative(100.0f);
screen_info.display_color_spaces = hdr_display_color_spaces;
}
display::ScreenInfos screen_infos{screen_info};
return screen_infos;
}
void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) {
SetupFrameRate(false);
display::Display display =
display::Screen::Get()->GetDisplayNearestView(GetNativeView());
const float scaleFactor = display.device_scale_factor();
float sf = GetDeviceScaleFactor();
const bool sf_did_change = scaleFactor != sf;
// Initialize a screen_infos_ struct as needed, to cache the scale factor.
if (screen_infos_.screen_infos.empty()) {
UpdateScreenInfo();
}
screen_infos_.mutable_current().device_scale_factor = scaleFactor;
auto old_screen_info = screen_infos_.current();
UpdateScreenInfo();
auto new_screen_info = screen_infos_.current();
gfx::Size size = GetViewBounds().size();
if (!force && !sf_did_change && size == root_layer()->bounds().size())
if (!force && size == root_layer()->bounds().size() &&
old_screen_info == new_screen_info)
return;
root_layer()->SetBounds(gfx::Rect(size));
const gfx::Size& size_in_pixels =
gfx::ToFlooredSize(gfx::ConvertSizeToPixels(size, sf));
auto sf = GetDeviceScaleFactor();
const gfx::Size& size_in_pixels = SizeInPixels();
if (compositor_) {
compositor_allocator_.GenerateId();
compositor_surface_id_ = compositor_allocator_.GetCurrentLocalSurfaceId();
compositor_->SetScaleAndSize(sf, size_in_pixels, compositor_surface_id_);
compositor_->SetDisplayColorSpaces(new_screen_info.display_color_spaces);
}
delegated_frame_host_allocator_.GenerateId();

View File

@@ -73,6 +73,7 @@ class OffScreenRenderWidgetHostView
bool transparent,
bool offscreen_use_shared_texture,
const std::string& offscreen_shared_texture_pixel_format,
float offscreen_device_scale_factor,
bool painting,
int frame_rate,
const OnPaintCallback& callback,
@@ -151,7 +152,6 @@ class OffScreenRenderWidgetHostView
base::TimeDelta timeout,
base::OnceCallback<void(const content::CopyFromSurfaceResult&)> callback)
override;
display::ScreenInfo GetScreenInfo() const override;
void TransformPointToRootSurface(gfx::PointF* point) override {}
gfx::Rect GetBoundsInRootWindow() override;
std::optional<content::DisplayFeature> GetDisplayFeature() override;
@@ -171,6 +171,7 @@ class OffScreenRenderWidgetHostView
const std::optional<std::vector<gfx::Rect>>& character_bounds) override {}
gfx::Size GetCompositorViewportPixelSize() override;
ui::Compositor* GetCompositor() override;
display::ScreenInfos GetNewScreenInfosForUpdate() override;
content::RenderWidgetHostViewBase* CreateViewForWidget(
content::RenderWidgetHost*,
@@ -293,6 +294,8 @@ class OffScreenRenderWidgetHostView
const bool transparent_;
const bool offscreen_use_shared_texture_;
const std::string offscreen_shared_texture_pixel_format_;
float offscreen_device_scale_factor_;
OnPaintCallback callback_;
OnPopupPaintCallback parent_callback_;

View File

@@ -17,11 +17,13 @@ OffScreenWebContentsView::OffScreenWebContentsView(
bool transparent,
bool offscreen_use_shared_texture,
const std::string& offscreen_shared_texture_pixel_format,
float offscreen_device_scale_factor,
const OnPaintCallback& callback)
: transparent_(transparent),
offscreen_use_shared_texture_(offscreen_use_shared_texture),
offscreen_shared_texture_pixel_format_(
offscreen_shared_texture_pixel_format),
offscreen_device_scale_factor_(offscreen_device_scale_factor),
callback_(callback) {
#if BUILDFLAG(IS_MAC)
PlatformCreate();
@@ -116,8 +118,9 @@ OffScreenWebContentsView::CreateViewForWidget(
return new OffScreenRenderWidgetHostView(
transparent_, offscreen_use_shared_texture_,
offscreen_shared_texture_pixel_format_, painting_, GetFrameRate(),
callback_, render_widget_host, nullptr, GetSize());
offscreen_shared_texture_pixel_format_, offscreen_device_scale_factor_,
painting_, GetFrameRate(), callback_, render_widget_host, nullptr,
GetSize());
}
content::RenderWidgetHostViewBase*
@@ -137,9 +140,9 @@ OffScreenWebContentsView::CreateViewForChildWidget(
return new OffScreenRenderWidgetHostView(
transparent_, offscreen_use_shared_texture_,
offscreen_shared_texture_pixel_format_, painting_,
embedder_host_view->frame_rate(), callback_, render_widget_host,
embedder_host_view, GetSize());
offscreen_shared_texture_pixel_format_, offscreen_device_scale_factor_,
painting_, embedder_host_view->frame_rate(), callback_,
render_widget_host, embedder_host_view, GetSize());
}
void OffScreenWebContentsView::RenderViewReady() {

View File

@@ -38,6 +38,7 @@ class OffScreenWebContentsView : public content::WebContentsView,
bool transparent,
bool offscreen_use_shared_texture,
const std::string& offscreen_shared_texture_pixel_format,
float offscreen_device_scale_factor,
const OnPaintCallback& callback);
~OffScreenWebContentsView() override;
@@ -113,6 +114,7 @@ class OffScreenWebContentsView : public content::WebContentsView,
const bool transparent_;
const bool offscreen_use_shared_texture_;
const std::string offscreen_shared_texture_pixel_format_;
const float offscreen_device_scale_factor_;
bool painting_ = true;
int frame_rate_ = 60;
OnPaintCallback callback_;

View File

@@ -186,6 +186,8 @@ inline constexpr std::string_view kUseSharedTexture = "useSharedTexture";
inline constexpr std::string_view kSharedTexturePixelFormat =
"sharedTexturePixelFormat";
inline constexpr std::string_view kDeviceScaleFactor = "deviceScaleFactor";
inline constexpr std::string_view kNodeIntegrationInSubFrames =
"nodeIntegrationInSubFrames";