From 17d85318c3ad0a3bcef0bc65f0787e15c7449497 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Jan 2018 14:40:37 +0100 Subject: [PATCH 1/7] Use null accelerated widget to avoid showing GPU accelerated OSR surface --- atom/browser/osr/osr_render_widget_host_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index 295b3f886d..8fd17f3435 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -303,7 +303,7 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( new ui::Compositor(context_factory_private->AllocateFrameSinkId(), content::GetContextFactory(), context_factory_private, base::ThreadTaskRunnerHandle::Get(), false)); - compositor_->SetAcceleratedWidget(native_window_->GetAcceleratedWidget()); + compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); compositor_->SetRootLayer(root_layer_.get()); #endif GetCompositor()->SetDelegate(this); From 708cde92cf8dd2904809236ab37e73e3da71f56c Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Jan 2018 14:42:11 +0100 Subject: [PATCH 2/7] Don't generate a paint when StartPainting is called inside paint cb --- atom/browser/osr/osr_render_widget_host_view.cc | 5 ++++- atom/browser/osr/osr_render_widget_host_view.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index 8fd17f3435..842cfba099 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -279,6 +279,7 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( popup_position_(gfx::Rect()), hold_resize_(false), pending_resize_(false), + paint_callback_running_(false), renderer_compositor_frame_sink_(nullptr), background_color_(SkColor()), weak_ptr_factory_(this) { @@ -999,7 +1000,9 @@ void OffScreenRenderWidgetHostView::OnPaint( } damage.Intersect(GetViewBounds()); + paint_callback_running_ = true; callback_.Run(damage, bitmap); + paint_callback_running_ = false; for (size_t i = 0; i < damages.size(); i++) { CopyBitmapTo(bitmap, originals[i], damages[i]); @@ -1147,7 +1150,7 @@ void OffScreenRenderWidgetHostView::SetPainting(bool painting) { painting_ = painting; if (software_output_device_) { - software_output_device_->SetActive(painting_, true); + software_output_device_->SetActive(painting_, !paint_callback_running_); } } diff --git a/atom/browser/osr/osr_render_widget_host_view.h b/atom/browser/osr/osr_render_widget_host_view.h index ed4b160440..42d4e7341f 100644 --- a/atom/browser/osr/osr_render_widget_host_view.h +++ b/atom/browser/osr/osr_render_widget_host_view.h @@ -315,6 +315,8 @@ class OffScreenRenderWidgetHostView bool hold_resize_; bool pending_resize_; + bool paint_callback_running_; + std::unique_ptr root_layer_; std::unique_ptr compositor_; std::unique_ptr delegated_frame_host_; From 304fd49e84e32ee10838e6082a48a59ee111a3a6 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Jan 2018 14:43:31 +0100 Subject: [PATCH 3/7] Don't generate a frame with GPU OSR if IsPainting is false --- atom/browser/osr/osr_render_widget_host_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index 842cfba099..9fdb6abe11 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -124,7 +124,7 @@ class AtomCopyFrameGenerator { } void GenerateCopyFrame(const gfx::Rect& damage_rect) { - if (!view_->render_widget_host()) + if (!view_->render_widget_host() || !view_->IsPainting()) return; std::unique_ptr request = From 099bbfbafbaf918d6befe3d84403d7e0e8a34ac3 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Jan 2018 14:44:19 +0100 Subject: [PATCH 4/7] Raise maximum OSR framerate to 240 --- atom/browser/osr/osr_render_widget_host_view.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index 9fdb6abe11..c6af6a7b44 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -1167,8 +1167,8 @@ void OffScreenRenderWidgetHostView::SetFrameRate(int frame_rate) { } else { if (frame_rate <= 0) frame_rate = 1; - if (frame_rate > 60) - frame_rate = 60; + if (frame_rate > 240) + frame_rate = 240; frame_rate_ = frame_rate; } From 1a8916ed4737a143442d6201f097b702e8cab3db Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Jan 2018 14:45:01 +0100 Subject: [PATCH 5/7] Call SetAuthoritativeVsyncInterval on the Compositor directly --- atom/browser/osr/osr_render_widget_host_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index c6af6a7b44..abcc0e416d 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -1204,7 +1204,7 @@ void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) { frame_rate_threshold_us_ = 1000000 / frame_rate_; - GetCompositor()->vsync_manager()->SetAuthoritativeVSyncInterval( + GetCompositor()->SetAuthoritativeVSyncInterval( base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_)); if (copy_frame_generator_.get()) { From 406f171c88fe6d7bbcefa7f1b4cafd47c26f8a0f Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Thu, 25 Jan 2018 14:46:30 +0100 Subject: [PATCH 6/7] Move OSR api to OsrWCV to allow api calls to take effect sooner --- atom/browser/api/atom_api_web_contents.cc | 60 ++++++++++++------- atom/browser/api/atom_api_web_contents.h | 5 ++ .../osr/osr_render_widget_host_view.cc | 14 +++-- .../browser/osr/osr_render_widget_host_view.h | 2 + atom/browser/osr/osr_web_contents_view.cc | 42 +++++++++++++ atom/browser/osr/osr_web_contents_view.h | 7 +++ 6 files changed, 105 insertions(+), 25 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 2426de7ac3..2b67c8274f 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -378,8 +378,8 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options) options.Get("transparent", &transparent); content::WebContents::CreateParams params(session->browser_context()); - auto* view = new OffScreenWebContentsView( - transparent, base::Bind(&WebContents::OnPaint, base::Unretained(this))); + auto* view = new OffScreenWebContentsView(transparent, + base::Bind(&WebContents::OnPaint, base::Unretained(this))); params.view = view; params.delegate_view = view; @@ -1652,10 +1652,14 @@ void WebContents::StartPainting() { return; #if defined(ENABLE_OSR) - auto* osr_rwhv = static_cast( - web_contents()->GetRenderWidgetHostView()); - if (osr_rwhv) - osr_rwhv->SetPainting(true); + const auto* wc_impl = web_contents_impl(); + if (!wc_impl) + return; + + auto* osr_wcv = static_cast( + wc_impl->GetView()); + if (osr_wcv) + osr_wcv->SetPainting(true); #endif } @@ -1664,10 +1668,14 @@ void WebContents::StopPainting() { return; #if defined(ENABLE_OSR) - auto* osr_rwhv = static_cast( - web_contents()->GetRenderWidgetHostView()); - if (osr_rwhv) - osr_rwhv->SetPainting(false); + const auto* wc_impl = web_contents_impl(); + if (!wc_impl) + return; + + auto* osr_wcv = static_cast( + wc_impl->GetView()); + if (osr_wcv) + osr_wcv->SetPainting(false); #endif } @@ -1676,9 +1684,13 @@ bool WebContents::IsPainting() const { return false; #if defined(ENABLE_OSR) - const auto* osr_rwhv = static_cast( - web_contents()->GetRenderWidgetHostView()); - return osr_rwhv && osr_rwhv->IsPainting(); + const auto* wc_impl = web_contents_impl(); + if (!wc_impl) + return false; + + const auto* osr_wcv = static_cast( + wc_impl->GetView()); + return osr_wcv && osr_wcv->IsPainting(); #else return false; #endif @@ -1689,10 +1701,14 @@ void WebContents::SetFrameRate(int frame_rate) { return; #if defined(ENABLE_OSR) - auto* osr_rwhv = static_cast( - web_contents()->GetRenderWidgetHostView()); - if (osr_rwhv) - osr_rwhv->SetFrameRate(frame_rate); + const auto* wc_impl = web_contents_impl(); + if (!wc_impl) + return; + + auto* osr_wcv = static_cast( + wc_impl->GetView()); + if (osr_wcv) + osr_wcv->SetFrameRate(frame_rate); #endif } @@ -1701,9 +1717,13 @@ int WebContents::GetFrameRate() const { return 0; #if defined(ENABLE_OSR) - const auto* osr_rwhv = static_cast( - web_contents()->GetRenderWidgetHostView()); - return osr_rwhv ? osr_rwhv->GetFrameRate() : 0; + const auto* wc_impl = web_contents_impl(); + if (!wc_impl) + return 0; + + const auto* osr_wcv = static_cast( + wc_impl->GetView()); + return osr_wcv ? osr_wcv->GetFrameRate() : 0; #else return 0; #endif diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 16f2321055..c27d1f7789 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -13,6 +13,7 @@ #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "atom/browser/ui/autofill_popup.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/cursors/webcursor.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/web_contents.h" @@ -373,6 +374,10 @@ class WebContents : public mate::TrackableObject, return ++request_id_; } + content::WebContentsImpl* web_contents_impl() const { + return static_cast(web_contents()); + } + // Called when we receive a CursorChange message from chromium. void OnCursorChange(const content::WebCursor& cursor); diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index abcc0e416d..a2f5407665 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -255,6 +255,8 @@ class AtomBeginFrameTimer : public cc::DelayBasedTimeSourceClient { OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( bool transparent, + bool painting, + int frame_rate, const OnPaintCallback& callback, content::RenderWidgetHost* host, OffScreenRenderWidgetHostView* parent_host_view, @@ -268,12 +270,12 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( transparent_(transparent), callback_(callback), parent_callback_(nullptr), - frame_rate_(60), + frame_rate_(frame_rate), frame_rate_threshold_us_(0), last_time_(base::Time::Now()), scale_factor_(kDefaultScaleFactor), size_(native_window->GetSize()), - painting_(true), + painting_(painting), is_showing_(!render_widget_host_->is_hidden()), is_destroyed_(false), popup_position_(gfx::Rect()), @@ -738,6 +740,8 @@ content::RenderWidgetHostViewBase* return new OffScreenRenderWidgetHostView( transparent_, + true, + embedder_host_view->GetFrameRate(), callback_, render_widget_host, embedder_host_view, @@ -929,7 +933,7 @@ bool OffScreenRenderWidgetHostView::IsAutoResizeEnabled() const { void OffScreenRenderWidgetHostView::SetNeedsBeginFrames( bool needs_begin_frames) { - SetupFrameRate(false); + SetupFrameRate(true); begin_frame_timer_->SetActive(needs_begin_frames); @@ -1173,10 +1177,10 @@ void OffScreenRenderWidgetHostView::SetFrameRate(int frame_rate) { frame_rate_ = frame_rate; } + SetupFrameRate(true); + for (auto guest_host_view : guest_host_views_) guest_host_view->SetFrameRate(frame_rate); - - SetupFrameRate(true); } int OffScreenRenderWidgetHostView::GetFrameRate() const { diff --git a/atom/browser/osr/osr_render_widget_host_view.h b/atom/browser/osr/osr_render_widget_host_view.h index 42d4e7341f..3858d69eba 100644 --- a/atom/browser/osr/osr_render_widget_host_view.h +++ b/atom/browser/osr/osr_render_widget_host_view.h @@ -74,6 +74,8 @@ class OffScreenRenderWidgetHostView public OffscreenViewProxyObserver { public: OffScreenRenderWidgetHostView(bool transparent, + bool painting, + int frame_rate, const OnPaintCallback& callback, content::RenderWidgetHost* render_widget_host, OffScreenRenderWidgetHostView* parent_host_view, diff --git a/atom/browser/osr/osr_web_contents_view.cc b/atom/browser/osr/osr_web_contents_view.cc index 0e10abf6a0..4cbc6a5c42 100644 --- a/atom/browser/osr/osr_web_contents_view.cc +++ b/atom/browser/osr/osr_web_contents_view.cc @@ -15,6 +15,8 @@ namespace atom { OffScreenWebContentsView::OffScreenWebContentsView( bool transparent, const OnPaintCallback& callback) : transparent_(transparent), + painting_(true), + frame_rate_(60), callback_(callback), web_contents_(nullptr) { #if defined(OS_MACOSX) @@ -103,6 +105,8 @@ content::RenderWidgetHostViewBase* auto relay = NativeWindowRelay::FromWebContents(web_contents_); return new OffScreenRenderWidgetHostView( transparent_, + painting_, + GetFrameRate(), callback_, render_widget_host, nullptr, @@ -125,6 +129,8 @@ content::RenderWidgetHostViewBase* return new OffScreenRenderWidgetHostView( transparent_, + true, + view->GetFrameRate(), callback_, render_widget_host, view, @@ -202,6 +208,42 @@ void OffScreenWebContentsView::UpdateDragCursor( blink::WebDragOperation operation) { } +void OffScreenWebContentsView::SetPainting(bool painting) { + auto* view = GetView(); + if (view != nullptr) { + view->SetPainting(painting); + } else { + painting_ = painting; + } +} + +bool OffScreenWebContentsView::IsPainting() const { + auto* view = GetView(); + if (view != nullptr) { + return view->IsPainting(); + } else { + return painting_; + } +} + +void OffScreenWebContentsView::SetFrameRate(int frame_rate) { + auto* view = GetView(); + if (view != nullptr) { + view->SetFrameRate(frame_rate); + } else { + frame_rate_ = frame_rate; + } +} + +int OffScreenWebContentsView::GetFrameRate() const { + auto* view = GetView(); + if (view != nullptr) { + return view->GetFrameRate(); + } else { + return frame_rate_; + } +} + OffScreenRenderWidgetHostView* OffScreenWebContentsView::GetView() const { if (web_contents_) { return static_cast( diff --git a/atom/browser/osr/osr_web_contents_view.h b/atom/browser/osr/osr_web_contents_view.h index ffb3b38619..788e55bf31 100644 --- a/atom/browser/osr/osr_web_contents_view.h +++ b/atom/browser/osr/osr_web_contents_view.h @@ -69,6 +69,11 @@ class OffScreenWebContentsView : public content::WebContentsView, content::RenderWidgetHostImpl* source_rwh) override; void UpdateDragCursor(blink::WebDragOperation operation) override; + void SetPainting(bool painting); + bool IsPainting() const; + void SetFrameRate(int frame_rate); + int GetFrameRate() const; + private: #if defined(OS_MACOSX) void PlatformCreate(); @@ -78,6 +83,8 @@ class OffScreenWebContentsView : public content::WebContentsView, OffScreenRenderWidgetHostView* GetView() const; const bool transparent_; + bool painting_; + int frame_rate_; OnPaintCallback callback_; // Weak refs. From df3d94b20d3d5bbc5e852fb68847699e75e25d60 Mon Sep 17 00:00:00 2001 From: Heilig Benedek Date: Fri, 26 Jan 2018 10:30:20 +0100 Subject: [PATCH 7/7] Remove web_contents_impl() helper to clarify code and remove unnecessary guard --- atom/browser/api/atom_api_web_contents.cc | 37 ++++++----------------- atom/browser/api/atom_api_web_contents.h | 5 --- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 2b67c8274f..c1881db488 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1652,12 +1652,8 @@ void WebContents::StartPainting() { return; #if defined(ENABLE_OSR) - const auto* wc_impl = web_contents_impl(); - if (!wc_impl) - return; - - auto* osr_wcv = static_cast( - wc_impl->GetView()); + const auto* wc_impl = static_cast(web_contents()); + auto* osr_wcv = static_cast(wc_impl->GetView()); if (osr_wcv) osr_wcv->SetPainting(true); #endif @@ -1668,12 +1664,8 @@ void WebContents::StopPainting() { return; #if defined(ENABLE_OSR) - const auto* wc_impl = web_contents_impl(); - if (!wc_impl) - return; - - auto* osr_wcv = static_cast( - wc_impl->GetView()); + const auto* wc_impl = static_cast(web_contents()); + auto* osr_wcv = static_cast(wc_impl->GetView()); if (osr_wcv) osr_wcv->SetPainting(false); #endif @@ -1684,12 +1676,9 @@ bool WebContents::IsPainting() const { return false; #if defined(ENABLE_OSR) - const auto* wc_impl = web_contents_impl(); - if (!wc_impl) - return false; + const auto* wc_impl = static_cast(web_contents()); + auto* osr_wcv = static_cast(wc_impl->GetView()); - const auto* osr_wcv = static_cast( - wc_impl->GetView()); return osr_wcv && osr_wcv->IsPainting(); #else return false; @@ -1701,12 +1690,9 @@ void WebContents::SetFrameRate(int frame_rate) { return; #if defined(ENABLE_OSR) - const auto* wc_impl = web_contents_impl(); - if (!wc_impl) - return; + const auto* wc_impl = static_cast(web_contents()); + auto* osr_wcv = static_cast(wc_impl->GetView()); - auto* osr_wcv = static_cast( - wc_impl->GetView()); if (osr_wcv) osr_wcv->SetFrameRate(frame_rate); #endif @@ -1717,12 +1703,9 @@ int WebContents::GetFrameRate() const { return 0; #if defined(ENABLE_OSR) - const auto* wc_impl = web_contents_impl(); - if (!wc_impl) - return 0; + const auto* wc_impl = static_cast(web_contents()); + auto* osr_wcv = static_cast(wc_impl->GetView()); - const auto* osr_wcv = static_cast( - wc_impl->GetView()); return osr_wcv ? osr_wcv->GetFrameRate() : 0; #else return 0; diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index c27d1f7789..16f2321055 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -13,7 +13,6 @@ #include "atom/browser/api/trackable_object.h" #include "atom/browser/common_web_contents_delegate.h" #include "atom/browser/ui/autofill_popup.h" -#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/cursors/webcursor.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/web_contents.h" @@ -374,10 +373,6 @@ class WebContents : public mate::TrackableObject, return ++request_id_; } - content::WebContentsImpl* web_contents_impl() const { - return static_cast(web_contents()); - } - // Called when we receive a CursorChange message from chromium. void OnCursorChange(const content::WebCursor& cursor);