| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_RENDERER_HOST_BROWSER_COMPOSITOR_VIEW_MAC_H_ |
| #define CONTENT_BROWSER_RENDERER_HOST_BROWSER_COMPOSITOR_VIEW_MAC_H_ |
| |
| #include <memory> |
| |
| #include "base/macros.h" |
| #include "components/viz/common/frame_sinks/begin_frame_source.h" |
| #include "content/browser/renderer_host/delegated_frame_host.h" |
| #include "ui/compositor/compositor.h" |
| #include "ui/compositor/compositor_observer.h" |
| |
| namespace ui { |
| class AcceleratedWidgetMac; |
| class AcceleratedWidgetMacNSView; |
| } |
| |
| namespace content { |
| |
| class RecyclableCompositorMac; |
| |
| class BrowserCompositorMacClient { |
| public: |
| virtual NSView* BrowserCompositorMacGetNSView() const = 0; |
| virtual SkColor BrowserCompositorMacGetGutterColor(SkColor color) const = 0; |
| virtual void BrowserCompositorMacOnBeginFrame() = 0; |
| }; |
| |
| // This class owns a DelegatedFrameHost, and will dynamically attach and |
| // detach it from a ui::Compositor as needed. The ui::Compositor will be |
| // detached from the DelegatedFrameHost when the following conditions are |
| // all met: |
| // - There are no outstanding copy requests |
| // - The RenderWidgetHostImpl providing frames to the DelegatedFrameHost |
| // is visible. |
| // - The RenderWidgetHostViewMac that is used to display these frames is |
| // attached to the NSView hierarchy of an NSWindow. |
| class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient { |
| public: |
| BrowserCompositorMac( |
| ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view, |
| BrowserCompositorMacClient* client, |
| bool render_widget_host_is_hidden, |
| bool ns_view_attached_to_window, |
| const viz::FrameSinkId& frame_sink_id); |
| ~BrowserCompositorMac() override; |
| |
| // These will not return nullptr until Destroy is called. |
| DelegatedFrameHost* GetDelegatedFrameHost(); |
| |
| // Ensure that the currect compositor frame be cleared (even if it is |
| // potentially visible). |
| void ClearCompositorFrame(); |
| |
| // This may return nullptr, if this has detached itself from its |
| // ui::Compositor. |
| ui::AcceleratedWidgetMac* GetAcceleratedWidgetMac(); |
| |
| void DidCreateNewRendererCompositorFrameSink( |
| viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink); |
| void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id, |
| cc::CompositorFrame frame); |
| void OnDidNotProduceFrame(const viz::BeginFrameAck& ack); |
| void SetHasTransparentBackground(bool transparent); |
| void SetDisplayColorSpace(const gfx::ColorSpace& color_space); |
| void UpdateVSyncParameters(const base::TimeTicks& timebase, |
| const base::TimeDelta& interval); |
| void SetNeedsBeginFrames(bool needs_begin_frames); |
| |
| // This is used to ensure that the ui::Compositor be attached to the |
| // DelegatedFrameHost while the RWHImpl is visible. |
| // Note: This should be called before the RWHImpl is made visible and after |
| // it has been hidden, in order to ensure that thumbnailer notifications to |
| // initiate copies occur before the ui::Compositor be detached. |
| void SetRenderWidgetHostIsHidden(bool hidden); |
| |
| // This is used to ensure that the ui::Compositor be attached to this |
| // NSView while its contents may be visible on-screen, even if the RWHImpl is |
| // hidden (e.g, because it is occluded by another window). |
| void SetNSViewAttachedToWindow(bool attached); |
| |
| // These functions will track the number of outstanding copy requests, and |
| // will not allow the ui::Compositor to be detached until all outstanding |
| // copies have returned. |
| void CopyFromCompositingSurface(const gfx::Rect& src_subrect, |
| const gfx::Size& dst_size, |
| const ReadbackRequestCallback& callback, |
| SkColorType preferred_color_type); |
| void CopyFromCompositingSurfaceToVideoFrame( |
| const gfx::Rect& src_subrect, |
| scoped_refptr<media::VideoFrame> target, |
| const base::Callback<void(const gfx::Rect&, bool)>& callback); |
| |
| // Indicate that the recyclable compositor should be destroyed, and no future |
| // compositors should be recycled. |
| static void DisableRecyclingForShutdown(); |
| |
| // DelegatedFrameHostClient implementation. |
| ui::Layer* DelegatedFrameHostGetLayer() const override; |
| bool DelegatedFrameHostIsVisible() const override; |
| SkColor DelegatedFrameHostGetGutterColor(SkColor color) const override; |
| gfx::Size DelegatedFrameHostDesiredSizeInDIP() const override; |
| bool DelegatedFrameCanCreateResizeLock() const override; |
| std::unique_ptr<CompositorResizeLock> DelegatedFrameHostCreateResizeLock() |
| override; |
| void OnBeginFrame() override; |
| bool IsAutoResizeEnabled() const override; |
| |
| // Returns nullptr if no compositor is attached. |
| ui::Compositor* CompositorForTesting() const; |
| |
| private: |
| // The state of |delegated_frame_host_| and |recyclable_compositor_| to |
| // manage being visible, hidden, or occluded. |
| enum State { |
| // Effects: |
| // - |recyclable_compositor_| exists and is attached to |
| // |delegated_frame_host_|. |
| // Happens when: |
| // - |render_widet_host_| is in the visible state, or there are |
| // outstanding copy requests. |
| HasAttachedCompositor, |
| // Effects: |
| // - |recyclable_compositor_| exists, but |delegated_frame_host_| is |
| // hidden and detached from it. |
| // Happens when: |
| // - The |render_widget_host_| is hidden, but |cocoa_view_| is still in the |
| // NSWindow hierarchy (e.g, when the window is occluded or offscreen). |
| // - Note: In this state, |recyclable_compositor_| and its CALayers are kept |
| // around so that we will have content to show when we are un-occluded. If |
| // we had a way to keep the CALayers attached to the NSView while |
| // detaching the ui::Compositor, then there would be no need for this |
| HasDetachedCompositor, |
| // Effects: |
| // - |recyclable_compositor_| has been recycled and |delegated_frame_host_| |
| // is hidden and detached from it. |
| // Happens when: |
| // - The |render_widget_host_| hidden or gone, and |cocoa_view_| is not |
| // attached to an NSWindow. |
| // - This happens for backgrounded tabs. |
| HasNoCompositor, |
| }; |
| State state_ = HasNoCompositor; |
| void UpdateState(); |
| void TransitionToState(State new_state); |
| |
| static void CopyCompleted( |
| base::WeakPtr<BrowserCompositorMac> browser_compositor, |
| const ReadbackRequestCallback& callback, |
| const SkBitmap& bitmap, |
| ReadbackResponse response); |
| static void CopyToVideoFrameCompleted( |
| base::WeakPtr<BrowserCompositorMac> browser_compositor, |
| const base::Callback<void(const gfx::Rect&, bool)>& callback, |
| const gfx::Rect& rect, |
| bool result); |
| uint64_t outstanding_copy_count_ = 0; |
| |
| bool render_widget_host_is_hidden_ = true; |
| bool ns_view_attached_to_window_ = false; |
| |
| BrowserCompositorMacClient* client_ = nullptr; |
| ui::AcceleratedWidgetMacNSView* accelerated_widget_mac_ns_view_ = nullptr; |
| std::unique_ptr<RecyclableCompositorMac> recyclable_compositor_; |
| |
| std::unique_ptr<DelegatedFrameHost> delegated_frame_host_; |
| std::unique_ptr<ui::Layer> root_layer_; |
| |
| bool has_transparent_background_ = false; |
| viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = |
| nullptr; |
| |
| base::WeakPtrFactory<BrowserCompositorMac> weak_factory_; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_RENDERER_HOST_BROWSER_COMPOSITOR_VIEW_MAC_H_ |