1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file.
4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/compositor/delegated_frame_host.h"
6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/callback_helpers.h"
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/command_line.h"
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "cc/output/compositor_frame.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "cc/output/compositor_frame_ack.h"
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "cc/output/copy_output_request.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "cc/resources/single_release_callback.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "cc/resources/texture_mailbox.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "cc/surfaces/surface_factory.h"
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/compositor/resize_lock.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/gpu/compositor_util.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/common/gpu/client/gl_helper.h"
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/common/content_switches.h"
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "media/base/video_frame.h"
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "media/base/video_util.h"
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "skia/ext/image_operations.h"
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/skia/include/core/SkCanvas.h"
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/skia/include/core/SkPaint.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/skia/include/effects/SkLumaColorFilter.h"
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/frame_time.h"
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace content {
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// DelegatedFrameHostClient
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DelegatedFrameHostClient::ShouldCreateResizeLock() {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // On Windows and Linux, holding pointer moves will not help throttling
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // resizes.
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(piman): on Windows we need to block (nested message loop?) the
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // WM_SIZE event. On Linux we need to throttle at the WM level using
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // _NET_WM_SYNC_REQUEST.
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(ccameron): Mac browser window resizing is incompletely implemented.
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(OS_CHROMEOS)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return GetDelegatedFrameHost()->ShouldCreateResizeLock();
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHostClient::RequestCopyOfOutput(
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::CopyOutputRequest> request) {
490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  GetDelegatedFrameHost()->RequestCopyOfOutput(request.Pass());
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// DelegatedFrameHost
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
56010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : client_(client),
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      use_surfaces_(UseSurfacesEnabled()),
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      last_output_surface_id_(0),
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pending_delegated_ack_count_(0),
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      skipped_frames_(false),
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      can_lock_compositor_(YES_CAN_LOCK),
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      delegated_frame_evictor_(new DelegatedFrameEvictor(this)) {
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ImageTransportFactory::GetInstance()->AddObserver(this);
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) {
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegated_frame_evictor_->SetVisible(true);
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (surface_id_.is_null() && !frame_provider_.get() &&
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !released_front_lock_.get()) {
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ui::Compositor* compositor = client_->GetCompositor();
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (compositor)
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      released_front_lock_ = compositor->GetCompositorLock();
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (compositor) {
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    compositor->SetLatencyInfo(latency_info);
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool DelegatedFrameHost::HasSavedFrame() {
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return delegated_frame_evictor_->HasFrame();
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::WasHidden() {
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegated_frame_evictor_->SetVisible(false);
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  released_front_lock_ = NULL;
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::MaybeCreateResizeLock() {
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!client_->ShouldCreateResizeLock())
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(client_->GetCompositor());
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Listen to changes in the compositor lock state.
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!compositor->HasObserver(this))
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    compositor->AddObserver(this);
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool defer_compositor_lock =
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      can_lock_compositor_ == NO_PENDING_COMMIT;
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (can_lock_compositor_ == YES_CAN_LOCK)
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    can_lock_compositor_ = YES_DID_LOCK;
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  resize_lock_ = client_->CreateResizeLock(defer_compositor_lock);
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DelegatedFrameHost::ShouldCreateResizeLock() {
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (resize_lock_)
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
117e578b2d213c837aab9cea5407d30f5c84065cd0eMarcin Kosiba  if (host->auto_resize_enabled())
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Size desired_size = client_->DesiredFrameSize();
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (desired_size == current_frame_size_in_dip_ || desired_size.IsEmpty())
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!compositor)
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return true;
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::RequestCopyOfOutput(
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::CopyOutputRequest> request) {
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (use_surfaces_) {
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (surface_factory_ && !surface_id_.is_null())
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      surface_factory_->RequestCopyOfSurface(surface_id_, request.Pass());
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request->SendEmptyResult();
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    client_->GetLayer()->RequestCopyOfOutput(request.Pass());
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::CopyFromCompositingSurface(
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Rect& src_subrect,
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& output_size,
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CopyFromCompositingSurfaceCallback& callback,
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const SkColorType color_type) {
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Only ARGB888 and RGB565 supported as of now.
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool format_support = ((color_type == kAlpha_8_SkColorType) ||
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         (color_type == kRGB_565_SkColorType) ||
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         (color_type == kN32_SkColorType));
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(format_support);
153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!CanCopyToBitmap()) {
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(false, SkBitmap());
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<cc::CopyOutputRequest> request =
159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      cc::CopyOutputRequest::CreateRequest(base::Bind(
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &DelegatedFrameHost::CopyFromCompositingSurfaceHasResult,
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          output_size,
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          color_type,
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          callback));
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  request->set_area(src_subrect);
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_->RequestCopyOfOutput(request.Pass());
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame(
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const gfx::Rect& src_subrect,
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const scoped_refptr<media::VideoFrame>& target,
171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      const base::Callback<void(bool)>& callback) {
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!CanCopyToVideoFrame()) {
173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(false);
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Try get a texture to reuse.
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_refptr<OwnedMailbox> subscriber_texture;
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (frame_subscriber_) {
180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!idle_frame_subscriber_textures_.empty()) {
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      subscriber_texture = idle_frame_subscriber_textures_.back();
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      idle_frame_subscriber_textures_.pop_back();
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else if (GLHelper* helper =
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   ImageTransportFactory::GetInstance()->GetGLHelper()) {
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      subscriber_texture = new OwnedMailbox(helper);
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<cc::CopyOutputRequest> request =
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      cc::CopyOutputRequest::CreateRequest(base::Bind(
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          &DelegatedFrameHost::
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)               CopyFromCompositingSurfaceHasResultForVideo,
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          AsWeakPtr(),  // For caching the ReadbackYUVInterface on this class.
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          subscriber_texture,
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          target,
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          callback));
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  request->set_area(src_subrect);
198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (subscriber_texture.get()) {
199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    request->SetTextureMailbox(
200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        cc::TextureMailbox(subscriber_texture->mailbox(),
201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           subscriber_texture->target(),
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           subscriber_texture->sync_point()));
203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_->RequestCopyOfOutput(request.Pass());
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DelegatedFrameHost::CanCopyToBitmap() const {
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return client_->GetCompositor() &&
209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         client_->GetLayer()->has_external_content();
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DelegatedFrameHost::CanCopyToVideoFrame() const {
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return client_->GetCompositor() &&
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         client_->GetLayer()->has_external_content();
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DelegatedFrameHost::CanSubscribeFrame() const {
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return true;
219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::BeginFrameSubscription(
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame_subscriber_ = subscriber.Pass();
224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::EndFrameSubscription() {
227010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  idle_frame_subscriber_textures_.clear();
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame_subscriber_.reset();
229010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
231010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const {
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Should skip a frame only when another frame from the renderer is guaranteed
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // to replace it. Otherwise may cause hangs when the renderer is waiting for
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // the completion of latency infos (such as when taking a Snapshot.)
235010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      can_lock_compositor_ == NO_PENDING_COMMIT ||
237010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      !resize_lock_.get())
238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return false;
239010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
240010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return size_in_dip != resize_lock_->expected_size();
241010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::WasResized() {
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (client_->DesiredFrameSize() != current_frame_size_in_dip_ &&
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      client_->GetHost()->is_hidden())
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EvictDelegatedFrame();
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MaybeCreateResizeLock();
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
249010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const {
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (resize_lock_)
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return resize_lock_->expected_size();
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return client_->DesiredFrameSize();
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
257010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::CheckResizeLock() {
258010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!resize_lock_ ||
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      resize_lock_->expected_size() != current_frame_size_in_dip_)
260010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
261010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
262010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Since we got the size we were looking for, unlock the compositor. But delay
263010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // the release of the lock until we've kicked a frame with the new texture, to
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // avoid resizing the UI before we have a chance to draw a "good" frame.
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  resize_lock_->UnlockCompositor();
266010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
267010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (compositor) {
268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!compositor->HasObserver(this))
269010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      compositor->AddObserver(this);
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
271010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
272010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DelegatedFrameHost::DidReceiveFrameFromRenderer(
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Rect& damage_rect) {
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!frame_subscriber() || !CanCopyToVideoFrame())
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::TimeTicks now = gfx::FrameTime::Now();
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::TimeTicks present_time;
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (vsync_timebase_.is_null() || vsync_interval_ <= base::TimeDelta()) {
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    present_time = now;
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const int64 intervals_elapsed = (now - vsync_timebase_) / vsync_interval_;
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    present_time = vsync_timebase_ + (intervals_elapsed + 1) * vsync_interval_;
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<media::VideoFrame> frame;
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (frame_subscriber()->ShouldCaptureFrame(damage_rect, present_time,
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                             &frame, &callback)) {
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CopyFromCompositingSurfaceToVideoFrame(
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        gfx::Rect(current_frame_size_in_dip_),
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        frame,
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(callback, present_time));
295010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
296010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::SwapDelegatedFrame(
299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint32 output_surface_id,
300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::DelegatedFrameData> frame_data,
301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    float frame_device_scale_factor,
302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::vector<ui::LatencyInfo>& latency_info) {
303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!frame_data->render_pass_list.empty());
305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  cc::RenderPass* root_pass = frame_data->render_pass_list.back();
307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Size frame_size = root_pass->output_rect.size();
309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Size frame_size_in_dip =
310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ConvertSizeToDIP(frame_device_scale_factor, frame_size);
311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect);
313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  damage_rect.Intersect(gfx::Rect(frame_size));
314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Rect damage_rect_in_dip =
315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ConvertRectToDIP(frame_device_scale_factor, damage_rect);
316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (ShouldSkipFrame(frame_size_in_dip)) {
318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    cc::CompositorFrameAck ack;
319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    cc::TransferableResource::ReturnResources(frame_data->resource_list,
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                              &ack.resources);
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    skipped_latency_info_list_.insert(skipped_latency_info_list_.end(),
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        latency_info.begin(), latency_info.end());
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
325010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    RenderWidgetHostImpl::SendSwapCompositorFrameAck(
326010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        host->GetRoutingID(), output_surface_id,
327010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        host->GetProcess()->GetID(), ack);
328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    skipped_frames_ = true;
329010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
331010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
332010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (skipped_frames_) {
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    skipped_frames_ = false;
334010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    damage_rect = gfx::Rect(frame_size);
335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    damage_rect_in_dip = gfx::Rect(frame_size_in_dip);
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Give the same damage rect to the compositor.
338010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    cc::RenderPass* root_pass = frame_data->render_pass_list.back();
339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    root_pass->damage_rect = damage_rect;
340010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (output_surface_id != last_output_surface_id_) {
343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Resource ids are scoped by the output surface.
344010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // If the originating output surface doesn't match the last one, it
345010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // indicates the renderer's output surface may have been recreated, in which
346010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // case we should recreate the DelegatedRendererLayer, to avoid matching
347010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // resources from the old one with resources from the new one which would
348010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // have the same id. Changing the layer to showing painted content destroys
349010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // the DelegatedRendererLayer.
350010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EvictDelegatedFrame();
351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
352010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Drop the cc::DelegatedFrameResourceCollection so that we will not return
353010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // any resources from the old output surface with the new output surface id.
354010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (resource_collection_.get()) {
355010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      resource_collection_->SetClient(NULL);
356010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      if (resource_collection_->LoseAllResources())
358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        SendReturnedDelegatedResources(last_output_surface_id_);
359010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      resource_collection_ = NULL;
361010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
362010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    last_output_surface_id_ = output_surface_id;
363010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
36403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool modified_layers = false;
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ui::Compositor* compositor = client_->GetCompositor();
366010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (frame_size.IsEmpty()) {
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(frame_data->resource_list.empty());
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EvictDelegatedFrame();
36903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    modified_layers = true;
370010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (use_surfaces_) {
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!surface_factory_) {
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        cc::SurfaceManager* manager = factory->GetSurfaceManager();
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        id_allocator_ = factory->CreateSurfaceIdAllocator();
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        surface_factory_ =
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            make_scoped_ptr(new cc::SurfaceFactory(manager, this));
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (surface_id_.is_null() || frame_size != current_surface_size_ ||
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          frame_size_in_dip != current_frame_size_in_dip_) {
38103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        // TODO(jbauman): Wait to destroy this surface until the parent has
38203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        // finished using it.
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (!surface_id_.is_null())
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          surface_factory_->Destroy(surface_id_);
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        surface_id_ = id_allocator_->GenerateId();
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        surface_factory_->Create(surface_id_, frame_size);
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        client_->GetLayer()->SetShowSurface(surface_id_, frame_size_in_dip);
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        current_surface_size_ = frame_size;
38903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        modified_layers = true;
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_ptr<cc::CompositorFrame> compositor_frame =
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          make_scoped_ptr(new cc::CompositorFrame());
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      compositor_frame->delegated_frame_data = frame_data.Pass();
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      compositor_frame->metadata.latency_info.swap(skipped_latency_info_list_);
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      compositor_frame->metadata.latency_info.insert(
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          compositor_frame->metadata.latency_info.end(),
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          latency_info.begin(),
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          latency_info.end());
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Closure ack_callback;
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (compositor) {
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ack_callback = base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  AsWeakPtr(),
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  output_surface_id);
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      surface_factory_->SubmitFrame(
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          surface_id_, compositor_frame.Pass(), ack_callback);
409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!resource_collection_.get()) {
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resource_collection_ = new cc::DelegatedFrameResourceCollection;
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        resource_collection_->SetClient(this);
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // If the physical frame size changes, we need a new |frame_provider_|. If
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // the physical frame size is the same, but the size in DIP changed, we
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // need to adjust the scale at which the frames will be drawn, and we do
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // this by making a new |frame_provider_| also to ensure the scale change
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // is presented in sync with the new frame content.
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!frame_provider_.get() ||
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          frame_size != frame_provider_->frame_size() ||
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          frame_size_in_dip != current_frame_size_in_dip_) {
4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        frame_provider_ = new cc::DelegatedFrameProvider(
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            resource_collection_.get(), frame_data.Pass());
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        client_->GetLayer()->SetShowDelegatedContent(frame_provider_.get(),
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                     frame_size_in_dip);
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      } else {
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        frame_provider_->SetFrameData(frame_data.Pass());
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
42903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      modified_layers = true;
430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
431010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  released_front_lock_ = NULL;
433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  current_frame_size_in_dip_ = frame_size_in_dip;
434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  CheckResizeLock();
435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (modified_layers && !damage_rect_in_dip.IsEmpty()) {
43703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // TODO(jbauman): Need to always tell the window observer about the
43803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // damage.
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    client_->GetLayer()->OnDelegatedFrameDamage(damage_rect_in_dip);
44003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  pending_delegated_ack_count_++;
443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!compositor) {
445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SendDelegatedFrameAck(output_surface_id);
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (!use_surfaces_) {
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<ui::LatencyInfo>::const_iterator it;
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (it = latency_info.begin(); it != latency_info.end(); ++it)
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      compositor->SetLatencyInfo(*it);
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If we've previously skipped any latency infos add them.
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (it = skipped_latency_info_list_.begin();
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        it != skipped_latency_info_list_.end();
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ++it)
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      compositor->SetLatencyInfo(*it);
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    skipped_latency_info_list_.clear();
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    AddOnCommitCallbackAndDisableLocks(
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   AsWeakPtr(),
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                   output_surface_id));
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DidReceiveFrameFromRenderer(damage_rect);
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (frame_provider_.get() || !surface_id_.is_null())
463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    delegated_frame_evictor_->SwappedFrame(!host->is_hidden());
464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Note: the frame may have been evicted immediately.
465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::SendDelegatedFrameAck(uint32 output_surface_id) {
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  cc::CompositorFrameAck ack;
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!surface_returned_resources_.empty())
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ack.resources.swap(surface_returned_resources_);
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (resource_collection_.get())
473010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
474010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl::SendSwapCompositorFrameAck(host->GetRoutingID(),
475010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                   output_surface_id,
476010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                   host->GetProcess()->GetID(),
477010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                   ack);
478010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK_GT(pending_delegated_ack_count_, 0);
479010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  pending_delegated_ack_count_--;
480010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
481010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
482010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::UnusedResourcesAreAvailable() {
483010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (pending_delegated_ack_count_)
484010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
485010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
486010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SendReturnedDelegatedResources(last_output_surface_id_);
487010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
488010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
489010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::SendReturnedDelegatedResources(
490010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint32 output_surface_id) {
491010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
492010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  cc::CompositorFrameAck ack;
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!surface_returned_resources_.empty()) {
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ack.resources.swap(surface_returned_resources_);
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else {
4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(resource_collection_.get());
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
500010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(!ack.resources.empty());
501010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
502010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl::SendReclaimCompositorResources(
503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      host->GetRoutingID(),
504010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      output_surface_id,
505010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      host->GetProcess()->GetID(),
506010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ack);
507010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
508010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void DelegatedFrameHost::ReturnResources(
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const cc::ReturnedResourceArray& resources) {
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (resources.empty())
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::copy(resources.begin(),
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            resources.end(),
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            std::back_inserter(surface_returned_resources_));
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!pending_delegated_ack_count_)
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SendReturnedDelegatedResources(last_output_surface_id_);
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
520010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::EvictDelegatedFrame() {
521010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_->GetLayer()->SetShowPaintedContent();
522010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  frame_provider_ = NULL;
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!surface_id_.is_null()) {
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    surface_factory_->Destroy(surface_id_);
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    surface_id_ = cc::SurfaceId();
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
527010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegated_frame_evictor_->DiscardedFrame();
528010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
529010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
530010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
531010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::CopyFromCompositingSurfaceHasResult(
532010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Size& dst_size_in_pixel,
533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const SkColorType color_type,
534010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Callback<void(bool, const SkBitmap&)>& callback,
535010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::CopyOutputResult> result) {
536010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result->IsEmpty() || result->size().IsEmpty()) {
537010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(false, SkBitmap());
538010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
539010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
540010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
541010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result->HasTexture()) {
5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // GPU-accelerated path
543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    PrepareTextureCopyOutputResult(dst_size_in_pixel, color_type,
544010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   callback,
545010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   result.Pass());
546010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
547010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
548010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
549010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(result->HasBitmap());
5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Software path
551116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PrepareBitmapCopyOutputResult(dst_size_in_pixel, color_type, callback,
552010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                result.Pass());
553010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
554010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
555010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)static void CopyFromCompositingSurfaceFinished(
556010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Callback<void(bool, const SkBitmap&)>& callback,
557010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::SingleReleaseCallback> release_callback,
558010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<SkBitmap> bitmap,
559010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
560010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool result) {
561010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bitmap_pixels_lock.reset();
562010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
563010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint32 sync_point = 0;
564010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result) {
565010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
566010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    sync_point = gl_helper->InsertSyncPoint();
567010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
568010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool lost_resource = sync_point == 0;
569010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  release_callback->Run(sync_point, lost_resource);
570010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
571010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  callback.Run(result, *bitmap);
572010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
573010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
574010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
575010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::PrepareTextureCopyOutputResult(
576010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Size& dst_size_in_pixel,
577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const SkColorType color_type,
578010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Callback<void(bool, const SkBitmap&)>& callback,
579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::CopyOutputResult> result) {
580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(result->HasTexture());
581010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::ScopedClosureRunner scoped_callback_runner(
582010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(callback, false, SkBitmap()));
583010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(sikugu): We should be able to validate the format here using
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // GLHelper::IsReadbackConfigSupported before we processs the result.
5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // See crbug.com/415682.
587010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<SkBitmap> bitmap(new SkBitmap);
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                dst_size_in_pixel.height(),
5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                color_type,
5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                kOpaque_SkAlphaType)))
592010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
593010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
594010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
595010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GLHelper* gl_helper = factory->GetGLHelper();
596010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!gl_helper)
597010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
598010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
599010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
600010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new SkAutoLockPixels(*bitmap));
601010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
602010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
603010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  cc::TextureMailbox texture_mailbox;
604010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<cc::SingleReleaseCallback> release_callback;
605010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result->TakeTexture(&texture_mailbox, &release_callback);
606010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(texture_mailbox.IsTexture());
607010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
608010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ignore_result(scoped_callback_runner.Release());
609010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
610010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gl_helper->CropScaleReadbackAndCleanMailbox(
611010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      texture_mailbox.mailbox(),
612010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      texture_mailbox.sync_point(),
613010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      result->size(),
614010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      gfx::Rect(result->size()),
615010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      dst_size_in_pixel,
616010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      pixels,
617116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      color_type,
618010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&CopyFromCompositingSurfaceFinished,
619010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 callback,
620010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Passed(&release_callback),
621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 base::Passed(&bitmap),
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&bitmap_pixels_lock)),
623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GLHelper::SCALER_QUALITY_FAST);
624010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
625010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
626010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
627010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::PrepareBitmapCopyOutputResult(
628010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Size& dst_size_in_pixel,
629116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const SkColorType color_type,
630010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Callback<void(bool, const SkBitmap&)>& callback,
631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::CopyOutputResult> result) {
6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
633010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    NOTIMPLEMENTED();
634010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(false, SkBitmap());
635010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
636010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
637010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(result->HasBitmap());
638010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<SkBitmap> source = result->TakeBitmap();
639010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(source);
6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkBitmap scaled_bitmap;
6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (source->width() != dst_size_in_pixel.width() ||
6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      source->height() != dst_size_in_pixel.height()) {
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scaled_bitmap =
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        skia::ImageOperations::Resize(*source,
6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      skia::ImageOperations::RESIZE_BEST,
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      dst_size_in_pixel.width(),
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      dst_size_in_pixel.height());
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scaled_bitmap = *source;
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (color_type == kN32_SkColorType) {
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(true, scaled_bitmap);
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(color_type, kAlpha_8_SkColorType);
6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The software path currently always returns N32 bitmap regardless of the
6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // |color_type| we ask for.
6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Paint |scaledBitmap| to alpha-only |grayscale_bitmap|.
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkBitmap grayscale_bitmap;
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool success = grayscale_bitmap.tryAllocPixels(
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SkImageInfo::MakeA8(scaled_bitmap.width(), scaled_bitmap.height()));
6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!success) {
6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(false, SkBitmap());
6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
6671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkCanvas canvas(grayscale_bitmap);
6691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkPaint paint;
6701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  skia::RefPtr<SkColorFilter> filter =
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      skia::AdoptRef(SkLumaColorFilter::Create());
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  paint.setColorFilter(filter.get());
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  canvas.drawBitmap(scaled_bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(true, grayscale_bitmap);
675010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
676010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
677010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
678010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::ReturnSubscriberTexture(
679010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::WeakPtr<DelegatedFrameHost> dfh,
680010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<OwnedMailbox> subscriber_texture,
681010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    uint32 sync_point) {
682010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!subscriber_texture.get())
683010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
684010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!dfh)
685010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
686010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
687010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  subscriber_texture->UpdateSyncPoint(sync_point);
688010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
689010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (dfh->frame_subscriber_ && subscriber_texture->texture_id())
690010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    dfh->idle_frame_subscriber_textures_.push_back(subscriber_texture);
691010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
692010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
694010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
695010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::WeakPtr<DelegatedFrameHost> dfh,
696010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Callback<void(bool)>& callback,
697010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<OwnedMailbox> subscriber_texture,
698010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::SingleReleaseCallback> release_callback,
699010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool result) {
700010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  callback.Run(result);
701010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
702010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  uint32 sync_point = 0;
703010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result) {
704010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
705010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    sync_point = gl_helper->InsertSyncPoint();
706010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
707010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (release_callback) {
708010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // A release callback means the texture came from the compositor, so there
709010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // should be no |subscriber_texture|.
7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(!subscriber_texture.get());
711010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool lost_resource = sync_point == 0;
712010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    release_callback->Run(sync_point, lost_resource);
713010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
714010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ReturnSubscriberTexture(dfh, subscriber_texture, sync_point);
715010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
716010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
717010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
718010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
719010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::WeakPtr<DelegatedFrameHost> dfh,
720010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<OwnedMailbox> subscriber_texture,
721010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_refptr<media::VideoFrame> video_frame,
722010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Callback<void(bool)>& callback,
723010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<cc::CopyOutputResult> result) {
724010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
725010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::ScopedClosureRunner scoped_return_subscriber_texture(
726010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Bind(&ReturnSubscriberTexture, dfh, subscriber_texture, 0));
727010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
728010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!dfh)
729010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
730010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result->IsEmpty())
731010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
732010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (result->size().IsEmpty())
733010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
734010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
735010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Compute the dest size we want after the letterboxing resize. Make the
736010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // coordinates and sizes even because we letterbox in YUV space
737010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // (see CopyRGBToVideoFrame). They need to be even for the UV samples to
738010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // line up correctly.
739010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // The video frame's coded_size() and the result's size() are both physical
740010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // pixels.
741010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Rect region_in_frame =
742010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()),
743010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    result->size());
744010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
745010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                              region_in_frame.y() & ~1,
746010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                              region_in_frame.width() & ~1,
747010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                              region_in_frame.height() & ~1);
748010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (region_in_frame.IsEmpty())
749010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
750010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
751010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!result->HasTexture()) {
752010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(result->HasBitmap());
753010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<SkBitmap> bitmap = result->TakeBitmap();
754010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Scale the bitmap to the required size, if necessary.
755010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    SkBitmap scaled_bitmap;
756010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result->size().width() != region_in_frame.width() ||
757010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        result->size().height() != region_in_frame.height()) {
758010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      skia::ImageOperations::ResizeMethod method =
759010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          skia::ImageOperations::RESIZE_GOOD;
760010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method,
761010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                    region_in_frame.width(),
762010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                    region_in_frame.height());
763010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    } else {
764010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      scaled_bitmap = *bitmap.get();
765010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
766010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
767010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    {
768010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap);
769010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
770010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      media::CopyRGBToVideoFrame(
771010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          reinterpret_cast<uint8*>(scaled_bitmap.getPixels()),
772010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          scaled_bitmap.rowBytes(),
773010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          region_in_frame,
774010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          video_frame.get());
775010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
776010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ignore_result(scoped_callback_runner.Release());
777010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    callback.Run(true);
778010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
779010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
780010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
781010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
782010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  GLHelper* gl_helper = factory->GetGLHelper();
783010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!gl_helper)
784010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
785010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (subscriber_texture.get() && !subscriber_texture->texture_id())
786010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
787010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
788010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  cc::TextureMailbox texture_mailbox;
789010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<cc::SingleReleaseCallback> release_callback;
790010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result->TakeTexture(&texture_mailbox, &release_callback);
791010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(texture_mailbox.IsTexture());
792010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
793010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  gfx::Rect result_rect(result->size());
794010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
795010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  content::ReadbackYUVInterface* yuv_readback_pipeline =
796010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      dfh->yuv_readback_pipeline_.get();
797010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (yuv_readback_pipeline == NULL ||
798010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
799010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
800010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
801010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
802010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    std::string quality_switch = switches::kTabCaptureDownscaleQuality;
803010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // If we're scaling up, we can use the "best" quality.
804010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (result_rect.size().width() < region_in_frame.size().width() &&
805010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        result_rect.size().height() < region_in_frame.size().height())
806010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      quality_switch = switches::kTabCaptureUpscaleQuality;
807010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
808010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    std::string switch_value =
8096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
8106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            quality_switch);
811010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (switch_value == "fast")
812010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      quality = GLHelper::SCALER_QUALITY_FAST;
813010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    else if (switch_value == "good")
814010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      quality = GLHelper::SCALER_QUALITY_GOOD;
815010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    else if (switch_value == "best")
816010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      quality = GLHelper::SCALER_QUALITY_BEST;
817010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
818010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    dfh->yuv_readback_pipeline_.reset(
819010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        gl_helper->CreateReadbackPipelineYUV(quality,
820010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             result_rect.size(),
821010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             result_rect,
822010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             video_frame->coded_size(),
823010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             region_in_frame,
824010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             true,
825010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                             true));
826010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    yuv_readback_pipeline = dfh->yuv_readback_pipeline_.get();
827010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
828010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
829010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ignore_result(scoped_callback_runner.Release());
830010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ignore_result(scoped_return_subscriber_texture.Release());
831010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::Callback<void(bool result)> finished_callback = base::Bind(
832010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      &DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo,
833010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      dfh->AsWeakPtr(),
834010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      callback,
835010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      subscriber_texture,
836010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      base::Passed(&release_callback));
837010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(),
838010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     texture_mailbox.sync_point(),
839010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     video_frame.get(),
840010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     finished_callback);
841010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
842010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
843010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
844010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// DelegatedFrameHost, ui::CompositorObserver implementation:
845010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
846010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnCompositingDidCommit(
847010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ui::Compositor* compositor) {
848010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
849010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (can_lock_compositor_ == NO_PENDING_COMMIT) {
850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    can_lock_compositor_ = YES_CAN_LOCK;
851010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
852010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      can_lock_compositor_ = YES_DID_LOCK;
853010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
854010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RunOnCommitCallbacks();
855010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (resize_lock_ &&
856010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      resize_lock_->expected_size() == current_frame_size_in_dip_) {
857010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    resize_lock_.reset();
858010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    host->WasResized();
859010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // We may have had a resize while we had the lock (e.g. if the lock expired,
860010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // or if the UI still gave us some resizes), so make sure we grab a new lock
861010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // if necessary.
862010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    MaybeCreateResizeLock();
863010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
864010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
865010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
866010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnCompositingStarted(
867010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ui::Compositor* compositor, base::TimeTicks start_time) {
868010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  last_draw_ended_ = start_time;
869010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
870010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
871010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnCompositingEnded(
872010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ui::Compositor* compositor) {
873010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
874010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
87546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void DelegatedFrameHost::OnCompositingAborted(ui::Compositor* compositor) {
876010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
877010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
878010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnCompositingLockStateChanged(
879010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ui::Compositor* compositor) {
880010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // A compositor lock that is part of a resize lock timed out. We
881010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // should display a renderer frame.
882010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
883010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
884010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
885010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
886010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
887010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnUpdateVSyncParameters(
888010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::TimeTicks timebase,
889010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::TimeDelta interval) {
8905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  vsync_timebase_ = timebase;
8915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  vsync_interval_ = interval;
892010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
893010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (client_->IsVisible())
894010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    host->UpdateVSyncParameters(timebase, interval);
895010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
896010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
897010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
898010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
899010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
900010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnLostResources() {
901010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RenderWidgetHostImpl* host = client_->GetHost();
9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (frame_provider_.get() || !surface_id_.is_null())
903010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    EvictDelegatedFrame();
904010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  idle_frame_subscriber_textures_.clear();
905010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  yuv_readback_pipeline_.reset();
906010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
907010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  host->ScheduleComposite();
908010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
909010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
910010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
911010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// DelegatedFrameHost, private:
912010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
913010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)DelegatedFrameHost::~DelegatedFrameHost() {
914010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ImageTransportFactory::GetInstance()->RemoveObserver(this);
915010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!surface_id_.is_null())
9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    surface_factory_->Destroy(surface_id_);
918010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (resource_collection_.get())
919010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    resource_collection_->SetClient(NULL);
920010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!vsync_manager_.get());
922010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
923010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
924010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::RunOnCommitCallbacks() {
925010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (std::vector<base::Closure>::const_iterator
926010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      it = on_compositing_did_commit_callbacks_.begin();
927010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      it != on_compositing_did_commit_callbacks_.end(); ++it) {
928010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    it->Run();
929010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
930010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  on_compositing_did_commit_callbacks_.clear();
931010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
932010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
933010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::AddOnCommitCallbackAndDisableLocks(
934010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const base::Closure& callback) {
935010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
936010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(compositor);
937010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
938010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!compositor->HasObserver(this))
939010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    compositor->AddObserver(this);
940010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
941010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  can_lock_compositor_ = NO_PENDING_COMMIT;
942010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  on_compositing_did_commit_callbacks_.push_back(callback);
943010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
944010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
945010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::AddedToWindow() {
946010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
947010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (compositor) {
9481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(!vsync_manager_.get());
949010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    vsync_manager_ = compositor->vsync_manager();
950010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    vsync_manager_->AddObserver(this);
951010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
952010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
953010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
954010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::RemovingFromWindow() {
955010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RunOnCommitCallbacks();
956010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  resize_lock_.reset();
957010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  client_->GetHost()->WasResized();
958010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ui::Compositor* compositor = client_->GetCompositor();
959010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (compositor && compositor->HasObserver(this))
960010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    compositor->RemoveObserver(this);
961010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
9621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (vsync_manager_.get()) {
963010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    vsync_manager_->RemoveObserver(this);
964010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    vsync_manager_ = NULL;
965010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
966010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
967010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
968010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::LockResources() {
9691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(frame_provider_.get() || !surface_id_.is_null());
970010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegated_frame_evictor_->LockFrame();
971010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
972010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
973010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::UnlockResources() {
9741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(frame_provider_.get() || !surface_id_.is_null());
975010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  delegated_frame_evictor_->UnlockFrame();
976010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
977010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
978010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
979010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// DelegatedFrameHost, ui::LayerOwnerDelegate implementation:
980010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
981010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void DelegatedFrameHost::OnLayerRecreated(ui::Layer* old_layer,
982010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                ui::Layer* new_layer) {
983010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // The new_layer is the one that will be used by our Window, so that's the one
984010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // that should keep our frame. old_layer will be returned to the
985010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // RecreateLayer caller, and should have a copy.
986010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (frame_provider_.get()) {
987010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    new_layer->SetShowDelegatedContent(frame_provider_.get(),
988010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                       current_frame_size_in_dip_);
989010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!surface_id_.is_null()) {
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    new_layer->SetShowSurface(surface_id_, current_frame_size_in_dip_);
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
993010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
994010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
995010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace content
996