From ca4a6e46925c4107023ca65bbe27c9cab4b12c3f Mon Sep 17 00:00:00 2001 From: Gellert Hegyi <93.morph@gmail.com> Date: Sat, 8 Jul 2017 21:25:15 +0200 Subject: [PATCH] fixes offscreen rendering on macos --- .../osr/osr_render_widget_host_view.cc | 72 +++++++++++++------ .../browser/osr/osr_render_widget_host_view.h | 15 ++++ .../osr/osr_render_widget_host_view_mac.mm | 9 --- 3 files changed, 67 insertions(+), 29 deletions(-) diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index eeea5b20ed17..39ed9f434ab1 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -339,6 +339,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( popup_position_(gfx::Rect()), hold_resize_(false), pending_resize_(false), + renderer_compositor_frame_sink_(nullptr), + background_color_(SkColor()), weak_ptr_factory_(this) { DCHECK(render_widget_host_); bool is_guest_view_hack = parent_host_view_ != nullptr; @@ -557,14 +559,18 @@ gfx::Rect OffScreenRenderWidgetHostView::GetViewBounds() const { } void OffScreenRenderWidgetHostView::SetBackgroundColor(SkColor color) { - if (transparent_) - color = SkColorSetARGB(SK_AlphaTRANSPARENT, 0, 0, 0); + // The renderer will feed its color back to us with the first CompositorFrame. + // We short-cut here to show a sensible color before that happens. + UpdateBackgroundColorFromRenderer(color); - content::RenderWidgetHostViewBase::SetBackgroundColor(color); + if (render_widget_host_) { + render_widget_host_->SetBackgroundOpaque(SkColorGetA(color) == + SK_AlphaOPAQUE); + } +} - const bool opaque = !transparent_ && GetBackgroundOpaque(); - if (render_widget_host_) - render_widget_host_->SetBackgroundOpaque(opaque); +SkColor OffScreenRenderWidgetHostView::background_color() const { + return background_color_; } gfx::Size OffScreenRenderWidgetHostView::GetVisibleViewportSize() const { @@ -581,11 +587,20 @@ bool OffScreenRenderWidgetHostView::LockMouse() { void OffScreenRenderWidgetHostView::UnlockMouse() { } -void OffScreenRenderWidgetHostView::OnSwapCompositorFrame( - uint32_t output_surface_id, - cc::CompositorFrame frame) { +void OffScreenRenderWidgetHostView::DidCreateNewRendererCompositorFrameSink( + cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) { + renderer_compositor_frame_sink_ = renderer_compositor_frame_sink; + if (GetDelegatedFrameHost()) { + GetDelegatedFrameHost()->DidCreateNewRendererCompositorFrameSink( + renderer_compositor_frame_sink_); + } +} + +void OffScreenRenderWidgetHostView::SubmitCompositorFrame( + const cc::LocalSurfaceId& local_surface_id, + cc::CompositorFrame frame) { TRACE_EVENT0("electron", - "OffScreenRenderWidgetHostView::OnSwapCompositorFrame"); + "OffScreenRenderWidgetHostView::SubmitCompositorFrame"); if (frame.metadata.root_scroll_offset != last_scroll_offset_) { last_scroll_offset_ = frame.metadata.root_scroll_offset; @@ -599,11 +614,11 @@ void OffScreenRenderWidgetHostView::OnSwapCompositorFrame( // The compositor will draw directly to the SoftwareOutputDevice which // then calls OnPaint. - // We would normally call BrowserCompositorMac::SwapCompositorFrame on + // We would normally call BrowserCompositorMac::SubmitCompositorFrame on // macOS, however it contains compositor resize logic that we don't want. - // Consequently we instead call the SwapDelegatedFrame method directly. - GetDelegatedFrameHost()->SwapDelegatedFrame(output_surface_id, - std::move(frame)); + // Consequently we instead call the SubmitCompositorFrame method directly. + GetDelegatedFrameHost()->SubmitCompositorFrame(local_surface_id, + std::move(frame)); } else { if (!copy_frame_generator_.get()) { copy_frame_generator_.reset( @@ -618,11 +633,11 @@ void OffScreenRenderWidgetHostView::OnSwapCompositorFrame( gfx::ToEnclosingRect(gfx::RectF(root_pass->damage_rect)); damage_rect.Intersect(gfx::Rect(frame_size)); - // We would normally call BrowserCompositorMac::SwapCompositorFrame on + // We would normally call BrowserCompositorMac::SubmitCompositorFrame on // macOS, however it contains compositor resize logic that we don't want. - // Consequently we instead call the SwapDelegatedFrame method directly. - GetDelegatedFrameHost()->SwapDelegatedFrame(output_surface_id, - std::move(frame)); + // Consequently we instead call the SubmitCompositorFrame method directly. + GetDelegatedFrameHost()->SubmitCompositorFrame(local_surface_id, + std::move(frame)); // Request a copy of the last compositor frame which will eventually call // OnPaint asynchronously. @@ -688,8 +703,14 @@ void OffScreenRenderWidgetHostView::Destroy() { popup_bitmap_.reset(); if (child_host_view_) child_host_view_->CancelWidget(); - for (auto guest_host_view : guest_host_views_) - guest_host_view->CancelWidget(); + if (!guest_host_views_.empty()) { + // Guest RWHVs will be destroyed when the associated RWHVGuest is + // destroyed. This parent RWHV may be destroyed first, so disassociate + // the guest RWHVs here without destroying them. + for (auto guest_host_view : guest_host_views_) + guest_host_view->parent_host_view_ = nullptr; + guest_host_views_.clear(); + } for (auto proxy_view : proxy_views_) proxy_view->RemoveObserver(); Hide(); @@ -1318,4 +1339,15 @@ cc::FrameSinkId OffScreenRenderWidgetHostView::AllocateFrameSinkId( render_widget_host_->GetRoutingID())); } +void OffScreenRenderWidgetHostView::UpdateBackgroundColorFromRenderer( + SkColor color) { + if (color == background_color()) + return; + background_color_ = color; + + bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE; + GetRootLayer()->SetFillsBoundsOpaquely(opaque); + GetRootLayer()->SetColor(color); +} + } // namespace atom diff --git a/atom/browser/osr/osr_render_widget_host_view.h b/atom/browser/osr/osr_render_widget_host_view.h index 24ede965d2ca..6a965ac6ce58 100644 --- a/atom/browser/osr/osr_render_widget_host_view.h +++ b/atom/browser/osr/osr_render_widget_host_view.h @@ -99,6 +99,7 @@ class OffScreenRenderWidgetHostView gfx::Size GetVisibleViewportSize() const override; void SetInsets(const gfx::Insets&) override; void SetBackgroundColor(SkColor color) override; + SkColor background_color() const override; bool LockMouse(void) override; void UnlockMouse(void) override; void SetNeedsBeginFrames(bool needs_begin_frames) override; @@ -113,6 +114,12 @@ class OffScreenRenderWidgetHostView #endif // defined(OS_MACOSX) // content::RenderWidgetHostViewBase: + void DidCreateNewRendererCompositorFrameSink( + cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink) + override; + void SubmitCompositorFrame(const cc::LocalSurfaceId& local_surface_id, + cc::CompositorFrame frame) override; + void ClearCompositorFrame(void) override; void InitAsPopup(content::RenderWidgetHostView *rwhv, const gfx::Rect& rect) override; @@ -269,6 +276,10 @@ class OffScreenRenderWidgetHostView cc::FrameSinkId AllocateFrameSinkId(bool is_guest_view_hack); + // Applies background color without notifying the RenderWidget about + // opaqueness changes. + void UpdateBackgroundColorFromRenderer(SkColor color); + // Weak ptrs. content::RenderWidgetHostImpl* render_widget_host_; @@ -326,6 +337,10 @@ class OffScreenRenderWidgetHostView std::string selected_text_; #endif + cc::mojom::MojoCompositorFrameSinkClient* renderer_compositor_frame_sink_; + + SkColor background_color_; + base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(OffScreenRenderWidgetHostView); diff --git a/atom/browser/osr/osr_render_widget_host_view_mac.mm b/atom/browser/osr/osr_render_widget_host_view_mac.mm index 8e13c2c577dc..034d8a1f519b 100644 --- a/atom/browser/osr/osr_render_widget_host_view_mac.mm +++ b/atom/browser/osr/osr_render_widget_host_view_mac.mm @@ -38,15 +38,6 @@ class MacHelper : return color; } - void BrowserCompositorMacSendReclaimCompositorResources( - int output_surface_id, - bool is_swap_ack, - const cc::ReturnedResourceArray& resources) override { - view_->render_widget_host()->Send(new ViewMsg_ReclaimCompositorResources( - view_->render_widget_host()->GetRoutingID(), output_surface_id, - is_swap_ack, resources)); - } - void BrowserCompositorMacSendBeginFrame( const cc::BeginFrameArgs& args) override { view_->render_widget_host()->Send(