| Index: content/browser/frame_host/render_widget_host_view_child_frame.cc
 | 
| diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
 | 
| index b8fdb0193d5800ad2867f95a5c1dc74014bf1828..e4ced729db79c6dcd942b564fd1f86c14b661300 100644
 | 
| --- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
 | 
| +++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
 | 
| @@ -4,8 +4,13 @@
 | 
|  
 | 
|  #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
 | 
|  
 | 
| +#include "cc/surfaces/surface.h"
 | 
| +#include "cc/surfaces/surface_factory.h"
 | 
| +#include "cc/surfaces/surface_manager.h"
 | 
| +#include "cc/surfaces/surface_sequence.h"
 | 
|  #include "content/browser/accessibility/browser_accessibility_manager.h"
 | 
|  #include "content/browser/frame_host/cross_process_frame_connector.h"
 | 
| +#include "content/browser/gpu/compositor_util.h"
 | 
|  #include "content/browser/renderer_host/render_widget_host_impl.h"
 | 
|  #include "content/common/gpu/gpu_messages.h"
 | 
|  #include "content/common/view_messages.h"
 | 
| @@ -16,11 +21,26 @@ namespace content {
 | 
|  RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
 | 
|      RenderWidgetHost* widget_host)
 | 
|      : host_(RenderWidgetHostImpl::From(widget_host)),
 | 
| -      frame_connector_(NULL) {
 | 
| +      use_surfaces_(UseSurfacesEnabled()),
 | 
| +      next_surface_sequence_(1u),
 | 
| +      last_output_surface_id_(0),
 | 
| +      current_surface_scale_factor_(1.f),
 | 
| +      ack_pending_count_(0),
 | 
| +      frame_connector_(NULL),
 | 
| +      weak_factory_(this) {
 | 
| +#if !defined(OS_ANDROID)
 | 
| +  if (use_surfaces_) {
 | 
| +    ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
 | 
| +    id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator();
 | 
| +  }
 | 
| +#endif  // !defined(OS_ANDROID)
 | 
| +
 | 
|    host_->SetView(this);
 | 
|  }
 | 
|  
 | 
|  RenderWidgetHostViewChildFrame::~RenderWidgetHostViewChildFrame() {
 | 
| +  if (!surface_id_.is_null())
 | 
| +    surface_factory_->Destroy(surface_id_);
 | 
|  }
 | 
|  
 | 
|  void RenderWidgetHostViewChildFrame::InitAsChild(
 | 
| @@ -186,17 +206,92 @@ void RenderWidgetHostViewChildFrame::UnlockCompositingSurface() {
 | 
|  }
 | 
|  #endif
 | 
|  
 | 
| +void RenderWidgetHostViewChildFrame::SurfaceDrawn(uint32 output_surface_id,
 | 
| +                                                  cc::SurfaceDrawStatus drawn) {
 | 
| +  cc::CompositorFrameAck ack;
 | 
| +  DCHECK(ack_pending_count_ > 0);
 | 
| +  if (!surface_returned_resources_.empty())
 | 
| +    ack.resources.swap(surface_returned_resources_);
 | 
| +  if (host_) {
 | 
| +    host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
 | 
| +                                                   output_surface_id, ack));
 | 
| +  }
 | 
| +  ack_pending_count_--;
 | 
| +}
 | 
| +
 | 
