diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 5b0a66f729bc..770b6b347ee4 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -403,11 +403,11 @@ void WebContents::OnCreateWindow(const GURL& target_url, } void WebContents::RenderViewReady() { - if (IsOffScreen()) { - const auto rwhv = web_contents()->GetRenderWidgetHostView(); - auto osr_rwhv = static_cast(rwhv); - osr_rwhv->SetPaintCallback(&paint_callback_); - } + // if (IsOffScreen()) { + // const auto rwhv = web_contents()->GetRenderWidgetHostView(); + // auto osr_rwhv = static_cast(rwhv); + // osr_rwhv->SetPaintCallback(&paint_callback_); + // } } content::WebContents* WebContents::OpenURLFromTab( @@ -444,6 +444,13 @@ void WebContents::MoveContents(content::WebContents* source, void WebContents::CloseContents(content::WebContents* source) { Emit("close"); + + if (IsOffScreen()) { + const auto osr_rwhv = static_cast( + web_contents()->GetRenderWidgetHostView()); + osr_rwhv->SetPainting(false); + } + if ((type_ == BROWSER_WINDOW || type_ == OFF_SCREEN) && owner_window()) owner_window()->CloseContents(source); } @@ -620,8 +627,15 @@ void WebContents::DidChangeThemeColor(SkColor theme_color) { void WebContents::DocumentLoadedInFrame( content::RenderFrameHost* render_frame_host) { - if (!render_frame_host->GetParent()) + if (!render_frame_host->GetParent()) { + if (IsOffScreen()) { + const auto rwhv = web_contents()->GetRenderWidgetHostView(); + auto osr_rwhv = static_cast(rwhv); + osr_rwhv->SetPaintCallback(&paint_callback_); + } + Emit("dom-ready"); + } } void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host, @@ -1400,6 +1414,49 @@ void WebContents::OnPaint( buffer.ToLocalChecked()); } +void WebContents::StartPainting() { + if (IsOffScreen()) { + const auto osr_rwhv = static_cast( + web_contents()->GetRenderWidgetHostView()); + osr_rwhv->SetPainting(true); + } +} + +void WebContents::StopPainting() { + if (IsOffScreen()) { + const auto osr_rwhv = static_cast( + web_contents()->GetRenderWidgetHostView()); + osr_rwhv->SetPainting(false); + } +} + +bool WebContents::IsPainting() const { + if (IsOffScreen()) { + const auto osr_rwhv = static_cast( + web_contents()->GetRenderWidgetHostView()); + return osr_rwhv->IsPainting(); + } + + return false; +} + +void WebContents::SetFrameRate(int frame_rate) { + if (IsOffScreen()) { + const auto osr_rwhv = static_cast( + web_contents()->GetRenderWidgetHostView()); + osr_rwhv->SetFrameRate(frame_rate); + } +} + +int WebContents::GetFrameRate() const { + if (IsOffScreen()) { + const auto osr_rwhv = static_cast( + web_contents()->GetRenderWidgetHostView()); + return osr_rwhv->GetFrameRate(); + } + return 0; +} + // static void WebContents::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { @@ -1473,6 +1530,12 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, &WebContents::ShowDefinitionForSelection) .SetMethod("capturePage", &WebContents::CapturePage) .SetMethod("isFocused", &WebContents::IsFocused) + .SetMethod("isOffScreen", &WebContents::IsOffScreen) + .SetMethod("startPainting", &WebContents::StartPainting) + .SetMethod("stopPainting", &WebContents::StopPainting) + .SetMethod("isPainting", &WebContents::IsPainting) + .SetMethod("setFrameRate", &WebContents::SetFrameRate) + .SetMethod("getFrameRate", &WebContents::GetFrameRate) .SetProperty("id", &WebContents::ID) .SetProperty("session", &WebContents::Session) .SetProperty("hostWebContents", &WebContents::HostWebContents) diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index bbe429cbf181..5294277d9651 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -145,7 +145,6 @@ class WebContents : public mate::TrackableObject, // Subscribe to the frame updates. void BeginFrameSubscription(mate::Arguments* args); void EndFrameSubscription(); - void OnPaint(v8::Isolate*, const gfx::Rect&, int, int, void*); // Dragging native items. void StartDrag(const mate::Dictionary& item, mate::Arguments* args); @@ -158,7 +157,14 @@ class WebContents : public mate::TrackableObject, void SetSize(const SetSizeParams& params); bool IsGuest() const; + // Methods for offscreen rendering + void OnPaint(v8::Isolate*, const gfx::Rect&, int, int, void*); bool IsOffScreen() const; + void StartPainting(); + void StopPainting(); + bool IsPainting() const; + void SetFrameRate(int); + int GetFrameRate() const; // Callback triggered on permission response. void OnEnterFullscreenModeForTab(content::WebContents* source, diff --git a/atom/browser/osr_render_widget_host_view.cc b/atom/browser/osr_render_widget_host_view.cc index f5ade21b55aa..c73ee8ff4d5f 100644 --- a/atom/browser/osr_render_widget_host_view.cc +++ b/atom/browser/osr_render_widget_host_view.cc @@ -61,9 +61,9 @@ class AtomCopyFrameGenerator { if (!damage_rect.IsEmpty()) pending_damage_rect_.Union(damage_rect); - if (frame_in_progress_) { + if (frame_in_progress_) return; - } + frame_in_progress_ = true; const int64_t frame_rate_delta = @@ -340,10 +340,13 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( content::RenderWidgetHost* host, NativeWindow* native_window): render_widget_host_(content::RenderWidgetHostImpl::From(host)), native_window_(native_window), software_output_device_(NULL), + callback_(nullptr), + frame_rate_(60), frame_rate_threshold_ms_(0), scale_factor_(kDefaultScaleFactor), is_showing_(!render_widget_host_->is_hidden()), size_(native_window->GetSize()), + painting_(true), delegated_frame_host_(new content::DelegatedFrameHost(this)), compositor_widget_(gfx::kNullAcceleratedWidget), weak_ptr_factory_(this) { @@ -388,7 +391,7 @@ OffScreenRenderWidgetHostView::~OffScreenRenderWidgetHostView() { void OffScreenRenderWidgetHostView::ResizeRootLayer() { - SetFrameRate(); + SetupFrameRate(false); const float orgScaleFactor = scale_factor_; const bool scaleFactorDidChange = (orgScaleFactor != scale_factor_); @@ -430,7 +433,7 @@ void OffScreenRenderWidgetHostView::SendBeginFrame(base::TimeTicks frame_time, void OffScreenRenderWidgetHostView::SetPaintCallback( const OnPaintCallback* callback) { - callback_.reset(callback); + callback_ = callback; } bool OffScreenRenderWidgetHostView::OnMessageReceived( @@ -550,6 +553,9 @@ void OffScreenRenderWidgetHostView::OnSwapCompositorFrame( TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnSwapCompositorFrame"); + if (!painting_) + return; + if (frame->metadata.root_scroll_offset != last_scroll_offset_) { last_scroll_offset_ = frame->metadata.root_scroll_offset; } @@ -762,21 +768,20 @@ std::unique_ptr } void OffScreenRenderWidgetHostView::OnSetNeedsBeginFrames(bool enabled) { - SetFrameRate(); + SetupFrameRate(false); - begin_frame_timer_->SetActive(enabled); + begin_frame_timer_->SetActive(painting_ && enabled); if (software_output_device_) { software_output_device_->SetActive(enabled); } } -void OffScreenRenderWidgetHostView::SetFrameRate() { - if (frame_rate_threshold_ms_ != 0) +void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) { + if (!force && frame_rate_threshold_ms_ != 0) return; - const int frame_rate = 60; - frame_rate_threshold_ms_ = 1000 / frame_rate; + frame_rate_threshold_ms_ = 1000 / frame_rate_; compositor_->vsync_manager()->SetAuthoritativeVSyncInterval( base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms_)); @@ -811,9 +816,36 @@ void OffScreenRenderWidgetHostView::OnPaint( void* bitmap_pixels) { TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnPaint"); - if (callback_) { + if (callback_ != nullptr) { callback_->Run(damage_rect, bitmap_width, bitmap_height, bitmap_pixels); } } +void OffScreenRenderWidgetHostView::SetPainting(bool painting) { + painting_ = painting; + + if (begin_frame_timer_.get()) { + begin_frame_timer_->SetActive(painting); + } +} + +bool OffScreenRenderWidgetHostView::IsPainting() const { + return painting_; +} + +void OffScreenRenderWidgetHostView::SetFrameRate(int frame_rate) { + if (frame_rate <= 0) + frame_rate = 1; + if (frame_rate > 60) + frame_rate = 60; + + frame_rate_ = frame_rate; + + SetupFrameRate(true); +} + +int OffScreenRenderWidgetHostView::GetFrameRate() const { + return frame_rate_; +} + } // namespace atom diff --git a/atom/browser/osr_render_widget_host_view.h b/atom/browser/osr_render_widget_host_view.h index 80b46c70d175..feb7ec4a6ca1 100644 --- a/atom/browser/osr_render_widget_host_view.h +++ b/atom/browser/osr_render_widget_host_view.h @@ -63,9 +63,6 @@ public: OffScreenRenderWidgetHostView(content::RenderWidgetHost*, NativeWindow*); ~OffScreenRenderWidgetHostView(); - void CreatePlatformWidget(); - void DestroyPlatformWidget(); - // content::RenderWidgetHostView bool OnMessageReceived(const IPC::Message&) override; void InitAsChild(gfx::NativeView) override; @@ -183,6 +180,9 @@ public: void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period); + void CreatePlatformWidget(); + void DestroyPlatformWidget(); + void SetPaintCallback(const atom::OnPaintCallback*); void OnPaint(const gfx::Rect& damage_rect, @@ -190,8 +190,13 @@ public: int bitmap_height, void* bitmap_pixels); + void SetPainting(bool); + bool IsPainting() const; + + void SetFrameRate(int); + int GetFrameRate() const; private: - void SetFrameRate(); + void SetupFrameRate(bool); void ResizeRootLayer(); content::RenderWidgetHostImpl* render_widget_host_; @@ -202,8 +207,9 @@ private: OffScreenOutputDevice* software_output_device_; - std::unique_ptr callback_; + const atom::OnPaintCallback* callback_; + int frame_rate_; int frame_rate_threshold_ms_; base::Time last_time_; @@ -212,6 +218,7 @@ private: bool is_showing_; gfx::Vector2dF last_scroll_offset_; gfx::Size size_; + bool painting_; std::unique_ptr delegated_frame_host_; std::unique_ptr compositor_;