1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_COMPOSITOR_DELEGATED_FRAME_HOST_H_
6#define CONTENT_BROWSER_COMPOSITOR_DELEGATED_FRAME_HOST_H_
7
8#include "cc/layers/delegated_frame_provider.h"
9#include "cc/layers/delegated_frame_resource_collection.h"
10#include "cc/output/copy_output_result.h"
11#include "cc/surfaces/surface_factory_client.h"
12#include "content/browser/compositor/image_transport_factory.h"
13#include "content/browser/compositor/owned_mailbox.h"
14#include "content/browser/renderer_host/delegated_frame_evictor.h"
15#include "content/browser/renderer_host/dip_util.h"
16#include "content/browser/renderer_host/render_widget_host_impl.h"
17#include "content/browser/renderer_host/render_widget_host_view_base.h"
18#include "content/public/browser/render_process_host.h"
19#include "ui/compositor/compositor.h"
20#include "ui/compositor/compositor_observer.h"
21#include "ui/compositor/compositor_vsync_manager.h"
22#include "ui/compositor/layer.h"
23#include "ui/compositor/layer_owner_delegate.h"
24#include "ui/gfx/rect_conversions.h"
25
26namespace cc {
27class SurfaceFactory;
28}
29
30namespace media {
31class VideoFrame;
32}
33
34namespace content {
35
36class DelegatedFrameHost;
37class ReadbackYUVInterface;
38class RenderWidgetHostViewFrameSubscriber;
39class RenderWidgetHostImpl;
40class ResizeLock;
41
42// The DelegatedFrameHostClient is the interface from the DelegatedFrameHost,
43// which manages delegated frames, and the ui::Compositor being used to
44// display them.
45class CONTENT_EXPORT DelegatedFrameHostClient {
46 public:
47  virtual ui::Compositor* GetCompositor() const = 0;
48  virtual ui::Layer* GetLayer() = 0;
49  virtual RenderWidgetHostImpl* GetHost() = 0;
50  virtual bool IsVisible() = 0;
51  virtual scoped_ptr<ResizeLock> CreateResizeLock(
52      bool defer_compositor_lock) = 0;
53  virtual gfx::Size DesiredFrameSize() = 0;
54
55  // TODO(ccameron): It is likely that at least one of these two functions is
56  // redundant. Find which one, and delete it.
57  virtual float CurrentDeviceScaleFactor() = 0;
58  virtual gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) = 0;
59
60  // These are to be overridden for testing only.
61  // TODO(ccameron): This is convoluted. Make the tests that need to override
62  // these functions test DelegatedFrameHost directly (rather than do it
63  // through RenderWidgetHostViewAura).
64  virtual DelegatedFrameHost* GetDelegatedFrameHost() const = 0;
65  virtual bool ShouldCreateResizeLock();
66  virtual void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request);
67};
68
69// The DelegatedFrameHost is used to host all of the RenderWidgetHostView state
70// and functionality that is associated with delegated frames being sent from
71// the RenderWidget. The DelegatedFrameHost will push these changes through to
72// the ui::Compositor associated with its DelegatedFrameHostClient.
73class CONTENT_EXPORT DelegatedFrameHost
74    : public ui::CompositorObserver,
75      public ui::CompositorVSyncManager::Observer,
76      public ui::LayerOwnerDelegate,
77      public ImageTransportFactoryObserver,
78      public DelegatedFrameEvictorClient,
79      public cc::DelegatedFrameResourceCollectionClient,
80      public cc::SurfaceFactoryClient,
81      public base::SupportsWeakPtr<DelegatedFrameHost> {
82 public:
83  DelegatedFrameHost(DelegatedFrameHostClient* client);
84  virtual ~DelegatedFrameHost();
85
86  bool CanCopyToBitmap() const;
87
88  // Public interface exposed to RenderWidgetHostView.
89  void SwapDelegatedFrame(
90      uint32 output_surface_id,
91      scoped_ptr<cc::DelegatedFrameData> frame_data,
92      float frame_device_scale_factor,
93      const std::vector<ui::LatencyInfo>& latency_info);
94  void WasHidden();
95  void WasShown(const ui::LatencyInfo& latency_info);
96  void WasResized();
97  bool HasSavedFrame();
98  gfx::Size GetRequestedRendererSize() const;
99  void AddedToWindow();
100  void RemovingFromWindow();
101  void CopyFromCompositingSurface(const gfx::Rect& src_subrect,
102                                  const gfx::Size& output_size,
103                                  CopyFromCompositingSurfaceCallback& callback,
104                                  const SkColorType color_type);
105  void CopyFromCompositingSurfaceToVideoFrame(
106      const gfx::Rect& src_subrect,
107      const scoped_refptr<media::VideoFrame>& target,
108      const base::Callback<void(bool)>& callback);
109  bool CanCopyToVideoFrame() const;
110  bool CanSubscribeFrame() const;
111  void BeginFrameSubscription(
112      scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber);
113  void EndFrameSubscription();
114  bool HasFrameSubscriber() const { return frame_subscriber_; }
115
116  // Exposed for tests.
117  cc::DelegatedFrameProvider* FrameProviderForTesting() const {
118    return frame_provider_.get();
119  }
120  void OnCompositingDidCommitForTesting(ui::Compositor* compositor) {
121    OnCompositingDidCommit(compositor);
122  }
123  bool ShouldCreateResizeLockForTesting() { return ShouldCreateResizeLock(); }
124  bool ReleasedFrontLockActiveForTesting() const {
125    return !!released_front_lock_.get();
126  }
127
128 private:
129  friend class DelegatedFrameHostClient;
130  FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
131                           SkippedDelegatedFrames);
132  FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
133                           DiscardDelegatedFramesWithLocking);
134  FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraCopyRequestTest,
135                           DestroyedAfterCopyRequest);
136
137  RenderWidgetHostViewFrameSubscriber* frame_subscriber() const {
138    return frame_subscriber_.get();
139  }
140  bool ShouldCreateResizeLock();
141  void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request);
142
143  void LockResources();
144  void UnlockResources();
145
146  // Overridden from ui::CompositorObserver:
147  virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE;
148  virtual void OnCompositingStarted(ui::Compositor* compositor,
149                                    base::TimeTicks start_time) OVERRIDE;
150  virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE;
151  virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE;
152  virtual void OnCompositingLockStateChanged(
153      ui::Compositor* compositor) OVERRIDE;
154
155  // Overridden from ui::CompositorVSyncManager::Observer:
156  virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
157                                       base::TimeDelta interval) OVERRIDE;
158
159  // Overridden from ui::LayerOwnerObserver:
160  virtual void OnLayerRecreated(ui::Layer* old_layer,
161                                ui::Layer* new_layer) OVERRIDE;
162
163  // Overridden from ImageTransportFactoryObserver:
164  virtual void OnLostResources() OVERRIDE;
165
166  bool ShouldSkipFrame(gfx::Size size_in_dip) const;
167
168  // Lazily grab a resize lock if the aura window size doesn't match the current
169  // frame size, to give time to the renderer.
170  void MaybeCreateResizeLock();
171
172  // Checks if the resize lock can be released because we received an new frame.
173  void CheckResizeLock();
174
175  // Run all on compositing commit callbacks.
176  void RunOnCommitCallbacks();
177
178  // Add on compositing commit callback.
179  void AddOnCommitCallbackAndDisableLocks(const base::Closure& callback);
180
181  // Called after async thumbnailer task completes.  Scales and crops the result
182  // of the copy.
183  static void CopyFromCompositingSurfaceHasResult(
184      const gfx::Size& dst_size_in_pixel,
185      const SkColorType color_type,
186      const base::Callback<void(bool, const SkBitmap&)>& callback,
187      scoped_ptr<cc::CopyOutputResult> result);
188  static void PrepareTextureCopyOutputResult(
189      const gfx::Size& dst_size_in_pixel,
190      const SkColorType color_type,
191      const base::Callback<void(bool, const SkBitmap&)>& callback,
192      scoped_ptr<cc::CopyOutputResult> result);
193  static void PrepareBitmapCopyOutputResult(
194      const gfx::Size& dst_size_in_pixel,
195      const SkColorType color_type,
196      const base::Callback<void(bool, const SkBitmap&)>& callback,
197      scoped_ptr<cc::CopyOutputResult> result);
198  static void CopyFromCompositingSurfaceHasResultForVideo(
199      base::WeakPtr<DelegatedFrameHost> rwhva,
200      scoped_refptr<OwnedMailbox> subscriber_texture,
201      scoped_refptr<media::VideoFrame> video_frame,
202      const base::Callback<void(bool)>& callback,
203      scoped_ptr<cc::CopyOutputResult> result);
204  static void CopyFromCompositingSurfaceFinishedForVideo(
205      base::WeakPtr<DelegatedFrameHost> rwhva,
206      const base::Callback<void(bool)>& callback,
207      scoped_refptr<OwnedMailbox> subscriber_texture,
208      scoped_ptr<cc::SingleReleaseCallback> release_callback,
209      bool result);
210  static void ReturnSubscriberTexture(
211      base::WeakPtr<DelegatedFrameHost> rwhva,
212      scoped_refptr<OwnedMailbox> subscriber_texture,
213      uint32 sync_point);
214
215  void SendDelegatedFrameAck(uint32 output_surface_id);
216  void SendReturnedDelegatedResources(uint32 output_surface_id);
217
218  // DelegatedFrameEvictorClient implementation.
219  virtual void EvictDelegatedFrame() OVERRIDE;
220
221  // cc::DelegatedFrameProviderClient implementation.
222  virtual void UnusedResourcesAreAvailable() OVERRIDE;
223
224  // cc::SurfaceFactoryClient implementation.
225  virtual void ReturnResources(
226      const cc::ReturnedResourceArray& resources) OVERRIDE;
227
228  void DidReceiveFrameFromRenderer(const gfx::Rect& damage_rect);
229
230  DelegatedFrameHostClient* client_;
231
232  // True if this renders into a Surface, false if it renders into a delegated
233  // layer.
234  bool use_surfaces_;
235
236  std::vector<base::Closure> on_compositing_did_commit_callbacks_;
237
238  // The vsync manager we are observing for changes, if any.
239  scoped_refptr<ui::CompositorVSyncManager> vsync_manager_;
240
241  // The current VSync timebase and interval. These are zero until the first
242  // call to OnUpdateVSyncParameters().
243  base::TimeTicks vsync_timebase_;
244  base::TimeDelta vsync_interval_;
245
246  // With delegated renderer, this is the last output surface, used to
247  // disambiguate resources with the same id coming from different output
248  // surfaces.
249  uint32 last_output_surface_id_;
250
251  // The number of delegated frame acks that are pending, to delay resource
252  // returns until the acks are sent.
253  int pending_delegated_ack_count_;
254
255  // True after a delegated frame has been skipped, until a frame is not
256  // skipped.
257  bool skipped_frames_;
258  std::vector<ui::LatencyInfo> skipped_latency_info_list_;
259
260  // Holds delegated resources that have been given to a DelegatedFrameProvider,
261  // and gives back resources when they are no longer in use for return to the
262  // renderer.
263  scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
264
265  // Provides delegated frame updates to the cc::DelegatedRendererLayer.
266  scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
267
268  // State for rendering into a Surface.
269  scoped_ptr<cc::SurfaceIdAllocator> id_allocator_;
270  scoped_ptr<cc::SurfaceFactory> surface_factory_;
271  cc::SurfaceId surface_id_;
272  gfx::Size current_surface_size_;
273  cc::ReturnedResourceArray surface_returned_resources_;
274
275  // This lock is the one waiting for a frame of the right size to come back
276  // from the renderer/GPU process. It is set from the moment the aura window
277  // got resized, to the moment we committed the renderer frame of the same
278  // size. It keeps track of the size we expect from the renderer, and locks the
279  // compositor, as well as the UI for a short time to give a chance to the
280  // renderer of producing a frame of the right size.
281  scoped_ptr<ResizeLock> resize_lock_;
282
283  // Keeps track of the current frame size.
284  gfx::Size current_frame_size_in_dip_;
285
286  // This lock is for waiting for a front surface to become available to draw.
287  scoped_refptr<ui::CompositorLock> released_front_lock_;
288
289  enum CanLockCompositorState {
290    YES_CAN_LOCK,
291    // We locked, so at some point we'll need to kick a frame.
292    YES_DID_LOCK,
293    // No. A lock timed out, we need to kick a new frame before locking again.
294    NO_PENDING_RENDERER_FRAME,
295    // No. We've got a frame, but it hasn't been committed.
296    NO_PENDING_COMMIT,
297  };
298  CanLockCompositorState can_lock_compositor_;
299
300  base::TimeTicks last_draw_ended_;
301
302  // Subscriber that listens to frame presentation events.
303  scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
304  std::vector<scoped_refptr<OwnedMailbox> > idle_frame_subscriber_textures_;
305
306  // YUV readback pipeline.
307  scoped_ptr<content::ReadbackYUVInterface>
308      yuv_readback_pipeline_;
309
310  scoped_ptr<DelegatedFrameEvictor> delegated_frame_evictor_;
311};
312
313}  // namespace content
314
315#endif  // CONTENT_BROWSER_COMPOSITOR_DELEGATED_FRAME_HOST_H_
316