|  void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame(
 | 
|        uint32 output_surface_id,
 | 
|        scoped_ptr<cc::CompositorFrame> frame) {
 | 
|    last_scroll_offset_ = frame->metadata.root_scroll_offset;
 | 
| -  if (frame_connector_) {
 | 
| +
 | 
| +  if (!frame_connector_)
 | 
| +    return;
 | 
| +
 | 
| +  // When not using surfaces, the frame just gets proxied to
 | 
| +  // the embedder's renderer to be composited.
 | 
| +  if (!frame->delegated_frame_data || !use_surfaces_) {
 | 
|      frame_connector_->ChildFrameCompositorFrameSwapped(
 | 
|          output_surface_id,
 | 
|          host_->GetProcess()->GetID(),
 | 
|          host_->GetRoutingID(),
 | 
|          frame.Pass());
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +#if !defined(OS_ANDROID)
 | 
| +  cc::RenderPass* root_pass =
 | 
| +      frame->delegated_frame_data->render_pass_list.back();
 | 
| +
 | 
| +  gfx::Size frame_size = root_pass->output_rect.size();
 | 
| +  float scale_factor = frame->metadata.device_scale_factor;
 | 
| +
 | 
| +  // Check whether we need to recreate the cc::Surface, which means the child
 | 
| +  // frame renderer has changed its output surface, or size, or scale factor.
 | 
| +  if (output_surface_id != last_output_surface_id_ && surface_factory_) {
 | 
| +    surface_factory_->Destroy(surface_id_);
 | 
| +    surface_factory_.reset();
 | 
| +  }
 | 
| +  if (output_surface_id != last_output_surface_id_ ||
 | 
| +      frame_size != current_surface_size_ ||
 | 
| +      scale_factor != current_surface_scale_factor_) {
 | 
| +    if (surface_factory_ && !surface_id_.is_null())
 | 
| +      surface_factory_->Destroy(surface_id_);
 | 
| +    surface_id_ = cc::SurfaceId();
 | 
| +    last_output_surface_id_ = output_surface_id;
 | 
| +    current_surface_size_ = frame_size;
 | 
| +    current_surface_scale_factor_ = scale_factor;
 | 
|    }
 | 
| +
 | 
| +  if (!surface_factory_) {
 | 
| +    ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
 | 
| +    cc::SurfaceManager* manager = factory->GetSurfaceManager();
 | 
| +    surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
 | 
| +  }
 | 
| +
 | 
| +  if (surface_id_.is_null()) {
 | 
| +    surface_id_ = id_allocator_->GenerateId();
 | 
| +    surface_factory_->Create(surface_id_);
 | 
| +
 | 
| +    ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
 | 
| +    cc::SurfaceSequence sequence = cc::SurfaceSequence(
 | 
| +        id_allocator_->id_namespace(), next_surface_sequence_++);
 | 
| +    // The renderer process will satisfy this dependency when it creates a
 | 
| +    // SurfaceLayer.
 | 
| +    factory->GetSurfaceManager()
 | 
| +        ->GetSurfaceForId(surface_id_)
 | 
| +        ->AddDestructionDependency(sequence);
 | 
| +    frame_connector_->SetChildFrameSurface(surface_id_, frame_size,
 | 
| +                                           scale_factor, sequence);
 | 
| +  }
 | 
| +
 | 
| +  cc::SurfaceFactory::DrawCallback ack_callback =
 | 
| +      base::Bind(&RenderWidgetHostViewChildFrame::SurfaceDrawn, AsWeakPtr(),
 | 
| +                 output_surface_id);
 | 
| +  ack_pending_count_++;
 | 
| +  // If this value grows very large, something is going wrong.
 | 
| +  DCHECK(ack_pending_count_ < 1000);
 | 
| +  surface_factory_->SubmitFrame(surface_id_, frame.Pass(), ack_callback);
 | 
| +#endif  // !defined(OS_ANDROID)
 | 
|  }
 | 
|  
 | 
|  void RenderWidgetHostViewChildFrame::GetScreenInfo(
 | 
| @@ -223,9 +318,10 @@ void RenderWidgetHostViewChildFrame::UnlockMouse() {
 | 
|  }
 | 
|  
 | 
|  uint32_t RenderWidgetHostViewChildFrame::GetSurfaceIdNamespace() {
 | 
| -  // TODO(kenrb): Create SurfaceFactory here when RWHVChildFrame
 | 
| -  // gets compositor surface support.
 | 
| -  return 0;
 | 
| +  if (!use_surfaces_)
 | 
| +    return 0;
 | 
| +
 | 
| +  return id_allocator_->id_namespace();
 | 
|  }
 | 
|  
 | 
|  #if defined(OS_MACOSX)
 | 
| @@ -301,6 +397,25 @@ gfx::NativeViewId RenderWidgetHostViewChildFrame::GetParentForWindowlessPlugin()
 | 
|  }
 | 
|  #endif // defined(OS_WIN)
 | 
|  
 | 
| +// cc::SurfaceFactoryClient implementation.
 | 
| +void RenderWidgetHostViewChildFrame::ReturnResources(
 | 
| +    const cc::ReturnedResourceArray& resources) {
 | 
| +  if (resources.empty())
 | 
| +    return;
 | 
| +
 | 
| +  if (!ack_pending_count_ && host_) {
 | 
| +    cc::CompositorFrameAck ack;
 | 
| +    std::copy(resources.begin(), resources.end(),
 | 
| +              std::back_inserter(ack.resources));
 | 
| +    host_->Send(new ViewMsg_ReclaimCompositorResources(
 | 
| +        host_->GetRoutingID(), last_output_surface_id_, ack));
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  std::copy(resources.begin(), resources.end(),
 | 
| +            std::back_inserter(surface_returned_resources_));
 | 
| +}
 | 
| +
 | 
|  BrowserAccessibilityManager*
 | 
|  RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
 | 
|      BrowserAccessibilityDelegate* delegate) {
 | 
| 
 |